commit 5bb602717205fa7fba969e7e54ca6acc5bc41eaf Author: Kerim Date: Sun Jun 18 01:52:33 2023 +0500 all diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..71464e1 --- /dev/null +++ b/.babelrc @@ -0,0 +1,13 @@ +{ + "presets": ["@babel/preset-env"], + "plugins": [ + [ + "module-resolver", { + "root": ["."], + "alias": { + "helpers": "./tests/js/helpers" + } + } + ] + ] +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6af90e1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: http://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 diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..24cb865 --- /dev/null +++ b/.env.example @@ -0,0 +1,46 @@ +APP_NAME="October CMS" +APP_ENV=local +APP_KEY= +APP_DEBUG=true +APP_URL=http://localhost +APP_LOCALE=en + +ACTIVE_THEME=demo +BACKEND_URI=/admin +CMS_ROUTE_CACHE=false +CMS_ASSET_CACHE=false +LINK_POLICY=detect +DEFAULT_FILE_MASK=775 +DEFAULT_FOLDER_MASK=775 + +DB_CONNECTION=mysql +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_DATABASE=database +DB_USERNAME=root +DB_PASSWORD= + +LOG_CHANNEL=single +BROADCAST_DRIVER=log +CACHE_DRIVER=file +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=log +MAIL_HOST=null +MAIL_PORT=null +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS=noreply@octobercms.tld +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..2125666 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..958248c --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Common +composer.phar +.DS_Store +.idea +.env +.env.*.php +.env.php +auth.json +php_errors.log +nginx-error.log +nginx-access.log +nginx-ssl.access.log +nginx-ssl.error.log +php-errors.log +sftp-config.json +.ftpconfig +.vscode/ +selenium.php +composer.lock +package-lock.json +/node_modules +_ide_helper.php +.phpunit.result.cache +nbproject +.phpstorm.meta.php + +# Project +/bootstrap/compiled.php +/vendor +/modules diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..bb22ad8 --- /dev/null +++ b/.htaccess @@ -0,0 +1,78 @@ + + + + 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] + + ## + ## Uncomment to redirect trailing slashes in URLs. + ## + # RewriteCond %{REQUEST_FILENAME} !-d + # RewriteRule ^(.*)/$ /$1 [L,R=301] + + ## + ## Uncomment to redirect /index.php/path to /path + ## + # RewriteRule ^index\.php/(.*)$ /$1 [L,R=301] + + ## + ## Handle Authorization Header + ## + RewriteCond %{HTTP:Authorization} . + RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] + + ## + ## Blocked folders + ## + 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] + + ## + ## Allowed folders + ## + RewriteCond %{REQUEST_FILENAME} -f + RewriteCond %{REQUEST_FILENAME} !/.well-known/* + RewriteCond %{REQUEST_FILENAME} !/app/(assets|resources)/.* + RewriteCond %{REQUEST_FILENAME} !/storage/app/media/.* + RewriteCond %{REQUEST_FILENAME} !/storage/app/resources/.* + RewriteCond %{REQUEST_FILENAME} !/storage/app/uploads/public/.* + 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/.jshintrc b/.jshintrc new file mode 100644 index 0000000..bb55890 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,5 @@ +{ + "esversion": 6, + "curly": true, + "asi": true +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..a954327 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1 @@ +View the changelog on the [October CMS website](https://octobercms.com/changelog) diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..63962f5 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,305 @@ +Copyright (c) 2013-2022 Responsiv Pty Ltd + +This End User License Agreement (“EULA”) constitutes a binding agreement between you (the “Licensee”, “you” or “your”) and Responsiv Pty Ltd - ACN 159 492 823 (the “Company”, “we”, “us” or “our”) with respect to your use of the October CMS software (“Licensed Software” or “October CMS Software”). The Company and the Licensee are each individually referred to as “Party” and collectively as “Parties”. + +Please carefully read the terms and conditions of this EULA before installing and using the Licensed Software. By using the Licensed Software, you represent that you have read this EULA, and you agree to be bound by all the terms and conditions of this EULA, including any other agreements and policies referenced in this EULA. If you do not agree with any provisions of this EULA, please do not install the October CMS Software. + +The Company reserves the right to modify or discontinue the October CMS Software or any portion thereof, temporarily or permanently, with or without notice to you. The Company will not be under any obligation to support or update the Licensed Software, except as described in this EULA. + +YOU AGREE THAT THE COMPANY SHALL NOT BE LIABLE TO YOU OR ANY THIRD PARTY IN THE EVENT THAT WE EXERCISE OUR RIGHT TO MODIFY OR DISCONTINUE THE LICENSED SOFTWARE OR ANY PORTION THEREOF. + +## Summary + +This section outlines some of the key provisions covered in this EULA. Please note that this summary is provided for your convenience only, and it does not relieve you of your obligation to read the full EULA before installing/using the October CMS Software. + +By proceeding to use the October CMS Software, you understand and agree that: + +- You must be at least 18 years of age to enter into this EULA; + +- You will only use the October CMS Software in compliance with applicable laws; + +- October CMS Software licenses are only issued for Projects created through the website. To acquire/renew your Project licence, you need to sign in to your October CMS Account, and select/create the Project for which you wish to acquire/renew the licence; + +- You will be responsible for paying the full License Fee prior to installing the October CMS Software; + +- All License Fee Payments are non-refundable; + +- Upon full payment of the License Fee, you will receive a License Key that allows you to install the Licensed Software to create a single production or non-production website and ancillary installations needed to support that single production or non-production website; + +- Each new/renewed Project licence comes with one year of Updates. You may continue to use your expired Project license in perpetuity, but if you wish to continue receiving all the Updates, you will be required to keep your Project licence active by renewing it every year; + +- Subject to the payment of full License Fee and compliance with this EULA, the Company and its third party licensors grant you a limited, non-exclusive, non-transferable, non-assignable, perpetual and worldwide license to install and/or use the October CMS Software; + +- The Company and its licensors retain all rights, title and interest in the October CMS Software, Documentation and other similar proprietary materials made available to you; + +- You will not sublicense, resell, distribute, or transfer the Licensed Software to any third party without the Company’s prior written consent; + +- You will not remove, obscure or otherwise modify any copyright notices from the October CMS Software files or this EULA; + +- You will not modify, disassemble, or reverse engineer any part of the October CMS Software; + +- You will take all required steps to prevent unauthorised installation/use of the October CMS Software and prevent any breach of this EULA; + +- The Company may terminate this EULA if you are in breach of any provision of this EULA or if we discontinue the October CMS Software; + +- SUBJECT TO YOUR STATUTORY RIGHTS, THE COMPANY PROVIDES THE OCTOBER CMS SOFTWARE TO YOU “AS IS” AND “WITH ALL FAULTS”. THE COMPANY DOES NOT OFFER ANY WARRANTIES, WHETHER EXPRESS OR IMPLIED. IN NO EVENT WILL THE COMPANY’S AGGREGATE LIABILITY TO YOU FOR ANY CLAIMS CONNECTED WITH THIS EULA OR THE OCTOBER CMS SOFTWARE EXCEED THE AMOUNT ACTUALLY PAID BY YOU TO THE COMPANY FOR THE OCTOBER CMS SOFTWARE IN THE TWELVE MONTHS PRECEDING THE DATE WHEN THE CLAIM FIRST AROSE; + +- This EULA shall be governed by and construed in accordance with the laws of the state of New South Wales, Australia, without giving effect to any principles of conflict of laws. + +## Table of Contents + +- [1. Definitions](#Definitions) +- [2. Authorisation](#Authorisation) +- [3. License Grant](#License-Grant) +- [4. License Purchase and Renewal](#License-Purchase-and-Renewal) +- [5. License Fees, Payments and Refunds](#License-Fees-Payments-and-Refunds) +- [6. Ownership](#Ownership) +- [7. Use and Restrictions](#Use-and-Restrictions) +- [8. Technical Support](#Technical-Support) +- [9. Termination](#Termination) +- [10. Statutory Consumer Rights](#Statutory-Consumer-Rights) +- [11. Disclaimer of Warranties](#Disclaimer-of-Warranties) +- [12. Limitation of Liability](#Limitation-of-Liability) +- [13. Waiver](#Waiver) +- [14. Indemnification](#Indemnification) +- [15. Compliance with the Laws](#Compliance-with-the-Laws) +- [16. Data Protection](#Data-Protection) +- [17. Delivery](#Delivery) +- [18. General](#General) + + +## 1. Definitions + +The following words shall have the meaning given hereunder whenever they appear in this EULA: + +Term | Definition +---- | ----------- +Account | refers to a user account registered on the Website by an individual or entity. +Active Term | means the period commencing from the date of License purchase/renewal until the License expiry date as specified on the Project page in your Account. +Documentation | means the current version of the documentation relating to the October CMS Software available at https://docs.octobercms.com or otherwise made available by the Company in electronic format. Documentation includes but is not limited to installation instructions, user guides and help documents regarding the use of the October CMS Software. +License Fee | means the fee payable by the Licensee for the use of the October CMS Software in accordance with the provisions of this EULA and any other applicable agreements referenced in this EULA. +License Key | means a unique string of characters provided by the Company that enables users to install the October CMS Software for a specific Project. +Modifications | means any changes to the original code or files of the October CMS Software by the Licensee or any third party. For the avoidance of any doubt, the term “Modifications” does not include any Updates furnished by the Company. +October CMS Software | refers to the collection of proprietary code and graphics in various file formats provided by the Company to the Licensee. +Project | means a collection of extensions and themes to be used in a single production website. +Updates | means all new releases of the October CMS Software, including but not limited to new features and fixes which are provided by the Company to a Licensee during the Active Term of the License. +The Website | refers to the Company website located at www.octobercms.com. + + +## 2. Authorisation + +You must be at least 18 years of age and have the legal capacity to enter into this EULA. If you are accepting this EULA on behalf of a corporation, organisation, or other legal entity (‘corporate entity’), you warrant that you have the authority to enter into this EULA on behalf of such corporate entity and to bind the former to this EULA. + + +## 3. License Grant + +Subject to your compliance with all the terms and conditions of this EULA and the payment of the full License Fee, the Company and its third party licensors grant you a limited, non-exclusive, non-transferable, non-assignable, perpetual and worldwide license to install and/or use the October CMS Software. + +You shall be solely responsible for ensuring that all your authorised employees, contractors or other users of the Licensed Software comply with all the terms and conditions of this EULA, and any failure to comply with this EULA will be deemed as a breach of this EULA by you. + +The Company and its third party licensors may make changes to the Licensed Software, which are provided to you through Updates. You will only receive all such Updates during the Active Term of your license. You will not have any right to receive Updates after the expiration of your license. Please note that if you terminate your Account, you will not be able to access your Projects and renew your license/receive any future Updates. + +UNLESS EXPRESSLY PROVIDED IN THIS EULA, YOU MAY NOT COPY OR MODIFY THE OCTOBER CMS SOFTWARE. + + +## 4. License Purchase and Renewal + +October CMS Software licenses are only issued for Projects created through the Website. To acquire a new Project licence or to renew an existing Project licence, you must sign in to your October CMS Account and select/create the Project for which you wish to acquire/renew the licence. + +Upon full payment of the License Fee, you will receive a License Key that allows you to install the Licensed Software to create a single production or non-production website and ancillary installations needed to support that single production or non-production website. + +Each new/renewed Project licence comes with one year of Updates starting from the date on which you pay the License Fee. You are not under any legal obligation to renew your Project licence, and you can continue to use your expired Project license for your website in perpetuity. Please note that expired Project licenses do not receive any Updates. If you wish to continue receiving all the Updates, you will be required to keep your Project licence active by renewing it every year. + +By installing and using the October CMS Software, you assume full responsibility for your selection of the Licensed Software, its installation, and the results obtained from the use of the October CMS Software. + + +## 5. License Fees, Payments and Refunds + +The current License Fee for the October CMS Software is published on the Website, and the amount is specified in United States Dollars (USD). The License fee as specified on the Website does not include any taxes which shall be payable by the Licensee in addition to the License Fee. + +The License fee becomes due and payable in full at the time the Licensee purchases a new Project license or renews an existing Project license. + +All Project licenses are issued/renewed subject to the payment of the License Fee by the Licensee as outlined in Section 7 of our [Website Terms of Use](https://octobercms.com/help/terms/website#fees-payments-refunds-policy) and incorporated into this EULA by reference. The Company reserves the right to refuse issuance of a new Project license or renewal of an existing license until the Company receives the full payment. + +To the extent permitted by law, all License Fee payments are non-refundable. + + +## 6. Ownership + +Nothing in this EULA constitutes the sale of October CMS Software to you. The Company and its licensors retain all rights, title and interest in the October CMS Software, Documentation and other similar proprietary materials made available to you (collectively “Proprietary Material”). All Proprietary Material is protected by copyright and other intellectual property laws of Australia and international conventions. You acknowledge that the October CMS Software may contain some open source software that is not owned by the Company and which shall be governed by its own license terms. + +Except where authorised by the Company in writing, any use of the October CMS trademark, trade name, or logo is strictly prohibited. The Company reserves all rights that are not expressly granted in and to the Proprietary Material. + + +## 7. Use and Restrictions + +You hereby agree that: + +1. A License Key may only be used to create a single production or non-production website as provided in Section 4 (License Purchase and Renewal) of this EULA. If you wish to create another website, you will need to create a new Project and acquire a new License for that Project; + +2. Unless expressly provided otherwise in this EULA or other applicable agreements referenced herein, you will not sublicense, resell, distribute, or transfer the Licensed Software to any third party without the Company’s prior written consent; + +3. You will not remove, obscure or otherwise modify any copyright notices from the October CMS Software files or this EULA; + +4. You will not modify, disassemble, or reverse engineer any part of the October CMS Software; + +5. You will take all required steps to prevent unauthorised installation/use of the October CMS Software and prevent any breach of this EULA; + +6. You do not receive any rights, interests or titles in the “October CMS” trademark, trade name or service mark (“Marks”), and you will not use any of these Marks without our express consent. + + +## 8. Technical Support + +The Company does not offer any technical support except as described in our Premium Support Policy. The Company reserves the right to deny any and all technical support for any Modifications of the October CMS Software or in the event of any breach of this EULA. + + +## 9. Termination + +This EULA shall remain effective until terminated by either Party as described below. + +### 9.1 Termination by Licensee + +You may terminate this EULA by uninstalling the October CMS Software and deleting all files and your Account. Please note that once you delete your Account, you will not be able to reactivate it to restore your Projects and access your License Key. + +### 9.2 Termination by the Company + +The Company may terminate this EULA if you are in breach of any provision of this EULA or if we discontinue the October CMS Software. + +### 9.3 Survival + +Section 11 (Disclaimer of Warranties), Section 12 (Limitation of Liability), Section 13 (Waiver), Section 14 (Indemnification) and other sections of this EULA that by their nature are intended to survive the termination of this EULA shall survive. + +Unless expressly specified otherwise in this EULA, any termination of this EULA either by you or the Company does not create any obligation on the Company to issue a full or partial refund of the License Fee paid by you. + + +## 10. Statutory Consumer Rights + +### 10.1 CONSUMERS IN AUSTRALIA + +If you acquire the October CMS Software license as a “consumer”, nothing in this EULA will exclude, limit or modify any rights and guarantees conferred on you by legislation, including the Australian Consumer Law (ACL) in the Competition and Consumer Act 2010 (Cth) (‘Statutory Rights’). If the Company is in breach of any such Statutory Rights, then the Company’s liability shall be limited (at the Company’s option) to: + +10.1.1 In case of products supplied to you, to resupplying, replacing or paying the cost of resupplying or replacing the product in respect of which the breach occurred; + +10.1.2 In case of services supplied to you, to resupply the service or to pay the cost of resupplying the service in respect of which the breach occurred. + +Unless expressly specified otherwise in this EULA, you agree that the Company’s liability for the October CMS Software is governed solely by this EULA and the Australian Consumer Law. + +### 10.1 CONSUMERS OUTSIDE OF AUSTRALIA + +If you are deemed a “consumer” by statutory law in your country of residence, you may enjoy some legal rights under your local law which prohibit the exclusions, modification or limitations of certain liabilities from applying to you, and where such prohibition exists in your country of residence, any such limitations or exclusions will only apply to you to the extent it is permitted by your local law. + +You agree that apart from the application of your statutory consumer rights, the Company’s liability for the October CMS Software is governed solely by this EULA. + + +## 11. Disclaimer of Warranties + +SUBJECT TO YOUR STATUTORY RIGHTS AS PROVIDED IN SECTION 10 ABOVE, THE COMPANY PROVIDES THE OCTOBER CMS SOFTWARE TO YOU “AS IS” AND “WITH ALL FAULTS”. + +EXCLUDING ANY EXPRESS WARRANTIES OFFERED IN THIS EULA, TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE COMPANY, ITS EMPLOYEES, DIRECTORS, CONTRACTORS, AFFILIATES (“THE COMPANY AND ITS OFFICERS”) DISCLAIM ANY EXPRESS OR IMPLIED WARRANTIES WITH RESPECT TO THE OCTOBER CMS SOFTWARE, INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, RELIABILITY, COURSE OF PERFORMANCE OR USAGE IN TRADE. THE COMPANY DOES NOT WARRANT THAT THE OCTOBER CMS SOFTWARE: WILL MEET YOUR REQUIREMENTS; WILL BE UNINTERRUPTED, ERROR-FREE, OR SECURE; OR THAT THE COMPANY WILL BE ABLE TO RECTIFY ANY ERRORS, BUGS, SECURITY VULNERABILITIES. NO OBLIGATION, WARRANTIES OR LIABILITY SHALL ARISE OUT OF ANY TECHNICAL SUPPORT SERVICES PROVIDED BY THE COMPANY AND ITS OFFICERS IN CONNECTION WITH THE OCTOBER CMS SOFTWARE. NO VERBAL OR WRITTEN COMMUNICATION RECEIVED FROM THE COMPANY AND ITS OFFICERS, WHETHER MARKETING, PROMOTIONAL OR TECHNICAL SUPPORT, SHALL CREATE ANY WARRANTIES THAT ARE NOT EXPRESSLY PROVIDED IN THIS EULA. + +ALTHOUGH THE COMPANY PERIODICALLY RELEASES UPDATES FOR THE OCTOBER CMS SOFTWARE THAT MAY INCLUDE FIXES FOR KNOWN VULNERABILITIES, YOU ACKNOWLEDGE AND AGREE THAT THERE MAY BE VULNERABILITIES THAT THE COMPANY HAS NOT YET IDENTIFIED AND THEREFORE CANNOT ADDRESS. YOU ACKNOWLEDGE AND AGREE THAT YOU ARE SOLELY RESPONSIBLE FOR TAKING ALL THE PRECAUTIONS AND SAFEGUARDS NECESSARY TO PROTECT YOUR WEBSITE AND DATA FROM ANY EXTERNAL ATTACKS, INCLUDING BUT NOT LIMITED TO KEEPING YOUR OCTOBER CMS SOFTWARE INSTALLATION CURRENT AND UP TO DATE. + +SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT APPLY TO YOU. + + +## 12. Limitation of Liability + +IN NO EVENT SHALL THE COMPANY BE LIABLE TO YOU OR ANY THIRD-PARTY FOR ANY LOSS OF REVENUE, LOSS OF PROFITS (ACTUAL OR ANTICIPATED), LOSS OF SAVINGS (ACTUAL OR ANTICIPATED), LOSS OF OPPORTUNITY, LOSS OF REPUTATION, LOSS OF GOODWILL OR FOR ANY INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES RESULTING FROM THE INSTALLATION, USE OR INABILITY TO USE THE OCTOBER CMS SOFTWARE, WHETHER ARISING FROM ANY BREACH OF CONTRACT, NEGLIGENCE OR ANY OTHER THEORY OF LIABILITY, EVEN IF THE COMPANY WAS PREVIOUSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. THE LICENSEE SHALL BE SOLELY RESPONSIBLE FOR DETERMINING THE SUITABILITY OF THE LICENSED SOFTWARE AND ALL RISKS ASSOCIATED WITH ITS USE. + +IN NO EVENT WILL THE COMPANY’S AGGREGATE LIABILITY TO YOU FOR ANY CLAIMS CONNECTED WITH THIS EULA OR THE OCTOBER CMS SOFTWARE, INCLUDING THOSE ARISING FROM ANY BREACH OF CONTRACT OR NEGLIGENCE, EXCEED THE AMOUNT ACTUALLY PAID BY YOU TO THE COMPANY FOR THE OCTOBER CMS SOFTWARE IN THE TWELVE MONTHS PRECEDING THE DATE WHEN THE CLAIM FIRST AROSE. + +NOTWITHSTANDING ANYTHING TO THE FOREGOING, NOTHING IN THIS PROVISION SHALL LIMIT EITHER PARTY’S LIABILITY FOR ANY FRAUD OR LIABILITY THAT CANNOT BE LIMITED BY LAW. + + +## 13. Waiver + +YOU HEREBY RELEASE THE COMPANY AND ITS OFFICERS FROM ALL UNKNOWN RISKS ARISING OUT OF OR ASSOCIATED WITH THE USE OF THE OCTOBER CMS SOFTWARE. IF YOU ARE A RESIDENT IN THE STATE OF CALIFORNIA, U.S.A., YOU EXPRESSLY WAIVE CALIFORNIA CIVIL CODE SECTION 1542, OR OTHER SIMILAR LAW APPLICABLE TO YOU, WHICH STATES: “A GENERAL RELEASE DOES NOT EXTEND TO CLAIMS WHICH THE CREDITOR DOES NOT KNOW OR SUSPECT TO EXIST IN HIS OR HER FAVOR AT THE TIME OF EXECUTING THE RELEASE, WHICH IF KNOWN BY HIM OR HER MUST HAVE MATERIALLY AFFECTED HIS OR HER SETTLEMENT WITH THE DEBTOR OR RELEASED PARTY. ” + +**YOU ACKNOWLEDGE AND AGREE THAT THE LIMITATION OF LIABILITY AND THE WAIVER SET FORTH ABOVE REFLECT A REASONABLE AND FAIR ALLOCATION OF RISK BETWEEN YOU AND THE COMPANY AND THAT THESE PROVISIONS FORM AN ESSENTIAL BASIS OF THE BARGAIN BETWEEN YOU AND THE COMPANY. THE COMPANY WOULD NOT BE ABLE TO PROVIDE THE OCTOBER CMS SOFTWARE TO YOU ON AN ECONOMICALLY REASONABLE BASIS WITHOUT THESE LIMITATIONS.** + + +## 14. Indemnification + +14.1 The Company will defend or settle any claims against you that allege that the October CMS Software as supplied to you for installation and use in accordance with this EULA and Documentation infringes the intellectual property rights of a third party provided that: + +14.1.1 You immediately notify the Company of any such claim that relates to this indemnity; + +14.1.2 The Company has the sole right to control the defence or settlement of such claim; and + +14.1.3 You provide the Company with all reasonable assistance in relation to the defence. + +14.2 For any claims of infringement of intellectual property mentioned in Section 14.1, the Company reserves the right to: + +14.2.1 Modify or replace the Licensed Software to make it non-infringing provided such modification or replacement does not substantively change the functionality of the Licensed Software; or + +14.2.2 Acquire at its own expense the right for you to continue the use of the Licensed Software; or + +14.2.3 Terminate the Project license and direct you to cease the use of the Licensed Software. In such cases, the Company will provide you with a full refund of the License Fees paid by you for the Licensed Software in the preceding 12 months. Please note that where the Company directs you to cease the use of the October CMS Software due to a third party claim of infringement, you are under a legal obligation to immediately cease such use. + +Unless otherwise provided by law, this Section 14 sets out your exclusive remedies for any infringement of intellectual property claims made by a third party against you and nothing in this EULA will create any obligations on the Company to offer greater indemnity. The Company does not have any obligation to defend or indemnify any other third party. + +14.3 The Company shall not have any obligation to indemnify you if: + +14.3.1 The infringement arises out of any Modification of the October CMS Software; + +14.3.2 The infringement arises from any combination, operation, or use of the Licensed Software with any other third party software; + +14.3.3 The infringement arises from the use of the Licensed Software in breach of this EULA; + +14.3.4 The infringement arises from the use of the Licensed Software after the Company has informed you to cease the use of the Licensed Software due to possible claims. + +14.4 You will indemnify the Company against any third party claims, damages, losses and costs, including reasonable attorney fees arising from: + +14.4.1 Your actions or omissions (actual or alleged), including without limitation, claims that your actions or omission infringe any third party’s intellectual property rights; or + +14.4.2 Your violation of any applicable laws; or + +14.4.3 Your breach of this EULA. + + +## 15. Compliance with the Laws + +You will only install/use the October CMS Software and fulfil all your obligations under this EULA in compliance with all applicable laws. You hereby confirm that neither you nor the corporate entity that you represent is subject or target of any government Sanctions, and your use of the October CMS Software would not result in violation of any Sanctions by the Company. + +You further confirm that the Licensed Software will not be used by any individual or entity engaged in any of the following activities: (i) Terrorist activities; (ii) design, development or production of any weapons of mass destruction; or (iii) any other illegal activity. + + +## 16. Data Protection + +The Company only collects minimal personal data from the Licensee, as described in our Privacy Policy. The Company does not process any data on behalf of the Licensee, and the Licensee shall be solely responsible for compliance with applicable data protection laws for any data it controls or processes. + + +## 17. Delivery + +The Company will deliver the October CMS Software and this EULA to you by electronic download. + + +## 18. General + +### 18.1 Amendments + +The Company reserves the right to amend the terms and conditions of this EULA at any time and without giving any prior notice to you. You acknowledge that you are responsible for periodically reviewing this EULA to familiarise yourself with any changes. Your continued use of the October CMS Software after any changes to the EULA shall constitute your consent to such change. You can access the latest version of the EULA by visiting https://octobercms.com/eula + +### 18.2 Assignment + +You may not assign any rights and obligations under this EULA, in whole or in part, without an authorised Company representative's written consent. Any attempt to assign any rights and obligations without the Company's consent shall be void. The Company reserves the right to assign any of its rights and obligations under this EULA to a third party without requiring your consent. + +### 18.3 Notices + +You hereby consent to receive all notices and communication from the Company electronically. + +All notices to the Company under this EULA shall be sent to: + +PO Box 47
+Queanbeyan NSW 2620
+Australia + +For any other questions relating to this EULA, please contact us at https://octobercms.com/contact + +### 18.4 Governing Law and Jurisdiction + +This EULA shall be governed by and construed in accordance with the laws of the state of New South Wales, Australia, without giving effect to any principles of conflict of laws. The parties hereby agree to submit to the non-exclusive jurisdiction of the courts of New South Wales to decide any matter arising out of these Terms. Both Parties hereby agree that the United Nations Convention on Contracts for the International Sale of Goods will not apply to this EULA. + +### 18.5 Force Majeure + +Neither Party will be liable to the other for any failure or delay in the performance of its obligations to the extent that such failure or delay is caused by any unforeseen events which are beyond the reasonable control of the obligated Party such as an act of God, strike, war, terrorism, epidemic, internet or telecommunication outage or other similar events, and the obligated Party is not able to avoid or remove the force measure by taking reasonable measures. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5c897f4 --- /dev/null +++ b/README.md @@ -0,0 +1,74 @@ +

+ October +

+ +[October](https://octobercms.com) is a Content Management System (CMS) and web platform whose sole purpose is to make your development workflow simple again. It was born out of frustration with existing systems. We feel building websites has become a convoluted and confusing process that leaves developers unsatisfied. We want to turn you around to the simpler side and get back to basics. + +October's mission is to show the world that web development is not rocket science. + +[![Build Status](https://github.com/octobercms/library/actions/workflows/tests.yml/badge.svg)](https://octobercms.com/) +[![Downloads](https://img.shields.io/packagist/dt/october/rain)](https://docs.octobercms.com/) +[![Version](https://img.shields.io/packagist/v/october/october)](https://octobercms.com/changelog) +[![License](https://poser.pugx.org/october/october/license.svg)](./LICENSE.md) + +> *Please note*: October is open source but it is not free software. A license with a small fee is required for each website you build with October CMS. + +## Installing October + +Instructions on how to install October can be found at the [installation guide](https://docs.octobercms.com/3.x/setup/installation.html). + +### Quick Start Installation + +If you have composer installed, run this in your terminal to install October CMS from command line. This will place the files in a directory named **myoctober**. + + composer create-project october/october myoctober + +If you plan on using a database, run this command inside the application directory. + + php artisan october:install + +## Learning October + +The best place to learn October CMS is by [reading the documentation](https://docs.octobercms.com) or [following some tutorials](https://octobercms.com/support/articles/tutorials). + +You may also watch this [introductory video](https://www.youtube.com/watch?v=yLZTOeOS7wI). Make sure to check out our [official YouTube channel](https://www.youtube.com/c/OctoberCMSOfficial). There is also the excellent video series by [Watch & Learn](https://watch-learn.com/series/making-websites-with-october-cms). + +For code examples of building with October CMS, visit the [RainLab Plugin Suite](https://github.com/rainlab) or the [October Demos Repo](https://github.com/octoberdemos). + +## 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) + +## Security Vulnerabilities + +Please review [our security policy](https://github.com/octobercms/october/security/policy) on how to report security vulnerabilities. + +## Development Team + +October CMS was created by [Alexey Bobkov](https://www.linkedin.com/in/alexey-bobkov-232ba02b/) and [Samuel Georges](https://www.linkedin.com/in/samuel-georges-0a964131/), who both continue to develop the platform. + +## Foundation library + +The CMS uses [Laravel](https://laravel.com) as a foundation PHP framework. + +## Contact + +For announcements and updates: + +* [Contact Us Page](http://octoberdev.test/contact) +* [Follow us on Twitter](https://twitter.com/octobercms) +* [Like us on Facebook](https://facebook.com/octobercms) + +To chat or hang out: + +* [Join us on Slack](https://octobercms.slack.com) +* [Join us on Discord](https://discord.gg/gEKgwSZ) +* [Join us on Telegram](https://t.me/octoberchat) + +## License + +The October CMS platform is licensed software, see [End User License Agreement](./LICENSE.md) (EULA) for more details. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..dc296d4 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,11 @@ +# Security Policy + +**PLEASE DO NOT DISCLOSE SECURITY-RELATED ISSUES PUBLICLY, [SEE BELOW](#reporting-a-vulnerability).** + +## Supported Versions + +October CMS is an evergreen product, no one version is singled out for security fixes because there is no way to update just one version. Builds are continually released and security fixes will always be available in the latest build. + +## Reporting a Vulnerability + +If you discover a security vulnerability within October CMS, please send an email to the team at hello@octobercms.com. All security vulnerabilities will be promptly addressed. diff --git a/app/Provider.php b/app/Provider.php new file mode 100644 index 0000000..b34c2b4 --- /dev/null +++ b/app/Provider.php @@ -0,0 +1,29 @@ +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..1364df4 --- /dev/null +++ b/bootstrap/app.php @@ -0,0 +1,55 @@ +singleton( + Illuminate\Contracts\Http\Kernel::class, + October\Rain\Foundation\Http\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Console\Kernel::class, + October\Rain\Foundation\Console\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Debug\ExceptionHandler::class, + October\Rain\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..99bf82c --- /dev/null +++ b/bootstrap/autoload.php @@ -0,0 +1,53 @@ + env('APP_NAME', 'October CMS'), + + /* + |-------------------------------------------------------------------------- + | Application Environment + |-------------------------------------------------------------------------- + | + | This value determines the "environment" your application is currently + | running in. This may determine how you prefer to configure various + | services the application utilizes. Set this in your ".env" file. + | + */ + + 'env' => env('APP_ENV', 'production'), + + /* + |-------------------------------------------------------------------------- + | Application Debug Mode + |-------------------------------------------------------------------------- + | + | When your application is in debug mode, detailed error messages with + | stack traces will be shown on every error that occurs within your + | application. If disabled, a simple generic error page is shown. + | + | You can create a CMS page with route "/error" to set the contents + | of this page. Otherwise a default error page is shown. + | + */ + + 'debug' => (bool) env('APP_DEBUG', false), + + /* + |-------------------------------------------------------------------------- + | 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' => env('ASSET_URL'), + + /* + |-------------------------------------------------------------------------- + | 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. + | + */ + + 'locale' => env('APP_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', + + /* + |-------------------------------------------------------------------------- + | 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')), [ + + // Core Service Provider + System\ServiceProvider::class, + + // Package Service Providers... + // Illuminate\Html\HtmlServiceProvider::class, // Example + + ]), + + /* + |-------------------------------------------------------------------------- + | 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::class, // Example + + ]), + + /* + |-------------------------------------------------------------------------- + | 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. + | + |-------------------------------- WARNING! -------------------------------- + | + | 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 can use backend.timezone or cms.timezone to set the default + | timezone used to display dates & times. + | + */ + + 'timezone' => 'UTC', + +]; diff --git a/config/backend.php b/config/backend.php new file mode 100644 index 0000000..82a6b2c --- /dev/null +++ b/config/backend.php @@ -0,0 +1,197 @@ + http://localhost/admin + | + */ + + 'uri' => env('BACKEND_URI', 'admin'), + + /* + |-------------------------------------------------------------------------- + | Backend Skin + |-------------------------------------------------------------------------- + | + | Specifies the backend skin class to use. + | + */ + + 'skin' => Backend\Skins\Standard::class, + + /* + |-------------------------------------------------------------------------- + | Default Branding + |-------------------------------------------------------------------------- + | + | The default backend customization settings. These values are all optional + | and remember to set the enabled value to true. Supported values: + | + | - menu_mode: inline, text, tile, collapse, icons, left + | - color_mode: light, dark, auto + | - color_palette: default, classic, oxford, console, valentino, punch + | - login_background_type: color, wallpaper + | - login_background_wallpaper_size: auto, cover + | - login_image_type: autumn_images, custom + | + */ + + 'brand' => [ + 'enabled' => false, + 'app_name' => env('APP_NAME', 'October CMS'), + 'tagline' => 'Administration Panel', + 'menu_mode' => 'icons', + 'color_mode' => 'light', + 'color_palette' => 'default', + 'logo_path' => '~/app/assets/images/logo.png', + 'favicon_path' => '~/app/assets/images/favicon.png', + 'menu_logo_path' => '~/app/assets/images/menu_logo.png', + 'dashboard_icon_path' => '~/app/assets/images/dashboard_icon.png', + 'stylesheet_path' => '~/app/assets/less/styles.less', + 'login_background_type' => 'color', + 'login_background_color' => '#fef6eb', + 'login_background_wallpaper_size' => 'auto', + 'login_image_type' => 'autumn_images', + 'login_custom_image' => '~/app/assets/images/loginimage.png', + ], + + /* + |-------------------------------------------------------------------------- + | Turbo Router + |-------------------------------------------------------------------------- + | + | Enhance the backend experience using PJAX (push state and AJAX) so when + | you click a link, the page is automatically swapped client-side without + | the cost of a full page load. + | + */ + + 'turbo_router' => true, + + /* + |-------------------------------------------------------------------------- + | Force HTTPS security + |-------------------------------------------------------------------------- + | + | Use this setting to force a secure protocol when accessing any backend + | pages, including the authentication pages. This is usually handled by + | web server config, but can be handled by the app for added security. + | + */ + + 'force_secure' => false, + + /* + |-------------------------------------------------------------------------- + | Remember Login + |-------------------------------------------------------------------------- + | + | Define live duration of backend sessions: + | + | true - session never expires (cookie expiration in 5 years) + | + | false - session has a limited time (see session.lifetime) + | + | null - the form login displays a checkbox that allow user to choose + | + */ + + 'force_remember' => null, + + /* + |-------------------------------------------------------------------------- + | Force Single Session + |-------------------------------------------------------------------------- + | + | Use this setting to prevent concurrent sessions. When enabled, backend + | users cannot sign in to multiple devices at the same time. When a new + | sign in occurs, all other sessions for that user are invalidated. + | + */ + + 'force_single_session' => false, + + /* + |-------------------------------------------------------------------------- + | Force Mail Setting + |-------------------------------------------------------------------------- + | + | Use this setting to remove the option to configure the mail settings + | via the backend. This can be used in developer environments to prevent + | accidentally sending mail via the configured database. + | + */ + + 'force_mail_setting' => false, + + /* + |-------------------------------------------------------------------------- + | Password Policy + |-------------------------------------------------------------------------- + | + | Specify the password policy for backend administrators. + | + | min_length - Password minimum length between 4 - 128 chars + | require_uppercase - Require at least one uppercase letter (A–Z) + | require_lowercase - Require at least one lowercase letter (a–z) + | require_number - Require at least one number + | require_nonalpha - Require at least one non-alphanumeric character + | expire_days - Enable password expiration after number of days (@todo) + | + */ + + 'password_policy' => [ + 'min_length' => 4, + 'require_uppercase' => false, + 'require_lowercase' => false, + 'require_number' => false, + 'require_nonalpha' => false, + ], + + /* + |-------------------------------------------------------------------------- + | Default Avatar + |-------------------------------------------------------------------------- + | + | The default avatar used for backend accounts that have no avatar defined. + | + | local - Use a local default image of a user + | gravatar - Use the Gravatar service to generate a unique image + | - Specify a custom URL to a default avatar + | + */ + + 'default_avatar' => 'gravatar', + + /* + |-------------------------------------------------------------------------- + | Backend Locale + |-------------------------------------------------------------------------- + | + | This acts as the default setting for a backend user's locale. This can + | be changed by the user at any time using the backend preferences. + | + */ + + 'locale' => env('APP_LOCALE', 'en'), + + /* + |-------------------------------------------------------------------------- + | Backend Timezone + |-------------------------------------------------------------------------- + | + | This acts as the default setting for a backend user's timezone. This can + | be changed by the user at any time using the backend preferences. All + | dates displayed in the backend will be converted to this timezone. + | + */ + + 'timezone' => 'UTC', + +]; diff --git a/config/broadcasting.php b/config/broadcasting.php new file mode 100644 index 0000000..e4d5204 --- /dev/null +++ b/config/broadcasting.php @@ -0,0 +1,53 @@ + env('BROADCASTING_DEFAULT', 'pusher'), + + /* + |-------------------------------------------------------------------------- + | 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' => [ + 'driver' => 'pusher', + 'key' => env('PUSHER_KEY'), + 'secret' => env('PUSHER_SECRET'), + 'app_id' => env('PUSHER_APP_ID'), + 'options' => [ + 'cluster' => 'eu', + 'encrypted' => true, + ], + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + ], + + 'log' => [ + 'driver' => 'log', + ], + + ], + +]; diff --git a/config/cache.php b/config/cache.php new file mode 100644 index 0000000..8bc0312 --- /dev/null +++ b/config/cache.php @@ -0,0 +1,99 @@ + 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. + | + */ + + 'stores' => [ + + 'apc' => [ + 'driver' => 'apc', + ], + + 'array' => [ + 'driver' => 'array', + 'serialize' => false, + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'cache', + 'connection' => null, + ], + + 'file' => [ + 'driver' => 'file', + 'path' => storage_path('framework/cache/data'), + ], + + 'memcached' => [ + 'driver' => 'memcached', + 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), + 'sasl' => [ + env('MEMCACHED_USERNAME'), + env('MEMCACHED_PASSWORD'), + ], + 'options' => [ + // Memcached::OPT_CONNECT_TIMEOUT => 2000, + ], + 'servers' => [ + [ + 'host' => env('MEMCACHED_HOST', '127.0.0.1'), + 'port' => env('MEMCACHED_PORT', 11211), + 'weight' => 100, + ], + ], + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'cache', + ], + + 'dynamodb' => [ + 'driver' => 'dynamodb', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), + 'endpoint' => env('DYNAMODB_ENDPOINT'), + ], + + ], + + /* + |-------------------------------------------------------------------------- + | 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', 'october'), '_').'_cache_'), + +]; diff --git a/config/cms.php b/config/cms.php new file mode 100644 index 0000000..3966bf6 --- /dev/null +++ b/config/cms.php @@ -0,0 +1,220 @@ + env('ACTIVE_THEME', 'demo'), + + /* + |-------------------------------------------------------------------------- + | Database Themes + |-------------------------------------------------------------------------- + | + | Globally forces all themes to store template changes in the database, + | instead of the file system. If this feature is enabled, changes will + | not be stored in the file system. + | + | false - All theme templates are sourced from the filesystem. + | true - Source theme templates from the database with fallback to the filesystem. + | + */ + + 'database_templates' => env('CMS_DB_TEMPLATES', false), + + /* + |-------------------------------------------------------------------------- + | Template Strictness + |-------------------------------------------------------------------------- + | + | When enabled, an error is thrown when a component, variable, or attribute + | used does not exist. When disabled, a null value is returned instead. + | + */ + + 'strict_variables' => env('CMS_STRICT_VARIABLES', false), + + 'strict_components' => env('CMS_STRICT_COMPONENTS', false), + + /* + |-------------------------------------------------------------------------- + | Frontend Timezone + |-------------------------------------------------------------------------- + | + | This acts as the default setting for a frontend user's timezone used when + | converting dates from the system setting, typically set to UTC. + | + */ + + 'timezone' => 'UTC', + + /* + |-------------------------------------------------------------------------- + | Template Caching + |-------------------------------------------------------------------------- + | + | 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. + | + */ + + 'template_cache_ttl' => 1440, + + /* + |-------------------------------------------------------------------------- + | Twig Cache + |-------------------------------------------------------------------------- + | + | Store a temporary cache of parsed Twig templates in the local filesystem. + | + */ + + 'enable_twig_cache' => env('CMS_TWIG_CACHE', true), + + /* + |-------------------------------------------------------------------------- + | 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 clear:cache command should be used. It is recommended + | to disable the caching during the development, and enable it in the production mode. + | + */ + + 'enable_route_cache' => env('CMS_ROUTE_CACHE', 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 backend or when the + | interval, in minutes, specified with the url_cache_ttl parameter expires. + | + */ + + 'url_cache_ttl' => 60, + + /* + |-------------------------------------------------------------------------- + | 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 clear cache command should be used. It is recommended + | to disable the caching during the development, and enable it in the production mode. + | + */ + + 'enable_asset_cache' => env('CMS_ASSET_CACHE', true), + + /* + |-------------------------------------------------------------------------- + | 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. + | + */ + + 'enable_asset_minify' => env('CMS_ASSET_MINIFY', false), + + /* + |-------------------------------------------------------------------------- + | 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. + | + */ + + 'enable_asset_deep_hashing' => env('CMS_ASSET_DEEP_HASHING', null), + + /* + |-------------------------------------------------------------------------- + | Site Redirect Policy + |-------------------------------------------------------------------------- + | + | Controls the behavior when the root URL is opened without a matched site. + | + | detect - detect the site based on the browser language + | primary - use the primary site + | - use a specific site identifier (id) + | + */ + + 'redirect_policy' => env('CMS_REDIRECT_POLICY', 'detect'), + + /* + |-------------------------------------------------------------------------- + | 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. + | + */ + + 'force_bytecode_invalidation' => true, + + /* + |-------------------------------------------------------------------------- + | 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. + | + */ + + 'safe_mode' => env('CMS_SAFE_MODE', null), + + /* + |-------------------------------------------------------------------------- + | V1 Security Policy + |-------------------------------------------------------------------------- + | + | When using safe mode configuration, the Twig sandbox becomes very strict and + | uses an allow-list to protect calling unapproved methods. Instead, you may + | use V1, which is a more relaxed policy that uses a block-list, it blocks + | most of the unsecure methods but is not as secure as an allow-list. + | + */ + + 'security_policy_v1' => env('CMS_SECURITY_POLICY_V1', false), + + /* + |-------------------------------------------------------------------------- + | V1 Exception Policy + |-------------------------------------------------------------------------- + | + | When debug mode is off, throwing exceptions in AJAX will display a generic + | message, except for specific exception types such as ApplicationException + | and ValidationException (allow-list). Instead, you may use V1, which is + | a more relaxed policy that allows all messages and blocks common exception + | types (block-list) but may still leak information in rare cases. + | + */ + + 'exception_policy_v1' => env('CMS_EXCEPTION_POLICY_V1', false), + +]; diff --git a/config/database.php b/config/database.php new file mode 100644 index 0000000..c53e0a6 --- /dev/null +++ b/config/database.php @@ -0,0 +1,158 @@ + PDO::FETCH_CLASS, + + /* + |-------------------------------------------------------------------------- + | Default Database Connection Name + |-------------------------------------------------------------------------- + | + | Here you may specify which of the database connections below you wish + | to use as your default connection for all database work. Of course + | you may use many connections at once using the Database library. + | + */ + + 'default' => 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 Laravel is shown below to make development simple. + | + | + | All database work in Laravel 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' => [ + 'driver' => 'sqlite', + 'url' => env('DATABASE_URL'), + 'database' => env('DB_DATABASE', database_path('database.sqlite')), + 'prefix' => '', + 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), + ], + + 'mysql' => [ + 'driver' => 'mysql', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '3306'), + 'database' => env('DB_DATABASE', 'database'), + 'username' => env('DB_USERNAME', 'root'), + 'password' => env('DB_PASSWORD', ''), + 'unix_socket' => env('DB_SOCKET', ''), + 'charset' => 'utf8mb4', + 'collation' => 'utf8mb4_unicode_ci', + 'prefix' => '', + 'prefix_indexes' => true, + 'strict' => true, + 'engine' => 'InnoDB', + 'options' => extension_loaded('pdo_mysql') ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + ]) : [], + ], + + 'pgsql' => [ + 'driver' => 'pgsql', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '5432'), + 'database' => env('DB_DATABASE', 'database'), + 'username' => env('DB_USERNAME', 'root'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => 'utf8', + 'prefix' => '', + 'prefix_indexes' => true, + 'schema' => 'public', + 'sslmode' => env('DB_SSLMODE', 'prefer'), + ], + + 'sqlsrv' => [ + 'driver' => 'sqlsrv', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', 'localhost'), + 'port' => env('DB_PORT', '1433'), + 'database' => env('DB_DATABASE', 'database'), + 'username' => env('DB_USERNAME', 'root'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => 'utf8', + 'prefix' => '', + 'prefix_indexes' => true, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | 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 have not actually be run in the databases. + | + */ + + 'migrations' => 'migrations', + + /* + |-------------------------------------------------------------------------- + | Redis Databases + |-------------------------------------------------------------------------- + | + | Redis is an open source, fast, and advanced key-value store that also + | provides a richer set of commands than a typical key-value systems + | such as APC or Memcached. Laravel makes it easy to dig right in. + | + */ + + 'redis' => [ + + 'client' => env('REDIS_CLIENT', 'phpredis'), + + 'options' => [ + 'cluster' => env('REDIS_CLUSTER', 'redis'), + 'prefix' => env('REDIS_PREFIX', 'october_database_'), + ], + + 'default' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', 6379), + 'database' => env('REDIS_DB', '0'), + ], + + 'cache' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('REDIS_CACHE_DB', '1'), + ], + + ], + +]; diff --git a/config/filesystems.php b/config/filesystems.php new file mode 100644 index 0000000..8e21ebf --- /dev/null +++ b/config/filesystems.php @@ -0,0 +1,77 @@ + env('FILESYSTEM_DRIVER', '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" + | + */ + + 'disks' => [ + + 'local' => [ + 'driver' => 'local', + 'root' => storage_path('app'), + 'throw' => false, + ], + + 'uploads' => [ + 'driver' => 'local', + 'root' => storage_path('app/uploads'), + 'url' => '/storage/app/uploads', + 'visibility' => 'public', + 'throw' => false, + ], + + 'media' => [ + 'driver' => 'local', + 'root' => storage_path('app/media'), + 'url' => '/storage/app/media', + 'visibility' => 'public', + 'throw' => false, + ], + + 'resources' => [ + 'driver' => 'local', + 'root' => storage_path('app/resources'), + 'url' => '/storage/app/resources', + 'visibility' => 'public', + 'throw' => false, + ], + + 's3' => [ + 'driver' => 's3', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION'), + 'bucket' => env('AWS_BUCKET'), + 'url' => env('AWS_URL'), + 'endpoint' => env('AWS_ENDPOINT'), + 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), + 'throw' => false, + ], + + ], + +]; diff --git a/config/hashing.php b/config/hashing.php new file mode 100644 index 0000000..8425770 --- /dev/null +++ b/config/hashing.php @@ -0,0 +1,52 @@ + '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' => 1024, + 'threads' => 2, + 'time' => 2, + ], + +]; diff --git a/config/logging.php b/config/logging.php new file mode 100644 index 0000000..62ce5e2 --- /dev/null +++ b/config/logging.php @@ -0,0 +1,93 @@ + env('LOG_CHANNEL', 'stack'), + + /* + |-------------------------------------------------------------------------- + | Log Channels + |-------------------------------------------------------------------------- + | + | Here you may configure the log channels for your application. Out of + | the box, Laravel 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' => [ + 'driver' => 'stack', + 'channels' => ['daily'], + 'ignore_exceptions' => false, + ], + + 'single' => [ + 'driver' => 'single', + 'path' => storage_path('logs/system.log'), + 'level' => 'debug' + ], + + 'daily' => [ + 'driver' => 'daily', + 'path' => storage_path('logs/system.log'), + 'level' => 'debug', + 'days' => 14 + ], + + 'slack' => [ + 'driver' => 'slack', + 'url' => env('LOG_SLACK_WEBHOOK_URL'), + 'username' => 'October CMS Log', + 'emoji' => ':boom:', + 'level' => 'critical', + ], + + 'papertrail' => [ + 'driver' => 'monolog', + 'level' => 'debug', + 'handler' => Monolog\Handler\SyslogUdpHandler::class, + 'handler_with' => [ + 'host' => env('PAPERTRAIL_URL'), + 'port' => env('PAPERTRAIL_PORT'), + ], + ], + + 'stderr' => [ + 'driver' => 'monolog', + 'handler' => Monolog\Handler\StreamHandler::class, + 'formatter' => env('LOG_STDERR_FORMATTER'), + 'with' => [ + 'stream' => 'php://stderr', + ], + ], + + 'syslog' => [ + 'driver' => 'syslog', + 'level' => 'debug', + ], + + 'errorlog' => [ + 'driver' => 'errorlog', + 'level' => 'debug', + ], + + ], + +]; diff --git a/config/mail.php b/config/mail.php new file mode 100644 index 0000000..19defe9 --- /dev/null +++ b/config/mail.php @@ -0,0 +1,99 @@ + 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. + | + | Laravel 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" + | + */ + + 'mailers' => [ + 'smtp' => [ + 'transport' => 'smtp', + 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), + 'port' => env('MAIL_PORT', 587), + 'encryption' => env('MAIL_ENCRYPTION', 'tls'), + 'username' => env('MAIL_USERNAME'), + 'password' => env('MAIL_PASSWORD'), + 'timeout' => null, + 'auth_mode' => null, + ], + + 'ses' => [ + 'transport' => 'ses', + ], + + 'mailgun' => [ + 'transport' => 'mailgun', + ], + + 'postmark' => [ + 'transport' => 'postmark', + ], + + 'sendmail' => [ + 'transport' => 'sendmail', + 'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -t -i'), + ], + + 'log' => [ + 'transport' => 'log', + 'channel' => env('MAIL_LOG_CHANNEL'), + ], + + 'array' => [ + 'transport' => 'array', + ], + + 'failover' => [ + 'transport' => 'failover', + 'mailers' => [ + 'smtp', + 'log', + ], + ], + ], + + /* + |-------------------------------------------------------------------------- + | 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.tld'), + 'name' => env('MAIL_FROM_NAME', 'October CMS'), + ], + +]; diff --git a/config/media.php b/config/media.php new file mode 100644 index 0000000..75f0f90 --- /dev/null +++ b/config/media.php @@ -0,0 +1,79 @@ + 10, + + /* + |-------------------------------------------------------------------------- + | Automatically Rename Filenames + |-------------------------------------------------------------------------- + | + | When a media file is uploaded, automatically transform its filename to + | something consistent. The "slug" mode will slug the file name for all + | uploads. + | + | Supported: "null", "slug" + | + */ + + 'auto_rename' => null, + + /* + |-------------------------------------------------------------------------- + | Ignored Files and Patterns + |-------------------------------------------------------------------------- + | + | The media manager wil ignore file names and patterns specified here + | + */ + + 'ignore_files' => ['.svn', '.git', '.DS_Store', '.AppleDouble'], + + 'ignore_patterns' => ['^\..*'], + + /* + |-------------------------------------------------------------------------- + | Image Extensions + |-------------------------------------------------------------------------- + | + | File extensions corresponding to the Image document type + | + */ + + 'image_extensions' => ['jpg', 'jpeg', 'bmp', 'png', 'webp', 'gif'], + + /* + |-------------------------------------------------------------------------- + | Video Extensions + |-------------------------------------------------------------------------- + | + | File extensions corresponding to the Video document type + | + */ + + 'video_extensions' => ['mp4', 'avi', 'mov', 'mpg', 'mpeg', 'mkv', 'webm'], + + /* + |-------------------------------------------------------------------------- + | Audio Extensions + |-------------------------------------------------------------------------- + | + | File extensions corresponding to the Audio document type + | + */ + + 'audio_extensions' => ['mp3', 'wav', 'wma', 'm4a', 'ogg'], + +]; diff --git a/config/queue.php b/config/queue.php new file mode 100644 index 0000000..7fa995c --- /dev/null +++ b/config/queue.php @@ -0,0 +1,90 @@ + 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 Laravel. You are free to add more. + | + */ + + 'connections' => [ + + 'sync' => [ + 'driver' => 'sync', + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'jobs', + 'queue' => 'default', + 'retry_after' => 90, + ], + + 'beanstalkd' => [ + 'driver' => 'beanstalkd', + 'host' => 'localhost', + 'queue' => 'default', + 'retry_after' => 90, + 'block_for' => 0, + ], + + 'sqs' => [ + 'driver' => 'sqs', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), + 'queue' => env('SQS_QUEUE', 'your-queue-name'), + 'suffix' => env('SQS_SUFFIX'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + 'queue' => env('REDIS_QUEUE', 'default'), + 'retry_after' => 90, + 'block_for' => null, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | 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' => [ + 'driver' => env('QUEUE_FAILED_DRIVER', 'database'), + 'database' => env('DB_CONNECTION', 'mysql'), + 'table' => 'failed_jobs', + ], + +]; diff --git a/config/services.php b/config/services.php new file mode 100644 index 0000000..b89f02c --- /dev/null +++ b/config/services.php @@ -0,0 +1,34 @@ + [ + 'domain' => env('MAILGUN_DOMAIN'), + 'secret' => env('MAILGUN_SECRET'), + 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), + 'scheme' => 'https', + ], + + 'postmark' => [ + 'token' => env('POSTMARK_TOKEN'), + ], + + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + +]; diff --git a/config/session.php b/config/session.php new file mode 100644 index 0000000..ce64bbf --- /dev/null +++ b/config/session.php @@ -0,0 +1,200 @@ + 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 for it is expired. If you want them + | to immediately expire when the browser closes, set it to zero. + | + */ + + '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', 'october_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 if it can not be done securely. + | + */ + + 'secure' => env('SESSION_SECURE_COOKIE'), + + /* + |-------------------------------------------------------------------------- + | 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 + | do not enable this as other CSRF protection services are in place. + | + | In the strict mode, the cookie is not sent with any cross-site usage + | even if the user follows a link to another website. Lax cookies are + | only sent with a top-level get request. + | + | Supported: "lax", "strict" + | + */ + + 'same_site' => 'lax', + +]; diff --git a/config/system.php b/config/system.php new file mode 100644 index 0000000..17cc25d --- /dev/null +++ b/config/system.php @@ -0,0 +1,181 @@ + env('LOAD_MODULES'), + + /* + |-------------------------------------------------------------------------- + | Disable Specified Plugins + |-------------------------------------------------------------------------- + | + | Specify plugin codes which will always be disabled in the application. + | + | DISABLE_PLUGINS="October.Demo,RainLab.Blog" + | + */ + + 'disable_plugins' => env('DISABLE_PLUGINS'), + + /* + |-------------------------------------------------------------------------- + | Link 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 + | + | By default most links use their fully qualified URLs or reference their + | CDN location. In some cases you may prefer relative links where possible + | if so, set the relative_links value to true. + | + */ + + 'link_policy' => env('LINK_POLICY', 'detect'), + + 'relative_links' => false, + + /* + |-------------------------------------------------------------------------- + | System Paths + |-------------------------------------------------------------------------- + | + | Specify location to core system paths. Local paths are relative if they + | do not have a leading slash. URLs can be relative to the base application + | URL or you can specify a full path URL. + | + | PLUGINS_PATH="plugins" + | PLUGINS_ASSET_URL="/plugins" + | + | THEMES_PATH="/absolute/path/to/themes" + | THEMES_ASSET_URL="http://localhost/themes" + | + */ + + 'plugins_path' => env('PLUGINS_PATH'), + + 'plugins_asset_url' => env('PLUGINS_ASSET_URL'), + + 'themes_path' => env('THEMES_PATH'), + + 'themes_asset_url' => env('THEMES_ASSET_URL'), + + 'storage_path' => env('STORAGE_PATH'), + + 'cache_path' => env('CACHE_PATH'), + + /* + |-------------------------------------------------------------------------- + | Default Permission Masks + |-------------------------------------------------------------------------- + | + | Specifies a default file and folder permission as a string (eg: "755") for + | created files and directories in the system paths. It is recommended + | to use file as "644" and folder as "755". + | + */ + + 'default_mask' => [ + 'file' => env('DEFAULT_FILE_MASK'), + 'folder' => env('DEFAULT_FOLDER_MASK'), + ], + + /* + |-------------------------------------------------------------------------- + | Cross Site Request Forgery (CSRF) Protection + |-------------------------------------------------------------------------- + | + | If the CSRF protection is enabled, all "postback" & AJAX requests are + | checked for a valid security token. + | + */ + + 'enable_csrf_protection' => env('ENABLE_CSRF', true), + + /* + |-------------------------------------------------------------------------- + | Convert Line Endings + |-------------------------------------------------------------------------- + | + | Determines if October CMS should convert line endings from the Windows + | style \r\n to the Unix style \n. + | + */ + + 'convert_line_endings' => env('CONVERT_LINE_ENDINGS', false), + + /* + |-------------------------------------------------------------------------- + | Cookie Encryption + |-------------------------------------------------------------------------- + | + | October CMS encrypts/decrypts cookies by default. You can specify cookies + | that should not be encrypted or decrypted here. This is useful, for + | example, when you want to pass data from frontend to server side backend + | via cookies, and vice versa. + | + */ + + 'unencrypt_cookies' => env('UNENCRYPT_COOKIES', [ + // 'my_cookie', + ]), + + /* + |-------------------------------------------------------------------------- + | Automatically Mirror to Public Directory + |-------------------------------------------------------------------------- + | + | Performed after a composer update. + | + | true - automatically mirror asset to the public directory + | false - never mirror assets to public directory + | null - only mirror assets when debug mode is OFF (in production) + | + */ + + 'auto_mirror_public' => env('AUTO_MIRROR_PUBLIC', false), + + /* + |-------------------------------------------------------------------------- + | Automatically Rollback Plugins + |-------------------------------------------------------------------------- + | + | Attempt to automatically reverse database migrations for a plugin when + | they are uninstalled using composer. This is disabled by default + | to prevent data loss. + | + */ + + 'auto_rollback_plugins' => env('AUTO_ROLLBACK_PLUGINS', false), + + /* + |-------------------------------------------------------------------------- + | Base Directory Restriction + |-------------------------------------------------------------------------- + | + | Restricts loading backend template and config files to within the base + | directory of the application. For example, when using the symlink option + | in composer for local packages. + | + | Warning: This should never be disabled in production for security reasons. + | + */ + + 'restrict_base_dir' => env('RESTRICT_BASE_DIR', true), + +]; diff --git a/config/view.php b/config/view.php new file mode 100644 index 0000000..d9dee4c --- /dev/null +++ b/config/view.php @@ -0,0 +1,36 @@ + [ + app_path('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..65eab1d --- /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/package.json b/package.json new file mode 100644 index 0000000..4b5bc94 --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "octobercms", + "homepage": "https://octobercms.com/", + "description": "October CMS is a self-hosted CMS platform based on the Laravel PHP Framework.", + "scripts": { + "dev": "npm run development", + "development": "mix", + "watch": "mix watch", + "watch-poll": "mix watch -- --watch-options-poll=1000", + "hot": "mix watch --hot", + "prod": "npm run production", + "production": "mix --production" + }, + "devDependencies": { + "babel-plugin-module-resolver": "^4.1.0", + "laravel-mix": "^6.0.39", + "less": "^4.1.2", + "less-loader": "^10.2.0", + "sass": "^1.45.0", + "sass-loader": "^12.1.0" + }, + "dependencies": { + "@popperjs/core": "^2.11.5", + "bluebird": "^3.7.2", + "bootstrap": "^5.3.0-alpha3", + "bootstrap-icons": "^1.10", + "dropzone": "^6.0.0-beta.2", + "jquery": "^3.6.0", + "js-cookie": "^3.0.1", + "popper.js": "^1.16.1", + "sortablejs": "^1.15.0", + "vue": "^2.6.14", + "vue-router": "^3.5.3" + } +} diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..fcdc873 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,44 @@ + + + The coding standard for October CMS. + + + + + + + + + + + + */database/migrations/*\.php + + + app/ + config/ + modules/ + plugins/october/demo/ + + + */vendor/* + + + */modules/*/tests/* + + + */modules/*/views/* + + + */modules/*/elements/* + + + */modules/*/layouts/* + */modules/*/controllers/*/* + + + */modules/**/_* + diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..2865e0b --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,34 @@ + + + + + ./modules/*/tests + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/blakejones/magicforms/.github/ISSUE_TEMPLATE/bug-report.md b/plugins/blakejones/magicforms/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 0000000..5a0e677 --- /dev/null +++ b/plugins/blakejones/magicforms/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,14 @@ +--- +name: Bug report +about: Create a bug report for Magic Forms + +--- + \ No newline at end of file diff --git a/plugins/blakejones/magicforms/.github/ISSUE_TEMPLATE/config.yml b/plugins/blakejones/magicforms/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..501d491 --- /dev/null +++ b/plugins/blakejones/magicforms/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Ask a question + url: https://github.com/blakej115/magic-forms/discussions + about: Ask questions and discuss with other community members \ No newline at end of file diff --git a/plugins/blakejones/magicforms/LICENCE.md b/plugins/blakejones/magicforms/LICENCE.md new file mode 100644 index 0000000..38cee79 --- /dev/null +++ b/plugins/blakejones/magicforms/LICENCE.md @@ -0,0 +1,19 @@ +# MIT license + +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/plugins/blakejones/magicforms/Plugin.php b/plugins/blakejones/magicforms/Plugin.php new file mode 100644 index 0000000..13069e8 --- /dev/null +++ b/plugins/blakejones/magicforms/Plugin.php @@ -0,0 +1,107 @@ + 'blakejones.magicforms::lang.plugin.name', + 'description' => 'blakejones.magicforms::lang.plugin.description', + 'author' => 'Martin M. (Forked by Blake Jones)', + 'icon' => 'icon-bolt', + 'homepage' => 'https://github.com/blakej115/magic-forms' + ]; + } + + public function registerNavigation() { + if(Settings::get('global_hide_button', false)) { return; } + return [ + 'forms' => [ + 'label' => 'blakejones.magicforms::lang.menu.label', + 'icon' => 'icon-bolt', + 'iconSvg' => 'plugins/blakejones/magicforms/assets/imgs/icon.svg', + 'url' => BackendHelpers::getBackendURL(['blakejones.magicforms.access_records' => 'blakejones/magicforms/records', 'blakejones.magicforms.access_exports' => 'blakejones/magicforms/exports'], 'blakejones.magicforms.access_records'), + 'permissions' => ['blakejones.magicforms.*'], + 'sideMenu' => [ + 'records' => [ + 'label' => 'blakejones.magicforms::lang.menu.records.label', + 'icon' => 'icon-database', + 'url' => Backend::url('blakejones/magicforms/records'), + 'permissions' => ['blakejones.magicforms.access_records'], + 'counter' => UnreadRecords::getTotal(), + 'counterLabel' => 'Un-Read Messages' + ], + 'exports' => [ + 'label' => 'blakejones.magicforms::lang.menu.exports.label', + 'icon' => 'icon-download', + 'url' => Backend::url('blakejones/magicforms/exports'), + 'permissions' => ['blakejones.magicforms.access_exports'] + ], + ] + ] + ]; + } + + public function registerSettings() { + return [ + 'config' => [ + 'label' => 'blakejones.magicforms::lang.menu.label', + 'description' => 'blakejones.magicforms::lang.menu.settings', + 'category' => SettingsManager::CATEGORY_CMS, + 'icon' => 'icon-bolt', + 'class' => 'BlakeJones\MagicForms\Models\Settings', + 'permissions' => ['blakejones.magicforms.access_settings'], + 'order' => 500 + ] + ]; + } + + public function registerPermissions() { + return [ + 'blakejones.magicforms.access_settings' => ['tab' => 'blakejones.magicforms::lang.permissions.tab', 'label' => 'blakejones.magicforms::lang.permissions.access_settings'], + 'blakejones.magicforms.access_records' => ['tab' => 'blakejones.magicforms::lang.permissions.tab', 'label' => 'blakejones.magicforms::lang.permissions.access_records'], + 'blakejones.magicforms.access_exports' => ['tab' => 'blakejones.magicforms::lang.permissions.tab', 'label' => 'blakejones.magicforms::lang.permissions.access_exports'], + 'blakejones.magicforms.gdpr_cleanup' => ['tab' => 'blakejones.magicforms::lang.permissions.tab', 'label' => 'blakejones.magicforms::lang.permissions.gdpr_cleanup'], + ]; + } + + public function registerComponents() { + return [ + 'BlakeJones\MagicForms\Components\GenericForm' => 'genericForm', + 'BlakeJones\MagicForms\Components\UploadForm' => 'uploadForm', + 'BlakeJones\MagicForms\Components\EmptyForm' => 'emptyForm', + ]; + } + + public function registerMailTemplates() { + return [ + 'blakejones.magicforms::mail.notification' => Lang::get('blakejones.magicforms::lang.mails.form_notification.description'), + 'blakejones.magicforms::mail.autoresponse' => Lang::get('blakejones.magicforms::lang.mails.form_autoresponse.description'), + ]; + } + + public function register() { + $this->app->resolving('validator', function($validator) { + Validator::extend('recaptcha', 'BlakeJones\MagicForms\Classes\ReCaptchaValidator@validateReCaptcha'); + }); + } + + public function registerSchedule($schedule) { + $schedule->call(function () { + $records = GDPR::cleanRecords(); + })->daily(); + } + + } + +?> diff --git a/plugins/blakejones/magicforms/README.md b/plugins/blakejones/magicforms/README.md new file mode 100644 index 0000000..087a802 --- /dev/null +++ b/plugins/blakejones/magicforms/README.md @@ -0,0 +1,35 @@ +# Magic Forms for October CMS v3 +Create easy (and almost magic) AJAX forms. + +# Support for October CMS v3 (Forked) +The original version of this plugin was [abandoned](https://github.com/skydiver/october-plugin-forms/discussions/267). This is an actively maintained fork of the [original plugin](https://octobercms.com/plugin/martin-forms) that supports October CMS v3. + +## Why Magic Forms? +Almost everyday we do forms for our clients, personal projects, etc + +Sometimes we need to add or remove fields, change validations, store data and at some point, this can be boring and repetitive. + +So, the objective was to find a way to just put the HTML elements on the page, skip the repetitive task of coding and (with some kind of magic) store this data on a database or send by mail. + +## Features +* Create any type of form: contact, feedback, registration, uploads, etc +* Write only HTML +* Don't code forms logic +* Laravel validation +* Custom validation errors +* Use multiple forms on same page +* Store on database +* Export data in CSV +* Access database records from backend +* Send mail notifications to multiple recipients +* Auto-response email on form submit +* reCAPTCHA validation +* Support for Translate plugin +* Inline errors with fields (read documentation for more info) +* AJAX file uploads (BETA, available since v1.3.0) + +## Documentation + +New documentation coming soon. For now, you may reference the old documentation: + +> https://skydiver.github.io/october-plugin-forms/docs/introduction/ \ No newline at end of file diff --git a/plugins/blakejones/magicforms/assets/css/records.css b/plugins/blakejones/magicforms/assets/css/records.css new file mode 100644 index 0000000..cdac4db --- /dev/null +++ b/plugins/blakejones/magicforms/assets/css/records.css @@ -0,0 +1,8 @@ +.files-container ul { padding:0; list-style:none; } + +.record-table { width:100%; border-collapse:collapse; box-shadow:5px 5px 10px #AAA; } +.record-table td { padding:10px; border:solid 1px #D4D8DA; } +.record-label { width:20%; background-color:#ECF0F1; text-align:right; } +.record-value { width:80%; background-color:#F9F9F9; } +.record-value ul { margin:0; } +.record-metadata { font-size:0.8em; color:#888; font-weight:bold; } \ No newline at end of file diff --git a/plugins/blakejones/magicforms/assets/css/uploader.css b/plugins/blakejones/magicforms/assets/css/uploader.css new file mode 100644 index 0000000..fc13815 --- /dev/null +++ b/plugins/blakejones/magicforms/assets/css/uploader.css @@ -0,0 +1,704 @@ +.responsiv-uploader-fileupload:after { + content: ""; + display: table; + clear: both; +} +.responsiv-uploader-fileupload .upload-object { + border-radius: 3px; + position: relative; + outline: none; + overflow: hidden; + display: inline-block; + vertical-align: top; +} +.responsiv-uploader-fileupload .upload-object img { + width: 100%; + height: 100%; +} +.responsiv-uploader-fileupload .upload-object .icon-container { + display: table; + opacity: .6; +} +.responsiv-uploader-fileupload .upload-object .icon-container i { + color: #95a5a6; + display: inline-block; +} +.responsiv-uploader-fileupload .upload-object .icon-container div { + display: table-cell; + text-align: center; + vertical-align: middle; +} +.responsiv-uploader-fileupload .upload-object .icon-container.image > div.icon-wrapper { + display: none; +} +.responsiv-uploader-fileupload .upload-object h4 { + font-weight: 600; + font-size: 13px; + color: #2b3e50; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + line-height: 150%; + margin: 15px 0 5px 0; + padding-right: 0; + transition: padding 0.1s; + position: relative; +} +.responsiv-uploader-fileupload .upload-object h4 a { + position: absolute; + right: 0; + top: 0; + display: none; + font-weight: 400; +} +.responsiv-uploader-fileupload .upload-object p.size, +.responsiv-uploader-fileupload .upload-object p.error { + font-size: 12px; + color: #95a5a6; +} +.responsiv-uploader-fileupload .upload-object p.size strong, +.responsiv-uploader-fileupload .upload-object p.error strong { + font-weight: 400; +} +.responsiv-uploader-fileupload .upload-object p.error { + display: none; + color: #ab2a1c; +} +.responsiv-uploader-fileupload .upload-object .info h4 a, +.responsiv-uploader-fileupload .upload-object .meta a.upload-remove-button { + color: #2b3e50; + display: none; + font-size: 24px; + line-height: 16px; + text-decoration: none; +} +.responsiv-uploader-fileupload .upload-object .icon-container { + position: relative; +} +.responsiv-uploader-fileupload .upload-object .icon-container:after { + background-image: url('../../../../../modules/system/assets/ui/images/loader-transparent.svg'); + position: absolute; + content: ' '; + width: 40px; + height: 40px; + left: 50%; + top: 50%; + margin-top: -20px; + margin-left: -20px; + display: block; + background-size: 40px 40px; + background-position: 50% 50%; + animation: spin 1s linear infinite; +} +.responsiv-uploader-fileupload .upload-object.is-success .icon-container { + opacity: 1; +} +.responsiv-uploader-fileupload .upload-object.is-success .icon-container:after { + opacity: 0; + transition: opacity .3s ease; +} +.responsiv-uploader-fileupload .upload-object.is-loading .icon-container { + opacity: .6; +} +.responsiv-uploader-fileupload .upload-object.is-loading .icon-container:after { + opacity: 1; + transition: opacity .3s ease; +} +.responsiv-uploader-fileupload .upload-object.is-success { + cursor: pointer; +} +.responsiv-uploader-fileupload .upload-object.is-success .progress-bar { + opacity: 0; + transition: opacity .3s ease; +} +.responsiv-uploader-fileupload .upload-object.is-success:hover h4 a, +.responsiv-uploader-fileupload .upload-object.is-success:hover .meta .upload-remove-button { + display: block; +} +.responsiv-uploader-fileupload .upload-object.is-error { + cursor: pointer; +} +.responsiv-uploader-fileupload .upload-object.is-error .progress-bar { + opacity: 0; + transition: opacity .3s ease; +} +.responsiv-uploader-fileupload .upload-object.is-error .icon-container { + opacity: 1; +} +.responsiv-uploader-fileupload .upload-object.is-error .icon-container > img, +.responsiv-uploader-fileupload .upload-object.is-error .icon-container > i { + opacity: .5; +} +.responsiv-uploader-fileupload .upload-object.is-error .info h4 { + color: #ab2a1c; +} +.responsiv-uploader-fileupload .upload-object.is-error p.error { + display: block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.responsiv-uploader-fileupload .upload-object.is-error .info .upload-remove-button, +.responsiv-uploader-fileupload .upload-object.is-error .meta .upload-remove-button { + display: block; +} +.responsiv-uploader-fileupload.is-preview .upload-button, +.responsiv-uploader-fileupload.is-preview .upload-remove-button { + display: none !important; +} +@media (max-width: 1024px) { + .responsiv-uploader-fileupload .upload-object.is-success h4 a, + .responsiv-uploader-fileupload .upload-object.is-success .meta .upload-remove-button { + display: block !important; + } +} +@-moz-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + } + 100% { + -moz-transform: rotate(359deg); + } +} +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + } +} +@-o-keyframes spin { + 0% { + -o-transform: rotate(0deg); + } + 100% { + -o-transform: rotate(359deg); + } +} +@-ms-keyframes spin { + 0% { + -ms-transform: rotate(0deg); + } + 100% { + -ms-transform: rotate(359deg); + } +} +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(359deg); + } +} +.responsiv-uploader-fileupload.style-image-multi .upload-button, +.responsiv-uploader-fileupload.style-image-multi .upload-object { + margin: 0 10px 10px 0; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object { + background: #fff; + border: 1px solid #ecf0f1; + width: 260px; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object .progress-bar { + display: block; + width: 100%; + overflow: hidden; + height: 5px; + background-color: #f5f5f5; + border-radius: 2px; + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + position: absolute; + bottom: 10px; + left: 0; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object .progress-bar .upload-progress { + float: left; + width: 0%; + height: 100%; + line-height: 5px; + color: #ffffff; + background-color: #5fb6f5; + box-shadow: none; + transition: width .6s ease; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object .icon-container { + border-right: 1px solid #f6f8f9; + float: left; + display: inline-block; + overflow: hidden; + width: 75px; + height: 75px; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object .icon-container i { + font-size: 35px; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object .icon-container.image img { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; + width: auto; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object .info { + margin-left: 90px; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object .info h4 { + padding-right: 15px; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object .info h4 a { + right: 15px; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object .meta { + position: absolute; + bottom: 0; + left: 0; + right: 0; + margin: 0 15px 0 90px; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object.upload-placeholder { + height: 75px; + background-color: transparent; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object.upload-placeholder:after { + opacity: 0; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object:hover { + background: #4da7e8 !important; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object:hover i, +.responsiv-uploader-fileupload.style-image-multi .upload-object:hover p.size, +.responsiv-uploader-fileupload.style-image-multi .upload-object:hover p.error, +.responsiv-uploader-fileupload.style-image-multi .upload-object:hover .upload-remove-button { + color: #ecf0f1; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object:hover h4 { + color: white; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object:hover .icon-container { + border-right-color: #4da7e8 !important; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object:hover.is-error { + background: #ab2a1c !important; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object:hover h4 { + padding-right: 35px; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object.is-error h4 { + padding-right: 35px; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object.is-error .info p.size { + display: none; +} +.responsiv-uploader-fileupload.style-image-multi .upload-object.is-error .info p.error { + padding-bottom: 11px; +} +.responsiv-uploader-fileupload.style-image-multi.is-preview .upload-files-container { + margin-left: 0; +} +@media (max-width: 1280px) { + .responsiv-uploader-fileupload.style-image-multi .upload-object { + width: 230px; + } +} +@media (max-width: 1024px) { + .responsiv-uploader-fileupload.style-image-multi .upload-button { + width: 100%; + } + .responsiv-uploader-fileupload.style-image-multi .upload-files-container { + margin-left: 0; + } + .responsiv-uploader-fileupload.style-image-multi .upload-object { + margin-right: 0; + display: block; + width: auto; + } +} +.responsiv-uploader-fileupload.style-image-single.is-populated .upload-button { + display: none; +} +.responsiv-uploader-fileupload.style-image-single .upload-button { + display: block; + float: left; + border: 2px dotted rgba(0, 0, 0, 0.1); + position: relative; + outline: none; + min-height: 100px; + min-width: 100px; +} +.responsiv-uploader-fileupload.style-image-single .upload-button .upload-button-icon { + position: absolute; + width: 22px; + height: 22px; + top: 50%; + left: 50%; + margin-top: -11px; + margin-left: -11px; +} +.responsiv-uploader-fileupload.style-image-single .upload-button .upload-button-icon:before { + content: "+"; + text-align: center; + display: block; + font-size: 22px; + height: 22px; + width: 22px; + line-height: 22px; + color: rgba(0, 0, 0, 0.1); + font-weight: 700; +} +.responsiv-uploader-fileupload.style-image-single .upload-button:hover { + border: 2px dotted rgba(0, 0, 0, 0.2); +} +.responsiv-uploader-fileupload.style-image-single .upload-button:hover .upload-button-icon:before { + color: #5cb85c; + color: rgba(0, 0, 0, 0.2); +} +.responsiv-uploader-fileupload.style-image-single .upload-button:focus { + border: 2px solid rgba(0, 0, 0, 0.3); + background: transparent; +} +.responsiv-uploader-fileupload.style-image-single .upload-button:focus .upload-button-icon:before { + color: #5cb85c; + color: rgba(0, 0, 0, 0.2); +} +.responsiv-uploader-fileupload.style-image-single .upload-object { + padding-bottom: 66px; +} +.responsiv-uploader-fileupload.style-image-single .upload-object .icon-container { + border: 1px solid #f6f8f9; + background: rgba(255, 255, 255, 0.5); +} +.responsiv-uploader-fileupload.style-image-single .upload-object .icon-container.image img { + border-radius: 3px; + display: block; + max-width: 100%; + height: auto; + min-height: 100px; + min-width: 100px; +} +.responsiv-uploader-fileupload.style-image-single .upload-object .progress-bar { + display: block; + width: 100%; + overflow: hidden; + height: 5px; + background-color: #f5f5f5; + border-radius: 2px; + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + position: absolute; + bottom: 10px; + left: 0; +} +.responsiv-uploader-fileupload.style-image-single .upload-object .progress-bar .upload-progress { + float: left; + width: 0%; + height: 100%; + line-height: 5px; + color: #ffffff; + background-color: #5fb6f5; + box-shadow: none; + transition: width .6s ease; +} +.responsiv-uploader-fileupload.style-image-single .upload-object .info { + position: absolute; + left: 0; + right: 0; + bottom: 0; + height: 66px; +} +.responsiv-uploader-fileupload.style-image-single .upload-object .meta { + position: absolute; + bottom: 65px; + left: 0; + right: 0; + margin: 0 15px; +} +.responsiv-uploader-fileupload.style-image-single .upload-object:hover h4 { + padding-right: 20px; +} +.responsiv-uploader-fileupload.style-image-single .upload-object.is-error h4 { + padding-right: 20px; +} +.responsiv-uploader-fileupload.style-image-single .upload-object.is-error .info p.size { + display: none; +} +.responsiv-uploader-fileupload.style-image-single .upload-object.is-error .info p.error { + padding-bottom: 11px; +} +@media (max-width: 1024px) { + .responsiv-uploader-fileupload.style-image-single .upload-object h4 { + padding-right: 20px !important; + } +} +.responsiv-uploader-fileupload.style-file-multi .upload-button { + margin-bottom: 10px; +} +.responsiv-uploader-fileupload.style-file-multi .upload-files-container { + border: 1px solid #eeeeee; + border-radius: 3px; + border-bottom: none; + display: none; +} +.responsiv-uploader-fileupload.style-file-multi.is-populated .upload-files-container { + display: block; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object { + display: block; + width: 100%; + border-bottom: 1px solid #eeeeee; + padding-left: 10px; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object:nth-child(even) { + background-color: #f5f5f5; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object .icon-container { + position: absolute; + top: 0; + left: 5px; + width: 35px; + padding: 11px 7px; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object .info { + margin-left: 35px; + margin-right: 15%; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object .info h4, +.responsiv-uploader-fileupload.style-file-multi .upload-object .info p { + margin: 0; + padding: 11px 0; + font-size: 12px; + font-weight: normal; + line-height: 150%; + color: #666666; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object .info h4 { + padding-right: 15px; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object .info h4 a { + padding: 10px 0; + right: 15px; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object .info p.size { + position: absolute; + top: 0; + right: 0; + width: 15%; + display: none; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object .info p.error { + color: #ab2a1c; + padding-top: 0; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object .progress-bar { + display: block; + width: 100%; + overflow: hidden; + height: 5px; + background-color: #f5f5f5; + border-radius: 2px; + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + position: absolute; + top: 18px; + left: 0; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object .progress-bar .upload-progress { + float: left; + width: 0%; + height: 100%; + line-height: 5px; + color: #ffffff; + background-color: #5fb6f5; + box-shadow: none; + transition: width .6s ease; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object .meta { + position: absolute; + top: 0; + right: 0; + margin-right: 15px; + width: 15%; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object .meta .upload-remove-button { + position: absolute; + top: -9px; + right: 0; + bottom: auto; + line-height: 150%; + padding: 10px 0; + z-index: 100; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object .icon-container:after { + width: 20px; + height: 20px; + margin-top: -10px; + margin-left: -10px; + background-size: 20px 20px; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object.is-success .info p.size { + display: block; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object:hover { + background: #4da7e8 !important; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object:hover i, +.responsiv-uploader-fileupload.style-file-multi .upload-object:hover p.size, +.responsiv-uploader-fileupload.style-file-multi .upload-object:hover p.error, +.responsiv-uploader-fileupload.style-file-multi .upload-object:hover .upload-remove-button { + color: #ecf0f1; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object:hover h4 { + color: white; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object:hover .icon-container { + border-right-color: #4da7e8 !important; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object:hover.is-error { + background: #ab2a1c !important; +} +.responsiv-uploader-fileupload.style-file-multi .upload-object:hover h4 { + padding-right: 35px; +} +@media (max-width: 1199px) { + .responsiv-uploader-fileupload.style-file-multi .info { + margin-right: 20% !important; + } + .responsiv-uploader-fileupload.style-file-multi .info p.size { + width: 20% !important; + } + .responsiv-uploader-fileupload.style-file-multi .meta { + width: 20% !important; + } +} +@media (max-width: 991px) { + .responsiv-uploader-fileupload.style-file-multi .upload-object h4 { + padding-right: 35px !important; + } + .responsiv-uploader-fileupload.style-file-multi .info { + margin-right: 25% !important; + } + .responsiv-uploader-fileupload.style-file-multi .info p.size { + width: 25% !important; + padding-right: 35px !important; + } + .responsiv-uploader-fileupload.style-file-multi .meta { + width: 25% !important; + } +} +.responsiv-uploader-fileupload.style-file-single { + background-color: #fff; + border: 1px solid #e0e0e0; + overflow: hidden; + position: relative; + padding-right: 11px; +} +.responsiv-uploader-fileupload.style-file-single .upload-button { + position: absolute; + top: 50%; + margin-top: -44px; + height: 88px; + right: 0; + margin-right: 0; +} +.responsiv-uploader-fileupload.style-file-single .upload-empty-message { + padding: 10px 0 10px 11px; + font-size: 13px; +} +.responsiv-uploader-fileupload.style-file-single.is-populated .upload-button, +.responsiv-uploader-fileupload.style-file-single.is-populated .upload-empty-message { + display: none; +} +.responsiv-uploader-fileupload.style-file-single .upload-object { + display: block; + width: 100%; + padding: 8px 0 10px 0; +} +.responsiv-uploader-fileupload.style-file-single .upload-object .icon-container { + position: absolute; + top: 0; + left: 0; + width: 35px; + padding: 0 5px; + margin: 8px 0 0 7px; + text-align: center; +} +.responsiv-uploader-fileupload.style-file-single .upload-object .info { + margin-left: 54px; + margin-right: 15%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.responsiv-uploader-fileupload.style-file-single .upload-object .info h4, +.responsiv-uploader-fileupload.style-file-single .upload-object .info p { + display: inline; + margin: 0; + padding: 0; + font-size: 12px; + line-height: 150%; + color: #666666; +} +.responsiv-uploader-fileupload.style-file-single .upload-object .info p.size { + font-weight: normal; +} +.responsiv-uploader-fileupload.style-file-single .upload-object .info p.size:before { + content: " - "; +} +.responsiv-uploader-fileupload.style-file-single .upload-object .info p.error { + color: #ab2a1c; + padding-top: 0; +} +.responsiv-uploader-fileupload.style-file-single .upload-object .progress-bar { + display: block; + width: 100%; + overflow: hidden; + height: 5px; + background-color: #f5f5f5; + border-radius: 2px; + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + position: absolute; + top: 50%; + margin-top: -2px; + right: 5px; +} +.responsiv-uploader-fileupload.style-file-single .upload-object .progress-bar .upload-progress { + float: left; + width: 0%; + height: 100%; + line-height: 5px; + color: #ffffff; + background-color: #5fb6f5; + box-shadow: none; + transition: width .6s ease; +} +.responsiv-uploader-fileupload.style-file-single .upload-object .meta { + position: absolute; + top: 50%; + margin-top: -44px; + height: 88px; + right: 0; + width: 15%; +} +.responsiv-uploader-fileupload.style-file-single .upload-object .meta .upload-remove-button { + position: absolute; + top: 50%; + right: 0; + height: 20px; + line-height: 20px; + margin-top: -10px; + margin-right: 10px; + z-index: 100; +} +.responsiv-uploader-fileupload.style-file-single .upload-object .icon-container:after { + width: 20px; + height: 20px; + margin-top: -10px; + margin-left: -10px; + background-size: 20px 20px; +} +.responsiv-uploader-fileupload.style-file-single .upload-object.is-error .info p.size { + display: none; +} +.responsiv-uploader-fileupload.style-file-single .upload-object.is-error .info p.error:before { + content: " - "; +} diff --git a/plugins/blakejones/magicforms/assets/imgs/icon.svg b/plugins/blakejones/magicforms/assets/imgs/icon.svg new file mode 100644 index 0000000..987832f --- /dev/null +++ b/plugins/blakejones/magicforms/assets/imgs/icon.svg @@ -0,0 +1,64 @@ + +image/svg+xml \ No newline at end of file diff --git a/plugins/blakejones/magicforms/assets/imgs/upload.png b/plugins/blakejones/magicforms/assets/imgs/upload.png new file mode 100644 index 0000000..bec4988 Binary files /dev/null and b/plugins/blakejones/magicforms/assets/imgs/upload.png differ diff --git a/plugins/blakejones/magicforms/assets/js/inline-errors.js b/plugins/blakejones/magicforms/assets/js/inline-errors.js new file mode 100644 index 0000000..eb7d34b --- /dev/null +++ b/plugins/blakejones/magicforms/assets/js/inline-errors.js @@ -0,0 +1,7 @@ +$(window).on('ajaxInvalidField', function(event, fieldElement, fieldName, errorMsg, isFirst) { + $(fieldElement).closest('.form-group').addClass('has-error'); +}); + +$(document).on('ajaxPromise', '[data-request]', function() { + $(this).closest('form').find('.form-group.has-error').removeClass('has-error'); +}); \ No newline at end of file diff --git a/plugins/blakejones/magicforms/assets/js/recaptcha.js b/plugins/blakejones/magicforms/assets/js/recaptcha.js new file mode 100644 index 0000000..753c207 --- /dev/null +++ b/plugins/blakejones/magicforms/assets/js/recaptcha.js @@ -0,0 +1,12 @@ +var captchas = []; + +var onloadCallback = function() { + jQuery('.g-recaptcha').each(function(index, el) { + captchas[el.id] = grecaptcha.render(el, $(el).data()); + }); +} + +function resetReCaptcha(id) { + var widget = captchas[id]; + grecaptcha.reset(widget); +} \ No newline at end of file diff --git a/plugins/blakejones/magicforms/assets/js/uploader.js b/plugins/blakejones/magicforms/assets/js/uploader.js new file mode 100644 index 0000000..de3b7b8 --- /dev/null +++ b/plugins/blakejones/magicforms/assets/js/uploader.js @@ -0,0 +1,360 @@ +/* + * File upload form field control + * + * Data attributes: + * - data-control="fileupload" - enables the file upload plugin + * - data-unique-id="XXX" - an optional identifier for multiple uploaders on the same page, this value will + * appear in the postback variable called X_OCTOBER_FILEUPLOAD + * - data-template - a Dropzone.js template to use for each item + * + * JavaScript API: + * $('div').fileUploader() + * + * Dependancies: + * - Dropzone.js + */ ++function ($) { "use strict"; + + // FILEUPLOAD CLASS DEFINITION + // ============================ + + var FileUpload = function (element, options) { + this.$el = $(element) + this.options = options || {} + + this.init() + } + + FileUpload.prototype.init = function() { + if (this.options.isMulti === null) { + this.options.isMulti = this.$el.hasClass('is-multi') + } + + if (this.options.isPreview === null) { + this.options.isPreview = this.$el.hasClass('is-preview') + } + + this.$uploadButton = $('.upload-button', this.$el) + this.$filesContainer = $('.upload-files-container', this.$el) + this.uploaderOptions = {} + + this.$el.on('click', '.upload-object.is-success', $.proxy(this.onClickSuccessObject, this)) + this.$el.on('click', '.upload-object.is-error', $.proxy(this.onClickErrorObject, this)) + + // Stop here for preview mode + if (this.options.isPreview) + return + + this.$el.on('click', '.upload-remove-button', $.proxy(this.onRemoveObject, this)) + + this.bindUploader() + } + + FileUpload.prototype.dispose = function() { + + this.$el.off('click', '.upload-object.is-success', $.proxy(this.onClickSuccessObject, this)) + this.$el.off('click', '.upload-object.is-error', $.proxy(this.onClickErrorObject, this)) + this.$el.off('click', '.upload-remove-button', $.proxy(this.onRemoveObject, this)) + + this.$el.removeData('oc.fileUpload') + + this.$el = null + this.$uploadButton = null + this.$filesContainer = null + this.uploaderOptions = null + + // In some cases options could contain callbacks, + // so it's better to clean them up too. + this.options = null + } + + // + // Uploading + // + + FileUpload.prototype.bindUploader = function() { + this.uploaderOptions = { + url: this.options.url, + paramName: this.options.paramName, + clickable: this.$uploadButton.get(0), + previewsContainer: this.$filesContainer.get(0), + maxFiles: !this.options.isMulti ? 1 : null, + headers: {} + } + + if (this.options.fileTypes) { + this.uploaderOptions.acceptedFiles = this.options.fileTypes + } + + if (this.options.template) { + this.uploaderOptions.previewTemplate = $(this.options.template).html() + } + + if (this.options.uniqueId) { + this.uploaderOptions.headers['X-OCTOBER-FILEUPLOAD'] = this.options.uniqueId + } + + this.uploaderOptions.thumbnailWidth = this.options.thumbnailWidth + ? this.options.thumbnailWidth : null + + this.uploaderOptions.thumbnailHeight = this.options.thumbnailHeight + ? this.options.thumbnailHeight : null + + this.uploaderOptions.resize = this.onResizeFileInfo + + /* + * Add CSRF token to headers + */ + var token = $('meta[name="csrf-token"]').attr('content') + if (token) { + this.uploaderOptions.headers['X-CSRF-TOKEN'] = token + } + + this.dropzone = new Dropzone(this.$el.get(0), this.uploaderOptions) + this.dropzone.on('addedfile', $.proxy(this.onUploadAddedFile, this)) + this.dropzone.on('sending', $.proxy(this.onUploadSending, this)) + this.dropzone.on('success', $.proxy(this.onUploadSuccess, this)) + this.dropzone.on('error', $.proxy(this.onUploadError, this)) + + var _this = this; + + this.dropzone.on("queuecomplete", function (file) { + if (this.getUploadingFiles().length === 0 && this.getQueuedFiles().length === 0) { + $.event.trigger({ + uploader: _this, + type : "uploadfinished", + message : "Dropzone Files upload finished", + }); + } + }); + + this.dropzone.on("sending", function (file) { + $.event.trigger({ + uploader: _this, + type : "uploadstarted", + message : "Dropzone File upload started", + }); + }); + + } + + FileUpload.prototype.onResizeFileInfo = function(file) { + var info, + targetWidth, + targetHeight + + if (!this.options.thumbnailWidth && !this.options.thumbnailWidth) { + targetWidth = targetHeight = 100 + } + else if (this.options.thumbnailWidth) { + targetWidth = this.options.thumbnailWidth + targetHeight = this.options.thumbnailWidth * file.height / file.width + } + else if (this.options.thumbnailHeight) { + targetWidth = this.options.thumbnailHeight * file.height / file.width + targetHeight = this.options.thumbnailHeight + } + + // drawImage(image, srcX, srcY, srcWidth, srcHeight, trgX, trgY, trgWidth, trgHeight) takes an image, clips it to + // the rectangle (srcX, srcY, srcWidth, srcHeight), scales it to dimensions (trgWidth, trgHeight), and draws it + // on the canvas at coordinates (trgX, trgY). + info = { + srcX: 0, + srcY: 0, + srcWidth: file.width, + srcHeight: file.height, + trgX: 0, + trgY: 0, + trgWidth: targetWidth, + trgHeight: targetHeight + } + + return info + } + + FileUpload.prototype.onUploadAddedFile = function(file) { + var $object = $(file.previewElement).data('dzFileObject', file) + + // Remove any exisiting objects for single variety + if (!this.options.isMulti) { + this.removeFileFromElement($object.siblings()) + } + + this.evalIsPopulated() + } + + FileUpload.prototype.onUploadSending = function(file, xhr, formData) { + this.addExtraFormData(formData) + } + + FileUpload.prototype.onUploadSuccess = function(file, response) { + var $preview = $(file.previewElement), + $img = $('.image img', $preview) + + $preview.addClass('is-success') + + if (response.id) { + $preview.data('id', response.id) + $preview.data('path', response.path) + $('.upload-remove-button', $preview).data('request-data', { file_id: response.id }) + $img.attr('src', response.thumb) + } + + /* + * Trigger change event (Compatability with october.form.js) + */ + this.$el.closest('[data-field-name]').trigger('change.oc.formwidget') + } + + FileUpload.prototype.onUploadError = function(file, error) { + var $preview = $(file.previewElement) + $preview.addClass('is-error') + } + + FileUpload.prototype.addExtraFormData = function(formData) { + if (this.options.extraData) { + $.each(this.options.extraData, function (name, value) { + formData.append(name, value) + }) + } + + var $form = this.$el.closest('form') + if ($form.length > 0) { + $.each($form.serializeArray(), function (index, field) { + formData.append(field.name, field.value) + }) + } + } + + FileUpload.prototype.removeFileFromElement = function($element) { + var self = this + + $element.each(function() { + var $el = $(this), + obj = $el.data('dzFileObject') + + if (obj) { + self.dropzone.removeFile(obj) + } + else { + $el.remove() + } + }) + } + + // + // User interaction + // + + FileUpload.prototype.onRemoveObject = function(ev) { + var self = this, + $object = $(ev.target).closest('.upload-object') + + $(ev.target) + .closest('.upload-remove-button') + .one('ajaxPromise', function(){ + $object.addClass('is-loading') + }) + .one('ajaxDone', function(){ + self.removeFileFromElement($object) + self.evalIsPopulated() + }) + .request() + + ev.stopPropagation() + } + + FileUpload.prototype.onClickSuccessObject = function(ev) { + // if ($(ev.target).closest('.meta').length) return + // + // var $target = $(ev.target).closest('.upload-object') + // window.open($target.data('path')) + } + + FileUpload.prototype.onClickErrorObject = function(ev) { + var + self = this, + $object = $(ev.target).closest('.upload-object'), + errorMsg = $('[data-dz-errormessage]', $object).text() + + alert(errorMsg) + + this.removeFileFromElement($object) + self.evalIsPopulated() + } + + // + // Helpers + // + + FileUpload.prototype.evalIsPopulated = function() { + var isPopulated = !!$('.upload-object', this.$filesContainer).length + this.$el.toggleClass('is-populated', isPopulated) + + // Reset maxFiles counter + if (!isPopulated) { + this.dropzone.removeAllFiles() + } + } + + FileUpload.DEFAULTS = { + url: window.location, + uniqueId: null, + extraData: {}, + paramName: 'file_data', + fileTypes: null, + template: null, + isMulti: null, + isPreview: null, + thumbnailWidth: 120, + thumbnailHeight: 120 + } + + // FILEUPLOAD PLUGIN DEFINITION + // ============================ + + var old = $.fn.fileUploader + + $.fn.fileUploader = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('oc.fileUpload') + var options = $.extend({}, FileUpload.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.fileUpload', (data = new FileUpload(this, options))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.fileUploader.Constructor = FileUpload + + // FILEUPLOAD NO CONFLICT + // ================= + + $.fn.fileUploader.noConflict = function () { + $.fn.fileUpload = old + return this + } + + // FILEUPLOAD DATA-API + // =============== + $(document).render(function () { + $('[data-control="fileupload"]').fileUploader() + }) + +}(window.jQuery); + + +var uploadDropZones = {}; + +$(document).on("uploadstarted", function(event) { + var frm = $(event.uploader.dropzone.element).parents('form'); + frm.find(':submit').prop('disabled', true); +}); + +var martin; +$(document).on("uploadfinished", function(event) { + var frm = $(event.uploader.dropzone.element).parents('form'); + frm.find(':submit').prop('disabled', false); + var dz = $(event.uploader.dropzone.element).data('unique-id'); + uploadDropZones[dz] = event; +}); \ No newline at end of file diff --git a/plugins/blakejones/magicforms/assets/less/uploader.base.less b/plugins/blakejones/magicforms/assets/less/uploader.base.less new file mode 100644 index 0000000..8ff530d --- /dev/null +++ b/plugins/blakejones/magicforms/assets/less/uploader.base.less @@ -0,0 +1,354 @@ +.uploader-object-active() { + background: @uploader-object-active-bg !important; + + i, p.size, p.error, .upload-remove-button { + color: #ecf0f1; + } + + h4 { + color: white; + } + + .icon-container { + border-right-color: @uploader-object-active-bg !important; + } + + &.is-error { + background: @uploader-object-error-bg !important; + } +} + +.uploader-progress-bar() { + display: block; + width: 100%; + overflow: hidden; + height: @uploader-progress-bar-height; + background-color: @uploader-progress-bar-bg; + border-radius: 2px; + box-shadow: inset 0 1px 2px rgba(0,0,0,.1); + + .upload-progress { + float: left; + width: 0%; + height: 100%; + line-height: @uploader-progress-bar-height; + color: @uploader-progress-bar-color; + background-color: #5fb6f5; + box-shadow: none; + transition: width .6s ease; + } +} + +.uploader-block-button() { + display: block; + float: left; + border: 2px dotted rgba(0,0,0,.1); + position: relative; + outline: none; + + .upload-button-icon { + position: absolute; + width: 22px; + height: 22px; + top: 50%; + left: 50%; + margin-top: -11px; + margin-left: -11px; + + &:before { + content: "+"; + text-align: center; + display: block; + font-size: 22px; + height: 22px; + width: 22px; + line-height: 22px; + color: rgba(0,0,0,.1); + font-weight: 700; + } + } + + &:hover { + border: 2px dotted rgba(0,0,0,.2); + + .upload-button-icon:before { + color: #5cb85c; + color: rgba(0,0,0,.2); + } + } + + &:focus { + border: 2px solid rgba(0,0,0,.3); + background: transparent; + + .upload-button-icon:before { + color: #5cb85c; + color: rgba(0,0,0,.2); + } + } +} + +.uploader-small-loader() { + width: 20px; + height: 20px; + margin-top: -10px; + margin-left: -10px; + background-size: 20px 20px; +} + +.uploader-vertical-align() { + position: absolute; + top: 50%; + margin-top: -44px; + height: 88px; +} + +// +// Shared +// + +.responsiv-uploader-fileupload { + + // Clearfix + &:after { + content: ""; + display: table; + clear: both; + } + + // + // Uploaded item + // + + .upload-object { + + border-radius: 3px; + position: relative; + outline: none; + overflow: hidden; + display: inline-block; + vertical-align: top; + + img { + width: 100%; + height: 100%; + } + + .icon-container { + display: table; + opacity: .6; + + i { + color: #95a5a6; + display: inline-block; + } + + div { + display: table-cell; + text-align: center; + vertical-align: middle; + } + } + + .icon-container.image { + > div.icon-wrapper { + display: none; + } + } + + h4 { + font-weight: 600; + font-size: 13px; + color: #2b3e50; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + line-height: 150%; + margin: 15px 0 5px 0; + padding-right: 0; + transition: padding 0.1s; + + position: relative; + + a { + position: absolute; + right: 0; + top: 0; + display: none; + font-weight: 400; + } + } + + p.size, p.error { + font-size: 12px; + color: #95a5a6; + strong { font-weight: 400; } + } + + p.error { + display: none; + color: #ab2a1c; + } + + .meta {} + + .info h4 a, + .meta a.upload-remove-button { + color: #2b3e50; + display: none; + font-size: 24px; + line-height: 16px; + text-decoration: none; + } + + } + + // + // Loading State + // + + .upload-object { + .icon-container { + position: relative; + } + + .icon-container:after { + background-image: url('../../../../../modules/system/assets/ui/images/loader-transparent.svg'); + position: absolute; + content: ' '; + width: 40px; + height: 40px; + left: 50%; + top: 50%; + margin-top: -20px; + margin-left: -20px; + display: block; + background-size: 40px 40px; + background-position: 50% 50%; + animation: spin 1s linear infinite; + } + + &.is-success { + .icon-container { + opacity: 1; + } + .icon-container:after { + opacity: 0; + transition: opacity .3s ease; + } + } + + &.is-loading { + .icon-container { + opacity: .6; + } + .icon-container:after { + opacity: 1; + transition: opacity .3s ease; + } + } + } + + // + // Success state + // + + .upload-object.is-success { + cursor: pointer; + + .progress-bar { + opacity: 0; + transition: opacity .3s ease; + } + + &:hover { + h4 a, + .meta .upload-remove-button { display: block; } + } + } + + // + // Error State + // + + .upload-object.is-error { + cursor: pointer; + + .progress-bar { + opacity: 0; + transition: opacity .3s ease; + } + + .icon-container { + opacity: 1; + > img, > i { + opacity: .5; + } + } + + .info h4 { + color: #ab2a1c; + } + + p.error { + display: block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .info .upload-remove-button, + .meta .upload-remove-button { + display: block; + } + } + + // + // Preview mode + // + + &.is-preview { + .upload-button, + .upload-remove-button { + display: none !important; + } + } +} + +// +// Media +// + +@media (max-width: 1024px) { + .responsiv-uploader-fileupload { + .upload-object.is-success { + h4 a, + .meta .upload-remove-button { display: block !important; } + } + } +} + +// +// Spin animation +// + +@-moz-keyframes spin { + 0% { -moz-transform: rotate(0deg); } + 100% { -moz-transform: rotate(359deg); } +} +@-webkit-keyframes spin { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(359deg); } +} +@-o-keyframes spin { + 0% { -o-transform: rotate(0deg); } + 100% { -o-transform: rotate(359deg); } +} +@-ms-keyframes spin { + 0% { -ms-transform: rotate(0deg); } + 100% { -ms-transform: rotate(359deg); } +} +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(359deg); } +} diff --git a/plugins/blakejones/magicforms/assets/less/uploader.filemulti.less b/plugins/blakejones/magicforms/assets/less/uploader.filemulti.less new file mode 100644 index 0000000..a237cd2 --- /dev/null +++ b/plugins/blakejones/magicforms/assets/less/uploader.filemulti.less @@ -0,0 +1,163 @@ +// +// Multi File +// + +.responsiv-uploader-fileupload.style-file-multi { + .upload-button { + margin-bottom: 10px; + } + + .upload-files-container { + border: 1px solid @uploader-list-border-color; + border-radius: 3px; + border-bottom: none; + display: none; + } + + &.is-populated .upload-files-container { + display: block; + } + + .upload-object { + display: block; + width: 100%; + border-bottom: 1px solid @uploader-list-border-color; + padding-left: 10px; + + &:nth-child(even) { + background-color: @uploader-list-accent-bg; + } + + .icon-container { + position: absolute; + top: 0; + left: 5px; + width: 35px; + padding: 11px 7px; + } + + .info { + margin-left: 35px; + margin-right: 15%; + + h4, p { + margin: 0; + padding: 11px 0; + font-size: 12px; + font-weight: normal; + line-height: 150%; + color: #666666; + } + + h4 { + padding-right: 15px; + + a { + padding: 10px 0; + right: 15px; + } + } + + p.size { + position: absolute; + top: 0; + right: 0; + width: 15%; + display: none; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + p.error { + color: #ab2a1c; + padding-top: 0; + } + } + + .progress-bar { + .uploader-progress-bar(); + position: absolute; + top: 18px; + left: 0; + } + + .meta { + position: absolute; + top: 0; + right: 0; + margin-right: 15px; + width: 15%; + + .upload-remove-button { + position: absolute; + top: -9px; + right: 0; + bottom: auto; + line-height: 150%; + padding: 10px 0; + z-index: 100; + } + } + + .icon-container:after { + .uploader-small-loader(); + } + + // + // Success + // + + &.is-success { + .info p.size { display: block; } + } + + // + // Hover + // + + &:hover { + .uploader-object-active(); + h4 { padding-right: 35px; } + } + } +} + +// +// Media +// + +@media (max-width: @screen-md-max) { + .responsiv-uploader-fileupload.style-file-multi { + .info { + margin-right: 20% !important; + p.size { + width: 20% !important; + } + } + + .meta { + width: 20% !important; + } + } +} + +@media (max-width: @screen-sm-max) { + .responsiv-uploader-fileupload.style-file-multi { + .upload-object { + h4 { padding-right: 35px !important; } + } + + .info { + margin-right: 25% !important; + p.size { + width: 25% !important; + padding-right: 35px !important; + } + } + + .meta { + width: 25% !important; + } + } +} \ No newline at end of file diff --git a/plugins/blakejones/magicforms/assets/less/uploader.filesingle.less b/plugins/blakejones/magicforms/assets/less/uploader.filesingle.less new file mode 100644 index 0000000..4a769bd --- /dev/null +++ b/plugins/blakejones/magicforms/assets/less/uploader.filesingle.less @@ -0,0 +1,112 @@ +// +// Single File +// + +.responsiv-uploader-fileupload.style-file-single { + background-color: #fff; + border: 1px solid #e0e0e0; + overflow: hidden; + position: relative; + padding-right: 11px; + + .upload-button { + .uploader-vertical-align(); + right: 0; + margin-right: 0; + } + + .upload-empty-message { + padding: 10px 0 10px 11px; + font-size: 13px; + } + + &.is-populated { + .upload-button, + .upload-empty-message { + display: none; + } + } + + .upload-object { + display: block; + width: 100%; + padding: 8px 0 10px 0; + + .icon-container { + position: absolute; + top: 0; + left: 0; + width: 35px; + padding: 0 5px; + margin: 8px 0 0 7px; + text-align: center; + } + + .info { + margin-left: 54px; + margin-right: 15%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + h4, p { + display: inline; + margin: 0; + padding: 0; + font-size: 12px; + line-height: 150%; + color: #666666; + } + + p.size { + font-weight: normal; + &:before { + content: " - "; + } + } + + p.error { + color: #ab2a1c; + padding-top: 0; + } + } + + .progress-bar { + .uploader-progress-bar(); + position: absolute; + top: 50%; + margin-top: -2px; + right: 5px; + } + + .meta { + .uploader-vertical-align(); + right: 0; + width: 15%; + .upload-remove-button { + position: absolute; + top: 50%; + right: 0; + height: 20px; + line-height: 20px; + margin-top: -10px; + margin-right: 10px; + z-index: 100; + } + } + + .icon-container:after { + .uploader-small-loader(); + } + + &.is-error { + .info { + p.size { display: none; } + p.error:before { + content: " - "; + } + } + } + } + +} \ No newline at end of file diff --git a/plugins/blakejones/magicforms/assets/less/uploader.imagemulti.less b/plugins/blakejones/magicforms/assets/less/uploader.imagemulti.less new file mode 100644 index 0000000..6607398 --- /dev/null +++ b/plugins/blakejones/magicforms/assets/less/uploader.imagemulti.less @@ -0,0 +1,117 @@ +// +// Multi Image +// + +.responsiv-uploader-fileupload.style-image-multi { + .upload-button, + .upload-object { + margin: 0 10px 10px 0; + } + + .upload-object { + background: #fff; + border: 1px solid #ecf0f1; + width: 260px; + + .progress-bar { + .uploader-progress-bar(); + position: absolute; + bottom: 10px; + left: 0; + } + + .icon-container { + border-right: 1px solid #f6f8f9; + float: left; + display: inline-block; + overflow: hidden; + width: 75px; + height: 75px; + + i { + font-size: 35px; + } + + &.image img { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; + width: auto; + } + } + + .info { + margin-left: 90px; + + h4 { + padding-right: 15px; + a { + right: 15px; + } + } + } + + .meta { + position: absolute; + bottom: 0; + left: 0; + right: 0; + margin: 0 15px 0 90px; + } + + &.upload-placeholder { + height: 75px; + background-color: transparent; + &:after { opacity: 0; } + } + + &:hover { + .uploader-object-active(); + h4 { padding-right: 35px; } + } + + &.is-error { + h4 { padding-right: 35px; } + + .info { + p.size { display: none; } + p.error { padding-bottom: 11px; } + } + } + } + + &.is-preview { + .upload-files-container { + margin-left: 0; + } + } +} + +// +// Media +// + +@media (max-width: 1280px) { + .responsiv-uploader-fileupload.style-image-multi { + .upload-object { + width: 230px; + } + } +} + +@media (max-width: 1024px) { + .responsiv-uploader-fileupload.style-image-multi { + .upload-button { + width: 100%; + } + + .upload-files-container { + margin-left: 0; + } + + .upload-object { + margin-right: 0; + display: block; + width: auto; + } + } +} \ No newline at end of file diff --git a/plugins/blakejones/magicforms/assets/less/uploader.imagesingle.less b/plugins/blakejones/magicforms/assets/less/uploader.imagesingle.less new file mode 100644 index 0000000..5af618d --- /dev/null +++ b/plugins/blakejones/magicforms/assets/less/uploader.imagesingle.less @@ -0,0 +1,91 @@ +// +// Single Image +// + +.responsiv-uploader-fileupload.style-image-single { + &.is-populated { + .upload-button { + display: none; + } + } + + .upload-button { + .uploader-block-button(); + min-height: 100px; + min-width: 100px; + } + + .upload-object { + padding-bottom: 66px; + + .icon-container { + border: 1px solid #f6f8f9; + background: rgba(255,255,255,.5); + + &.image img { + border-radius: 3px; + + // Img responsive + display: block; + max-width: 100%; + height: auto; + + // This is needed when the image is very large and + // being processed by dropzone on the client-side + // the image has no height or width. + min-height: 100px; + min-width: 100px; + } + } + + .progress-bar { + .uploader-progress-bar(); + position: absolute; + bottom: 10px; + left: 0; + } + + .info { + position: absolute; + left: 0; + right: 0; + bottom: 0; + height: 66px; + } + + .meta { + position: absolute; + bottom: 65px; + left: 0; + right: 0; + margin: 0 15px; + } + + &:hover { + h4 { padding-right: 20px; } + } + + &.is-error { + h4 { padding-right: 20px; } + + .info { + p.size { display: none; } + p.error { padding-bottom: 11px; } + } + } + } + +} + + +// +// Media +// + +@media (max-width: 1024px) { + .responsiv-uploader-fileupload.style-image-single { + .upload-object { + h4 { padding-right: 20px !important; } + } + } +} \ No newline at end of file diff --git a/plugins/blakejones/magicforms/assets/less/uploader.less b/plugins/blakejones/magicforms/assets/less/uploader.less new file mode 100644 index 0000000..384bca3 --- /dev/null +++ b/plugins/blakejones/magicforms/assets/less/uploader.less @@ -0,0 +1,19 @@ +@uploader-progress-bar-height: 5px; +@uploader-progress-bar-color: #fff; +@uploader-progress-bar-bg: #f5f5f5; +@uploader-inactive-icon: #808b93; +@uploader-object-active-bg: #4da7e8; +@uploader-object-error-bg: #ab2a1c; +@uploader-list-accent-bg: #f5f5f5; +@uploader-list-border-color: #eeeeee; +@uploader-inline-button-color: #333333; + +@screen-xs-max: 767px; +@screen-sm-max: 991px; +@screen-md-max: 1199px; + +@import "uploader.base.less"; +@import "uploader.imagemulti.less"; +@import "uploader.imagesingle.less"; +@import "uploader.filemulti.less"; +@import "uploader.filesingle.less"; diff --git a/plugins/blakejones/magicforms/assets/vendor/dropzone/dropzone.js b/plugins/blakejones/magicforms/assets/vendor/dropzone/dropzone.js new file mode 100644 index 0000000..cd7855f --- /dev/null +++ b/plugins/blakejones/magicforms/assets/vendor/dropzone/dropzone.js @@ -0,0 +1,1752 @@ + +/* + * + * More info at [www.dropzonejs.com](http://www.dropzonejs.com) + * + * Copyright (c) 2012, Matias Meno + * + * 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() { + var Dropzone, Emitter, camelize, contentLoaded, detectVerticalSquash, drawImageIOSFix, noop, without, + __slice = [].slice, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + noop = function() {}; + + Emitter = (function() { + function Emitter() {} + + Emitter.prototype.addEventListener = Emitter.prototype.on; + + Emitter.prototype.on = function(event, fn) { + this._callbacks = this._callbacks || {}; + if (!this._callbacks[event]) { + this._callbacks[event] = []; + } + this._callbacks[event].push(fn); + return this; + }; + + Emitter.prototype.emit = function() { + var args, callback, callbacks, event, _i, _len; + event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + this._callbacks = this._callbacks || {}; + callbacks = this._callbacks[event]; + if (callbacks) { + for (_i = 0, _len = callbacks.length; _i < _len; _i++) { + callback = callbacks[_i]; + callback.apply(this, args); + } + } + return this; + }; + + Emitter.prototype.removeListener = Emitter.prototype.off; + + Emitter.prototype.removeAllListeners = Emitter.prototype.off; + + Emitter.prototype.removeEventListener = Emitter.prototype.off; + + Emitter.prototype.off = function(event, fn) { + var callback, callbacks, i, _i, _len; + if (!this._callbacks || arguments.length === 0) { + this._callbacks = {}; + return this; + } + callbacks = this._callbacks[event]; + if (!callbacks) { + return this; + } + if (arguments.length === 1) { + delete this._callbacks[event]; + return this; + } + for (i = _i = 0, _len = callbacks.length; _i < _len; i = ++_i) { + callback = callbacks[i]; + if (callback === fn) { + callbacks.splice(i, 1); + break; + } + } + return this; + }; + + return Emitter; + + })(); + + Dropzone = (function(_super) { + var extend, resolveOption; + + __extends(Dropzone, _super); + + Dropzone.prototype.Emitter = Emitter; + + + /* + This is a list of all available events you can register on a dropzone object. + + You can register an event handler like this: + + dropzone.on("dragEnter", function() { }); + */ + + Dropzone.prototype.events = ["drop", "dragstart", "dragend", "dragenter", "dragover", "dragleave", "addedfile", "addedfiles", "removedfile", "thumbnail", "error", "errormultiple", "processing", "processingmultiple", "uploadprogress", "totaluploadprogress", "sending", "sendingmultiple", "success", "successmultiple", "canceled", "canceledmultiple", "complete", "completemultiple", "reset", "maxfilesexceeded", "maxfilesreached", "queuecomplete"]; + + Dropzone.prototype.defaultOptions = { + url: null, + method: "post", + withCredentials: false, + parallelUploads: 2, + uploadMultiple: false, + maxFilesize: 256, + paramName: "file", + createImageThumbnails: true, + maxThumbnailFilesize: 10, + thumbnailWidth: 120, + thumbnailHeight: 120, + filesizeBase: 1000, + maxFiles: null, + params: {}, + clickable: true, + ignoreHiddenFiles: true, + acceptedFiles: null, + acceptedMimeTypes: null, + autoProcessQueue: true, + autoQueue: true, + addRemoveLinks: false, + previewsContainer: null, + hiddenInputContainer: "body", + capture: null, + dictDefaultMessage: "Drop files here to upload", + dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.", + dictFallbackText: "Please use the fallback form below to upload your files like in the olden days.", + dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.", + dictInvalidFileType: "You can't upload files of this type.", + dictResponseError: "Server responded with {{statusCode}} code.", + dictCancelUpload: "Cancel upload", + dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?", + dictRemoveFile: "Remove file", + dictRemoveFileConfirmation: null, + dictMaxFilesExceeded: "You can not upload any more files.", + accept: function(file, done) { + return done(); + }, + init: function() { + return noop; + }, + forceFallback: false, + fallback: function() { + var child, messageElement, span, _i, _len, _ref; + this.element.className = "" + this.element.className + " dz-browser-not-supported"; + _ref = this.element.getElementsByTagName("div"); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + child = _ref[_i]; + if (/(^| )dz-message($| )/.test(child.className)) { + messageElement = child; + child.className = "dz-message"; + continue; + } + } + if (!messageElement) { + messageElement = Dropzone.createElement("
"); + this.element.appendChild(messageElement); + } + 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(file) { + var info, srcRatio, trgRatio; + info = { + srcX: 0, + srcY: 0, + srcWidth: file.width, + srcHeight: file.height + }; + srcRatio = file.width / file.height; + info.optWidth = this.options.thumbnailWidth; + info.optHeight = this.options.thumbnailHeight; + if ((info.optWidth == null) && (info.optHeight == null)) { + info.optWidth = info.srcWidth; + info.optHeight = info.srcHeight; + } else if (info.optWidth == null) { + info.optWidth = srcRatio * info.optHeight; + } else if (info.optHeight == null) { + info.optHeight = (1 / srcRatio) * info.optWidth; + } + trgRatio = info.optWidth / info.optHeight; + if (file.height < info.optHeight || file.width < info.optWidth) { + info.trgHeight = info.srcHeight; + info.trgWidth = info.srcWidth; + } else { + if (srcRatio > trgRatio) { + info.srcHeight = file.height; + info.srcWidth = info.srcHeight * trgRatio; + } else { + info.srcWidth = file.width; + info.srcHeight = info.srcWidth / trgRatio; + } + } + info.srcX = (file.width - info.srcWidth) / 2; + info.srcY = (file.height - info.srcHeight) / 2; + return info; + }, + + /* + Those functions register themselves to the events on init and handle all + the user interface specific stuff. Overwriting them won't break the upload + but can break the way it's displayed. + You can overwrite them if you don't like the default behavior. If you just + want to add an additional event handler, register it on the dropzone object + and don't overwrite those options. + */ + drop: function(e) { + return this.element.classList.remove("dz-drag-hover"); + }, + dragstart: noop, + dragend: function(e) { + return this.element.classList.remove("dz-drag-hover"); + }, + dragenter: function(e) { + return this.element.classList.add("dz-drag-hover"); + }, + dragover: function(e) { + return this.element.classList.add("dz-drag-hover"); + }, + dragleave: function(e) { + return this.element.classList.remove("dz-drag-hover"); + }, + paste: noop, + reset: function() { + return this.element.classList.remove("dz-started"); + }, + addedfile: function(file) { + var node, removeFileEvent, removeLink, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results; + 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); + _ref = file.previewElement.querySelectorAll("[data-dz-name]"); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + node = _ref[_i]; + node.textContent = file.name; + } + _ref1 = file.previewElement.querySelectorAll("[data-dz-size]"); + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + node = _ref1[_j]; + node.innerHTML = this.filesize(file.size); + } + if (this.options.addRemoveLinks) { + file._removeLink = Dropzone.createElement("" + this.options.dictRemoveFile + ""); + file.previewElement.appendChild(file._removeLink); + } + removeFileEvent = (function(_this) { + return function(e) { + e.preventDefault(); + e.stopPropagation(); + if (file.status === Dropzone.UPLOADING) { + return Dropzone.confirm(_this.options.dictCancelUploadConfirmation, function() { + return _this.removeFile(file); + }); + } else { + if (_this.options.dictRemoveFileConfirmation) { + return Dropzone.confirm(_this.options.dictRemoveFileConfirmation, function() { + return _this.removeFile(file); + }); + } else { + return _this.removeFile(file); + } + } + }; + })(this); + _ref2 = file.previewElement.querySelectorAll("[data-dz-remove]"); + _results = []; + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + removeLink = _ref2[_k]; + _results.push(removeLink.addEventListener("click", removeFileEvent)); + } + return _results; + } + }, + removedfile: function(file) { + var _ref; + if (file.previewElement) { + if ((_ref = file.previewElement) != null) { + _ref.parentNode.removeChild(file.previewElement); + } + } + return this._updateMaxFilesReachedClass(); + }, + thumbnail: function(file, dataUrl) { + var thumbnailElement, _i, _len, _ref; + if (file.previewElement) { + file.previewElement.classList.remove("dz-file-preview"); + _ref = file.previewElement.querySelectorAll("[data-dz-thumbnail]"); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + thumbnailElement = _ref[_i]; + thumbnailElement.alt = file.name; + thumbnailElement.src = dataUrl; + } + return setTimeout(((function(_this) { + return function() { + return file.previewElement.classList.add("dz-image-preview"); + }; + })(this)), 1); + } + }, + error: function(file, message) { + var node, _i, _len, _ref, _results; + if (file.previewElement) { + file.previewElement.classList.add("dz-error"); + if (typeof message !== "String" && message.error) { + message = message.error; + } + _ref = file.previewElement.querySelectorAll("[data-dz-errormessage]"); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + node = _ref[_i]; + _results.push(node.textContent = message); + } + return _results; + } + }, + errormultiple: noop, + processing: function(file) { + if (file.previewElement) { + file.previewElement.classList.add("dz-processing"); + if (file._removeLink) { + return file._removeLink.textContent = this.options.dictCancelUpload; + } + } + }, + processingmultiple: noop, + uploadprogress: function(file, progress, bytesSent) { + var node, _i, _len, _ref, _results; + if (file.previewElement) { + _ref = file.previewElement.querySelectorAll("[data-dz-uploadprogress]"); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + node = _ref[_i]; + if (node.nodeName === 'PROGRESS') { + _results.push(node.value = progress); + } else { + _results.push(node.style.width = "" + progress + "%"); + } + } + return _results; + } + }, + totaluploadprogress: noop, + sending: noop, + sendingmultiple: noop, + success: function(file) { + if (file.previewElement) { + return file.previewElement.classList.add("dz-success"); + } + }, + successmultiple: noop, + canceled: function(file) { + return this.emit("error", file, "Upload canceled."); + }, + canceledmultiple: noop, + complete: function(file) { + if (file._removeLink) { + file._removeLink.textContent = this.options.dictRemoveFile; + } + if (file.previewElement) { + return file.previewElement.classList.add("dz-complete"); + } + }, + completemultiple: noop, + maxfilesexceeded: noop, + maxfilesreached: noop, + queuecomplete: noop, + addedfiles: noop, + 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
" + }; + + extend = function() { + var key, object, objects, target, val, _i, _len; + target = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + for (_i = 0, _len = objects.length; _i < _len; _i++) { + object = objects[_i]; + for (key in object) { + val = object[key]; + target[key] = val; + } + } + return target; + }; + + function Dropzone(element, options) { + var elementOptions, fallback, _ref; + this.element = element; + 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; + elementOptions = (_ref = Dropzone.optionsForElement(this.element)) != null ? _ref : {}; + this.options = extend({}, this.defaultOptions, elementOptions, options != null ? options : {}); + if (this.options.forceFallback || !Dropzone.isBrowserSupported()) { + return this.options.fallback.call(this); + } + 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.acceptedMimeTypes) { + this.options.acceptedFiles = this.options.acceptedMimeTypes; + delete this.options.acceptedMimeTypes; + } + 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(); + } + + Dropzone.prototype.getAcceptedFiles = function() { + var file, _i, _len, _ref, _results; + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (file.accepted) { + _results.push(file); + } + } + return _results; + }; + + Dropzone.prototype.getRejectedFiles = function() { + var file, _i, _len, _ref, _results; + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (!file.accepted) { + _results.push(file); + } + } + return _results; + }; + + Dropzone.prototype.getFilesWithStatus = function(status) { + var file, _i, _len, _ref, _results; + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (file.status === status) { + _results.push(file); + } + } + return _results; + }; + + Dropzone.prototype.getQueuedFiles = function() { + return this.getFilesWithStatus(Dropzone.QUEUED); + }; + + Dropzone.prototype.getUploadingFiles = function() { + return this.getFilesWithStatus(Dropzone.UPLOADING); + }; + + Dropzone.prototype.getAddedFiles = function() { + return this.getFilesWithStatus(Dropzone.ADDED); + }; + + Dropzone.prototype.getActiveFiles = function() { + var file, _i, _len, _ref, _results; + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED) { + _results.push(file); + } + } + return _results; + }; + + Dropzone.prototype.init = function() { + var eventName, noPropagation, setupHiddenFileInput, _i, _len, _ref, _ref1; + 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) { + setupHiddenFileInput = (function(_this) { + return function() { + if (_this.hiddenFileInput) { + _this.hiddenFileInput.parentNode.removeChild(_this.hiddenFileInput); + } + _this.hiddenFileInput = document.createElement("input"); + _this.hiddenFileInput.setAttribute("type", "file"); + if ((_this.options.maxFiles == null) || _this.options.maxFiles > 1) { + _this.hiddenFileInput.setAttribute("multiple", "multiple"); + } + _this.hiddenFileInput.className = "dz-hidden-input"; + if (_this.options.acceptedFiles != null) { + _this.hiddenFileInput.setAttribute("accept", _this.options.acceptedFiles); + } + if (_this.options.capture != null) { + _this.hiddenFileInput.setAttribute("capture", _this.options.capture); + } + _this.hiddenFileInput.style.visibility = "hidden"; + _this.hiddenFileInput.style.position = "absolute"; + _this.hiddenFileInput.style.top = "0"; + _this.hiddenFileInput.style.left = "0"; + _this.hiddenFileInput.style.height = "0"; + _this.hiddenFileInput.style.width = "0"; + document.querySelector(_this.options.hiddenInputContainer).appendChild(_this.hiddenFileInput); + return _this.hiddenFileInput.addEventListener("change", function() { + var file, files, _i, _len; + files = _this.hiddenFileInput.files; + if (files.length) { + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + _this.addFile(file); + } + } + _this.emit("addedfiles", files); + return setupHiddenFileInput(); + }); + }; + })(this); + setupHiddenFileInput(); + } + this.URL = (_ref = window.URL) != null ? _ref : window.webkitURL; + _ref1 = this.events; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + eventName = _ref1[_i]; + this.on(eventName, this.options[eventName]); + } + this.on("uploadprogress", (function(_this) { + return function() { + return _this.updateTotalUploadProgress(); + }; + })(this)); + this.on("removedfile", (function(_this) { + return function() { + return _this.updateTotalUploadProgress(); + }; + })(this)); + this.on("canceled", (function(_this) { + return function(file) { + return _this.emit("complete", file); + }; + })(this)); + this.on("complete", (function(_this) { + return function(file) { + if (_this.getAddedFiles().length === 0 && _this.getUploadingFiles().length === 0 && _this.getQueuedFiles().length === 0) { + return setTimeout((function() { + return _this.emit("queuecomplete"); + }), 0); + } + }; + })(this)); + noPropagation = function(e) { + e.stopPropagation(); + if (e.preventDefault) { + return e.preventDefault(); + } else { + return e.returnValue = false; + } + }; + this.listeners = [ + { + element: this.element, + events: { + "dragstart": (function(_this) { + return function(e) { + return _this.emit("dragstart", e); + }; + })(this), + "dragenter": (function(_this) { + return function(e) { + noPropagation(e); + return _this.emit("dragenter", e); + }; + })(this), + "dragover": (function(_this) { + return function(e) { + var efct; + try { + efct = e.dataTransfer.effectAllowed; + } catch (_error) {} + e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy'; + noPropagation(e); + return _this.emit("dragover", e); + }; + })(this), + "dragleave": (function(_this) { + return function(e) { + return _this.emit("dragleave", e); + }; + })(this), + "drop": (function(_this) { + return function(e) { + noPropagation(e); + return _this.drop(e); + }; + })(this), + "dragend": (function(_this) { + return function(e) { + return _this.emit("dragend", e); + }; + })(this) + } + } + ]; + this.clickableElements.forEach((function(_this) { + return function(clickableElement) { + return _this.listeners.push({ + element: clickableElement, + events: { + "click": function(evt) { + if ((clickableElement !== _this.element) || (evt.target === _this.element || Dropzone.elementInside(evt.target, _this.element.querySelector(".dz-message")))) { + _this.hiddenFileInput.click(); + } + return true; + } + } + }); + }; + })(this)); + this.enable(); + return this.options.init.call(this); + }; + + Dropzone.prototype.destroy = function() { + var _ref; + this.disable(); + this.removeAllFiles(true); + if ((_ref = this.hiddenFileInput) != null ? _ref.parentNode : void 0) { + this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput); + this.hiddenFileInput = null; + } + delete this.element.dropzone; + return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1); + }; + + Dropzone.prototype.updateTotalUploadProgress = function() { + var activeFiles, file, totalBytes, totalBytesSent, totalUploadProgress, _i, _len, _ref; + totalBytesSent = 0; + totalBytes = 0; + activeFiles = this.getActiveFiles(); + if (activeFiles.length) { + _ref = this.getActiveFiles(); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + totalBytesSent += file.upload.bytesSent; + totalBytes += file.upload.total; + } + totalUploadProgress = 100 * totalBytesSent / totalBytes; + } else { + totalUploadProgress = 100; + } + return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent); + }; + + Dropzone.prototype._getParamName = function(n) { + if (typeof this.options.paramName === "function") { + return this.options.paramName(n); + } else { + return "" + this.options.paramName + (this.options.uploadMultiple ? "[" + n + "]" : ""); + } + }; + + Dropzone.prototype.getFallbackForm = function() { + var existingFallback, fields, fieldsString, form; + if (existingFallback = this.getExistingFallback()) { + return existingFallback; + } + fieldsString = "
"; + if (this.options.dictFallbackText) { + fieldsString += "

" + this.options.dictFallbackText + "

"; + } + fieldsString += "
"; + 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; + }; + + Dropzone.prototype.getExistingFallback = function() { + var fallback, getFallback, tagName, _i, _len, _ref; + getFallback = function(elements) { + var el, _i, _len; + for (_i = 0, _len = elements.length; _i < _len; _i++) { + el = elements[_i]; + if (/(^| )fallback($| )/.test(el.className)) { + return el; + } + } + }; + _ref = ["div", "form"]; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + tagName = _ref[_i]; + if (fallback = getFallback(this.element.getElementsByTagName(tagName))) { + return fallback; + } + } + }; + + Dropzone.prototype.setupEventListeners = function() { + var elementListeners, event, listener, _i, _len, _ref, _results; + _ref = this.listeners; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + elementListeners = _ref[_i]; + _results.push((function() { + var _ref1, _results1; + _ref1 = elementListeners.events; + _results1 = []; + for (event in _ref1) { + listener = _ref1[event]; + _results1.push(elementListeners.element.addEventListener(event, listener, false)); + } + return _results1; + })()); + } + return _results; + }; + + Dropzone.prototype.removeEventListeners = function() { + var elementListeners, event, listener, _i, _len, _ref, _results; + _ref = this.listeners; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + elementListeners = _ref[_i]; + _results.push((function() { + var _ref1, _results1; + _ref1 = elementListeners.events; + _results1 = []; + for (event in _ref1) { + listener = _ref1[event]; + _results1.push(elementListeners.element.removeEventListener(event, listener, false)); + } + return _results1; + })()); + } + return _results; + }; + + Dropzone.prototype.disable = function() { + var file, _i, _len, _ref, _results; + this.clickableElements.forEach(function(element) { + return element.classList.remove("dz-clickable"); + }); + this.removeEventListeners(); + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + _results.push(this.cancelUpload(file)); + } + return _results; + }; + + Dropzone.prototype.enable = function() { + this.clickableElements.forEach(function(element) { + return element.classList.add("dz-clickable"); + }); + return this.setupEventListeners(); + }; + + Dropzone.prototype.filesize = function(size) { + var cutoff, i, selectedSize, selectedUnit, unit, units, _i, _len; + selectedSize = 0; + selectedUnit = "b"; + if (size > 0) { + units = ['TB', 'GB', 'MB', 'KB', 'b']; + for (i = _i = 0, _len = units.length; _i < _len; i = ++_i) { + unit = units[i]; + cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10; + if (size >= cutoff) { + selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i); + selectedUnit = unit; + break; + } + } + selectedSize = Math.round(10 * selectedSize) / 10; + } + return "" + selectedSize + " " + selectedUnit; + }; + + Dropzone.prototype._updateMaxFilesReachedClass = function() { + 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"); + } + }; + + Dropzone.prototype.drop = function(e) { + var files, items; + if (!e.dataTransfer) { + return; + } + this.emit("drop", e); + files = e.dataTransfer.files; + this.emit("addedfiles", files); + if (files.length) { + items = e.dataTransfer.items; + if (items && items.length && (items[0].webkitGetAsEntry != null)) { + this._addFilesFromItems(items); + } else { + this.handleFiles(files); + } + } + }; + + Dropzone.prototype.paste = function(e) { + var items, _ref; + if ((e != null ? (_ref = e.clipboardData) != null ? _ref.items : void 0 : void 0) == null) { + return; + } + this.emit("paste", e); + items = e.clipboardData.items; + if (items.length) { + return this._addFilesFromItems(items); + } + }; + + Dropzone.prototype.handleFiles = function(files) { + var file, _i, _len, _results; + _results = []; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + _results.push(this.addFile(file)); + } + return _results; + }; + + Dropzone.prototype._addFilesFromItems = function(items) { + var entry, item, _i, _len, _results; + _results = []; + for (_i = 0, _len = items.length; _i < _len; _i++) { + item = items[_i]; + if ((item.webkitGetAsEntry != null) && (entry = item.webkitGetAsEntry())) { + if (entry.isFile) { + _results.push(this.addFile(item.getAsFile())); + } else if (entry.isDirectory) { + _results.push(this._addFilesFromDirectory(entry, entry.name)); + } else { + _results.push(void 0); + } + } else if (item.getAsFile != null) { + if ((item.kind == null) || item.kind === "file") { + _results.push(this.addFile(item.getAsFile())); + } else { + _results.push(void 0); + } + } else { + _results.push(void 0); + } + } + return _results; + }; + + Dropzone.prototype._addFilesFromDirectory = function(directory, path) { + var dirReader, entriesReader; + dirReader = directory.createReader(); + entriesReader = (function(_this) { + return function(entries) { + var entry, _i, _len; + for (_i = 0, _len = entries.length; _i < _len; _i++) { + entry = entries[_i]; + if (entry.isFile) { + entry.file(function(file) { + if (_this.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') { + return; + } + file.fullPath = "" + path + "/" + file.name; + return _this.addFile(file); + }); + } else if (entry.isDirectory) { + _this._addFilesFromDirectory(entry, "" + path + "/" + entry.name); + } + } + }; + })(this); + return dirReader.readEntries(entriesReader, function(error) { + return typeof console !== "undefined" && console !== null ? typeof console.log === "function" ? console.log(error) : void 0 : void 0; + }); + }; + + Dropzone.prototype.accept = function(file, done) { + if (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); + } + }; + + Dropzone.prototype.addFile = function(file) { + file.upload = { + progress: 0, + total: file.size, + bytesSent: 0 + }; + this.files.push(file); + file.status = Dropzone.ADDED; + this.emit("addedfile", file); + this._enqueueThumbnail(file); + return this.accept(file, (function(_this) { + return function(error) { + if (error) { + file.accepted = false; + _this._errorProcessing([file], error); + } else { + file.accepted = true; + if (_this.options.autoQueue) { + _this.enqueueFile(file); + } + } + return _this._updateMaxFilesReachedClass(); + }; + })(this)); + }; + + Dropzone.prototype.enqueueFiles = function(files) { + var file, _i, _len; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + this.enqueueFile(file); + } + return null; + }; + + Dropzone.prototype.enqueueFile = function(file) { + if (file.status === Dropzone.ADDED && file.accepted === true) { + file.status = Dropzone.QUEUED; + if (this.options.autoProcessQueue) { + return setTimeout(((function(_this) { + return function() { + return _this.processQueue(); + }; + })(this)), 0); + } + } else { + throw new Error("This file can't be queued because it has already been processed or was rejected."); + } + }; + + Dropzone.prototype._thumbnailQueue = []; + + Dropzone.prototype._processingThumbnail = false; + + Dropzone.prototype._enqueueThumbnail = function(file) { + if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) { + this._thumbnailQueue.push(file); + return setTimeout(((function(_this) { + return function() { + return _this._processThumbnailQueue(); + }; + })(this)), 0); + } + }; + + Dropzone.prototype._processThumbnailQueue = function() { + if (this._processingThumbnail || this._thumbnailQueue.length === 0) { + return; + } + this._processingThumbnail = true; + return this.createThumbnail(this._thumbnailQueue.shift(), (function(_this) { + return function() { + _this._processingThumbnail = false; + return _this._processThumbnailQueue(); + }; + })(this)); + }; + + Dropzone.prototype.removeFile = function(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"); + } + }; + + Dropzone.prototype.removeAllFiles = function(cancelIfNecessary) { + var file, _i, _len, _ref; + if (cancelIfNecessary == null) { + cancelIfNecessary = false; + } + _ref = this.files.slice(); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) { + this.removeFile(file); + } + } + return null; + }; + + Dropzone.prototype.createThumbnail = function(file, callback) { + var fileReader; + fileReader = new FileReader; + fileReader.onload = (function(_this) { + return function() { + if (file.type === "image/svg+xml") { + _this.emit("thumbnail", file, fileReader.result); + if (callback != null) { + callback(); + } + return; + } + return _this.createThumbnailFromUrl(file, fileReader.result, callback); + }; + })(this); + return fileReader.readAsDataURL(file); + }; + + Dropzone.prototype.createThumbnailFromUrl = function(file, imageUrl, callback, crossOrigin) { + var img; + img = document.createElement("img"); + if (crossOrigin) { + img.crossOrigin = crossOrigin; + } + img.onload = (function(_this) { + return function() { + var canvas, ctx, resizeInfo, thumbnail, _ref, _ref1, _ref2, _ref3; + file.width = img.width; + file.height = img.height; + resizeInfo = _this.options.resize.call(_this, file); + if (resizeInfo.trgWidth == null) { + resizeInfo.trgWidth = resizeInfo.optWidth; + } + if (resizeInfo.trgHeight == null) { + resizeInfo.trgHeight = resizeInfo.optHeight; + } + canvas = document.createElement("canvas"); + ctx = canvas.getContext("2d"); + canvas.width = resizeInfo.trgWidth; + canvas.height = resizeInfo.trgHeight; + drawImageIOSFix(ctx, img, (_ref = resizeInfo.srcX) != null ? _ref : 0, (_ref1 = resizeInfo.srcY) != null ? _ref1 : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, (_ref2 = resizeInfo.trgX) != null ? _ref2 : 0, (_ref3 = resizeInfo.trgY) != null ? _ref3 : 0, resizeInfo.trgWidth, resizeInfo.trgHeight); + thumbnail = canvas.toDataURL("image/png"); + _this.emit("thumbnail", file, thumbnail); + if (callback != null) { + return callback(); + } + }; + })(this); + if (callback != null) { + img.onerror = callback; + } + return img.src = imageUrl; + }; + + Dropzone.prototype.processQueue = function() { + var i, parallelUploads, processingLength, queuedFiles; + parallelUploads = this.options.parallelUploads; + processingLength = this.getUploadingFiles().length; + i = processingLength; + if (processingLength >= parallelUploads) { + return; + } + queuedFiles = this.getQueuedFiles(); + if (!(queuedFiles.length > 0)) { + return; + } + if (this.options.uploadMultiple) { + return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength)); + } else { + while (i < parallelUploads) { + if (!queuedFiles.length) { + return; + } + this.processFile(queuedFiles.shift()); + i++; + } + } + }; + + Dropzone.prototype.processFile = function(file) { + return this.processFiles([file]); + }; + + Dropzone.prototype.processFiles = function(files) { + var file, _i, _len; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + file.processing = true; + file.status = Dropzone.UPLOADING; + this.emit("processing", file); + } + if (this.options.uploadMultiple) { + this.emit("processingmultiple", files); + } + return this.uploadFiles(files); + }; + + Dropzone.prototype._getFilesWithXhr = function(xhr) { + var file, files; + return files = (function() { + var _i, _len, _ref, _results; + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (file.xhr === xhr) { + _results.push(file); + } + } + return _results; + }).call(this); + }; + + Dropzone.prototype.cancelUpload = function(file) { + var groupedFile, groupedFiles, _i, _j, _len, _len1, _ref; + if (file.status === Dropzone.UPLOADING) { + groupedFiles = this._getFilesWithXhr(file.xhr); + for (_i = 0, _len = groupedFiles.length; _i < _len; _i++) { + groupedFile = groupedFiles[_i]; + groupedFile.status = Dropzone.CANCELED; + } + file.xhr.abort(); + for (_j = 0, _len1 = groupedFiles.length; _j < _len1; _j++) { + groupedFile = groupedFiles[_j]; + this.emit("canceled", groupedFile); + } + if (this.options.uploadMultiple) { + this.emit("canceledmultiple", groupedFiles); + } + } else if ((_ref = file.status) === Dropzone.ADDED || _ref === 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(); + } + }; + + resolveOption = function() { + var args, option; + option = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + if (typeof option === 'function') { + return option.apply(this, args); + } + return option; + }; + + Dropzone.prototype.uploadFile = function(file) { + return this.uploadFiles([file]); + }; + + Dropzone.prototype.uploadFiles = function(files) { + var file, formData, handleError, headerName, headerValue, headers, i, input, inputName, inputType, key, method, option, progressObj, response, updateProgress, url, value, xhr, _i, _j, _k, _l, _len, _len1, _len2, _len3, _m, _ref, _ref1, _ref2, _ref3, _ref4, _ref5; + xhr = new XMLHttpRequest(); + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + file.xhr = xhr; + } + method = resolveOption(this.options.method, files); + url = resolveOption(this.options.url, files); + xhr.open(method, url, true); + xhr.withCredentials = !!this.options.withCredentials; + response = null; + handleError = (function(_this) { + return function() { + var _j, _len1, _results; + _results = []; + for (_j = 0, _len1 = files.length; _j < _len1; _j++) { + file = files[_j]; + _results.push(_this._errorProcessing(files, response || _this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr)); + } + return _results; + }; + })(this); + updateProgress = (function(_this) { + return function(e) { + var allFilesFinished, progress, _j, _k, _l, _len1, _len2, _len3, _results; + if (e != null) { + progress = 100 * e.loaded / e.total; + for (_j = 0, _len1 = files.length; _j < _len1; _j++) { + file = files[_j]; + file.upload = { + progress: progress, + total: e.total, + bytesSent: e.loaded + }; + } + } else { + allFilesFinished = true; + progress = 100; + for (_k = 0, _len2 = files.length; _k < _len2; _k++) { + file = files[_k]; + if (!(file.upload.progress === 100 && file.upload.bytesSent === file.upload.total)) { + allFilesFinished = false; + } + file.upload.progress = progress; + file.upload.bytesSent = file.upload.total; + } + if (allFilesFinished) { + return; + } + } + _results = []; + for (_l = 0, _len3 = files.length; _l < _len3; _l++) { + file = files[_l]; + _results.push(_this.emit("uploadprogress", file, progress, file.upload.bytesSent)); + } + return _results; + }; + })(this); + xhr.onload = (function(_this) { + return function(e) { + var _ref; + if (files[0].status === Dropzone.CANCELED) { + return; + } + if (xhr.readyState !== 4) { + return; + } + 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."; + } + } + updateProgress(); + if (!((200 <= (_ref = xhr.status) && _ref < 300))) { + return handleError(); + } else { + return _this._finished(files, response, e); + } + }; + })(this); + xhr.onerror = (function(_this) { + return function() { + if (files[0].status === Dropzone.CANCELED) { + return; + } + return handleError(); + }; + })(this); + progressObj = (_ref = xhr.upload) != null ? _ref : xhr; + progressObj.onprogress = updateProgress; + headers = { + "Accept": "application/json", + "Cache-Control": "no-cache", + "X-Requested-With": "XMLHttpRequest" + }; + if (this.options.headers) { + extend(headers, this.options.headers); + } + for (headerName in headers) { + headerValue = headers[headerName]; + if (headerValue) { + xhr.setRequestHeader(headerName, headerValue); + } + } + formData = new FormData(); + if (this.options.params) { + _ref1 = this.options.params; + for (key in _ref1) { + value = _ref1[key]; + formData.append(key, value); + } + } + for (_j = 0, _len1 = files.length; _j < _len1; _j++) { + file = files[_j]; + this.emit("sending", file, xhr, formData); + } + if (this.options.uploadMultiple) { + this.emit("sendingmultiple", files, xhr, formData); + } + if (this.element.tagName === "FORM") { + _ref2 = this.element.querySelectorAll("input, textarea, select, button"); + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + input = _ref2[_k]; + inputName = input.getAttribute("name"); + inputType = input.getAttribute("type"); + if (input.tagName === "SELECT" && input.hasAttribute("multiple")) { + _ref3 = input.options; + for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { + option = _ref3[_l]; + if (option.selected) { + formData.append(inputName, option.value); + } + } + } else if (!inputType || ((_ref4 = inputType.toLowerCase()) !== "checkbox" && _ref4 !== "radio") || input.checked) { + formData.append(inputName, input.value); + } + } + } + for (i = _m = 0, _ref5 = files.length - 1; 0 <= _ref5 ? _m <= _ref5 : _m >= _ref5; i = 0 <= _ref5 ? ++_m : --_m) { + formData.append(this._getParamName(i), files[i], files[i].name); + } + return this.submitRequest(xhr, formData, files); + }; + + Dropzone.prototype.submitRequest = function(xhr, formData, files) { + return xhr.send(formData); + }; + + Dropzone.prototype._finished = function(files, responseText, e) { + var file, _i, _len; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + 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(); + } + }; + + Dropzone.prototype._errorProcessing = function(files, message, xhr) { + var file, _i, _len; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + 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(); + } + }; + + return Dropzone; + + })(Emitter); + + Dropzone.version = "4.2.0"; + + Dropzone.options = {}; + + Dropzone.optionsForElement = function(element) { + if (element.getAttribute("id")) { + return Dropzone.options[camelize(element.getAttribute("id"))]; + } else { + return void 0; + } + }; + + Dropzone.instances = []; + + Dropzone.forElement = function(element) { + if (typeof element === "string") { + element = document.querySelector(element); + } + if ((element != null ? element.dropzone : void 0) == 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 checkElements, dropzone, dropzones, _i, _len, _results; + if (document.querySelectorAll) { + dropzones = document.querySelectorAll(".dropzone"); + } else { + dropzones = []; + checkElements = function(elements) { + var el, _i, _len, _results; + _results = []; + for (_i = 0, _len = elements.length; _i < _len; _i++) { + el = elements[_i]; + if (/(^| )dropzone($| )/.test(el.className)) { + _results.push(dropzones.push(el)); + } else { + _results.push(void 0); + } + } + return _results; + }; + checkElements(document.getElementsByTagName("div")); + checkElements(document.getElementsByTagName("form")); + } + _results = []; + for (_i = 0, _len = dropzones.length; _i < _len; _i++) { + dropzone = dropzones[_i]; + if (Dropzone.optionsForElement(dropzone) !== false) { + _results.push(new Dropzone(dropzone)); + } else { + _results.push(void 0); + } + } + return _results; + }; + + Dropzone.blacklistedBrowsers = [/opera.*Macintosh.*version\/12/i]; + + Dropzone.isBrowserSupported = function() { + var capableBrowser, regex, _i, _len, _ref; + capableBrowser = true; + if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) { + if (!("classList" in document.createElement("a"))) { + capableBrowser = false; + } else { + _ref = Dropzone.blacklistedBrowsers; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + regex = _ref[_i]; + if (regex.test(navigator.userAgent)) { + capableBrowser = false; + continue; + } + } + } + } else { + capableBrowser = false; + } + return capableBrowser; + }; + + without = function(list, rejectedItem) { + var item, _i, _len, _results; + _results = []; + for (_i = 0, _len = list.length; _i < _len; _i++) { + item = list[_i]; + if (item !== rejectedItem) { + _results.push(item); + } + } + return _results; + }; + + camelize = function(str) { + return str.replace(/[\-_](\w)/g, function(match) { + return match.charAt(1).toUpperCase(); + }); + }; + + Dropzone.createElement = function(string) { + var div; + 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; + 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 e, el, elements, _i, _j, _len, _len1, _ref; + if (els instanceof Array) { + elements = []; + try { + for (_i = 0, _len = els.length; _i < _len; _i++) { + el = els[_i]; + elements.push(this.getElement(el, name)); + } + } catch (_error) { + e = _error; + elements = null; + } + } else if (typeof els === "string") { + elements = []; + _ref = document.querySelectorAll(els); + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + el = _ref[_j]; + 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) { + var baseMimeType, mimeType, validType, _i, _len; + if (!acceptedFiles) { + return true; + } + acceptedFiles = acceptedFiles.split(","); + mimeType = file.type; + baseMimeType = mimeType.replace(/\/.*$/, ""); + for (_i = 0, _len = acceptedFiles.length; _i < _len; _i++) { + validType = acceptedFiles[_i]; + 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"; + + + /* + + Bugfix for iOS 6 and 7 + Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios + based on the work of https://github.com/stomita/ios-imagefile-megapixel + */ + + detectVerticalSquash = function(img) { + var alpha, canvas, ctx, data, ey, ih, iw, py, ratio, sy; + iw = img.naturalWidth; + ih = img.naturalHeight; + canvas = document.createElement("canvas"); + canvas.width = 1; + canvas.height = ih; + ctx = canvas.getContext("2d"); + ctx.drawImage(img, 0, 0); + data = ctx.getImageData(0, 0, 1, ih).data; + sy = 0; + ey = ih; + py = ih; + while (py > sy) { + alpha = data[(py - 1) * 4 + 3]; + if (alpha === 0) { + ey = py; + } else { + sy = py; + } + py = (ey + sy) >> 1; + } + ratio = py / ih; + if (ratio === 0) { + return 1; + } else { + return ratio; + } + }; + + drawImageIOSFix = function(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) { + var vertSquashRatio; + vertSquashRatio = detectVerticalSquash(img); + return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio); + }; + + + /* + * contentloaded.js + * + * Author: Diego Perini (diego.perini at gmail.com) + * Summary: cross-browser wrapper for DOMContentLoaded + * Updated: 20101020 + * License: MIT + * Version: 1.2 + * + * URL: + * http://javascript.nwbox.com/ContentLoaded/ + * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE + */ + + contentLoaded = function(win, fn) { + var add, doc, done, init, poll, pre, rem, root, top; + done = false; + top = true; + doc = win.document; + root = doc.documentElement; + add = (doc.addEventListener ? "addEventListener" : "attachEvent"); + rem = (doc.addEventListener ? "removeEventListener" : "detachEvent"); + pre = (doc.addEventListener ? "" : "on"); + init = function(e) { + if (e.type === "readystatechange" && doc.readyState !== "complete") { + return; + } + (e.type === "load" ? win : doc)[rem](pre + e.type, init, false); + if (!done && (done = true)) { + return fn.call(win, e.type || e); + } + }; + poll = function() { + var e; + try { + root.doScroll("left"); + } catch (_error) { + e = _error; + setTimeout(poll, 50); + return; + } + return init("poll"); + }; + if (doc.readyState !== "complete") { + if (doc.createEventObject && root.doScroll) { + try { + top = !win.frameElement; + } catch (_error) {} + if (top) { + poll(); + } + } + doc[add](pre + "DOMContentLoaded", init, false); + doc[add](pre + "readystatechange", init, false); + return win[add](pre + "load", init, false); + } + }; + + Dropzone._autoDiscoverFunction = function() { + if (Dropzone.autoDiscover) { + return Dropzone.discover(); + } + }; + + contentLoaded(window, Dropzone._autoDiscoverFunction); + +}).call(this); diff --git a/plugins/blakejones/magicforms/classes/BackendHelpers.php b/plugins/blakejones/magicforms/classes/BackendHelpers.php new file mode 100644 index 0000000..7182f64 --- /dev/null +++ b/plugins/blakejones/magicforms/classes/BackendHelpers.php @@ -0,0 +1,87 @@ + $URL) { + if ($user->hasAccess($permission)) { + return Backend::url($URL); + } + } + return Backend::url($urls[$default]); + } + + /** + * Check if Translator plugin is installed + * + * @return boolean + */ + public static function isTranslatePlugin() :bool { + return class_exists('\RainLab\Translate\Classes\Translator') && class_exists('\RainLab\Translate\Models\Message') && class_exists('\RainLab\Translate\Models\Locale'); + } + + /** + * Render an array|object as HTML list (UL > LI) + * + * @param mixed $data List items + * + * @return string + */ + public static function array2ul($data) :string { + $return = ''; + foreach ($data as $index => $item) { + if (!is_string($item)) { + $return .= '
  • ' . htmlspecialchars($index, ENT_QUOTES) . '
      ' . self::array2ul($item) . "
  • "; + } else { + $return .= '
  • '; + if (is_object($data)) { + $return .= htmlspecialchars($index, ENT_QUOTES) . ' - '; + } + $return .= htmlspecialchars($item, ENT_QUOTES) .'
  • '; + } + } + return $return; + } + + /** + * Anonymize an IPv4 address + * (credits: https://github.com/geertw/php-ip-anonymizer) + * + * @param string $address IPv4 address + * + * @return string Anonymized address + */ + public static function anonymizeIPv4(string $address) :string { + return inet_ntop(inet_pton($address) & inet_pton("255.255.255.0")); + } + + /** + * Extract string from curly braces + * + * @param string $pattern Pattern to replace + * @param string $replacement Replacement string + * @param string $subject Strings to replace + * + * @return string + */ + public static function replaceToken(string $pattern, string $replacement = null, string $subject) :string { + $pattern = '/{{\s*('.$pattern.')\s*}}/'; + return preg_replace($pattern, $replacement, $subject); + } + +} + +?> diff --git a/plugins/blakejones/magicforms/classes/GDPR.php b/plugins/blakejones/magicforms/classes/GDPR.php new file mode 100644 index 0000000..2bb8d6e --- /dev/null +++ b/plugins/blakejones/magicforms/classes/GDPR.php @@ -0,0 +1,37 @@ +subDays($gdpr_days); + $rows = Record::whereDate('created_at', '<', $days)->forceDelete(); + return $rows; + } + + Flash::error(e(trans('blakejones.magicforms::lang.classes.GDPR.alert_invalid_gdpr'))); + + } + +} + +?> \ No newline at end of file diff --git a/plugins/blakejones/magicforms/classes/MagicForm.php b/plugins/blakejones/magicforms/classes/MagicForm.php new file mode 100644 index 0000000..74c29ec --- /dev/null +++ b/plugins/blakejones/magicforms/classes/MagicForm.php @@ -0,0 +1,308 @@ +page['recaptcha_enabled'] = $this->isReCaptchaEnabled(); + $this->page['recaptcha_misconfigured'] = $this->isReCaptchaMisconfigured(); + + if ($this->isReCaptchaEnabled()) { + $this->loadReCaptcha(); + } + + if ($this->isReCaptchaMisconfigured()) { + $this->page['recaptcha_warn'] = Lang::get('blakejones.magicforms::lang.components.shared.recaptcha_warn'); + } + + if ($this->property('inline_errors') == 'display') { + $this->addJs('assets/js/inline-errors.js'); + } + + } + + public function settings() { + return [ + 'recaptcha_site_key' => Settings::get('recaptcha_site_key'), + 'recaptcha_secret_key' => Settings::get('recaptcha_secret_key'), + ]; + } + + public function onFormSubmit() { + + // FLASH PARTIAL + $flash_partial = $this->property('messages_partial', '@flash.htm'); + + // CSRF CHECK + if (Config::get('cms.enableCsrfProtection') && (Session::token() != post('_token'))) { + throw new AjaxException(['#' . $this->alias . '_forms_flash' => $this->renderPartial($flash_partial, [ + 'status' => 'error', + 'type' => 'danger', + 'content' => Lang::get('blakejones.magicforms::lang.components.shared.csrf_error'), + ])]); + } + + // LOAD TRANSLATOR PLUGIN + if (BackendHelpers::isTranslatePlugin()) { + $translator = \RainLab\Translate\Classes\Translator::instance(); + $translator->loadLocaleFromSession(); + $locale = $translator->getLocale(); + \RainLab\Translate\Models\Message::setContext($locale); + } + + // FILTER ALLOWED FIELDS + $allow = $this->property('allowed_fields'); + if (is_array($allow) && !empty($allow)) { + foreach ($allow as $field) { + $post[$field] = post($field); + } + if ($this->isReCaptchaEnabled()) { + $post['g-recaptcha-response'] = post('g-recaptcha-response'); + } + } else { + $post = post(); + } + + // SANITIZE FORM DATA + if ($this->property('sanitize_data') == 'htmlspecialchars') { + $post = $this->array_map_recursive(function ($value) { + return htmlspecialchars($value, ENT_QUOTES); + }, $post); + } + + // VALIDATION PARAMETERS + $rules = (array)$this->property('rules'); + $msgs = (array)$this->property('rules_messages'); + $custom_attributes = (array)$this->property('custom_attributes'); + + // TRANSLATE CUSTOM ERROR MESSAGES + if (BackendHelpers::isTranslatePlugin()) { + foreach ($msgs as $rule => $msg) { + $msgs[$rule] = \RainLab\Translate\Models\Message::trans($msg); + } + } + + // ADD reCAPTCHA VALIDATION + if ($this->isReCaptchaEnabled() && $this->property('recaptcha_size') != 'invisible') { + $rules['g-recaptcha-response'] = 'required'; + } + + // DO FORM VALIDATION + $validator = Validator::make($post, $rules, $msgs, $custom_attributes); + + // NICE reCAPTCHA FIELD NAME + if ($this->isReCaptchaEnabled()) { + $fields_names = ['g-recaptcha-response' => 'reCAPTCHA']; + $validator->setAttributeNames(array_merge($fields_names, $custom_attributes)); + } + + // VALIDATE ALL + CAPTCHA EXISTS + if ($validator->fails()) { + + // GET DEFAULT ERROR MESSAGE + $message = $this->property('messages_errors'); + + // LOOK FOR TRANSLATION + if (BackendHelpers::isTranslatePlugin()) { + $message = \RainLab\Translate\Models\Message::trans($message); + } + + // THROW ERRORS + if ($this->property('inline_errors') == 'display') { + throw new ValidationException($validator); + } else { + throw new AjaxException($this->_exceptionResponse($validator, [ + 'status' => 'error', + 'type' => 'danger', + 'title' => $message, + 'list' => $validator->messages()->all(), + 'errors' => json_encode($validator->messages()->messages()), + 'jscript' => $this->property('js_on_error'), + ])); + } + + } + + // IF FIRST VALIDATION IS OK, VALIDATE CAPTCHA vs GOOGLE + // (this prevents to resolve captcha after every form error) + if ($this->isReCaptchaEnabled()) { + + // PREPARE RECAPTCHA VALIDATION + $rules = ['g-recaptcha-response' => 'recaptcha']; + $err_msg = ['g-recaptcha-response.recaptcha' => Lang::get('blakejones.magicforms::lang.validation.recaptcha_error')]; + + // DO SECOND VALIDATION + $validator = Validator::make($post, $rules, $err_msg); + + // VALIDATE ALL + CAPTCHA EXISTS + if ($validator->fails()) { + + // THROW ERRORS + if ($this->property('inline_errors') == 'display') { + throw new ValidationException($validator); + } else { + throw new AjaxException($this->_exceptionResponse($validator, [ + 'status' => 'error', + 'type' => 'danger', + 'content' => Lang::get('blakejones.magicforms::lang.validation.recaptcha_error'), + 'errors' => json_encode($validator->messages()->messages()), + 'jscript' => $this->property('js_on_error'), + ])); + } + + } + + } + + // REMOVE EXTRA FIELDS FROM STORED DATA + unset($post['_token'], $post['g-recaptcha-response'], $post['_session_key'], $post['_uploader']); + + // FIRE BEFORE SAVE EVENT + Event::fire('blakejones.magicforms.beforeSaveRecord', [&$post, $this]); + + if (count($custom_attributes)) { + $post = collect($post)->mapWithKeys(function ($val, $key) use ($custom_attributes) { + return [array_get($custom_attributes, $key, $key) => $val]; + })->all(); + } + + $record = new Record; + $record->ip = $this->getIP(); + $record->created_at = date('Y-m-d H:i:s'); + + // SAVE RECORD TO DATABASE + if (! $this->property('skip_database')) { + $record->form_data = json_encode($post, JSON_UNESCAPED_UNICODE); + if ($this->property('group') != '') { + $record->group = $this->property('group'); + } + $record->save(null, post('_session_key')); + } + + // SEND NOTIFICATION EMAIL + if ($this->property('mail_enabled')) { + SendMail::sendNotification($this->getProperties(), $post, $record, $record->files); + } + + // SEND AUTORESPONSE EMAIL + if ($this->property('mail_resp_enabled')) { + SendMail::sendAutoResponse($this->getProperties(), $post, $record); + } + + // FIRE AFTER SAVE EVENT + Event::fire('blakejones.magicforms.afterSaveRecord', [&$post, $this, $record]); + + // CHECK FOR REDIRECT + if ($this->property('redirect')) { + return Redirect::to($this->property('redirect')); + } + + // GET DEFAULT SUCCESS MESSAGE + $message = $this->property('messages_success'); + + // LOOK FOR TRANSLATION + if (BackendHelpers::isTranslatePlugin()) { + $message = \RainLab\Translate\Models\Message::trans($message); + } + + // DISPLAY SUCCESS MESSAGE + return ['#' . $this->alias . '_forms_flash' => $this->renderPartial($flash_partial, [ + 'status' => 'success', + 'type' => 'success', + 'content' => $message, + 'jscript' => $this->prepareJavaScript(), + ])]; + + } + + private function _exceptionResponse($validator, $params) { + + // FLASH PARTIAL + $flash_partial = $this->property('messages_partial', '@flash.htm'); + + // EXCEPTION RESPONSE + $response = ['#' . $this->alias . '_forms_flash' => $this->renderPartial($flash_partial, $params)]; + + // INCLUDE ERROR FIELDS IF REQUIRED + if ($this->property('inline_errors') != 'disabled') { + $response['error_fields'] = $validator->messages(); + } + + return $response; + + } + + private function prepareJavaScript() + { + $code = false; + + /* SUCCESS JS */ + if ($this->property('js_on_success') != '') { + $code .= $this->property('js_on_success'); + } + + /* RECAPTCHA JS */ + if ($this->isReCaptchaEnabled()) { + $code .= $this->renderPartial('@js/recaptcha.htm'); + } + + /* RESET FORM JS */ + if ($this->property('reset_form')) { + $params = ['id' => '#' . $this->alias . '_forms_flash']; + $code .= $this->renderPartial('@js/reset-form.htm', $params); + } + + /* RESET UPLOAD FORM */ + if ($this->property('reset_form') && $this->property('uploader_enable')) { + $params = ['id' => $this->alias]; + $code .= $this->renderPartial('@js/reset-uploader.htm', $params); + } + + return $code; + } + + private function getIP() + { + if ($this->property('anonymize_ip') == 'full') { + return '(Not stored)'; + } + + $ip = Request::getClientIp(); + + if ($this->property('anonymize_ip') == 'partial') { + return BackendHelpers::anonymizeIPv4($ip); + } + + return $ip; + } + + private function array_map_recursive($callback, $array) + { + $func = function ($item) use (&$func, &$callback) { + return is_array($item) ? array_map($func, $item) : call_user_func($callback, $item); + }; + + return array_map($func, $array); + } +} diff --git a/plugins/blakejones/magicforms/classes/ReCaptcha.php b/plugins/blakejones/magicforms/classes/ReCaptcha.php new file mode 100644 index 0000000..5181f98 --- /dev/null +++ b/plugins/blakejones/magicforms/classes/ReCaptcha.php @@ -0,0 +1,52 @@ +translator = Translator::instance(); + } + } + + private function isReCaptchaEnabled() { + return ($this->property('recaptcha_enabled') && Settings::get('recaptcha_site_key') != '' && Settings::get('recaptcha_secret_key') != ''); + } + + private function isReCaptchaMisconfigured() { + return ($this->property('recaptcha_enabled') && (Settings::get('recaptcha_site_key') == '' || Settings::get('recaptcha_secret_key') == '')); + } + + private function getReCaptchaLang($lang='') { + if (BackendHelpers::isTranslatePlugin()) { + $lang = '&hl=' . $this->activeLocale = $this->translator->getLocale(); + } else { + $lang = '&hl=' . $this->activeLocale = app()->getLocale(); + } + return $lang; + } + + private function loadReCaptcha() { + $this->addJs('https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit'.$this->getReCaptchaLang(), ['async', 'defer']); + $this->addJs('assets/js/recaptcha.js'); + } + +} + +?> diff --git a/plugins/blakejones/magicforms/classes/ReCaptchaValidator.php b/plugins/blakejones/magicforms/classes/ReCaptchaValidator.php new file mode 100644 index 0000000..ce3d69e --- /dev/null +++ b/plugins/blakejones/magicforms/classes/ReCaptchaValidator.php @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/plugins/blakejones/magicforms/classes/SendMail.php b/plugins/blakejones/magicforms/classes/SendMail.php new file mode 100644 index 0000000..d197fde --- /dev/null +++ b/plugins/blakejones/magicforms/classes/SendMail.php @@ -0,0 +1,146 @@ + $record->id, + 'data' => $post, + 'ip' => $record->ip, + 'date' => $record->created_at + ]; + + // CHECK FOR CUSTOM SUBJECT + if (isset($properties['mail_subject'])) { + + // set date format + $dateFormat = $properties['emails_date_format'] ?? 'Y-m-d'; + + // REPLACE RECORD TOKENS IN SUBJECT + $properties['mail_subject'] = BackendHelpers::replaceToken('record.id', $data['id'], $properties['mail_subject']); + $properties['mail_subject'] = BackendHelpers::replaceToken('record.ip', $data['ip'], $properties['mail_subject']); + $properties['mail_subject'] = BackendHelpers::replaceToken('record.date', date($dateFormat), $properties['mail_subject']); + + // REPLACE FORM FIELDS TOKENS IN SUBJECT + foreach ($data['data'] as $key => $value) { + if (!is_array($value)) { + $properties['mail_subject'] = BackendHelpers::replaceToken('form.'.$key, $value, $properties['mail_subject']); + } + } + + // SET CUSTOM SUBJECT + $data['subject'] = $properties['mail_subject']; + + } + + // SEND NOTIFICATION EMAIL + Mail::sendTo($properties['mail_recipients'], $template, $data, function ($message) use ($properties, $post, $files) { + + // SEND BLIND CARBON COPY + if (isset($properties['mail_bcc']) && is_array($properties['mail_bcc'])) { + $message->bcc($properties['mail_bcc']); + } + + // USE CUSTOM SUBJECT + if (isset($properties['mail_subject'])) { + $message->subject($properties['mail_subject']); + } + + // ADD REPLY TO ADDRESS + if (isset($properties['mail_replyto']) && isset($post[$properties['mail_replyto']])) { + $message->replyTo($post[$properties['mail_replyto']]); + } + + // ADD UPLOADS + if (isset($properties['mail_uploads']) && $properties['mail_uploads'] && !empty($files)) { + foreach ($files as $file) { + $message->attach($file->getLocalPath(), ['as' => $file->getFilename()]); + } + } + + }); + + } + + } + + public static function sendAutoResponse($properties, $post, $record) { + + $data = [ + 'id' => $record->id, + 'data' => $post, + 'ip' => $record->ip, + 'date' => $record->created_at + ]; + + // CHECK FOR CUSTOM SUBJECT + if (isset($properties['mail_resp_subject'])) { + + // set date format + $dateFormat = $properties['emails_date_format'] ?? 'Y-m-d'; + + // REPLACE RECORD TOKENS IN SUBJECT + $properties['mail_resp_subject'] = BackendHelpers::replaceToken('record.id', $data['id'], $properties['mail_resp_subject']); + $properties['mail_resp_subject'] = BackendHelpers::replaceToken('record.ip', $data['ip'], $properties['mail_resp_subject']); + $properties['mail_resp_subject'] = BackendHelpers::replaceToken('record.date', date($dateFormat), $properties['mail_resp_subject']); + + // REPLACE FORM FIELDS TOKENS IN SUBJECT + foreach ($data['data'] as $key => $value) { + if (!is_array($value)) { + $properties['mail_resp_subject'] = BackendHelpers::replaceToken('form.'.$key, $value, $properties['mail_resp_subject']); + } + } + } + + $response = isset($properties['mail_resp_field']) ? $properties['mail_resp_field'] : null; + $to = isset($post[$response]) ? $post[$response] : null; + $from = isset($properties['mail_resp_from']) ? $properties['mail_resp_from'] : null; + $subject = isset($properties['mail_resp_subject']) ? $properties['mail_resp_subject'] : null; + + if (filter_var($to, FILTER_VALIDATE_EMAIL) && filter_var($from, FILTER_VALIDATE_EMAIL)) { + + // CUSTOM TEMPLATE + $template = isset($properties['mail_resp_template']) && $properties['mail_resp_template'] != '' && MailTemplate::findOrMakeTemplate($properties['mail_resp_template']) ? $properties['mail_resp_template'] : 'blakejones.magicforms::mail.autoresponse'; + + Mail::sendTo($to, $template, [ + 'id' => $record->id, + 'data' => $post, + 'ip' => $record->ip, + 'date' => $record->created_at + ], function ($message) use ($from, $subject) { + $message->from($from); + if (isset($subject)) { + $message->subject($subject); + } + } + ); + + } + + } + +} + +?> diff --git a/plugins/blakejones/magicforms/classes/SharedProperties.php b/plugins/blakejones/magicforms/classes/SharedProperties.php new file mode 100644 index 0000000..0c56430 --- /dev/null +++ b/plugins/blakejones/magicforms/classes/SharedProperties.php @@ -0,0 +1,259 @@ + [ + 'title' => 'blakejones.magicforms::lang.components.shared.group.title', + 'description' => 'blakejones.magicforms::lang.components.shared.group.description', + 'type' => 'string', + 'showExternalParam' => false, + ], + 'rules' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.rules.title', + 'description' => 'blakejones.magicforms::lang.components.shared.rules.description', + 'type' => 'dictionary', + 'group' => 'blakejones.magicforms::lang.components.shared.group_validation', + 'showExternalParam' => false, + ], + 'rules_messages' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.rules_messages.title', + 'description' => 'blakejones.magicforms::lang.components.shared.rules_messages.description', + 'type' => 'dictionary', + 'group' => 'blakejones.magicforms::lang.components.shared.group_validation', + 'showExternalParam' => false, + ], + 'custom_attributes' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.custom_attributes.title', + 'description' => 'blakejones.magicforms::lang.components.shared.custom_attributes.description', + 'type' => 'dictionary', + 'group' => 'blakejones.magicforms::lang.components.shared.group_validation', + 'showExternalParam' => false, + ], + 'messages_success' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.messages_success.title', + 'description' => 'blakejones.magicforms::lang.components.shared.messages_success.description', + 'type' => 'string', + 'group' => 'blakejones.magicforms::lang.components.shared.group_messages', + 'default' => Lang::get('blakejones.magicforms::lang.components.shared.messages_success.default'), + 'showExternalParam' => false, + 'validation' => ['required' => ['message' => Lang::get('blakejones.magicforms::lang.components.shared.validation_req')]] + ], + 'messages_errors' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.messages_errors.title', + 'description' => 'blakejones.magicforms::lang.components.shared.messages_errors.description', + 'type' => 'string', + 'group' => 'blakejones.magicforms::lang.components.shared.group_messages', + 'default' => Lang::get('blakejones.magicforms::lang.components.shared.messages_errors.default'), + 'showExternalParam' => false, + 'validation' => ['required' => ['message' => Lang::get('blakejones.magicforms::lang.components.shared.validation_req')]] + ], + 'messages_partial' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.messages_partial.title', + 'description' => 'blakejones.magicforms::lang.components.shared.messages_partial.description', + 'type' => 'string', + 'group' => 'blakejones.magicforms::lang.components.shared.group_messages', + 'showExternalParam' => false + ], + 'mail_enabled' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.mail_enabled.title', + 'description' => 'blakejones.magicforms::lang.components.shared.mail_enabled.description', + 'type' => 'checkbox', + 'group' => 'blakejones.magicforms::lang.components.shared.group_mail', + 'showExternalParam' => false + ], + 'mail_subject' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.mail_subject.title', + 'description' => 'blakejones.magicforms::lang.components.shared.mail_subject.description', + 'type' => 'string', + 'group' => 'blakejones.magicforms::lang.components.shared.group_mail', + 'showExternalParam' => false + ], + 'mail_recipients' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.mail_recipients.title', + 'description' => 'blakejones.magicforms::lang.components.shared.mail_recipients.description', + 'type' => 'dictionary', + 'group' => 'blakejones.magicforms::lang.components.shared.group_mail', + 'showExternalParam' => false + ], + 'mail_bcc' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.mail_bcc.title', + 'description' => 'blakejones.magicforms::lang.components.shared.mail_bcc.description', + 'type' => 'stringList', + 'group' => 'blakejones.magicforms::lang.components.shared.group_mail', + 'showExternalParam' => false + ], + 'mail_replyto' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.mail_replyto.title', + 'description' => 'blakejones.magicforms::lang.components.shared.mail_replyto.description', + 'type' => 'string', + 'group' => 'blakejones.magicforms::lang.components.shared.group_mail', + 'showExternalParam' => false + ], + 'mail_template' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.mail_template.title', + 'description' => 'blakejones.magicforms::lang.components.shared.mail_template.description', + 'type' => 'string', + 'group' => 'blakejones.magicforms::lang.components.shared.group_mail', + 'showExternalParam' => false + ], + 'mail_resp_enabled' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.mail_resp_enabled.title', + 'description' => 'blakejones.magicforms::lang.components.shared.mail_resp_enabled.description', + 'type' => 'checkbox', + 'group' => 'blakejones.magicforms::lang.components.shared.group_mail_resp', + 'showExternalParam' => false + ], + 'mail_resp_field' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.mail_resp_field.title', + 'description' => 'blakejones.magicforms::lang.components.shared.mail_resp_field.description', + 'type' => 'string', + 'group' => 'blakejones.magicforms::lang.components.shared.group_mail_resp', + 'showExternalParam' => false + ], + 'mail_resp_from' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.mail_resp_from.title', + 'description' => 'blakejones.magicforms::lang.components.shared.mail_resp_from.description', + 'type' => 'string', + 'group' => 'blakejones.magicforms::lang.components.shared.group_mail_resp', + 'showExternalParam' => false + ], + 'mail_resp_subject' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.mail_resp_subject.title', + 'description' => 'blakejones.magicforms::lang.components.shared.mail_resp_subject.description', + 'type' => 'string', + 'group' => 'blakejones.magicforms::lang.components.shared.group_mail_resp', + 'showExternalParam' => false + ], + 'mail_resp_template' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.mail_template.title', + 'description' => 'blakejones.magicforms::lang.components.shared.mail_template.description', + 'type' => 'string', + 'group' => 'blakejones.magicforms::lang.components.shared.group_mail_resp', + 'showExternalParam' => false + ], + 'reset_form' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.reset_form.title', + 'description' => 'blakejones.magicforms::lang.components.shared.reset_form.description', + 'type' => 'checkbox', + 'group' => 'blakejones.magicforms::lang.components.shared.group_settings', + 'showExternalParam' => false + ], + 'redirect' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.redirect.title', + 'description' => 'blakejones.magicforms::lang.components.shared.redirect.description', + 'type' => 'string', + 'group' => 'blakejones.magicforms::lang.components.shared.group_settings', + 'showExternalParam' => false + ], + 'inline_errors' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.inline_errors.title', + 'description' => 'blakejones.magicforms::lang.components.shared.inline_errors.description', + 'type' => 'dropdown', + 'options' => ['disabled' => 'blakejones.magicforms::lang.components.shared.inline_errors.disabled', 'display' => 'blakejones.magicforms::lang.components.shared.inline_errors.display', 'variable' => 'blakejones.magicforms::lang.components.shared.inline_errors.variable'], + 'default' => 'disabled', + 'group' => 'blakejones.magicforms::lang.components.shared.group_settings', + 'showExternalParam' => false + ], + 'js_on_success' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.js_on_success.title', + 'description' => 'blakejones.magicforms::lang.components.shared.js_on_success.description', + 'type' => 'text', + 'group' => 'blakejones.magicforms::lang.components.shared.group_settings', + 'showExternalParam' => false + ], + 'js_on_error' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.js_on_error.title', + 'description' => 'blakejones.magicforms::lang.components.shared.js_on_error.description', + 'type' => 'text', + 'group' => 'blakejones.magicforms::lang.components.shared.group_settings', + 'showExternalParam' => false + ], + 'allowed_fields' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.allowed_fields.title', + 'description' => 'blakejones.magicforms::lang.components.shared.allowed_fields.description', + 'type' => 'stringList', + 'group' => 'blakejones.magicforms::lang.components.shared.group_security', + 'showExternalParam' => false + ], + 'sanitize_data' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.sanitize_data.title', + 'description' => 'blakejones.magicforms::lang.components.shared.sanitize_data.description', + 'type' => 'dropdown', + 'options' => ['disabled' => 'blakejones.magicforms::lang.components.shared.sanitize_data.disabled', 'htmlspecialchars' => 'blakejones.magicforms::lang.components.shared.sanitize_data.htmlspecialchars'], + 'default' => 'disabled', + 'group' => 'blakejones.magicforms::lang.components.shared.group_security', + 'showExternalParam' => false + ], + 'anonymize_ip' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.anonymize_ip.title', + 'description' => 'blakejones.magicforms::lang.components.shared.anonymize_ip.description', + 'type' => 'dropdown', + 'options' => ['disabled' => 'blakejones.magicforms::lang.components.shared.anonymize_ip.disabled', 'partial' => 'blakejones.magicforms::lang.components.shared.anonymize_ip.partial', 'full' => 'blakejones.magicforms::lang.components.shared.anonymize_ip.full'], + 'default' => 'disabled', + 'group' => 'blakejones.magicforms::lang.components.shared.group_security', + 'showExternalParam' => false + ], + 'recaptcha_enabled' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.recaptcha_enabled.title', + 'description' => 'blakejones.magicforms::lang.components.shared.recaptcha_enabled.description', + 'type' => 'checkbox', + 'group' => 'blakejones.magicforms::lang.components.shared.group_recaptcha', + 'showExternalParam' => false + ], + 'recaptcha_theme' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.recaptcha_theme.title', + 'description' => 'blakejones.magicforms::lang.components.shared.recaptcha_theme.description', + 'type' => 'dropdown', + 'options' => ['light' => 'blakejones.magicforms::lang.components.shared.recaptcha_theme.light', 'dark' => 'blakejones.magicforms::lang.components.shared.recaptcha_theme.dark'], + 'default' => 'light', + 'group' => 'blakejones.magicforms::lang.components.shared.group_recaptcha', + 'showExternalParam' => false + ], + 'recaptcha_type' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.recaptcha_type.title', + 'description' => 'blakejones.magicforms::lang.components.shared.recaptcha_type.description', + 'type' => 'dropdown', + 'options' => ['image' => 'blakejones.magicforms::lang.components.shared.recaptcha_type.image', 'audio' => 'blakejones.magicforms::lang.components.shared.recaptcha_type.audio'], + 'default' => 'image', + 'group' => 'blakejones.magicforms::lang.components.shared.group_recaptcha', + 'showExternalParam' => false + ], + 'recaptcha_size' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.recaptcha_size.title', + 'description' => 'blakejones.magicforms::lang.components.shared.recaptcha_size.description', + 'type' => 'dropdown', + 'options' => [ + 'normal' => 'blakejones.magicforms::lang.components.shared.recaptcha_size.normal', + 'compact' => 'blakejones.magicforms::lang.components.shared.recaptcha_size.compact', + 'invisible' => 'blakejones.magicforms::lang.components.shared.recaptcha_size.invisible', + ], + 'default' => 'normal', + 'group' => 'blakejones.magicforms::lang.components.shared.group_recaptcha', + 'showExternalParam' => false + ], + 'skip_database' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.skip_database.title', + 'description' => 'blakejones.magicforms::lang.components.shared.skip_database.description', + 'type' => 'checkbox', + 'group' => 'blakejones.magicforms::lang.components.shared.group_advanced', + 'showExternalParam' => false + ], + 'emails_date_format' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.emails_date_format.title', + 'description' => 'blakejones.magicforms::lang.components.shared.emails_date_format.description', + 'default' => 'Y-m-d', + 'group' => 'blakejones.magicforms::lang.components.shared.group_advanced', + 'showExternalParam' => false + ], + ]; + } + +} + +?> diff --git a/plugins/blakejones/magicforms/classes/UnreadRecords.php b/plugins/blakejones/magicforms/classes/UnreadRecords.php new file mode 100644 index 0000000..de3bd02 --- /dev/null +++ b/plugins/blakejones/magicforms/classes/UnreadRecords.php @@ -0,0 +1,20 @@ +count(); + } + + return (isset($unread) && $unread > 0) ? $unread : null; + } + +} + +?> \ No newline at end of file diff --git a/plugins/blakejones/magicforms/components/EmptyForm.php b/plugins/blakejones/magicforms/components/EmptyForm.php new file mode 100644 index 0000000..a880cd3 --- /dev/null +++ b/plugins/blakejones/magicforms/components/EmptyForm.php @@ -0,0 +1,18 @@ + 'blakejones.magicforms::lang.components.empty_form.name', + 'description' => 'blakejones.magicforms::lang.components.empty_form.description', + ]; + } + + } + +?> \ No newline at end of file diff --git a/plugins/blakejones/magicforms/components/GenericForm.php b/plugins/blakejones/magicforms/components/GenericForm.php new file mode 100644 index 0000000..5219756 --- /dev/null +++ b/plugins/blakejones/magicforms/components/GenericForm.php @@ -0,0 +1,18 @@ + 'blakejones.magicforms::lang.components.generic_form.name', + 'description' => 'blakejones.magicforms::lang.components.generic_form.description', + ]; + } + + } + +?> \ No newline at end of file diff --git a/plugins/blakejones/magicforms/components/UploadForm.php b/plugins/blakejones/magicforms/components/UploadForm.php new file mode 100644 index 0000000..c883650 --- /dev/null +++ b/plugins/blakejones/magicforms/components/UploadForm.php @@ -0,0 +1,104 @@ + 'blakejones.magicforms::lang.components.upload_form.name', + 'description' => 'blakejones.magicforms::lang.components.upload_form.description', + ]; + } + + public function init() { + parent::init(); + $this->fileTypes = $this->processFileTypes(true); + $this->maxSize = $this->property('maxSize'); + $this->placeholderText = $this->property('placeholderText'); + $this->removeText = $this->property('removeText'); + $this->setProperty('deferredBinding', 1); + $this->bindModel('files', new Record); + } + + public function onRun() { + parent::onRun(); + $this->addCss('assets/css/uploader.css'); + $this->addJs('assets/vendor/dropzone/dropzone.js'); + $this->addJs('assets/js/uploader.js'); + $this->isMulti = $this->property('uploader_multi'); + if($result = $this->checkUploadAction()) { return $result; } + } + + public function defineProperties() { + $local = [ + 'mail_uploads' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.mail_uploads.title', + 'description' => 'blakejones.magicforms::lang.components.shared.mail_uploads.description', + 'type' => 'checkbox', + 'default' => false, + 'group' => 'blakejones.magicforms::lang.components.shared.group_mail', + 'showExternalParam' => false + ], + 'uploader_enable' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.uploader_enable.title', + 'description' => 'blakejones.magicforms::lang.components.shared.uploader_enable.description', + 'default' => false, + 'type' => 'checkbox', + 'group' => 'blakejones.magicforms::lang.components.shared.group_uploader', + 'showExternalParam' => false, + ], + 'uploader_multi' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.uploader_multi.title', + 'description' => 'blakejones.magicforms::lang.components.shared.uploader_multi.description', + 'default' => true, + 'type' => 'checkbox', + 'group' => 'blakejones.magicforms::lang.components.shared.group_uploader', + 'showExternalParam' => false, + ], + 'placeholderText' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.uploader_pholder.title', + 'description' => 'blakejones.magicforms::lang.components.shared.uploader_pholder.description', + 'default' => Lang::get('blakejones.magicforms::lang.components.shared.uploader_pholder.default'), + 'type' => 'string', + 'group' => 'blakejones.magicforms::lang.components.shared.group_uploader', + 'showExternalParam' => false, + ], + 'removeText' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.uploader_remFile.title', + 'description' => 'blakejones.magicforms::lang.components.shared.uploader_remFile.description', + 'default' => Lang::get('blakejones.magicforms::lang.components.shared.uploader_remFile.default'), + 'type' => 'string', + 'group' => 'blakejones.magicforms::lang.components.shared.group_uploader', + 'showExternalParam' => false, + ], + 'maxSize' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.uploader_maxsize.title', + 'description' => 'blakejones.magicforms::lang.components.shared.uploader_maxsize.description', + 'default' => '5', + 'type' => 'string', + 'group' => 'blakejones.magicforms::lang.components.shared.group_uploader', + 'showExternalParam' => false, + ], + 'fileTypes' => [ + 'title' => 'blakejones.magicforms::lang.components.shared.uploader_types.title', + 'description' => 'blakejones.magicforms::lang.components.shared.uploader_types.description', + 'default' => Definitions::get('defaultExtensions'), + 'type' => 'stringList', + 'group' => 'blakejones.magicforms::lang.components.shared.group_uploader', + 'showExternalParam' => false, + ], + ]; + return array_merge(parent::defineProperties(), $local); + } + + } + +?> \ No newline at end of file diff --git a/plugins/blakejones/magicforms/components/emptyform/default.htm b/plugins/blakejones/magicforms/components/emptyform/default.htm new file mode 100644 index 0000000..9354444 --- /dev/null +++ b/plugins/blakejones/magicforms/components/emptyform/default.htm @@ -0,0 +1,12 @@ +

    Here goes your custom form

    +

    Override HTML by creating a new partial called default.htm (more info here)

    +

    You can copy/paste this basic template:

    +
    +    <form data-request="{{ __SELF__ }}::onFormSubmit">
    +        {{ form_token() }}
    +        <div id="{{ __SELF__ }}_forms_flash"></div>
    +        <!-- YOUR FORM FIELDS -->
    +        {% partial '@recaptcha' %}
    +        <!-- SUBMIT BUTTON -->
    +    </form>
    +
    \ No newline at end of file diff --git a/plugins/blakejones/magicforms/components/genericform/default.htm b/plugins/blakejones/magicforms/components/genericform/default.htm new file mode 100644 index 0000000..4911953 --- /dev/null +++ b/plugins/blakejones/magicforms/components/genericform/default.htm @@ -0,0 +1,32 @@ +
    + + {{ form_token() }} + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + +
    + +
    + {% partial '@recaptcha' %} +
    + + + +
    \ No newline at end of file diff --git a/plugins/blakejones/magicforms/components/partials/flash.htm b/plugins/blakejones/magicforms/components/partials/flash.htm new file mode 100644 index 0000000..fa06a3f --- /dev/null +++ b/plugins/blakejones/magicforms/components/partials/flash.htm @@ -0,0 +1,28 @@ + + +{% if jscript %} + +{% endif %} \ No newline at end of file diff --git a/plugins/blakejones/magicforms/components/partials/js/recaptcha.htm b/plugins/blakejones/magicforms/components/partials/js/recaptcha.htm new file mode 100644 index 0000000..9dd3d4c --- /dev/null +++ b/plugins/blakejones/magicforms/components/partials/js/recaptcha.htm @@ -0,0 +1 @@ +resetReCaptcha('{{ __SELF__ }}'); \ No newline at end of file diff --git a/plugins/blakejones/magicforms/components/partials/js/reset-form.htm b/plugins/blakejones/magicforms/components/partials/js/reset-form.htm new file mode 100644 index 0000000..d051d44 --- /dev/null +++ b/plugins/blakejones/magicforms/components/partials/js/reset-form.htm @@ -0,0 +1 @@ +$('{{ id }}').parents('form')[0].reset(); \ No newline at end of file diff --git a/plugins/blakejones/magicforms/components/partials/js/reset-uploader.htm b/plugins/blakejones/magicforms/components/partials/js/reset-uploader.htm new file mode 100644 index 0000000..a5a6505 --- /dev/null +++ b/plugins/blakejones/magicforms/components/partials/js/reset-uploader.htm @@ -0,0 +1,2 @@ +var dz = uploadDropZones['{{ id }}']; +if(dz) { dz.uploader.dropzone.removeAllFiles(); dz.uploader.evalIsPopulated(); } \ No newline at end of file diff --git a/plugins/blakejones/magicforms/components/partials/recaptcha.htm b/plugins/blakejones/magicforms/components/partials/recaptcha.htm new file mode 100644 index 0000000..b677c50 --- /dev/null +++ b/plugins/blakejones/magicforms/components/partials/recaptcha.htm @@ -0,0 +1,5 @@ +{% if (recaptcha_enabled) %} +
    +{% elseif (recaptcha_misconfigured) %} +
    {{ recaptcha_warn }}
    +{% endif %} \ No newline at end of file diff --git a/plugins/blakejones/magicforms/components/uploadform/default.htm b/plugins/blakejones/magicforms/components/uploadform/default.htm new file mode 100644 index 0000000..d6c66d8 --- /dev/null +++ b/plugins/blakejones/magicforms/components/uploadform/default.htm @@ -0,0 +1,51 @@ +{{ form_ajax(__SELF__ ~ '::onFormSubmit') }} + +
    + +
    +

    Apply for online job

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

    Upload your resume

    + {% partial '@file-upload' %} +
    + +
    + +
    + {% partial '@recaptcha' %} +
    + + {{ form_submit() }} + +{{ form_close() }} \ No newline at end of file diff --git a/plugins/blakejones/magicforms/components/uploadform/file-multi.htm b/plugins/blakejones/magicforms/components/uploadform/file-multi.htm new file mode 100644 index 0000000..db8f1a0 --- /dev/null +++ b/plugins/blakejones/magicforms/components/uploadform/file-multi.htm @@ -0,0 +1,71 @@ +
    + + + + + + + + +
    + {% for file in __SELF__.fileList %} +
    +
    + {% if file.isImage %} + + {% else %} + + {% endif %} +
    +
    +

    + {{ file.title ?: file.file_name }} +

    +

    {{ file.sizeToString }}

    +
    +
    + × +
    +
    + {% endfor %} +
    +
    + + + diff --git a/plugins/blakejones/magicforms/components/uploadform/file-single.htm b/plugins/blakejones/magicforms/components/uploadform/file-single.htm new file mode 100644 index 0000000..3c7eadc --- /dev/null +++ b/plugins/blakejones/magicforms/components/uploadform/file-single.htm @@ -0,0 +1,79 @@ +{% set file = __SELF__.singleFile %} + +
    + + + + + + + + +
    + {% if file %} +
    +
    + {% if file.isImage %} + + {% else %} + + {% endif %} +
    +
    +

    + {{ file.title ?: file.file_name }} +

    +

    {{ file.sizeToString }}

    +
    +
    + × +
    +
    + {% endif %} +
    + + +
    + {{ __SELF__.placeholderText }} +
    + +
    + + + diff --git a/plugins/blakejones/magicforms/components/uploadform/file-upload.htm b/plugins/blakejones/magicforms/components/uploadform/file-upload.htm new file mode 100644 index 0000000..e0b4b28 --- /dev/null +++ b/plugins/blakejones/magicforms/components/uploadform/file-upload.htm @@ -0,0 +1,21 @@ +{% if __SELF__.property('uploader_enable') == 0 %} + +
    +
    Warning
    +
    Uploads are disabled.
    +
    You need to explicitly enable this option on the component (this is a security measure).
    +
    + +{% else %} + + {% if __SELF__.isMulti %} + + {% partial __SELF__ ~ '::file-multi' %} + + {% else %} + + {% partial __SELF__ ~ '::file-single' %} + + {% endif %} + +{% endif %} \ No newline at end of file diff --git a/plugins/blakejones/magicforms/composer.json b/plugins/blakejones/magicforms/composer.json new file mode 100644 index 0000000..44a713d --- /dev/null +++ b/plugins/blakejones/magicforms/composer.json @@ -0,0 +1,8 @@ +{ + "name": "blakejones/magicforms-plugin", + "type": "october-plugin", + "description": "Create easy (and almost magic) AJAX forms", + "keywords": ["october", "cms", "plugin", "forms", "magic forms"], + "homepage": "https://github.com/blakej115/magic-forms", + "license": "MIT" +} diff --git a/plugins/blakejones/magicforms/controllers/Exports.php b/plugins/blakejones/magicforms/controllers/Exports.php new file mode 100644 index 0000000..711b0fa --- /dev/null +++ b/plugins/blakejones/magicforms/controllers/Exports.php @@ -0,0 +1,123 @@ +pageTitle = e(trans('blakejones.magicforms::lang.controllers.exports.title')); + $this->create('frontend'); + } + + public function csv() { + + $records = Record::orderBy('created_at'); + + // FILTER GROUPS + if (!empty($groups = post('Record.filter_groups'))) { + $records->whereIn('group', $groups); + } + + // FILTER DATE + if (!empty($date_after = post('Record.filter_date_after'))) { + $records->whereDate('created_at', '>=', $date_after); + } + + // FILTER DATE + if (!empty($date_before = post('Record.filter_date_before'))) { + $records->whereDate('created_at', '<=', $date_before); + } + + // FILTER DELETED + if ($deleted = post('Record.options_deleted')) { + $records->withTrashed(); + } + + // CREATE CSV + $csv = CsvWriter::createFromFileObject(new SplTempFileObject()); + + // CHANGE DELIMTER + if (post('Record.options_delimiter')) { + $csv->setDelimiter(';'); + } + + // SET UTF-8 Output + if (post('Record.options_utf')) { + $csv->setOutputBOM(AbstractCsv::BOM_UTF8); + } + + // CSV HEADERS + $headers = []; + + // METADATA HEADERS + if (post('Record.options_metadata')) { + $meta_headers = [ + e(trans('blakejones.magicforms::lang.controllers.records.columns.id')), + e(trans('blakejones.magicforms::lang.controllers.records.columns.group')), + e(trans('blakejones.magicforms::lang.controllers.records.columns.ip')), + e(trans('blakejones.magicforms::lang.controllers.records.columns.created_at')), + ]; + $headers = array_merge($meta_headers, $headers); + } + + // ADD STORED FIELDS AS HEADER ROW IN CSV + $filteredRecords = $records->get(); + $recordsArray = $filteredRecords->toArray(); + $record = $filteredRecords->first(); + if (isset($record)) { + $headers = array_merge($headers, array_keys($record->form_data_arr)); + } + + // ADD HEADERS + $csv->insertOne($headers); + + // WRITE CSV LINES + foreach ($records->get()->toArray() as $row) { + + $data = (array) json_decode($row['form_data']); + + // IF DATA IS ARRAY CONVERT TO JSON STRING + foreach ($data as $field => $value) { + if (is_array($value) || is_object($value)) { + $data[$field] = json_encode($value); + } + } + + // ADD METADATA IF NEEDED + if (post('Record.options_metadata')) { + array_unshift($data, $row['id'], $row['group'], $row['ip'], $row['created_at']); + } + + $csv->insertOne($data); + + } + + // RETURN CSV + $csv->output('records.csv'); + exit(); + + } + +} + +?> diff --git a/plugins/blakejones/magicforms/controllers/Records.php b/plugins/blakejones/magicforms/controllers/Records.php new file mode 100644 index 0000000..0766bf0 --- /dev/null +++ b/plugins/blakejones/magicforms/controllers/Records.php @@ -0,0 +1,107 @@ +unread = false; + $record->save(); + $this->addCss('/plugins/blakejones/magicforms/assets/css/records.css'); + $this->pageTitle = e(trans('blakejones.magicforms::lang.controllers.records.view_title')); + $this->vars['record'] = $record; + } + + public function onDelete() { + if (($checkedIds = post('checked')) && is_array($checkedIds) && count($checkedIds)) { + Record::whereIn('id',$checkedIds)->delete(); + } + $counter = UnreadRecords::getTotal(); + return [ + 'counter' => ($counter != null) ? $counter : 0, + 'list' => $this->listRefresh() + ]; + } + + public function onDeleteSingle() { + $id = post('id' ); + $record = Record::find($id); + if($record) { + $record->delete(); + Flash::success(e(trans('blakejones.magicforms::lang.controllers.records.deleted'))); + } else { + Flash::error(e(trans('blakejones.magicforms::lang.controllers.records.error'))); + } + return Redirect::to(Backend::url('blakejones/magicforms/records')); + } + + public function download($record_id, $file_id) { + $record = Record::findOrFail($record_id); + $file = $record->files->find($file_id); + if(!$file) { App::abort(404, Lang::get('backend::lang.import_export.file_not_found_error')); } + return response()->download($file->getLocalPath(), $file->getFilename()); + exit(); + } + + public function listInjectRowClass($record, $definition = null) { + if ($record->unread) { + return 'new'; + } + } + + public function onReadState() { + if (($checkedIds = post('checked')) && is_array($checkedIds) && count($checkedIds)) { + $unread = (post('state') == 'read') ? 0 : 1; + Record::whereIn('id',$checkedIds)->update(['unread' => $unread]); + } + $counter = UnreadRecords::getTotal(); + return [ + 'counter' => ($counter != null) ? $counter : 0, + 'list' => $this->listRefresh() + ]; + } + + public function onGDPRClean() { + if ($this->user->hasPermission(['blakejones.magicforms.gdpr_cleanup'])) { + GDPR::cleanRecords(); + Flash::success(e(trans('blakejones.magicforms::lang.controllers.records.alerts.gdpr_success'))); + } else { + Flash::error(e(trans('blakejones.magicforms::lang.controllers.records.alerts.gdpr_perms'))); + } + $counter = UnreadRecords::getTotal(); + return [ + 'counter' => ($counter != null) ? $counter : 0, + 'list' => $this->listRefresh() + ]; + } + + } + +?> \ No newline at end of file diff --git a/plugins/blakejones/magicforms/controllers/exports/config_form.yaml b/plugins/blakejones/magicforms/controllers/exports/config_form.yaml new file mode 100644 index 0000000..0ffb86c --- /dev/null +++ b/plugins/blakejones/magicforms/controllers/exports/config_form.yaml @@ -0,0 +1,2 @@ +form : $/blakejones/magicforms/models/export/fields.yaml +modelClass: BlakeJones\MagicForms\Models\Record \ No newline at end of file diff --git a/plugins/blakejones/magicforms/controllers/exports/index.htm b/plugins/blakejones/magicforms/controllers/exports/index.htm new file mode 100644 index 0000000..a50a2ba --- /dev/null +++ b/plugins/blakejones/magicforms/controllers/exports/index.htm @@ -0,0 +1,16 @@ + +
      +
    • +
    • +
    + + + Backend::url('blakejones/magicforms/exports/csv/')]) ?> + + formRender() ?> + +
    + 'btn btn-primary']) ?> +
    + + \ No newline at end of file diff --git a/plugins/blakejones/magicforms/controllers/records/config_filter.yaml b/plugins/blakejones/magicforms/controllers/records/config_filter.yaml new file mode 100644 index 0000000..a1b0fb8 --- /dev/null +++ b/plugins/blakejones/magicforms/controllers/records/config_filter.yaml @@ -0,0 +1,13 @@ +scopes: + + group: + label : blakejones.magicforms::lang.controllers.records.columns.group + type : group + modelClass: BlakeJones\MagicForms\Models\Record + options : filterGroups + conditions: "`group` in (:filtered)" + + created_at: + label : blakejones.magicforms::lang.controllers.records.columns.created_at + type : daterange + conditions: created_at >= ':after' AND created_at <= ':before' \ No newline at end of file diff --git a/plugins/blakejones/magicforms/controllers/records/config_list.yaml b/plugins/blakejones/magicforms/controllers/records/config_list.yaml new file mode 100644 index 0000000..072bfa4 --- /dev/null +++ b/plugins/blakejones/magicforms/controllers/records/config_list.yaml @@ -0,0 +1,19 @@ +list : $/blakejones/magicforms/models/record/columns.yaml +modelClass : BlakeJones\MagicForms\Models\Record +title : blakejones.magicforms::lang.controllers.records.title +recordUrl : blakejones/magicforms/records/view/:id +noRecordsMessage: backend::lang.list.no_records +recordsPerPage : 20 +showSetup : true +showSorting : true +showCheckboxes : true +filter : config_filter.yaml + +defaultSort: + column : created_at + direction: desc + +toolbar: + buttons: partials/list_toolbar + search : + prompt: backend::lang.list.search_prompt \ No newline at end of file diff --git a/plugins/blakejones/magicforms/controllers/records/index.htm b/plugins/blakejones/magicforms/controllers/records/index.htm new file mode 100644 index 0000000..498d5dc --- /dev/null +++ b/plugins/blakejones/magicforms/controllers/records/index.htm @@ -0,0 +1 @@ +listRender() ?> \ No newline at end of file diff --git a/plugins/blakejones/magicforms/controllers/records/partials/_action_button.htm b/plugins/blakejones/magicforms/controllers/records/partials/_action_button.htm new file mode 100644 index 0000000..fa9dc53 --- /dev/null +++ b/plugins/blakejones/magicforms/controllers/records/partials/_action_button.htm @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/plugins/blakejones/magicforms/controllers/records/partials/_list_toolbar.htm b/plugins/blakejones/magicforms/controllers/records/partials/_list_toolbar.htm new file mode 100644 index 0000000..d8c8305 --- /dev/null +++ b/plugins/blakejones/magicforms/controllers/records/partials/_list_toolbar.htm @@ -0,0 +1,80 @@ +
    + + makePartial('$/blakejones/magicforms/controllers/records/partials/_action_button.htm', [ + 'type' => 'danger', + 'icon' => 'oc-icon-trash', + 'label' => e(trans('backend::lang.list.delete_selected')), + 'onclick' => "$(this).data('request-data', { checked: $('.control-list').listWidget('getChecked') })", + 'needs_selected' => true, + 'request' => 'onDelete', + 'request_confirm' => e(trans('backend::lang.list.delete_selected_confirm')), + 'request_success' => " + $('#records-toolbar').find('button').prop('disabled', true); + $.oc.flashMsg({ + 'text': '" . e(trans('backend::lang.list.delete_selected_success')) . "', + 'class': 'success', + 'interval': 3 + }); + $.oc.sideNav.setCounter('forms/records', data.counter); + $.oc.sideNav.setCounter('forms', data.counter); + $('#Lists').html(data.list['#Lists']); + ", + ]); + ?> + +
    + makePartial('$/blakejones/magicforms/controllers/records/partials/_action_button.htm', [ + 'type' => 'default', + 'icon' => 'oc-icon-eye-slash', + 'label' => e(trans('blakejones.magicforms::lang.controllers.records.buttons.unread')), + 'onclick' => "$(this).data('request-data', { state: 'unread', checked: $('.control-list').listWidget('getChecked') })", + 'needs_selected' => true, + 'request' => 'onReadState', + 'request_confirm' => '', + 'request_success' => " + $('#records-toolbar').find('button').prop('disabled', true); + $.oc.sideNav.setCounter('forms/records', data.counter); + $.oc.sideNav.setCounter('forms', data.counter); + $('#Lists').html(data.list['#Lists']); + ", + ]); + + echo $this->makePartial('$/blakejones/magicforms/controllers/records/partials/_action_button.htm', [ + 'type' => 'default', + 'icon' => 'oc-icon-eye', + 'label' => e(trans('blakejones.magicforms::lang.controllers.records.buttons.read')), + 'onclick' => "$(this).data('request-data', { state: 'read', checked: $('.control-list').listWidget('getChecked') })", + 'needs_selected' => true, + 'request' => 'onReadState', + 'request_confirm' => '', + 'request_success' => " + $('#records-toolbar').find('button').prop('disabled', true); + $.oc.sideNav.setCounter('forms/records', data.counter); + $.oc.sideNav.setCounter('forms', data.counter); + $('#Lists').html(data.list['#Lists']); + ", + ]); + ?> +
    + + makePartial('$/blakejones/magicforms/controllers/records/partials/_action_button.htm', [ + 'type' => 'danger', + 'icon' => 'oc-icon-history', + 'label' => e(trans('blakejones.magicforms::lang.controllers.records.buttons.gdpr_clean')), + 'request' => 'onGDPRClean', + 'request_confirm' => e(trans('blakejones.magicforms::lang.controllers.records.alerts.gdpr_confirm')), + 'request_success' => " + $('#records-toolbar').find('button').blur(); + $.oc.sideNav.setCounter('forms/records', data.counter); + $.oc.sideNav.setCounter('forms', data.counter); + $('#Lists').html(data.list['#Lists']); + ", + ]); + } + ?> + +
    \ No newline at end of file diff --git a/plugins/blakejones/magicforms/controllers/records/partials/_view_toolbar.htm b/plugins/blakejones/magicforms/controllers/records/partials/_view_toolbar.htm new file mode 100644 index 0000000..9c5faad --- /dev/null +++ b/plugins/blakejones/magicforms/controllers/records/partials/_view_toolbar.htm @@ -0,0 +1,13 @@ +
    +
    +
    + + +
    +
    +
    \ No newline at end of file diff --git a/plugins/blakejones/magicforms/controllers/records/view.htm b/plugins/blakejones/magicforms/controllers/records/view.htm new file mode 100644 index 0000000..f33f777 --- /dev/null +++ b/plugins/blakejones/magicforms/controllers/records/view.htm @@ -0,0 +1,50 @@ + +
      +
    • +
    • Record #id ?>
    • +
    + + +makePartial('partials/view_toolbar') ?> + +

    Record #id ?>

    + + +form_data_arr as $label => $value): ?> + + + + + +files) > 0): ?> + + + + + +
    : + +
      + +
    + + + +
    Attached Files: + +
    + + \ No newline at end of file diff --git a/plugins/blakejones/magicforms/lang/de/lang.php b/plugins/blakejones/magicforms/lang/de/lang.php new file mode 100644 index 0000000..777cd2c --- /dev/null +++ b/plugins/blakejones/magicforms/lang/de/lang.php @@ -0,0 +1,177 @@ + [ + 'name' => 'Magic Forms', + 'description' => 'einfaches Erstellen von AJAX Formularen' + ], + + 'menu' => [ + 'label' => 'Magic Forms', + 'records' => ['label' => 'Records'], + 'exports' => ['label' => 'Export'], + 'settings' => 'Konfigurieren der plugin parameter', + ], + + 'controllers' => [ + 'records' => [ + 'title' => 'Einträge anzeigen', + 'view_title' => 'Details zum Eintrag', + 'error' => 'Eintrag nicht gefunden', + 'deleted' => 'Eintrag erfolgreich gelöscht', + 'columns' => [ + 'id' => 'Eintrag ID', + 'group' => 'Gruppe', + 'ip' => 'IP Adresse', + 'form_data' => 'Gespeicherte Felder', + 'files' => 'Anhänge', + 'created_at' => 'Erstellt', + ], + 'buttons' => [ + 'read' => 'Als gelesen markieren', + 'unread' => 'Als ungelesen markieren', + 'gdpr_clean' => 'DSVGO Aufräumung', + ], + 'alerts' => [ + 'gdpr_confirm' => "Sind sie sicher dass Sie alte Einträge aufräumen wollen?\nDiese Aktion kann nicht wiederrufen werden!", + 'gdpr_success' => 'DSVGO Aufräumung wurde erfolgreich ausgeführt', + 'gdpr_perms' => 'Sie haben keine Berechtigung für diese Funktion.', + ], + ], + 'exports' => [ + 'title' => 'Einträge exportieren', + 'breadcrumb' => 'Exportieren', + 'filter_section' => '1. Einträge filtern', + 'filter_type' => 'Alle Einträge exportieren', + 'filter_groups' => 'Gruppen', + 'filter_date_after' => 'Nach dem Datum', + 'filter_date_before' => 'Vor dem Datum', + 'options_section' => '2. Extra Optionen', + 'options_metadata' => 'Inklusive Metadaten', + 'options_metadata_com' => 'Exportiere die Einträge mit Metadaten (Eintrag ID, Gruppe, IP, Erstellungsdatum)', + 'options_deleted' => 'Inklusive gelöschter Einträge', + 'options_delimiter' => 'Alternatives Trennzeichen benutzen', + 'options_delimiter_com' => 'Semikolon als Trennzeichen', + 'options_utf' => 'Enkodierung in UTF8', + 'options_utf_com' => 'Enkodierung Ihrer CSV-Datei im UTF-8 Format für die Unterstützung von Umlauten und Sonderzeichen.', + ], + ], + + 'components' => [ + 'generic_form' => [ + 'name' => 'Generisches AJAX Formular', + 'description' => 'Mit Standardeinstellungen rendered ein generisches Formular; Überschreib Komponenten HTML mit deinen eigenen Feldern.', + ], + 'upload_form' => [ + 'name' => 'Upload AJAX Formular [BETA]', + 'description' => 'Zeigt wie man Dateiupload in deinem Formular implementiert.', + ], + 'empty_form' => [ + 'name' => 'Leeres AJAX Formular', + 'description' => 'Erstellt eine leere Vorlage für dein individuelles Formular; Überschreib Komponenten HTML.', + ], + 'shared' => [ + 'csrf_error' => 'Formular Seitzung abgelaufen! Bitte die Seite neuladen.', + 'recaptcha_warn' => 'Warnung: reCAPTCHA ist nicht ordentlich konfiguriert. Bitte, gehe zum Backend > Einstellungen > CMS > Magic Forms um reCAPTCHA zu kofigurieren.', + 'group_validation' => 'Formular Validierung', + 'group_messages' => 'Flash Benachrichtung', + 'group_mail' => 'Benachrichtigungen Einstellungen', + 'group_mail_resp' => 'Automatische Antwort Einstellungen', + 'group_settings' => 'Weitere Einstellungen', + 'group_security' => 'Sicherheit', + 'group_recaptcha' => 'reCAPTCHA Einstellungen', + 'group_advanced' => 'Fortgeschrittene Einstellungen', + 'group_uploader' => 'Uploader Einstellungen', + 'validation_req' => 'Die Eigenschaft wird benötigt', + 'group' => ['title' => 'Gruppe' , 'description' => 'Organisiere deine Formulare durch eigene Gruppennamen. Diese Option ist für das Exportieren der Daten sehr praktischt.'], + 'rules' => ['title' => 'Regeln' , 'description' => 'Erstelle eigene Regeln Mithilfe der Laravel Validierungsfunktion'], + 'rules_messages' => ['title' => 'Regeln Benachrichtigungen' , 'description' => 'Erstelle eigene Benachrichtigungen Mithilfe der Laravel Validierungsfunktion'], + 'custom_attributes' => ['title' => 'Eigene Attribute' , 'description' => 'Erstelle eigene Attribute Mithilfe der Laravel Validierungsfunktion'], + 'messages_success' => ['title' => 'Erfolg' , 'description' => 'Nachricht bei erfolgreicher Übermittlung des Formulars', 'default' => 'Your form was successfully submitted' ], + 'messages_errors' => ['title' => 'Fehler' , 'description' => 'Nachricht bei Fehlern während der Eingabe der Formulardaten' , 'default' => 'There were errors with your submission'], + 'messages_partial' => ['title' => 'Benutze eigene Partial' , 'description' => 'Überschreibe Flash-Nachrichten mit deinem eigenem Partial in deinem Theme'], + 'mail_enabled' => ['title' => 'Sende Benachrichtigungen' , 'description' => 'Sende eine Benachrichtigungsmail nach jeder erfolgreichen Übertragung.'], + 'mail_subject' => ['title' => 'Betreff' , 'description' => 'Überschreibe die standard E-Mail Betreffszeile'], + 'mail_recipients' => ['title' => 'Empfänger' , 'description' => 'E-Mail-Empfänger angeben. Verwenden Sie E-Mail-Adressen als Schlüssel und Namen als Werte.'], + 'mail_bcc' => ['title' => 'BCC' , 'description' => 'Sende blind carbon copy (BCC) zur folgenden Empfängern (Füge eine E-Mail Adresse per Zeile ein)'], + 'mail_replyto' => ['title' => 'Empfänger E-Mail Feld', 'description' => 'Formular Feld das die E-Mail Adresse enthält. Diese Adresse wird als Empfänger Adresse benutzt.'], + 'mail_template' => ['title' => 'E-Mail Vorlage' , 'description' => 'Benutze eigene E-Mail Vorlagen. Gebe einen Vorlagen Code ein wie z.B. "blakejones.magicforms::mail.notification" (Kann im Einstellungen der E-Mail Vorlagen im Backend gefunden werden). Leer lassen für Standardvorlage.'], + 'mail_uploads' => ['title' => 'Sende Uploads' , 'description' => 'Sende Uploads als Anhang'], + 'mail_resp_enabled' => ['title' => 'Sende Auto-Antwort' , 'description' => 'Sende eine automatische Antwort E-Mail zu der Person die dein Formular ausgfüllt.'], + 'mail_resp_field' => ['title' => 'E-Mail Feld' , 'description' => 'Formular Feld das die E-Mail Adresse enthät für die automatische Antwort'], + 'mail_resp_from' => ['title' => 'Absender Adresse' , 'description' => 'Absender E-Mail Adresse was benutzt werden soll (z.B. noreply@yourcompany.com)'], + 'mail_resp_subject' => ['title' => 'Betreff' , 'description' => 'Überschreibe standard E-Mail Betreffszeile'], + 'reset_form' => ['title' => 'Resete Formular' , 'description' => 'Resete das Formular nach erfolgreichen Übertragung'], + 'redirect' => ['title' => 'Umleitung bei Erfolg', 'description' => 'URL-Umleitung nach erfoglreichen Übertragung'], + 'inline_errors' => ['title' => 'Inline Fehler' , 'description' => 'Zeige Inline-Fehler an. Die Funktion braucht Extra-Code. Siehe in der Dokumentation für mehr Informationen.', 'disabled' => 'Deaktiviert', 'display' => 'Zeige Fehler', 'variable' => 'JS Variable'], + 'js_on_success' => ['title' => 'JS bei Erfolg' , 'description' => 'Führe eigenen JavaScript-Code aus wenn das Formular erfolgreich übertragen wurde. Keine Script Tags benutzen!'], + 'js_on_error' => ['title' => 'JS bei Fehlern' , 'description' => 'Führe eigenen JavaScript-Code aus wenn das Formular nicht validiert werden kann. Keine Script Tags benutzen!'], + 'allowed_fields' => ['title' => 'Erlaubte Felder' , 'description' => 'Festlegen welche Felder gefiltert und gespeichert werden sollen. (Füge ein Feld per Zeile ein)'], + 'anonymize_ip' => ['title' => 'IP-Anonymisierung' , 'description' => 'IP-Adresse nicht speichern.', 'full' => 'Voll', 'partial' => 'Teilanonymisierung', 'disabled' => 'Deaktiviert'], + 'sanitize_data' => ['title' => 'Bereinigung der Formulardaten' , 'description' => 'Bereinige die Formulardaten und speichere das Ergebnis in der Datenbank', 'disabled' => 'deaktiviert', 'htmlspecialchars' => 'Benutzer htmlspecialchars'], + 'recaptcha_enabled' => ['title' => 'Aktiviere reCAPTCHA' , 'description' => 'reCAPTCHA-Widget in deinem Formular einfügen'], + 'recaptcha_theme' => ['title' => 'Theme' , 'description' => 'Farbschema des Widgets', 'light' => 'Hell' , 'dark' => 'Dunkel'], + 'recaptcha_type' => ['title' => 'Typ' , 'description' => 'reCAPTCHA Typ festlegen' , 'image' => 'Bild' , 'audio' => 'Audio'], + 'recaptcha_size' => [ + 'title' => 'Größe', + 'description' => 'Die Größe des Widgets', + 'normal' => 'Normal', + 'compact' => 'Kompakt', + 'invisible' => 'Unsichtbar', + ], + 'skip_database' => ['title' => 'Überspringe DB' , 'description' => 'Keine Speicherung der Formulardaten in der Datenbank. Nützlich wenn man Events mit einem eigenem Plugin nutzen möchte.'], + 'emails_date_format' => ['title' => 'Datum Formatierung in E-Mails', 'description' => 'Ändere die Datumformatierung die dann in E-Mails verwendet wird.'], + 'uploader_enable' => ['title' => 'Erlaube Uploads' , 'description' => 'Aktiviere Datei-Upload. Diese Option muss aufgrund der Sicherheitseinstellungen explizit aktiviert werden.'], + 'uploader_multi' => ['title' => 'Merhfachdateien' , 'description' => 'Erlaube Mehrfachdateien-Uploads'], + 'uploader_pholder' => ['title' => 'Platzhalter Text' , 'description' => 'Platzhalter Text der angezeigt wird so lange keine Datei hochgeladen wurde', 'default' => 'Click or drag files to upload'], + 'uploader_maxsize' => ['title' => 'Dateigröße Limitierung' , 'description' => 'Die maximale Dateigröße die hochgeladen werden kann in Megabytes'], + 'uploader_types' => ['title' => 'Erlaubte Datei-Typen' , 'description' => 'Erlaubte Dateiendungen oder ein Stern (*) für alle Typen (Füge eine Dateiendung per Zeile ein)'], + 'uploader_remFile' => ['title' => 'Popup Text Datei entfernen' , 'description' => 'Text Platzhalter für die Abfrage, wenn eine Datei vor dem Upload entfernt wird', 'default' => 'Are you sure ?'], + ] + ], + + 'settings' => [ + 'tabs' => ['general' => 'Allgemein', 'recaptcha' => 'reCAPTCHA', 'gdpr' => 'DSVGO'], + 'section_flash_messages' => 'Flash Nachrichten', + 'global_messages_success' => ['label' => 'Globale Erfolgsnachricht', 'comment' => '(Diese Einstellung kann aus der Komponente heraus überschrieben werden)', 'default' => 'Your form was successfully submitted'], + 'global_messages_errors' => ['label' => 'Globale Fehlernachricht' , 'comment' => '(Diese Einstellung kann aus der Komponente heraus überschrieben werden)', 'default' => 'There were errors with your submission'], + 'plugin_help' => 'Die Plugindokumentation erreichst Du über die GitHub repo:', + 'global_hide_button' => 'Navigationsobjekt vestecken', + 'global_hide_button_desc' => 'Praktisch, wenn Du eigene Events mit einem eigenem Plugin nutzen möchtest.', + 'section_recaptcha' => 'reCAPTCHA Einstellungen', + 'recaptcha_site_key' => 'Site key', + 'recaptcha_secret_key' => 'Secret key', + 'gdpr_help_title' => 'Information', + 'gdpr_help_comment' => 'Das neue EU-DSVGO Gesetz in Europa besagt dass die Einträge nicht mehr unendlich aufbewahrt werden dürfen. Diese müssen je nach nach Bedarf automatisiert gelöscht werden.', + 'gdpr_enable' => 'Aktiviere EU-DSVGO konforme Aufräumung', + 'gdpr_days' => 'Behalte die Einträge für die Anzahl an: X Tagen', + ], + + 'permissions' => [ + 'tab' => 'Magic Forms', + 'access_records' => 'Zugriff auf gespeicherte Formular-Einsendedaten', + 'access_exports' => 'Zugriff für das Exportieren der gespeicherten Formular-Einsendedaten', + 'access_settings' => 'Zugriff auf Modul-Konfiguration', + 'gdpr_cleanup' => 'Führe EU-DSVGO Aufräumung der Datenbank durch.', + ], + + 'mails' => [ + 'form_notification' => ['description' => 'Benachrichtung nach erfolgreicher Einsendung der Formulardaten.'], + 'form_autoresponse' => ['description' => 'Automatische Antwort nach erfolgreicher Einsendung der Formulardaten.'], + ], + + 'validation' => [ + 'recaptcha_error' => 'Kann das reCAPTCHA Feld nicht validieren.' + ], + + 'classes' => [ + 'GDPR' => [ + 'alert_gdpr_disabled' => 'EU-DSVGO Einstellungen sind deaktiviert.', + 'alert_invalid_gdpr' => 'Ungültige Einstellung des EU-DSVGO Aufräumvorgangs Intervals nach X Tagen.', + ] + ] + + ]; + +?> diff --git a/plugins/blakejones/magicforms/lang/en/lang.php b/plugins/blakejones/magicforms/lang/en/lang.php new file mode 100644 index 0000000..e5148b3 --- /dev/null +++ b/plugins/blakejones/magicforms/lang/en/lang.php @@ -0,0 +1,175 @@ + [ + 'name' => 'Magic Forms', + 'description' => 'Create easy AJAX forms', + ], + + 'menu' => [ + 'label' => 'Magic Forms', + 'records' => ['label' => 'Records'], + 'exports' => ['label' => 'Export'], + 'settings' => 'Configure plugin parameters', + ], + + 'controllers' => [ + 'records' => [ + 'title' => 'View Records', + 'view_title' => 'Record Details', + 'error' => 'Record not found', + 'deleted' => 'Record deleted successfully', + 'columns' => [ + 'id' => 'Record ID', + 'group' => 'Group', + 'ip' => 'IP Address', + 'form_data' => 'Stored Fields', + 'files' => 'Attached Files', + 'created_at' => 'Created', + ], + 'buttons' => [ + 'read' => 'Mark as Read', + 'unread' => 'Mark as Unread', + 'gdpr_clean' => 'GDPR Clean', + ], + 'alerts' => [ + 'gdpr_confirm' => "Are you sure you want to clean old records?\nThis action cannot be undone!", + 'gdpr_success' => 'GDPR cleanup was executed successfully', + 'gdpr_perms' => 'You don\'t have permission to this feature', + ], + ], + 'exports' => [ + 'title' => 'Export Records', + 'breadcrumb' => 'Export', + 'filter_section' => '1. Filter records', + 'filter_type' => 'Export all records', + 'filter_groups' => 'Groups', + 'filter_date_after' => 'Date after', + 'filter_date_before' => 'Date before', + 'options_section' => '2. Extra options', + 'options_metadata' => 'Include metadata', + 'options_metadata_com' => 'Export records with metadata (Record ID, group, IP, created date)', + 'options_deleted' => 'Include deleted records', + 'options_delimiter' => 'Use alternative delimiter', + 'options_delimiter_com' => 'Use semicolon as delimiter', + 'options_utf' => 'Encode in UTF8', + 'options_utf_com' => 'Encode your csv in UTF-8 to support non standard characters', + ], + ], + + 'components' => [ + 'generic_form' => [ + 'name' => 'Generic AJAX Form', + 'description' => 'By default renders a generic form; override component HTML with your custom fields.', + ], + 'upload_form' => [ + 'name' => 'Upload AJAX Form [BETA]', + 'description' => 'Shows how to implement file uploads on your form.', + ], + 'empty_form' => [ + 'name' => 'Empty AJAX Form', + 'description' => 'Create a empty template for your custom form; override component HTML.', + ], + 'shared' => [ + 'csrf_error' => 'Form session expired! Please refresh the page.', + 'recaptcha_warn' => 'Warning: reCAPTCHA is not properly configured. Please, goto Backend > Settings > CMS > Magic Forms and configure.', + 'group_validation' => 'Form Validation', + 'group_messages' => 'Flash Messages', + 'group_mail' => 'Notifications Settings', + 'group_mail_resp' => 'Auto-Response Settings', + 'group_settings' => 'More Settings', + 'group_security' => 'Security', + 'group_recaptcha' => 'reCAPTCHA Settings', + 'group_advanced' => 'Advanced Settings', + 'group_uploader' => 'Uploader Settings', + 'validation_req' => 'The property is required', + 'group' => ['title' => 'Group' , 'description' => 'Organize your forms with a custom group name. This option is useful when exporting data.'], + 'rules' => ['title' => 'Rules' , 'description' => 'Set your own rules using Laravel validation'], + 'rules_messages' => ['title' => 'Rules Messages' , 'description' => 'Use your own rules messages using Laravel validation'], + 'custom_attributes' => ['title' => 'Custom Attributes' , 'description' => 'Use your own custom attributes using Laravel validation'], + 'messages_success' => ['title' => 'Success' , 'description' => 'Message when the form is successfully submitted', 'default' => 'Your form was successfully submitted'], + 'messages_errors' => ['title' => 'Errors' , 'description' => 'Message when the form contains errors' , 'default' => 'There were errors with your submission'], + 'messages_partial' => ['title' => 'Use Custom Partial' , 'description' => 'Override flash messages with your custom partial inside your theme'], + 'mail_enabled' => ['title' => 'Send Notifications' , 'description' => 'Send mail notifications on every form submitted'], + 'mail_subject' => ['title' => 'Subject' , 'description' => 'Override default email subject'], + 'mail_recipients' => ['title' => 'Recipients' , 'description' => 'Specify email recipients. Use email addresses as keys and names as the values.'], + 'mail_bcc' => ['title' => 'BCC' , 'description' => 'Send blind carbon copy to email recipients (add one address per line)'], + 'mail_replyto' => ['title' => 'ReplyTo Email Field', 'description' => 'Form field containing the email address of sender to be used as "ReplyTo"'], + 'mail_template' => ['title' => 'Mail Template' , 'description' => 'Use custom mail template. Specify template code like "blakejones.magicforms::mail.notification" (found on Settings, Mail templates). Leave empty to use default.'], + 'mail_uploads' => ['title' => 'Send Uploads' , 'description' => 'Send uploads as attachments'], + 'mail_resp_enabled' => ['title' => 'Send Auto-Response' , 'description' => 'Send an auto-response email to the person submitting the form'], + 'mail_resp_field' => ['title' => 'Email Field' , 'description' => 'Form field containing the email address of the recipient of auto-response'], + 'mail_resp_from' => ['title' => 'Sender Address' , 'description' => 'Email address of auto-response email sender (e.g. noreply@yourcompany.com)'], + 'mail_resp_subject' => ['title' => 'Subject' , 'description' => 'Override default email subject'], + 'reset_form' => ['title' => 'Reset Form' , 'description' => 'Reset form after successfully submit'], + 'redirect' => ['title' => 'Redirect on Success', 'description' => 'Redirect to URL on successfully submit.'], + 'inline_errors' => ['title' => 'Inline errors' , 'description' => 'Display inline errors. This requires extra code, check documentation for more info.', 'disabled' => 'Disabled', 'display' => 'Display errors', 'variable' => 'JS variable'], + 'js_on_success' => ['title' => 'JS on Success' , 'description' => 'Execute custom JavaScript code when the form was successfully submitted. Don\'t use script tags.'], + 'js_on_error' => ['title' => 'JS on Error' , 'description' => 'Execute custom JavaScript code when the form doesn\'t validate. Don\'t use script tags.'], + 'allowed_fields' => ['title' => 'Allowed Fields' , 'description' => 'Specify which fields should be filtered and stored (add one field name per line)'], + 'anonymize_ip' => ['title' => 'Anonymize IP' , 'description' => 'Don\'t store IP address', 'full' => 'Full', 'partial' => 'Partial', 'disabled' => 'Disabled'], + 'sanitize_data' => ['title' => 'Sanitize form data' , 'description' => 'Sanitize form data and save result on database', 'disabled' => 'Disabled', 'htmlspecialchars' => 'Use htmlspecialchars'], + 'recaptcha_enabled' => ['title' => 'Enable reCAPTCHA' , 'description' => 'Insert the reCAPTCHA widget on your form'], + 'recaptcha_theme' => ['title' => 'Theme' , 'description' => 'The color theme of the widget', 'light' => 'Light' , 'dark' => 'Dark'], + 'recaptcha_type' => ['title' => 'Type' , 'description' => 'The type of CAPTCHA to serve' , 'image' => 'Image' , 'audio' => 'Audio'], + 'recaptcha_size' => [ + 'title' => 'Size', + 'description' => 'The size of the widget', + 'normal' => 'Normal', + 'compact' => 'Compact', + 'invisible' => 'Invisible', + ], + 'skip_database' => ['title' => 'Skip DB' , 'description' => 'Don\'t store this form on database. Useful if you want to use events with your custom plugin.'], + 'emails_date_format' => ['title' => 'Date format on emails', 'description' => 'Set custom format for dates used on emails subjects.'], + 'uploader_enable' => ['title' => 'Allow uploads' , 'description' => 'Enable files uploading. You need to explicitly enable this option as a security measure.'], + 'uploader_multi' => ['title' => 'Multiple files' , 'description' => 'Allow multipe files uploads'], + 'uploader_pholder' => ['title' => 'Placeholder text' , 'description' => 'Wording to display when no file is uploaded', 'default' => 'Click or drag files to upload'], + 'uploader_maxsize' => ['title' => 'File size limit' , 'description' => 'The maximum file size that can be uploaded in megabytes'], + 'uploader_types' => ['title' => 'Allowed file types' , 'description' => 'Allowed file extensions or star (*) for all types (add one extension per line)'], + 'uploader_remFile' => ['title' => 'Remove Popup text' , 'description' => 'Wording to display in the popup when you remove file', 'default' => 'Are you sure ?'], + ], + ], + + 'settings' => [ + 'tabs' => ['general' => 'General', 'recaptcha' => 'reCAPTCHA', 'gdpr' => 'GDPR'], + 'section_flash_messages' => 'Flash Messages', + 'global_messages_success' => ['label' => 'Global Success Message', 'comment' => '(This setting can be overridden from the component)', 'default' => 'Your form was successfully submitted'], + 'global_messages_errors' => ['label' => 'Global Errors Message' , 'comment' => '(This setting can be overridden from the component)', 'default' => 'There were errors with your submission'], + 'plugin_help' => 'You can access plugin documentation at GitHub repo:', + 'global_hide_button' => 'Hide navigation item', + 'global_hide_button_desc' => 'Useful if you want to use events with your custom plugin.', + 'section_recaptcha' => 'reCAPTCHA Settings', + 'recaptcha_site_key' => 'Site key', + 'recaptcha_secret_key' => 'Secret key', + 'gdpr_help_title' => 'Information', + 'gdpr_help_comment' => 'New GDPR law in Europe, you can\'t keep records undefinitely, need to clear them after a certain period of time depending on your needs', + 'gdpr_enable' => 'Enable GDPR', + 'gdpr_days' => 'Keep records for a maximum of X days', + ], + + 'permissions' => [ + 'tab' => 'Magic Forms', + 'access_records' => 'Access stored forms data', + 'access_exports' => 'Access to export stored data', + 'access_settings' => 'Access module configuration', + 'gdpr_cleanup' => 'Perform GDPR database cleanup', + ], + + 'mails' => [ + 'form_notification' => ['description' => 'Notify when a form is submitted'], + 'form_autoresponse' => ['description' => 'Auto-Response when a form is submitted'], + ], + + 'validation' => [ + 'recaptcha_error' => 'Cannot validate reCAPTCHA field', + ], + + 'classes' => [ + 'GDPR' => [ + 'alert_gdpr_disabled' => 'GDPR options are disabled', + 'alert_invalid_gdpr' => 'Invalid GDPR days setting value', + ], + ], + + ]; diff --git a/plugins/blakejones/magicforms/lang/fr/lang.php b/plugins/blakejones/magicforms/lang/fr/lang.php new file mode 100644 index 0000000..65ef26a --- /dev/null +++ b/plugins/blakejones/magicforms/lang/fr/lang.php @@ -0,0 +1,153 @@ + [ + 'name' => 'Magic Forms', + 'description' => 'Créer des formulaires AJAX facilement' + ], + 'menu' => [ + 'label' => 'Magic Forms', + 'records' => ['label' => 'Enregistrements'], + 'exports' => ['label' => 'Export'], + 'settings' => 'Configurer kes parameters du plugin', + ], + 'controllers' => [ + 'records' => [ + 'title' => 'Voir les enregistrements', + 'view_title' => 'Détails de l\'enregistrement', + 'error' => 'Enregistrement non trouvé', + 'deleted' => 'Enregistrement supprimé avec succès', + 'columns' => [ + 'id' => 'Enregistrement N°', + 'group' => 'Groupe', + 'ip' => 'Adresse IP', + 'form_data' => 'Champs stockés', + 'files' => 'Fichiers attachés', + 'created_at' => 'Créer le', + ], + 'buttons' => [ + 'read' => 'Marquer comme lu', + 'unread' => 'Marquer comme non lu', + 'gdpr_clean' => 'Nettoyage RGPD', + ], + 'alerts' => [ + 'gdpr_confirm' => "Êtes-vous sûr de vouloir nettoyer les anciens enregistrements?\nCette action ne peut pas être annulée!", + 'gdpr_success' => 'Le nettoyage RGPD a été exécuté avec succès', + 'gdpr_perms' => 'Vous n\'avez pas l\'autorisation pour utiliser cette fonctionnalité', + ], + ], + 'exports' => [ + 'title' => 'Exporter les enregistrements', + 'breadcrumb' => 'Exporter', + 'filter_section' => '1. Filtrer les enregistrements', + 'filter_type' => 'Exporter tous les enregistrements', + 'filter_groups' => 'Groupes', + 'filter_date_after' => 'Date de début', + 'filter_date_before' => 'Date de fin', + 'options_section' => '2. Options supplémentaires', + 'options_metadata' => 'Inclure les metadonnées', + 'options_metadata_com' => 'Exporter les enregistrements avec les metadonnées (n°, groupe, IP, date de création)', + 'options_deleted' => 'Inclure les enregistrements supprimés', + ], + ], + 'components' => [ + 'generic_form' => [ + 'name' => 'Formulaire générique AJAX', + 'description' => 'Rendu d\'un formulaire générique; remplacer le composant HTML par vos propres champs personnalisés.', + ], + 'upload_form' => [ + 'name' => 'Téléchargements AJAX [BETA]', + 'description' => 'Montre comment implémenter des téléchargements de fichiers sur votre formulaire.', + ], + 'empty_form' => [ + 'name' => 'Formulaire AJAX vide', + 'description' => 'Créer un modèle vide pour votre formulaire personnalisé; remplacer le composant HTML.', + ], + 'shared' => [ + 'csrf_error' => 'La session du formulaire a expirée ! Veuillez actualiser la page.', + 'recaptcha_warn' => 'Avertissement: reCAPTCHA n\'est pas correctement configuré. Àllez dans Backend > Paramètres > CMS > Magic Forms et configurez svp.', + 'group_validation' => 'Validation du formulaire', + 'group_messages' => 'Messages Flash ', + 'group_mail' => 'Notifications', + 'group_mail_resp' => 'Réponse automatique', + 'group_settings' => 'Plus de réglages', + 'group_security' => 'Securité', + 'group_recaptcha' => 'reCAPTCHA', + 'group_uploader' => 'Transfert de fichiers', + 'validation_req' => 'La propriété est requise', + 'group' => ['title' => 'Groupe' , 'description' => 'Organisez vos formulaires avec un nom de groupe personnalisé. Cette option est utile lorsque vous exportez des données.'], + 'rules' => ['title' => 'Règles' , 'description' => 'Définissez vos propres règles en utilisant la validation de Laravel'], + 'rules_messages' => ['title' => 'Messages de règles' , 'description' => 'Utilisez vos propres messages de règles en utilisant la validation de Laravel'], + 'messages_success' => ['title' => 'Succès' , 'description' => 'Message lorsque le formulaire est soumis avec succès' , 'default' => 'Votre formulaire a été envoyé avec succès' ], + 'messages_errors' => ['title' => 'Erreurs' , 'description' => 'Message lorsque le formulaire contient des erreurs' , 'default' => 'Il y a eu des erreurs dans votre formulaire'], + 'messages_partial' => ['title' => 'Utiliser un modèle partiel personnalisé', 'description' => 'Modifier le message flash avec un modèle partiel personnalisé de votre thème'], + 'mail_enabled' => ['title' => 'Envoyer des notifications' , 'description' => 'Envoyer des notifications par mail sur chaque formulaire envoyé'], + 'mail_subject' => ['title' => 'Sujet' , 'description' => 'Remplacer le sujet par défaut du courrier électronique'], + 'mail_recipients' => ['title' => 'Destinataires' , 'description' => 'Spécifiez les destinataires des e-mails. Utilisez les adresses e-mail comme clés et les noms comme valeurs.'], + 'mail_bcc' => ['title' => 'CCI' , 'description' => 'Envoyer une copie carbone invisible aux destinataires des e-mails (ajouter une adresse par ligne)'], + 'mail_replyto' => ['title' => 'Champ du email de réponse (ReplyTo)' , 'description' => 'Champ de formulaire contenant l\'adresse e-mail de l\'expéditeur à utiliser comme "ReplyTo"'], + 'mail_uploads' => ['title' => 'Envoyer les téléchargements' , 'description' => 'Envoi des fichiers téléchargés en pièce jointe'], + 'mail_template' => ['title' => 'Modèle e-mail' , 'description' => 'Utiliser un modèle e-mail personnalisé. Spécifiez un code de modèle tel que "blakejones.magicforms::mail.notification" (situé dans Paramètres, Modèles des e-mails). Laissez vide pour utiliser les paramètres par défaut.'], + 'mail_uploads' => ['title' => 'Envoyer les téléchargements' , 'description' => 'Envoyer les téléchargements en pièces jointes'], + 'mail_resp_enabled' => ['title' => 'Envoyer une réponse automatique' , 'description' => 'Envoyer un e-mail d\'auto-réponse à la personne qui soumet le formulaire'], + 'mail_resp_field' => ['title' => 'Champ email' , 'description' => 'Champ de formulaire contenant l\'adresse e-mail du destinataire de réponse automatique '], + 'mail_resp_from' => ['title' => 'Adresse de l\'expéditeur' , 'description' => 'Adresse e-mail de l\'expéditeur du courrier électronique de réponse automatique (par exemple nepasrepondre@votreentreprise.com)'], + 'mail_resp_subject' => ['title' => 'Sujet' , 'description' => 'Remplacer le sujet par défaut du courrier électronique'], + 'reset_form' => ['title' => 'Réinitialiser le formulaire' , 'description' => 'Réinitialiser le formulaire après l\'envoi réussi'], + 'redirect' => ['title' => 'Redirection envoi réussi' , 'description' => 'Rediriger vers une URL spécifique lors de l\'envoi réussi. Remarque: doit être une URL valide commençant par http ou https ou la redirection sera ignorée.'], + 'inline_errors' => ['title' => 'Erreurs sur la même ligne' , 'description' => 'Afficher les erreurs sur la même ligne. Cela nécéssite du code supplémentaire, consultez la documentation pour plus d\'informations. ', 'disabled' => 'Désactivé', 'display' => 'Afficher les erreurs', 'variable' => 'Variable Javascript'], + 'js_on_success' => ['title' => 'JS au succès' , 'description' => 'Exécutez du code JavaScript personnalisé lorsque le formulaire a été soumis avec succès. Ne pas utiliser les balises script'], + 'js_on_error' => ['title' => 'JS si erreur' , 'description' => 'Exécutez du code JavaScript personnalisé lorsque le formulaire ne se valide pas. Ne pas utiliser les balises script.'], + 'allowed_fields' => ['title' => 'Allowed Fields' , 'description' => 'Spécifiez quels champs doivent être filtrés et stockés (ajoutez un nom de champ par ligne).'], + 'anonymize_ip' => ['title' => 'Anonymiser IP' , 'description' => 'Ne pas enregistrer les adresses IP', 'full' => 'Complet', 'partial' => 'Partiel', 'disabled' => 'Désactivé'], + 'sanitize_data' => ['title' => 'Désinfecter les données de formulaire' , 'description' => 'Désinfectez les données de formulaire et enregistrez le résultat dans la base de données', 'disabled' => 'Désactivé', 'htmlspecialchars' => 'Utilisez htmlspecialchars'], + 'recaptcha_enabled' => ['title' => 'Activer reCAPTCHA' , 'description' => 'Insère le widget reCAPTCHA sur votre formulaire'], + 'recaptcha_theme' => ['title' => 'Thème' , 'description' => 'Le thème de couleur du widget' , 'light' => 'Léger' , 'dark' => 'Sombre'], + 'recaptcha_type' => ['title' => 'Type' , 'description' => 'Le type de CAPTCHA à servir' , 'image' => 'Image' , 'audio' => 'Audio'], + 'recaptcha_size' => ['title' => 'Taille' , 'description' => 'La taille du widget' , 'normal' => 'Normale', 'compact' => 'Compacte'], + 'skip_database' => ['title' => 'Ignore la BDD' , 'description' => 'Ne pas stocker ce formulaire dans la base de données. Utile si vous souhaitez utiliser des évènements avec votre plugin personnalisé.'], + 'uploader_enable' => ['title' => 'Autoriser les téléchargements' , 'description' => 'Activer le téléchargement des fichiers. Vous devez activer cette option explicitement comme mesure de sécurité.'], + 'uploader_multi' => ['title' => 'Fichiers multiples' , 'description' => 'Autoriser plusieurs téléchargements de fichiers'], + 'uploader_pholder' => ['title' => 'Texte de remplacement' , 'description' => 'Texte à afficher quand aucun fichier n\'est téléchargé', 'default' => 'Cliquez pour choisir ou faites glisser les fichiers à télécharger'], + 'uploader_maxsize' => ['title' => 'Limite de taille de fichier' , 'description' => 'Taille maximale du fichier pouvant être téléchargée en mégaoctets'], + 'uploader_types' => ['title' => 'Types de fichiers autorisés' , 'description' => 'Extensions de fichiers autorisées ou étoile (*) pour tous les types (ajoutez une extension par ligne)'], + 'uploader_remFile' => ['title' => 'Texte de Suppression' , 'description' => 'Texte à afficher dans la popup lors de la suppression d\'un fichier', 'default' => 'Êtes-vous sûr ?'], + ] + ], + 'settings' => [ + 'tabs' => ['general' => 'Général', 'recaptcha' => 'reCAPTCHA', 'gdpr' => 'RGPD'], + 'section_flash_messages' => 'Messages Flash', + 'global_messages_success' => ['label' => 'Message de réussite', 'comment' => '(Ce paramètre peut être remplacé par le composant)', 'default' => 'Votre formulaire a été envoyé avec succès'], + 'global_messages_errors' => ['label' => 'Global Errors Message' , 'comment' => '(Ce paramètre peut être remplacé par le composant)', 'default' => 'Il y a eu des erreurs dans votre formulaire'], + 'plugin_help' => 'Vous pouvez accéder à la documentation du plugin sur GitHub :', + 'global_hide_button' => 'Masquer l\'élément de navigation', + 'global_hide_button_desc' => 'Utile si vous souhaitez utiliser des événements avec votre plugin personnalisé.', + 'section_recaptcha' => 'Paramètres reCAPTCHA', + 'recaptcha_site_key' => 'Clé du site', + 'recaptcha_secret_key' => 'Clé secrète', + 'gdpr_help_title' => 'Information', + 'gdpr_help_comment' => 'Nouvelle loi RGPD/GDPR en Europe : vous ne pouvez pas conserver les enregistrements indéfiniment, vous devez les effacer au bout d\'un certain temps en fonction de vos besoins.', + 'gdpr_enable' => 'Activer RGPD', + 'gdpr_days' => 'Garder les enregistrements pour un maximum de X jours', + ], + 'permissions' => [ + 'tab' => 'Magic Forms', + 'access_records' => 'Accéder aux données des formulaires stockés', + 'access_exports' => 'Accès aux exports des formulaires stockés', + 'access_settings' => 'Accès à la configuration du module', + 'gdpr_cleanup' => 'Accès au nettoyage de la base de donnée RGPD', + ], + 'mails' => [ + 'form_notification' => ['description' => 'Notifier quand un formulaire est envoyé'], + 'form_autoresponse' => ['description' => 'Auto-Réponse lorsqu\'un formulaire est envoyé'], + ], + 'validation' => [ + 'recaptcha_error' => 'Impossible de valider le champ reCAPTCHA' + ], + 'classes' => [ + 'GDPR' => [ + 'alert_gdpr_disabled' => 'LEs options RGPD sont désactivés', + 'alert_invalid_gdpr' => 'Valeur de réglage des jours RGPD invalide', + ] + ] + ]; +?> diff --git a/plugins/blakejones/magicforms/lang/nl/lang.php b/plugins/blakejones/magicforms/lang/nl/lang.php new file mode 100644 index 0000000..ff500c2 --- /dev/null +++ b/plugins/blakejones/magicforms/lang/nl/lang.php @@ -0,0 +1,175 @@ + [ + 'name' => 'Magic Forms', + 'description' => 'Eenvoudige AJAX-formulieren maken', + ], + + 'menu' => [ + 'label' => 'Magic Forms', + 'records' => ['label' => 'Records'], + 'exports' => ['label' => 'Exporteren'], + 'settings' => 'Configureer plugin parameters', + ], + + 'controllers' => [ + 'records' => [ + 'title' => 'Bekijk Records', + 'view_title' => 'Record Details', + 'error' => 'Record niet gevonden', + 'deleted' => 'Record succesvol verwijderd', + 'columns' => [ + 'id' => 'Record ID', + 'group' => 'Groep', + 'ip' => 'IP adres', + 'form_data' => 'Opgeslagen velden', + 'files' => 'Bijlagen', + 'created_at' => 'Gemaakt', + ], + 'buttons' => [ + 'read' => 'Als gelezen markeren', + 'unread' => 'Als ongelezen markeren', + 'gdpr_clean' => 'AVG opschoning uitvoeren', + ], + 'alerts' => [ + 'gdpr_confirm' => "Weet u zeker dat u oude gegevens wilt wissen?\nDeze actie kan niet ongedaan worden gemaakt!", + 'gdpr_success' => 'AVG-opschoning is met succes uitgevoerd', + 'gdpr_perms' => 'Je hebt geen toestemming voor deze functie.', + ], + ], + 'exports' => [ + 'title' => 'Exporteer Records', + 'breadcrumb' => 'Exporteren', + 'filter_section' => '1. Filter records', + 'filter_type' => 'Exporteer alle records', + 'filter_groups' => 'Groepen', + 'filter_date_after' => 'Vanaf datum', + 'filter_date_before' => 'Tot datum', + 'options_section' => '2. Extra opties', + 'options_metadata' => 'Metagegevens meenemen', + 'options_metadata_com' => 'Exporteer records met metadata (Record ID, groep, IP, aanmaakdatum)', + 'options_deleted' => 'Verwijderde records meenemen', + 'options_delimiter' => 'Use alternative delimiter', + 'options_delimiter_com' => 'Gebruik alternatief scheidingsteken', + 'options_utf' => 'Encoderen in UTF-8', + 'options_utf_com' => 'Codeer uw csv in UTF-8 om niet-standaard tekens te ondersteunen', + ], + ], + + 'components' => [ + 'generic_form' => [ + 'name' => 'Algemeen AJAX Formulier', + 'description' => 'Toont standaard een algemeen formulier; overschrijf component HTML met uw aangepaste velden.', + ], + 'upload_form' => [ + 'name' => 'Upload AJAX Formulier [BETA]', + 'description' => 'Laat zien hoe je bestandsuploads kunt implementeren in je formulier.', + ], + 'empty_form' => [ + 'name' => 'Leeg AJAX Formulier', + 'description' => 'Maak een leeg sjabloon voor uw aangepaste formulier; overschrijf component HTML.', + ], + 'shared' => [ + 'csrf_error' => 'Formulier sessie verlopen! Vernieuw de pagina.', + 'recaptcha_warn' => 'Waarschuwing: reCAPTCHA is niet goed geconfigureerd. Ga aub naar Backend > Instellingen > CMS > Magic Forms en configureer.', + 'group_validation' => 'Formulier Validatie', + 'group_messages' => 'Flash Berichten', + 'group_mail' => 'Notificatie Instellingen', + 'group_mail_resp' => 'Auto-Response Instellingen', + 'group_settings' => 'Meer Instellingen', + 'group_security' => 'Beveiliging', + 'group_recaptcha' => 'reCAPTCHA Instellingen', + 'group_advanced' => 'Geavanceerde Instellingen', + 'group_uploader' => 'Uploader Instellingen', + 'validation_req' => 'De property is verplicht', + 'group' => ['title' => 'Groep' , 'description' => 'Organiseer uw formulieren met een aangepaste groepsnaam. Deze optie is handig bij het exporteren van gegevens.'], + 'rules' => ['title' => 'Regels' , 'description' => 'Stel je eigen regels in met Laravel validatie'], + 'rules_messages' => ['title' => 'Regels Berichten' , 'description' => 'Gebruik uw eigen regels berichten met behulp van Laravel validatie'], + 'custom_attributes' => ['title' => 'Aangepaste attributen' , 'description' => 'Gebruik je eigen aangepaste attributen met Laravel validatie'], + 'messages_success' => ['title' => 'Succes' , 'description' => 'Bericht wanneer het formulier succesvol is verzonden', 'default' => 'Uw formulier is succesvol verzonden'], + 'messages_errors' => ['title' => 'Fouten' , 'description' => 'Bericht wanneer het formulier fouten bevat' , 'default' => 'Er zijn fouten opgetreden bij uw inzending'], + 'messages_partial' => ['title' => 'Gebruik Aangepaste Partial' , 'description' => 'Overschrijf flashberichten met uw eigen partials in uw thema'], + 'mail_enabled' => ['title' => 'Stuur Notificaties' , 'description' => 'Stuur e-mailmeldingen over elk ingediend formulier'], + 'mail_subject' => ['title' => 'Onderwerp' , 'description' => 'Standaard e-mail onderwerp overschrijven'], + 'mail_recipients' => ['title' => 'Ontvangers' , 'description' => 'Geef e-mailontvangers op. Gebruik e-mailadressen als sleutels en namen als waarden.'], + 'mail_bcc' => ['title' => 'BCC' , 'description' => 'Stuur een BBC naar de ontvangers (één adres per regel)'], + 'mail_replyto' => ['title' => 'ReplyTo E-mail Veld' , 'description' => 'Formulierveld met het e-mailadres van de afzender dat moet worden gebruikt als "ReplyTo"'], + 'mail_template' => ['title' => 'E-mail sjabloon' , 'description' => 'Gebruik een aangepast e-mail sjabloon. Specificeer sjabloon code zoals "blakejones.magicforms::mail.notification" (te vinden onder Instellingen, E-mail sjablonen). Laat leeg om de standaard te gebruiken.'], + 'mail_uploads' => ['title' => 'Verstuur uploads' , 'description' => 'Verstuur uploads als bijlagen'], + 'mail_resp_enabled' => ['title' => 'Stuur automatisch antwoord' , 'description' => 'Stuur een automatische e-mail naar de persoon die het formulier heeft ingediend'], + 'mail_resp_field' => ['title' => 'E-mail Veld' , 'description' => 'Formulierveld met het e-mailadres van de ontvanger van het automatische antwoord'], + 'mail_resp_from' => ['title' => 'Verzender adres' , 'description' => 'E-mailadres van de afzender van de auto-response e-mail (bv. noreply@yourcompany.com)'], + 'mail_resp_subject' => ['title' => 'Onderwerp' , 'description' => 'Standaard e-mail onderwerp overschrijven'], + 'reset_form' => ['title' => 'Reset Form' , 'description' => 'Formulier terugzetten na succesvol verzenden'], + 'redirect' => ['title' => 'Redirect on Success' , 'description' => 'Doorverwijzen bij succes'], + 'inline_errors' => ['title' => 'Inline fouten' , 'description' => 'Toon inline fouten. Dit heeft extra code nodig, zie de documentatie voor meer info info.', 'disabled' => 'Uitgeschakeld', 'display' => 'Toon fouten', 'variable' => 'JS variabele'], + 'js_on_success' => ['title' => 'JS bij Succes' , 'description' => 'Voer aangepaste JavaScript code uit wanneer het formulier succesvol is verstuurd. Gebruik geen script tags.'], + 'js_on_error' => ['title' => 'JS bij Fout' , 'description' => 'Voer aangepaste JavaScript code uit als het formulier niet valideert. Gebruik geen script tags.'], + 'allowed_fields' => ['title' => 'Toegestane Velden' , 'description' => 'Geef aan welke velden moeten worden gefilterd en opgeslagen (voeg één veldnaam per regel toe)'], + 'anonymize_ip' => ['title' => 'Anonimiseer IP' , 'description' => 'Sla het IP adres niet op', 'full' => 'Volledig', 'partial' => 'Gedeeltelijk', 'disabled' => 'Uitgeschakeld'], + 'sanitize_data' => ['title' => 'Sanitize form data' , 'description' => 'Formuliergegevens zuiveren', 'disabled' => 'Uitgeschakeld', 'htmlspecialchars' => 'Gebruik htmlspecialchars'], + 'recaptcha_enabled' => ['title' => 'Schakel reCAPTCHA in' , 'description' => 'Plaats de reCAPTCHA widget op uw formulierm'], + 'recaptcha_theme' => ['title' => 'Thema' , 'description' => 'Het kleurenthema van de widget', 'light' => 'Licht' , 'dark' => 'Donker'], + 'recaptcha_type' => ['title' => 'Type' , 'description' => 'Het type CAPTCHA dat moet worden gebruikt' , 'image' => 'Afbeelding' , 'audio' => 'Audio'], + 'recaptcha_size' => [ + 'title' => 'Grootte', + 'description' => 'De grootte van de widget', + 'normal' => 'Normaal', + 'compact' => 'Compact', + 'invisible' => 'Onzichtbaar', + ], + 'skip_database' => ['title' => 'Sla database over' , 'description' => 'Sla dit formulier niet op in de database. Handig als je gebeurtenissen wilt gebruiken met je aangepaste plugin.'], + 'emails_date_format' => ['title' => 'Datumnotatie op e-mails' , 'description' => 'Aangepaste notatie instellen voor datums in e-mailonderwerpen.'], + 'uploader_enable' => ['title' => 'Sta uploads toe' , 'description' => 'Bestanden uploaden inschakelen. U moet deze optie expliciet inschakelen als veiligheidsmaatregel.'], + 'uploader_multi' => ['title' => 'Meerdere bestanden' , 'description' => 'Sta uploaden van meerdere bestanden toe'], + 'uploader_pholder' => ['title' => 'Placeholder tekst' , 'description' => 'Formulering die wordt weergegeven wanneer geen bestand is geüpload', 'default' => 'Klik of sleep bestanden om te uploaden'], + 'uploader_maxsize' => ['title' => 'Limiet bestandsgrootte' , 'description' => 'De maximale bestandsgrootte die kan worden geüpload in megabytes'], + 'uploader_types' => ['title' => 'Toegestane bestandstypen', 'description' => 'Toegestane bestandsextensies of sterretje (*) voor alle types (één extensie per regel)'], + 'uploader_remFile' => ['title' => 'Popup tekst verwijderen' , 'description' => 'Tekst die wordt weergegeven in de popup wanneer u een bestand verwijdert', 'default' => 'Weet je het zeker?'], + ], + ], + + 'settings' => [ + 'tabs' => ['general' => 'Algemeen', 'recaptcha' => 'reCAPTCHA', 'gdpr' => 'AVG'], + 'section_flash_messages' => 'Flash Berichten', + 'global_messages_success' => ['label' => 'Globaal succesbericht', 'comment' => '((Deze instelling kan worden overschreven vanuit het component))', 'default' => 'Uw formulier is succesvol verzonden'], + 'global_messages_errors' => ['label' => 'Globaal foutbericht' , 'comment' => '((Deze instelling kan worden overschreven vanuit het component))', 'default' => 'Er zijn fouten opgetreden bij uw inzending'], + 'plugin_help' => 'U kunt de plugin documentatie vinden op de GitHub repo:', + 'global_hide_button' => 'Verberg menu item', + 'global_hide_button_desc' => 'Handig als je events wilt gebruiken met je aangepaste plugin.', + 'section_recaptcha' => 'reCAPTCHA Instellingen', + 'recaptcha_site_key' => 'Site key', + 'recaptcha_secret_key' => 'Secret key', + 'gdpr_help_title' => 'Informatie', + 'gdpr_help_comment' => 'Voor AVG-wetgeving in Europa, u kunt records niet onbeperkt bewaren, u moet ze wissen na een bepaalde periode, afhankelijk van uw behoeften', + 'gdpr_enable' => 'Schakel AVG in', + 'gdpr_days' => 'Bewaar de gegevens maximaal X dagen', + ], + + 'permissions' => [ + 'tab' => 'Magic Forms', + 'access_records' => 'Toegang tot opgeslagen formuliergegevens', + 'access_exports' => 'Toegang tot export van opgeslagen gegevens', + 'access_settings' => 'Toegang tot instellingen', + 'gdpr_cleanup' => 'AVG opschoning uitvoeren', + ], + + 'mails' => [ + 'form_notification' => ['description' => 'Notificeer wanneer een formulier wordt verzonden'], + 'form_autoresponse' => ['description' => 'Automatisch antwoord wanneer een formulier wordt verzonden'], + ], + + 'validation' => [ + 'recaptcha_error' => 'Kan reCAPTCHA-veld niet valideren', + ], + + 'classes' => [ + 'GDPR' => [ + 'alert_gdpr_disabled' => 'AVG opties zijn uitgeschakeld', + 'alert_invalid_gdpr' => 'Ongeldige AVG instellingswaarde voor dagen', + ], + ], + + ]; diff --git a/plugins/blakejones/magicforms/lang/pt-br/lang.php b/plugins/blakejones/magicforms/lang/pt-br/lang.php new file mode 100644 index 0000000..66c4042 --- /dev/null +++ b/plugins/blakejones/magicforms/lang/pt-br/lang.php @@ -0,0 +1,116 @@ + [ + 'name' => 'Magic Forms', + 'description' => 'Crie formulários fácilmente com AJAX' + ], + 'menu' => [ + 'label' => 'Formulários Mágico', + 'records' => ['label' => 'Registros'], + 'exports' => ['label' => 'Exportar'], + 'settings' => 'Configurar parâmetros do plug-in', + ], + 'controllers' => [ + 'records' => [ + 'title' => 'Ver registos', + 'view_title' => 'Detalhes do registro', + 'error' => 'Registro não encontrado', + 'deleted' => 'Registro excluído com sucesso', + 'columns' => [ + 'id' => 'ID do registro', + 'group' => 'Grupo', + 'ip' => 'Endereço IP', + 'form_data' => 'Campos armazenados', + 'files' => 'Arquivos anexados', + 'created_at' => 'Criado', + ], + ], + 'exports' => [ + 'title' => 'Exportar registros', + 'breadcrumb' => 'Exportar', + 'filter_section' => '1. Filtrar registos', + 'filter_type' => 'Exportar todos os registros', + 'filter_groups' => 'Grupos', + 'filter_date_after' => 'Data após', + 'filter_date_before' => 'Data anterior', + 'options_section' => '2. Opções extras', + 'options_metadata' => 'Incluir metadados', + 'options_metadata_com' => 'Exportar registros com metadados (ID de registro, grupo, IP, data criação)', + 'options_deleted' => 'Incluir registros excluídos', + ], + ], + 'components' => [ + 'generic_form' => [ + 'name' => 'Formulário AJAX Genérico', + 'description' => 'Por padrão renderiza um formulário genérico; Substitua o componente HTML com seus campos personalizados.', + ], + 'upload_form' => [ + 'name' => 'formulário upload AJAX [BETA]', + 'description' => 'Mostra como implementar uploads de arquivos no formulário.', + ], + 'empty_form' => [ + 'name' => 'Formulário AJAX vazio', + 'description' => 'Crie um modelo vazio para seu formulário personalizado; Substituir o componente HTML.', + ], + 'shared' => [ + 'csrf_error' => 'A sessão do formulário expirou! Atualize a página.', + 'recaptcha_warn' => 'Aviso: reCAPTCHA não está configurado corretamente. Por favor, vá para Back-end> Configurações> CMS> Magic Forms e configure.', + 'group_validation' => 'Validação de formulários', + 'group_messages' => 'Mensagens Flash', + 'group_mail' => 'Configurações de Notificações', + 'group_mail_resp' => 'Configurações de Resposta Automática', + 'group_settings' => 'Mais configurações', + 'group_security' => 'Segurança', + 'group_recaptcha' => 'Configurações de reCAPTCHA', + 'group_uploader' => 'Configurações do Uploader', + 'validation_req' => 'A propriedade é obrigatória', + 'group' => ['title' => 'Grupo' , 'description' => 'Organize seus formulários com um nome de grupo personalizado. Esta opção é útil ao exportar dados.'], + 'rules' => ['title' => 'Regras' , 'description' => 'Defina suas próprias regras usando a validação Laravel'], + 'rules_messages' => ['title' => 'Mensagens de Regras' , 'description' => 'Use suas próprias mensagens de regras usando a validação do Laravel'], + 'messages_success' => ['title' => 'Sucesso' , 'description' => 'Mensagem quando o formulário é enviado com sucesso', 'default '=>' Seu formulário foi enviado com sucesso'], + 'messages_errors' => ['title' => 'Erros' , 'description' => 'Mensagem quando o formulário contém erros', 'default' => 'Ocorreu um erro no envio'], + 'mail_enabled' => ['title' => 'Enviar Notificações' , 'description' => 'Enviar notificações por email em todos os formulários enviados'], + 'mail_subject' => ['title' => 'Assunto' , 'description' => 'Substitui o assunto de email padrão'], + 'mail_recipients' => ['title' => 'Destinatários' , 'description' => 'Especifique os destinatários de e-mail. Use endereços de e-mail como chaves e nomes como valores.'], + 'mail_uploads' => ['title' => 'Enviar Uploads' , 'description' => 'Enviar uploads como anexos'], + 'mail_resp_enabled' => ['title' => 'Enviar Resposta Automática' , 'description' => 'Enviar um email de resposta automática para a pessoa que envia o formulário'], + 'mail_resp_field' => ['title' => 'Campo de Email' , 'description' => 'Campo de formulário que contém o endereço de email do destinatário da resposta automática'], + 'mail_resp_from' => ['title' => 'Endereço do Remetente' , 'description' => 'Endereço de email do remetente de e-mail de resposta automática (por exemplo, noreply@yourcompany.com)'], + 'mail_resp_subject' => ['title' => 'Assunto' , 'description' => 'Substitui assunto de e-mail padrão'], + 'reset_form' => ['title' => 'Limpar Fomulário' , 'description' => 'Limpar o formulário após o envio com sucesso'], + 'allowed_fields' => ['title' => 'Campos permitidos' , 'description' => 'Especifique quais campos devem ser filtrados e armazenados (adicione um nome de campo por linha)'], + 'recaptcha_enabled' => ['title' => 'Habiltar reCAPTCHA' , 'description' => 'Inserir o widget reCAPTCHA no seu formulário'], + 'recaptcha_theme' => ['title' => 'Tema' , 'description' => 'Cor do tema do widget', 'light' => 'Claro' , 'dark' => 'Escuro'], + 'recaptcha_type' => ['title' => 'Tipo' , 'description' => 'O tipo de CAPTCHA para servir' , 'image' => 'Imagem' , 'audio' => 'Áudio'], + 'recaptcha_size' => ['title' => 'Tamanho' , 'description' => 'O tamanho do widget' , 'normal' => 'Normal', 'compact' => 'Compacto'], + 'uploader_enable' => ['title' => 'Permitir Uploads' , 'description' => 'Ativar o upload de arquivos. Você precisa ativar essa opção explicitamente como uma medida de segurança.'], + 'uploader_multi' => ['title' => 'Multiplos Arquivos' , 'description' => 'Permitir multiplos uploads de arquivos'], + 'uploader_pholder' => ['title' => 'texto do Placeholder' , 'description' => 'Texto a ser exibido quando nenhum arquivo é carregado', 'default' => 'Clique ou arraste os arquivos para fazer o upload'], + 'uploader_maxsize' => ['title' => 'Limite do Tamanho do Arquivo' , 'description' => 'O tamanho máximo de arquivo que pode ser carregado em megabytes'], + 'uploader_types' => ['title' => 'Tipos de Arquivos Permitidos' , 'description' => 'Extensões de arquivo permitido ou asterisco (*) para todos os tipos (adicionar uma extensão por linha)'], + ] + ], + 'settings' => [ + 'section_flash_messages' => 'Mensagens Flash', + 'global_messages_success' => ['label' => 'Mensagem de sucesso global' , 'comment' => '(Esta definição pode ser substituída a partir do componente)', 'default' => 'Seu formulário foi enviado com sucesso'], + 'global_messages_errors' => ['label' => 'Mensagem de Erros Global' , 'comment' => '(Esta definição pode ser substituída a partir do componente)', 'default' => 'Ocorreu um erro o envio do formulário'], + 'section_recaptcha' => 'Configurações de reCAPTCHA', + 'recaptcha_site_key' => 'Chave do site', + 'recaptcha_secret_key' => 'Chave secreta', + ], + 'permissions' => [ + 'tab' => 'Formulários Mágico', + 'access_records' => 'Acessar dados de formulários armazenados', + 'access_exports' => 'Acesso à exportação de dados armazenados', + 'access_settings' => 'Acesso do módulo de configuração', + ], + 'mails' => [ + 'form_notification' => ['description' => 'Notificar quando um formulário é enviado'], + 'form_autoresponse' => ['description' => 'Resposta automática quando um formulário é enviado'], + ], + 'validation' => [ + 'recaptcha_error' => 'Não é possível validar o campo reCAPTCHA' + ], + ]; +?> diff --git a/plugins/blakejones/magicforms/lang/ru/lang.php b/plugins/blakejones/magicforms/lang/ru/lang.php new file mode 100644 index 0000000..4939077 --- /dev/null +++ b/plugins/blakejones/magicforms/lang/ru/lang.php @@ -0,0 +1,170 @@ + [ + 'name' => 'Magic Forms', + 'description' => 'С легкостью создайте AJAX форму' + ], + + 'menu' => [ + 'label' => 'Magic Forms', + 'records' => ['label' => 'Записи'], + 'exports' => ['label' => 'Экспорт'], + 'settings' => 'Настройки плагина', + ], + + 'controllers' => [ + 'records' => [ + 'title' => 'Все заявки', + 'view_title' => 'Запись', + 'error' => 'Запись не найдена', + 'deleted' => 'Запись успешно удалена', + 'columns' => [ + 'id' => 'ID записи', + 'group' => 'Группа', + 'ip' => 'IP адрес', + 'form_data' => 'Поля формы', + 'files' => 'Прикрепленные файлы', + 'created_at' => 'Создано', + ], + 'buttons' => [ + 'read' => 'Отметить как прочитано', + 'unread' => 'Отметить как непрочитанное', + 'gdpr_clean' => 'Очистить GDPR', + ], + 'alerts' => [ + 'gdpr_confirm' => "Вы действительно хотите удалить эти старые записи?\nЭто действие не может быть отменено!", + 'gdpr_success' => 'Очистка GDPR успешна', + 'gdpr_perms' => 'У вас нет прав использования этой функции', + ], + ], + 'exports' => [ + 'title' => 'Экспорт записей', + 'breadcrumb' => 'Экспорт', + 'filter_section' => '1. Фильтровать записи', + 'filter_type' => 'Экспорт всех записей', + 'filter_groups' => 'Группы', + 'filter_date_after' => 'Дата от', + 'filter_date_before' => 'дата до', + 'options_section' => '2. Экстра опции', + 'options_metadata' => 'Вложить метаданные', + 'options_metadata_com' => 'Экспорт записей с метаданными(ID, группа, дата создания)', + 'options_deleted' => 'Вложить удаленные записи', + 'options_delimiter' => 'Использовать альтернативный разделитель полей', + 'options_delimiter_com' => 'Точка с запятой вместо запятой', + 'options_utf' => 'Кодировать в UTF8', + 'options_utf_com' => 'Ваш CSV файл будет закодирван в UTF-8', + ], + ], + + 'components' => [ + 'generic_form' => [ + 'name' => 'Стандартная AJAX форма', + 'description' => 'Выводит стандартную форму; Перезапишите HTML компонент со своей формой.', + ], + 'upload_form' => [ + 'name' => 'AJAX форма с файлами', + 'description' => '[BETA] Форма с возможностью прикрепления файлов.', + ], + 'empty_form' => [ + 'name' => 'Пустая AJAX форма', + 'description' => 'Создает пустой плейсхолдер для вашей формы, который вы должны перезаписать своим HTML кодом.', + ], + 'shared' => [ + 'csrf_error' => 'Сессия формы истекла! Перезагрузите страницу.', + 'recaptcha_warn' => 'Внимание: reCAPTCHA настроена не правильно. Пожалуйста, перейдите в Настройки > CMS > Magic Forms и заполните все обязательные поля.', + 'group_validation' => 'Валидация формы', + 'group_messages' => 'Флэш-сообщения', + 'group_mail' => 'Настройки уведомлений', + 'group_mail_resp' => 'Настройки авто-ответа', + 'group_settings' => 'Остальные настройки', + 'group_security' => 'Безопасность', + 'group_recaptcha' => 'Настройки reCAPTCHA', + 'group_advanced' => 'Продвинутые настройки', + 'group_uploader' => 'Настройки файлового загрузчика', + 'validation_req' => 'Этот атрибут обязателен', + 'group' => ['title' => 'Группа' , 'description' => 'Организуйте свои формы по группам. Эта опция полезна для экспорта записей.'], + 'rules' => ['title' => 'Правила' , 'description' => 'Используйте валидацию Laravel для установки своих правил обработки полей.'], + 'rules_messages' => ['title' => 'Сообщения от правил', 'description' => 'Используйте свои собственные сообщения от кастомных валидаций.'], + 'custom_attributes' => ['title' => 'Кастомные атрибуты' , 'description' => 'Используйте кастомные атрибуты в своих правилах валидаций.'], + 'messages_success' => ['title' => 'Успешно' , 'description' => 'Сообщение об успешной отправке формы', 'default' => 'Ваша форма была успешно отправлена!'], + 'messages_errors' => ['title' => 'Ошибки' , 'description' => 'Сообщение с ошибками формы' , 'default' => 'В вашей заявке содержатся ошибки.'], + 'messages_partial' => ['title' => 'Кастомный фрагмент' , 'description' => 'Переопределить стандартные уведомления кастомным фрагментом из вашей фронтенд темы.'], + 'mail_enabled' => ['title' => 'Отправка уведомлений','description' => 'Отправлять увдеомления по email после каждого успешного заполенния формы.'], + 'mail_subject' => ['title' => 'Тема письма' , 'description' => 'Переопределить тему письма по умолчанию'], + 'mail_recipients' => ['title' => 'Получатели' , 'description' => 'Укажите получателей электронной почты. Используйте адреса электронной почты в качестве ключей и имена в качестве значений.'], + 'mail_bcc' => ['title' => 'BCC' , 'description' => 'Отправить копию получателям электронной почты (По одному адресу в строке)'], + 'mail_replyto' => ['title' => 'ReplyTo поле email' , 'description' => 'Поле формы, содержащее адрес электронной почты отправителя, который будет использоваться как "ReplyTo"'], + 'mail_template' => ['title' => 'Шаблон письма' , 'description' => 'Используйте собственный шаблон письма. Укажите код шаблона, например, "blakejones.magicforms::mail.notification" (находится в разделе Настройки -> Почтовые шаблоны). Оставьте пустым, чтобы использовать по умолчанию.'], + 'mail_uploads' => ['title' => 'Прикреплять файлы' , 'description' => 'Прикреплять файлы к письму'], + 'mail_resp_enabled' => ['title' => 'Отправить авто-ответ','description' => 'Отправить автоответчик на email отправителя.'], + 'mail_resp_field' => ['title' => 'Email поле' , 'description' => 'Имя поля с email отправителя'], + 'mail_resp_from' => ['title' => 'Email адрес отправителя', 'description' => 'Адрес электронной почты отправителя электронной почты с автоматическим ответом (например, noreply@yourcompany.com)'], + 'mail_resp_subject' => ['title' => 'Тема пиьсма' , 'description' => 'Переопределить тему письма по умолчанию'], + 'reset_form' => ['title' => 'Сбросить форму' , 'description' => 'Сбросить форму после успешной отправки'], + 'redirect' => ['title' => 'Редирект' , 'description' => 'Редирект на URL после успешной отправки формы.'], + 'inline_errors' => ['title' => 'Встроенные ошибки' , 'description' => 'Отображать встроенные ошибки. Это требует дополнительного кода, проверьте документацию для получения дополнительной информации.', 'disabled' => 'Отключено', 'display' => 'Отображать ошибки', 'variable' => 'JS переменная'], + 'js_on_success' => ['title' => '"Успешный" JS' , 'description' => 'Выполнияет скрипт после успешной отправки формы. Не используйте + + \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexdatabasetableoperations/partials/_tab.php b/plugins/rainlab/builder/behaviors/indexdatabasetableoperations/partials/_tab.php new file mode 100644 index 0000000..2cb010c --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexdatabasetableoperations/partials/_tab.php @@ -0,0 +1,17 @@ + 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => e(trans('backend::lang.form.confirm_tab_close')), + 'data-entity' => 'database', + 'onsubmit' => 'return false', + 'data-lang-add-id' => e(trans('rainlab.builder::lang.database.btn_add_id')), + 'data-lang-add-timestamps' => e(trans('rainlab.builder::lang.database.btn_add_timestamps')), + 'data-lang-add-soft-delete' => e(trans('rainlab.builder::lang.database.btn_add_soft_deleting')), + 'data-lang-id-exists' => e(trans('rainlab.builder::lang.database.id_exists')), + 'data-lang-timestamps-exist' => e(trans('rainlab.builder::lang.database.timestamps_exist')), + 'data-lang-soft-deleting-exist' => e(trans('rainlab.builder::lang.database.soft_deleting_exist')), +]) ?> + render() ?> + + + diff --git a/plugins/rainlab/builder/behaviors/indexdatabasetableoperations/partials/_toolbar.php b/plugins/rainlab/builder/behaviors/indexdatabasetableoperations/partials/_toolbar.php new file mode 100644 index 0000000..51cb08e --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexdatabasetableoperations/partials/_toolbar.php @@ -0,0 +1,17 @@ +
    + + + + + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indeximportsoperations/partials/_import-blueprints-popup-form.php b/plugins/rainlab/builder/behaviors/indeximportsoperations/partials/_import-blueprints-popup-form.php new file mode 100644 index 0000000..e094388 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indeximportsoperations/partials/_import-blueprints-popup-form.php @@ -0,0 +1,26 @@ +'imports:cmdSaveImports', + 'data-plugin-code' => $pluginCode +]) ?> + + + + + diff --git a/plugins/rainlab/builder/behaviors/indeximportsoperations/partials/_tab.php b/plugins/rainlab/builder/behaviors/indeximportsoperations/partials/_tab.php new file mode 100644 index 0000000..2361f9e --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indeximportsoperations/partials/_tab.php @@ -0,0 +1,15 @@ + 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => e(trans('backend::lang.form.confirm_tab_close')), + 'data-entity' => 'imports', + 'onsubmit' => 'return false' +]) ?> + + render() ?> + + + + + + diff --git a/plugins/rainlab/builder/behaviors/indeximportsoperations/partials/_toolbar.php b/plugins/rainlab/builder/behaviors/indeximportsoperations/partials/_toolbar.php new file mode 100644 index 0000000..e15fba8 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indeximportsoperations/partials/_toolbar.php @@ -0,0 +1,17 @@ + diff --git a/plugins/rainlab/builder/behaviors/indexlocalizationoperations/partials/_copy-strings-popup-form.php b/plugins/rainlab/builder/behaviors/indexlocalizationoperations/partials/_copy-strings-popup-form.php new file mode 100644 index 0000000..faca9d7 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexlocalizationoperations/partials/_copy-strings-popup-form.php @@ -0,0 +1,41 @@ +'localization:cmdCopyMissingStrings' +]) ?> + + + + + diff --git a/plugins/rainlab/builder/behaviors/indexlocalizationoperations/partials/_new-string-popup.php b/plugins/rainlab/builder/behaviors/indexlocalizationoperations/partials/_new-string-popup.php new file mode 100644 index 0000000..55c7437 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexlocalizationoperations/partials/_new-string-popup.php @@ -0,0 +1,42 @@ +'return false' +]) ?> + + + + + diff --git a/plugins/rainlab/builder/behaviors/indexlocalizationoperations/partials/_tab.php b/plugins/rainlab/builder/behaviors/indexlocalizationoperations/partials/_tab.php new file mode 100644 index 0000000..7b68bb2 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexlocalizationoperations/partials/_tab.php @@ -0,0 +1,15 @@ + 'layout hide-secondary-tabs', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => e(trans('backend::lang.form.confirm_tab_close')), + 'data-new-string-message' => e(trans('rainlab.builder::lang.localization.new_string_warning')), + 'data-structure-mismatch' => e(trans('rainlab.builder::lang.localization.structure_mismatch')), + 'data-entity' => 'localization', + 'data-default-language' => e($defaultLanguage), + 'onsubmit' => 'return false' +]) ?> + render() ?> + + + + \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexlocalizationoperations/partials/_toolbar.php b/plugins/rainlab/builder/behaviors/indexlocalizationoperations/partials/_toolbar.php new file mode 100644 index 0000000..85b3e7c --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexlocalizationoperations/partials/_toolbar.php @@ -0,0 +1,27 @@ +
    + + + + + + + + + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexmenusoperations/partials/_tab.php b/plugins/rainlab/builder/behaviors/indexmenusoperations/partials/_tab.php new file mode 100644 index 0000000..db93b35 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexmenusoperations/partials/_tab.php @@ -0,0 +1,11 @@ + 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => e(trans('backend::lang.form.confirm_tab_close')), + 'data-entity' => 'menus', + 'onsubmit' => 'return false' +]) ?> + render() ?> + + + \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexmenusoperations/partials/_toolbar.php b/plugins/rainlab/builder/behaviors/indexmenusoperations/partials/_toolbar.php new file mode 100644 index 0000000..ba880c5 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexmenusoperations/partials/_toolbar.php @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexmodelformoperations/partials/_add-database-fields-popup-form.php b/plugins/rainlab/builder/behaviors/indexmodelformoperations/partials/_add-database-fields-popup-form.php new file mode 100644 index 0000000..7f7d672 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexmodelformoperations/partials/_add-database-fields-popup-form.php @@ -0,0 +1,28 @@ +'modelForm:cmdAddDatabaseFields' +]) ?> + + + + + + \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexmodelformoperations/partials/_tab.php b/plugins/rainlab/builder/behaviors/indexmodelformoperations/partials/_tab.php new file mode 100644 index 0000000..ae1ba27 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexmodelformoperations/partials/_tab.php @@ -0,0 +1,13 @@ + 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => e(trans('backend::lang.form.confirm_tab_close')), + 'data-entity' => 'models', + 'onsubmit' => 'return false' +]) ?> + render() ?> + + + + + \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexmodelformoperations/partials/_toolbar.php b/plugins/rainlab/builder/behaviors/indexmodelformoperations/partials/_toolbar.php new file mode 100644 index 0000000..5729ea0 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexmodelformoperations/partials/_toolbar.php @@ -0,0 +1,27 @@ +
    + + + + + + + + + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexmodellistoperations/partials/_tab.php b/plugins/rainlab/builder/behaviors/indexmodellistoperations/partials/_tab.php new file mode 100644 index 0000000..aa1139f --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexmodellistoperations/partials/_tab.php @@ -0,0 +1,16 @@ + 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => e(trans('backend::lang.form.confirm_tab_close')), + 'data-entity' => 'models', + 'onsubmit' => 'return false', + 'data-sub-entity' => 'model-list', + 'data-lang-add-database-columns' => e(trans('rainlab.builder::lang.list.btn_add_database_columns')), + 'data-lang-all-database-columns-exist' => e(trans('rainlab.builder::lang.list.all_database_columns_exist')), +]) ?> + render() ?> + + + + + \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexmodellistoperations/partials/_toolbar.php b/plugins/rainlab/builder/behaviors/indexmodellistoperations/partials/_toolbar.php new file mode 100644 index 0000000..eb8ecdf --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexmodellistoperations/partials/_toolbar.php @@ -0,0 +1,17 @@ +
    + + + + + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexmodeloperations/partials/_model-popup-form.php b/plugins/rainlab/builder/behaviors/indexmodeloperations/partials/_model-popup-form.php new file mode 100644 index 0000000..f244d31 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexmodeloperations/partials/_model-popup-form.php @@ -0,0 +1,32 @@ +'model:cmdApplyModelSettings' +]) ?> + + + + \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexpermissionsoperations/partials/_tab.php b/plugins/rainlab/builder/behaviors/indexpermissionsoperations/partials/_tab.php new file mode 100644 index 0000000..bea6379 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexpermissionsoperations/partials/_tab.php @@ -0,0 +1,11 @@ + 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => e(trans('backend::lang.form.confirm_tab_close')), + 'data-entity' => 'permissions', + 'onsubmit' => 'return false' +]) ?> + render() ?> + + + \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexpermissionsoperations/partials/_toolbar.php b/plugins/rainlab/builder/behaviors/indexpermissionsoperations/partials/_toolbar.php new file mode 100644 index 0000000..6e416a5 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexpermissionsoperations/partials/_toolbar.php @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexpluginoperations/partials/_plugin-popup-form.php b/plugins/rainlab/builder/behaviors/indexpluginoperations/partials/_plugin-popup-form.php new file mode 100644 index 0000000..54492cd --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexpluginoperations/partials/_plugin-popup-form.php @@ -0,0 +1,33 @@ +'plugin:cmdApplyPluginSettings' +]) ?> + + + + + + + \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexpluginoperations/partials/_plugin-update-hint.php b/plugins/rainlab/builder/behaviors/indexpluginoperations/partials/_plugin-update-hint.php new file mode 100644 index 0000000..0feedb0 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexpluginoperations/partials/_plugin-update-hint.php @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexversionsoperations/partials/_tab.php b/plugins/rainlab/builder/behaviors/indexversionsoperations/partials/_tab.php new file mode 100644 index 0000000..ceed210 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexversionsoperations/partials/_tab.php @@ -0,0 +1,40 @@ + 'layout hide-secondary-tabs', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => e(trans('backend::lang.form.confirm_tab_close')), + 'data-entity' => 'versions', + 'onsubmit' => 'return false' +]) ?> + render() ?> + + + + + + + + + + + + + diff --git a/plugins/rainlab/builder/behaviors/indexversionsoperations/partials/_toolbar.php b/plugins/rainlab/builder/behaviors/indexversionsoperations/partials/_toolbar.php new file mode 100644 index 0000000..a44d9ee --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexversionsoperations/partials/_toolbar.php @@ -0,0 +1,33 @@ +
    + + + + + + + + + + + + + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/behaviors/indexversionsoperations/partials/_version-hint-block.php b/plugins/rainlab/builder/behaviors/indexversionsoperations/partials/_version-hint-block.php new file mode 100644 index 0000000..e9eff67 --- /dev/null +++ b/plugins/rainlab/builder/behaviors/indexversionsoperations/partials/_version-hint-block.php @@ -0,0 +1,28 @@ + +
    + + + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/classes/BehaviorDesignTimeProviderBase.php b/plugins/rainlab/builder/classes/BehaviorDesignTimeProviderBase.php new file mode 100644 index 0000000..2121cff --- /dev/null +++ b/plugins/rainlab/builder/classes/BehaviorDesignTimeProviderBase.php @@ -0,0 +1,33 @@ +sourceModel = $source; + } + + /** + * generate + */ + public function inspect($blueprint) + { + $this->setBlueprintContext($blueprint); + + $result = [ + 'controllerFile' => null, + 'modelFiles' => [], + 'migrationFiles' => [], + 'errorMessage' => null + ]; + + try { + if ($model = $this->makeControllerModel()) { + $result['controllerFile'] = $model->getControllerFilePath(); + } + + if ($model = $this->makeModelModel()) { + $result['modelFiles'][] = $model->getModelFilePath(); + } + + foreach ($this->makeExpandoModels(true) as $model) { + $result['modelFiles'][] = $model->getModelFilePath(); + } + + $result['migrationFiles'] = array_keys($this->inspectMigrations()); + } + catch (Throwable $ex) { + $result['errorMessage'] = $ex->getMessage(); + } + + return $result; + } + + /** + * generate + */ + public function generate() + { + $this->templateVars = []; + $this->filesGenerated = []; + $this->filesValidated = []; + $this->blueprintFiles = []; + $this->migrationScripts = []; + $this->sourceBlueprints = []; + + $this->loadSourceBlueprints(); + $this->validateNavigation(); + + // Validate + foreach ($this->sourceBlueprints as $blueprint) { + $this->setBlueprintContext($blueprint); + $this->validateModel(); + $this->validateExpandoModels(); + $this->validateController(); + $this->validatePermission(); + } + + // Generate + try { + foreach ($this->sourceBlueprints as $blueprint) { + $this->setBlueprintContext($blueprint); + $this->generateMigrations(); + $this->generateModel(); + $this->generateExpandoModels(); + $this->generateController(); + $this->generatePermission(); + + $this->blueprintFiles[] = $blueprint->getFilePath(); + } + } + catch (Throwable $ex) { + $this->rollback(); + throw $ex; + } + + $this->generateNavigation(); + $this->generateVersionUpdate(); + + if ($this->sourceModel->deleteBlueprintData) { + $this->deleteGeneratedBlueprintData(); + } + + if ($this->sourceModel->disableBlueprints) { + $this->disableGeneratedBlueprints(); + } + } + + /** + * loadSourceBlueprints + */ + protected function loadSourceBlueprints() + { + $blueprintLib = TailorBlueprintLibrary::instance(); + + foreach ($this->sourceModel->blueprints as $uuid => $config) { + $blueprint = $blueprintLib->getBlueprintObject($uuid); + if ($blueprint) { + $this->sourceBlueprints[$uuid] = $blueprint; + } + } + } + + /** + * setBlueprintContext + */ + protected function setBlueprintContext($blueprint) + { + $config = $this->sourceModel->blueprints[$blueprint->uuid] ?? []; + + $this->sourceModel->setBlueprintContext($blueprint, $config); + + $this->setTemplateVars(); + } + + /** + * disableGeneratedBlueprints + */ + protected function disableGeneratedBlueprints() + { + foreach ($this->blueprintFiles as $filePath) { + File::move( + $filePath, + str_replace('.yaml', '.yaml.bak', $filePath) + ); + } + } + + /** + * deleteGeneratedBlueprintData + */ + protected function deleteGeneratedBlueprintData() + { + foreach ($this->sourceBlueprints as $blueprint) { + $contentTable = $blueprint->getContentTableName(); + Schema::dropIfExists($contentTable); + + $joinTable = $blueprint->getJoinTableName(); + Schema::dropIfExists($joinTable); + + $repeaterTable = $blueprint->getRepeaterTableName(); + Schema::dropIfExists($repeaterTable); + } + } + + /** + * setTemplateVars + */ + protected function setTemplateVars() + { + $pluginCodeObj = $this->sourceModel->getPluginCodeObj(); + + $this->templateVars = $this->getConfig(); + $this->templateVars['pluginNamespace'] = $pluginCodeObj->toPluginNamespace(); + $this->templateVars['pluginCode'] = $pluginCodeObj->toCode(); + } + + /** + * getTemplatePath + */ + protected function getTemplatePath($template) + { + return __DIR__.'/blueprintgenerator/templates/'.$template; + } + + /** + * parseTemplate + */ + protected function parseTemplate($templatePath, $vars = []) + { + $template = File::get($templatePath); + + $vars = array_merge($this->templateVars, $vars); + $code = Twig::parse($template, $vars); + + return $code; + } + + /** + * writeFile + */ + protected function writeFile($path, $data) + { + $fileDirectory = dirname($path); + if (!File::isDirectory($fileDirectory)) { + if (!File::makeDirectory($fileDirectory, 0777, true, true)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.common.error_make_dir', [ + 'name' => $fileDirectory + ])); + } + } + + if (@File::put($path, $data) === false) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_save_file', [ + 'file' => basename($path) + ])); + } + + @File::chmod($path); + $this->filesGenerated[] = $path; + } + + /** + * rollback + */ + protected function rollback() + { + foreach ($this->filesGenerated as $path) { + @unlink($path); + } + } + + /** + * makeTabs + */ + protected function makeTabs($str) + { + return str_replace('\t', ' ', $str); + } + + /** + * getConfig + */ + protected function getConfig($key = null, $default = null) + { + return $this->sourceModel->getBlueprintConfig($key, $default); + } + + /** + * validateUniqueFiles + */ + protected function validateUniqueFiles(array $files) + { + if (!is_array($this->filesValidated)) { + $this->filesValidated = []; + } + + foreach ($files as $path) { + if (File::isFile($path) || in_array($path, $this->filesValidated)) { + throw new ValidationException([ + 'modelClass' => __("File [:file] already exists when trying to import [:blueprint]", [ + 'file' => basename(dirname($path)) . '/' . basename($path), + 'blueprint' => $this->sourceModel->getBlueprintObject()->handle ?? 'unknown' + ]) + ]); + } + } + + $this->filesValidated = array_merge($this->filesValidated, $files); + } +} diff --git a/plugins/rainlab/builder/classes/ComponentHelper.php b/plugins/rainlab/builder/classes/ComponentHelper.php new file mode 100644 index 0000000..12ae887 --- /dev/null +++ b/plugins/rainlab/builder/classes/ComponentHelper.php @@ -0,0 +1,123 @@ +modelListCache !== null) { + return $this->modelListCache; + } + + $key = 'builder-global-model-list'; + $cached = Cache::get($key, false); + + if ($cached !== false && ($cached = @unserialize($cached)) !== false) { + return $this->modelListCache = $cached; + } + + $plugins = PluginBaseModel::listAllPluginCodes(); + + $result = []; + foreach ($plugins as $pluginCode) { + try { + $pluginCodeObj = new PluginCode($pluginCode); + + $models = ModelModel::listPluginModels($pluginCodeObj); + + $pluginCodeStr = $pluginCodeObj->toCode(); + $pluginModelsNamespace = $pluginCodeObj->toPluginNamespace().'\\Models\\'; + foreach ($models as $model) { + $fullClassName = $pluginModelsNamespace.$model->className; + + $result[$fullClassName] = $pluginCodeStr.' - '.$model->className; + } + } + catch (Exception $ex) { + // Ignore invalid plugins and models + } + } + + $expiresAt = now()->addMinutes(1); + Cache::put($key, serialize($result), $expiresAt); + + return $this->modelListCache = $result; + } + + /** + * getModelClassDesignTime + */ + public function getModelClassDesignTime() + { + $modelClass = trim(Input::get('modelClass')); + + if ($modelClass && !is_scalar($modelClass)) { + throw new ApplicationException('Model class name should be a string.'); + } + + if (!strlen($modelClass)) { + $models = $this->listGlobalModels(); + $modelClass = key($models); + } + + if (!ModelModel::validateModelClassName($modelClass)) { + throw new ApplicationException('Invalid model class name.'); + } + + return $modelClass; + } + + /** + * listModelColumnNames + */ + public function listModelColumnNames() + { + $modelClass = $this->getModelClassDesignTime(); + + $key = md5('builder-global-model-list-'.$modelClass); + $cached = Cache::get($key, false); + + if ($cached !== false && ($cached = @unserialize($cached)) !== false) { + return $cached; + } + + $pluginCodeObj = PluginCode::createFromNamespace($modelClass); + + $modelClassParts = explode('\\', $modelClass); // The full class name is already validated in PluginCode::createFromNamespace() + $modelClass = array_pop($modelClassParts); + + $columnNames = ModelModel::getModelFields($pluginCodeObj, $modelClass); + + $result = []; + foreach ($columnNames as $columnName) { + $result[$columnName] = $columnName; + } + + $expiresAt = now()->addMinutes(1); + Cache::put($key, serialize($result), $expiresAt); + + return $result; + } +} diff --git a/plugins/rainlab/builder/classes/ControlDesignTimeProviderBase.php b/plugins/rainlab/builder/classes/ControlDesignTimeProviderBase.php new file mode 100644 index 0000000..5264a96 --- /dev/null +++ b/plugins/rainlab/builder/classes/ControlDesignTimeProviderBase.php @@ -0,0 +1,42 @@ +groupedControls !== null) { + return $returnGrouped ? $this->groupedControls : $this->controls; + } + + $this->groupedControls = [ + $this->resolveControlGroupName(self::GROUP_STANDARD) => [], + $this->resolveControlGroupName(self::GROUP_WIDGETS) => [], + $this->resolveControlGroupName(self::GROUP_UI) => [] + ]; + + Event::fire('pages.builder.registerControls', [$this]); + + foreach ($this->controls as $controlType => $controlInfo) { + $controlGroup = $this->resolveControlGroupName($controlInfo['group']); + + if (!array_key_exists($controlGroup, $this->groupedControls)) { + $this->groupedControls[$controlGroup] = []; + } + + $this->groupedControls[$controlGroup][$controlType] = $controlInfo; + } + + return $returnGrouped ? $this->groupedControls : $this->controls; + } + + /** + * getControlInfo returns information about a control by its code. + * @param string $code Specifies the control code. + * @return array Returns an associative array or null if the control is not registered. + */ + public function getControlInfo($code) + { + $controls = $this->listControls(false); + + if (array_key_exists($code, $controls)) { + return $controls[$code]; + } + + return [ + 'properties' => [], + 'designTimeProvider' => self::DEFAULT_DESIGN_TIME_PROVIDER, + 'name' => $code, + 'description' => null, + 'unknownControl' => true + ]; + } + + /** + * registerControl registers a control. + * @param string $code Specifies the control code, for example "codeeditor". + * @param string $name Specifies the control name, for example "Code editor". + * @param string $description Specifies the control descritpion, can be empty. + * @param string|integer $controlGroup Specifies the control group. + * Control groups are used to create tabs in the Control Palette in Form Builder. + * The group could one of the ControlLibrary::GROUP_ constants or a string. + * @param string $icon Specifies the control icon for the Control Palette. + * @see http://octobercms.com/docs/ui/icon + * @param array $properties Specifies the control properties. + * The property definitions should be compatible with Inspector properties, similarly + * to the Component properties: http://octobercms.com/docs/plugin/components#component-properties + * Use the getStandardProperties() of the ControlLibrary to get the standard control properties. + * @param string $designTimeProviderClass Specifies the control design-time provider class name. + * The class should extend RainLab\Builder\Classes\ControlDesignTimeProviderBase. If the class is not provided, + * the default control design and design settings will be used. + */ + public function registerControl($code, $name, $description, $controlGroup, $icon, $properties, $designTimeProviderClass) + { + if (!$designTimeProviderClass) { + $designTimeProviderClass = self::DEFAULT_DESIGN_TIME_PROVIDER; + } + + $this->controls[$code] = [ + 'group' => $controlGroup, + 'name' => $name, + 'description' => $description, + 'icon' => $icon, + 'properties' => $properties, + 'designTimeProvider' => $designTimeProviderClass + ]; + } + + /** + * getStandardProperties + */ + public function getStandardProperties($excludeProperties = [], $addProperties = []) + { + $result = [ + 'label' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_label_title'), + 'type' => 'builderLocalization', + ], + 'oc.comment' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_comment_title'), + 'type' => 'builderLocalization', + ], + 'oc.commentPosition' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_comment_position'), + 'type' => 'dropdown', + 'options' => [ + 'above' => Lang::get('rainlab.builder::lang.form.property_comment_position_above'), + 'below' => Lang::get('rainlab.builder::lang.form.property_comment_position_below') + ], + 'ignoreIfEmpty' => true, + ], + 'span' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_span_title'), + 'type' => 'dropdown', + 'default' => 'full', + 'options' => [ + 'left' => Lang::get('rainlab.builder::lang.form.span_left'), + 'right' => Lang::get('rainlab.builder::lang.form.span_right'), + 'full' => Lang::get('rainlab.builder::lang.form.span_full'), + 'auto' => Lang::get('rainlab.builder::lang.form.span_auto') + ] + ], + 'placeholder' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_placeholder_title'), + 'type' => 'builderLocalization', + ], + 'default' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_default_title'), + 'type' => 'builderLocalization', + ], + 'cssClass' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_css_class_title'), + 'description' => Lang::get('rainlab.builder::lang.form.property_css_class_description'), + 'type' => 'string' + ], + 'disabled' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_disabled_title'), + 'type' => 'checkbox' + ], + 'readOnly' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_read_only_title'), + 'type' => 'checkbox' + ], + 'hidden' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_hidden_title'), + 'type' => 'checkbox' + ], + 'required' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_required_title'), + 'type' => 'checkbox' + ], + 'stretch' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_stretch_title'), + 'description' => Lang::get('rainlab.builder::lang.form.property_stretch_description'), + 'type' => 'checkbox' + ], + 'context' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_context_title'), + 'description' => Lang::get('rainlab.builder::lang.form.property_context_description'), + 'type' => 'set', + 'items' => [ + 'create' => Lang::get('rainlab.builder::lang.form.property_context_create'), + 'update' => Lang::get('rainlab.builder::lang.form.property_context_update'), + 'preview' => Lang::get('rainlab.builder::lang.form.property_context_preview') + ], + 'default' => ['create', 'update', 'preview'], + 'ignoreIfDefault' => true + ] + ]; + + $result = array_merge($result, $addProperties); + + $advancedProperties = [ + 'defaultFrom' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_default_from_title'), + 'description' => Lang::get('rainlab.builder::lang.form.property_default_from_description'), + 'type' => 'dropdown', + 'group' => Lang::get('rainlab.builder::lang.form.property_group_advanced'), + 'ignoreIfEmpty' => true, + 'fillFrom' => 'form-controls' + ], + 'dependsOn' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_dependson_title'), + 'description' => Lang::get('rainlab.builder::lang.form.property_dependson_description'), + 'type' => 'stringList', + 'group' => Lang::get('rainlab.builder::lang.form.property_group_advanced'), + ], + 'trigger' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_trigger_title'), + 'description' => Lang::get('rainlab.builder::lang.form.property_trigger_description'), + 'type' => 'object', + 'group' => Lang::get('rainlab.builder::lang.form.property_group_advanced'), + 'ignoreIfPropertyEmpty' => 'field', + 'properties' => [ + [ + 'property' => 'action', + 'title' => Lang::get('rainlab.builder::lang.form.property_trigger_action'), + 'type' => 'dropdown', + 'options' => [ + 'show' => Lang::get('rainlab.builder::lang.form.property_trigger_show'), + 'hide' => Lang::get('rainlab.builder::lang.form.property_trigger_hide'), + 'enable' => Lang::get('rainlab.builder::lang.form.property_trigger_enable'), + 'disable' => Lang::get('rainlab.builder::lang.form.property_trigger_disable'), + 'empty' => Lang::get('rainlab.builder::lang.form.property_trigger_empty') + ] + ], + [ + 'property' => 'field', + 'title' => Lang::get('rainlab.builder::lang.form.property_trigger_field'), + 'description' => Lang::get('rainlab.builder::lang.form.property_trigger_field_description'), + 'type' => 'dropdown', + 'fillFrom' => 'form-controls' + ], + [ + 'property' => 'condition', + 'title' => Lang::get('rainlab.builder::lang.form.property_trigger_condition'), + 'description' => Lang::get('rainlab.builder::lang.form.property_trigger_condition_description'), + 'type' => 'autocomplete', + 'items' => [ + 'checked' => Lang::get('rainlab.builder::lang.form.property_trigger_condition_checked'), + 'unchecked' => Lang::get('rainlab.builder::lang.form.property_trigger_condition_unchecked'), + 'value[somevalue]' => Lang::get('rainlab.builder::lang.form.property_trigger_condition_somevalue'), + ] + ] + ] + ], + 'preset' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_preset_title'), + 'description' => Lang::get('rainlab.builder::lang.form.property_preset_description'), + 'type' => 'object', + 'group' => Lang::get('rainlab.builder::lang.form.property_group_advanced'), + 'ignoreIfPropertyEmpty' => 'field', + 'properties' => [ + [ + 'property' => 'field', + 'title' => Lang::get('rainlab.builder::lang.form.property_preset_field'), + 'description' => Lang::get('rainlab.builder::lang.form.property_preset_field_description'), + 'type' => 'dropdown', + 'fillFrom' => 'form-controls' + ], + [ + 'property' => 'type', + 'title' => Lang::get('rainlab.builder::lang.form.property_preset_type'), + 'description' => Lang::get('rainlab.builder::lang.form.property_preset_type_description'), + 'type' => 'dropdown', + 'options' => [ + 'url' => 'URL', + 'file' => 'File', + 'slug' => 'Slug', + 'camel' => 'Camel' + ] + ] + ] + ], + 'attributes' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_attributes_title'), + 'description' => Lang::get('rainlab.builder::lang.form.property_attributes_description'), + 'type' => 'dictionary', + 'group' => Lang::get('rainlab.builder::lang.form.property_group_advanced'), + ], + 'containerAttributes' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_container_attributes_title'), + 'description' => Lang::get('rainlab.builder::lang.form.property_container_attributes_description'), + 'type' => 'dictionary', + 'group' => Lang::get('rainlab.builder::lang.form.property_group_advanced'), + ] + ]; + + $result = array_merge($result, $advancedProperties); + + foreach ($excludeProperties as $property) { + if (array_key_exists($property, $result)) { + unset($result[$property]); + } + } + + return $result; + } + + /** + * resolveControlGroupName + */ + protected function resolveControlGroupName($group) + { + if ($group === self::GROUP_STANDARD) { + return Lang::get('rainlab.builder::lang.form.control_group_standard'); + } + + if ($group === self::GROUP_WIDGETS) { + return Lang::get('rainlab.builder::lang.form.control_group_widgets'); + } + + if ($group === self::GROUP_UI) { + return Lang::get('rainlab.builder::lang.form.control_group_ui'); + } + + return Lang::get($group); + } +} diff --git a/plugins/rainlab/builder/classes/ControllerBehaviorLibrary.php b/plugins/rainlab/builder/classes/ControllerBehaviorLibrary.php new file mode 100644 index 0000000..7db3ff6 --- /dev/null +++ b/plugins/rainlab/builder/classes/ControllerBehaviorLibrary.php @@ -0,0 +1,84 @@ +listBehaviors(); + + if (!array_key_exists($behaviorClassName, $behaviors)) { + return null; + } + + return $behaviors[$behaviorClassName]; + } + + /** + * Registers a controller behavior. + * @param string $class Specifies the behavior class name. + * @param string $name Specifies the behavior name, for example "Form behavior". + * @param string $description Specifies the behavior description. + * @param array $properties Specifies the behavior properties. + * The property definitions should be compatible with Inspector properties, similarly + * to the Component properties: http://octobercms.com/docs/plugin/components#component-properties + * @param string $configFilePropertyName Specifies the name of the controller property that contains the configuration file name for the behavior. + * @param string $designTimeProviderClass Specifies the behavior design-time provider class name. + * The class should extend RainLab\Builder\Classes\BehaviorDesignTimeProviderBase. If the class is not provided, + * the default control design and design settings will be used. + * @param string $configFileName Default behavior configuration file name, for example config_form.yaml. + * @param array $viewTemplates An array of view templates that are required for the behavior. + * The templates are used when a new controller is created. The templates should be specified as paths + * to Twig files in the format ['~/plugins/author/plugin/behaviors/behaviorname/templates/view.htm.tpl']. + */ + public function registerBehavior($class, $name, $description, $properties, $configFilePropertyName, $designTimeProviderClass, $configFileName, $viewTemplates = []) + { + if (!$designTimeProviderClass) { + $designTimeProviderClass = self::DEFAULT_DESIGN_TIME_PROVIDER; + } + + $this->behaviors[$class] = [ + 'class' => $class, + 'name' => Lang::get($name), + 'description' => Lang::get($description), + 'properties' => $properties, + 'designTimeProvider' => $designTimeProviderClass, + 'viewTemplates' => $viewTemplates, + 'configFileName' => $configFileName, + 'configPropertyName' => $configFilePropertyName + ]; + } + + /** + * listBehaviors + */ + public function listBehaviors() + { + if ($this->behaviors !== null) { + return $this->behaviors; + } + + $this->behaviors = []; + + Event::fire('pages.builder.registerControllerBehaviors', [$this]); + + return $this->behaviors; + } +} diff --git a/plugins/rainlab/builder/classes/ControllerFileParser.php b/plugins/rainlab/builder/classes/ControllerFileParser.php new file mode 100644 index 0000000..e158dc2 --- /dev/null +++ b/plugins/rainlab/builder/classes/ControllerFileParser.php @@ -0,0 +1,146 @@ +stream = new PhpSourceStream($fileContents); + } + + /** + * listBehaviors + */ + public function listBehaviors() + { + $this->stream->reset(); + + while ($this->stream->forward()) { + $tokenCode = $this->stream->getCurrentCode(); + + if ($tokenCode == T_PUBLIC) { + $behaviors = $this->extractBehaviors(); + if ($behaviors !== false) { + return $behaviors; + } + } + } + } + + /** + * getStringPropertyValue + */ + public function getStringPropertyValue($property) + { + $this->stream->reset(); + + while ($this->stream->forward()) { + $tokenCode = $this->stream->getCurrentCode(); + + if ($tokenCode == T_PUBLIC) { + $value = $this->extractPropertyValue($property); + if ($value !== false) { + return $value; + } + } + } + } + + /** + * extractBehaviors + */ + protected function extractBehaviors() + { + if ($this->stream->getNextExpected(T_WHITESPACE) === null) { + return false; + } + + if ($this->stream->getNextExpected(T_VARIABLE) === null) { + return false; + } + + if ($this->stream->getCurrentText() != '$implement') { + return false; + } + + if ($this->stream->getNextExpectedTerminated(['=', T_WHITESPACE], ['[', T_ARRAY]) === null) { + return false; + } + + if ($this->stream->getCurrentText() === 'array') { + // For the array syntax 'array(' - forward to the next + // character after the opening bracket + + if ($this->stream->getNextExpectedTerminated(['(', T_WHITESPACE], [T_CONSTANT_ENCAPSED_STRING]) === null) { + return false; + } + + $this->stream->back(); + } + + $result = []; + while ($line = $this->stream->getNextExpectedTerminated([T_CONSTANT_ENCAPSED_STRING, T_NAME_FULLY_QUALIFIED, T_WHITESPACE], [',', ']', ')'], [T_DOUBLE_COLON, T_CLASS])) { + $line = $this->stream->unquotePhpString(trim($line), $line); + if (!strlen($line)) { + continue; + } + + $result[] = $this->normalizeBehaviorClassName($line); + } + + return $result; + } + + /** + * extractPropertyValue + */ + protected function extractPropertyValue($property) + { + if ($this->stream->getNextExpected(T_WHITESPACE) === null) { + return false; + } + + if ($this->stream->getNextExpected(T_VARIABLE) === null) { + return false; + } + + if ($this->stream->getCurrentText() != '$'.$property) { + return false; + } + + if ($this->stream->getNextExpectedTerminated(['=', T_WHITESPACE], [T_CONSTANT_ENCAPSED_STRING]) === null) { + return null; + } + + $value = trim($this->stream->getCurrentText()); + $value = $this->stream->unquotePhpString($value); + + if ($value === false) { + return null; + } + + return $value; + } + + /** + * normalizeBehaviorClassName + */ + protected function normalizeBehaviorClassName($className) + { + $className = str_replace('.', '\\', trim($className)); + return ltrim($className, '\\'); + } +} diff --git a/plugins/rainlab/builder/classes/ControllerGenerator.php b/plugins/rainlab/builder/classes/ControllerGenerator.php new file mode 100644 index 0000000..2f18ff9 --- /dev/null +++ b/plugins/rainlab/builder/classes/ControllerGenerator.php @@ -0,0 +1,411 @@ +sourceModel = $source; + } + + /** + * generate + */ + public function generate() + { + $this->filesGenerated = []; + $this->templateVars = []; + + try { + $this->validateBehaviorViewTemplates(); + $this->validateBehaviorConfigSettings(); + $this->validateControllerUnique(); + + $this->setTemplateVars(); + $this->generateControllerFile(); + $this->generateConfigFiles(); + $this->generateViews(); + } + catch (Exception $ex) { + $this->rollback(); + + throw $ex; + } + } + + /** + * setTemplateVariable + */ + public function setTemplateVariable($var, $value) + { + $this->templateVars[$var] = $value; + } + + /** + * validateBehaviorViewTemplates + */ + protected function validateBehaviorViewTemplates() + { + if (!$this->sourceModel->behaviors) { + return; + } + + $this->templateFiles = []; + + $controllerPath = $this->sourceModel->getControllerFilePath(true); + $behaviorLibrary = ControllerBehaviorLibrary::instance(); + + $knownTemplates = []; + foreach ($this->sourceModel->behaviors as $behaviorClass => $behaviorConfig) { + $behaviorInfo = $behaviorLibrary->getBehaviorInfo($behaviorClass); + if (!$behaviorInfo) { + throw new ValidationException([ + 'behaviors' => Lang::get('rainlab.builder::lang.controller.error_unknown_behavior', [ + 'class' => $behaviorClass + ]) + ]); + } + + foreach ($behaviorInfo['viewTemplates'] as $viewTemplate) { + $templateFileName = basename($viewTemplate); + $templateBaseName = pathinfo($templateFileName, PATHINFO_FILENAME); + + if (in_array($templateFileName, $knownTemplates)) { + throw new ValidationException([ + 'behaviors' => Lang::get('rainlab.builder::lang.controller.error_behavior_view_conflict', [ + 'view' => $templateBaseName + ]) + ]); + } + + $knownTemplates[] = $templateFileName; + + $filePath = File::symbolizePath($viewTemplate); + if (!File::isFile($filePath)) { + throw new ValidationException([ + 'behaviors' => Lang::get('rainlab.builder::lang.controller.error_behavior_view_file_not_found', [ + 'class' => $behaviorClass, + 'view' => $templateFileName + ]) + ]); + } + + $destFilePath = $controllerPath.'/'.$templateBaseName; + if (File::isFile($destFilePath)) { + throw new ValidationException([ + 'behaviors' => Lang::get('rainlab.builder::lang.controller.error_behavior_view_file_exists', [ + 'view' => $destFilePath + ]) + ]); + } + + $this->templateFiles[$filePath] = $destFilePath; + } + } + } + + /** + * validateBehaviorConfigSettings + */ + protected function validateBehaviorConfigSettings() + { + if (!$this->sourceModel->behaviors) { + return; + } + + $this->configTemplateProperties = []; + + $controllerPath = $this->sourceModel->getControllerFilePath(true); + $behaviorLibrary = ControllerBehaviorLibrary::instance(); + + $knownConfigFiles = []; + foreach ($this->sourceModel->behaviors as $behaviorClass => $behaviorConfig) { + $behaviorInfo = $behaviorLibrary->getBehaviorInfo($behaviorClass); + $configFileName = $behaviorInfo['configFileName']; + + if (!strlen($configFileName)) { + continue; + } + + if (in_array($configFileName, $knownConfigFiles)) { + throw new ValidationException([ + 'behaviors' => Lang::get('rainlab.builder::lang.controller.error_behavior_config_conflict', [ + 'file' => $configFileName + ]) + ]); + } + + $knownConfigFiles[] = $configFileName; + + $destFilePath = $controllerPath.'/'.$configFileName; + if (File::isFile($destFilePath)) { + throw new ValidationException([ + 'behaviors' => Lang::get('rainlab.builder::lang.controller.error_behavior_config_file_exists', [ + 'file' => $destFilePath + ]) + ]); + } + + $configPropertyName = $behaviorInfo['configPropertyName']; + $this->configTemplateProperties[$configPropertyName] = $configFileName; + } + } + + /** + * validateControllerUnique + */ + protected function validateControllerUnique() + { + $controllerFilePath = $this->sourceModel->getControllerFilePath(); + + if (File::isFile($controllerFilePath)) { + throw new ValidationException([ + 'controller' => Lang::get('rainlab.builder::lang.controller.error_controller_exists', [ + 'file' => basename($controllerFilePath) + ]) + ]); + } + } + + /** + * setTemplateVars + */ + protected function setTemplateVars() + { + $pluginCodeObj = $this->sourceModel->getPluginCodeObj(); + + $this->templateVars['pluginNamespace'] = $pluginCodeObj->toPluginNamespace(); + $this->templateVars['pluginCode'] = $pluginCodeObj->toCode(); + $this->templateVars['permissions'] = $this->sourceModel->permissions; + $this->templateVars['controller'] = $this->sourceModel->controller; + $this->templateVars['controllerName'] = $this->sourceModel->controllerName; + $this->templateVars['baseModelClassName'] = $this->sourceModel->baseModelClassName; + + $this->templateVars['controllerUrl'] = $pluginCodeObj->toUrl().'/'.strtolower($this->sourceModel->controller); + + $menuItem = $this->sourceModel->menuItem; + if ($menuItem) { + $itemParts = explode('||', $menuItem); + $this->templateVars['menuItem'] = $itemParts[0]; + + if (count($itemParts) > 1) { + $this->templateVars['sideMenuItem'] = $itemParts[1]; + } + } + + if ($this->sourceModel->behaviors) { + $this->templateVars['behaviors'] = array_keys($this->sourceModel->behaviors); + } + else { + $this->templateVars['behaviors'] = []; + } + + $this->templateVars['behaviorConfigVars'] = $this->configTemplateProperties; + } + + /** + * getTemplatePath + */ + protected function getTemplatePath($template) + { + return __DIR__.'/controllergenerator/templates/'.$template; + } + + /** + * parseTemplate + */ + protected function parseTemplate($templatePath, $vars = []) + { + $template = File::get($templatePath); + + $vars = array_merge($this->templateVars, $vars); + $code = Twig::parse($template, $vars); + + return $code; + } + + /** + * writeFile + */ + protected function writeFile($path, $data) + { + $fileDirectory = dirname($path); + if (!File::isDirectory($fileDirectory)) { + if (!File::makeDirectory($fileDirectory, 0777, true, true)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.common.error_make_dir', [ + 'name' => $fileDirectory + ])); + } + } + + if (@File::put($path, $data) === false) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_save_file', [ + 'file' => basename($path) + ])); + } + + @File::chmod($path); + $this->filesGenerated[] = $path; + } + + /** + * rollback + */ + protected function rollback() + { + foreach ($this->filesGenerated as $path) { + @unlink($path); + } + } + + /** + * generateControllerFile + */ + protected function generateControllerFile() + { + $templateParts = []; + $code = $this->parseTemplate($this->getTemplatePath('controller-config-vars.php.tpl')); + if (strlen($code)) { + $templateParts[] = $code; + } + + $code = $this->parseTemplate($this->getTemplatePath('controller-permissions.php.tpl')); + if (strlen($code)) { + $templateParts[] = $code; + } + + if (count($templateParts)) { + $templateParts = "\n".implode("\n", $templateParts); + } + else { + $templateParts = ""; + } + + $noListTemplate = ""; + if ( + !array_key_exists(\Backend\Behaviors\ListController::class, $this->sourceModel->behaviors) && + array_key_exists(\Backend\Behaviors\FormController::class, $this->sourceModel->behaviors) + ) { + $noListTemplate = $this->parseTemplate($this->getTemplatePath('controller-no-list.php.tpl')); + } + + $code = $this->parseTemplate($this->getTemplatePath('controller.php.tpl'), [ + 'templateParts' => $templateParts, + 'noListTemplate' => $noListTemplate, + ]); + + $controllerFilePath = $this->sourceModel->getControllerFilePath(); + + $this->writeFile($controllerFilePath, $code); + } + + /** + * getBehaviorDesignTimeProvider + */ + protected function getBehaviorDesignTimeProvider($providerClass) + { + if (array_key_exists($providerClass, $this->designTimeProviders)) { + return $this->designTimeProviders[$providerClass]; + } + + return $this->designTimeProviders[$providerClass] = new $providerClass(null, []); + } + + /** + * generateConfigFiles + */ + protected function generateConfigFiles() + { + if (!$this->sourceModel->behaviors) { + return; + } + + $controllerPath = $this->sourceModel->getControllerFilePath(true); + $behaviorLibrary = ControllerBehaviorLibrary::instance(); + $dumper = new YamlDumper(); + + foreach ($this->sourceModel->behaviors as $behaviorClass => $behaviorConfig) { + $behaviorInfo = $behaviorLibrary->getBehaviorInfo($behaviorClass); + $configFileName = $behaviorInfo['configFileName']; + + if (!strlen($configFileName)) { + continue; + } + + $provider = $this->getBehaviorDesignTimeProvider($behaviorInfo['designTimeProvider']); + + $destFilePath = $controllerPath.'/'.$configFileName; + + try { + $configArray = $provider->getDefaultConfiguration($behaviorClass, $this->sourceModel, $this); + } + catch (Exception $ex) { + throw new ValidationException(['baseModelClassName' => $ex->getMessage()]); + } + + $configArray = array_merge($configArray, $behaviorConfig); + + $code = $dumper->dump($configArray, 20, 0, false, true); + + $this->writeFile($destFilePath, $code); + } + } + + /** + * generateViews + */ + protected function generateViews() + { + foreach ($this->templateFiles as $templatePath => $destPath) { + $code = $this->parseTemplate($templatePath); + + $this->writeFile($destPath, $code); + } + } +} diff --git a/plugins/rainlab/builder/classes/DatabaseTableSchemaCreator.php b/plugins/rainlab/builder/classes/DatabaseTableSchemaCreator.php new file mode 100644 index 0000000..b99a4c1 --- /dev/null +++ b/plugins/rainlab/builder/classes/DatabaseTableSchemaCreator.php @@ -0,0 +1,66 @@ +formatOptions($type, $column); + + $schema->addColumn($column['name'], $typeName, $options); + if ($column['primary_key']) { + $primaryKeyColumns[] = $column['name']; + } + } + + if ($primaryKeyColumns) { + $schema->setPrimaryKey($primaryKeyColumns); + } + + return $schema; + } + + /** + * Converts column options to a format supported by Doctrine\DBAL\Schema\Column + */ + protected function formatOptions($type, $options) + { + $result = MigrationColumnType::lengthToPrecisionAndScale($type, $options['length']); + + $result['unsigned'] = !!$options['unsigned']; + $result['notnull'] = !$options['allow_null']; + $result['autoincrement'] = !!$options['auto_increment']; + $result['comment'] = trim($options['comment'] ?? ''); + + // Note - this code doesn't allow to set empty string as default. + // But converting empty strings to NULLs is required for the further + // work with Doctrine types. As an option - empty strings could be specified + // as '' in the editor UI (table column editor). + $default = trim($options['default']); + $result['default'] = $default === '' ? null : $default; + + return $result; + } +} diff --git a/plugins/rainlab/builder/classes/EnumDbType.php b/plugins/rainlab/builder/classes/EnumDbType.php new file mode 100644 index 0000000..43777e6 --- /dev/null +++ b/plugins/rainlab/builder/classes/EnumDbType.php @@ -0,0 +1,38 @@ + 'plugin.php.tpl' + * ]; + * $generator = new FilesystemGenerator('$', $structure, '$/Author/Plugin/templates/plugin'); + * + * $variables = [ + * 'namespace' => 'Author/Plugin' + * ]; + * $generator->setVariables($variables); + * $generator->generate(); + * + * @package rainlab\builder + * @author Alexey Bobkov, Samuel Georges + */ +class FilesystemGenerator +{ + protected $destinationPath; + + protected $structure; + + protected $variables = []; + + protected $templatesPath; + + /** + * Initializes the object. + * @param string $destinationPath Destination path to create the filesystem objects in. + * The path can contain filesystem symbols. + * @param array $structure Specifies the structure as array. + * @param string $templatesPath Path to the directory that contains file templates. + * The parameter is required only in case any files should be created. The path can + * contain filesystem symbols. + */ + public function __construct($destinationPath, array $structure, $templatesPath = null) + { + $this->destinationPath = File::symbolizePath($destinationPath); + $this->structure = $structure; + + if ($templatesPath) { + $this->templatesPath = File::symbolizePath($templatesPath); + } + } + + public function setVariables($variables) + { + foreach ($variables as $key => $value) { + $this->setVariable($key, $value); + } + } + + public function setVariable($key, $value) + { + $this->variables[$key] = $value; + } + + public function generate() + { + if (!File::isDirectory($this->destinationPath)) { + throw new SystemException(Lang::get('rainlab.builder::lang.common.destination_dir_not_exists', ['path'=>$this->destinationPath])); + } + + foreach ($this->structure as $key => $value) { + if (is_numeric($key)) { + $this->makeDirectory($value); + } + else { + $this->makeFile($key, $value); + } + } + } + + public function getTemplateContents($templateName) + { + $templatePath = $this->templatesPath.DIRECTORY_SEPARATOR.$templateName; + if (!File::isFile($templatePath)) { + throw new SystemException(Lang::get('rainlab.builder::lang.common.template_not_found', ['name'=>$templateName])); + } + + $fileContents = File::get($templatePath); + + return TextParser::parse($fileContents, $this->variables); + } + + protected function makeDirectory($dirPath) + { + $path = $this->destinationPath.DIRECTORY_SEPARATOR.$dirPath; + + if (File::isDirectory($path)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.common.error_dir_exists', ['path'=>$path])); + } + + if (!File::makeDirectory($path, 0777, true, true)) { + throw new SystemException(Lang::get('rainlab.builder::lang.common.error_make_dir', ['name'=>$path])); + } + } + + protected function makeFile($filePath, $templateName) + { + $path = $this->destinationPath.DIRECTORY_SEPARATOR.$filePath; + + if (File::isFile($path)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.common.error_file_exists', ['path'=>$path])); + } + + $fileDirectory = dirname($path); + if (!File::isDirectory($fileDirectory)) { + if (!File::makeDirectory($fileDirectory, 0777, true, true)) { + throw new SystemException(Lang::get('rainlab.builder::lang.common.error_make_dir', ['name'=>$fileDirectory])); + } + } + + $fileContents = $this->getTemplateContents($templateName); + if (@File::put($path, $fileContents) === false) { + throw new SystemException(Lang::get('rainlab.builder::lang.common.error_generating_file', ['path'=>$path])); + } + + @File::chmod($path); + } +} diff --git a/plugins/rainlab/builder/classes/IconList.php b/plugins/rainlab/builder/classes/IconList.php new file mode 100644 index 0000000..ab2eace --- /dev/null +++ b/plugins/rainlab/builder/classes/IconList.php @@ -0,0 +1,607 @@ + ['adjust', 'oc-icon-adjust'], + 'oc-icon-adn' => ['adn', 'oc-icon-adn'], + 'oc-icon-align-center' => ['align-center', 'oc-icon-align-center'], + 'oc-icon-align-justify' => ['align-justify', 'oc-icon-align-justify'], + 'oc-icon-align-left' => ['align-left', 'oc-icon-align-left'], + 'oc-icon-align-right' => ['align-right', 'oc-icon-align-right'], + 'oc-icon-ambulance' => ['ambulance', 'oc-icon-ambulance'], + 'oc-icon-anchor' => ['anchor', 'oc-icon-anchor'], + 'oc-icon-android' => ['android', 'oc-icon-android'], + 'oc-icon-angellist' => ['angellist', 'oc-icon-angellist'], + 'oc-icon-angle-double-down' => ['angle-double-down', 'oc-icon-angle-double-down'], + 'oc-icon-angle-double-left' => ['angle-double-left', 'oc-icon-angle-double-left'], + 'oc-icon-angle-double-right' => ['angle-double-right', 'oc-icon-angle-double-right'], + 'oc-icon-angle-double-up' => ['angle-double-up', 'oc-icon-angle-double-up'], + 'oc-icon-angle-down' => ['angle-down', 'oc-icon-angle-down'], + 'oc-icon-angle-left' => ['angle-left', 'oc-icon-angle-left'], + 'oc-icon-angle-right' => ['angle-right', 'oc-icon-angle-right'], + 'oc-icon-angle-up' => ['angle-up', 'oc-icon-angle-up'], + 'oc-icon-apple' => ['apple', 'oc-icon-apple'], + 'oc-icon-archive' => ['archive', 'oc-icon-archive'], + 'oc-icon-area-chart' => ['area-chart', 'oc-icon-area-chart'], + 'oc-icon-arrow-circle-down' => ['arrow-circle-down', 'oc-icon-arrow-circle-down'], + 'oc-icon-arrow-circle-left' => ['arrow-circle-left', 'oc-icon-arrow-circle-left'], + 'oc-icon-arrow-circle-o-down' => ['arrow-circle-o-down', 'oc-icon-arrow-circle-o-down'], + 'oc-icon-arrow-circle-o-left' => ['arrow-circle-o-left', 'oc-icon-arrow-circle-o-left'], + 'oc-icon-arrow-circle-o-right' => ['arrow-circle-o-right', 'oc-icon-arrow-circle-o-right'], + 'oc-icon-arrow-circle-o-up' => ['arrow-circle-o-up', 'oc-icon-arrow-circle-o-up'], + 'oc-icon-arrow-circle-right' => ['arrow-circle-right', 'oc-icon-arrow-circle-right'], + 'oc-icon-arrow-circle-up' => ['arrow-circle-up', 'oc-icon-arrow-circle-up'], + 'oc-icon-arrow-down' => ['arrow-down', 'oc-icon-arrow-down'], + 'oc-icon-arrow-left' => ['arrow-left', 'oc-icon-arrow-left'], + 'oc-icon-arrow-right' => ['arrow-right', 'oc-icon-arrow-right'], + 'oc-icon-arrow-up' => ['arrow-up', 'oc-icon-arrow-up'], + 'oc-icon-arrows' => ['arrows', 'oc-icon-arrows'], + 'oc-icon-arrows-alt' => ['arrows-alt', 'oc-icon-arrows-alt'], + 'oc-icon-arrows-h' => ['arrows-h', 'oc-icon-arrows-h'], + 'oc-icon-arrows-v' => ['arrows-v', 'oc-icon-arrows-v'], + 'oc-icon-asterisk' => ['asterisk', 'oc-icon-asterisk'], + 'oc-icon-at' => ['at', 'oc-icon-at'], + 'oc-icon-automobile' => ['automobile', 'oc-icon-automobile'], + 'oc-icon-backward' => ['backward', 'oc-icon-backward'], + 'oc-icon-ban' => ['ban', 'oc-icon-ban'], + 'oc-icon-bank' => ['bank', 'oc-icon-bank'], + 'oc-icon-bar-chart' => ['bar-chart', 'oc-icon-bar-chart'], + 'oc-icon-bar-chart-o' => ['bar-chart-o', 'oc-icon-bar-chart-o'], + 'oc-icon-barcode' => ['barcode', 'oc-icon-barcode'], + 'oc-icon-bars' => ['bars', 'oc-icon-bars'], + 'oc-icon-bed' => ['bed', 'oc-icon-bed'], + 'oc-icon-beer' => ['beer', 'oc-icon-beer'], + 'oc-icon-behance' => ['behance', 'oc-icon-behance'], + 'oc-icon-behance-square' => ['behance-square', 'oc-icon-behance-square'], + 'oc-icon-bell' => ['bell', 'oc-icon-bell'], + 'oc-icon-bell-o' => ['bell-o', 'oc-icon-bell-o'], + 'oc-icon-bell-slash' => ['bell-slash', 'oc-icon-bell-slash'], + 'oc-icon-bell-slash-o' => ['bell-slash-o', 'oc-icon-bell-slash-o'], + 'oc-icon-bicycle' => ['bicycle', 'oc-icon-bicycle'], + 'oc-icon-binoculars' => ['binoculars', 'oc-icon-binoculars'], + 'oc-icon-birthday-cake' => ['birthday-cake', 'oc-icon-birthday-cake'], + 'oc-icon-bitbucket' => ['bitbucket', 'oc-icon-bitbucket'], + 'oc-icon-bitbucket-square' => ['bitbucket-square', 'oc-icon-bitbucket-square'], + 'oc-icon-bitcoin' => ['bitcoin', 'oc-icon-bitcoin'], + 'oc-icon-bold' => ['bold', 'oc-icon-bold'], + 'oc-icon-bolt' => ['bolt', 'oc-icon-bolt'], + 'oc-icon-bomb' => ['bomb', 'oc-icon-bomb'], + 'oc-icon-book' => ['book', 'oc-icon-book'], + 'oc-icon-bookmark' => ['bookmark', 'oc-icon-bookmark'], + 'oc-icon-bookmark-o' => ['bookmark-o', 'oc-icon-bookmark-o'], + 'oc-icon-briefcase' => ['briefcase', 'oc-icon-briefcase'], + 'oc-icon-btc' => ['btc', 'oc-icon-btc'], + 'oc-icon-bug' => ['bug', 'oc-icon-bug'], + 'oc-icon-building' => ['building', 'oc-icon-building'], + 'oc-icon-building-o' => ['building-o', 'oc-icon-building-o'], + 'oc-icon-bullhorn' => ['bullhorn', 'oc-icon-bullhorn'], + 'oc-icon-bullseye' => ['bullseye', 'oc-icon-bullseye'], + 'oc-icon-bus' => ['bus', 'oc-icon-bus'], + 'oc-icon-buysellads' => ['buysellads', 'oc-icon-buysellads'], + 'oc-icon-cab' => ['cab', 'oc-icon-cab'], + 'oc-icon-calculator' => ['calculator', 'oc-icon-calculator'], + 'oc-icon-calendar' => ['calendar', 'oc-icon-calendar'], + 'oc-icon-calendar-o' => ['calendar-o', 'oc-icon-calendar-o'], + 'oc-icon-camera' => ['camera', 'oc-icon-camera'], + 'oc-icon-camera-retro' => ['camera-retro', 'oc-icon-camera-retro'], + 'oc-icon-car' => ['car', 'oc-icon-car'], + 'oc-icon-caret-down' => ['caret-down', 'oc-icon-caret-down'], + 'oc-icon-caret-left' => ['caret-left', 'oc-icon-caret-left'], + 'oc-icon-caret-right' => ['caret-right', 'oc-icon-caret-right'], + 'oc-icon-caret-square-o-down' => ['caret-square-o-down', 'oc-icon-caret-square-o-down'], + 'oc-icon-caret-square-o-left' => ['caret-square-o-left', 'oc-icon-caret-square-o-left'], + 'oc-icon-caret-square-o-right' => ['caret-square-o-right', 'oc-icon-caret-square-o-right'], + 'oc-icon-caret-square-o-up' => ['caret-square-o-up', 'oc-icon-caret-square-o-up'], + 'oc-icon-caret-up' => ['caret-up', 'oc-icon-caret-up'], + 'oc-icon-cart-arrow-down' => ['cart-arrow-down', 'oc-icon-cart-arrow-down'], + 'oc-icon-cart-plus' => ['cart-plus', 'oc-icon-cart-plus'], + 'oc-icon-cc' => ['cc', 'oc-icon-cc'], + 'oc-icon-cc-amex' => ['cc-amex', 'oc-icon-cc-amex'], + 'oc-icon-cc-discover' => ['cc-discover', 'oc-icon-cc-discover'], + 'oc-icon-cc-mastercard' => ['cc-mastercard', 'oc-icon-cc-mastercard'], + 'oc-icon-cc-paypal' => ['cc-paypal', 'oc-icon-cc-paypal'], + 'oc-icon-cc-stripe' => ['cc-stripe', 'oc-icon-cc-stripe'], + 'oc-icon-cc-visa' => ['cc-visa', 'oc-icon-cc-visa'], + 'oc-icon-certificate' => ['certificate', 'oc-icon-certificate'], + 'oc-icon-chain' => ['chain', 'oc-icon-chain'], + 'oc-icon-chain-broken' => ['chain-broken', 'oc-icon-chain-broken'], + 'oc-icon-check' => ['check', 'oc-icon-check'], + 'oc-icon-check-circle' => ['check-circle', 'oc-icon-check-circle'], + 'oc-icon-check-circle-o' => ['check-circle-o', 'oc-icon-check-circle-o'], + 'oc-icon-check-square' => ['check-square', 'oc-icon-check-square'], + 'oc-icon-check-square-o' => ['check-square-o', 'oc-icon-check-square-o'], + 'oc-icon-chevron-circle-down' => ['chevron-circle-down', 'oc-icon-chevron-circle-down'], + 'oc-icon-chevron-circle-left' => ['chevron-circle-left', 'oc-icon-chevron-circle-left'], + 'oc-icon-chevron-circle-right' => ['chevron-circle-right', 'oc-icon-chevron-circle-right'], + 'oc-icon-chevron-circle-up' => ['chevron-circle-up', 'oc-icon-chevron-circle-up'], + 'oc-icon-chevron-down' => ['chevron-down', 'oc-icon-chevron-down'], + 'oc-icon-chevron-left' => ['chevron-left', 'oc-icon-chevron-left'], + 'oc-icon-chevron-right' => ['chevron-right', 'oc-icon-chevron-right'], + 'oc-icon-chevron-up' => ['chevron-up', 'oc-icon-chevron-up'], + 'oc-icon-child' => ['child', 'oc-icon-child'], + 'oc-icon-circle' => ['circle', 'oc-icon-circle'], + 'oc-icon-circle-o' => ['circle-o', 'oc-icon-circle-o'], + 'oc-icon-circle-o-notch' => ['circle-o-notch', 'oc-icon-circle-o-notch'], + 'oc-icon-circle-thin' => ['circle-thin', 'oc-icon-circle-thin'], + 'oc-icon-clipboard' => ['clipboard', 'oc-icon-clipboard'], + 'oc-icon-clock-o' => ['clock-o', 'oc-icon-clock-o'], + 'oc-icon-close' => ['close', 'oc-icon-close'], + 'oc-icon-cloud' => ['cloud', 'oc-icon-cloud'], + 'oc-icon-cloud-download' => ['cloud-download', 'oc-icon-cloud-download'], + 'oc-icon-cloud-upload' => ['cloud-upload', 'oc-icon-cloud-upload'], + 'oc-icon-cny' => ['cny', 'oc-icon-cny'], + 'oc-icon-code' => ['code', 'oc-icon-code'], + 'oc-icon-code-fork' => ['code-fork', 'oc-icon-code-fork'], + 'oc-icon-codepen' => ['codepen', 'oc-icon-codepen'], + 'oc-icon-coffee' => ['coffee', 'oc-icon-coffee'], + 'oc-icon-cog' => ['cog', 'oc-icon-cog'], + 'oc-icon-cogs' => ['cogs', 'oc-icon-cogs'], + 'oc-icon-columns' => ['columns', 'oc-icon-columns'], + 'oc-icon-comment' => ['comment', 'oc-icon-comment'], + 'oc-icon-comment-o' => ['comment-o', 'oc-icon-comment-o'], + 'oc-icon-comments' => ['comments', 'oc-icon-comments'], + 'oc-icon-comments-o' => ['comments-o', 'oc-icon-comments-o'], + 'oc-icon-compass' => ['compass', 'oc-icon-compass'], + 'oc-icon-compress' => ['compress', 'oc-icon-compress'], + 'oc-icon-connectdevelop' => ['connectdevelop', 'oc-icon-connectdevelop'], + 'oc-icon-copy' => ['copy', 'oc-icon-copy'], + 'oc-icon-copyright' => ['copyright', 'oc-icon-copyright'], + 'oc-icon-credit-card' => ['credit-card', 'oc-icon-credit-card'], + 'oc-icon-crop' => ['crop', 'oc-icon-crop'], + 'oc-icon-crosshairs' => ['crosshairs', 'oc-icon-crosshairs'], + 'oc-icon-css3' => ['css3', '|'], + 'oc-icon-cube' => ['cube', 'oc-icon-cube'], + 'oc-icon-cubes' => ['cubes', 'oc-icon-cubes'], + 'oc-icon-cut' => ['cut', 'oc-icon-cut'], + 'oc-icon-cutlery' => ['cutlery', 'oc-icon-cutlery'], + 'oc-icon-dashboard' => ['dashboard', 'oc-icon-dashboard'], + 'oc-icon-dashcube' => ['dashcube', 'oc-icon-dashcube'], + 'oc-icon-database' => ['database', 'oc-icon-database'], + 'oc-icon-dedent' => ['dedent', 'oc-icon-dedent'], + 'oc-icon-delicious' => ['delicious', 'oc-icon-delicious'], + 'oc-icon-desktop' => ['desktop', 'oc-icon-desktop'], + 'oc-icon-deviantart' => ['deviantart', 'oc-icon-deviantart'], + 'oc-icon-diamond' => ['diamond', 'oc-icon-diamond'], + 'oc-icon-digg' => ['digg', 'oc-icon-digg'], + 'oc-icon-dollar' => ['dollar', 'oc-icon-dollar'], + 'oc-icon-dot-circle-o' => ['dot-circle-o', 'oc-icon-dot-circle-o'], + 'oc-icon-download' => ['download', 'oc-icon-download'], + 'oc-icon-dribbble' => ['dribbble', 'oc-icon-dribbble'], + 'oc-icon-dropbox' => ['dropbox', 'oc-icon-dropbox'], + 'oc-icon-drupal' => ['drupal', 'oc-icon-drupal'], + 'oc-icon-edit' => ['edit', 'oc-icon-edit'], + 'oc-icon-eject' => ['eject', 'oc-icon-eject'], + 'oc-icon-ellipsis-h' => ['ellipsis-h', 'oc-icon-ellipsis-h'], + 'oc-icon-ellipsis-v' => ['ellipsis-v', 'oc-icon-ellipsis-v'], + 'oc-icon-empire' => ['empire', 'oc-icon-empire'], + 'oc-icon-envelope' => ['envelope', 'oc-icon-envelope'], + 'oc-icon-envelope-o' => ['envelope-o', 'oc-icon-envelope-o'], + 'oc-icon-envelope-square' => ['envelope-square', 'oc-icon-envelope-square'], + 'oc-icon-eraser' => ['eraser', 'oc-icon-eraser'], + 'oc-icon-eur' => ['eur', 'oc-icon-eur'], + 'oc-icon-euro' => ['euro', 'oc-icon-euro'], + 'oc-icon-exchange' => ['exchange', 'oc-icon-exchange'], + 'oc-icon-exclamation' => ['exclamation', 'oc-icon-exclamation'], + 'oc-icon-exclamation-circle' => ['exclamation-circle', 'oc-icon-exclamation-circle'], + 'oc-icon-exclamation-triangle' => ['exclamation-triangle', 'oc-icon-exclamation-triangle'], + 'oc-icon-expand' => ['expand', 'oc-icon-expand'], + 'oc-icon-external-link' => ['external-link', 'oc-icon-external-link'], + 'oc-icon-external-link-square' => ['external-link-square', 'oc-icon-external-link-square'], + 'oc-icon-eye' => ['eye', 'oc-icon-eye'], + 'oc-icon-eye-slash' => ['eye-slash', 'oc-icon-eye-slash'], + 'oc-icon-eyedropper' => ['eyedropper', 'oc-icon-eyedropper'], + 'oc-icon-facebook' => ['facebook', 'oc-icon-facebook'], + 'oc-icon-facebook-f' => ['facebook-f', 'oc-icon-facebook-f'], + 'oc-icon-facebook-official' => ['facebook-official', 'oc-icon-facebook-official'], + 'oc-icon-facebook-square' => ['facebook-square', 'oc-icon-facebook-square'], + 'oc-icon-fast-backward' => ['fast-backward', 'oc-icon-fast-backward'], + 'oc-icon-fast-forward' => ['fast-forward', 'oc-icon-fast-forward'], + 'oc-icon-fax' => ['fax', 'oc-icon-fax'], + 'oc-icon-female' => ['female', 'oc-icon-female'], + 'oc-icon-fighter-jet' => ['fighter-jet', 'oc-icon-fighter-jet'], + 'oc-icon-file' => ['file', 'oc-icon-file'], + 'oc-icon-file-archive-o' => ['file-archive-o', 'oc-icon-file-archive-o'], + 'oc-icon-file-audio-o' => ['file-audio-o', 'oc-icon-file-audio-o'], + 'oc-icon-file-code-o' => ['file-code-o', 'oc-icon-file-code-o'], + 'oc-icon-file-excel-o' => ['file-excel-o', 'oc-icon-file-excel-o'], + 'oc-icon-file-image-o' => ['file-image-o', 'oc-icon-file-image-o'], + 'oc-icon-file-movie-o' => ['file-movie-o', 'oc-icon-file-movie-o'], + 'oc-icon-file-o' => ['file-o', 'oc-icon-file-o'], + 'oc-icon-file-pdf-o' => ['file-pdf-o', 'oc-icon-file-pdf-o'], + 'oc-icon-file-photo-o' => ['file-photo-o', 'oc-icon-file-photo-o'], + 'oc-icon-file-picture-o' => ['file-picture-o', 'oc-icon-file-picture-o'], + 'oc-icon-file-powerpoint-o' => ['file-powerpoint-o', 'oc-icon-file-powerpoint-o'], + 'oc-icon-file-sound-o' => ['file-sound-o', 'oc-icon-file-sound-o'], + 'oc-icon-file-text' => ['file-text', 'oc-icon-file-text'], + 'oc-icon-file-text-o' => ['file-text-o', 'oc-icon-file-text-o'], + 'oc-icon-file-video-o' => ['file-video-o', 'oc-icon-file-video-o'], + 'oc-icon-file-word-o' => ['file-word-o', 'oc-icon-file-word-o'], + 'oc-icon-file-zip-o' => ['file-zip-o', 'oc-icon-file-zip-o'], + 'oc-icon-files-o' => ['files-o', 'oc-icon-files-o'], + 'oc-icon-film' => ['film', 'oc-icon-film'], + 'oc-icon-filter' => ['filter', 'oc-icon-filter'], + 'oc-icon-fire' => ['fire', 'oc-icon-fire'], + 'oc-icon-fire-extinguisher' => ['fire-extinguisher', 'oc-icon-fire-extinguisher'], + 'oc-icon-flag' => ['flag', 'oc-icon-flag'], + 'oc-icon-flag-checkered' => ['flag-checkered', 'oc-icon-flag-checkered'], + 'oc-icon-flag-o' => ['flag-o', 'oc-icon-flag-o'], + 'oc-icon-flash' => ['flash', 'oc-icon-flash'], + 'oc-icon-flask' => ['flask', 'oc-icon-flask'], + 'oc-icon-flickr' => ['flickr', 'oc-icon-flickr'], + 'oc-icon-floppy-o' => ['floppy-o', 'oc-icon-floppy-o'], + 'oc-icon-folder' => ['folder', 'oc-icon-folder'], + 'oc-icon-folder-o' => ['folder-o', 'oc-icon-folder-o'], + 'oc-icon-folder-open' => ['folder-open', 'oc-icon-folder-open'], + 'oc-icon-folder-open-o' => ['folder-open-o', 'oc-icon-folder-open-o'], + 'oc-icon-font' => ['font', 'oc-icon-font'], + 'oc-icon-forumbee' => ['forumbee', 'oc-icon-forumbee'], + 'oc-icon-forward' => ['forward', 'oc-icon-forward'], + 'oc-icon-foursquare' => ['foursquare', 'oc-icon-foursquare'], + 'oc-icon-frown-o' => ['frown-o', 'oc-icon-frown-o'], + 'oc-icon-futbol-o' => ['futbol-o', 'oc-icon-futbol-o'], + 'oc-icon-gamepad' => ['gamepad', 'oc-icon-gamepad'], + 'oc-icon-gavel' => ['gavel', 'oc-icon-gavel'], + 'oc-icon-gbp' => ['gbp', 'oc-icon-gbp'], + 'oc-icon-ge' => ['ge', 'oc-icon-ge'], + 'oc-icon-gear' => ['gear', 'oc-icon-gear'], + 'oc-icon-gears' => ['gears', 'oc-icon-gears'], + 'oc-icon-genderless' => ['genderless', 'oc-icon-genderless'], + 'oc-icon-gift' => ['gift', 'oc-icon-gift'], + 'oc-icon-git' => ['git', 'oc-icon-git'], + 'oc-icon-git-square' => ['git-square', 'oc-icon-git-square'], + 'oc-icon-github' => ['github', 'oc-icon-github'], + 'oc-icon-github-alt' => ['github-alt', 'oc-icon-github-alt'], + 'oc-icon-github-square' => ['github-square', 'oc-icon-github-square'], + 'oc-icon-gittip' => ['gittip', 'oc-icon-gittip'], + 'oc-icon-glass' => ['glass', 'oc-icon-glass'], + 'oc-icon-globe' => ['globe', 'oc-icon-globe'], + 'oc-icon-google' => ['google', 'oc-icon-google'], + 'oc-icon-google-plus' => ['google-plus', 'oc-icon-google-plus'], + 'oc-icon-google-plus-square' => ['google-plus-square', 'oc-icon-google-plus-square'], + 'oc-icon-google-wallet' => ['google-wallet', 'oc-icon-google-wallet'], + 'oc-icon-graduation-cap' => ['graduation-cap', 'oc-icon-graduation-cap'], + 'oc-icon-gratipay' => ['gratipay', 'oc-icon-gratipay'], + 'oc-icon-group' => ['group', 'oc-icon-group'], + 'oc-icon-h-square' => ['h-square', 'oc-icon-h-square'], + 'oc-icon-hacker-news' => ['hacker-news', 'oc-icon-hacker-news'], + 'oc-icon-hand-o-down' => ['hand-o-down', 'oc-icon-hand-o-down'], + 'oc-icon-hand-o-left' => ['hand-o-left', 'oc-icon-hand-o-left'], + 'oc-icon-hand-o-right' => ['hand-o-right', 'oc-icon-hand-o-right'], + 'oc-icon-hand-o-up' => ['hand-o-up', 'oc-icon-hand-o-up'], + 'oc-icon-hdd-o' => ['hdd-o', 'oc-icon-hdd-o'], + 'oc-icon-header' => ['header', 'oc-icon-header'], + 'oc-icon-headphones' => ['headphones', 'oc-icon-headphones'], + 'oc-icon-heart' => ['heart', 'oc-icon-heart'], + 'oc-icon-heart-o' => ['heart-o', 'oc-icon-heart-o'], + 'oc-icon-heartbeat' => ['heartbeat', 'oc-icon-heartbeat'], + 'oc-icon-history' => ['history', 'oc-icon-history'], + 'oc-icon-home' => ['home', 'oc-icon-home'], + 'oc-icon-hospital-o' => ['hospital-o', 'oc-icon-hospital-o'], + 'oc-icon-hotel' => ['hotel', 'oc-icon-hotel'], + 'oc-icon-html5' => ['html5', '|'], + 'oc-icon-ils' => ['ils', 'oc-icon-ils'], + 'oc-icon-image' => ['image', 'oc-icon-image'], + 'oc-icon-inbox' => ['inbox', 'oc-icon-inbox'], + 'oc-icon-indent' => ['indent', 'oc-icon-indent'], + 'oc-icon-info' => ['info', 'oc-icon-info'], + 'oc-icon-info-circle' => ['info-circle', 'oc-icon-info-circle'], + 'oc-icon-inr' => ['inr', 'oc-icon-inr'], + 'oc-icon-instagram' => ['instagram', 'oc-icon-instagram'], + 'oc-icon-institution' => ['institution', 'oc-icon-institution'], + 'oc-icon-ioxhost' => ['ioxhost', 'oc-icon-ioxhost'], + 'oc-icon-italic' => ['italic', 'oc-icon-italic'], + 'oc-icon-joomla' => ['joomla', 'oc-icon-joomla'], + 'oc-icon-jpy' => ['jpy', 'oc-icon-jpy'], + 'oc-icon-jsfiddle' => ['jsfiddle', 'oc-icon-jsfiddle'], + 'oc-icon-key' => ['key', 'oc-icon-key'], + 'oc-icon-keyboard-o' => ['keyboard-o', 'oc-icon-keyboard-o'], + 'oc-icon-krw' => ['krw', 'oc-icon-krw'], + 'oc-icon-language' => ['language', 'oc-icon-language'], + 'oc-icon-laptop' => ['laptop', 'oc-icon-laptop'], + 'oc-icon-lastfm' => ['lastfm', 'oc-icon-lastfm'], + 'oc-icon-lastfm-square' => ['lastfm-square', 'oc-icon-lastfm-square'], + 'oc-icon-leaf' => ['leaf', 'oc-icon-leaf'], + 'oc-icon-leanpub' => ['leanpub', 'oc-icon-leanpub'], + 'oc-icon-legal' => ['legal', 'oc-icon-legal'], + 'oc-icon-lemon-o' => ['lemon-o', 'oc-icon-lemon-o'], + 'oc-icon-level-down' => ['level-down', 'oc-icon-level-down'], + 'oc-icon-level-up' => ['level-up', 'oc-icon-level-up'], + 'oc-icon-life-bouy' => ['life-bouy', 'oc-icon-life-bouy'], + 'oc-icon-lightbulb-o' => ['lightbulb-o', 'oc-icon-lightbulb-o'], + 'oc-icon-line-chart' => ['line-chart', 'oc-icon-line-chart'], + 'oc-icon-link' => ['link', 'oc-icon-link'], + 'oc-icon-linkedin' => ['linkedin', 'oc-icon-linkedin'], + 'oc-icon-linkedin-square' => ['linkedin-square', 'oc-icon-linkedin-square'], + 'oc-icon-linux' => ['linux', 'oc-icon-linux'], + 'oc-icon-list' => ['list', 'oc-icon-list'], + 'oc-icon-list-alt' => ['list-alt', 'oc-icon-list-alt'], + 'oc-icon-list-ol' => ['list-ol', 'oc-icon-list-ol'], + 'oc-icon-list-ul' => ['list-ul', 'oc-icon-list-ul'], + 'oc-icon-location-arrow' => ['location-arrow', 'oc-icon-location-arrow'], + 'oc-icon-lock' => ['lock', 'oc-icon-lock'], + 'oc-icon-long-arrow-down' => ['long-arrow-down', 'oc-icon-long-arrow-down'], + 'oc-icon-long-arrow-left' => ['long-arrow-left', 'oc-icon-long-arrow-left'], + 'oc-icon-long-arrow-right' => ['long-arrow-right', 'oc-icon-long-arrow-right'], + 'oc-icon-long-arrow-up' => ['long-arrow-up', 'oc-icon-long-arrow-up'], + 'oc-icon-magic' => ['magic', 'oc-icon-magic'], + 'oc-icon-magnet' => ['magnet', 'oc-icon-magnet'], + 'oc-icon-mail-forward' => ['mail-forward', 'oc-icon-mail-forward'], + 'oc-icon-mail-reply' => ['mail-reply', 'oc-icon-mail-reply'], + 'oc-icon-mail-reply-all' => ['mail-reply-all', 'oc-icon-mail-reply-all'], + 'oc-icon-male' => ['male', 'oc-icon-male'], + 'oc-icon-map-marker' => ['map-marker', 'oc-icon-map-marker'], + 'oc-icon-mars' => ['mars', 'oc-icon-mars'], + 'oc-icon-mars-double' => ['mars-double', 'oc-icon-mars-double'], + 'oc-icon-mars-stroke' => ['mars-stroke', 'oc-icon-mars-stroke'], + 'oc-icon-mars-stroke-h' => ['mars-stroke-h', 'oc-icon-mars-stroke-h'], + 'oc-icon-mars-stroke-v' => ['mars-stroke-v', 'oc-icon-mars-stroke-v'], + 'oc-icon-maxcdn' => ['maxcdn', 'oc-icon-maxcdn'], + 'oc-icon-meanpath' => ['meanpath', 'oc-icon-meanpath'], + 'oc-icon-medium' => ['medium', 'oc-icon-medium'], + 'oc-icon-medkit' => ['medkit', 'oc-icon-medkit'], + 'oc-icon-meh-o' => ['meh-o', 'oc-icon-meh-o'], + 'oc-icon-mercury' => ['mercury', 'oc-icon-mercury'], + 'oc-icon-microphone' => ['microphone', 'oc-icon-microphone'], + 'oc-icon-microphone-slash' => ['microphone-slash', 'oc-icon-microphone-slash'], + 'oc-icon-minus' => ['minus', 'oc-icon-minus'], + 'oc-icon-minus-circle' => ['minus-circle', 'oc-icon-minus-circle'], + 'oc-icon-minus-square' => ['minus-square', 'oc-icon-minus-square'], + 'oc-icon-minus-square-o' => ['minus-square-o', 'oc-icon-minus-square-o'], + 'oc-icon-mobile' => ['mobile', 'oc-icon-mobile'], + 'oc-icon-mobile-phone' => ['mobile-phone', 'oc-icon-mobile-phone'], + 'oc-icon-money' => ['money', 'oc-icon-money'], + 'oc-icon-moon-o' => ['moon-o', 'oc-icon-moon-o'], + 'oc-icon-mortar-board' => ['mortar-board', 'oc-icon-mortar-board'], + 'oc-icon-motorcycle' => ['motorcycle', 'oc-icon-motorcycle'], + 'oc-icon-music' => ['music', 'oc-icon-music'], + 'oc-icon-navicon' => ['navicon', 'oc-icon-navicon'], + 'oc-icon-neuter' => ['neuter', 'oc-icon-neuter'], + 'oc-icon-newspaper-o' => ['newspaper-o', 'oc-icon-newspaper-o'], + 'oc-icon-openid' => ['openid', 'oc-icon-openid'], + 'oc-icon-outdent' => ['outdent', 'oc-icon-outdent'], + 'oc-icon-pagelines' => ['pagelines', 'oc-icon-pagelines'], + 'oc-icon-paint-brush' => ['paint-brush', 'oc-icon-paint-brush'], + 'oc-icon-paper-plane' => ['paper-plane', 'oc-icon-paper-plane'], + 'oc-icon-paper-plane-o' => ['paper-plane-o', 'oc-icon-paper-plane-o'], + 'oc-icon-paperclip' => ['paperclip', 'oc-icon-paperclip'], + 'oc-icon-paragraph' => ['paragraph', 'oc-icon-paragraph'], + 'oc-icon-paste' => ['paste', 'oc-icon-paste'], + 'oc-icon-pause' => ['pause', 'oc-icon-pause'], + 'oc-icon-paw' => ['paw', 'oc-icon-paw'], + 'oc-icon-paypal' => ['paypal', 'oc-icon-paypal'], + 'oc-icon-pencil' => ['pencil', 'oc-icon-pencil'], + 'oc-icon-pencil-square' => ['pencil-square', 'oc-icon-pencil-square'], + 'oc-icon-pencil-square-o' => ['pencil-square-o', 'oc-icon-pencil-square-o'], + 'oc-icon-phone' => ['phone', 'oc-icon-phone'], + 'oc-icon-phone-square' => ['phone-square', 'oc-icon-phone-square'], + 'oc-icon-photo' => ['photo', 'oc-icon-photo'], + 'oc-icon-picture-o' => ['picture-o', 'oc-icon-picture-o'], + 'oc-icon-pie-chart' => ['pie-chart', 'oc-icon-pie-chart'], + 'oc-icon-pied-piper' => ['pied-piper', 'oc-icon-pied-piper'], + 'oc-icon-pied-piper-alt' => ['pied-piper-alt', 'oc-icon-pied-piper-alt'], + 'oc-icon-pinterest' => ['pinterest', 'oc-icon-pinterest'], + 'oc-icon-pinterest-p' => ['pinterest-p', 'oc-icon-pinterest-p'], + 'oc-icon-pinterest-square' => ['pinterest-square', 'oc-icon-pinterest-square'], + 'oc-icon-plane' => ['plane', 'oc-icon-plane'], + 'oc-icon-play' => ['play', 'oc-icon-play'], + 'oc-icon-play-circle' => ['play-circle', 'oc-icon-play-circle'], + 'oc-icon-play-circle-o' => ['play-circle-o', 'oc-icon-play-circle-o'], + 'oc-icon-plug' => ['plug', 'oc-icon-plug'], + 'oc-icon-plus' => ['plus', 'oc-icon-plus'], + 'oc-icon-plus-circle' => ['plus-circle', 'oc-icon-plus-circle'], + 'oc-icon-plus-square' => ['plus-square', 'oc-icon-plus-square'], + 'oc-icon-plus-square-o' => ['plus-square-o', 'oc-icon-plus-square-o'], + 'oc-icon-power-off' => ['power-off', 'oc-icon-power-off'], + 'oc-icon-print' => ['print', 'oc-icon-print'], + 'oc-icon-puzzle-piece' => ['puzzle-piece', 'oc-icon-puzzle-piece'], + 'oc-icon-qq' => ['qq', 'oc-icon-qq'], + 'oc-icon-qrcode' => ['qrcode', 'oc-icon-qrcode'], + 'oc-icon-question' => ['question', 'oc-icon-question'], + 'oc-icon-question-circle' => ['question-circle', 'oc-icon-question-circle'], + 'oc-icon-quote-left' => ['quote-left', 'oc-icon-quote-left'], + 'oc-icon-quote-right' => ['quote-right', 'oc-icon-quote-right'], + 'oc-icon-ra' => ['ra', 'oc-icon-ra'], + 'oc-icon-random' => ['random', 'oc-icon-random'], + 'oc-icon-rebel' => ['rebel', 'oc-icon-rebel'], + 'oc-icon-recycle' => ['recycle', 'oc-icon-recycle'], + 'oc-icon-reddit' => ['reddit', 'oc-icon-reddit'], + 'oc-icon-reddit-square' => ['reddit-square', 'oc-icon-reddit-square'], + 'oc-icon-refresh' => ['refresh', 'oc-icon-refresh'], + 'oc-icon-remove' => ['remove', 'oc-icon-remove'], + 'oc-icon-renren' => ['renren', 'oc-icon-renren'], + 'oc-icon-reorder' => ['reorder', 'oc-icon-reorder'], + 'oc-icon-repeat' => ['repeat', 'oc-icon-repeat'], + 'oc-icon-reply' => ['reply', 'oc-icon-reply'], + 'oc-icon-reply-all' => ['reply-all', 'oc-icon-reply-all'], + 'oc-icon-retweet' => ['retweet', 'oc-icon-retweet'], + 'oc-icon-rmb' => ['rmb', 'oc-icon-rmb'], + 'oc-icon-road' => ['road', 'oc-icon-road'], + 'oc-icon-rocket' => ['rocket', 'oc-icon-rocket'], + 'oc-icon-rotate-left' => ['rotate-left', 'oc-icon-rotate-left'], + 'oc-icon-rotate-right' => ['rotate-right', 'oc-icon-rotate-right'], + 'oc-icon-rouble' => ['rouble', 'oc-icon-rouble'], + 'oc-icon-rss' => ['rss', 'oc-icon-rss'], + 'oc-icon-rss-square' => ['rss-square', 'oc-icon-rss-square'], + 'oc-icon-rub' => ['rub', 'oc-icon-rub'], + 'oc-icon-ruble' => ['ruble', 'oc-icon-ruble'], + 'oc-icon-rupee' => ['rupee', 'oc-icon-rupee'], + 'oc-icon-save' => ['save', 'oc-icon-save'], + 'oc-icon-scissors' => ['scissors', 'oc-icon-scissors'], + 'oc-icon-search' => ['search', 'oc-icon-search'], + 'oc-icon-search-minus' => ['search-minus', 'oc-icon-search-minus'], + 'oc-icon-search-plus' => ['search-plus', 'oc-icon-search-plus'], + 'oc-icon-sellsy' => ['sellsy', 'oc-icon-sellsy'], + 'oc-icon-send' => ['send', 'oc-icon-send'], + 'oc-icon-send-o' => ['send-o', 'oc-icon-send-o'], + 'oc-icon-server' => ['server', 'oc-icon-server'], + 'oc-icon-share' => ['share', 'oc-icon-share'], + 'oc-icon-share-alt' => ['share-alt', 'oc-icon-share-alt'], + 'oc-icon-share-alt-square' => ['share-alt-square', 'oc-icon-share-alt-square'], + 'oc-icon-share-square' => ['share-square', 'oc-icon-share-square'], + 'oc-icon-share-square-o' => ['share-square-o', 'oc-icon-share-square-o'], + 'oc-icon-shekel' => ['shekel', 'oc-icon-shekel'], + 'oc-icon-sheqel' => ['sheqel', 'oc-icon-sheqel'], + 'oc-icon-shield' => ['shield', 'oc-icon-shield'], + 'oc-icon-ship' => ['ship', 'oc-icon-ship'], + 'oc-icon-shirtsinbulk' => ['shirtsinbulk', 'oc-icon-shirtsinbulk'], + 'oc-icon-shopping-cart' => ['shopping-cart', 'oc-icon-shopping-cart'], + 'oc-icon-sign-in' => ['sign-in', 'oc-icon-sign-in'], + 'oc-icon-sign-out' => ['sign-out', 'oc-icon-sign-out'], + 'oc-icon-signal' => ['signal', 'oc-icon-signal'], + 'oc-icon-simplybuilt' => ['simplybuilt', 'oc-icon-simplybuilt'], + 'oc-icon-sitemap' => ['sitemap', 'oc-icon-sitemap'], + 'oc-icon-skyatlas' => ['skyatlas', 'oc-icon-skyatlas'], + 'oc-icon-skype' => ['skype', 'oc-icon-skype'], + 'oc-icon-slack' => ['slack', 'oc-icon-slack'], + 'oc-icon-sliders' => ['sliders', 'oc-icon-sliders'], + 'oc-icon-slideshare' => ['slideshare', 'oc-icon-slideshare'], + 'oc-icon-smile-o' => ['smile-o', 'oc-icon-smile-o'], + 'oc-icon-soccer-ball-o' => ['soccer-ball-o', 'oc-icon-soccer-ball-o'], + 'oc-icon-sort' => ['sort', 'oc-icon-sort'], + 'oc-icon-sort-alpha-asc' => ['sort-alpha-asc', 'oc-icon-sort-alpha-asc'], + 'oc-icon-sort-alpha-desc' => ['sort-alpha-desc', 'oc-icon-sort-alpha-desc'], + 'oc-icon-sort-amount-asc' => ['sort-amount-asc', 'oc-icon-sort-amount-asc'], + 'oc-icon-sort-amount-desc' => ['sort-amount-desc', 'oc-icon-sort-amount-desc'], + 'oc-icon-sort-asc' => ['sort-asc', 'oc-icon-sort-asc'], + 'oc-icon-sort-desc' => ['sort-desc', 'oc-icon-sort-desc'], + 'oc-icon-sort-down' => ['sort-down', 'oc-icon-sort-down'], + 'oc-icon-sort-numeric-asc' => ['sort-numeric-asc', 'oc-icon-sort-numeric-asc'], + 'oc-icon-sort-numeric-desc' => ['sort-numeric-desc', 'oc-icon-sort-numeric-desc'], + 'oc-icon-sort-up' => ['sort-up', 'oc-icon-sort-up'], + 'oc-icon-soundcloud' => ['soundcloud', 'oc-icon-soundcloud'], + 'oc-icon-space-shuttle' => ['space-shuttle', 'oc-icon-space-shuttle'], + 'oc-icon-spinner' => ['spinner', 'oc-icon-spinner'], + 'oc-icon-spoon' => ['spoon', 'oc-icon-spoon'], + 'oc-icon-spotify' => ['spotify', 'oc-icon-spotify'], + 'oc-icon-square' => ['square', 'oc-icon-square'], + 'oc-icon-square-o' => ['square-o', 'oc-icon-square-o'], + 'oc-icon-stack-exchange' => ['stack-exchange', 'oc-icon-stack-exchange'], + 'oc-icon-stack-overflow' => ['stack-overflow', 'oc-icon-stack-overflow'], + 'oc-icon-star' => ['star', 'oc-icon-star'], + 'oc-icon-star-half' => ['star-half', 'oc-icon-star-half'], + 'oc-icon-star-half-empty' => ['star-half-empty', 'oc-icon-star-half-empty'], + 'oc-icon-star-half-full' => ['star-half-full', 'oc-icon-star-half-full'], + 'oc-icon-star-half-o' => ['star-half-o', 'oc-icon-star-half-o'], + 'oc-icon-star-o' => ['star-o', 'oc-icon-star-o'], + 'oc-icon-steam' => ['steam', 'oc-icon-steam'], + 'oc-icon-steam-square' => ['steam-square', 'oc-icon-steam-square'], + 'oc-icon-step-backward' => ['step-backward', 'oc-icon-step-backward'], + 'oc-icon-step-forward' => ['step-forward', 'oc-icon-step-forward'], + 'oc-icon-stethoscope' => ['stethoscope', 'oc-icon-stethoscope'], + 'oc-icon-stop' => ['stop', 'oc-icon-stop'], + 'oc-icon-street-view' => ['street-view', 'oc-icon-street-view'], + 'oc-icon-strikethrough' => ['strikethrough', 'oc-icon-strikethrough'], + 'oc-icon-stumbleupon' => ['stumbleupon', 'oc-icon-stumbleupon'], + 'oc-icon-stumbleupon-circle' => ['stumbleupon-circle', 'oc-icon-stumbleupon-circle'], + 'oc-icon-subscript' => ['subscript', 'oc-icon-subscript'], + 'oc-icon-subway' => ['subway', 'oc-icon-subway'], + 'oc-icon-suitcase' => ['suitcase', 'oc-icon-suitcase'], + 'oc-icon-sun-o' => ['sun-o', 'oc-icon-sun-o'], + 'oc-icon-superscript' => ['superscript', 'oc-icon-superscript'], + 'oc-icon-support' => ['support', 'oc-icon-support'], + 'oc-icon-table' => ['table', 'oc-icon-table'], + 'oc-icon-tablet' => ['tablet', 'oc-icon-tablet'], + 'oc-icon-tachometer' => ['tachometer', 'oc-icon-tachometer'], + 'oc-icon-tag' => ['tag', 'oc-icon-tag'], + 'oc-icon-tags' => ['tags', 'oc-icon-tags'], + 'oc-icon-tasks' => ['tasks', 'oc-icon-tasks'], + 'oc-icon-taxi' => ['taxi', 'oc-icon-taxi'], + 'oc-icon-tencent-weibo' => ['tencent-weibo', 'oc-icon-tencent-weibo'], + 'oc-icon-terminal' => ['terminal', 'oc-icon-terminal'], + 'oc-icon-text-height' => ['text-height', 'oc-icon-text-height'], + 'oc-icon-text-width' => ['text-width', 'oc-icon-text-width'], + 'oc-icon-th' => ['th', 'oc-icon-th'], + 'oc-icon-th-large' => ['th-large', 'oc-icon-th-large'], + 'oc-icon-th-list' => ['th-list', 'oc-icon-th-list'], + 'oc-icon-thumb-tack' => ['thumb-tack', 'oc-icon-thumb-tack'], + 'oc-icon-thumbs-down' => ['thumbs-down', 'oc-icon-thumbs-down'], + 'oc-icon-thumbs-o-down' => ['thumbs-o-down', 'oc-icon-thumbs-o-down'], + 'oc-icon-thumbs-o-up' => ['thumbs-o-up', 'oc-icon-thumbs-o-up'], + 'oc-icon-thumbs-up' => ['thumbs-up', 'oc-icon-thumbs-up'], + 'oc-icon-ticket' => ['ticket', 'oc-icon-ticket'], + 'oc-icon-times' => ['times', 'oc-icon-times'], + 'oc-icon-times-circle' => ['times-circle', 'oc-icon-times-circle'], + 'oc-icon-times-circle-o' => ['times-circle-o', 'oc-icon-times-circle-o'], + 'oc-icon-tint' => ['tint', 'oc-icon-tint'], + 'oc-icon-toggle-down' => ['toggle-down', 'oc-icon-toggle-down'], + 'oc-icon-toggle-left' => ['toggle-left', 'oc-icon-toggle-left'], + 'oc-icon-toggle-off' => ['toggle-off', 'oc-icon-toggle-off'], + 'oc-icon-toggle-on' => ['toggle-on', 'oc-icon-toggle-on'], + 'oc-icon-toggle-right' => ['toggle-right', 'oc-icon-toggle-right'], + 'oc-icon-toggle-up' => ['toggle-up', 'oc-icon-toggle-up'], + 'oc-icon-train' => ['train', 'oc-icon-train'], + 'oc-icon-transgender' => ['transgender', 'oc-icon-transgender'], + 'oc-icon-transgender-alt' => ['transgender-alt', 'oc-icon-transgender-alt'], + 'oc-icon-trash' => ['trash', 'oc-icon-trash'], + 'oc-icon-trash-o' => ['trash-o', 'oc-icon-trash-o'], + 'oc-icon-tree' => ['tree', 'oc-icon-tree'], + 'oc-icon-trello' => ['trello', 'oc-icon-trello'], + 'oc-icon-trophy' => ['trophy', 'oc-icon-trophy'], + 'oc-icon-truck' => ['truck', 'oc-icon-truck'], + 'oc-icon-try' => ['try', 'oc-icon-try'], + 'oc-icon-tty' => ['tty', 'oc-icon-tty'], + 'oc-icon-tumblr' => ['tumblr', 'oc-icon-tumblr'], + 'oc-icon-tumblr-square' => ['tumblr-square', 'oc-icon-tumblr-square'], + 'oc-icon-turkish-lira' => ['turkish-lira', 'oc-icon-turkish-lira'], + 'oc-icon-twitch' => ['twitch', 'oc-icon-twitch'], + 'oc-icon-twitter' => ['twitter', 'oc-icon-twitter'], + 'oc-icon-twitter-square' => ['twitter-square', 'oc-icon-twitter-square'], + 'oc-icon-umbrella' => ['umbrella', 'oc-icon-umbrella'], + 'oc-icon-underline' => ['underline', 'oc-icon-underline'], + 'oc-icon-undo' => ['undo', 'oc-icon-undo'], + 'oc-icon-university' => ['university', 'oc-icon-university'], + 'oc-icon-unlink' => ['unlink', 'oc-icon-unlink'], + 'oc-icon-unlock' => ['unlock', 'oc-icon-unlock'], + 'oc-icon-unlock-alt' => ['unlock-alt', 'oc-icon-unlock-alt'], + 'oc-icon-unsorted' => ['unsorted', 'oc-icon-unsorted'], + 'oc-icon-upload' => ['upload', 'oc-icon-upload'], + 'oc-icon-usd' => ['usd', 'oc-icon-usd'], + 'oc-icon-user' => ['user', 'oc-icon-user'], + 'oc-icon-user-md' => ['user-md', 'oc-icon-user-md'], + 'oc-icon-user-plus' => ['user-plus', 'oc-icon-user-plus'], + 'oc-icon-user-secret' => ['user-secret', 'oc-icon-user-secret'], + 'oc-icon-user-times' => ['user-times', 'oc-icon-user-times'], + 'oc-icon-users' => ['users', 'oc-icon-users'], + 'oc-icon-venus' => ['venus', 'oc-icon-venus'], + 'oc-icon-venus-double' => ['venus-double', 'oc-icon-venus-double'], + 'oc-icon-venus-mars' => ['venus-mars', 'oc-icon-venus-mars'], + 'oc-icon-viacoin' => ['viacoin', 'oc-icon-viacoin'], + 'oc-icon-video-camera' => ['video-camera', 'oc-icon-video-camera'], + 'oc-icon-vimeo-square' => ['vimeo-square', 'oc-icon-vimeo-square'], + 'oc-icon-vine' => ['vine', 'oc-icon-vine'], + 'oc-icon-vk' => ['vk', 'oc-icon-vk'], + 'oc-icon-volume-down' => ['volume-down', 'oc-icon-volume-down'], + 'oc-icon-volume-off' => ['volume-off', 'oc-icon-volume-off'], + 'oc-icon-volume-up' => ['volume-up', 'oc-icon-volume-up'], + 'oc-icon-warning' => ['warning', 'oc-icon-warning'], + 'oc-icon-wechat' => ['wechat', 'oc-icon-wechat'], + 'oc-icon-weibo' => ['weibo', 'oc-icon-weibo'], + 'oc-icon-weixin' => ['weixin', 'oc-icon-weixin'], + 'oc-icon-whatsapp' => ['whatsapp', 'oc-icon-whatsapp'], + 'oc-icon-wheelchair' => ['wheelchair', 'oc-icon-wheelchair'], + 'oc-icon-wifi' => ['wifi', 'oc-icon-wifi'], + 'oc-icon-windows' => ['windows', 'oc-icon-windows'], + 'oc-icon-won' => ['won', 'oc-icon-won'], + 'oc-icon-wordpress' => ['wordpress', 'oc-icon-wordpress'], + 'oc-icon-wrench' => ['wrench', 'oc-icon-wrench'], + 'oc-icon-xing' => ['xing', 'oc-icon-xing'], + 'oc-icon-xing-square' => ['xing-square', 'oc-icon-xing-square'], + 'oc-icon-yahoo' => ['yahoo', 'oc-icon-yahoo'], + 'oc-icon-yelp' => ['yelp', 'oc-icon-yelp'], + 'oc-icon-yen' => ['yen', 'oc-icon-yen'], + 'oc-icon-youtube' => ['youtube', 'oc-icon-youtube'], + 'oc-icon-youtube-play' => ['youtube-play', 'oc-icon-youtube-play'], + 'oc-icon-youtube-square' => ['youtube-square', 'oc-icon-youtube-square'] + ]; + } +} diff --git a/plugins/rainlab/builder/classes/IndexOperationsBehaviorBase.php b/plugins/rainlab/builder/classes/IndexOperationsBehaviorBase.php new file mode 100644 index 0000000..8929d86 --- /dev/null +++ b/plugins/rainlab/builder/classes/IndexOperationsBehaviorBase.php @@ -0,0 +1,78 @@ +getPluginCode(); + $pluginCode = $pluginCodeObj->toCode(); + $widget = $this->makeBaseFormWidget($pluginCode, ['alias' => $alias]); + $widget->bindToController(); + return $widget; + } + + /** + * makeBaseFormWidget + */ + protected function makeBaseFormWidget($modelCode, $options = []) + { + if (!strlen($this->baseFormConfigFile)) { + throw new ApplicationException(sprintf('Base form configuration file is not specified for %s behavior', get_class($this))); + } + + $widgetConfig = $this->makeConfig($this->baseFormConfigFile); + $widgetConfig->model = $this->loadOrCreateBaseModel($modelCode, $options); + $widgetConfig->alias = $options['alias'] ?? 'form_'.md5(get_class($this)).uniqid(); + + $widgetConfig = $this->extendBaseFormWidgetConfig($widgetConfig); + + $form = $this->makeWidget(\Backend\Widgets\Form::class, $widgetConfig); + $form->context = strlen($modelCode) ? 'update' : 'create'; + + return $form; + } + + /** + * extendBaseFormWidgetConfig + */ + protected function extendBaseFormWidgetConfig($config) + { + return $config; + } + + /** + * getPluginCode + */ + protected function getPluginCode() + { + $vector = $this->controller->getBuilderActivePluginVector(); + + if (!$vector) { + throw new ApplicationException('Cannot determine the currently active plugin.'); + } + + return $vector->pluginCodeObj; + } + + /** + * loadOrCreateBaseModel + */ + abstract protected function loadOrCreateBaseModel($modelCode, $options = []); +} diff --git a/plugins/rainlab/builder/classes/LanguageMixer.php b/plugins/rainlab/builder/classes/LanguageMixer.php new file mode 100644 index 0000000..70a2294 --- /dev/null +++ b/plugins/rainlab/builder/classes/LanguageMixer.php @@ -0,0 +1,196 @@ + '', + 'mismatch' => false, + 'updatedLines' => [], + ]; + + try { + $destArray = Yaml::parse($destContents); + } + catch (Exception $ex) { + throw new ApplicationException(sprintf('Cannot parse the YAML content: %s', $ex->getMessage())); + } + + if (!$destArray) { + $result['strings'] = $this->arrayToYaml($srcArray); + return $result; + } + + $mismatch = false; + $missingPaths = $this->findMissingPaths($destArray, $srcArray, $mismatch); + $mergedArray = self::arrayMergeRecursive($srcArray, $destArray); + + $destStrings = $this->arrayToYaml($mergedArray); + $addedLines = $this->getAddedLines($destStrings, $missingPaths); + + $result['strings'] = $destStrings; + $result['updatedLines'] = $addedLines['lines']; + $result['mismatch'] = $mismatch || $addedLines['mismatch']; + + return $result; + } + + public static function arrayMergeRecursive(&$array1, &$array2) + { + // The native PHP implementation of array_merge_recursive + // generates unexpected results when two scalar elements with a + // same key is found, so we use a custom one. + + $result = $array1; + + foreach ($array2 as $key => &$value) { + if (is_array($value) && isset($result[$key]) && is_array($result[$key])) { + $result[$key] = self::arrayMergeRecursive($result[$key], $value); + } else { + $result[$key] = $value; + } + } + + return $result; + } + + protected function findMissingPaths($destArray, $srcArray, &$mismatch) + { + $result = []; + $mismatch = false; + $this->findMissingPathsRecursive($destArray, $srcArray, $result, [], $mismatch); + + return $result; + } + + protected function findMissingPathsRecursive($destArray, $srcArray, &$result, $currentPath, &$mismatch) + { + foreach ($srcArray as $key => $value) { + $newPath = array_merge($currentPath, [$key]); + $pathValue = null; + $pathExists = $this->pathExistsInArray($destArray, $newPath, $pathValue); + + if (!$pathExists) { + $result[] = $newPath; + } + + if (is_array($value)) { + $this->findMissingPathsRecursive($destArray, $value, $result, $newPath, $mismatch); + } + else { + // Detect the case when the value in the destination file + // is an array, when the value in the source file a is a string. + if ($pathExists && is_array($pathValue)) { + $mismatch = true; + } + } + } + } + + protected function pathExistsInArray($array, $path, &$value) + { + $currentArray = $array; + + while ($path) { + $currentPath = array_shift($path); + + if (!is_array($currentArray)) { + return false; + } + + if (!array_key_exists($currentPath, $currentArray)) { + return false; + } + + $currentArray = $currentArray[$currentPath]; + } + + $value = $currentArray; + return true; + } + + protected function arrayToYaml($array) + { + $dumper = new YamlDumper(); + return $dumper->dump($array, 20, 0, false, true); + } + + protected function getAddedLines($strings, $paths) + { + $result = [ + 'lines' => [], + 'mismatch' => false + ]; + + foreach ($paths as $path) { + $line = $this->getLineForPath($strings, $path); + + if ($line !== false) { + $result['lines'][] = $line; + } + else { + $result['mismatch'] = true; + } + } + + return $result; + } + + protected function getLineForPath($strings, $path) + { + $strings = str_replace("\n\r", "\n", trim($strings)); + $lines = explode("\n", $strings); + + $lineCount = count($lines); + $currentLineIndex = 0; + foreach ($path as $indentaion => $key) { + $expectedKeyDefinition = str_repeat(' ', $indentaion).$key.':'; + + $firstLineAfterKey = true; + for ($lineIndex = $currentLineIndex; $lineIndex < $lineCount; $lineIndex++) { + $line = $lines[$lineIndex]; + + if (!$firstLineAfterKey) { + $lineIndentation = 0; + if (preg_match('/^\s+/', $line, $matches)) { + $lineIndentation = strlen($matches[0])/4; + } + + if ($lineIndentation < $indentaion) { + continue; // Don't allow entering wrong branches + } + } + + $firstLineAfterKey = false; + + if (strpos($line, $expectedKeyDefinition) === 0) { + $currentLineIndex = $lineIndex; + continue 2; + } + } + + // If the key wasn't found in the text, there is + // a structure difference between the source an destination + // languages - for example when a string key was replaced + // with an array of strings. + return false; + } + + return $currentLineIndex; + } +} diff --git a/plugins/rainlab/builder/classes/MigrationColumnType.php b/plugins/rainlab/builder/classes/MigrationColumnType.php new file mode 100644 index 0000000..2e7da46 --- /dev/null +++ b/plugins/rainlab/builder/classes/MigrationColumnType.php @@ -0,0 +1,234 @@ + DoctrineType::INTEGER, + self::TYPE_SMALLINTEGER => DoctrineType::SMALLINT, + self::TYPE_BIGINTEGER => DoctrineType::BIGINT, + self::TYPE_DATE => DoctrineType::DATE_MUTABLE, + self::TYPE_TIME => DoctrineType::TIME_MUTABLE, + self::TYPE_DATETIME => DoctrineType::DATETIME_MUTABLE, + self::TYPE_TIMESTAMP => DoctrineType::DATETIME_MUTABLE, + self::TYPE_STRING => DoctrineType::STRING, + self::TYPE_TEXT => DoctrineType::TEXT, + self::TYPE_BINARY => DoctrineType::BLOB, + self::TYPE_BOOLEAN => DoctrineType::BOOLEAN, + self::TYPE_DECIMAL => DoctrineType::DECIMAL, + self::TYPE_DOUBLE => DoctrineType::FLOAT + ]; + } + + /** + * Converts a migration column type to a corresponding Doctrine mapping type name. + */ + public static function toDoctrineTypeName($type) + { + $typeMap = self::getDoctrineTypeMap(); + + if (!array_key_exists($type, $typeMap)) { + throw new SystemException(sprintf('Unknown column type: %s', $type)); + } + + return $typeMap[$type]; + } + + /** + * Converts Doctrine mapping type name to a migration column method name + */ + public static function toMigrationMethodName($type, $columnName) + { + $typeMap = self::getDoctrineTypeMap(); + + if (!in_array($type, $typeMap)) { + throw new SystemException(sprintf('Unknown column type: %s', $type)); + } + + // Some Doctrine types map to multiple migration types, for example + // Doctrine boolean could be boolean and tinyInteger in migrations. + // Some guessing could be required in this method. The method is not + // 100% reliable. + + if ($type == DoctrineType::DATETIME_MUTABLE) { + // The datetime type maps to datetime and timestamp. Use the name + // guessing as the only possible solution. + + if (in_array($columnName, ['created_at', 'updated_at', 'deleted_at', 'published_at', 'deleted_at'])) { + return self::TYPE_TIMESTAMP; + } + + return self::TYPE_DATETIME; + } + + $typeMap = array_flip($typeMap); + return $typeMap[$type]; + } + + /** + * Validates the column length parameter basing on the column type + */ + public static function validateLength($type, $value) + { + $value = trim($value); + + if (!strlen($value)) { + return; + } + + if (in_array($type, self::getDecimalTypes())) { + if (!preg_match(self::REGEX_LENGTH_DOUBLE, $value)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.database.error_table_decimal_length', [ + 'type' => $type + ])); + } + } else { + if (!preg_match(self::REGEX_LENGTH_SINGLE, $value)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.database.error_table_length', [ + 'type' => $type + ])); + } + } + } + + /** + * Returns an array containing a column length, precision and scale, basing on the column type. + */ + public static function lengthToPrecisionAndScale($type, $length) + { + $length = trim($length); + + if (!strlen($length)) { + return []; + } + + $result = [ + 'length' => null, + 'precision' => null, + 'scale' => null + ]; + + if (in_array($type, self::getDecimalTypes())) { + $matches = []; + + if (!preg_match(self::REGEX_LENGTH_DOUBLE, $length, $matches)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.database.error_table_length', [ + 'type' => $type + ])); + } + + $result['precision'] = $matches[1]; + $result['scale'] = $matches[2]; + + return $result; + } + + if (in_array($type, self::getIntegerTypes())) { + if (!preg_match(self::REGEX_LENGTH_SINGLE, $length)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.database.error_table_length', [ + 'type' => $type + ])); + } + + $result['precision'] = $length; + $result['scale'] = 0; + + return $result; + } + + $result['length'] = $length; + return $result; + } + + /** + * doctrineLengthToMigrationLength converts Doctrine length, precision and scale to migration-compatible length string + * @return string + */ + public static function doctrineLengthToMigrationLength($column) + { + $typeName = $column->getType()->getName(); + $migrationTypeName = self::toMigrationMethodName($typeName, $column->getName()); + + if (in_array($migrationTypeName, self::getDecimalTypes())) { + return $column->getPrecision().','.$column->getScale(); + } + + if (in_array($migrationTypeName, self::getIntegerTypes())) { + return $column->getPrecision(); + } + + return $column->getLength(); + } +} diff --git a/plugins/rainlab/builder/classes/MigrationFileParser.php b/plugins/rainlab/builder/classes/MigrationFileParser.php new file mode 100644 index 0000000..6efb900 --- /dev/null +++ b/plugins/rainlab/builder/classes/MigrationFileParser.php @@ -0,0 +1,77 @@ +forward()) { + $tokenCode = $stream->getCurrentCode(); + + if ($tokenCode == T_NAMESPACE) { + $namespace = $this->extractNamespace($stream); + if ($namespace === null) { + return null; + } + + $result['namespace'] = $namespace; + } + + if ($tokenCode == T_CLASS) { + $className = $this->extractClassName($stream); + if ($className === null) { + return null; + } + + $result['class'] = $className; + } + } + + if (!$result) { + return null; + } + + return $result; + } + + protected function extractClassName($stream) + { + if ($stream->getNextExpected(T_WHITESPACE) === null) { + return null; + } + + return $stream->getNextExpectedTerminated([T_STRING], [T_WHITESPACE, ';']); + } + + protected function extractNamespace($stream) + { + if ($stream->getNextExpected(T_WHITESPACE) === null) { + return null; + } + + $expected = [T_STRING, T_NS_SEPARATOR]; + + // Namespace string on PHP 8.0 returns code 314 (T_NAME_QUALIFIED) + // @deprecated combine when min req > php 8 + if (defined('T_NAME_QUALIFIED') && T_NAME_QUALIFIED > 0) { + $expected[] = T_NAME_QUALIFIED; + } + + return $stream->getNextExpectedTerminated($expected, [T_WHITESPACE, ';']); + } +} diff --git a/plugins/rainlab/builder/classes/ModelFileParser.php b/plugins/rainlab/builder/classes/ModelFileParser.php new file mode 100644 index 0000000..8770760 --- /dev/null +++ b/plugins/rainlab/builder/classes/ModelFileParser.php @@ -0,0 +1,200 @@ +forward()) { + $tokenCode = $stream->getCurrentCode(); + + if ($tokenCode == T_NAMESPACE) { + $namespace = $this->extractNamespace($stream); + if ($namespace === null) { + return null; + } + + $result['namespace'] = $namespace; + } + + if ($tokenCode == T_CLASS && !isset($result['class'])) { + $className = $this->extractClassName($stream); + if ($className === null) { + return null; + } + + $result['class'] = $className; + } + + if ($tokenCode == T_PUBLIC || $tokenCode == T_PROTECTED) { + $tableName = $this->extractTableName($stream); + if ($tableName === false) { + continue; + } + + if ($tableName === null) { + return null; + } + + $result['table'] = $tableName; + } + } + + if (!$result) { + return null; + } + + return $result; + } + + /** + * Extracts names and types of model relations. + * @param string $fileContents Specifies the file contents. + * @return array|null Returns an array with keys matching the relation types and values containing relation names as array. + * Returns null if the parsing fails. + */ + public function extractModelRelationsFromSource($fileContents) + { + $result = []; + + $stream = new PhpSourceStream($fileContents); + + while ($stream->forward()) { + $tokenCode = $stream->getCurrentCode(); + + if ($tokenCode == T_PUBLIC) { + $relations = $this->extractRelations($stream); + if ($relations === false) { + continue; + } + } + } + + if (!$result) { + return null; + } + + return $result; + } + + /** + * extractNamespace from model info + */ + protected function extractNamespace($stream) + { + if ($stream->getNextExpected(T_WHITESPACE) === null) { + return null; + } + + $expected = [T_STRING, T_NS_SEPARATOR]; + + // Namespace string on PHP 8.0 returns code 314 (T_NAME_QUALIFIED) + // @deprecated combine when min req > php 8 + if (defined('T_NAME_QUALIFIED') && T_NAME_QUALIFIED > 0) { + $expected[] = T_NAME_QUALIFIED; + } + + return $stream->getNextExpectedTerminated($expected, [T_WHITESPACE, ';']); + } + + /** + * extractClassName from model info + */ + protected function extractClassName($stream) + { + if ($stream->getNextExpected(T_WHITESPACE) === null) { + return null; + } + + return $stream->getNextExpectedTerminated([T_STRING], [T_WHITESPACE, ';']); + } + + /** + * Returns the table name. This method would return null in case if the + * $table variable was found, but it value cannot be read. If the variable + * is not found, the method returns false, allowing the outer loop to go to + * the next token. + */ + protected function extractTableName($stream) + { + if ($stream->getNextExpected(T_WHITESPACE) === null) { + return false; + } + + if ($stream->getNextExpected(T_VARIABLE) === null) { + return false; + } + + if ($stream->getCurrentText() != '$table') { + return false; + } + + if ($stream->getNextExpectedTerminated(['=', T_WHITESPACE], [T_CONSTANT_ENCAPSED_STRING]) === null) { + return null; + } + + $tableName = $stream->getCurrentText(); + $tableName = trim($tableName, '\''); + $tableName = trim($tableName, '"'); + + return $tableName; + } + + protected function extractRelations($stream) + { + if ($stream->getNextExpected(T_WHITESPACE) === null) { + return false; + } + + if ($stream->getNextExpected(T_VARIABLE) === null) { + return false; + } + + $relationTypes = [ + 'belongsTo', + 'belongsToMany', + 'attachMany', + 'hasMany', + 'morphToMany', + 'morphedByMany', + 'morphMany', + 'hasManyThrough' + ]; + + $relationType = null; + $currentText = $stream->getCurrentText(); + + foreach ($relationTypes as $type) { + if ($currentText == '$'.$type) { + $relationType = $type; + break; + } + } + + if (!$relationType) { + return false; + } + + if ($stream->getNextExpectedTerminated(['=', T_WHITESPACE], ['[']) === null) { + return null; + } + + // The implementation is not finished and postponed. Relation definition could + // be quite complex and contain nested arrays. + } +} diff --git a/plugins/rainlab/builder/classes/PhpSourceStream.php b/plugins/rainlab/builder/classes/PhpSourceStream.php new file mode 100644 index 0000000..1412fb8 --- /dev/null +++ b/plugins/rainlab/builder/classes/PhpSourceStream.php @@ -0,0 +1,259 @@ +tokens = token_get_all($fileContents); + } + + /** + * Moves head to the beginning and cleans the internal bookmarks. + */ + public function reset() + { + $this->head = 0; + $this->headBookmarks = []; + } + + public function getHead() + { + return $this->head; + } + + /** + * Updates the head position. + * @return boolean Returns true if the head was successfully updated. Returns false otherwise. + */ + public function setHead($head) + { + if ($head < 0) { + return false; + } + + if ($head > (count($this->tokens) - 1)) { + return false; + } + + $this->head = $head; + return true; + } + + /** + * Bookmarks the head position in the internal bookmark stack. + */ + public function bookmarkHead() + { + array_push($this->headBookmarks, $this->head); + } + + /** + * Restores the head position from the last stored bookmark. + */ + public function restoreBookmark() + { + $head = array_pop($this->headBookmarks); + if ($head === null) { + throw new SystemException("Can't restore PHP token stream bookmark - the bookmark doesn't exist"); + } + + return $this->setHead($head); + } + + /** + * Discards the last stored bookmark without changing the head position. + */ + public function discardBookmark() + { + $head = array_pop($this->headBookmarks); + if ($head === null) { + throw new SystemException("Can't discard PHP token stream bookmark - the bookmark doesn't exist"); + } + } + + /** + * Returns the current token and doesn't move the head. + */ + public function getCurrent() + { + return $this->tokens[$this->head]; + } + + /** + * Returns the current token's text and doesn't move the head. + */ + public function getCurrentText() + { + $token = $this->getCurrent(); + if (!is_array($token)) { + return $token; + } + + return $token[1]; + } + + /** + * Returns the current token's code and doesn't move the head. + */ + public function getCurrentCode() + { + $token = $this->getCurrent(); + if (!is_array($token)) { + return null; + } + + return $token[0]; + } + + /** + * Returns the next token and moves the head forward. + */ + public function getNext() + { + $nextIndex = $this->head + 1; + if (!array_key_exists($nextIndex, $this->tokens)) { + return null; + } + + $this->head = $nextIndex; + return $this->tokens[$nextIndex]; + } + + /** + * Reads the next token, updates the head and and returns the token if it has the expected code. + * @param integer $expectedCode Specifies the code to expect. + * @return mixed Returns the token or null if the token code was not expected. + */ + public function getNextExpected($expectedCode) + { + $token = $this->getNext(); + if ($this->getCurrentCode() != $expectedCode) { + return null; + } + + return $token; + } + + /** + * Reads expected tokens, until the termination token is found. + * If any unexpected token is found before the termination token, returns null. + * If the method succeeds, the head is positioned on the termination token. + * @param array $expectedCodesOrValues Specifies the expected codes or token values. + * @param integer|string|array $terminationToken Specifies the termination token text or code. + * The termination tokens could be specified as array. + * @return string|null Returns the tokens text or null + */ + public function getNextExpectedTerminated($expectedCodesOrValues, $terminationToken, $skipToken = []) + { + $buffer = null; + + if (!is_array($skipToken)) { + $skipToken = [$skipToken]; + } + + if (!is_array($terminationToken)) { + $terminationToken = [$terminationToken]; + } + + while (($nextToken = $this->getNext()) !== null) { + $code = $this->getCurrentCode(); + $text = $this->getCurrentText(); + + if (in_array($code, $expectedCodesOrValues) || in_array($text, $expectedCodesOrValues)) { + $buffer .= $text; + continue; + } + + if (in_array($code, $terminationToken) || in_array($text, $terminationToken)) { + return $buffer; + } + + if (in_array($code, $skipToken) || in_array($text, $skipToken)) { + continue; + } + + // The token should be either expected or termination. + // If something else is found, return null. + return null; + } + + return $buffer; + } + + /** + * Moves the head forward. + * @return boolean Returns true if the head was successfully moved. + * Returns false if the head can't be moved because it has reached the end of the steam. + */ + public function forward() + { + return $this->setHead($this->getHead()+1); + } + + /** + * Moves the head backward. + * @return boolean Returns true if the head was successfully moved. + * Returns false if the head can't be moved because it has reached the beginning of the steam. + */ + public function back() + { + return $this->setHead($this->getHead()-1); + } + + /** + * getTextToSemicolon returns the stream text from the head position to the next + * semicolon and updates the head. If the method succeeds, the head is positioned + * on the semicolon. + */ + public function getTextToSemicolon() + { + $buffer = null; + + while (($nextToken = $this->getNext()) !== null) { + if ($nextToken == ';') { + return $buffer; + } + + $buffer .= $this->getCurrentText(); + } + + // The semicolon wasn't found. + return null; + } + + /** + * unquotePhpString + */ + public function unquotePhpString($string, $default = false) + { + if ((substr($string, 0, 1) === '\'' && substr($string, -1) === '\'') || + (substr($string, 0, 1) === '"' && substr($string, -1) === '"')) { + return substr($string, 1, -1); + } + + return $default; + } +} diff --git a/plugins/rainlab/builder/classes/PluginCode.php b/plugins/rainlab/builder/classes/PluginCode.php new file mode 100644 index 0000000..1eef2b3 --- /dev/null +++ b/plugins/rainlab/builder/classes/PluginCode.php @@ -0,0 +1,170 @@ +validateCodeWord($authorCode) || !$this->validateCodeWord($pluginCode)) { + throw new ApplicationException(sprintf('Invalid plugin code: %s', $pluginCodeStr)); + } + + $this->authorCode = trim($authorCode); + $this->pluginCode = trim($pluginCode); + } + + /** + * createFromNamespace + */ + public static function createFromNamespace($namespace) + { + $namespaceParts = explode('\\', $namespace); + if (count($namespaceParts) < 2) { + throw new ApplicationException('Invalid plugin namespace value.'); + } + + $authorCode = $namespaceParts[0]; + $pluginCode = $namespaceParts[1]; + + return new self($authorCode.'.'.$pluginCode); + } + + /** + * toPluginNamespace + */ + public function toPluginNamespace() + { + return $this->authorCode.'\\'.$this->pluginCode; + } + + /** + * toUrl + */ + public function toUrl() + { + return strtolower($this->authorCode).'/'.strtolower($this->pluginCode); + } + + /** + * toUpdatesNamespace + */ + public function toUpdatesNamespace() + { + return $this->toPluginNamespace().'\\Updates'; + } + + /** + * toFilesystemPath + */ + public function toFilesystemPath() + { + return strtolower($this->authorCode.'/'.$this->pluginCode); + } + + /** + * toCode + */ + public function toCode() + { + return $this->authorCode.'.'.$this->pluginCode; + } + + /** + * toPluginFilePath + */ + public function toPluginFilePath() + { + return '$/'.$this->toFilesystemPath().'/plugin.yaml'; + } + + /** + * toPluginInformationFilePath + */ + public function toPluginInformationFilePath() + { + return '$/'.$this->toFilesystemPath().'/Plugin.php'; + } + + /** + * toPluginDirectoryPath + */ + public function toPluginDirectoryPath() + { + return '$/'.$this->toFilesystemPath(); + } + + /** + * toDatabasePrefix + */ + public function toDatabasePrefix($dbPrefix = false) + { + $builderPrefix = strtolower($this->authorCode.'_'.$this->pluginCode); + + if ($dbPrefix) { + return Db::getTablePrefix() . $builderPrefix; + } + + return $builderPrefix; + } + + /** + * toPermissionPrefix + */ + public function toPermissionPrefix() + { + return strtolower($this->authorCode.'.'.$this->pluginCode); + } + + /** + * getAuthorCode + */ + public function getAuthorCode() + { + return $this->authorCode; + } + + /** + * getPluginCode + */ + public function getPluginCode() + { + return $this->pluginCode; + } + + /** + * validateCodeWord + */ + protected function validateCodeWord($str) + { + $str = trim($str); + return strlen($str) && preg_match('/^[a-z]+[a-z0-9]+$/i', $str); + } +} diff --git a/plugins/rainlab/builder/classes/PluginVector.php b/plugins/rainlab/builder/classes/PluginVector.php new file mode 100644 index 0000000..433b6ec --- /dev/null +++ b/plugins/rainlab/builder/classes/PluginVector.php @@ -0,0 +1,67 @@ +plugin = $plugin; + $this->pluginCodeObj = $pluginCodeObj; + } + + /** + * createFromPluginCode + */ + public static function createFromPluginCode($pluginCode) + { + $pluginCodeObj = new PluginCode($pluginCode); + + $plugins = PluginManager::instance()->getPlugins(); + + foreach ($plugins as $code => $plugin) { + if ($code == $pluginCode) { + return new PluginVector($plugin, $pluginCodeObj); + } + } + + return null; + } + + /** + * getPluginName + */ + public function getPluginName() + { + if (!$this->plugin) { + return null; + } + + $pluginInfo = $this->plugin->pluginDetails(); + if (!isset($pluginInfo['name'])) { + return null; + } + + return $pluginInfo['name']; + } +} diff --git a/plugins/rainlab/builder/classes/PluginVersion.php b/plugins/rainlab/builder/classes/PluginVersion.php new file mode 100644 index 0000000..1726c8c --- /dev/null +++ b/plugins/rainlab/builder/classes/PluginVersion.php @@ -0,0 +1,71 @@ +getPluginUpdatesPath($pluginCodeObj, 'version.yaml'); + + if (!File::isFile($filePath)) { + throw new SystemException('Plugin version.yaml file is not found.'); + } + + $versionInfo = Yaml::parseFile($filePath); + + if (!is_array($versionInfo)) { + $versionInfo = []; + } + + if ($versionInfo) { + uksort($versionInfo, function ($a, $b) { + return version_compare($a, $b); + }); + } + + // Normalize result + $result = []; + + foreach ($versionInfo as $version => $info) { + $result[$this->normalizeVersion($version)] = $info; + } + + return $result; + } + + /** + * getPluginUpdatesPath + */ + protected function getPluginUpdatesPath($pluginCodeObj, $fileName = null) + { + $filePath = '$/'.$pluginCodeObj->toFilesystemPath().'/updates'; + $filePath = File::symbolizePath($filePath); + + if ($fileName !== null) { + return $filePath .= '/'.$fileName; + } + + return $filePath; + } + + /** + * normalizeVersion checks some versions start with v and others not + */ + protected function normalizeVersion($version): string + { + return rtrim(ltrim((string) $version, 'v'), '.'); + } +} diff --git a/plugins/rainlab/builder/classes/StandardBehaviorsRegistry.php b/plugins/rainlab/builder/classes/StandardBehaviorsRegistry.php new file mode 100644 index 0000000..449c0fb --- /dev/null +++ b/plugins/rainlab/builder/classes/StandardBehaviorsRegistry.php @@ -0,0 +1,529 @@ +behaviorLibrary = $behaviorLibrary; + + $this->registerBehaviors(); + } + + /** + * registerBehaviors + */ + protected function registerBehaviors() + { + $this->registerFormBehavior(); + $this->registerListBehavior(); + $this->registerImportExportBehavior(); + } + + /** + * registerFormBehavior + */ + protected function registerFormBehavior() + { + $properties = [ + 'name' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_name'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_name_description'), + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_name_required') + ] + ], + ], + 'modelClass' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_model_class'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_model_class_description'), + 'placeholder' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_model_class_placeholder'), + 'type' => 'dropdown', + 'fillFrom' => 'model-classes', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_model_class_required') + ] + ], + ], + 'form' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_file'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_file_description'), + 'placeholder' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_placeholder'), + 'type' => 'autocomplete', + 'fillFrom' => 'model-forms', + 'subtypeFrom' => 'modelClass', + 'depends' => ['modelClass'], + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_file_required') + ] + ], + ], + 'defaultRedirect' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_default_redirect'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_default_redirect_description'), + 'type' => 'autocomplete', + 'fillFrom' => 'controller-urls', + 'ignoreIfEmpty' => true + ], + 'create' => [ + 'type' => 'object', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_create'), + 'ignoreIfEmpty' => true, + 'properties' => [ + [ + 'property' => 'title', + 'type' => 'builderLocalization', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_page_title'), + 'ignoreIfEmpty' => true + ], + [ + 'property' => 'redirect', + 'type' => 'autocomplete', + 'fillFrom' => 'controller-urls', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_redirect'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_redirect_description'), + 'ignoreIfEmpty' => true + ], + [ + 'property' => 'redirectClose', + 'type' => 'autocomplete', + 'fillFrom' => 'controller-urls', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_redirect_close'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_redirect_close_description'), + 'ignoreIfEmpty' => true + ], + [ + 'property' => 'flashSave', + 'type' => 'builderLocalization', + 'ignoreIfEmpty' => true, + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_flash_save'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_flash_save_description'), + ] + ] + ], + 'update' => [ + 'type' => 'object', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_update'), + 'ignoreIfEmpty' => true, + 'properties' => [ + [ + 'property' => 'title', + 'type' => 'builderLocalization', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_page_title'), + 'ignoreIfEmpty' => true + ], + [ + 'property' => 'redirect', + 'type' => 'autocomplete', + 'fillFrom' => 'controller-urls', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_redirect'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_redirect_description'), + 'ignoreIfEmpty' => true + ], + [ + 'property' => 'redirectClose', + 'type' => 'autocomplete', + 'fillFrom' => 'controller-urls', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_redirect_close'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_redirect_close_description'), + 'ignoreIfEmpty' => true + ], + [ + 'property' => 'flashSave', + 'type' => 'builderLocalization', + 'ignoreIfEmpty' => true, + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_flash_save'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_flash_save_description'), + ], + [ + 'property' => 'flashDelete', + 'type' => 'builderLocalization', + 'ignoreIfEmpty' => true, + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_flash_delete'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_flash_delete_description'), + ] + ] + ], + 'preview' => [ + 'type' => 'object', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_preview'), + 'ignoreIfEmpty' => true, + 'properties' => [ + [ + 'property' => 'title', + 'type' => 'builderLocalization', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_page_title'), + 'ignoreIfEmpty' => true + ] + ] + ] + ]; + + $templates = [ + '$/rainlab/builder/classes/standardbehaviorsregistry/formcontroller/templates/create.php.tpl', + '$/rainlab/builder/classes/standardbehaviorsregistry/formcontroller/templates/update.php.tpl', + '$/rainlab/builder/classes/standardbehaviorsregistry/formcontroller/templates/preview.php.tpl' + ]; + + $this->behaviorLibrary->registerBehavior( + \Backend\Behaviors\FormController::class, + 'rainlab.builder::lang.controller.behavior_form_controller', + 'rainlab.builder::lang.controller.behavior_form_controller_description', + $properties, + 'formConfig', + null, + 'config_form.yaml', + $templates + ); + } + + /** + * registerListBehavior + */ + protected function registerListBehavior() + { + $properties = [ + 'title' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_title'), + 'type' => 'builderLocalization', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_title_required') + ] + ], + ], + 'modelClass' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_model_class'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_model_class_description'), + 'placeholder' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_model_placeholder'), + 'type' => 'dropdown', + 'fillFrom' => 'model-classes', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_model_class_required') + ] + ], + ], + 'list' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_file'), + 'placeholder' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_placeholder'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_file_description'), + 'type' => 'autocomplete', + 'fillFrom' => 'model-lists', + 'subtypeFrom' => 'modelClass', + 'depends' => ['modelClass'], + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_file_required') + ] + ], + ], + 'recordUrl' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_record_url'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_record_url_description'), + 'ignoreIfEmpty' => true, + 'type' => 'autocomplete', + 'fillFrom' => 'controller-urls', + ], + 'noRecordsMessage' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_no_records_message'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_no_records_message_description'), + 'ignoreIfEmpty' => true, + 'type' => 'builderLocalization', + ], + 'recordsPerPage' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_recs_per_page'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_recs_per_page_description'), + 'ignoreIfEmpty' => true, + 'type' => 'string', + 'validation' => [ + 'regex' => [ + 'pattern' => '^[0-9]+$', + 'message' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_recs_per_page_regex') + ] + ], + ], + 'showSetup' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_show_setup'), + 'type' => 'checkbox', + 'ignoreIfEmpty' => true, + ], + 'showCheckboxes' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_show_checkboxes'), + 'type' => 'checkbox', + 'ignoreIfEmpty' => true, + ], + 'structure' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_structure'), + 'ignoreIfEmpty' => true, + 'type' => 'object', + 'ignoreIfPropertyEmpty' => 'maxDepth', + 'properties' => [ + [ + 'property' => 'maxDepth', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_max_depth'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'validation' => [ + 'regex' => [ + 'pattern' => '^[0-9]+$', + 'message' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_max_depth_regex') + ] + ], + ], + [ + 'property' => 'showTree', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_show_tree'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_show_tree_description'), + 'type' => 'checkbox', + 'default' => true, + 'ignoreIfDefault' => true, + ], + [ + 'property' => 'treeExpanded', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_tree_expanded'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_tree_expanded_description'), + 'type' => 'checkbox', + 'default' => true, + 'ignoreIfDefault' => true, + ], + [ + 'property' => 'showReorder', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_show_reorder'), + 'type' => 'checkbox', + 'default' => true, + 'ignoreIfDefault' => true, + ], + [ + 'property' => 'showSorting', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_show_sorting'), + 'type' => 'checkbox', + 'default' => true, + 'ignoreIfDefault' => true, + ], + [ + 'property' => 'dragRow', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_drag_row'), + 'type' => 'checkbox', + 'default' => true, + 'ignoreIfDefault' => true, + ], + ], + ], + 'defaultSort' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_default_sort'), + 'ignoreIfEmpty' => true, + 'type' => 'object', + 'ignoreIfPropertyEmpty' => 'column', + 'properties' => [ + [ + 'property' => 'column', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_ds_column'), + 'type' => 'autocomplete', + 'fillFrom' => 'model-columns', + 'subtypeFrom' => 'modelClass', + 'depends' => ['modelClass'] + ], + [ + 'property' => 'direction', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_ds_direction'), + 'type' => 'dropdown', + 'options' => [ + 'asc' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_ds_asc'), + 'desc' => Lang::get('rainlab.builder::lang.controller.property_behavior_form_ds_desc'), + ], + ] + ] + ], + 'toolbar' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_toolbar'), + 'type' => 'object', + 'ignoreIfEmpty' => true, + 'properties' => [ + [ + 'property' => 'buttons', + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_toolbar_buttons'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_toolbar_buttons_description'), + ], + [ + 'property' => 'search', + 'type' => 'object', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_search'), + 'properties' => [ + [ + 'property' => 'prompt', + 'type' => 'builderLocalization', + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_search_prompt'), + ] + ] + ] + ] + ], + 'recordOnClick' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_onclick'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_onclick_description'), + 'ignoreIfEmpty' => true, + 'type' => 'string' + ], + 'filter' => [ + 'type' => 'string', // Should be configurable in place later + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_filter'), + 'ignoreIfEmpty' => true + ] + ]; + + $templates = [ + '$/rainlab/builder/classes/standardbehaviorsregistry/listcontroller/templates/index.php.tpl', + '$/rainlab/builder/classes/standardbehaviorsregistry/listcontroller/templates/_list_toolbar.php.tpl' + ]; + + $this->behaviorLibrary->registerBehavior( + \Backend\Behaviors\ListController::class, + 'rainlab.builder::lang.controller.behavior_list_controller', + 'rainlab.builder::lang.controller.behavior_list_controller_description', + $properties, + 'listConfig', + null, + 'config_list.yaml', + $templates + ); + } + + /** + * registerImportExportBehavior + */ + protected function registerImportExportBehavior() + { + $properties = [ + 'import.title' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_import_title'), + 'type' => 'builderLocalization', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.controller.property_behavior_import_title_required') + ] + ], + 'group' => Lang::get('rainlab.builder::lang.controller.property_group_import'), + ], + 'import.modelClass' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_import_model_class'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_import_model_class_description'), + 'placeholder' => Lang::get('rainlab.builder::lang.controller.property_behavior_import_model_class_placeholder'), + 'type' => 'dropdown', + 'fillFrom' => 'model-classes', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.controller.property_behavior_import_model_class_required') + ] + ], + 'group' => Lang::get('rainlab.builder::lang.controller.property_group_import'), + ], + 'import.list' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_file'), + 'placeholder' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_placeholder'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_file_description'), + 'type' => 'autocomplete', + 'fillFrom' => 'model-lists', + 'subtypeFrom' => 'import.modelClass', + 'depends' => ['import.modelClass'], + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_file_required') + ] + ], + 'group' => Lang::get('rainlab.builder::lang.controller.property_group_import'), + ], + 'import.redirect' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_import_redirect'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_import_redirect_description'), + 'type' => 'autocomplete', + 'fillFrom' => 'controller-urls', + 'ignoreIfEmpty' => true, + 'group' => Lang::get('rainlab.builder::lang.controller.property_group_import'), + ], + 'export.title' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_export_title'), + 'type' => 'builderLocalization', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.controller.property_behavior_import_title_required') + ] + ], + 'group' => Lang::get('rainlab.builder::lang.controller.property_group_export'), + ], + 'export.modelClass' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_export_model_class'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_export_model_class_description'), + 'placeholder' => Lang::get('rainlab.builder::lang.controller.property_behavior_import_model_class_placeholder'), + 'type' => 'dropdown', + 'fillFrom' => 'model-classes', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.controller.property_behavior_import_model_class_required') + ] + ], + 'group' => Lang::get('rainlab.builder::lang.controller.property_group_export'), + ], + 'export.list' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_file'), + 'placeholder' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_placeholder'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_file_description'), + 'type' => 'autocomplete', + 'fillFrom' => 'model-lists', + 'subtypeFrom' => 'export.modelClass', + 'depends' => ['export.modelClass'], + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.controller.property_behavior_list_file_required') + ] + ], + 'group' => Lang::get('rainlab.builder::lang.controller.property_group_export'), + ], + 'export.redirect' => [ + 'title' => Lang::get('rainlab.builder::lang.controller.property_behavior_import_redirect'), + 'description' => Lang::get('rainlab.builder::lang.controller.property_behavior_import_redirect_description'), + 'type' => 'autocomplete', + 'fillFrom' => 'controller-urls', + 'ignoreIfEmpty' => true, + 'group' => Lang::get('rainlab.builder::lang.controller.property_group_export'), + ], + ]; + + $templates = [ + '$/rainlab/builder/classes/standardbehaviorsregistry/importexportcontroller/templates/import.php.tpl', + '$/rainlab/builder/classes/standardbehaviorsregistry/importexportcontroller/templates/export.php.tpl', + ]; + + $this->behaviorLibrary->registerBehavior( + \Backend\Behaviors\ImportExportController::class, + 'rainlab.builder::lang.controller.behavior_import_export_controller', + 'rainlab.builder::lang.controller.behavior_import_export_controller_description', + $properties, + 'importExportConfig', + null, + 'config_import_export.yaml', + $templates + ); + } +} diff --git a/plugins/rainlab/builder/classes/StandardBlueprintsRegistry.php b/plugins/rainlab/builder/classes/StandardBlueprintsRegistry.php new file mode 100644 index 0000000..1498026 --- /dev/null +++ b/plugins/rainlab/builder/classes/StandardBlueprintsRegistry.php @@ -0,0 +1,204 @@ +blueprintLibrary = $blueprintLibrary; + + $this->registerBlueprints(); + } + + /** + * registerBlueprints + */ + protected function registerBlueprints() + { + $this->registerEntryBlueprint(); + $this->registerGlobalBlueprint(); + } + + /** + * registerEntryBlueprint + */ + protected function registerEntryBlueprint() + { + $properties = [ + 'name' => [ + 'title' => "Name", + 'description' => "The name to use for this blueprint in the user interface", + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => "A name is required" + ] + ], + ], + 'controllerClass' => [ + 'title' => "Controller Class", + 'description' => "Controller name defines the class name and URL of the controller's back-end pages. Standard PHP variable naming conventions apply. The first symbol should be a capital Latin letter. Examples: Categories, Posts, Products.", + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => "A controller name is required" + ] + ], + ], + 'modelClass' => [ + 'title' => "Model Class", + 'description' => "Model name defines the class name of the model. Standard PHP variable naming conventions apply. The first symbol should be a capital Latin letter. Examples: Category, Post, Product.", + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => "A model name is required" + ] + ], + ], + 'tableName' => [ + 'title' => "Table Name", + 'description' => "Table name defines the table name in the database.", + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => "A table name is required" + ] + ], + ], + 'permissionCode' => [ + 'title' => "Permission Code", + 'description' => "Permission code used to manage this item.", + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => "A permission code is required" + ] + ], + ], + 'menuCode' => [ + 'title' => "Menu Code", + 'description' => "Menu code used to include navigation for this item.", + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => "A menu code is required" + ] + ], + ] + ]; + + $this->blueprintLibrary->registerBlueprint( + \Tailor\Classes\Blueprint\EntryBlueprint::class, + 'Entry Blueprint', + 'The standard content structure that supports drafts.', + $properties, + ); + + $this->blueprintLibrary->registerBlueprint( + \Tailor\Classes\Blueprint\StreamBlueprint::class, + 'Stream Blueprint', + 'A stream of time stamped entries.', + $properties, + ); + + $this->blueprintLibrary->registerBlueprint( + \Tailor\Classes\Blueprint\SingleBlueprint::class, + 'Single Blueprint', + 'A single entry with dedicated fields.', + $properties, + ); + + $this->blueprintLibrary->registerBlueprint( + \Tailor\Classes\Blueprint\StructureBlueprint::class, + 'Structure Blueprint', + 'A defined structure of entries.', + $properties, + ); + } + + protected function registerGlobalBlueprint() + { + $properties = [ + 'name' => [ + 'title' => "Name", + 'description' => "The name to use for this blueprint in the user interface", + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => "A name is required" + ] + ], + ], + 'controllerClass' => [ + 'title' => "Controller Class", + 'description' => "Controller name defines the class name and URL of the controller's back-end pages. Standard PHP variable naming conventions apply. The first symbol should be a capital Latin letter. Examples: Categories, Posts, Products.", + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => "A controller name is required" + ] + ], + ], + 'modelClass' => [ + 'title' => "Model Class", + 'description' => "Model name defines the class name of the model. Standard PHP variable naming conventions apply. The first symbol should be a capital Latin letter. Examples: Category, Post, Product.", + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => "A model name is required" + ] + ], + ], + 'tableName' => [ + 'title' => "Table Name", + 'description' => "Table name defines the table name in the database.", + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => "A table name is required" + ] + ], + ], + 'permissionCode' => [ + 'title' => "Permission Code", + 'description' => "Permission code used to manage this item.", + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => "A permission code is required" + ] + ], + ], + 'menuCode' => [ + 'title' => "Menu Code", + 'description' => "Menu code used to include navigation for this item.", + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => "A menu code is required" + ] + ], + ] + ]; + + $this->blueprintLibrary->registerBlueprint( + \Tailor\Classes\Blueprint\GlobalBlueprint::class, + 'Global Blueprint', + 'A single record in the database and is often used for settings and configuration.', + $properties, + ); + } +} diff --git a/plugins/rainlab/builder/classes/StandardControlsRegistry.php b/plugins/rainlab/builder/classes/StandardControlsRegistry.php new file mode 100644 index 0000000..d06d71c --- /dev/null +++ b/plugins/rainlab/builder/classes/StandardControlsRegistry.php @@ -0,0 +1,73 @@ +controlLibrary = $controlLibrary; + + $this->registerControls(); + } + + /** + * registerControls + */ + protected function registerControls() + { + // UI + $this->registerSectionControl(); + $this->registerHintControl(); + $this->registerRulerControl(); + $this->registerPartialControl(); + + // Fields + $this->registerTextControl(); + $this->registerNumberControl(); + $this->registerPasswordControl(); + $this->registerEmailControl(); + $this->registerTextareaControl(); + $this->registerDropdownControl(); + $this->registerRadioListControl(); + $this->registerBalloonSelectorControl(); + $this->registerCheckboxControl(); + $this->registerCheckboxListControl(); + $this->registerSwitchControl(); + + // Widgets + $this->registerCodeEditorWidget(); + $this->registerColorPickerWidget(); + $this->registerDataTableWidget(); + $this->registerDatepickerWidget(); + $this->registerFileUploadWidget(); + $this->registerMarkdownWidget(); + $this->registerMediaFinderWidget(); + $this->registerNestedFormWidget(); + $this->registerRecordFinderWidget(); + $this->registerRelationWidget(); + $this->registerRepeaterWidget(); + $this->registerRichEditorWidget(); + $this->registerPageFinderWidget(); + $this->registerSensitiveWidget(); + $this->registerTagListWidget(); + } +} diff --git a/plugins/rainlab/builder/classes/TableMigrationCodeGenerator.php b/plugins/rainlab/builder/classes/TableMigrationCodeGenerator.php new file mode 100644 index 0000000..710688b --- /dev/null +++ b/plugins/rainlab/builder/classes/TableMigrationCodeGenerator.php @@ -0,0 +1,654 @@ +diffTable($existingTable, $updatedTable); + + // Remove database prefix + $existingTableName = substr($existingTable->getName(), mb_strlen(Db::getTablePrefix())); + + if ($newTableName !== $existingTableName) { + if (!$tableDiff) { + $tableDiff = new TableDiff($existingTableName); + } + + $tableDiff->newName = $newTableName; + } + } + // The table doesn't exist + else { + $tableDiff = new TableDiff( + $updatedTable->getName(), + $updatedTable->getColumns(), + [], // Changed columns + [], // Removed columns + $updatedTable->getIndexes() // Added indexes + ); + + $tableDiff->fromTable = $updatedTable; + } + + if (!$tableDiff) { + return false; + } + + if (!$this->tableHasNameOrColumnChanges($tableDiff) && !$this->tableHasPrimaryKeyChanges($tableDiff)) { + return false; + } + + return $this->generateCreateOrUpdateCode($tableDiff, !$existingTable, $updatedTable); + } + + /** + * Wrap migration's up() and down() functions into a complete migration class declaration + * @param string $scriptFilename Specifies the migration script file name + * @param string $code Specifies the migration code + * @param PluginCode $pluginCodeObj The plugin code object + * @return TextParser + */ + public function wrapMigrationCode($scriptFilename, $code, $pluginCodeObj) + { + $templatePath = '$/rainlab/builder/models/databasetablemodel/templates/full-migration-code.php.tpl'; + $templatePath = File::symbolizePath($templatePath); + + $fileContents = File::get($templatePath); + + return TextParser::parse($fileContents, [ + 'className' => Str::studly($scriptFilename), + 'migrationCode' => $this->indent($code), + 'namespace' => $pluginCodeObj->toUpdatesNamespace() + ]); + } + + /** + * Generates code for dropping a database table. + * @param \Doctrine\DBAL\Schema\Table $existingTable Specifies the existing table schema. + * @return string Returns the migration up() and down() methods code. + */ + public function dropTable($existingTable) + { + return $this->generateMigrationCode( + $this->generateDropUpCode($existingTable), + $this->generateDropDownCode($existingTable) + ); + } + + protected function generateCreateOrUpdateCode($tableDiff, $isNewTable, $newOrUpdatedTable) + { + /* + * Although it might seem that a reverse diff could be used + * for the down() method, that's not so. The up and down operations + * are not fully symmetrical. + */ + + return $this->generateMigrationCode( + $this->generateCreateOrUpdateUpCode($tableDiff, $isNewTable, $newOrUpdatedTable), + $this->generateCreateOrUpdateDownCode($tableDiff, $isNewTable, $newOrUpdatedTable) + ); + } + + protected function generateMigrationCode($upCode, $downCode) + { + $templatePath = '$/rainlab/builder/models/databasetablemodel/templates/migration-code.php.tpl'; + $templatePath = File::symbolizePath($templatePath); + + $fileContents = File::get($templatePath); + + return TextParser::parse($fileContents, [ + 'upCode' => $upCode, + 'downCode' => $downCode + ]); + } + + protected function generateCreateOrUpdateUpCode($tableDiff, $isNewTable, $newOrUpdatedTable) + { + $result = null; + + $hasColumnChanges = $this->tableHasNameOrColumnChanges($tableDiff, true); + $changedPrimaryKey = $this->getChangedOrRemovedPrimaryKey($tableDiff); + $addedPrimaryKey = $this->findPrimaryKeyIndex($tableDiff->addedIndexes, $newOrUpdatedTable); + + if ($tableDiff->getNewName()) { + $result .= $this->generateTableRenameCode($tableDiff->name, $tableDiff->newName); + + if ($hasColumnChanges || $changedPrimaryKey) { + $result .= $this->eol; + } + } + + if (!$hasColumnChanges && !$changedPrimaryKey && !$addedPrimaryKey) { + return $this->makeTabs($result); + } + + $tableName = $tableDiff->getNewName() ? $tableDiff->newName : $tableDiff->name; + $result .= $this->generateSchemaTableMethodStart($tableName, $isNewTable); + + if ($changedPrimaryKey) { + $result .= $this->generatePrimaryKeyDrop($tableDiff->fromTable); + } + + foreach ($tableDiff->addedColumns as $column) { + $result .= $this->generateColumnCode($column, self::COLUMN_MODE_CREATE); + } + + foreach ($tableDiff->changedColumns as $columnDiff) { + $result .= $this->generateColumnCode($columnDiff, self::COLUMN_MODE_CHANGE); + } + + foreach ($tableDiff->renamedColumns as $oldName => $column) { + $result .= $this->generateColumnRenameCode($oldName, $column->getName()); + } + + foreach ($tableDiff->removedColumns as $name => $column) { + $result .= $this->generateColumnRemoveCode($name); + } + + $primaryKey = $changedPrimaryKey ? + $this->findPrimaryKeyIndex($tableDiff->changedIndexes, $newOrUpdatedTable) : + $this->findPrimaryKeyIndex($tableDiff->addedIndexes, $newOrUpdatedTable); + + if ($primaryKey) { + $result .= $this->generatePrimaryKeyCode($primaryKey, self::COLUMN_MODE_CREATE); + } + + $result .= $this->generateSchemaTableMethodEnd(); + + return $this->makeTabs($result); + } + + protected function generateCreateOrUpdateDownCode($tableDiff, $isNewTable, $newOrUpdatedTable) + { + $result = ''; + + if ($isNewTable) { + $result = $this->generateTableDropCode($tableDiff->name); + } else { + $changedPrimaryKey = $this->getChangedOrRemovedPrimaryKey($tableDiff); + $addedPrimaryKey = $this->findPrimaryKeyIndex($tableDiff->addedIndexes, $newOrUpdatedTable); + + if ($this->tableHasNameOrColumnChanges($tableDiff) || $changedPrimaryKey || $addedPrimaryKey) { + $hasColumnChanges = $this->tableHasNameOrColumnChanges($tableDiff, true); + + if ($tableDiff->getNewName()) { + $result .= $this->generateTableRenameCode($tableDiff->newName, $tableDiff->name); + + if ($hasColumnChanges || $changedPrimaryKey || $addedPrimaryKey) { + $result .= $this->eol; + } + } + + if (!$hasColumnChanges && !$changedPrimaryKey && !$addedPrimaryKey) { + return $this->makeTabs($result); + } + + $result .= $this->generateSchemaTableMethodStart($tableDiff->name, $isNewTable); + + if ($changedPrimaryKey || $addedPrimaryKey) { + $result .= $this->generatePrimaryKeyDrop($newOrUpdatedTable); + } + + foreach ($tableDiff->addedColumns as $column) { + $result .= $this->generateColumnDrop($column); + } + + foreach ($tableDiff->changedColumns as $columnDiff) { + $result .= $this->generateColumnCode($columnDiff, self::COLUMN_MODE_REVERT); + } + + foreach ($tableDiff->renamedColumns as $oldName => $column) { + $result .= $this->generateColumnRenameCode($column->getName(), $oldName); + } + + foreach ($tableDiff->removedColumns as $name => $column) { + $result .= $this->generateColumnCode($column, self::COLUMN_MODE_CREATE); + } + + if ($changedPrimaryKey || $addedPrimaryKey) { + $primaryKey = $this->findPrimaryKeyIndex($tableDiff->fromTable->getIndexes(), $tableDiff->fromTable); + if ($primaryKey) { + $result .= $this->generatePrimaryKeyCode($primaryKey, self::COLUMN_MODE_CREATE); + } + } + + $result .= $this->generateSchemaTableMethodEnd(); + } + } + + return $this->makeTabs($result); + } + + protected function generateDropUpCode($table) + { + $result = $this->generateTableDropCode($table->getName()); + return $this->makeTabs($result); + } + + protected function generateDropDownCode($table) + { + $tableDiff = new TableDiff( + $table->getName(), + $table->getColumns(), + [], // Changed columns + [], // Removed columns + $table->getIndexes() // Added indexes + ); + + return $this->generateCreateOrUpdateUpCode($tableDiff, true, $table); + } + + protected function formatLengthParameters($column, $method) + { + $length = $column->getLength(); + $precision = $column->getPrecision(); + $scale = $column->getScale(); + + if (!strlen($length) && !strlen($precision)) { + return null; + } + + if ($method == MigrationColumnType::TYPE_STRING) { + if (!strlen($length)) { + return null; + } + + return ', '.$length; + } + + if ($method == MigrationColumnType::TYPE_DECIMAL || $method == MigrationColumnType::TYPE_DOUBLE) { + if (!strlen($precision)) { + return null; + } + + if (strlen($scale)) { + return ', '.$precision.', '.$scale; + } + + return ', '.$precision; + } + } + + protected function applyMethodIncrements($method, $column) + { + if (!$column->getAutoincrement()) { + return $method; + } + + if ($method == MigrationColumnType::TYPE_BIGINTEGER) { + return 'bigIncrements'; + } + + return 'increments'; + } + + protected function generateSchemaTableMethodStart($tableName, $isNewTable) + { + $tableFunction = $isNewTable ? 'create' : 'table'; + $result = sprintf('\tSchema::%s(\'%s\', function($table)', $tableFunction, $tableName).$this->eol; + $result .= '\t{'.$this->eol; + return $result; + } + + protected function generateSchemaTableMethodEnd() + { + return '\t});'; + } + + protected function generateColumnDrop($column) + { + return sprintf('\t\t$table->dropColumn(\'%s\');', $column->getName()).$this->eol; + } + + protected function generateIndexDrop($index) + { + return sprintf('\t\t$table->dropIndex(\'%s\');', $index->getName()).$this->eol; + } + + protected function generatePrimaryKeyDrop($table) + { + $index = $this->findPrimaryKeyIndex($table->getIndexes(), $table); + if (!$index) { + return; + } + + $indexColumns = $index->getColumns(); + return sprintf('\t\t$table->dropPrimary([%s]);', $this->implodeColumnList($indexColumns)).$this->eol; + } + + protected function generateColumnCode($columnData, $mode) + { + $forceFlagsChange = false; + + switch ($mode) { + case self::COLUMN_MODE_CREATE: + $column = $columnData; + $changeMode = false; + break; + case self::COLUMN_MODE_CHANGE: + $column = $columnData->column; + $changeMode = true; + + $forceFlagsChange = in_array('type', $columnData->changedProperties); + break; + case self::COLUMN_MODE_REVERT: + $column = $columnData->fromColumn; + $changeMode = true; + + $forceFlagsChange = in_array('type', $columnData->changedProperties); + break; + } + + $result = $this->generateColumnMethodCall($column); + $result .= $this->generateNullable($column, $changeMode, $columnData, $forceFlagsChange); + $result .= $this->generateUnsigned($column, $changeMode, $columnData, $forceFlagsChange); + $result .= $this->generateDefault($column, $changeMode, $columnData, $forceFlagsChange); + $result .= $this->generateComment($column, $changeMode, $columnData, $forceFlagsChange); + + if ($changeMode) { + $result .= '->change()'; + } + + $result .= ';'.$this->eol; + + return $result; + } + + protected function generateColumnRenameCode($fromName, $toName) + { + return sprintf('\t\t$table->renameColumn(\'%s\', \'%s\');', $fromName, $toName).$this->eol; + } + + protected function generateTableRenameCode($fromName, $toName) + { + return sprintf('\tSchema::rename(\'%s\', \'%s\');', $fromName, $toName); + } + + protected function generateTableDropCode($name) + { + return sprintf('\tSchema::dropIfExists(\'%s\');', $name); + } + + protected function generateColumnRemoveCode($name) + { + return sprintf('\t\t$table->dropColumn(\'%s\');', $name).$this->eol; + } + + protected function generateColumnMethodCall($column) + { + $columnName = $column->getName(); + $typeName = $column->getType()->getName(); + + $method = MigrationColumnType::toMigrationMethodName($typeName, $columnName); + $method = $this->applyMethodIncrements($method, $column); + + $lengthStr = $this->formatLengthParameters($column, $method); + + return sprintf('\t\t$table->%s(\'%s\'%s)', $method, $columnName, $lengthStr); + } + + protected function generateNullable($column, $changeMode, $columnData, $forceFlagsChange) + { + $result = null; + + if (!$changeMode) { + if (!$column->getNotnull()) { + $result = $this->generateBooleanMethod('nullable', true); + } + } + elseif (in_array('notnull', $columnData->changedProperties) || $forceFlagsChange) { + $result = $this->generateBooleanMethod('nullable', !$column->getNotnull()); + } + + return $result; + } + + protected function generateUnsigned($column, $changeMode, $columnData, $forceFlagsChange) + { + $result = null; + + if (!$changeMode) { + if ($column->getUnsigned()) { + $result = $this->generateBooleanMethod('unsigned', true); + } + } + elseif (in_array('unsigned', $columnData->changedProperties) || $forceFlagsChange) { + $result = $this->generateBooleanMethod('unsigned', $column->getUnsigned()); + } + + return $result; + } + + protected function generateDefault($column, $changeMode, $columnData, $forceFlagsChange) + { + /* + * See a note about empty strings as default values in + * DatabaseTableSchemaCreator::formatOptions() method. + */ + $result = null; + $default = $column->getDefault(); + + if (!$changeMode) { + if (strlen($default)) { + $result = $this->generateDefaultMethodCall($default, $column); + } + } elseif (in_array('default', $columnData->changedProperties) || $forceFlagsChange) { + if (strlen($default)) { + $result = $this->generateDefaultMethodCall($default, $column); + } elseif ($changeMode) { + $result = sprintf('->default(null)'); + } + } + + return $result; + } + + protected function generateDefaultMethodCall($default, $column) + { + $columnName = $column->getName(); + $typeName = $column->getType()->getName(); + + $type = MigrationColumnType::toMigrationMethodName($typeName, $columnName); + + if (in_array($type, MigrationColumnType::getIntegerTypes()) || + in_array($type, MigrationColumnType::getDecimalTypes()) || + $type == MigrationColumnType::TYPE_BOOLEAN) { + return sprintf('->default(%s)', $default); + } + + return sprintf('->default(\'%s\')', $this->quoteParameter($default)); + } + + protected function generateComment($column, $changeMode, $columnData, $forceFlagsChange) + { + $result = null; + $default = $column->getComment(); + + if (!$changeMode) { + if (strlen($default)) { + $result = $this->generateCommentMethodCall($default, $column); + } + } + elseif (in_array('comment', $columnData->changedProperties) || $forceFlagsChange) { + if (strlen($default)) { + $result = $this->generateCommentMethodCall($default, $column); + } + elseif ($changeMode) { + $result = sprintf('->comment(null)'); + } + } + + return $result; + } + + protected function generateCommentMethodCall($default, $column) + { + return sprintf('->comment(\'%s\')', $this->quoteParameter($default)); + } + + protected function generatePrimaryKeyCode($index) + { + $columns = $index->getColumns(); + + return sprintf('\t\t$table->primary([%s]);', $this->implodeColumnList($columns)).$this->eol; + } + + protected function generateBooleanString($value) + { + $result = $value ? 'true' : 'false'; + + return $result; + } + + protected function generateBooleanMethod($methodName, $value) + { + if ($value) { + return '->'.$methodName.'()'; + } + + return '->'.$methodName.'('.$this->generateBooleanString($value).')'; + } + + protected function quoteParameter($str) + { + return str_replace("'", "\'", $str); + } + + protected function makeTabs($str) + { + return str_replace('\t', ' ', $str); + } + + protected function indent($str) + { + return $this->indent . str_replace($this->eol, $this->eol . $this->indent, $str); + } + + protected function implodeColumnList($columnNames) + { + foreach ($columnNames as &$columnName) { + $columnName = '\''.$columnName.'\''; + } + + return implode(',', $columnNames); + } + + protected function tableHasNameOrColumnChanges($tableDiff, $columnChangesOnly = false) + { + $result = $tableDiff->addedColumns + || $tableDiff->changedColumns + || $tableDiff->removedColumns + || $tableDiff->renamedColumns; + + if ($columnChangesOnly) { + return $result; + } + + return $result || $tableDiff->getNewName(); + } + + protected function tableHasPrimaryKeyChanges($tableDiff) + { + return $this->findPrimaryKeyIndex($tableDiff->addedIndexes, $tableDiff->fromTable) || + $this->findPrimaryKeyIndex($tableDiff->changedIndexes, $tableDiff->fromTable) || + $this->findPrimaryKeyIndex($tableDiff->removedIndexes, $tableDiff->fromTable); + } + + protected function getChangedOrRemovedPrimaryKey($tableDiff) + { + foreach ($tableDiff->changedIndexes as $index) { + if ($index->isPrimary()) { + return $index; + } + } + + foreach ($tableDiff->removedIndexes as $index) { + if ($index->isPrimary()) { + return $index; + } + } + + return null; + } + + protected function findPrimaryKeyIndex($indexes, $table) + { + /* + * This method ignores auto-increment primary keys + * as they are managed with the increments() method + * instead of the primary(). + */ + foreach ($indexes as $index) { + if (!$index->isPrimary()) { + continue; + } + + if ($this->indexHasAutoincrementColumns($index, $table)) { + continue; + } + + return $index; + } + + return null; + } + + protected function indexHasAutoincrementColumns($index, $table) + { + $indexColumns = $index->getColumns(); + + foreach ($indexColumns as $indexColumn) { + if (!$table->hasColumn($indexColumn)) { + continue; + } + + $tableColumn = $table->getColumn($indexColumn); + if ($tableColumn->getAutoincrement()) { + return true; + } + } + + return false; + } +} diff --git a/plugins/rainlab/builder/classes/TailorBlueprintLibrary.php b/plugins/rainlab/builder/classes/TailorBlueprintLibrary.php new file mode 100644 index 0000000..c9099c6 --- /dev/null +++ b/plugins/rainlab/builder/classes/TailorBlueprintLibrary.php @@ -0,0 +1,154 @@ +getBlueprintObject($blueprintUuid); + if (!$blueprintObj) { + return null; + } + + $blueprintClassName = get_class($blueprintObj); + + $blueprints = $this->listBlueprints(); + if (!array_key_exists($blueprintClassName, $blueprints)) { + return null; + } + + return [ + 'blueprintObj' => $blueprintObj, + 'blueprintClass' => get_class($blueprintObj) + ] + $blueprints[$blueprintClassName]; + } + + /** + * getRelatedBlueprintUuids returns blueprints related to the supplied blueprint UUID + */ + public function getRelatedBlueprintUuids($blueprintUuid) + { + $indexer = BlueprintIndexer::instance(); + $fieldset = $indexer->findContentFieldset($blueprintUuid); + + $relatedFieldTypes = ['entries']; + + $result = []; + foreach ($fieldset->getAllFields() as $name => $field) { + if (!in_array($field->type, $relatedFieldTypes)) { + continue; + } + + $bp = $this->getBlueprintObject($field->source, $field->source); + if (!$bp) { + continue; + } + + $result[$name] = $bp->uuid; + } + + return $result; + } + + /** + * registerBlueprint + * + * @param string $class Specifies the blueprint class name. + * @param string $name Specifies the blueprint name, for example "Form blueprint". + * @param string $description Specifies the blueprint description. + * @param array $properties Specifies the blueprint properties. + * The property definitions should be compatible with Inspector properties, similarly + * to the Component properties: http://octobercms.com/docs/plugin/components#component-properties + * @param string $designTimeProviderClass Specifies the blueprint design-time provider class name. + * The class should extend RainLab\Builder\Classes\BlueprintDesignTimeProviderBase. If the class is not provided, + * the default control design and design settings will be used. + * The templates are used when a new controller is created. The templates should be specified as paths + * to Twig files in the format ['~/plugins/author/plugin/blueprints/blueprintname/templates/view.htm.tpl']. + */ + public function registerBlueprint($class, $name, $description, $properties, $designTimeProviderClass = null) + { + if (!$designTimeProviderClass) { + $designTimeProviderClass = self::DEFAULT_DESIGN_TIME_PROVIDER; + } + + $this->blueprints[$class] = [ + 'class' => $class, + 'name' => Lang::get($name), + 'description' => Lang::get($description), + 'properties' => $properties, + 'designTimeProvider' => $designTimeProviderClass, + ]; + } + + /** + * listBlueprints + */ + public function listBlueprints() + { + if ($this->blueprints !== null) { + return $this->blueprints; + } + + $this->blueprints = []; + + Event::fire('pages.builder.registerTailorBlueprints', [$this]); + + return $this->blueprints; + } + + /** + * getBlueprintObject + */ + public function getBlueprintObject($uuid, $handle = null) + { + if (isset($this->blueprintUuidCache[$uuid])) { + return $this->blueprintUuidCache[$uuid]; + } + + foreach (EntryBlueprint::listInProject() as $blueprint) { + if ($blueprint->uuid === $uuid) { + return $this->blueprintUuidCache[$blueprint->uuid] = $blueprint; + } + if ($handle && $blueprint->handle === $handle) { + return $this->blueprintUuidCache[$blueprint->uuid] = $blueprint; + } + } + + foreach (GlobalBlueprint::listInProject() as $blueprint) { + if ($blueprint->uuid === $uuid) { + return $this->blueprintUuidCache[$blueprint->uuid] = $blueprint; + } + if ($handle && $blueprint->handle === $handle) { + return $this->blueprintUuidCache[$blueprint->uuid] = $blueprint; + } + } + } +} diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/ContainerUtils.php b/plugins/rainlab/builder/classes/blueprintgenerator/ContainerUtils.php new file mode 100644 index 0000000..739f6d7 --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/ContainerUtils.php @@ -0,0 +1,71 @@ +sourceModel = $sourceModel; + } + + /** + * getBlueprintDefinition + */ + public function getBlueprintDefinition() + { + return $this->sourceModel->getBlueprintObject(); + } + + /** + * findUuidFromSource + */ + protected function findUuidFromSource($uuidOrHandle): ?string + { + if (!$this->sourceModel) { + return null; + } + + $blueprint = TailorBlueprintLibrary::instance()->getBlueprintObject($uuidOrHandle, $uuidOrHandle); + if (!$blueprint) { + return null; + } + + return $blueprint->uuid; + } + + /** + * findRelatedModelClass + */ + protected function findRelatedModelClass($uuidOrHandle): ?string + { + $uuid = $this->findUuidFromSource($uuidOrHandle); + if (!$uuid) { + return null; + } + + $modelClass = $this->sourceModel->blueprints[$uuid]['modelClass'] ?? null; + if (!$modelClass) { + return null; + } + + $pluginCodeObj = $this->sourceModel->getPluginCodeObj(); + return $pluginCodeObj->toPluginNamespace().'\\Models\\'.$modelClass; + } +} diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/ExpandoModelContainer.php b/plugins/rainlab/builder/classes/blueprintgenerator/ExpandoModelContainer.php new file mode 100644 index 0000000..1fbb393 --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/ExpandoModelContainer.php @@ -0,0 +1,56 @@ +repeaterFieldset) { + throw new ApplicationException('Missing repeater fieldset'); + } + + // Process join table entries specifically + $fieldset = $this->repeaterFieldset; + foreach ($fieldset->getAllFields() as $name => $field) { + if ($field->type === 'entries') { + $this->processEntryRelationDefinitions($definitions, $name, $field); + } + if ($field->type === 'repeater' || $field->type === 'nestedform') { + $this->processRepeaterRelationDefinitions($definitions, $name, $field); + } + } + + return $definitions; + } + + /** + * processRepeaterRelationDefinitions + */ + protected function processRepeaterRelationDefinitions(&$definitions, $fieldName, $fieldObj) + { + foreach ($definitions as $type => &$relations) { + foreach ($relations as $name => &$props) { + if ($name === $fieldName && isset($props[0]) && $props[0] === \Tailor\Models\RepeaterItem::class) { + // Field to be jsonable (nested) + $this->addJsonable($name); + unset($relations[$name]); + break; + } + } + } + } +} diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/FilterElementContainer.php b/plugins/rainlab/builder/classes/blueprintgenerator/FilterElementContainer.php new file mode 100644 index 0000000..cee02d7 --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/FilterElementContainer.php @@ -0,0 +1,77 @@ +label($label)->displayAs('text'); + + $this->scopes[$scopeName] = $scope; + + return $scope; + } + + /** + * getControls + */ + public function getControls(): array + { + $result = []; + $index = 0; + + foreach ($this->scopes as $name => $field) { + $result[$name] = $this->parseFieldConfig($index, $name, $field->config); + $index++; + } + + return $result; + } + + /** + * parseFieldConfig + */ + protected function parseFieldConfig($index, $name, $config): array + { + // Remove tailor values + $ignoreConfig = [ + 'scopeName', + 'source', + 'externalToolbarAppState', + 'externalToolbarEventBus' + ]; + + $parsedConfig = array_except((array) $config, $ignoreConfig); + + $parsedConfig['id'] = $index; + $parsedConfig['field'] = $name; + + // Remove default values + $keepDefaults = [ + 'type', + ]; + + $defaultField = new FilterScope; + foreach ($parsedConfig as $key => $value) { + if (!in_array($key, $keepDefaults) && $defaultField->$key === $value) { + unset($parsedConfig[$key]); + } + } + + return $parsedConfig; + } +} diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/FormElementContainer.php b/plugins/rainlab/builder/classes/blueprintgenerator/FormElementContainer.php new file mode 100644 index 0000000..24a3a19 --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/FormElementContainer.php @@ -0,0 +1,135 @@ +label($label)->displayAs('text'); + + $this->addField($fieldName, $field); + + return $field; + } + + /** + * getFormFieldset returns the current fieldset definition + */ + public function getFormFieldset(): FieldsetDefinition + { + return $this; + } + + /** + * getFormContext returns the current form context, e.g. create, update + */ + public function getFormContext() + { + return ''; + } + + /** + * getPrimaryControls + */ + public function getPrimaryControls() + { + $host = new self; + + $host->addFormField('title', 'Title')->span('auto'); + $host->addFormField('slug', 'Slug')->preset(['field' => 'title', 'type' => 'slug'])->span('auto'); + + return $host->getControls(); + } + + /** + * getControls + */ + public function getControls(): array + { + $result = []; + + foreach ($this->getAllFields() as $name => $field) { + $result[$name] = $this->parseFieldConfig($name, $field); + } + + return $result; + } + + /** + * parseFieldConfig + */ + protected function parseFieldConfig($fieldName, $fieldObj): array + { + // Apply mutations to field object + if ($fieldObj->span === 'adaptive') { + $fieldObj->span('full'); + } + + if ($fieldObj->type === 'recordfinder') { + $relatedModelClass = $this->findRelatedModelClass($fieldObj->source); + if ($relatedModelClass) { + $baseClass = mb_strtolower(class_basename($relatedModelClass)); + $path = $this->sourceModel->getPluginCodeObj()->toPluginDirectoryPath().'/models/'.$baseClass; + $fieldObj->list($path.'/columns.yaml'); + } + } + + if ($fieldObj->type === 'repeater') { + $modelClass = $this->sourceModel->getBlueprintConfig('modelClass'); + $baseClass = mb_strtolower(class_basename($modelClass)).mb_strtolower(Str::studly($fieldName)).'item'; + $path = $this->sourceModel->getPluginCodeObj()->toPluginDirectoryPath().'/models/'.$baseClass; + if ($fieldObj->groups) { + $newGroups = []; + foreach ($fieldObj->groups as $groupName => $groupConfig) { + $newGroups[$groupName] = $path."/fields_{$groupName}.yaml"; + } + $fieldObj->groups($newGroups); + } + else { + $fieldObj->form($path.'/fields.yaml'); + } + } + + // Remove tailor values + $ignoreConfig = [ + 'fieldName', + 'source', + 'column', + 'scope', + 'inverse', + 'validation', + 'externalToolbarAppState', + 'externalToolbarEventBus' + ]; + + $parsedConfig = array_except((array) $fieldObj->config, $ignoreConfig); + + // Remove default values + $keepDefaults = [ + 'type', + 'span', + ]; + + $defaultField = new FormField; + foreach ($parsedConfig as $key => $value) { + if (!in_array($key, $keepDefaults) && $defaultField->$key === $value) { + unset($parsedConfig[$key]); + } + } + + return $parsedConfig; + } +} diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/HasControllers.php b/plugins/rainlab/builder/classes/blueprintgenerator/HasControllers.php new file mode 100644 index 0000000..1740d05 --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/HasControllers.php @@ -0,0 +1,71 @@ +makeControllerModel()) { + $files[] = $model->getControllerFilePath(); + } + + $this->validateUniqueFiles($files); + + $model && $model->validate(); + } + + /** + * generateController + */ + protected function generateController() + { + if ($controller = $this->makeControllerModel()) { + $controller->save(); + } + } + + /** + * makeControllerModel + */ + protected function makeControllerModel() + { + $controller = new ControllerModel; + + $controller->setPluginCodeObj($this->sourceModel->getPluginCodeObj()); + + $controller->baseModelClassName = $this->getConfig('modelClass'); + + $controller->controllerName = $this->getConfig('name'); + + $controller->controller = $this->getConfig('controllerClass'); + + $controller->menuItem = $this->getActiveMenuItemCode(); + + $controller->permissions = [$this->getConfig('permissionCode')]; + + $controller->behaviors = []; + + if ($this->sourceModel->useListController()) { + $listConfig = []; + + if ($this->sourceModel->useStructure()) { + $listConfig['structure'] = $this->sourceModel->getBlueprintObject()->structure ?? true; + } + + $controller->behaviors[\Backend\Behaviors\ListController::class] = $listConfig; + } + + $controller->behaviors[\Backend\Behaviors\FormController::class] = []; + + return $controller; + } +} diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/HasExpandoModels.php b/plugins/rainlab/builder/classes/blueprintgenerator/HasExpandoModels.php new file mode 100644 index 0000000..55b50e3 --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/HasExpandoModels.php @@ -0,0 +1,203 @@ +makeExpandoModels(true) as $model) { + $this->validateUniqueFiles([$model->getModelFilePath()]); + $model->validate(); + } + } + + /** + * generateExpandoModels + */ + protected function generateExpandoModels() + { + foreach ($this->makeExpandoModels() as $model) { + $model->save(); + $this->filesGenerated[] = $model->getModelFilePath(); + } + } + + /** + * makeExpandoModels + */ + protected function makeExpandoModels($isValidate = false) + { + $models = []; + + $fieldset = $this->sourceModel->getBlueprintFieldset(); + + foreach ($fieldset->getAllFields() as $name => $field) { + if ($field->type !== 'repeater') { + continue; + } + + $container = new ExpandoModelContainer; + + $container->setSourceModel($this->sourceModel); + + $fieldset = $container->repeaterFieldset = $this->makeExpandoRepeaterFieldset($field); + + $fieldset->applyModelExtensions($container); + + // Generate form fields + $this->generateExpandoModelFormFields($container, $name, $field, $isValidate); + + // Generate model + $models[] = $this->makeExpandoModelModel($container, $name, $field); + } + + return $models; + } + + /** + * generateExpandoModelModel + */ + protected function makeExpandoModelModel($container, $name, $field) + { + $repeaterInfo = $container->getRepeaterTableInfoFor($name, $field); + + $model = new ModelModel; + + $model->setPluginCodeObj($this->sourceModel->getPluginCodeObj()); + + $model->className = $repeaterInfo['modelClass']; + + $model->databaseTable = $repeaterInfo['tableName']; + + $model->addTimestamps = true; + + $model->skipDbValidation = true; + + $model->traits[] = \Tailor\Traits\BlueprintRelationModel::class; + + $model->baseClassName = \October\Rain\Database\ExpandoModel::class; + + $model->relationDefinitions = (array) $container->getProcessedRelationDefinitions(); + + $model->validationDefinitions = (array) $container->getValidationDefinitions(); + + $model->addRawContentToModel(<<getJsonable()) { + $jsonableStr = ''; + foreach ($jsonable as $j) { + $jsonableStr = "'".$j."', "; + } + $jsonableStr = trim($jsonableStr, ', '); + $model->addRawContentToModel(<<groups) { + return FieldManager::instance()->makeFieldset((array) $field->form); + } + + // Create a merged fieldset for groups to acquire relations + $fieldsets = []; + foreach ($field->groups as $config) { + $fieldsets[] = FieldManager::instance()->makeFieldset($config); + } + + $fieldset = array_shift($fieldsets); + foreach ($fieldsets as $otherFieldset) { + foreach ($otherFieldset->getAllFields() as $name => $field) { + $fieldset->addField($name, $field); + } + } + + return $fieldset; + } + + /** + * generateExpandoModelFormFields generates form fields YAML files + */ + protected function generateExpandoModelFormFields($container, $name, $field, $isValidate = false) + { + $repeaterInfo = $container->getRepeaterTableInfoFor($name, $field); + + $forms = []; + if ($field->groups) { + foreach ($field->groups as $groupName => $groupConfig) { + $forms[] = $this->makeExpandoModelFormFields($repeaterInfo, $groupConfig, $groupName); + } + } + elseif ($field->form) { + $forms[] = $this->makeExpandoModelFormFields($repeaterInfo, $field->form); + } + + foreach ($forms as $form) { + if ($isValidate) { + $this->validateUniqueFiles([$form->getYamlFilePath()]); + $form->validate(); + } + else { + $form->save(); + $this->filesGenerated[] = $form->getYamlFilePath(); + } + } + } + + /** + * makeExpandoModelFormFields + */ + protected function makeExpandoModelFormFields($repeaterInfo, $formConfig, $groupPrefix = '') + { + $model = new ModelFormModel; + + $model->setPluginCodeObj($this->sourceModel->getPluginCodeObj()); + + $model->setModelClassName($repeaterInfo['modelClass']); + + $model->fileName = $groupPrefix ? "fields_{$groupPrefix}.yaml" : 'fields.yaml'; + + $container = new FormElementContainer; + + $container->setSourceModel($this->sourceModel); + + $fieldset = FieldManager::instance()->makeFieldset($formConfig); + + $fieldset->defineAllFormFields($container, ['context' => '*']); + + $model->controls = array_except($formConfig, 'fields') + [ + 'fields' => $container->getControls(), + ]; + + return $model; + } +} diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/HasMigrations.php b/plugins/rainlab/builder/classes/blueprintgenerator/HasMigrations.php new file mode 100644 index 0000000..1643eda --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/HasMigrations.php @@ -0,0 +1,230 @@ +dryRunMigrations = true; + + $this->generateMigrations(); + + return $this->migrationScripts; + } + + /** + * generateMigrations for a blueprint + */ + protected function generateMigrations() + { + if ($this->sourceModel->wantsDatabaseMigration()) { + $this->generateContentTable(); + } + + $this->generateJoinTables(); + $this->generateRepeaterTables(); + } + + /** + * generateContentTable + */ + protected function generateContentTable() + { + $tableName = $this->getConfig('tableName'); + if (!$tableName) { + throw new ApplicationException('Missing a table name for migrations'); + } + + [$proposedFile, $migrationFilePath] = $this->findAvailableMigrationFile($tableName); + + $this->migrationScripts[$proposedFile] = __("Create :name Content Table", ['name' => $this->getConfig('name')]); + + if ($this->dryRunMigrations) { + return; + } + + // Prepare the schema from the fieldset + $table = $this->makeSchemaBlueprint($tableName); + + // Write migration to disk + $migrationCode = ''; + foreach ($table->getColumns() as $column) { + $migrationCode .= '\t\t\t'.$this->makeTableDefinition($column).PHP_EOL; + } + + $code = $this->parseTemplate($this->getTemplatePath('migration.php.tpl'), [ + 'migrationCode' => $this->makeTabs(trim($migrationCode, PHP_EOL)), + 'useStructure' => $this->sourceModel->useStructure() + ]); + + $this->writeFile($migrationFilePath, $code); + } + + /** + * makeTableDefinition + */ + protected function makeTableDefinition($column) + { + $defaultStrLength = \Illuminate\Database\Schema\Builder::$defaultStringLength; + + $code = '$table->'.$column['type'].'(\''.$column['name'].'\')'; + + foreach ($column->getAttributes() as $attribute => $value) { + if (in_array($attribute, ['name', 'type'])) { + continue; + } + + if ($attribute === 'length' && $value === $defaultStrLength) { + continue; + } + + $exportValue = $value !== true ? var_export($value, true) : ''; + $code .= '->'.$attribute.'('.$exportValue.')'; + } + + $code .= ';'; + + return $code; + } + + /** + * makeSchemaBlueprint + */ + protected function makeSchemaBlueprint($tableName) + { + $table = App::make(\October\Rain\Database\Schema\Blueprint::class, ['table' => $tableName]); + + $fieldset = $this->sourceModel->getBlueprintFieldset(); + foreach ($fieldset->getAllFields() as $fieldObj) { + $fieldObj->extendDatabaseTable($table); + } + + return $table; + } + + /** + * generateJoinTables + */ + protected function generateJoinTables() + { + $container = new ModelContainer; + + $container->setSourceModel($this->sourceModel); + + $fieldset = $this->sourceModel->getBlueprintFieldset(); + + $fieldset->applyModelExtensions($container); + + foreach ($fieldset->getAllFields() as $name => $field) { + if ($field->type === 'entries' && !$field->inverse && $field->maxItems !== 1) { + if ($joinInfo = $container->getJoinTableInfoFor($name, $field)) { + $this->generateJoinTableForEntries($joinInfo); + } + } + } + } + + /** + * generateJoinTableForEntries + */ + protected function generateJoinTableForEntries($joinInfo) + { + $tableName = $joinInfo['tableName']; + + [$proposedFile, $migrationFilePath] = $this->findAvailableMigrationFile($tableName); + + $this->migrationScripts[$proposedFile] = __("Create :name Pivot Table for :field", [ + 'name' => $this->getConfig('name'), + 'field' => $joinInfo['fieldName'] ?? '??' + ]); + + if ($this->dryRunMigrations) { + return; + } + + $code = $this->parseTemplate($this->getTemplatePath('migration-join.php.tpl'), $joinInfo); + + $this->writeFile($migrationFilePath, $code); + } + + /** + * generateRepeaterTables + */ + protected function generateRepeaterTables() + { + $container = new ExpandoModelContainer; + + $container->setSourceModel($this->sourceModel); + + $fieldset = $this->sourceModel->getBlueprintFieldset(); + + $fieldset->applyModelExtensions($container); + + foreach ($fieldset->getAllFields() as $name => $field) { + if ($field->type === 'repeater') { + if ($repeaterInfo = $container->getRepeaterTableInfoFor($name, $field)) { + $this->generateRepeaterTableForEntries($repeaterInfo); + } + } + } + } + + /** + * generateJoinTableForEntries + */ + protected function generateRepeaterTableForEntries($repeaterInfo) + { + $tableName = $repeaterInfo['tableName']; + + [$proposedFile, $migrationFilePath] = $this->findAvailableMigrationFile($tableName); + + $this->migrationScripts[$proposedFile] = __("Create :name Repeater Table for :field", [ + 'name' => $this->getConfig('name'), + 'field' => $repeaterInfo['fieldName'] ?? '??' + ]); + + if ($this->dryRunMigrations) { + return; + } + + $code = $this->parseTemplate($this->getTemplatePath('migration-repeater.php.tpl'), $repeaterInfo); + + $this->writeFile($migrationFilePath, $code); + } + + /** + * findAvailableMigrationFile + */ + protected function findAvailableMigrationFile(string $tableName): array + { + // Shorten table name + $tableName = trim(str_replace($this->sourceModel->getPluginCodeObj()->toDatabasePrefix(), '', $tableName), "_"); + + $proposedFile = "create_{$tableName}_table.php"; + $migrationFilePath = $this->sourceModel->getPluginFilePath('updates/'.$proposedFile); + + // Find an available file name + $counter = 2; + while (File::isFile($migrationFilePath)) { + $proposedFile = "create_{$tableName}_table_{$counter}.php"; + $migrationFilePath = $this->sourceModel->getPluginFilePath('updates/'.$proposedFile); + $counter++; + } + + return [$proposedFile, $migrationFilePath]; + } +} diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/HasModels.php b/plugins/rainlab/builder/classes/blueprintgenerator/HasModels.php new file mode 100644 index 0000000..7571045 --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/HasModels.php @@ -0,0 +1,224 @@ +makeModelModel()) { + $files[] = $model->getModelFilePath(); + } + + if ($form = $this->makeModelFormFields()) { + $files[] = $form->getYamlFilePath(); + } + + if ($lists = $this->makeModelListColumns()) { + $files[] = $lists->getYamlFilePath(); + } + + if ($filter = $this->makeModelFilterScopes()) { + $files[] = $filter->getYamlFilePath(); + } + + $this->validateUniqueFiles($files); + + $model && $model->validate(); + $form && $form->validate(); + $lists && $lists->validate(); + $filter && $filter->validate(); + } + + /** + * generateModel + */ + protected function generateModel() + { + if ($filter = $this->makeModelFilterScopes()) { + $filter->save(); + $this->filesGenerated[] = $filter->getYamlFilePath(); + } + + if ($lists = $this->makeModelListColumns()) { + $lists->save(); + $this->filesGenerated[] = $lists->getYamlFilePath(); + } + + if ($form = $this->makeModelFormFields()) { + $form->save(); + $this->filesGenerated[] = $form->getYamlFilePath(); + } + + if ($model = $this->makeModelModel()) { + $model->save(); + $this->filesGenerated[] = $model->getModelFilePath(); + } + } + + /** + * makeModelModel + */ + protected function makeModelModel() + { + $model = new ModelModel; + + $model->setPluginCodeObj($this->sourceModel->getPluginCodeObj()); + + $model->className = $this->getConfig('modelClass'); + + $model->databaseTable = $this->getConfig('tableName'); + + $model->addTimestamps = true; + + $model->addSoftDeleting = true; + + $model->skipDbValidation = true; + + $model->traits[] = \Tailor\Traits\BlueprintRelationModel::class; + + // Custom logic for settings models + if ($this->sourceModel->useSettingModel()) { + $model->baseClassName = \System\Models\SettingModel::class; + + $model->addSoftDeleting = false; + } + + $this->extendModelWithModelSpecs($model); + + return $model; + } + + /** + * extendModelWithModelSpecs + */ + protected function extendModelWithModelSpecs($model) + { + $container = new ModelContainer; + + $container->setSourceModel($this->sourceModel); + + $fieldset = $this->sourceModel->getBlueprintFieldset(); + + $fieldset->applyModelExtensions($container); + + $model->relationDefinitions = (array) $container->getProcessedRelationDefinitions(); + + $model->validationDefinitions = (array) $container->getValidationDefinitions(); + + $model->validationDefinitions['rules'] += ['title' => 'required']; + + if ($this->sourceModel->useMultisite()) { + $model->traits[] = \October\Rain\Database\Traits\Multisite::class; + + $model->multisiteDefinition = (array) $container->getMultisiteDefinition(); + } + + if ($this->sourceModel->useStructure()) { + $model->traits[] = \October\Rain\Database\Traits\NestedTree::class; + } + } + + /** + * makeModelFormFields + */ + protected function makeModelFormFields() + { + $model = new ModelFormModel; + + $model->setPluginCodeObj($this->sourceModel->getPluginCodeObj()); + + $model->setModelClassName($this->getConfig('modelClass')); + + $model->fileName = 'fields.yaml'; + + $container = new FormElementContainer; + + $container->setSourceModel($this->sourceModel); + + $fieldset = $this->sourceModel->getBlueprintFieldset(); + + $fieldset->defineAllFormFields($container, ['context' => '*']); + + $model->controls = [ + 'fields' => $container->getPrimaryControls(), + 'tabs' => ['fields' => $container->getControls()] + ]; + + return $model; + } + + /** + * makeModelListColumns + */ + protected function makeModelListColumns() + { + $model = new ModelListModel; + + $model->setPluginCodeObj($this->sourceModel->getPluginCodeObj()); + + $model->setModelClassName($this->getConfig('modelClass')); + + $model->fileName = 'columns.yaml'; + + $container = new ListElementContainer; + + $fieldset = $this->sourceModel->getBlueprintFieldset(); + + $fieldset->defineAllListColumns($container); + + $container->postProcessControls(); + + $model->columns = $container->getPrimaryControls() + $container->getControls(); + + if (!$model->columns) { + return null; + } + + return $model; + } + + /** + * makeModelFilterScopes + */ + protected function makeModelFilterScopes() + { + $model = new ModelFilterModel; + + $model->setPluginCodeObj($this->sourceModel->getPluginCodeObj()); + + $model->setModelClassName($this->getConfig('modelClass')); + + $model->fileName = 'scopes.yaml'; + + $container = new FilterElementContainer; + + $fieldset = $this->sourceModel->getBlueprintFieldset(); + + $fieldset->defineAllFilterScopes($container); + + $model->scopes = $container->getControls(); + + if (!$model->scopes) { + return null; + } + + return $model; + } +} diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/HasNavigation.php b/plugins/rainlab/builder/classes/blueprintgenerator/HasNavigation.php new file mode 100644 index 0000000..c5caa9b --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/HasNavigation.php @@ -0,0 +1,152 @@ + menu_code + */ + protected $seenMenuItems = []; + + /** + * validateNavigation + */ + protected function validateNavigation() + { + $this->seenMenuItems = []; + $model = $this->loadOrCreateMenusModel(); + $model->menus = array_merge($model->menus, $this->makeNavigationItems()); + $model->validate(); + } + + /** + * generateNavigation + */ + protected function generateNavigation() + { + $model = $this->loadOrCreateMenusModel(); + $model->menus = array_merge($model->menus, $this->makeNavigationItems()); + $model->save(); + } + + /** + * makeNavigationItems + */ + protected function makeNavigationItems() + { + $indexer = BlueprintIndexer::instance(); + + $menus = []; + + $parentCodes = []; + + // Primary navigation + foreach ($this->sourceBlueprints as $blueprint) { + $this->setBlueprintContext($blueprint); + + $primaryNav = $indexer->findPrimaryNavigation($blueprint->uuid); + if (!$primaryNav) { + continue; + } + + $parentCodes[$primaryNav->code] = $blueprint->uuid; + $menuItem = $primaryNav->toBackendMenuArray(); + $menuItem['url'] = $this->getControllerUrl(); + $menuItem['code'] = $this->getNavigationCodeForUuid($blueprint->uuid); + $menuItem['sideMenu'] = []; + + $secondaryNav = $indexer->findSecondaryNavigation($blueprint->uuid); + if ($secondaryNav && $secondaryNav->hasPrimary) { + $subItem = $secondaryNav->toBackendMenuArray(); + $subItem['url'] = $this->getControllerUrl(); + $subItem['code'] = $this->getNavigationCodeForUuid($blueprint->uuid); + $subItem['permissions'] = [$this->getConfig('permissionCode')]; + $menuItem['sideMenu'][$secondaryNav->code] = $subItem; + $this->seenMenuItems[$blueprint->uuid] = $menuItem['code'].'||'.$subItem['code']; + } + + $menus[$primaryNav->code] = $menuItem; + } + + // Secondary navigation + foreach ($this->sourceBlueprints as $blueprint) { + $this->setBlueprintContext($blueprint); + + $secondaryNav = $indexer->findSecondaryNavigation($blueprint->uuid); + if (!$secondaryNav || $secondaryNav->hasPrimary) { + continue; + } + + if (!$secondaryNav->parentCode || !isset($menus[$secondaryNav->parentCode])) { + continue; + } + + $subItem = $secondaryNav->toBackendMenuArray(); + $subItem['url'] = $this->getControllerUrl(); + $subItem['code'] = $this->getNavigationCodeForUuid($blueprint->uuid); + $subItem['permissions'] = [$this->getConfig('permissionCode')]; + + $parentUuid = $parentCodes[$secondaryNav->parentCode] ?? null; + $this->seenMenuItems[$blueprint->uuid] = $parentUuid + ? $this->getNavigationCodeForUuid($parentUuid).'||'.$subItem['code'] + : $subItem['code']; + + $menus[$secondaryNav->parentCode]['sideMenu'][$secondaryNav->code] = $subItem; + } + + foreach ($menus as &$menu) { + $parentPermissions = []; + foreach ($menu['sideMenu'] as $item) { + $parentPermissions = array_merge($parentPermissions, $item['permissions']); + } + $menu['permissions'] = $parentPermissions; + } + + return $menus; + } + + /** + * getNavigationCodeForUuid + */ + protected function getNavigationCodeForUuid($uuid) + { + return $this->sourceModel->blueprints[$uuid]['menuCode'] ?? 'unknown'; + } + + /** + * loadOrCreateMenusModel + */ + protected function loadOrCreateMenusModel() + { + $model = new MenusModel; + + $model->loadPlugin($this->sourceModel->getPluginCodeObj()->toCode()); + + $model->setPluginCodeObj($this->sourceModel->getPluginCodeObj()); + + return $model; + } + + /** + * getControllerUrl + */ + protected function getControllerUrl() + { + return $this->sourceModel->getPluginCodeObj()->toUrl().'/'.strtolower($this->getConfig('controllerClass')); + } + + /** + * getActiveMenuItemCode + */ + protected function getActiveMenuItemCode() + { + $uuid = $this->sourceModel->getBlueprintObject()->uuid; + + return $this->seenMenuItems[$uuid] ?? 'unknown'; + } +} diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/HasPermissions.php b/plugins/rainlab/builder/classes/blueprintgenerator/HasPermissions.php new file mode 100644 index 0000000..a4f7666 --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/HasPermissions.php @@ -0,0 +1,61 @@ +getConfig('permissionCode')) { + $blueprint = $this->sourceModel->getBlueprintObject(); + $model = $this->loadOrCreatePermissionsModel(); + $model->permissions[] = $this->makePermissionItem($blueprint, $permissionCode); + $model->validate(); + } + } + + /** + * generatePermission + */ + protected function generatePermission() + { + if ($permissionCode = $this->getConfig('permissionCode')) { + $blueprint = $this->sourceModel->getBlueprintObject(); + $model = $this->loadOrCreatePermissionsModel(); + $model->permissions[] = $this->makePermissionItem($blueprint, $permissionCode); + $model->save(); + } + } + + /** + * makePermissionItem + */ + protected function makePermissionItem($blueprint, $code) + { + return [ + 'permission' => $code, + 'tab' => $this->sourceModel->getPluginName(), + 'label' => __("Manage :name Items", ['name' => $blueprint->name]), + ]; + } + + /** + * loadOrCreatePermissionsModel + */ + protected function loadOrCreatePermissionsModel() + { + $model = new PermissionsModel; + + $model->loadPlugin($this->sourceModel->getPluginCodeObj()->toCode()); + + $model->setPluginCodeObj($this->sourceModel->getPluginCodeObj()); + + return $model; + } +} diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/HasVersionFile.php b/plugins/rainlab/builder/classes/blueprintgenerator/HasVersionFile.php new file mode 100644 index 0000000..95a8a38 --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/HasVersionFile.php @@ -0,0 +1,77 @@ +sourceModel->getPluginFilePath('updates/version.yaml'); + + $versionInformation = $this->sourceModel->getPluginVersionInformation(); + + $nextVersion = $this->getNextVersion(); + + foreach ($this->migrationScripts as $scriptName => $comment) { + $versionInformation[$nextVersion] = [ + $comment, + $scriptName + ]; + + $nextVersion = $this->getNextVersion($nextVersion); + } + + // Add "v" to the version information + $versionInformation = $this->normalizeVersions((array) $versionInformation); + + $yamlData = Yaml::render($versionInformation); + + if (!File::put($versionFilePath, $yamlData)) { + throw new ApplicationException(sprintf('Error saving file %s', $versionFilePath)); + } + + @File::chmod($versionFilePath); + } + + /** + * getNextVersion returns the next version for this plugin + */ + protected function getNextVersion($fromVersion = null) + { + if ($fromVersion) { + $parts = explode('.', $fromVersion); + + $parts[count($parts)-1]++; + + return implode('.', $parts); + } + + $migration = new MigrationModel; + + $migration->setPluginCodeObj($this->sourceModel->getPluginCodeObj()); + + return $migration->getNextVersion(); + } + + /** + * normalizeVersions checks some versions start with v and others not + */ + protected function normalizeVersions(array $versions): array + { + $result = []; + foreach ($versions as $key => $value) { + $version = rtrim(ltrim((string) $key, 'v'), '.'); + $result['v'.$version] = $value; + } + return $result; + } +} diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/ListElementContainer.php b/plugins/rainlab/builder/classes/blueprintgenerator/ListElementContainer.php new file mode 100644 index 0000000..9fb7578 --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/ListElementContainer.php @@ -0,0 +1,103 @@ +label($label)->displayAs('text'); + + $this->columns[$columnName] = $column; + + return $column; + } + + /** + * postProcessControls + */ + public function postProcessControls() + { + foreach ($this->columns as $name => $field) { + if ($field->type === 'partial' && starts_with($field->path, '~/modules/tailor/contentfields/')) { + $field->displayAs('text')->path(null)->relation($name)->select('title'); + } + } + } + + /** + * getPrimaryControls + */ + public function getPrimaryControls() + { + $host = new self; + + $host->defineColumn('id', 'ID')->invisible(); + $host->defineColumn('title', 'Title')->searchable(true); + $host->defineColumn('slug', 'Slug')->searchable(true)->invisible(); + + return $host->getControls(); + } + + /** + * getControls + */ + public function getControls(): array + { + $result = []; + $index = 0; + + foreach ($this->columns as $name => $field) { + $result[$name] = $this->parseFieldConfig($index, $name, $field->config); + $index++; + } + + return $result; + } + + /** + * parseFieldConfig + */ + protected function parseFieldConfig($index, $name, $config): array + { + // Remove tailor values + $ignoreConfig = [ + 'columnName', + 'source', + 'externalToolbarAppState', + 'externalToolbarEventBus' + ]; + + $parsedConfig = array_except((array) $config, $ignoreConfig); + + $parsedConfig['id'] = $index; + $parsedConfig['field'] = $name; + + // Remove default values + $keepDefaults = [ + 'type', + ]; + + $defaultField = new ListColumn; + foreach ($parsedConfig as $key => $value) { + if (!in_array($key, $keepDefaults) && $defaultField->$key === $value) { + unset($parsedConfig[$key]); + } + } + + return $parsedConfig; + } +} diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/ModelContainer.php b/plugins/rainlab/builder/classes/blueprintgenerator/ModelContainer.php new file mode 100644 index 0000000..c0db724 --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/ModelContainer.php @@ -0,0 +1,269 @@ +propagatable = array_merge($this->propagatable, $attributes); + } + + /** + * getBlueprintAttribute + */ + public function getBlueprintAttribute() + { + return $this->getBlueprintDefinition(); + } + + /** + * getProcessedRelationDefinitions + */ + public function getProcessedRelationDefinitions() + { + $definitions = parent::getRelationDefinitions(); + + // Process specific field types + $fieldset = $this->sourceModel->getBlueprintFieldset(); + foreach ($fieldset->getAllFields() as $name => $field) { + if ($field->type === 'entries') { + $this->processEntryRelationDefinitions($definitions, $name, $field); + } + if ($field->type === 'repeater') { + $this->processRepeaterRelationDefinitions($definitions, $name, $field); + } + } + + return $definitions; + } + + /** + * processRepeaterRelationDefinitions + */ + protected function processRepeaterRelationDefinitions(&$definitions, $fieldName, $fieldObj) + { + foreach ($definitions as $type => &$relations) { + foreach ($relations as $name => &$props) { + if ($name === $fieldName && isset($props[0]) && $props[0] === \Tailor\Models\RepeaterItem::class) { + $repeaterInfo = $this->getRepeaterTableInfoFor($fieldName, $fieldObj); + $pluginCodeObj = $this->sourceModel->getPluginCodeObj(); + $props[0] = $pluginCodeObj->toPluginNamespace().'\\Models\\'.$repeaterInfo['modelClass']; + $props['key'] = 'parent_id'; + unset($props['relationClass']); + break; + } + } + } + } + + /** + * getRepeaterTableInfoFor + */ + public function getRepeaterTableInfoFor($fieldName, $fieldObj): ?array + { + $tableName = $this->sourceModel->getBlueprintConfig('tableName'); + if (!$tableName) { + throw new ApplicationException('Missing a table name for repeaters'); + } + + $modelClass = $this->sourceModel->getBlueprintConfig('modelClass'); + $repeaterTable = $tableName .= '_' . mb_strtolower($fieldName) . '_items'; + $repeaterModelClass = $modelClass . Str::studly($fieldName) . 'Item'; + + return [ + 'fieldName' => $fieldName, + 'tableName' => $repeaterTable, + 'modelClass' => $repeaterModelClass + ]; + } + + /** + * processEntryRelationDefinitions + */ + protected function processEntryRelationDefinitions(&$definitions, $fieldName, $fieldObj) + { + $foundDefinition = null; + $foundAsType = null; + foreach ($definitions as $type => &$relations) { + foreach ($relations as $name => &$props) { + if ($name === $fieldName) { + // (╯°□°)╯︵ ┻━┻ + $foundDefinition = array_pull($relations, $name); + $foundAsType = $type; + break; + } + } + } + + if (!$foundDefinition) { + return; + } + + // Clean up and replace class + if ($overrideClass = $this->findRelatedModelClass($fieldObj->source)) { + $foundDefinition[0] = $overrideClass; + } + elseif ($overrideBlueprint = $this->findUuidFromSource($fieldObj->source)) { + $foundDefinition['blueprint'] = $overrideBlueprint; + } + + unset($foundDefinition['relationClass']); + + // This converts custom tailor relations to standard belongs to many + if (isset($foundDefinition['table'])) { + $joinInfo = $fieldObj->inverse + ? $this->getInverseJoinTableInfoFor($fieldName, $fieldObj, $foundDefinition) + : $this->getJoinTableInfoFor($fieldName, $fieldObj); + + if ($joinInfo) { + $foundAsType = 'belongsToMany'; + $foundDefinition['table'] = $joinInfo['tableName']; + unset($foundDefinition['name']); + + // Generic key for blueprints + if ($joinInfo['isBlueprint']) { + $foundDefinition['otherKey'] = $joinInfo['relatedKey']; + } + + // Swap keys + if ($fieldObj->inverse) { + $foundDefinition['key'] = $joinInfo['relatedKey']; + $foundDefinition['otherKey'] = $joinInfo['parentKey']; + } + } + } + + // ┬─┬ノ( º _ ºノ) + $definitions[$foundAsType][$fieldName] = $foundDefinition; + } + + /** + * getJoinTableInfoFor + */ + public function getJoinTableInfoFor($fieldName, $fieldObj): ?array + { + $tableName = $this->sourceModel->getBlueprintConfig('tableName'); + if (!$tableName) { + throw new ApplicationException('Missing a table name for joins'); + } + + $joinTable = $tableName .= '_' . mb_strtolower($fieldName) . '_join'; + + $modelClass = $this->sourceModel->getBlueprintConfig('modelClass'); + $relatedModelClass = $this->findRelatedModelClass($fieldObj->source); + if (!$modelClass) { + return null; + } + + $parentKey = Str::snake(class_basename($modelClass)).'_id'; + $relatedKey = $relatedModelClass + ? Str::snake(class_basename($relatedModelClass)).'_id' + : 'relation_id'; + + return [ + 'fieldName' => $fieldName, + 'tableName' => $joinTable, + 'parentKey' => $parentKey, + 'relatedKey' => $relatedKey, + 'isBlueprint' => !$relatedModelClass + ]; + } + + /** + * getInverseJoinTableInfoFor + */ + public function getInverseJoinTableInfoFor($fieldName, $fieldObj, $foundDefinition): ?array + { + $relatedUuid = $this->findUuidFromSource($fieldObj->source); + if (!$relatedUuid) { + return null; + } + + // Determine join table + $tableName = $this->sourceModel->blueprints[$relatedUuid]['tableName'] ?? null; + if ($tableName) { + $joinTable = $tableName .= '_' . mb_strtolower($fieldObj->inverse) . '_join'; + } + else { + $joinTable = $foundDefinition['table'] ?? 'unknown'; + } + + $modelClass = $this->sourceModel->getBlueprintConfig('modelClass'); + $relatedModelClass = $this->findRelatedModelClass($fieldObj->source); + if (!$modelClass) { + return null; + } + + $parentKey = Str::snake(class_basename($modelClass)).'_id'; + $relatedKey = $relatedModelClass + ? Str::snake(class_basename($relatedModelClass)).'_id' + : 'relation_id'; + + return [ + 'tableName' => $joinTable, + 'parentKey' => $parentKey, + 'relatedKey' => $relatedKey, + 'isBlueprint' => !$relatedModelClass + ]; + } + + /** + * getValidationDefinitions + */ + public function getValidationDefinitions() + { + return [ + 'rules' => $this->rules, + 'attributeNames' => $this->attributeNames, + 'customMessages' => $this->customMessages, + ]; + } + + /** + * getMultisiteDefinition + */ + public function getMultisiteDefinition() + { + return [ + 'fields' => $this->propagatable, + 'sync' => $this->blueprint->useMultisiteSync() + ]; + } +} diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/templates/migration-join.php.tpl b/plugins/rainlab/builder/classes/blueprintgenerator/templates/migration-join.php.tpl new file mode 100644 index 0000000..9cbe949 --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/templates/migration-join.php.tpl @@ -0,0 +1,24 @@ +integer('{{ parentKey }}')->unsigned(); + $table->integer('{{ relatedKey }}')->unsigned(); + $table->primary(['{{ parentKey }}', '{{ relatedKey }}']); + }); + } + + public function down() + { + Schema::dropIfExists('{{ tableName }}'); + } +}; diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/templates/migration-repeater.php.tpl b/plugins/rainlab/builder/classes/blueprintgenerator/templates/migration-repeater.php.tpl new file mode 100644 index 0000000..b26ec1d --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/templates/migration-repeater.php.tpl @@ -0,0 +1,25 @@ +increments('id'); + $table->integer('parent_id')->unsigned()->nullable()->index(); + $table->mediumText('value')->nullable(); + $table->timestamps(); + }); + } + + public function down() + { + Schema::dropIfExists('{{ tableName }}'); + } +}; diff --git a/plugins/rainlab/builder/classes/blueprintgenerator/templates/migration.php.tpl b/plugins/rainlab/builder/classes/blueprintgenerator/templates/migration.php.tpl new file mode 100644 index 0000000..7f42e88 --- /dev/null +++ b/plugins/rainlab/builder/classes/blueprintgenerator/templates/migration.php.tpl @@ -0,0 +1,35 @@ +increments('id'); + $table->integer('site_id')->nullable()->index(); + $table->integer('site_root_id')->nullable()->index(); + $table->string('title')->nullable(); + $table->string('slug')->nullable()->index(); +{{ migrationCode|raw }} +{% if useStructure %} + $table->integer('parent_id')->nullable(); + $table->integer('nest_left')->nullable(); + $table->integer('nest_right')->nullable(); + $table->integer('nest_depth')->nullable(); +{% endif %} + $table->softDeletes(); + $table->timestamps(); + }); + } + + public function down() + { + Schema::dropIfExists('{{ tableName }}'); + } +}; diff --git a/plugins/rainlab/builder/classes/controllergenerator/templates/controller-config-vars.php.tpl b/plugins/rainlab/builder/classes/controllergenerator/templates/controller-config-vars.php.tpl new file mode 100644 index 0000000..62c2600 --- /dev/null +++ b/plugins/rainlab/builder/classes/controllergenerator/templates/controller-config-vars.php.tpl @@ -0,0 +1,3 @@ +{% for configVar, varValue in behaviorConfigVars %} + public ${{ configVar }} = '{{ varValue }}'; +{% endfor %} \ No newline at end of file diff --git a/plugins/rainlab/builder/classes/controllergenerator/templates/controller-no-list.php.tpl b/plugins/rainlab/builder/classes/controllergenerator/templates/controller-no-list.php.tpl new file mode 100644 index 0000000..c77f05f --- /dev/null +++ b/plugins/rainlab/builder/classes/controllergenerator/templates/controller-no-list.php.tpl @@ -0,0 +1,12 @@ + + public function index() + { + $model = $this->formCreateModelObject()->first(); + + if (!$model) { + $model = $this->formCreateModelObject(); + $model->forceSave(); + } + + return Backend::redirect("{{ controllerUrl }}/update/{$model->id}"); + } \ No newline at end of file diff --git a/plugins/rainlab/builder/classes/controllergenerator/templates/controller-permissions.php.tpl b/plugins/rainlab/builder/classes/controllergenerator/templates/controller-permissions.php.tpl new file mode 100644 index 0000000..e1395dd --- /dev/null +++ b/plugins/rainlab/builder/classes/controllergenerator/templates/controller-permissions.php.tpl @@ -0,0 +1,7 @@ +{% if permissions %} + public $requiredPermissions = [ +{% for permission in permissions %} + '{{ permission }}'{% if not loop.last %},{% endif %} +{% endfor %} + ]; +{% endif %} \ No newline at end of file diff --git a/plugins/rainlab/builder/classes/controllergenerator/templates/controller.php.tpl b/plugins/rainlab/builder/classes/controllergenerator/templates/controller.php.tpl new file mode 100644 index 0000000..f6482ef --- /dev/null +++ b/plugins/rainlab/builder/classes/controllergenerator/templates/controller.php.tpl @@ -0,0 +1,27 @@ +getName(); + + if (in_array($name, ['mysql', 'sqlite'])) { + $method = 'get'.ucfirst($name).'PlatformSQLDeclaration'; + + return $this->$method($fieldDeclaration); + } + + throw DBALException::notSupported(__METHOD__); + } + + /** + * Gets the SQL declaration snippet for a field of this type for the MySQL Platform. + * + * @param array $fieldDeclaration The field declaration. + * + * @return string + */ + protected function getMysqlPlatformSQLDeclaration(array $fieldDeclaration) + { + $columnType = $fieldDeclaration['precision'] ? "TIMESTAMP({$fieldDeclaration['precision']})" : 'TIMESTAMP'; + + if (isset($fieldDeclaration['notnull']) && $fieldDeclaration['notnull'] == true) { + return $columnType; + } + + return "$columnType NULL"; + } + + /** + * Gets the SQL declaration snippet for a field of this type for the Sqlite Platform. + * + * @param array $fieldDeclaration The field declaration. + * + * @return string + */ + protected function getSqlitePlatformSQLDeclaration(array $fieldDeclaration) + { + return $this->getMysqlPlatformSQLDeclaration($fieldDeclaration); + } +} diff --git a/plugins/rainlab/builder/classes/standardbehaviorsregistry/formcontroller/templates/create.php.tpl b/plugins/rainlab/builder/classes/standardbehaviorsregistry/formcontroller/templates/create.php.tpl new file mode 100644 index 0000000..5a9b5e7 --- /dev/null +++ b/plugins/rainlab/builder/classes/standardbehaviorsregistry/formcontroller/templates/create.php.tpl @@ -0,0 +1,46 @@ + + + + +fatalError): ?> + + 'layout']) ?> + +
    + formRender() ?> +
    + +
    +
    + + + + + +
    +
    + + + + +

    fatalError)) ?>

    +

    + \ No newline at end of file diff --git a/plugins/rainlab/builder/classes/standardbehaviorsregistry/formcontroller/templates/preview.php.tpl b/plugins/rainlab/builder/classes/standardbehaviorsregistry/formcontroller/templates/preview.php.tpl new file mode 100644 index 0000000..8236c2f --- /dev/null +++ b/plugins/rainlab/builder/classes/standardbehaviorsregistry/formcontroller/templates/preview.php.tpl @@ -0,0 +1,22 @@ + + + + +fatalError): ?> + +
    + formRenderPreview() ?> +
    + + +

    fatalError) ?>

    + + +

    + + + +

    \ No newline at end of file diff --git a/plugins/rainlab/builder/classes/standardbehaviorsregistry/formcontroller/templates/update.php.tpl b/plugins/rainlab/builder/classes/standardbehaviorsregistry/formcontroller/templates/update.php.tpl new file mode 100644 index 0000000..544f44a --- /dev/null +++ b/plugins/rainlab/builder/classes/standardbehaviorsregistry/formcontroller/templates/update.php.tpl @@ -0,0 +1,54 @@ + + + + +fatalError): ?> + + 'layout']) ?> + +
    + formRender() ?> +
    + +
    +
    + + + + + + + +
    +
    + + + +

    fatalError)) ?>

    +

    + \ No newline at end of file diff --git a/plugins/rainlab/builder/classes/standardbehaviorsregistry/importexportcontroller/templates/export.php.tpl b/plugins/rainlab/builder/classes/standardbehaviorsregistry/importexportcontroller/templates/export.php.tpl new file mode 100644 index 0000000..352e5bf --- /dev/null +++ b/plugins/rainlab/builder/classes/standardbehaviorsregistry/importexportcontroller/templates/export.php.tpl @@ -0,0 +1,18 @@ + 'layout']) ?> + +
    + exportRender() ?> +
    + +
    + +
    + + diff --git a/plugins/rainlab/builder/classes/standardbehaviorsregistry/importexportcontroller/templates/import.php.tpl b/plugins/rainlab/builder/classes/standardbehaviorsregistry/importexportcontroller/templates/import.php.tpl new file mode 100644 index 0000000..10122a0 --- /dev/null +++ b/plugins/rainlab/builder/classes/standardbehaviorsregistry/importexportcontroller/templates/import.php.tpl @@ -0,0 +1,18 @@ + 'layout']) ?> + +
    + importRender() ?> +
    + +
    + +
    + + diff --git a/plugins/rainlab/builder/classes/standardbehaviorsregistry/listcontroller/templates/_list_toolbar.php.tpl b/plugins/rainlab/builder/classes/standardbehaviorsregistry/listcontroller/templates/_list_toolbar.php.tpl new file mode 100644 index 0000000..6a78847 --- /dev/null +++ b/plugins/rainlab/builder/classes/standardbehaviorsregistry/listcontroller/templates/_list_toolbar.php.tpl @@ -0,0 +1,26 @@ +
    +{% if hasFormBehavior %} + + + +{% endif %} +{% if hasImportExportBehavior %} + + + + + + +{% endif %} + +
    diff --git a/plugins/rainlab/builder/classes/standardbehaviorsregistry/listcontroller/templates/index.php.tpl b/plugins/rainlab/builder/classes/standardbehaviorsregistry/listcontroller/templates/index.php.tpl new file mode 100644 index 0000000..ea43a36 --- /dev/null +++ b/plugins/rainlab/builder/classes/standardbehaviorsregistry/listcontroller/templates/index.php.tpl @@ -0,0 +1 @@ +listRender() ?> diff --git a/plugins/rainlab/builder/classes/standardcontrolsregistry/HasFormFields.php b/plugins/rainlab/builder/classes/standardcontrolsregistry/HasFormFields.php new file mode 100644 index 0000000..ade2531 --- /dev/null +++ b/plugins/rainlab/builder/classes/standardcontrolsregistry/HasFormFields.php @@ -0,0 +1,347 @@ +controlLibrary->registerControl( + 'text', + 'rainlab.builder::lang.form.control_text', + 'rainlab.builder::lang.form.control_text_description', + ControlLibrary::GROUP_STANDARD, + 'icon-terminal', + $this->controlLibrary->getStandardProperties(['stretch']), + null + ); + } + + /** + * registerNumberControl + */ + protected function registerNumberControl() + { + // Extra properties + $extraProps = [ + 'min' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_min'), + 'description' => Lang::get('rainlab.builder::lang.form.property_min_description'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'validation' => [ + 'regex' => [ + 'pattern' => '^[0-9]+$', + 'message' => Lang::get('rainlab.builder::lang.form.property_min_number') + ] + ], + ], + 'max' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_max'), + 'description' => Lang::get('rainlab.builder::lang.form.property_max_description'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'validation' => [ + 'regex' => [ + 'pattern' => '^[0-9]+$', + 'message' => Lang::get('rainlab.builder::lang.form.property_max_number') + ] + ], + ], + 'step' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_step'), + 'description' => Lang::get('rainlab.builder::lang.form.property_step_description'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'validation' => [ + 'regex' => [ + 'pattern' => '^[0-9]+$', + 'message' => Lang::get('rainlab.builder::lang.form.property_step_number') + ] + ], + ], + ]; + + $this->controlLibrary->registerControl( + 'number', + 'rainlab.builder::lang.form.control_number', + 'rainlab.builder::lang.form.control_number_description', + ControlLibrary::GROUP_STANDARD, + 'icon-superscript', + $this->controlLibrary->getStandardProperties(['stretch'], $extraProps), + null + ); + } + + /** + * registerPasswordControl + */ + protected function registerPasswordControl() + { + $this->controlLibrary->registerControl( + 'password', + 'rainlab.builder::lang.form.control_password', + 'rainlab.builder::lang.form.control_password_description', + ControlLibrary::GROUP_STANDARD, + 'icon-lock', + $this->controlLibrary->getStandardProperties(['stretch']), + null + ); + } + + /** + * registerEmailControl + */ + protected function registerEmailControl() + { + $this->controlLibrary->registerControl( + 'email', + 'rainlab.builder::lang.form.control_email', + 'rainlab.builder::lang.form.control_email_description', + ControlLibrary::GROUP_STANDARD, + 'icon-envelope', + $this->controlLibrary->getStandardProperties(['stretch']), + null + ); + } + + /** + * registerTextareaControl + */ + protected function registerTextareaControl() + { + $properties = $this->getFieldSizeProperties(); + + $this->controlLibrary->registerControl( + 'textarea', + 'rainlab.builder::lang.form.control_textarea', + 'rainlab.builder::lang.form.control_textarea_description', + ControlLibrary::GROUP_STANDARD, + 'icon-pencil-square-o', + $this->controlLibrary->getStandardProperties(['stretch'], $properties), + null + ); + } + + /** + * registerDropdownControl + */ + protected function registerDropdownControl() + { + $properties = [ + 'options' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_options'), + 'type' => 'dictionary', + 'ignoreIfEmpty' => true, + 'sortOrder' => 81 + ], + 'optionsMethod' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_options_method'), + 'description' => Lang::get('rainlab.builder::lang.form.property_options_method_description'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 82 + ], + 'emptyOption' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_empty_option'), + 'description' => Lang::get('rainlab.builder::lang.form.property_empty_option_description'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 83 + ], + 'showSearch' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_show_search'), + 'description' => Lang::get('rainlab.builder::lang.form.property_show_search_description'), + 'type' => 'checkbox', + 'sortOrder' => 84, + 'default' => true + ] + ]; + + $this->controlLibrary->registerControl( + 'dropdown', + 'rainlab.builder::lang.form.control_dropdown', + 'rainlab.builder::lang.form.control_dropdown_description', + ControlLibrary::GROUP_STANDARD, + 'icon-angle-double-down', + $this->controlLibrary->getStandardProperties(['stretch'], $properties), + null + ); + } + + /** + * registerRadioListControl + */ + protected function registerRadioListControl() + { + $properties = [ + 'options' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_options'), + 'type' => 'dictionary', + 'ignoreIfEmpty' => true, + 'sortOrder' => 81 + ], + 'optionsMethod' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_options_method'), + 'description' => Lang::get('rainlab.builder::lang.form.property_options_method_description'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 82 + ], + ]; + + $excludeProperties = [ + 'stretch', + 'default', + 'placeholder', + 'defaultFrom', + 'preset' + ]; + + $this->controlLibrary->registerControl( + 'radio', + 'rainlab.builder::lang.form.control_radio', + 'rainlab.builder::lang.form.control_radio_description', + ControlLibrary::GROUP_STANDARD, + 'icon-dot-circle-o', + $this->controlLibrary->getStandardProperties($excludeProperties, $properties), + null + ); + } + + /** + * registerBalloonSelectorControl + */ + protected function registerBalloonSelectorControl() + { + $properties = [ + 'options' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_options'), + 'type' => 'dictionary', + 'ignoreIfEmpty' => true, + 'sortOrder' => 81 + ], + 'optionsMethod' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_options_method'), + 'description' => Lang::get('rainlab.builder::lang.form.property_options_method_description'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 82 + ], + ]; + + $this->controlLibrary->registerControl( + 'balloon-selector', + 'rainlab.builder::lang.form.control_balloon-selector', + 'rainlab.builder::lang.form.control_balloon-selector_description', + ControlLibrary::GROUP_STANDARD, + 'icon-ellipsis-h', + $this->controlLibrary->getStandardProperties(['stretch'], $properties), + null + ); + } + + /** + * registerCheckboxControl + */ + protected function registerCheckboxControl() + { + $this->controlLibrary->registerControl( + 'checkbox', + 'rainlab.builder::lang.form.control_checkbox', + 'rainlab.builder::lang.form.control_checkbox_description', + ControlLibrary::GROUP_STANDARD, + 'icon-check-square-o', + $this->controlLibrary->getStandardProperties(['oc.commentPosition', 'stretch'], $this->getCheckboxTypeProperties()), + null + ); + } + + /** + * registerCheckboxListControl + */ + protected function registerCheckboxListControl() + { + $properties = [ + 'options' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_options'), + 'type' => 'dictionary', + 'ignoreIfEmpty' => true, + 'sortOrder' => 81 + ], + 'optionsMethod' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_options_method'), + 'description' => Lang::get('rainlab.builder::lang.form.property_options_method_description'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 82 + ], + 'quickselect' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_quickselect'), + 'description' => Lang::get('rainlab.builder::lang.form.property_quickselect_description'), + 'type' => 'checkbox', + 'ignoreIfEmpty' => true, + ], + 'inlineOptions' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_inline_options'), + 'description' => Lang::get('rainlab.builder::lang.form.property_inline_options_description'), + 'type' => 'checkbox', + 'ignoreIfEmpty' => true, + ] + ]; + + $excludeProperties = [ + 'stretch', + 'default', + 'placeholder', + 'defaultFrom', + 'preset' + ]; + + $this->controlLibrary->registerControl( + 'checkboxlist', + 'rainlab.builder::lang.form.control_checkboxlist', + 'rainlab.builder::lang.form.control_checkboxlist_description', + ControlLibrary::GROUP_STANDARD, + 'icon-list', + $this->controlLibrary->getStandardProperties($excludeProperties, $properties), + null + ); + } + + /** + * registerSwitchControl + */ + protected function registerSwitchControl() + { + $this->controlLibrary->registerControl( + 'switch', + 'rainlab.builder::lang.form.control_switch', + 'rainlab.builder::lang.form.control_switch_description', + ControlLibrary::GROUP_STANDARD, + 'icon-toggle-on', + $this->controlLibrary->getStandardProperties(['oc.commentPosition', 'stretch'], $this->getCheckboxTypeProperties()), + null + ); + } + + /** + * getCheckboxTypeProperties + */ + protected function getCheckboxTypeProperties() + { + return [ + 'default' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_checked_default_title'), + 'type' => 'checkbox' + ] + ]; + } +} diff --git a/plugins/rainlab/builder/classes/standardcontrolsregistry/HasFormUi.php b/plugins/rainlab/builder/classes/standardcontrolsregistry/HasFormUi.php new file mode 100644 index 0000000..60d7c9a --- /dev/null +++ b/plugins/rainlab/builder/classes/standardcontrolsregistry/HasFormUi.php @@ -0,0 +1,166 @@ +controlLibrary->registerControl( + 'section', + 'rainlab.builder::lang.form.control_section', + 'rainlab.builder::lang.form.control_section_description', + ControlLibrary::GROUP_UI, + 'icon-minus', + $this->controlLibrary->getStandardProperties($excludeProperties), + null + ); + } + + /** + * registerHintControl + */ + protected function registerHintControl() + { + $excludeProperties = [ + 'stretch', + 'default', + 'placeholder', + 'required', + 'defaultFrom', + 'dependsOn', + 'preset', + 'attributes', + 'oc.commentPosition', + 'disabled' + ]; + + $properties = [ + 'path' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_hint_path'), + 'description' => Lang::get('rainlab.builder::lang.form.property_hint_path_description'), + 'type' => 'string', + 'sortOrder' => 81 + ], + 'mode' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_display_mode'), + 'description' => Lang::get('rainlab.builder::lang.form.property_display_mode_description'), + 'type' => 'dropdown', + 'default' => 'info', + 'options' => [ + 'tip' => Lang::get('rainlab.builder::lang.form.class_mode_tip'), + 'info' => Lang::get('rainlab.builder::lang.form.class_mode_info'), + 'warning' => Lang::get('rainlab.builder::lang.form.class_mode_warning'), + 'danger' => Lang::get('rainlab.builder::lang.form.class_mode_danger'), + 'success' => Lang::get('rainlab.builder::lang.form.class_mode_success'), + ], + 'sortOrder' => 82 + ] + ]; + + $this->controlLibrary->registerControl( + 'hint', + 'rainlab.builder::lang.form.control_hint', + 'rainlab.builder::lang.form.control_hint_description', + ControlLibrary::GROUP_UI, + 'icon-question-circle', + $this->controlLibrary->getStandardProperties($excludeProperties, $properties), + null + ); + } + + /** + * registerRulerControl + */ + protected function registerRulerControl() + { + $excludeProperties = [ + 'label', + 'stretch', + 'default', + 'placeholder', + 'required', + 'defaultFrom', + 'dependsOn', + 'preset', + 'attributes', + 'oc.comment', + 'oc.commentPosition', + 'disabled' + ]; + + $this->controlLibrary->registerControl( + 'ruler', + 'rainlab.builder::lang.form.control_ruler', + 'rainlab.builder::lang.form.control_ruler_description', + ControlLibrary::GROUP_UI, + 'icon-minus', + $this->controlLibrary->getStandardProperties($excludeProperties), + null + ); + } + + /** + * registerPartialControl + */ + protected function registerPartialControl() + { + $excludeProperties = [ + 'stretch', + 'default', + 'placeholder', + 'required', + 'defaultFrom', + 'dependsOn', + 'preset', + 'attributes', + 'oc.commentPosition', + 'oc.comment', + 'disabled' + ]; + + $properties = [ + 'path' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_partial_path'), + 'description' => Lang::get('rainlab.builder::lang.form.property_partial_path_description'), + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.form.property_partial_path_required') + ] + ], + 'sortOrder' => 81 + ] + ]; + + $this->controlLibrary->registerControl( + 'partial', + 'rainlab.builder::lang.form.control_partial', + 'rainlab.builder::lang.form.control_partial_description', + ControlLibrary::GROUP_UI, + 'icon-file-text-o', + $this->controlLibrary->getStandardProperties($excludeProperties, $properties), + null + ); + } +} diff --git a/plugins/rainlab/builder/classes/standardcontrolsregistry/HasFormWidgets.php b/plugins/rainlab/builder/classes/standardcontrolsregistry/HasFormWidgets.php new file mode 100644 index 0000000..c67b96f --- /dev/null +++ b/plugins/rainlab/builder/classes/standardcontrolsregistry/HasFormWidgets.php @@ -0,0 +1,1269 @@ +getFieldSizeProperties() + [ + 'language' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_code_language'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_code_editor'), + 'type' => 'dropdown', + 'default' => 'php', + 'options' => [ + 'css' => 'CSS', + 'html' => 'HTML', + 'javascript' => 'JavaScript', + 'less' => 'LESS', + 'markdown' => 'Markdown', + 'php' => 'PHP', + 'plain_text' => 'Plain text', + 'sass' => 'SASS', + 'scss' => 'SCSS', + 'twig' => 'Twig' + ], + 'sortOrder' => 82 + ], + 'theme' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_code_theme'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_code_editor'), + 'type' => 'dropdown', + 'default' => '', + 'ignoreIfEmpty' => true, + 'options' => [ + '' => Lang::get('rainlab.builder::lang.form.property_theme_use_default'), + 'ambiance' => 'Ambiance', + 'chaos' => 'Chaos', + 'chrome' => 'Chrome', + 'clouds' => 'Clouds', + 'clouds_midnight' => 'Clouds midnight', + 'cobalt' => 'Cobalt', + 'crimson_editor' => 'Crimson editor', + 'dawn' => 'Dawn', + 'dreamweaver' => 'Dreamweaver', + 'eclipse' => 'Eclipse', + 'github' => 'Github', + 'idle_fingers' => 'Idle fingers', + 'iplastic' => 'IPlastic', + 'katzenmilch' => 'Katzenmilch', + 'kr_theme' => 'krTheme', + 'kuroir' => 'Kuroir', + 'merbivore' => 'Merbivore', + 'merbivore_soft' => 'Merbivore soft', + 'mono_industrial' => 'Mono industrial', + 'monokai' => 'Monokai', + 'pastel_on_dark' => 'Pastel on dark', + 'solarized_dark' => 'Solarized dark', + 'solarized_light' => 'Solarized light', + 'sqlserver' => 'SQL server', + 'terminal' => 'Terminal', + 'textmate' => 'Textmate', + 'tomorrow' => 'Tomorrow', + 'tomorrow_night' => 'Tomorrow night', + 'tomorrow_night_blue' => 'Tomorrow night blue', + 'tomorrow_night_bright' => 'Tomorrow night bright', + 'tomorrow_night_eighties' => 'Tomorrow night eighties', + 'twilight' => 'Twilight', + 'vibrant_ink' => 'Vibrant ink', + 'xcode' => 'XCode' + ], + 'sortOrder' => 83 + ], + 'showGutter' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_gutter'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_code_editor'), + 'type' => 'dropdown', + 'default' => '', + 'ignoreIfEmpty' => true, + 'booleanValues' => true, + 'options' => [ + '' => Lang::get('rainlab.builder::lang.form.property_use_default'), + 'true' => Lang::get('rainlab.builder::lang.form.property_gutter_show'), + 'false' => Lang::get('rainlab.builder::lang.form.property_gutter_hide'), + ], + 'sortOrder' => 84 + ], + 'wordWrap' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_wordwrap'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_code_editor'), + 'type' => 'dropdown', + 'default' => '', + 'ignoreIfEmpty' => true, + 'booleanValues' => true, + 'options' => [ + '' => Lang::get('rainlab.builder::lang.form.property_use_default'), + 'true' => Lang::get('rainlab.builder::lang.form.property_wordwrap_wrap'), + 'false' => Lang::get('rainlab.builder::lang.form.property_wordwrap_nowrap'), + ], + 'sortOrder' => 85 + ], + 'fontSize' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_fontsize'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_code_editor'), + 'type' => 'dropdown', + 'default' => '', + 'ignoreIfEmpty' => true, + 'options' => [ + '' => Lang::get('rainlab.builder::lang.form.property_use_default'), + '10' => '10px', + '11' => '11px', + '12' => '11px', + '13' => '13px', + '14' => '14px', + '16' => '16px', + '18' => '18px', + '20' => '20px', + '24' => '24px' + ], + 'sortOrder' => 86 + ], + 'codeFolding' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_codefolding'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_code_editor'), + 'type' => 'dropdown', + 'default' => '', + 'ignoreIfEmpty' => true, + 'options' => [ + '' => Lang::get('rainlab.builder::lang.form.property_use_default'), + 'manual' => Lang::get('rainlab.builder::lang.form.property_codefolding_manual'), + 'markbegin' => Lang::get('rainlab.builder::lang.form.property_codefolding_markbegin'), + 'markbeginend' => Lang::get('rainlab.builder::lang.form.property_codefolding_markbeginend'), + ], + 'sortOrder' => 87 + ], + 'autoClosing' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_autoclosing'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_code_editor'), + 'type' => 'dropdown', + 'default' => '', + 'ignoreIfEmpty' => true, + 'booleanValues' => true, + 'options' => [ + '' => Lang::get('rainlab.builder::lang.form.property_use_default'), + 'true' => Lang::get('rainlab.builder::lang.form.property_enabled'), + 'false' => Lang::get('rainlab.builder::lang.form.property_disabled') + ], + 'sortOrder' => 88 + ], + 'useSoftTabs' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_soft_tabs'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_code_editor'), + 'type' => 'dropdown', + 'default' => '', + 'ignoreIfEmpty' => true, + 'booleanValues' => true, + 'options' => [ + '' => Lang::get('rainlab.builder::lang.form.property_use_default'), + 'true' => Lang::get('rainlab.builder::lang.form.property_enabled'), + 'false' => Lang::get('rainlab.builder::lang.form.property_disabled') + ], + 'sortOrder' => 89 + ], + 'tabSize' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_tab_size'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_code_editor'), + 'type' => 'dropdown', + 'default' => '', + 'ignoreIfEmpty' => true, + 'options' => [ + '' => Lang::get('rainlab.builder::lang.form.property_use_default'), + 2 => 2, + 4 => 4, + 8 => 8 + ], + 'sortOrder' => 90 + ], + 'readOnly' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_readonly'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_code_editor'), + 'default' => 0, + 'ignoreIfEmpty' => true, + 'type' => 'checkbox' + ] + ]; + + $this->controlLibrary->registerControl( + 'codeeditor', + 'rainlab.builder::lang.form.control_codeeditor', + 'rainlab.builder::lang.form.control_codeeditor_description', + ControlLibrary::GROUP_WIDGETS, + 'icon-code', + $this->controlLibrary->getStandardProperties($excludeProperties, $properties), + null + ); + } + + /** + * registerColorPickerWidget + */ + protected function registerColorPickerWidget() + { + $excludeProperties = [ + 'stretch' + ]; + + $properties = [ + 'availableColors' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_available_colors'), + 'description' => Lang::get('rainlab.builder::lang.form.property_available_colors_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_colorpicker'), + 'type' => 'stringList', + 'ignoreIfEmpty' => true, + 'sortOrder' => 81 + ], + 'allowEmpty' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_allow_empty'), + 'description' => Lang::get('rainlab.builder::lang.form.property_allow_empty_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_colorpicker'), + 'type' => 'checkbox', + 'default' => true, + 'ignoreIfEmpty' => true, + ], + 'allowCustom' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_allow_custom'), + 'description' => Lang::get('rainlab.builder::lang.form.property_allow_custom_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_colorpicker'), + 'type' => 'checkbox', + 'default' => true, + 'ignoreIfEmpty' => true, + ], + 'showAlpha' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_show_alpha'), + 'description' => Lang::get('rainlab.builder::lang.form.property_show_alpha_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_colorpicker'), + 'type' => 'checkbox', + 'ignoreIfEmpty' => true, + ], + 'showInput' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_show_input'), + 'description' => Lang::get('rainlab.builder::lang.form.property_show_input_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_colorpicker'), + 'type' => 'checkbox', + 'ignoreIfEmpty' => true, + ], + ]; + + $this->controlLibrary->registerControl( + 'colorpicker', + 'rainlab.builder::lang.form.control_colorpicker', + 'rainlab.builder::lang.form.control_colorpicker_description', + ControlLibrary::GROUP_WIDGETS, + 'icon-eyedropper', + $this->controlLibrary->getStandardProperties($excludeProperties, $properties), + null + ); + } + + /** + * registerDataTableWidget + */ + protected function registerDataTableWidget() + { + $excludeProperties = [ + 'stretch' + ]; + + $properties = [ + 'oc.columns' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_columns'), + 'description' => Lang::get('rainlab.builder::lang.form.property_columns_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_datatable'), + 'type' => 'objectList', + 'ignoreIfEmpty' => true, + 'titleProperty' => 'title', + 'itemProperties' => [ + [ + 'property' => 'type', + 'title' => Lang::get('rainlab.builder::lang.form.property_datatable_type'), + 'type' => 'dropdown', + 'default' => 'string', + 'options' => [ + 'string' => "String", + 'checkbox' => "Checkbox", + 'dropdown' => "Dropdown", + 'autocomplete' => "Autocomplete", + ], + ], + [ + 'property' => 'code', + 'title' => Lang::get('rainlab.builder::lang.form.property_datatable_code'), + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.form.property_datatable_code_regex'), + ] + ], + ], + [ + 'property' => 'title', + 'title' => Lang::get('rainlab.builder::lang.form.property_datatable_title'), + 'type' => 'string' + ], + [ + 'property' => 'options', + 'title' => Lang::get('rainlab.builder::lang.form.property_options'), + 'type' => 'dictionary', + 'ignoreIfEmpty' => true, + ], + [ + 'property' => 'width', + 'title' => Lang::get('rainlab.builder::lang.form.property_datatable_width'), + 'type' => 'string', + 'validation' => [ + 'regex' => [ + 'pattern' => '^[0-9]+$', + 'message' => Lang::get('rainlab.builder::lang.form.property_datatable_width_regex') + ] + ], + ] + ], + 'sortOrder' => 81 + ], + 'adding' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_datatable_adding'), + 'description' => Lang::get('rainlab.builder::lang.form.property_datatable_adding_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_datatable'), + 'type' => 'checkbox', + 'ignoreIfEmpty' => true, + ], + 'deleting' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_datatable_deleting'), + 'description' => Lang::get('rainlab.builder::lang.form.property_datatable_deleting_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_datatable'), + 'type' => 'checkbox', + 'ignoreIfEmpty' => true, + ], + 'searching' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_datatable_searching'), + 'description' => Lang::get('rainlab.builder::lang.form.property_datatable_searching_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_datatable'), + 'type' => 'checkbox', + 'ignoreIfEmpty' => true, + ], + ]; + + $this->controlLibrary->registerControl( + 'datatable', + 'rainlab.builder::lang.form.control_datatable', + 'rainlab.builder::lang.form.control_datatable_description', + ControlLibrary::GROUP_WIDGETS, + 'icon-table', + $this->controlLibrary->getStandardProperties($excludeProperties, $properties), + null + ); + } + + /** + * registerDatepickerWidget + */ + protected function registerDatepickerWidget() + { + $excludeProperties = [ + 'stretch' + ]; + + $properties = [ + 'mode' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_datepicker_mode'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_datepicker'), + 'type' => 'dropdown', + 'default' => 'datetime', + 'options' => [ + 'date' => Lang::get('rainlab.builder::lang.form.property_datepicker_mode_date'), + 'datetime' => Lang::get('rainlab.builder::lang.form.property_datepicker_mode_datetime'), + 'time' => Lang::get('rainlab.builder::lang.form.property_datepicker_mode_time') + ], + 'sortOrder' => 81 + ], + 'format' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_datepicker_format'), + 'description' => Lang::get('rainlab.builder::lang.form.property_datepicker_year_format_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_datepicker'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 82 + ], + 'minDate' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_datepicker_min_date'), + 'description' => Lang::get('rainlab.builder::lang.form.property_datepicker_min_date_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_datepicker'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 83 + ], + 'maxDate' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_datepicker_max_date'), + 'description' => Lang::get('rainlab.builder::lang.form.property_datepicker_max_date_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_datepicker'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 84 + ], + 'yearRange' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_datepicker_year_range'), + 'description' => Lang::get('rainlab.builder::lang.form.property_datepicker_year_range_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_datepicker'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'validation' => [ + 'regex' => [ + 'pattern' => '^([0-9]+|\[[0-9]{4},[0-9]{4}\])$', + 'message' => Lang::get('rainlab.builder::lang.form.property_datepicker_year_range_invalid_format') + ] + ], + 'sortOrder' => 85 + ], + 'firstDay' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_datepicker_first_day'), + 'description' => Lang::get('rainlab.builder::lang.form.property_datepicker_first_day_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_datepicker'), + 'type' => 'string', + 'validation' => [ + 'regex' => [ + 'pattern' => '^[0-9]+$', + 'message' => Lang::get('rainlab.builder::lang.form.property_datepicker_first_day_regex') + ] + ], + 'ignoreIfEmpty' => true, + 'sortOrder' => 86 + ], + 'twelveHour' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_datepicker_twelve_hour'), + 'description' => Lang::get('rainlab.builder::lang.form.property_datepicker_twelve_hour_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_datepicker'), + 'type' => 'checkbox', + 'ignoreIfEmpty' => true, + 'sortOrder' => 87 + ], + 'showWeekNumber' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_datepicker_show_week_number'), + 'description' => Lang::get('rainlab.builder::lang.form.property_datepicker_show_week_number_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_datepicker'), + 'type' => 'checkbox', + 'ignoreIfEmpty' => true, + 'sortOrder' => 88 + ], + ]; + + $this->controlLibrary->registerControl( + 'datepicker', + 'rainlab.builder::lang.form.control_datepicker', + 'rainlab.builder::lang.form.control_datepicker_description', + ControlLibrary::GROUP_WIDGETS, + 'icon-calendar', + $this->controlLibrary->getStandardProperties($excludeProperties, $properties), + null + ); + } + + /** + * registerFileUploadWidget + */ + protected function registerFileUploadWidget() + { + $excludeProperties = [ + 'stretch', + 'default', + 'placeholder', + 'defaultFrom', + 'dependsOn', + 'preset', + 'attributes' + ]; + + $properties = [ + 'mode' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_fileupload_mode'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_fileupload'), + 'type' => 'dropdown', + 'default' => 'file', + 'options' => [ + 'file' => Lang::get('rainlab.builder::lang.form.property_fileupload_mode_file'), + 'image' => Lang::get('rainlab.builder::lang.form.property_fileupload_mode_image') + ], + 'sortOrder' => 81 + ], + 'imageWidth' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_fileupload_image_width'), + 'description' => Lang::get('rainlab.builder::lang.form.property_fileupload_image_width_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_fileupload'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'validation' => [ + 'regex' => [ + 'pattern' => '^[0-9]+$', + 'message' => Lang::get('rainlab.builder::lang.form.property_fileupload_invalid_dimension') + ] + ], + 'sortOrder' => 83 + ], + 'imageHeight' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_fileupload_image_height'), + 'description' => Lang::get('rainlab.builder::lang.form.property_fileupload_image_height_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_fileupload'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'validation' => [ + 'regex' => [ + 'pattern' => '^[0-9]+$', + 'message' => Lang::get('rainlab.builder::lang.form.property_fileupload_invalid_dimension') + ] + ], + 'sortOrder' => 84 + ], + 'fileTypes' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_fileupload_file_types'), + 'description' => Lang::get('rainlab.builder::lang.form.property_fileupload_file_types_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_fileupload'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 85 + ], + 'mimeTypes' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_fileupload_mime_types'), + 'description' => Lang::get('rainlab.builder::lang.form.property_fileupload_mime_types_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_fileupload'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 86 + ], + 'useCaption' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_fileupload_use_caption'), + 'description' => Lang::get('rainlab.builder::lang.form.property_fileupload_use_caption_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_fileupload'), + 'type' => 'checkbox', + 'default' => true, + 'sortOrder' => 87 + ], + 'thumbOptions' => $this->getFieldThumbOptionsProperties()['thumbOptions'], + 'maxFilesize' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_fileupload_maxfilesize'), + 'description' => Lang::get('rainlab.builder::lang.form.property_fileupload_maxfilesize_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_fileupload'), + 'sortOrder' => 89, + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'validation' => [ + 'regex' => [ + 'pattern' => '^[0-9\.]+$', + 'message' => Lang::get('rainlab.builder::lang.form.property_fileupload_invalid_maxfilesize') + ] + ], + ], + 'maxFiles' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_fileupload_maxfiles'), + 'description' => Lang::get('rainlab.builder::lang.form.property_fileupload_maxfiles_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_fileupload'), + 'sortOrder' => 90, + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'validation' => [ + 'regex' => [ + 'pattern' => '^[0-9]+$', + 'message' => Lang::get('rainlab.builder::lang.form.property_fileupload_invalid_maxfiles') + ] + ], + ] + ]; + + $this->controlLibrary->registerControl( + 'fileupload', + 'rainlab.builder::lang.form.control_fileupload', + 'rainlab.builder::lang.form.control_fileupload_description', + ControlLibrary::GROUP_WIDGETS, + 'icon-upload', + $this->controlLibrary->getStandardProperties($excludeProperties, $properties), + null + ); + } + + /** + * registerMarkdownWidget + */ + protected function registerMarkdownWidget() + { + $properties = $this->getFieldSizeProperties() + [ + 'sideBySide' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_side_by_side'), + 'description' => Lang::get('rainlab.builder::lang.form.property_side_by_side_description'), + 'type' => 'checkbox', + 'sortOrder' => 81 + ] + ]; + + $this->controlLibrary->registerControl( + 'markdown', + 'rainlab.builder::lang.form.control_markdown', + 'rainlab.builder::lang.form.control_markdown_description', + ControlLibrary::GROUP_WIDGETS, + 'icon-columns', + $this->controlLibrary->getStandardProperties([], $properties), + null + ); + } + + /** + * registerMediaFinderWidget + */ + protected function registerMediaFinderWidget() + { + $excludeProperties = [ + 'stretch', + 'default', + 'placeholder', + 'defaultFrom', + 'dependsOn', + 'preset', + 'attributes', + 'disabled' + ]; + + $properties = [ + 'mode' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_mediafinder_mode'), + 'type' => 'dropdown', + 'default' => 'file', + 'options' => [ + 'file' => Lang::get('rainlab.builder::lang.form.property_mediafinder_mode_file'), + 'image' => Lang::get('rainlab.builder::lang.form.property_mediafinder_mode_image') + ], + 'sortOrder' => 81 + ], + 'imageWidth' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_fileupload_image_width'), + 'description' => Lang::get('rainlab.builder::lang.form.property_mediafinder_image_width_description'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'validation' => [ + 'regex' => [ + 'pattern' => '^[0-9]+$', + 'message' => Lang::get('rainlab.builder::lang.form.property_fileupload_invalid_dimension') + ] + ], + 'sortOrder' => 82 + ], + 'imageHeight' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_fileupload_image_height'), + 'description' => Lang::get('rainlab.builder::lang.form.property_mediafinder_image_height_description'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'validation' => [ + 'regex' => [ + 'pattern' => '^[0-9]+$', + 'message' => Lang::get('rainlab.builder::lang.form.property_fileupload_invalid_dimension') + ] + ], + 'sortOrder' => 83 + ], + 'maxItems' => $this->getFieldMaxItemsProperties()['maxItems'], + 'thumbOptions' => $this->getFieldThumbOptionsProperties()['thumbOptions'], + ]; + + $this->controlLibrary->registerControl( + 'mediafinder', + 'rainlab.builder::lang.form.control_mediafinder', + 'rainlab.builder::lang.form.control_mediafinder_description', + ControlLibrary::GROUP_WIDGETS, + 'icon-picture-o', + $this->controlLibrary->getStandardProperties($excludeProperties, $properties), + null + ); + } + + /** + * registerNestedFormWidget + */ + protected function registerNestedFormWidget() + { + $properties = [ + 'form' => [ + 'type' => 'control-container' + ], + 'showPanel' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_nestedform_show_panel'), + 'description' => Lang::get('rainlab.builder::lang.form.property_nestedform_show_panel_description'), + 'type' => 'checkbox', + 'ignoreIfEmpty' => true, + 'sortOrder' => 87, + ], + 'defaultCreate' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_nestedform_default_create'), + 'description' => Lang::get('rainlab.builder::lang.form.property_nestedform_default_create_description'), + 'type' => 'checkbox', + 'ignoreIfEmpty' => true, + 'sortOrder' => 88, + ], + ]; + + $excludeProperties = [ + 'stretch', + 'placeholder', + 'default', + 'required', + 'defaultFrom', + 'dependsOn', + 'preset', + 'attributes' + ]; + + $this->controlLibrary->registerControl( + 'nestedform', + 'rainlab.builder::lang.form.control_nestedform', + 'rainlab.builder::lang.form.control_nestedform_description', + ControlLibrary::GROUP_WIDGETS, + 'icon-object-group', + $this->controlLibrary->getStandardProperties($excludeProperties, $properties), + null + ); + } + + /** + * registerRecordFinderWidget + */ + protected function registerRecordFinderWidget() + { + $excludeProperties = [ + 'stretch', + 'default', + 'placeholder', + 'defaultFrom', + 'dependsOn', + 'preset', + 'attributes', + 'disabled' + ]; + + $properties = [ + 'nameFrom' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_name_from'), + 'description' => Lang::get('rainlab.builder::lang.form.property_name_from_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_recordfinder'), + 'type' => 'string', + 'default' => 'name', + 'sortOrder' => 81 + ], + 'descriptionFrom' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_description_from'), + 'description' => Lang::get('rainlab.builder::lang.form.property_description_from_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_recordfinder'), + 'type' => 'string', + 'default' => 'description', + 'sortOrder' => 82 + ], + 'title' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_recordfinder_title'), + 'description' => Lang::get('rainlab.builder::lang.form.property_recordfinder_title_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_recordfinder'), + 'type' => 'builderLocalization', + 'ignoreIfEmpty' => true, + 'sortOrder' => 83 + ], + 'list' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_recordfinder_list'), + 'description' => Lang::get('rainlab.builder::lang.form.property_recordfinder_list_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_recordfinder'), + 'type' => 'autocomplete', + 'fillFrom' => 'plugin-lists', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.form.property_recordfinder_list_required'), + ] + ], + 'sortOrder' => 83 + ], + 'scope' => $this->getFieldConditionsProperties()['scope'], + ]; + + $this->controlLibrary->registerControl( + 'recordfinder', + 'rainlab.builder::lang.form.control_recordfinder', + 'rainlab.builder::lang.form.control_recordfinder_description', + ControlLibrary::GROUP_WIDGETS, + 'icon-search', + $this->controlLibrary->getStandardProperties($excludeProperties, $properties), + null + ); + } + + /** + * registerRelationWidget + */ + protected function registerRelationWidget() + { + $excludeProperties = [ + 'stretch', + 'default', + 'placeholder', + 'defaultFrom', + 'dependsOn', + 'preset', + 'attributes', + 'trigger', + 'disabled' + ]; + + $properties = [ + 'nameFrom' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_name_from'), + 'description' => Lang::get('rainlab.builder::lang.form.property_name_from_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_relation'), + 'type' => 'string', + 'default' => 'name', + 'sortOrder' => 81 + ], + 'descriptionFrom' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_description_from'), + 'description' => Lang::get('rainlab.builder::lang.form.property_description_from_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_relation'), + 'type' => 'string', + 'default' => 'description', + 'ignoreIfEmpty' => true, + 'sortOrder' => 82 + ], + 'emptyOption' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_relation_prompt'), + 'description' => Lang::get('rainlab.builder::lang.form.property_relation_prompt_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_relation'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 83 + ], + 'select' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_relation_select'), + 'description' => Lang::get('rainlab.builder::lang.form.property_relation_select_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_relation'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 84 + ], + 'scope' => $this->getFieldConditionsProperties()['scope'], + ]; + + $this->controlLibrary->registerControl( + 'relation', + 'rainlab.builder::lang.form.control_relation', + 'rainlab.builder::lang.form.control_relation_description', + ControlLibrary::GROUP_WIDGETS, + 'icon-code-fork', + $this->controlLibrary->getStandardProperties($excludeProperties, $properties), + null + ); + } + + /** + * registerRepeaterWidget + */ + protected function registerRepeaterWidget() + { + $properties = [ + 'prompt' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_prompt'), + 'description' => Lang::get('rainlab.builder::lang.form.property_prompt_description'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'default' => Lang::get('rainlab.builder::lang.form.property_prompt_default'), + 'sortOrder' => 81 + ], + 'titleFrom' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_title_from'), + 'description' => Lang::get('rainlab.builder::lang.form.property_title_from_description'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 82 + ], + 'form' => [ + 'type' => 'control-container' + ], + 'minItems' => $this->getFieldMaxItemsProperties()['minItems'], + 'maxItems' => $this->getFieldMaxItemsProperties()['maxItems'], + 'displayMode' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_display_mode'), + 'description' => Lang::get('rainlab.builder::lang.form.property_display_mode_description'), + 'type' => 'dropdown', + 'default' => 'accordion', + 'options' => [ + 'builder' => Lang::get('rainlab.builder::lang.form.display_mode_builder'), + 'accordion' => Lang::get('rainlab.builder::lang.form.display_mode_accordion'), + ], + 'sortOrder' => 85, + ], + // @todo this needs work, the control container doesn't support tabs + // 'useTabs' => [ + // 'title' => "Use Tabs", + // 'description' => "Shows tabs when enabled, allowing fields to specify a tab property.", + // 'type' => 'checkbox', + // 'ignoreIfEmpty' => true, + // 'sortOrder' => 86, + // ], + 'showReorder' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_repeater_show_reorder'), + 'description' => Lang::get('rainlab.builder::lang.form.property_repeater_show_reorder_description'), + 'type' => 'checkbox', + 'ignoreIfEmpty' => true, + 'sortOrder' => 87, + ], + 'showDuplicate' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_repeater_show_duplicate'), + 'description' => Lang::get('rainlab.builder::lang.form.property_repeater_show_duplicate_description'), + 'type' => 'checkbox', + 'ignoreIfEmpty' => true, + 'sortOrder' => 88, + ], + ]; + + $excludeProperties = [ + 'stretch', + 'placeholder', + 'default', + 'required', + 'defaultFrom', + 'dependsOn', + 'preset', + 'attributes' + ]; + + $this->controlLibrary->registerControl( + 'repeater', + 'rainlab.builder::lang.form.control_repeater', + 'rainlab.builder::lang.form.control_repeater_description', + ControlLibrary::GROUP_WIDGETS, + 'icon-server', + $this->controlLibrary->getStandardProperties($excludeProperties, $properties), + null + ); + } + + /** + * registerRichEditorWidget + */ + protected function registerRichEditorWidget() + { + $properties = $this->getFieldSizeProperties() + [ + 'toolbarButtons' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_richeditor_toolbar_buttons'), + 'description' => Lang::get('rainlab.builder::lang.form.property_richeditor_toolbar_buttons_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_rich_editor'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 81 + ], + ]; + + $this->controlLibrary->registerControl( + 'richeditor', + 'rainlab.builder::lang.form.control_richeditor', + 'rainlab.builder::lang.form.control_richeditor_description', + ControlLibrary::GROUP_WIDGETS, + 'icon-indent', + $this->controlLibrary->getStandardProperties([], $properties), + null + ); + } + + /** + * registerPageFinderWidget + */ + protected function registerPageFinderWidget() + { + $properties = [ + 'singleMode' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_pagefinder_single_mode'), + 'description' => Lang::get('rainlab.builder::lang.form.property_pagefinder_single_mode_description'), + 'type' => 'checkbox', + 'sortOrder' => 81 + ] + ]; + + $this->controlLibrary->registerControl( + 'pagefinder', + 'rainlab.builder::lang.form.control_pagefinder', + 'rainlab.builder::lang.form.control_pagefinder_description', + ControlLibrary::GROUP_WIDGETS, + 'icon-paperclip', + $this->controlLibrary->getStandardProperties(['stretch'], $properties), + null + ); + } + + /** + * registerSensitiveWidget + */ + protected function registerSensitiveWidget() + { + $properties = [ + 'mode' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_display_mode'), + 'description' => Lang::get('rainlab.builder::lang.form.property_display_mode_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_sensitive'), + 'type' => 'dropdown', + 'options' => [ + 'text' => "Text", + 'textarea' => "Textarea", + ], + 'ignoreIfDefault' => true, + 'default' => 'text', + 'sortOrder' => 83 + ], + 'allowCopy' => [ + 'title' => Lang::get('rainlab.builder::lang.form.allow_copy'), + 'description' => Lang::get('rainlab.builder::lang.form.allow_copy_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_sensitive'), + 'type' => 'checkbox', + 'ignoreIfDefault' => true, + 'sortOrder' => 84, + 'default' => true + ], + 'hiddenPlaceholder' => [ + 'title' => Lang::get('rainlab.builder::lang.form.hidden_placeholder'), + 'description' => Lang::get('rainlab.builder::lang.form.hidden_placeholder_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_sensitive'), + 'type' => 'string', + 'default' => '__hidden__', + 'ignoreIfDefault' => true, + 'sortOrder' => 85 + ], + 'hideOnTabChange' => [ + 'title' => Lang::get('rainlab.builder::lang.form.hide_on_tab_change'), + 'description' => Lang::get('rainlab.builder::lang.form.hide_on_tab_change_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_sensitive'), + 'type' => 'checkbox', + 'ignoreIfDefault' => true, + 'sortOrder' => 86, + 'default' => true + ], + ]; + + $this->controlLibrary->registerControl( + 'sensitive', + 'rainlab.builder::lang.form.control_sensitive', + 'rainlab.builder::lang.form.control_sensitive_description', + ControlLibrary::GROUP_WIDGETS, + 'icon-eye-slash', + $this->controlLibrary->getStandardProperties(['stretch'], $properties), + null + ); + } + + /** + * registerTagListWidget + */ + protected function registerTagListWidget() + { + $excludeProperties = [ + 'stretch', + 'readOnly' + ]; + + $properties = [ + 'mode' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_taglist_mode'), + 'description' => Lang::get('rainlab.builder::lang.form.property_taglist_mode_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_taglist'), + 'type' => 'dropdown', + 'options' => [ + 'string' => Lang::get('rainlab.builder::lang.form.property_taglist_mode_string'), + 'array' => Lang::get('rainlab.builder::lang.form.property_taglist_mode_array'), + 'relation' => Lang::get('rainlab.builder::lang.form.property_taglist_mode_relation') + ], + 'default' => 'string', + 'sortOrder' => 83 + ], + 'separator' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_taglist_separator'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_taglist'), + 'type' => 'dropdown', + 'options' => [ + 'comma' => Lang::get('rainlab.builder::lang.form.property_taglist_separator_comma'), + 'space' => Lang::get('rainlab.builder::lang.form.property_taglist_separator_space') + ], + 'default' => 'comma', + 'sortOrder' => 84 + ], + 'customTags' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_taglist_custom_tags'), + 'description' => Lang::get('rainlab.builder::lang.form.property_taglist_custom_tags_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_taglist'), + 'type' => 'checkbox', + 'default' => true, + 'sortOrder' => 86 + ], + 'options' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_taglist_options'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_taglist'), + 'type' => 'stringList', + 'ignoreIfEmpty' => true, + 'sortOrder' => 85 + ], + 'optionsMethod' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_options_method'), + 'description' => Lang::get('rainlab.builder::lang.form.property_options_method_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_taglist'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 86 + ], + 'nameFrom' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_taglist_name_from'), + 'description' => Lang::get('rainlab.builder::lang.form.property_taglist_name_from_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_taglist'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 87 + ], + 'useKey' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_taglist_use_key'), + 'description' => Lang::get('rainlab.builder::lang.form.property_taglist_use_key_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_taglist'), + 'type' => 'checkbox', + 'default' => false, + 'ignoreIfEmpty' => true, + 'sortOrder' => 88 + ] + ]; + + $this->controlLibrary->registerControl( + 'taglist', + 'rainlab.builder::lang.form.control_taglist', + 'rainlab.builder::lang.form.control_taglist_description', + ControlLibrary::GROUP_WIDGETS, + 'icon-tags', + $this->controlLibrary->getStandardProperties($excludeProperties, $properties), + null + ); + } + + /** + * getFieldThumbOptionsProperties + */ + protected function getFieldThumbOptionsProperties(): array + { + return [ + 'thumbOptions' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_fileupload_thumb_options'), + 'description' => Lang::get('rainlab.builder::lang.form.property_fileupload_thumb_options_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_fileupload'), + 'type' => 'object', + 'properties' => [ + [ + 'property' => 'mode', + 'title' => Lang::get('rainlab.builder::lang.form.property_fileupload_thumb_mode'), + 'type' => 'dropdown', + 'default' => 'crop', + 'options' => [ + 'auto' => Lang::get('rainlab.builder::lang.form.property_fileupload_thumb_auto'), + 'exact' => Lang::get('rainlab.builder::lang.form.property_fileupload_thumb_exact'), + 'portrait' => Lang::get('rainlab.builder::lang.form.property_fileupload_thumb_portrait'), + 'landscape' => Lang::get('rainlab.builder::lang.form.property_fileupload_thumb_landscape'), + 'crop' => Lang::get('rainlab.builder::lang.form.property_fileupload_thumb_crop') + ] + ], + [ + 'property' => 'extension', + 'title' => Lang::get('rainlab.builder::lang.form.property_fileupload_thumb_extension'), + 'type' => 'dropdown', + 'default' => 'auto', + 'options' => [ + 'auto' => Lang::get('rainlab.builder::lang.form.property_fileupload_thumb_auto'), + 'jpg' => 'jpg', + 'gif' => 'gif', + 'png' => 'png' + ] + ] + ], + 'sortOrder' => 88 + ] + ]; + } + + /** + * getFieldMaxItemsProperties + */ + protected function getFieldMaxItemsProperties(): array + { + return [ + 'minItems' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_min_items'), + 'description' => Lang::get('rainlab.builder::lang.form.property_min_items_description'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 83, + 'validation' => [ + 'integer' => [ + 'message' => Lang::get('rainlab.builder::lang.form.property_min_items_integer'), + 'allowNegative' => false, + ] + ], + ], + 'maxItems' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_max_items'), + 'description' => Lang::get('rainlab.builder::lang.form.property_max_items_description'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 84, + 'validation' => [ + 'integer' => [ + 'message' => Lang::get('rainlab.builder::lang.form.property_max_items_integer'), + 'allowNegative' => false, + ] + ], + ], + ]; + } + + /** + * getFieldConditionsProperties + */ + protected function getFieldConditionsProperties(): array + { + return [ + 'scope' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_relation_scope'), + 'description' => Lang::get('rainlab.builder::lang.form.property_relation_scope_description'), + 'group' => Lang::get('rainlab.builder::lang.form.property_group_relation'), + 'type' => 'string', + 'ignoreIfEmpty' => true, + 'sortOrder' => 85 + ] + ]; + } + + /** + * getFieldSizeProperties + */ + protected function getFieldSizeProperties(): array + { + return [ + 'size' => [ + 'title' => Lang::get('rainlab.builder::lang.form.property_attributes_size'), + 'type' => 'dropdown', + 'options' => [ + 'tiny' => Lang::get('rainlab.builder::lang.form.property_attributes_size_tiny'), + 'small' => Lang::get('rainlab.builder::lang.form.property_attributes_size_small'), + 'large' => Lang::get('rainlab.builder::lang.form.property_attributes_size_large'), + 'huge' => Lang::get('rainlab.builder::lang.form.property_attributes_size_huge'), + 'giant' => Lang::get('rainlab.builder::lang.form.property_attributes_size_giant') + ], + 'sortOrder' => 51 + ] + ]; + } +} diff --git a/plugins/rainlab/builder/components/RecordDetails.php b/plugins/rainlab/builder/components/RecordDetails.php new file mode 100644 index 0000000..c2ddb68 --- /dev/null +++ b/plugins/rainlab/builder/components/RecordDetails.php @@ -0,0 +1,161 @@ + 'rainlab.builder::lang.components.details_title', + 'description' => 'rainlab.builder::lang.components.details_description' + ]; + } + + // + // Properties + // + + public function defineProperties() + { + return [ + 'modelClass' => [ + 'title' => 'rainlab.builder::lang.components.details_model', + 'type' => 'dropdown', + 'showExternalParam' => false + ], + 'identifierValue' => [ + 'title' => 'rainlab.builder::lang.components.details_identifier_value', + 'description' => 'rainlab.builder::lang.components.details_identifier_value_description', + 'type' => 'string', + 'default' => '{{ :id }}', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.components.details_identifier_value_required') + ] + ] + ], + 'modelKeyColumn' => [ + 'title' => 'rainlab.builder::lang.components.details_key_column', + 'description' => 'rainlab.builder::lang.components.details_key_column_description', + 'type' => 'autocomplete', + 'default' => 'id', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.components.details_key_column_required') + ] + ], + 'showExternalParam' => false + ], + 'displayColumn' => [ + 'title' => 'rainlab.builder::lang.components.details_display_column', + 'description' => 'rainlab.builder::lang.components.details_display_column_description', + 'type' => 'autocomplete', + 'depends' => ['modelClass'], + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.components.details_display_column_required') + ] + ], + 'showExternalParam' => false + ], + 'notFoundMessage' => [ + 'title' => 'rainlab.builder::lang.components.details_not_found_message', + 'description' => 'rainlab.builder::lang.components.details_not_found_message_description', + 'default' => Lang::get('rainlab.builder::lang.components.details_not_found_message_default'), + 'type' => 'string', + 'showExternalParam' => false + ] + ]; + } + + public function getModelClassOptions() + { + return ComponentHelper::instance()->listGlobalModels(); + } + + public function getDisplayColumnOptions() + { + return ComponentHelper::instance()->listModelColumnNames(); + } + + public function getModelKeyColumnOptions() + { + return ComponentHelper::instance()->listModelColumnNames(); + } + + // + // Rendering and processing + // + + public function onRun() + { + $this->prepareVars(); + + $this->record = $this->page['record'] = $this->loadRecord(); + } + + protected function prepareVars() + { + $this->notFoundMessage = $this->page['notFoundMessage'] = Lang::get($this->property('notFoundMessage')); + $this->displayColumn = $this->page['displayColumn'] = $this->property('displayColumn'); + $this->modelKeyColumn = $this->page['modelKeyColumn'] = $this->property('modelKeyColumn'); + $this->identifierValue = $this->page['identifierValue'] = $this->property('identifierValue'); + + if (!strlen($this->displayColumn)) { + throw new SystemException('The display column name is not set.'); + } + + if (!strlen($this->modelKeyColumn)) { + throw new SystemException('The model key column name is not set.'); + } + } + + protected function loadRecord() + { + if (!strlen($this->identifierValue)) { + return; + } + + $modelClassName = $this->property('modelClass'); + if (!strlen($modelClassName) || !class_exists($modelClassName)) { + throw new SystemException('Invalid model class name'); + } + + $model = new $modelClassName(); + return $model->where($this->modelKeyColumn, '=', $this->identifierValue)->first(); + } +} diff --git a/plugins/rainlab/builder/components/RecordList.php b/plugins/rainlab/builder/components/RecordList.php new file mode 100644 index 0000000..e57c0a3 --- /dev/null +++ b/plugins/rainlab/builder/components/RecordList.php @@ -0,0 +1,343 @@ + 'rainlab.builder::lang.components.list_title', + 'description' => 'rainlab.builder::lang.components.list_description' + ]; + } + + // + // Properties + // + + public function defineProperties() + { + return [ + 'modelClass' => [ + 'title' => 'rainlab.builder::lang.components.list_model', + 'type' => 'dropdown', + 'showExternalParam' => false + ], + 'scope' => [ + 'title' => 'rainlab.builder::lang.components.list_scope', + 'description' => 'rainlab.builder::lang.components.list_scope_description', + 'type' => 'dropdown', + 'depends' => ['modelClass'], + 'showExternalParam' => false + ], + 'scopeValue' => [ + 'title' => 'rainlab.builder::lang.components.list_scope_value', + 'description' => 'rainlab.builder::lang.components.list_scope_value_description', + 'type' => 'string', + 'default' => '{{ :scope }}', + ], + 'displayColumn' => [ + 'title' => 'rainlab.builder::lang.components.list_display_column', + 'description' => 'rainlab.builder::lang.components.list_display_column_description', + 'type' => 'autocomplete', + 'depends' => ['modelClass'], + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.components.list_display_column_required') + ] + ] + ], + 'noRecordsMessage' => [ + 'title' => 'rainlab.builder::lang.components.list_no_records', + 'description' => 'rainlab.builder::lang.components.list_no_records_description', + 'type' => 'string', + 'default' => Lang::get('rainlab.builder::lang.components.list_no_records_default'), + 'showExternalParam' => false, + ], + 'detailsPage' => [ + 'title' => 'rainlab.builder::lang.components.list_details_page', + 'description' => 'rainlab.builder::lang.components.list_details_page_description', + 'type' => 'dropdown', + 'showExternalParam' => false, + 'group' => 'rainlab.builder::lang.components.list_details_page_link' + ], + 'detailsKeyColumn' => [ + 'title' => 'rainlab.builder::lang.components.list_details_key_column', + 'description' => 'rainlab.builder::lang.components.list_details_key_column_description', + 'type' => 'autocomplete', + 'depends' => ['modelClass'], + 'showExternalParam' => false, + 'group' => 'rainlab.builder::lang.components.list_details_page_link' + ], + 'detailsUrlParameter' => [ + 'title' => 'rainlab.builder::lang.components.list_details_url_parameter', + 'description' => 'rainlab.builder::lang.components.list_details_url_parameter_description', + 'type' => 'string', + 'default' => 'id', + 'showExternalParam' => false, + 'group' => 'rainlab.builder::lang.components.list_details_page_link' + ], + 'recordsPerPage' => [ + 'title' => 'rainlab.builder::lang.components.list_records_per_page', + 'description' => 'rainlab.builder::lang.components.list_records_per_page_description', + 'type' => 'string', + 'validationPattern' => '^[0-9]*$', + 'validationMessage' => 'rainlab.builder::lang.components.list_records_per_page_validation', + 'group' => 'rainlab.builder::lang.components.list_pagination' + ], + 'pageNumber' => [ + 'title' => 'rainlab.builder::lang.components.list_page_number', + 'description' => 'rainlab.builder::lang.components.list_page_number_description', + 'type' => 'string', + 'default' => '{{ :page }}', + 'group' => 'rainlab.builder::lang.components.list_pagination' + ], + 'sortColumn' => [ + 'title' => 'rainlab.builder::lang.components.list_sort_column', + 'description' => 'rainlab.builder::lang.components.list_sort_column_description', + 'type' => 'autocomplete', + 'depends' => ['modelClass'], + 'group' => 'rainlab.builder::lang.components.list_sorting', + 'showExternalParam' => false + ], + 'sortDirection' => [ + 'title' => 'rainlab.builder::lang.components.list_sort_direction', + 'type' => 'dropdown', + 'showExternalParam' => false, + 'group' => 'rainlab.builder::lang.components.list_sorting', + 'options' => [ + 'asc' => 'rainlab.builder::lang.components.list_order_direction_asc', + 'desc' => 'rainlab.builder::lang.components.list_order_direction_desc' + ] + ] + ]; + } + + public function getDetailsPageOptions() + { + $pages = Page::sortBy('baseFileName')->lists('baseFileName', 'baseFileName'); + + $pages = [ + '-' => Lang::get('rainlab.builder::lang.components.list_details_page_no') + ] + $pages; + + return $pages; + } + + public function getModelClassOptions() + { + return ComponentHelper::instance()->listGlobalModels(); + } + + public function getDisplayColumnOptions() + { + return ComponentHelper::instance()->listModelColumnNames(); + } + + public function getDetailsKeyColumnOptions() + { + return ComponentHelper::instance()->listModelColumnNames(); + } + + public function getSortColumnOptions() + { + return ComponentHelper::instance()->listModelColumnNames(); + } + + public function getScopeOptions() + { + $modelClass = ComponentHelper::instance()->getModelClassDesignTime(); + + $result = [ + '-' => Lang::get('rainlab.builder::lang.components.list_scope_default') + ]; + try { + $model = new $modelClass; + $methods = $model->getClassMethods(); + + foreach ($methods as $method) { + if (preg_match('/scope[A-Z].*/', $method)) { + $result[$method] = $method; + } + } + } + catch (Exception $ex) { + // Ignore invalid models + } + + return $result; + } + + // + // Rendering and processing + // + + public function onRun() + { + $this->prepareVars(); + + $this->records = $this->page['records'] = $this->listRecords(); + } + + protected function prepareVars() + { + $this->noRecordsMessage = $this->page['noRecordsMessage'] = Lang::get($this->property('noRecordsMessage')); + $this->displayColumn = $this->page['displayColumn'] = $this->property('displayColumn'); + $this->pageParam = $this->page['pageParam'] = $this->paramName('pageNumber'); + + $this->detailsKeyColumn = $this->page['detailsKeyColumn'] = $this->property('detailsKeyColumn'); + $this->detailsUrlParameter = $this->page['detailsUrlParameter'] = $this->property('detailsUrlParameter'); + + $detailsPage = $this->property('detailsPage'); + if ($detailsPage == '-') { + $detailsPage = null; + } + + $this->detailsPage = $this->page['detailsPage'] = $detailsPage; + + if (!strlen($this->displayColumn)) { + throw new SystemException('The display column name is not set.'); + } + + if (strlen($this->detailsPage)) { + if (!strlen($this->detailsKeyColumn)) { + throw new SystemException('The details key column should be set to generate links to the details page.'); + } + + if (!strlen($this->detailsUrlParameter)) { + throw new SystemException('The details page URL parameter name should be set to generate links to the details page.'); + } + } + } + + protected function listRecords() + { + $modelClassName = $this->property('modelClass'); + if (!strlen($modelClassName) || !class_exists($modelClassName)) { + throw new SystemException('Invalid model class name'); + } + + $model = new $modelClassName(); + $scope = $this->getScopeName($model); + $scopeValue = $this->property('scopeValue'); + + if ($scope !== null) { + $model = $model->$scope($scopeValue); + } + + $model = $this->sort($model); + $records = $this->paginate($model); + + return $records; + } + + protected function getScopeName($model) + { + $scopeMethod = trim($this->property('scope')); + if (!strlen($scopeMethod) || $scopeMethod == '-') { + return null; + } + + if (!preg_match('/scope[A-Z].+/', $scopeMethod)) { + throw new SystemException('Invalid scope method name.'); + } + + if (!$model->methodExists($scopeMethod)) { + throw new SystemException('Scope method not found.'); + } + + return lcfirst(substr($scopeMethod, 5)); + } + + protected function paginate($model) + { + $recordsPerPage = trim($this->property('recordsPerPage')); + if (!strlen($recordsPerPage)) { + // Pagination is disabled - return all records + return $model->get(); + } + + if (!preg_match('/^[0-9]+$/', $recordsPerPage)) { + throw new SystemException('Invalid records per page value.'); + } + + $pageNumber = trim($this->property('pageNumber')); + if (!strlen($pageNumber) || !preg_match('/^[0-9]+$/', $pageNumber)) { + $pageNumber = 1; + } + + return $model->paginate($recordsPerPage, $pageNumber); + } + + protected function sort($model) + { + $sortColumn = trim($this->property('sortColumn')); + if (!strlen($sortColumn)) { + return $model; + } + + $sortDirection = trim($this->property('sortDirection')); + + if ($sortDirection !== 'desc') { + $sortDirection = 'asc'; + } + + // Note - no further validation of the sort column + // value is performed here, relying to the ORM sanitizing. + return $model->orderBy($sortColumn, $sortDirection); + } +} diff --git a/plugins/rainlab/builder/components/recorddetails/default.htm b/plugins/rainlab/builder/components/recorddetails/default.htm new file mode 100644 index 0000000..3d56a45 --- /dev/null +++ b/plugins/rainlab/builder/components/recorddetails/default.htm @@ -0,0 +1,9 @@ +{% set record = __SELF__.record %} +{% set displayColumn = __SELF__.displayColumn %} +{% set notFoundMessage = __SELF__.notFoundMessage %} + +{% if record %} + {{ attribute(record, displayColumn) }} +{% else %} + {{ notFoundMessage }} +{% endif %} \ No newline at end of file diff --git a/plugins/rainlab/builder/components/recordlist/default.htm b/plugins/rainlab/builder/components/recordlist/default.htm new file mode 100644 index 0000000..4e01590 --- /dev/null +++ b/plugins/rainlab/builder/components/recordlist/default.htm @@ -0,0 +1,36 @@ +{% set records = __SELF__.records %} +{% set displayColumn = __SELF__.displayColumn %} +{% set noRecordsMessage = __SELF__.noRecordsMessage %} +{% set detailsPage = __SELF__.detailsPage %} +{% set detailsKeyColumn = __SELF__.detailsKeyColumn %} +{% set detailsUrlParameter = __SELF__.detailsUrlParameter %} + + + +{% if records.lastPage > 1 %} +
      + {% if records.currentPage > 1 %} +
    • ← Prev
    • + {% endif %} + + {% for page in 1..records.lastPage %} +
    • + {{ page }} +
    • + {% endfor %} + + {% if records.lastPage > records.currentPage %} +
    • Next →
    • + {% endif %} +
    +{% endif %} \ No newline at end of file diff --git a/plugins/rainlab/builder/composer.json b/plugins/rainlab/builder/composer.json new file mode 100644 index 0000000..5a39a0b --- /dev/null +++ b/plugins/rainlab/builder/composer.json @@ -0,0 +1,29 @@ +{ + "name": "rainlab/builder-plugin", + "type": "october-plugin", + "description": "Builder plugin for October CMS", + "homepage": "https://octobercms.com/plugin/rainlab-builder", + "keywords": ["october", "octobercms", "builder"], + "license": "MIT", + "authors": [ + { + "name": "Alexey Bobkov", + "email": "aleksey.bobkov@gmail.com", + "role": "Co-founder" + }, + { + "name": "Samuel Georges", + "email": "daftspunky@gmail.com", + "role": "Co-founder" + } + ], + "require": { + "php": "^8.0.2", + "october/rain": ">=3.0", + "composer/installers": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "minimum-stability": "dev" +} diff --git a/plugins/rainlab/builder/controllers/Index.php b/plugins/rainlab/builder/controllers/Index.php new file mode 100644 index 0000000..c7b5e51 --- /dev/null +++ b/plugins/rainlab/builder/controllers/Index.php @@ -0,0 +1,153 @@ +bodyClass = 'compact-container sidenav-responsive'; + $this->pageTitle = "Builder"; + } + + /** + * beforeDisplay + */ + public function beforeDisplay() + { + new PluginList($this, 'pluginList'); + new DatabaseTableList($this, 'databaseTableList'); + new ModelList($this, 'modelList'); + new VersionList($this, 'versionList'); + new LanguageList($this, 'languageList'); + new ControllerList($this, 'controllerList'); + new CodeList($this, 'codeList'); + + $this->bindFormWidgetToController(); + } + + /** + * bindFormWidgetToController + */ + protected function bindFormWidgetToController() + { + if (!Request::ajax() || !post('operationClass') || !post('formWidgetAlias')) { + return; + } + + $extension = $this->asExtension(post('operationClass')); + if (!$extension) { + return; + } + + $extension->bindFormWidgetToController(post('formWidgetAlias')); + } + + /** + * index + */ + public function index() + { + $this->addCss('/plugins/rainlab/builder/assets/css/builder.css', 'RainLab.Builder'); + + // The table widget scripts should be preloaded + $this->addJs('/modules/backend/widgets/table/assets/js/build-min.js', 'core'); + $this->addJs('/plugins/rainlab/builder/assets/js/build-min.js', 'RainLab.Builder'); + + $this->pageTitleTemplate = '%s Builder'; + } + + /** + * setBuilderActivePlugin + */ + public function setBuilderActivePlugin($pluginCode, $refreshPluginList = false) + { + $this->widget->pluginList->setActivePlugin($pluginCode); + + $result = []; + if ($refreshPluginList) { + $result = $this->widget->pluginList->updateList(); + } + + $result = array_merge( + $result, + $this->widget->databaseTableList->refreshActivePlugin(), + $this->widget->modelList->refreshActivePlugin(), + $this->widget->versionList->refreshActivePlugin(), + $this->widget->languageList->refreshActivePlugin(), + $this->widget->controllerList->refreshActivePlugin(), + $this->widget->codeList->refreshActivePlugin() + ); + + return $result; + } + + /** + * getBuilderActivePluginVector + */ + public function getBuilderActivePluginVector() + { + return $this->widget->pluginList->getActivePluginVector(); + } + + /** + * updatePluginList + */ + public function updatePluginList() + { + return $this->widget->pluginList->updateList(); + } +} diff --git a/plugins/rainlab/builder/controllers/index/_plugin-selector.php b/plugins/rainlab/builder/controllers/index/_plugin-selector.php new file mode 100644 index 0000000..a3fdda0 --- /dev/null +++ b/plugins/rainlab/builder/controllers/index/_plugin-selector.php @@ -0,0 +1,9 @@ +
    +
    +
    +
    + widget->pluginList->render() ?> +
    +
    +
    +
    diff --git a/plugins/rainlab/builder/controllers/index/_sidepanel.php b/plugins/rainlab/builder/controllers/index/_sidepanel.php new file mode 100644 index 0000000..8cacf37 --- /dev/null +++ b/plugins/rainlab/builder/controllers/index/_sidepanel.php @@ -0,0 +1,65 @@ +
    +
    +
    + +
    + widget->databaseTableList->render() ?> +
    + + +
    + widget->modelList->render() ?> +
    + + +
    + widget->controllerList->render() ?> +
    + + +
    + widget->versionList->render() ?> +
    + + +
    + widget->languageList->render() ?> +
    + + +
    + widget->codeList->render() ?> +
    +
    +
    +
    diff --git a/plugins/rainlab/builder/controllers/index/index.php b/plugins/rainlab/builder/controllers/index/index.php new file mode 100644 index 0000000..f1e3bd7 --- /dev/null +++ b/plugins/rainlab/builder/controllers/index/index.php @@ -0,0 +1,38 @@ + + + + fatalError): ?> + makePartial('sidepanel') ?> + + + + + makePartial('plugin-selector') ?> + + + + fatalError): ?> +
    + +
    +
    + +
    +
    +
    +
    + +
    + + +

    fatalError)) ?>

    + + \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/BlueprintBuilder.php b/plugins/rainlab/builder/formwidgets/BlueprintBuilder.php new file mode 100644 index 0000000..2850e4c --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/BlueprintBuilder.php @@ -0,0 +1,320 @@ +getSelectFormWidget(); + } + } + + /** + * {@inheritDoc} + */ + public function render() + { + $this->prepareVars(); + return $this->makePartial('body'); + } + + /** + * Prepares the list data + */ + public function prepareVars() + { + $this->vars['model'] = $this->model; + $this->vars['items'] = $this->model->blueprints; + $this->vars['selectWidget'] = $this->getSelectFormWidget(); + $this->vars['pluginCode'] = $this->getPluginCode(); + + $this->vars['emptyItem'] = [ + 'label' => __("Add Blueprint"), + 'icon' => 'icon-life-ring', + 'code' => 'newitemcode', + 'url' => '/' + ]; + } + + /** + * onRefreshBlueprintContainer + */ + public function onRefreshBlueprintContainer() + { + $uuid = post('blueprint_uuid'); + $blueprintInfo = $this->getBlueprintInfo($uuid); + $blueprintConfig = (array) post('properties'); + + return [ + 'markup' => $this->renderBlueprintBody($blueprintInfo, $blueprintConfig), + 'blueprintUuid' => $uuid + ]; + } + + /** + * onShowSelectBlueprintForm + */ + public function onShowSelectBlueprintForm() + { + $this->prepareVars(); + + $selectedBlueprints = (array) post('blueprints') ?: []; + if ($selectedBlueprints) { + $model = $this->getSelectFormWidget()->getModel(); + $model->blueprints = $selectedBlueprints; + } + + return $this->makePartial('select_blueprint_form'); + } + + /** + * onSelectBlueprint + */ + public function onSelectBlueprint() + { + $widget = $this->getSelectFormWidget(); + $data = $widget->getSaveData(); + $uuids = (array) ($data['blueprint_uuid'] ?? []); + if (!$uuids) { + throw new ApplicationException(__("There are no blueprints to import, please select a blueprint and try again.")); + } + + $result = []; + $availableUuids = $this->getSelectFormWidget()->getModel()->getBlueprintUuidOptions(); + foreach ($uuids as $uuid) { + $blueprintInfo = $this->getBlueprintInfo($uuid); + $blueprintConfig = $this->generateBlueprintConfiguration($blueprintInfo); + + $result[] = $this->makePartial('blueprint', [ + 'blueprintUuid' => $uuid, + 'blueprintConfig' => $blueprintConfig + ]); + + unset($availableUuids[$uuid]); + } + + $includeRelated = (bool) ($data['include_related'] ?? false); + if ($includeRelated) { + foreach ($uuids as $uuid) { + $this->appendRelatedBlueprintsToOutput($uuid, $result, $availableUuids); + } + } + + return ['@#blueprintList' => implode(PHP_EOL, $result)]; + } + + /** + * appendRelatedBlueprintsToOutput + */ + protected function appendRelatedBlueprintsToOutput($parentUuid, &$result, &$available) + { + $library = TailorBlueprintLibrary::instance(); + $relatedUuids = $library->getRelatedBlueprintUuids($parentUuid); + + foreach ($relatedUuids as $uuid) { + if (!isset($available[$uuid])) { + continue; + } + + $blueprintInfo = $this->getBlueprintInfo($uuid); + $blueprintConfig = $this->generateBlueprintConfiguration($blueprintInfo); + + $result[] = $this->makePartial('blueprint', [ + 'blueprintUuid' => $uuid, + 'blueprintConfig' => $blueprintConfig + ]); + + unset($available[$uuid]); + + // Recursion + $this->appendRelatedBlueprintsToOutput($uuid, $result, $available); + } + } + + /** + * {@inheritDoc} + */ + public function loadAssets() + { + $this->addJs('js/blueprintbuilder.js', 'builder'); + } + + /** + * getPluginCode + */ + public function getPluginCode() + { + $pluginCode = post('plugin_code'); + if (strlen($pluginCode)) { + return $pluginCode; + } + + $pluginVector = $this->controller->getBuilderActivePluginVector(); + + return $pluginVector->pluginCodeObj->toCode(); + } + + + /** + * getSelectFormWidget + */ + protected function getSelectFormWidget() + { + if ($this->selectFormWidget) { + return $this->selectFormWidget; + } + + $config = $this->makeConfig('~/plugins/rainlab/builder/models/importsmodel/fields_select.yaml'); + $config->model = $this->makeImportsModelInstance(); + $config->alias = $this->alias . 'Select'; + $config->arrayName = 'BlueprintBuilder'; + + $form = $this->makeWidget(\Backend\Widgets\Form::class, $config); + $form->bindToController(); + + return $this->selectFormWidget = $form; + } + + /** + * makeImportsModelInstance + */ + protected function makeImportsModelInstance() + { + $model = new ImportsModel; + $model->setPluginCode($this->getPluginCode()); + return $model; + } + + // + // Methods for the internal use + // + + /** + * getBlueprintDesignTimeProvider + */ + protected function getBlueprintDesignTimeProvider($providerClass) + { + if (array_key_exists($providerClass, $this->designTimeProviders)) { + return $this->designTimeProviders[$providerClass]; + } + + return $this->designTimeProviders[$providerClass] = new $providerClass($this->controller); + } + + /** + * getPropertyValue + */ + protected function getPropertyValue($properties, $property) + { + if (array_key_exists($property, $properties)) { + return $properties[$property]; + } + + return null; + } + + /** + * propertiesToInspectorSchema + */ + protected function propertiesToInspectorSchema($propertyConfiguration) + { + $result = []; + + foreach ($propertyConfiguration as $property => $propertyData) { + $propertyData['property'] = $property; + + $result[] = $propertyData; + } + + return $result; + } + + /** + * getBlueprintInfo + */ + protected function getBlueprintInfo($uuid) + { + if (array_key_exists($uuid, $this->blueprintInfoCache)) { + return $this->blueprintInfoCache[$uuid]; + } + + $library = TailorBlueprintLibrary::instance(); + $blueprintInfo = $library->getBlueprintInfo($uuid); + + if (!$blueprintInfo) { + throw new ApplicationException('The requested blueprint class information is not found.'); + } + + return $this->blueprintInfoCache[$uuid] = $blueprintInfo; + } + + /** + * renderBlueprintBody + */ + protected function renderBlueprintBody($blueprintInfo, $blueprintConfig) + { + $blueprintClass = $blueprintInfo['blueprintClass']; + + $blueprintObj = $blueprintInfo['blueprintObj']; + + $provider = $this->getBlueprintDesignTimeProvider($blueprintInfo['designTimeProvider']); + + // Inspect the generated output files + $importsModel = $this->makeImportsModelInstance(); + + $importsModel->fill(post()); + + $importsModel->blueprints[$blueprintObj->uuid] = $blueprintConfig; + + $inspectedOutput = $importsModel->inspect($blueprintObj); + + $blueprintConfig['inspectedOutput'] = $inspectedOutput; + + return $provider->renderBlueprintBody($blueprintClass, $blueprintConfig, $blueprintObj); + } + + /** + * generateBlueprintConfiguration + */ + protected function generateBlueprintConfiguration($blueprintInfo): array + { + $blueprintClass = $blueprintInfo['blueprintClass']; + + $blueprintObj = $blueprintInfo['blueprintObj']; + + $provider = $this->getBlueprintDesignTimeProvider($blueprintInfo['designTimeProvider']); + + $model = $this->makeImportsModelInstance(); + + return $provider->getDefaultConfiguration($blueprintClass, $blueprintObj, $model); + } +} diff --git a/plugins/rainlab/builder/formwidgets/ControllerBuilder.php b/plugins/rainlab/builder/formwidgets/ControllerBuilder.php new file mode 100644 index 0000000..9bd7b9c --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/ControllerBuilder.php @@ -0,0 +1,132 @@ +prepareVars(); + return $this->makePartial('body'); + } + + /** + * Prepares the list data + */ + public function prepareVars() + { + $this->vars['model'] = $this->model; + } + + /** + * {@inheritDoc} + */ + public function loadAssets() + { + $this->addJs('js/controllerbuilder.js', 'builder'); + } + + /* + * Event handlers + */ + + // + // Methods for the internal use + // + + /** + * getBehaviorDesignTimeProvider + */ + protected function getBehaviorDesignTimeProvider($providerClass) + { + if (array_key_exists($providerClass, $this->designTimeProviders)) { + return $this->designTimeProviders[$providerClass]; + } + + return $this->designTimeProviders[$providerClass] = new $providerClass($this->controller); + } + + /** + * getPropertyValue + */ + protected function getPropertyValue($properties, $property) + { + if (array_key_exists($property, $properties)) { + return $properties[$property]; + } + + return null; + } + + /** + * propertiesToInspectorSchema + */ + protected function propertiesToInspectorSchema($propertyConfiguration) + { + $result = []; + + foreach ($propertyConfiguration as $property => $propertyData) { + $propertyData['property'] = $property; + + $result[] = $propertyData; + } + + return $result; + } + + /** + * getBehaviorInfo + */ + protected function getBehaviorInfo($class) + { + if (array_key_exists($class, $this->behaviorInfoCache)) { + return $this->behaviorInfoCache[$class]; + } + + $library = ControllerBehaviorLibrary::instance(); + $behaviorInfo = $library->getBehaviorInfo($class); + + if (!$behaviorInfo) { + throw new ApplicationException('The requested behavior class information is not found.'); + } + + return $this->behaviorInfoCache[$class] = $behaviorInfo; + } + + /** + * renderBehaviorBody + */ + protected function renderBehaviorBody($behaviorClass, $behaviorInfo, $behaviorConfig) + { + $provider = $this->getBehaviorDesignTimeProvider($behaviorInfo['designTimeProvider']); + + return $provider->renderBehaviorBody($behaviorClass, $behaviorConfig, $this); + } +} diff --git a/plugins/rainlab/builder/formwidgets/FormBuilder.php b/plugins/rainlab/builder/formwidgets/FormBuilder.php new file mode 100644 index 0000000..d265b52 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/FormBuilder.php @@ -0,0 +1,488 @@ +prepareVars(); + return $this->makePartial('body'); + } + + /** + * Prepares the list data + */ + public function prepareVars() + { + $this->vars['model'] = $this->model; + } + + /** + * {@inheritDoc} + */ + public function loadAssets() + { + $this->addJs('js/formbuilder.js', 'builder'); + $this->addJs('js/formbuilder.domtopropertyjson.js', 'builder'); + $this->addJs('js/formbuilder.tabs.js', 'builder'); + $this->addJs('js/formbuilder.controlpalette.js', 'builder'); + } + + /** + * renderControlList + */ + public function renderControlList($controls, $listName = '') + { + return $this->makePartial('controllist', [ + 'controls' => $controls, + 'listName' => $listName + ]); + } + + /** + * onModelFormRenderControlWrapper + */ + public function onModelFormRenderControlWrapper() + { + $type = Input::get('controlType'); + $controlId = Input::get('controlId'); + $properties = Input::get('properties'); + + $controlInfo = $this->getControlInfo($type); + + return [ + 'markup' => $this->renderControlWrapper($type, $properties), + 'controlId' => $controlId, + 'controlTitle' => Lang::get($controlInfo['name']), + 'description' => Lang::get($controlInfo['description']), + 'type' => $type + ]; + } + + /** + * onModelFormRenderControlBody + */ + public function onModelFormRenderControlBody() + { + $type = Input::get('controlType'); + $controlId = Input::get('controlId'); + $properties = Input::get('properties'); + + return [ + 'markup' => $this->renderControlBody($type, $properties, $this), + 'controlId' => $controlId + ]; + } + + /** + * onModelFormLoadControlPalette + */ + public function onModelFormLoadControlPalette() + { + $controlId = Input::get('controlId'); + + $library = ControlLibrary::instance(); + $controls = $library->listControls(); + $this->vars['registeredControls'] = $controls; + $this->vars['controlGroups'] = array_keys($controls); + + return [ + 'markup' => $this->makePartial('controlpalette'), + 'controlId' => $controlId + ]; + } + + /** + * getPluginCode + */ + public function getPluginCode() + { + $pluginCode = Input::get('plugin_code'); + if (strlen($pluginCode)) { + return $pluginCode; + } + + return $this->model->getPluginCodeObj()->toCode(); + } + + // + // Methods for the internal use + // + + /** + * getControlDesignTimeProvider + */ + protected function getControlDesignTimeProvider($providerClass) + { + if (array_key_exists($providerClass, $this->designTimeProviders)) { + return $this->designTimeProviders[$providerClass]; + } + + return $this->designTimeProviders[$providerClass] = new $providerClass($this->controller); + } + + /** + * getPropertyValue + */ + protected function getPropertyValue($properties, $property) + { + if (array_key_exists($property, $properties)) { + return $properties[$property]; + } + + return null; + } + + /** + * propertiesToInspectorSchema + */ + protected function propertiesToInspectorSchema($propertyConfiguration) + { + $result = []; + + $fieldNameProperty = [ + 'title' => Lang::get('rainlab.builder::lang.form.property_field_name_title'), + 'property' => 'oc.fieldName', + 'type' => 'autocomplete', + 'fillFrom' => 'model-fields', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.form.property_field_name_required') + ], + 'regex' => [ + 'message' => Lang::get('rainlab.builder::lang.form.property_field_name_regex'), + 'pattern' => '^[a-zA-Z\_]+[0-9a-z\_\[\]]*$' + ] + ] + ]; + + $result[] = $fieldNameProperty; + + foreach ($propertyConfiguration as $property => $propertyData) { + $propertyData['property'] = $property; + + if ($propertyData['type'] === 'control-container') { + // Control container type properties are handled with the form builder UI and + // should not be available in Inspector. + // + continue; + } + + $result[] = $propertyData; + } + + return $result; + } + + /** + * getControlInfo + */ + protected function getControlInfo($type) + { + if (array_key_exists($type, $this->controlInfoCache)) { + return $this->controlInfoCache[$type]; + } + + $library = ControlLibrary::instance(); + $controlInfo = $library->getControlInfo($type); + + if (!$controlInfo) { + throw new ApplicationException('The requested control type is not found.'); + } + + return $this->controlInfoCache[$type] = $controlInfo; + } + + /** + * renderControlBody + */ + protected function renderControlBody($type, $properties) + { + $controlInfo = $this->getControlInfo($type); + $provider = $this->getControlDesignTimeProvider($controlInfo['designTimeProvider']); + + return $this->makePartial('controlbody', [ + 'hasLabels' => $provider->controlHasLabels($type), + 'body' => $provider->renderControlBody($type, $properties, $this), + 'properties' => $properties + ]); + } + + /** + * renderControlStaticBody + */ + protected function renderControlStaticBody($type, $properties, $controlConfiguration) + { + // The control body footer is never updated with AJAX and currently + // used only by the Repeater widget to display its controls. + + $controlInfo = $this->getControlInfo($type); + $provider = $this->getControlDesignTimeProvider($controlInfo['designTimeProvider']); + + return $provider->renderControlStaticBody($type, $properties, $controlConfiguration, $this); + } + + /** + * renderControlWrapper + */ + protected function renderControlWrapper($type, $properties = [], $controlConfiguration = []) + { + // This method renders the entire control, including + // the wrapping element. + + $controlInfo = $this->getControlInfo($type); + + // Builder UI displays Comment and Comment Above properties + // as Comment and Comment Position properties. + + if (array_key_exists('comment', $properties) && strlen($properties['comment'])) { + $properties['oc.comment'] = $properties['comment']; + $properties['oc.commentPosition'] = 'below'; + } + + if (array_key_exists('commentAbove', $properties) && strlen($properties['commentAbove'])) { + $properties['oc.comment'] = $properties['commentAbove']; + $properties['oc.commentPosition'] = 'above'; + } + + // Data table columns (TODO: move to design time provider? -sg 2023) + if ($type === 'datatable' && is_array($properties['columns'])) { + $ocColumns = []; + foreach ($properties['columns'] as $key => $config) { + $ocColumns[] = ['code' => $key] + $config; + } + $properties['oc.columns'] = $ocColumns; + } + + $provider = $this->getControlDesignTimeProvider($controlInfo['designTimeProvider']); + return $this->makePartial('controlwrapper', [ + 'fieldsConfiguration' => $this->propertiesToInspectorSchema($controlInfo['properties']), + 'controlConfiguration' => $controlConfiguration, + 'type' => $type, + 'properties' => $properties + ]); + } + + /** + * getSpan + */ + protected function getSpan($currentSpan, $prevSpan, $isPlaceholder = false) + { + if ($currentSpan == 'auto' || !strlen($currentSpan)) { + if ($prevSpan == 'left') { + return 'right'; + } + else { + return $isPlaceholder ? 'full' : 'left'; + } + } + + return $currentSpan; + } + + /** + * preprocessPropertyValues + */ + protected function preprocessPropertyValues($controlName, $properties, $controlInfo) + { + $properties['oc.fieldName'] = $controlName; + + // Remove the control container type property values. + // + if (isset($controlInfo['properties'])) { + foreach ($controlInfo['properties'] as $property => $propertyConfig) { + if (isset($propertyConfig['type']) && $propertyConfig['type'] === 'control-container' && isset($properties[$property])) { + unset($properties[$property]); + } + } + } + + return $properties; + } + + /** + * getControlRenderingInfo + */ + protected function getControlRenderingInfo($controlName, $properties, $prevProperties) + { + $type = isset($properties['type']) ? $properties['type'] : 'text'; + $spanFixed = isset($properties['span']) ? $properties['span'] : 'auto'; + $prevSpan = isset($prevProperties['span']) ? $prevProperties['span'] : 'auto'; + + $span = $this->getSpan($spanFixed, $prevSpan); + $spanClass = 'span-'.$span; + + $controlInfo = $this->getControlInfo($type); + + $properties = $this->preprocessPropertyValues($controlName, $properties, $controlInfo); + + return [ + 'title' => Lang::get($controlInfo['name']), + 'description' => Lang::get($controlInfo['description']), + 'type' => $type, + 'span' => $span, + 'spanFixed' => $spanFixed, + 'spanClass' => $spanClass, + 'properties' => $properties, + 'unknownControl' => isset($controlInfo['unknownControl']) && $controlInfo['unknownControl'] + ]; + } + + /** + * getTabConfigurationSchema + */ + protected function getTabConfigurationSchema() + { + if ($this->tabConfigurationSchema !== null) { + return $this->tabConfigurationSchema; + } + + $result = [ + [ + 'title' => Lang::get('rainlab.builder::lang.form.tab_title'), + 'property' => 'title', + 'type' => 'builderLocalization', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.form.property_tab_title_required') + ] + ] + ] + ]; + + return $this->tabConfigurationSchema = json_encode($result); + } + + /** + * getTabsConfigurationSchema + */ + protected function getTabsConfigurationSchema() + { + if ($this->tabsConfigurationSchema !== null) { + return $this->tabsConfigurationSchema; + } + + $result = [ + [ + 'title' => Lang::get('rainlab.builder::lang.form.tab_stretch'), + 'description' => Lang::get('rainlab.builder::lang.form.tab_stretch_description'), + 'property' => 'stretch', + 'type' => 'checkbox' + ], + [ + 'title' => Lang::get('rainlab.builder::lang.form.tab_css_class'), + 'description' => Lang::get('rainlab.builder::lang.form.tab_css_class_description'), + 'property' => 'cssClass', + 'type' => 'string' + ] + ]; + + return $this->tabsConfigurationSchema = json_encode($result); + } + + /** + * getTabConfigurationValues + */ + protected function getTabConfigurationValues($values) + { + if (!count($values)) { + return '{}'; + } + + return json_encode($values); + } + + /** + * getTabsConfigurationValues + */ + protected function getTabsConfigurationValues($values) + { + if (!count($values)) { + return '{}'; + } + + return json_encode($values); + } + + /** + * getTabsFields + */ + protected function getTabsFields($tabsName, $fields) + { + $result = []; + + if (!is_array($fields)) { + return $result; + } + + if (!array_key_exists($tabsName, $fields) || !array_key_exists('fields', $fields[$tabsName])) { + return $result; + } + + $defaultTab = Lang::get('backend::lang.form.undefined_tab'); + if (array_key_exists('defaultTab', $fields[$tabsName])) { + $defaultTab = Lang::get($fields[$tabsName]['defaultTab']); + } + + foreach ($fields[$tabsName]['fields'] as $fieldName => $fieldConfiguration) { + if (!isset($fieldConfiguration['tab'])) { + $fieldConfiguration['tab'] = $defaultTab; + } + + $tab = $fieldConfiguration['tab']; + if (!array_key_exists($tab, $result)) { + $result[$tab] = []; + } + + $result[$tab][$fieldName] = $fieldConfiguration; + } + + return $result; + } +} diff --git a/plugins/rainlab/builder/formwidgets/MenuEditor.php b/plugins/rainlab/builder/formwidgets/MenuEditor.php new file mode 100644 index 0000000..923e46f --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/MenuEditor.php @@ -0,0 +1,241 @@ +prepareVars(); + return $this->makePartial('body'); + } + + /** + * Prepares the list data + */ + public function prepareVars() + { + $this->vars['model'] = $this->model; + $this->vars['items'] = $this->model->menus; + + $this->vars['emptyItem'] = [ + 'label' => Lang::get('rainlab.builder::lang.menu.new_menu_item'), + 'icon' => 'icon-life-ring', + 'code' => 'newitemcode', + 'url' => '/' + ]; + + $this->vars['emptySubItem'] = [ + 'label' => Lang::get('rainlab.builder::lang.menu.new_menu_item'), + 'icon' => 'icon-sitemap', + 'code' => 'newitemcode', + 'url' => '/' + ]; + } + + /** + * {@inheritDoc} + */ + public function loadAssets() + { + $this->addJs('js/menubuilder.js', 'builder'); + } + + public function getPluginCode() + { + $pluginCode = Input::get('plugin_code'); + if (strlen($pluginCode)) { + return $pluginCode; + } + + $pluginVector = $this->controller->getBuilderActivePluginVector(); + + return $pluginVector->pluginCodeObj->toCode(); + } + + // + // Event handlers + // + + // + // Methods for the internal use + // + + protected function getItemArrayProperty($item, $property) + { + if (array_key_exists($property, $item)) { + return $item[$property]; + } + + return null; + } + + protected function getIconList() + { + if ($this->iconList !== null) { + return $this->iconList; + } + + $icons = IconList::getList(); + $this->iconList = []; + + foreach ($icons as $iconCode => $iconInfo) { + $iconCode = preg_replace('/^oc\-/', '', $iconCode); + + $this->iconList[$iconCode] = $iconInfo; + } + + return $this->iconList; + } + + protected function getCommonMenuItemConfigurationSchema() + { + $result = [ + [ + 'title' => Lang::get('rainlab.builder::lang.menu.property_code'), + 'property' => 'code', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.menu.property_code_required') + ] + ] + ], + [ + 'title' => Lang::get('rainlab.builder::lang.menu.property_label'), + 'type' => 'builderLocalization', + 'property' => 'label', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.menu.property_label_required') + ] + ] + ], + [ + 'title' => Lang::get('rainlab.builder::lang.menu.property_url'), + 'property' => 'url', + 'type' => 'autocomplete', + 'fillFrom' => 'controller-urls', + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.menu.property_url_required') + ] + ] + ], + [ + 'title' => Lang::get('rainlab.builder::lang.menu.property_icon'), + 'property' => 'icon', + 'type' => 'dropdown', + 'options' => $this->getIconList(), + 'validation' => [ + 'required' => [ + 'message' => Lang::get('rainlab.builder::lang.menu.property_icon_required') + ] + ], + ], + [ + 'title' => Lang::get('rainlab.builder::lang.menu.icon_svg'), + 'description' => Lang::get('rainlab.builder::lang.menu.icon_svg_description'), + 'property' => 'iconSvg', + ], + [ + 'title' => Lang::get('rainlab.builder::lang.menu.property_permissions'), + 'property' => 'permissions', + 'type' => 'stringListAutocomplete', + 'fillFrom' => 'permissions' + ], + [ + 'title' => Lang::get('rainlab.builder::lang.menu.counter'), + 'description' => Lang::get('rainlab.builder::lang.menu.counter_description'), + 'property' => 'counter', + 'group' => Lang::get('rainlab.builder::lang.menu.counter_group'), + + ], + // Removed in OCv2 + // [ + // 'title' => Lang::get('rainlab.builder::lang.menu.counter_label'), + // 'description' => Lang::get('rainlab.builder::lang.menu.counter_label_description'), + // 'property' => 'counterLabel', + // 'group' => Lang::get('rainlab.builder::lang.menu.counter_group'), + // ], + ]; + + return $result; + } + + protected function getSideMenuConfigurationSchema() + { + $result = $this->getCommonMenuItemConfigurationSchema(); + + $result[] = [ + 'title' => Lang::get('rainlab.builder::lang.menu.property_attributes'), + 'property' => 'attributes', + 'type' => 'stringList' + ]; + + return json_encode($result); + } + + protected function getSideMenuConfiguration($item) + { + if (!count($item)) { + return '{}'; + } + + return json_encode($item); + } + + + protected function getMainMenuConfigurationSchema() + { + $result = $this->getCommonMenuItemConfigurationSchema(); + + $result[] = [ + 'title' => Lang::get('rainlab.builder::lang.menu.property_order'), + 'description' => Lang::get('rainlab.builder::lang.menu.property_order_description'), + 'property' => 'order', + 'validation' => [ + 'regex' => [ + 'pattern' => '^[0-9]+$', + 'message' => Lang::get('rainlab.builder::lang.menu.property_order_invalid') + ] + ] + ]; + + return json_encode($result); + } + + protected function getMainMenuConfiguration($item) + { + if (!count($item)) { + return '{}'; + } + + return json_encode($item); + } +} diff --git a/plugins/rainlab/builder/formwidgets/blueprintbuilder/assets/js/blueprintbuilder.js b/plugins/rainlab/builder/formwidgets/blueprintbuilder/assets/js/blueprintbuilder.js new file mode 100644 index 0000000..437f5b5 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/blueprintbuilder/assets/js/blueprintbuilder.js @@ -0,0 +1,145 @@ +/* + * Blueprint Importer widget class. + * + * There is only a single instance of the Blueprint Importer class and it handles + * as many import builder user interfaces as needed. + * + */ ++function ($) { "use strict"; + + if ($.oc.builder.blueprintbuilder === undefined) { + $.oc.builder.blueprintbuilder = {}; + } + + var Base = $.oc.foundation.base, + BaseProto = Base.prototype; + + var BlueprintBuilder = function() { + Base.call(this); + + this.updateBlueprintTimer = null; + + this.init(); + } + + BlueprintBuilder.prototype = Object.create(BaseProto) + BlueprintBuilder.prototype.constructor = BlueprintBuilder + + // INTERNAL METHODS + // ============================ + + BlueprintBuilder.prototype.init = function() { + this.registerHandlers(); + } + + BlueprintBuilder.prototype.registerHandlers = function() { + $(document).on('click', '.tailor-blueprint-list > li div[data-builder-remove-blueprint]', this.proxy(this.onRemoveBlueprint)) + $(document).on('livechange', '.tailor-blueprint-list > li.blueprint', this.proxy(this.onBlueprintLiveChange)) + } + + // BUILDER API METHODS + // ============================ + + BlueprintBuilder.prototype.onBlueprintLiveChange = function(ev) { + var $li = $(ev.currentTarget).closest('li'); + + this.startUpdateBlueprintBody($li.data('blueprint-uuid')); + + ev.stopPropagation(); + return false; + } + + BlueprintBuilder.prototype.startUpdateBlueprintBody = function(uuid) { + this.clearUpdateBlueprintBodyTimer(); + + var self = this; + this.updateBlueprintTimer = window.setTimeout(function(){ + self.updateBlueprintBody(uuid); + }, 300); + } + + BlueprintBuilder.prototype.clearUpdateBlueprintBodyTimer = function() { + if (this.updateBlueprintTimer === null) { + return; + } + + clearTimeout(this.updateBlueprintTimer); + this.updateBlueprintTimer = null; + } + + BlueprintBuilder.prototype.updateBlueprintBody = function(uuid) { + var $blueprint = $('li[data-blueprint-uuid="'+uuid+'"]'); + if (!$blueprint.length) { + return; + } + + this.clearUpdateBlueprintBodyTimer(); + $blueprint.addClass('updating-blueprint'); + + var properties = this.getBlueprintProperties($blueprint), + data = { + blueprint_uuid: uuid, + properties: properties + }; + + $blueprint.request('onRefreshBlueprintContainer', { + data: data + }).done( + this.proxy(this.blueprintMarkupLoaded) + ).always(function(){ + $blueprint.removeClass('updating-blueprint'); + }); + } + + BlueprintBuilder.prototype.blueprintMarkupLoaded = function(responseData) { + var $li = $('li[data-blueprint-uuid="'+responseData.blueprintUuid+'"]'); + if (!$li.length) { + return; + } + + $('.blueprint-body:first', $li).html(responseData.markup); + } + + BlueprintBuilder.prototype.getBlueprintProperties = function($blueprint) { + var value = $('input[data-inspector-values]', $blueprint).val(); + + if (value) { + return $.parseJSON(value); + } + + throw new Error('Inspector values element is not found in control.'); + } + + BlueprintBuilder.prototype.onRemoveBlueprint = function(ev) { + this.removeBlueprint($(ev.target).closest('li')); + + ev.preventDefault(); + ev.stopPropagation(); + + return false; + } + + BlueprintBuilder.prototype.removeBlueprint = function($control) { + var $container = $('.blueprint-container:first', $control); + + if ($container.hasClass('inspector-open')) { + var $inspectorContainer = this.findInspectorContainer($container); + $.oc.foundation.controlUtils.disposeControls($inspectorContainer.get(0)); + } + + $control.remove(); + } + + BlueprintBuilder.prototype.findInspectorContainer = function($element) { + var $containerRoot = $element.closest('[data-inspector-container]') + + return $containerRoot.find('.inspector-container') + } + + $(document).ready(function(){ + // There is a single instance of the form builder. All operations + // are stateless, so instance properties or DOM references are not needed. + $.oc.builder.blueprintbuilder.controller = new BlueprintBuilder(); + }) + +}(window.jQuery); diff --git a/plugins/rainlab/builder/formwidgets/blueprintbuilder/partials/_blueprint.php b/plugins/rainlab/builder/formwidgets/blueprintbuilder/partials/_blueprint.php new file mode 100644 index 0000000..51f9369 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/blueprintbuilder/partials/_blueprint.php @@ -0,0 +1,18 @@ +getBlueprintInfo($blueprintUuid); + $fieldsConfiguration = $this->propertiesToInspectorSchema($blueprintInfo['properties']); +?> +
  • +

    + +
    +
    + renderBlueprintBody($blueprintInfo, $blueprintConfig) ?> +
    + + + +
    + +
    ×
    +
  • diff --git a/plugins/rainlab/builder/formwidgets/blueprintbuilder/partials/_body.php b/plugins/rainlab/builder/formwidgets/blueprintbuilder/partials/_body.php new file mode 100644 index 0000000..acfc94a --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/blueprintbuilder/partials/_body.php @@ -0,0 +1,11 @@ +
    +
    + +
    + makePartial('buildingarea') ?> +
    + + +
    +
    +
    diff --git a/plugins/rainlab/builder/formwidgets/blueprintbuilder/partials/_buildingarea.php b/plugins/rainlab/builder/formwidgets/blueprintbuilder/partials/_buildingarea.php new file mode 100644 index 0000000..d4abe87 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/blueprintbuilder/partials/_buildingarea.php @@ -0,0 +1,24 @@ +
    +
    +
    +
      + blueprints as $blueprintUuid => $blueprintConfig): ?> + makePartial('blueprint', [ + 'blueprintUuid' => $blueprintUuid, + 'blueprintConfig' => $blueprintConfig + ]) ?> + +
    + +
    +
    +
    diff --git a/plugins/rainlab/builder/formwidgets/blueprintbuilder/partials/_select_blueprint_form.php b/plugins/rainlab/builder/formwidgets/blueprintbuilder/partials/_select_blueprint_form.php new file mode 100644 index 0000000..3364f52 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/blueprintbuilder/partials/_select_blueprint_form.php @@ -0,0 +1,36 @@ +
    + getEventHandler('onSelectBlueprint'), [ + 'data-popup-load-indicator' => true, + ]) ?> + + + + + + + + + + + +
    diff --git a/plugins/rainlab/builder/formwidgets/controllerbuilder/assets/js/controllerbuilder.js b/plugins/rainlab/builder/formwidgets/controllerbuilder/assets/js/controllerbuilder.js new file mode 100644 index 0000000..e69de29 diff --git a/plugins/rainlab/builder/formwidgets/controllerbuilder/partials/_behavior.php b/plugins/rainlab/builder/formwidgets/controllerbuilder/partials/_behavior.php new file mode 100644 index 0000000..e5839b0 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/controllerbuilder/partials/_behavior.php @@ -0,0 +1,16 @@ +getBehaviorInfo($behaviorClass); + + $fieldsConfiguration = $this->propertiesToInspectorSchema($behaviorInfo['properties']); +?> + +
  • +

    + +
    + renderBehaviorBody($behaviorClass, $behaviorInfo, $behaviorConfig) ?> + + + +
    +
  • diff --git a/plugins/rainlab/builder/formwidgets/controllerbuilder/partials/_body.php b/plugins/rainlab/builder/formwidgets/controllerbuilder/partials/_body.php new file mode 100644 index 0000000..ad34004 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/controllerbuilder/partials/_body.php @@ -0,0 +1,10 @@ +
    +
    +
    + makePartial('buildingarea') ?> +
    + + +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/controllerbuilder/partials/_buildingarea.php b/plugins/rainlab/builder/formwidgets/controllerbuilder/partials/_buildingarea.php new file mode 100644 index 0000000..5fae3d5 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/controllerbuilder/partials/_buildingarea.php @@ -0,0 +1,11 @@ +
    +
    +
    +
      + behaviors as $behaviorClass=>$behaviorConfig): ?> + makePartial('behavior', ['behaviorClass'=>$behaviorClass, 'behaviorConfig'=>$behaviorConfig]) ?> + +
    +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/formbuilder/assets/js/formbuilder.controlpalette.js b/plugins/rainlab/builder/formwidgets/formbuilder/assets/js/formbuilder.controlpalette.js new file mode 100644 index 0000000..f5c9ec6 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/formbuilder/assets/js/formbuilder.controlpalette.js @@ -0,0 +1,263 @@ +/* + * Manages the control palette loading and displaying + */ ++function ($) { "use strict"; + + var Base = $.oc.foundation.base, + BaseProto = Base.prototype + + var ControlPalette = function() { + Base.call(this) + + this.controlPaletteMarkup = null + this.popoverMarkup = null + this.containerMarkup = null + this.$popoverContainer = null + } + + ControlPalette.prototype = Object.create(BaseProto) + ControlPalette.prototype.constructor = ControlPalette + + // INTERNAL METHODS + // ============================ + + ControlPalette.prototype.loadControlPalette = function(element, controlId) { + if (this.controlPaletteMarkup === null) { + var data = { + controlId: controlId + } + + $.oc.stripeLoadIndicator.show() + $(element).request('onModelFormLoadControlPalette', { + data: data + }).done( + this.proxy(this.controlPaletteMarkupLoaded) + ).always(function(){ + $.oc.stripeLoadIndicator.hide() + }) + } + else { + this.showControlPalette(controlId, true) + } + } + + ControlPalette.prototype.controlPaletteMarkupLoaded = function(responseData) { + this.controlPaletteMarkup = responseData.markup + + this.showControlPalette(responseData.controlId) + } + + ControlPalette.prototype.getControlById = function(controlId) { + return document.body.querySelector('li[data-builder-control-id="'+controlId+'"]') + } + + ControlPalette.prototype.showControlPalette = function(controlId, initControls) { + if (this.getContainerPreference()) { + this.showControlPalletteInContainer(controlId, initControls) + } + else { + this.showControlPalletteInPopup(controlId, initControls) + } + } + + ControlPalette.prototype.assignControlIdToTemplate = function(template, controlId) { + return template.replace('%c', controlId) + } + + ControlPalette.prototype.markPlaceholderPaletteOpen = function(control) { + $(control).addClass('control-palette-open') + } + + ControlPalette.prototype.markPlaceholderPaletteNotOpen = function(control) { + $(control).removeClass('control-palette-open') + } + + ControlPalette.prototype.getContainerPreference = function() { + return $.oc.inspector.manager.getContainerPreference() + } + + ControlPalette.prototype.setContainerPreference = function(value) { + return $.oc.inspector.manager.setContainerPreference(value) + } + + ControlPalette.prototype.addControl = function(ev) { + var $target = $(ev.currentTarget), + controlId = $target.closest('[data-control-palette-controlid]').attr('data-control-palette-controlid') + + ev.preventDefault() + ev.stopPropagation() + + if (!controlId) { + return false; + } + + var control = this.getControlById(controlId) + if (!control) { + return false + } + + if ($(control).hasClass('loading-control')) { + return false + } + + $target.trigger('close.oc.popover') + + var promise = $.oc.builder.formbuilder.controller.addControlFromControlPalette(controlId, + $target.data('builderControlType'), + $target.data('builderControlName')) + + promise.done(function() { + $.oc.inspector.manager.createInspector(control) + $(control).trigger('change') // Set modified state for the form + }) + + return false + } + + // + // Popover wrapper + // + + ControlPalette.prototype.showControlPalletteInPopup = function(controlId, initControls) { + var control = this.getControlById(controlId) + + if (!control) { + return + } + + var $control = $(control) + + $control.ocPopover({ + content: this.assignControlIdToTemplate(this.getPopoverMarkup(), controlId), + highlightModalTarget: true, + modal: true, + placement: 'below', + containerClass: 'control-inspector', + offset: 15, + width: 400 + }) + + var $popoverContainer = $control.data('oc.popover').$container + + if (initControls) { + // Initialize the scrollpad control in the popup only when the + // popup is created from the cached markup string + $popoverContainer.trigger('render') + } + } + + ControlPalette.prototype.getPopoverMarkup = function() { + if (this.popoverMarkup !== null) { + return this.popoverMarkup + } + + var outerMarkup = $('script[data-template=control-palette-popover]').html() + + this.popoverMarkup = outerMarkup.replace('%s', this.controlPaletteMarkup) + + return this.popoverMarkup + } + + ControlPalette.prototype.dockToContainer = function(ev) { + var $popoverBody = $(ev.target).closest('.control-popover'), + $controlIdContainer = $popoverBody.find('[data-control-palette-controlid]'), + controlId = $controlIdContainer.attr('data-control-palette-controlid'), + control = this.getControlById(controlId) + + $popoverBody.trigger('close.oc.popover') + + this.setContainerPreference(true) + + if (control) { + this.loadControlPalette($(control), controlId) + } + } + + // + // Container wrapper + // + + ControlPalette.prototype.showControlPalletteInContainer = function(controlId, initControls) { + var control = this.getControlById(controlId) + + if (!control) { + return + } + + var inspectorManager = $.oc.inspector.manager, + $container = inspectorManager.getContainerElement($(control)) + + // If the container is already in use, apply values to the inspectable elements + if (!inspectorManager.applyValuesFromContainer($container) || !inspectorManager.containerHidingAllowed($container)) { + return + } + + // Dispose existing Inspector + $.oc.foundation.controlUtils.disposeControls($container.get(0)) + + this.markPlaceholderPaletteOpen(control) + + var template = this.assignControlIdToTemplate(this.getContainerMarkup(), controlId) + $container.append(template) + + $container.find('[data-control-palette-controlid]').one('dispose-control', this.proxy(this.onRemovePaletteFromContainer)) + + if (initControls) { + // Initialize the scrollpad control in the container only when the + // palette is created from the cached markup string + $container.trigger('render') + } + } + + ControlPalette.prototype.onRemovePaletteFromContainer = function(ev) { + this.removePaletteFromContainer($(ev.target)) + } + + ControlPalette.prototype.removePaletteFromContainer = function($container) { + var controlId = $container.attr('data-control-palette-controlid'), + control = this.getControlById(controlId) + + if (control) { + this.markPlaceholderPaletteNotOpen(control) + } + + var $parent = $container.parent() + $container.remove() + $parent.html('') + } + + ControlPalette.prototype.getContainerMarkup = function() { + if (this.containerMarkup !== null) { + return this.containerMarkup + } + + var outerMarkup = $('script[data-template=control-palette-container]').html() + + this.containerMarkup = outerMarkup.replace('%s', this.controlPaletteMarkup) + + return this.containerMarkup + } + + ControlPalette.prototype.closeInContainer = function(ev) { + this.removePaletteFromContainer($(ev.target).closest('[data-control-palette-controlid]')) + } + + ControlPalette.prototype.undockFromContainer = function(ev) { + var $container = $(ev.target).closest('[data-control-palette-controlid]'), + controlId = $container.attr('data-control-palette-controlid'), + control = this.getControlById(controlId) + + this.removePaletteFromContainer($container) + this.setContainerPreference(false) + + if (control) { + this.loadControlPalette($(control), controlId) + } + } + + $(document).ready(function(){ + // There is a single instance of the control palette manager. + $.oc.builder.formbuilder.controlPalette = new ControlPalette() + }) + +}(window.jQuery); \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/formbuilder/assets/js/formbuilder.domtopropertyjson.js b/plugins/rainlab/builder/formwidgets/formbuilder/assets/js/formbuilder.domtopropertyjson.js new file mode 100644 index 0000000..95e530e --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/formbuilder/assets/js/formbuilder.domtopropertyjson.js @@ -0,0 +1,350 @@ +/* + * Converts control properties from DOM elements to JSON format. + */ ++function ($) { "use strict"; + + if ($.oc.builder === undefined) + $.oc.builder = {} + + if ($.oc.builder.formbuilder === undefined) + $.oc.builder.formbuilder = {} + + function getControlPropertyValues(item) { + for (var i=0, len=item.children.length; i 0 && properties['oc.commentPosition'] == 'above') { + properties['commentAbove'] = properties['oc.comment'] + + if (properties['comment'] !== undefined) { + delete properties['comment'] + } + + delete properties['oc.comment'] + delete properties['oc.commentPosition'] + } + + if (String(properties['oc.comment']).length > 0 && properties['oc.commentPosition'] == 'below') { + properties['comment'] = properties['oc.comment'] + + if (properties['comentAbove'] !== undefined) { + delete properties['comentAbove'] + } + + delete properties['oc.comment'] + delete properties['oc.commentPosition'] + } + + if (properties['oc.comment'] !== undefined) { + if (String(properties['oc.comment']).length > 0) { + properties['comment'] = properties['oc.comment'] + } + + delete properties['oc.comment'] + } + } + + function parseControlControlContainer(control) { + var children = control.children, + result = {} + + for (var i=0, len=children.length; i 0) { + if (objectHasProperties(controls)) { + if (result[listName].fields === undefined) { + result[listName].fields = {} + } + + result[listName].fields = $.extend(result[listName].fields, controls) + } + } + else { + if (objectHasProperties(controls)) { + if (result.fields === undefined) { + result.fields = {} + } + + result.fields = $.extend(result.fields, controls) + } + } + } + + function containerToJson(container) { + var containerElements = container.children, + result = {} + + for (var i=0, len=containerElements.length; i li.control'), + result = [] + + for (var i=controls.length-1; i>=0; i--) { + var properties = getControlPropertyValues(controls[i]) + + if (typeof properties !== 'object') { + continue + } + + if (properties['oc.fieldName'] === undefined) { + continue + } + + var name = properties['oc.fieldName'] + + if (result.indexOf(name) === -1) { + result.push(name) + } + } + + result.sort() + + return result + } + + + $.oc.builder.formbuilder.domToPropertyJson = DomToJson + +}(window.jQuery); \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/formbuilder/assets/js/formbuilder.js b/plugins/rainlab/builder/formwidgets/formbuilder/assets/js/formbuilder.js new file mode 100644 index 0000000..1f7d38b --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/formbuilder/assets/js/formbuilder.js @@ -0,0 +1,803 @@ +/* + * Form Builder widget class. + * + * There is only a single instance of the Form Builder class and it handles + * as many form builder user interfaces as needed. + * + */ ++function ($) { "use strict"; + + var Base = $.oc.foundation.base, + BaseProto = Base.prototype + + var FormBuilder = function() { + Base.call(this); + + this.placeholderIdIndex = 0; + this.updateControlBodyTimer = null; + + this.init(); + } + + FormBuilder.prototype = Object.create(BaseProto) + FormBuilder.prototype.constructor = FormBuilder + + // INTERNAL METHODS + // ============================ + + FormBuilder.prototype.init = function() { + this.registerHandlers() + } + + FormBuilder.prototype.registerHandlers = function() { + document.addEventListener('dragstart', this.proxy(this.onDragStart)) + document.addEventListener('dragover', this.proxy(this.onDragOver)) + document.addEventListener('dragenter', this.proxy(this.onDragEnter)) + document.addEventListener('dragleave', this.proxy(this.onDragLeave)) + document.addEventListener('drop', this.proxy(this.onDragDrop), false); + + $(document).on('change', '.builder-control-list > li.control', this.proxy(this.onControlChange)) + $(document).on('click', '.builder-control-list > li.control div[data-builder-remove-control]', this.proxy(this.onRemoveControl)) + $(document).on('click', '.builder-control-list > li.oc-placeholder', this.proxy(this.onPlaceholderClick)) + $(document).on('showing.oc.inspector', '.builder-control-list > li.control', this.proxy(this.onInspectorShowing)) + $(document).on('livechange', '.builder-control-list > li.control', this.proxy(this.onControlLiveChange)) + $(document).on('autocompleteitems.oc.inspector', '.builder-control-list > li.control', this.proxy(this.onAutocompleteItems)) + $(document).on('dropdownoptions.oc.inspector', '.builder-control-list > li.control', this.proxy(this.onDropdownOptions)) + } + + FormBuilder.prototype.getControlId = function(li) { + if (li.hasAttribute('data-builder-control-id')) { + return li.getAttribute('data-builder-control-id') + } + + this.placeholderIdIndex++ + li.setAttribute('data-builder-control-id', this.placeholderIdIndex) + + return this.placeholderIdIndex + } + + // PROPERTY HELPERS + // ============================ + + FormBuilder.prototype.getControlProperties = function(li) { + var children = li.children + + for (var i=children.length-1; i>=0; i--) { + var element = children[i] + + if (element.tagName === 'INPUT' && element.hasAttribute('data-inspector-values')) { + return $.parseJSON(element.value) + } + } + + throw new Error('Inspector values element is not found in control.') + } + + FormBuilder.prototype.setControlProperties = function(li, propertiesObj) { + var propertiesStr = JSON.stringify(propertiesObj), + valuesInput = li.querySelector('[data-inspector-values]') + + valuesInput.value = propertiesStr + } + + FormBuilder.prototype.loadModelFields = function(control, callback) { + var $form = $(this.findForm(control)), + pluginCode = $.oc.builder.indexController.getFormPluginCode($form), + modelClass = $form.find('input[name=model_class]').val() + + $.oc.builder.dataRegistry.get($form, pluginCode, 'model-columns', modelClass, function(response){ + callback({ + options: $.oc.builder.indexController.dataToInspectorArray(response) + }) + }) + } + + FormBuilder.prototype.getContainerFieldNames = function(control, callback) { + var controlWrapper = this.findRootControlWrapper(control), + fieldNames = $.oc.builder.formbuilder.domToPropertyJson.getAllControlNames(controlWrapper), + options = [] + + options.push({ + title: '---', + value: '' + }) + + for (var i=0, len=fieldNames.length; i=0; i--) { + var value = String(valueInputs[i].value) + + if (value.length === 0) { + continue + } + + var properties = $.parseJSON(value) + + if (properties['oc.fieldName'] == fieldName) { + return true + } + } + + return false + } + + // FLOW MANAGEMENT + // ============================ + + FormBuilder.prototype.reflow = function(li, listElement) { + if (!li && !listElement) { + throw new Error('Invalid call of the reflow method. Either li or list parameter should be not empty.') + } + + var list = listElement ? listElement : li.parentNode, + items = list.children, + prevSpan = null + + for (var i=0, len = items.length; i < len; i++) { + var item = items[i], + itemSpan = item.getAttribute('data-builder-span') + + if ($.oc.foundation.element.hasClass(item, 'clear-row')) { + continue + } + + if (itemSpan == 'auto') { + $.oc.foundation.element.removeClass(item, 'span-left') + $.oc.foundation.element.removeClass(item, 'span-full') + $.oc.foundation.element.removeClass(item, 'span-right') + + if (prevSpan == 'left') { + $.oc.foundation.element.addClass(item, 'span-right') + prevSpan = 'right' + } + else { + if (!$.oc.foundation.element.hasClass(item, 'oc-placeholder')) { + $.oc.foundation.element.addClass(item, 'span-left') + } + else { + $.oc.foundation.element.addClass(item, 'span-full') + } + + prevSpan = 'left' + } + } + else { + $.oc.foundation.element.removeClass(item, 'span-left') + $.oc.foundation.element.removeClass(item, 'span-full') + $.oc.foundation.element.removeClass(item, 'span-right') + $.oc.foundation.element.addClass(item, 'span-' + itemSpan) + + prevSpan = itemSpan + } + } + } + + FormBuilder.prototype.setControlSpanFromProperties = function(li, properties) { + if (properties.span === undefined) { + return + } + + li.setAttribute('data-builder-span', properties.span) + this.reflow(li) + } + + FormBuilder.prototype.appendClearRowElement = function(li) { + li.insertAdjacentHTML('afterend', '
  • '); + } + + FormBuilder.prototype.patchControlSpan = function(li, span) { + li.setAttribute('data-builder-span', span) + + var properties = this.getControlProperties(li) + properties.span = span + this.setControlProperties(li, properties) + } + + // DRAG AND DROP + // ============================ + + FormBuilder.prototype.targetIsPlaceholder = function(ev) { + if (!ev.target.getAttribute) { + return false // In Gecko ev.target could be a text node + } + + return ev.target.getAttribute('data-builder-placeholder') + } + + FormBuilder.prototype.dataTransferContains = function(ev, element) { + if (ev.dataTransfer.types.indexOf !== undefined){ + return ev.dataTransfer.types.indexOf(element) >= 0 + } + + return ev.dataTransfer.types.contains(element) + } + + FormBuilder.prototype.sourceIsContainer = function(ev) { + return this.dataTransferContains(ev, 'builder/source/container') + } + + FormBuilder.prototype.startDragFromContainer = function(ev) { + ev.dataTransfer.effectAllowed = 'move' + + var controlId = this.getControlId(ev.target) + ev.dataTransfer.setData('builder/source/container', 'true') + ev.dataTransfer.setData('builder/control/id', controlId) + ev.dataTransfer.setData(controlId, controlId) + } + + FormBuilder.prototype.dropTargetIsChildOf = function(target, ev) { + var current = target + + while (current) { + if (this.elementIsControl(current) && this.dataTransferContains(ev, this.getControlId(current))) { + return true + } + + current = current.parentNode + } + + return false + } + + FormBuilder.prototype.dropFromContainerToPlaceholderOrControl = function(ev, targetControl) { + var targetElement = targetControl ? targetControl : ev.target + + $.oc.foundation.event.stop(ev) + this.stopHighlightingTargets(targetElement) + + var controlId = ev.dataTransfer.getData('builder/control/id'), + originalControl = document.body.querySelector('li[data-builder-control-id="'+controlId+'"]') + + if (!originalControl) { + return + } + + var isSameList = originalControl.parentNode === targetElement.parentNode, + originalList = originalControl.parentNode, + $originalClearRow = $(originalControl).next() + + targetElement.parentNode.insertBefore(originalControl, targetElement) + + this.appendClearRowElement(originalControl) + if ($originalClearRow.hasClass('clear-row')) { + $originalClearRow.remove() + } + + if (!$.oc.foundation.element.hasClass(originalControl, 'inspector-open')) { + this.patchControlSpan(originalControl, 'auto') + } + + this.reflow(targetElement) + + if (!isSameList) { + this.reflow(null, originalList) + } + + $(targetElement).closest('form').trigger('change') + } + + FormBuilder.prototype.elementContainsPoint = function(point, element) { + var elementPosition = $.oc.foundation.element.absolutePosition(element), + elementRight = elementPosition.left + element.offsetWidth, + elementBottom = elementPosition.top + element.offsetHeight + + return point.x >= elementPosition.left && point.x <= elementRight + && point.y >= elementPosition.top && point.y <= elementBottom + } + + FormBuilder.prototype.stopHighlightingTargets = function(target, excludeTarget) { + var rootWrapper = this.findRootControlWrapper(target), + controls = rootWrapper.querySelectorAll('li.control.drag-over') + + for (var i=controls.length-1; i>= 0; i--) { + if (!excludeTarget || target !== controls[i]) { + $.oc.foundation.element.removeClass(controls[i], 'drag-over') + } + } + } + + // UPDATING CONTROLS + // ============================ + + FormBuilder.prototype.startUpdateControlBody = function(controlId) { + this.clearUpdateControlBodyTimer() + + var self = this + this.updateControlBodyTimer = window.setTimeout(function(){ + self.updateControlBody(controlId) + }, 300) + } + + FormBuilder.prototype.clearUpdateControlBodyTimer = function() { + if (this.updateControlBodyTimer === null) { + return + } + + clearTimeout(this.updateControlBodyTimer) + this.updateControlBodyTimer = null + } + + FormBuilder.prototype.updateControlBody = function(controlId) { + var control = document.body.querySelector('li[data-builder-control-id="'+controlId+'"]') + if (!control) { + return + } + + this.clearUpdateControlBodyTimer() + + var rootWrapper = this.findRootControlWrapper(control), + controls = rootWrapper.querySelectorAll('li.control.updating-control') + + for (var i=controls.length-1; i>=0; i--) { + $.oc.foundation.element.removeClass(controls[i], 'updating-control') + } + + $.oc.foundation.element.addClass(control, 'updating-control') + + var controlType = control.getAttribute('data-control-type'), + properties = this.getControlProperties(control), + data = { + controlType: controlType, + controlId: controlId, + properties: properties + } + + $(control).request('onModelFormRenderControlBody', { + data: data + }).done( + this.proxy(this.controlBodyMarkupLoaded) + ).always(function(){ + $.oc.foundation.element.removeClass(control, 'updating-control') + }) + } + + FormBuilder.prototype.controlBodyMarkupLoaded = function(responseData) { + var li = document.body.querySelector('li[data-builder-control-id="'+responseData.controlId+'"]') + if (!li) { + return + } + + var wrapper = li.querySelector('.control-wrapper') + + wrapper.innerHTML = responseData.markup + } + + // ADDING CONTROLS + // ============================ + + FormBuilder.prototype.generateFieldName = function(controlType, placeholder) { + var controlContainer = this.findControlContainer(placeholder) + + if (!controlContainer) { + throw new Error('Cannot find control container for a placeholder.') + } + + // Replace any banned characters + controlType = controlType.replace(/[^a-zA-Z0-9_\[\]]/g, '') + + var counter = 1, + fieldName = controlType + counter + + while (this.fieldNameExistsInContainer(controlContainer, fieldName)) { + counter ++ + fieldName = controlType + counter + } + + return fieldName + } + + FormBuilder.prototype.addControlToPlaceholder = function(placeholder, controlType, controlName, noNewPlaceholder, fieldName) { + // Duplicate the placeholder and place it after + // the existing one + if (!noNewPlaceholder) { + var newPlaceholder = $(placeholder.outerHTML) + + newPlaceholder.removeAttr('data-builder-control-id') + newPlaceholder.removeClass('control-palette-open') + + placeholder.insertAdjacentHTML('afterend', newPlaceholder.get(0).outerHTML) + } + + // Create the clear-row element after the current placeholder + this.appendClearRowElement(placeholder) + + // Replace the placeholder class with control + // loading indicator + $.oc.foundation.element.removeClass(placeholder, 'oc-placeholder') + $.oc.foundation.element.addClass(placeholder, 'loading-control') + $.oc.foundation.element.removeClass(placeholder, 'control-palette-open') + placeholder.innerHTML = '' + placeholder.removeAttribute('data-builder-placeholder') + + if (!fieldName) { + fieldName = this.generateFieldName(controlType, placeholder) + } + + // Send request to the server to load the + // control markup, Inspector data schema, inspector title, etc. + var data = { + controlType: controlType, + controlId: this.getControlId(placeholder), + properties: { + 'label': controlName, + 'span': 'auto', + 'oc.fieldName': fieldName + } + } + this.reflow(placeholder) + + return $(placeholder).request('onModelFormRenderControlWrapper', { + data: data + }).done(this.proxy(this.controlWrapperMarkupLoaded)) + } + + FormBuilder.prototype.controlWrapperMarkupLoaded = function(responseData) { + var placeholder = document.body.querySelector('li[data-builder-control-id="'+responseData.controlId+'"]') + if (!placeholder) { + return + } + + placeholder.setAttribute('draggable', true) + placeholder.setAttribute('data-inspectable', true) + placeholder.setAttribute('data-control-type', responseData.type) + + placeholder.setAttribute('data-inspector-title', responseData.controlTitle) + placeholder.setAttribute('data-inspector-description', responseData.description) + + placeholder.innerHTML = responseData.markup + $.oc.foundation.element.removeClass(placeholder, 'loading-control') + } + + FormBuilder.prototype.displayControlPaletteForPlaceholder = function(element) { + $.oc.builder.formbuilder.controlPalette.loadControlPalette(element, this.getControlId(element)) + } + + FormBuilder.prototype.addControlFromControlPalette = function(placeholderId, controlType, controlName) { + var placeholder = document.body.querySelector('li[data-builder-control-id="'+placeholderId+'"]') + if (!placeholder) { + return + } + + return this.addControlToPlaceholder(placeholder, controlType, controlName) + } + + // REMOVING CONTROLS + // ============================ + + FormBuilder.prototype.removeControl = function($control) { + if ($control.hasClass('inspector-open')) { + var $inspectorContainer = this.findInspectorContainer($control) + $.oc.foundation.controlUtils.disposeControls($inspectorContainer.get(0)) + } + + var $nextControl = $control.next() // Even if the removed element was alone, there's always a placeholder element + $control.remove() + + this.reflow($nextControl.get(0)) + $nextControl.trigger('change') + } + + // DOM HELPERS + // ============================ + + FormBuilder.prototype.findControlContainer = function(element) { + var current = element + + while (current) { + if (current.hasAttribute && current.hasAttribute('data-control-container') ) { + return current + } + + current = current.parentNode + } + + return null + } + + FormBuilder.prototype.findForm = function(element) { + var current = element + + while (current) { + if (current.tagName === 'FORM') { + return current + } + + current = current.parentNode + } + + return null + } + + FormBuilder.prototype.findControlList = function(element) { + var current = element + + while (current) { + if (current.hasAttribute('data-control-list')) { + return current + } + + current = current.parentNode + } + + throw new Error('Cannot find control list for an element.') + } + + FormBuilder.prototype.findPlaceholder = function(controlList) { + var children = controlList.children + + for (var i=children.length-1; i>=0; i--) { + var element = children[i] + + if (element.tagName === 'LI' && $.oc.foundation.element.hasClass(element, 'oc-placeholder')) { + return element + } + } + + throw new Error('Cannot find placeholder in a control list.') + } + + FormBuilder.prototype.findRootControlWrapper = function(control) { + var current = control + + while (current) { + if (current.hasAttribute('data-root-control-wrapper')) { + return current + } + + current = current.parentNode + } + + throw new Error('Cannot find root control wrapper.') + } + + FormBuilder.prototype.findInspectorContainer = function($element) { + var $containerRoot = $element.closest('[data-inspector-container]') + + return $containerRoot.find('.inspector-container') + } + + FormBuilder.prototype.elementIsControl = function(element) { + return element.tagName === 'LI' && element.hasAttribute('data-control-type') && $.oc.foundation.element.hasClass(element, 'control') + } + + FormBuilder.prototype.getClosestControl = function(element) { + var current = element + + while (current) { + if (this.elementIsControl(current)) { + return current + } + + current = current.parentNode + } + + return null + } + + // EVENT HANDLERS + // ============================ + + FormBuilder.prototype.onDragStart = function(ev) { + if (this.elementIsControl(ev.target)) { + this.startDragFromContainer(ev) + + return + } + } + + FormBuilder.prototype.onDragOver = function(ev) { + var targetLi = ev.target + + if (ev.target.tagName !== 'LI') { + targetLi = this.getClosestControl(ev.target) + } + + if (!targetLi || targetLi.tagName != 'LI') { + return + } + + var sourceIsContainer = this.sourceIsContainer(ev), + elementIsControl = this.elementIsControl(targetLi) + + if ((this.targetIsPlaceholder(ev) || elementIsControl) && sourceIsContainer) { + // Do not allow dropping controls to themselves or their + // children controls. + if (sourceIsContainer && elementIsControl && this.dropTargetIsChildOf(targetLi, ev)) { + return false + } + + // Dragging from container over a placeholder or another control. + // Allow the drop. + $.oc.foundation.event.stop(ev) + ev.dataTransfer.dropEffect = 'move' + return + } + } + + FormBuilder.prototype.onDragEnter = function(ev) { + var targetLi = ev.target + + if (ev.target.tagName !== 'LI') { + targetLi = this.getClosestControl(ev.target) + } + + if (!targetLi || targetLi.tagName != 'LI') { + return + } + + var sourceIsContainer = this.sourceIsContainer(ev) + + if (this.targetIsPlaceholder(ev) && sourceIsContainer) { + // Do not allow dropping controls to themselves or their + // children controls. + if (sourceIsContainer && this.dropTargetIsChildOf(ev.target, ev)) { + this.stopHighlightingTargets(ev.target, true) + return + } + + // Dragging from a container over a placeholder. + // Highlight the placeholder. + $.oc.foundation.element.addClass(ev.target, 'drag-over') + return + } + + var elementIsControl = this.elementIsControl(targetLi) + + if (elementIsControl && sourceIsContainer) { + // Do not allow dropping controls to themselves or their + // children controls. + if (sourceIsContainer && elementIsControl && this.dropTargetIsChildOf(targetLi, ev)) { + this.stopHighlightingTargets(targetLi, true) + return + } + + // Dragging from a container over another control. + // Highlight the other control. + $.oc.foundation.element.addClass(targetLi, 'drag-over') + + this.stopHighlightingTargets(targetLi, true) + + return + } + } + + FormBuilder.prototype.onDragLeave = function(ev) { + var targetLi = ev.target + + if (ev.target.tagName !== 'LI') { + targetLi = this.getClosestControl(ev.target) + } + + if (!targetLi || targetLi.tagName != 'LI') { + return + } + + if (this.targetIsPlaceholder(ev) && this.sourceIsContainer(ev)) { + // Dragging from a container over a placeholder. + // Stop highlighting the placeholder. + this.stopHighlightingTargets(ev.target) + + return + } + + if (this.elementIsControl(targetLi) && this.sourceIsContainer(ev)) { + // Dragging from a container over another control. + // Stop highlighting the other control. + var mousePosition = $.oc.foundation.event.pageCoordinates(ev) + + if (!this.elementContainsPoint(mousePosition, targetLi)) { + this.stopHighlightingTargets(targetLi) + } + } + } + + FormBuilder.prototype.onDragDrop = function(ev) { + var targetLi = ev.target + + if (ev.target.tagName !== 'LI') { + targetLi = this.getClosestControl(ev.target) + } + + if (!targetLi || targetLi.tagName != 'LI') { + return + } + + var elementIsControl = this.elementIsControl(targetLi), + sourceIsContainer = this.sourceIsContainer(ev) + + if ((elementIsControl || this.targetIsPlaceholder(ev)) && sourceIsContainer) { + this.stopHighlightingTargets(targetLi) + + if (this.dropTargetIsChildOf(targetLi, ev)) { + return + } + + // Dropped from a container to a placeholder or another control. + // Stop highlighting the placeholder, move the control. + this.dropFromContainerToPlaceholderOrControl(ev, targetLi) + return + } + } + + FormBuilder.prototype.onControlChange = function(ev) { + // Control has changed (with Inspector) - + // update the control markup with AJAX + + var li = ev.currentTarget, + properties = this.getControlProperties(li) + + this.setControlSpanFromProperties(li, properties) + this.updateControlBody(this.getControlId(li)) + + ev.stopPropagation() + return false + } + + FormBuilder.prototype.onControlLiveChange = function(ev) { + $(this.findForm(ev.currentTarget)).trigger('change') // Set modified state for the form + + var li = ev.currentTarget, + propertiesParsed = this.getControlProperties(li) + + this.setControlSpanFromProperties(li, propertiesParsed) + this.startUpdateControlBody(this.getControlId(li)) + + ev.stopPropagation() + return false + } + + FormBuilder.prototype.onAutocompleteItems = function(ev, data) { + if (data.propertyDefinition.fillFrom === 'model-fields') { + ev.preventDefault() + this.loadModelFields(ev.target, data.callback) + } + } + + FormBuilder.prototype.onDropdownOptions = function(ev, data) { + if (data.propertyDefinition.fillFrom === 'form-controls') { + this.getContainerFieldNames(ev.target, data.callback) + ev.preventDefault() + } + } + + FormBuilder.prototype.onRemoveControl = function(ev) { + this.removeControl($(ev.target).closest('li.control')) + + ev.preventDefault() + ev.stopPropagation() + + return false + } + + FormBuilder.prototype.onInspectorShowing = function(ev) { + if ($(ev.target).find('input[data-non-inspectable-control]').length > 0) { + ev.preventDefault() + return false + } + } + + FormBuilder.prototype.onPlaceholderClick = function(ev) { + this.displayControlPaletteForPlaceholder(ev.target) + ev.stopPropagation() + ev.preventDefault() + return false; + } + + $(document).ready(function(){ + // There is a single instance of the form builder. All operations + // are stateless, so instance properties or DOM references are not needed. + $.oc.builder.formbuilder.controller = new FormBuilder() + }) + +}(window.jQuery); \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/formbuilder/assets/js/formbuilder.tabs.js b/plugins/rainlab/builder/formwidgets/formbuilder/assets/js/formbuilder.tabs.js new file mode 100644 index 0000000..3123d25 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/formbuilder/assets/js/formbuilder.tabs.js @@ -0,0 +1,286 @@ +/* + * Manages tabs in the form builder area. + */ ++function ($) { "use strict"; + + var Base = $.oc.foundation.base, + BaseProto = Base.prototype + + var TabManager = function() { + Base.call(this) + + this.init() + } + + TabManager.prototype = Object.create(BaseProto) + TabManager.prototype.constructor = TabManager + + // INTERNAL METHODS + // ============================ + + TabManager.prototype.init = function() { + this.registerHandlers() + } + + TabManager.prototype.registerHandlers = function() { + var $layoutBody = $('#layout-body') + + $layoutBody.on('click', 'li[data-builder-new-tab]', this.proxy(this.onNewTabClick)) + $layoutBody.on('click', 'div[data-builder-tab]', this.proxy(this.onTabClick)) + $layoutBody.on('click', 'div[data-builder-close-tab]', this.proxy(this.onTabCloseClick)) + $layoutBody.on('change livechange', 'ul.tabs > li div.inspector-trigger.tab-control', this.proxy(this.onTabChange)) + $layoutBody.on('hiding.oc.inspector', 'ul.tabs > li div.inspector-trigger.tab-control', this.proxy(this.onTabInspectorHiding)) + } + + TabManager.prototype.getTabList = function($tabControl) { + return $tabControl.find('> ul.tabs') + } + + TabManager.prototype.getPanelList = function($tabControl) { + return $tabControl.find('> ul.panels') + } + + TabManager.prototype.findTabControl = function($tab) { + return $tab.closest('div.tabs') + } + + TabManager.prototype.findTabPanel = function($tab) { + var $tabControl = this.findTabControl($tab), + tabIndex = $tab.index() + + return this.getPanelList($tabControl).find(' > li').eq(tabIndex) + } + + TabManager.prototype.findPanelTab = function($panel) { + var $tabControl = this.findTabControl($panel), + tabIndex = $panel.index() + + return this.getTabList($tabControl).find(' > li').eq(tabIndex) + } + + TabManager.prototype.findTabPanel = function($tab) { + var $tabControl = this.findTabControl($tab), + tabIndex = $tab.index() + + return this.getPanelList($tabControl).find(' > li').eq(tabIndex) + } + + TabManager.prototype.findTabForm = function(tab) { + return $(tab).closest('form') + } + + TabManager.prototype.getGlobalTabsProperties = function(tabsContainer) { + var properties = $(tabsContainer).find('.inspector-trigger.tab-control.global [data-inspector-values]').val() + + if (properties.length == 0) { + properties = '{}' + } + + return $.parseJSON(properties) + } + + /* + * Returns tab title an element belongs to + */ + TabManager.prototype.getElementTabTitle = function(element) { + var $panel = $(element).closest('li.tab-panel'), + $tab = this.findPanelTab($panel), + properties = $tab.find('[data-inspector-values]').val(), + propertiesParsed = $.parseJSON(properties) + + return propertiesParsed.title + } + + TabManager.prototype.tabHasControls = function($tab) { + return this.findTabPanel($tab).find('ul[data-control-list] li.control:not(.oc-placeholder)').length > 0 + } + + TabManager.prototype.tabNameExists = function($tabList, name, $ignoreTab) { + var tabs = $tabList.get(0).children + + for (var i=0, len = tabs.length; i li[data-builder-new-tab]') + + $('[data-tab-title]', $newTab).text(tabName) + + $newTab.insertBefore($newTabControl) + this.getPanelList($tabControl).append(panelTemplate) + + this.gotoTab($newTab) + } + + TabManager.prototype.gotoTab = function($tab) { + var tabIndex = $tab.index(), + $tabControl = this.findTabControl($tab), + $tabList = this.getTabList($tabControl), + $panelList = this.getPanelList($tabControl) + + $('> li', $tabList).removeClass('active') + $tab.addClass('active') + + $('> li', $panelList).removeClass('active') + $('> li', $panelList).eq(tabIndex).addClass('active') + } + + TabManager.prototype.findInspectorContainer = function($element) { + var $containerRoot = $element.closest('[data-inspector-container]') + + return $containerRoot.find('.inspector-container') + } + + TabManager.prototype.closeTabInspectors = function($tab, $tabPanel) { + if ($tab.find('.inspector-open').length === 0 && $tabPanel.find('.inspector-open').length === 0) { + return + } + + var $inspectorContainer = this.findInspectorContainer($tab) + + $.oc.foundation.controlUtils.disposeControls($inspectorContainer.get(0)) + } + + TabManager.prototype.closeTabControlPalette = function($tab, $tabPanel) { + if ($tabPanel.find('.control-palette-open').length === 0) { + return + } + + var $inspectorContainer = this.findInspectorContainer($tab) + + $.oc.foundation.controlUtils.disposeControls($inspectorContainer.get(0)) + } + + TabManager.prototype.closeTab = function($tab) { + var $tabControl = this.findTabControl($tab) + + if (this.tabHasControls($tab)) { + if (!confirm($tabControl.data('tabCloseConfirmation'))) { + return + } + + $tab.trigger('change') + } + + var $prevTab = $tab.prev(), + $nextTab = $tab.next(), + $tabPanel = this.findTabPanel($tab) + + this.closeTabInspectors($tab, $tabPanel) + this.closeTabControlPalette($tab, $tabPanel) + + $tab.remove() + $tabPanel.remove() + + if ($prevTab.length > 0) { + this.gotoTab($prevTab) + } + else { + if ($nextTab.length > 0 && !$nextTab.hasClass('new-tab')) { + this.gotoTab($nextTab) + } + else { + this.createNewTab($tabControl) + } + } + } + + TabManager.prototype.updateTabProperties = function($tab) { + var properties = $tab.find('[data-inspector-values]').val(), + propertiesParsed = $.parseJSON(properties), + $form = this.findTabForm($tab), + pluginCode = $form.find('input[name=plugin_code]').val() + + $tab.find('[data-tab-title]').attr('data-localization-key', propertiesParsed.title) + + $.oc.builder.dataRegistry.getLocalizationString($form, pluginCode, propertiesParsed.title, function(title){ + $tab.find('[data-tab-title]').text(title) + }) + } + + // EVENT HANDLERS + // ============================ + + TabManager.prototype.onNewTabClick = function(ev) { + this.createNewTab($(ev.currentTarget).closest('div.tabs')) + + ev.stopPropagation() + ev.preventDefault() + + return false + } + + TabManager.prototype.onTabClick = function(ev) { + this.gotoTab($(ev.currentTarget).closest('li')) + + ev.stopPropagation() + ev.preventDefault() + + return false + } + + TabManager.prototype.onTabCloseClick = function(ev) { + this.closeTab($(ev.currentTarget).closest('li')) + + ev.stopPropagation() + ev.preventDefault() + + return false + } + + TabManager.prototype.onTabChange = function(ev) { + this.updateTabProperties($(ev.currentTarget).closest('li')) + } + + TabManager.prototype.onTabInspectorHiding = function(ev, data) { + var $tab = $(ev.currentTarget).closest('li'), + $tabControl = this.findTabControl($tab), + $tabList = this.getTabList($tabControl) + + if (this.tabNameExists($tabList, data.values.title, $tab)) { + alert($tabControl.data('tabAlreadyExists')) + + ev.preventDefault() + } + } + + $(document).ready(function(){ + // There is a single instance of the tabs manager. + $.oc.builder.formbuilder.tabManager = new TabManager() + }) + +}(window.jQuery); \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/formbuilder/partials/_body.php b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_body.php new file mode 100644 index 0000000..c6bd2b8 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_body.php @@ -0,0 +1,34 @@ +
    +
    +
    + makePartial('buildingarea') ?> +
    + + +
    +
    +
    + + + + \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/formbuilder/partials/_buildingarea.php b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_buildingarea.php new file mode 100644 index 0000000..a15e7a0 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_buildingarea.php @@ -0,0 +1,9 @@ +
    +
    +
    +
    + makePartial('controlcontainer', ['fieldsConfiguration'=>$model->controls]) ?> +
    +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/formbuilder/partials/_controlbody.php b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_controlbody.php new file mode 100644 index 0000000..1dfe6c9 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_controlbody.php @@ -0,0 +1,26 @@ +
    + getPropertyValue($properties, 'label'); + $comment = $this->getPropertyValue($properties, 'oc.comment'); + + // Note - the label and comment elements should not have whitespace in the markup. + ?> +
    + +
    getPropertyValue($properties, 'oc.commentPosition') == 'above'): ?>
    + + + + + +
    getPropertyValue($properties, 'oc.commentPosition') == 'below'): ?>
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/formbuilder/partials/_controlcontainer.php b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_controlcontainer.php new file mode 100644 index 0000000..eca3d0a --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_controlcontainer.php @@ -0,0 +1,26 @@ +
    + + makePartial('controllist', [ + 'controls' => isset($fieldsConfiguration['fields']) ? $fieldsConfiguration['fields'] : [], + 'listName' => '' + ]) ?> + + makePartial('tabs', [ + 'type' => 'primary', + 'controls' => $this->getTabsFields('tabs', $fieldsConfiguration), + 'listName' => 'tabs', + 'tabsTitle' => trans('rainlab.builder::lang.form.tabs_primary'), + 'configuration' => [], + 'tabNameTemplate' => trans('rainlab.builder::lang.form.tab_name_template'), + ]) ?> + + makePartial('tabs', [ + 'type' => 'secondary', + 'controls' => $this->getTabsFields('secondaryTabs', $fieldsConfiguration), + 'listName' => 'secondaryTabs', + 'tabsTitle' => trans('rainlab.builder::lang.form.tabs_secondary'), + 'configuration' => [], + 'tabNameTemplate' => trans('rainlab.builder::lang.form.tab_name_template'), + ]) ?> + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/formbuilder/partials/_controllist.php b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_controllist.php new file mode 100644 index 0000000..018e50e --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_controllist.php @@ -0,0 +1,40 @@ +
      + $controlConfig): + $controlRenderingInfo = $this->getControlRenderingInfo($controlName, $controlConfig, $prevConfig); + + $prevSpan = $controlConfig['span'] = $controlRenderingInfo['span']; + $prevConfig = $controlConfig; + ?> +
    • + data-inspectable="true" + + data-unknown + + draggable="true" + data-control-type="" + data-inspector-title="" + data-inspector-description=""> + + renderControlWrapper($controlRenderingInfo['type'], $controlRenderingInfo['properties'], $controlConfig) ?> + +
    • + +
    • + + +
    • + +
    • +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/formbuilder/partials/_controlpalette.php b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_controlpalette.php new file mode 100644 index 0000000..05559ab --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_controlpalette.php @@ -0,0 +1,33 @@ +
    +
    + +
    + +
    + +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/formbuilder/partials/_controlwrapper.php b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_controlwrapper.php new file mode 100644 index 0000000..9256feb --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_controlwrapper.php @@ -0,0 +1,14 @@ + + +
    + renderControlBody($type, $properties) ?> +
    + +renderControlStaticBody($type, $properties, $controlConfiguration) ?> + + + + +
    ×
    \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/formbuilder/partials/_tab.php b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_tab.php new file mode 100644 index 0000000..140ed71 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_tab.php @@ -0,0 +1,22 @@ +
  • +
    +
    + +
    +
    + +
    + + + + + +
    + +
    ×
    +
  • \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/formbuilder/partials/_tabpanel.php b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_tabpanel.php new file mode 100644 index 0000000..7c2d65c --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_tabpanel.php @@ -0,0 +1,6 @@ +
  • + makePartial('controllist', [ + 'controls' => $controls, + 'listName' => $listName + ]) ?> +
  • \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/formbuilder/partials/_tabs.php b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_tabs.php new file mode 100644 index 0000000..4ce12df --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/formbuilder/partials/_tabs.php @@ -0,0 +1,57 @@ +
    +
    +
      + + makePartial('tab', ['active'=>true, 'title'=>sprintf($tabNameTemplate, '1') ]) ?> + + $tabControls): + $tabIndex++; + ?> + makePartial('tab', ['active'=>$tabIndex == 1, 'title'=>$tabName]) ?> + + +
    • +
    + +
      + + makePartial('tabpanel', ['controls' => [], 'listName'=>$listName, 'active'=>true]); ?> + + + $tabControls): ?> + + makePartial('tabpanel', ['controls' => $tabControls, 'listName'=>$listName, 'active'=>$tabIndex == 1]) ?> + + +
    + +
    +
    + + + +
    + +
    + + + + +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/menueditor/assets/js/menubuilder.js b/plugins/rainlab/builder/formwidgets/menueditor/assets/js/menubuilder.js new file mode 100644 index 0000000..7a76446 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/menueditor/assets/js/menubuilder.js @@ -0,0 +1,230 @@ +/* + * Menu Builder widget class. + * + * There is only a single instance of the Menu Builder class and it handles + * as many menu builder user interfaces as needed. + * + */ ++function ($) { "use strict"; + + if ($.oc.builder.menubuilder === undefined) + $.oc.builder.menubuilder = {} + + var Base = $.oc.foundation.base, + BaseProto = Base.prototype + + var MenuBulder = function() { + Base.call(this) + + this.init() + } + + MenuBulder.prototype = Object.create(BaseProto) + MenuBulder.prototype.constructor = MenuBulder + + // INTERNAL METHODS + // ============================ + + MenuBulder.prototype.init = function() { + this.registerHandlers() + } + + MenuBulder.prototype.registerHandlers = function() { + $(document).on('change', '.builder-menu-editor li.item', this.proxy(this.onItemChange)) + $(document).on('dragged.list.sortable', '.builder-menu-editor li.item', this.proxy(this.onItemDragged)) + $(document).on('livechange', '.builder-menu-editor li.item', this.proxy(this.onItemLiveChange)) + } + + MenuBulder.prototype.getParentList = function(element) { + return $(element).closest('ul') + } + + MenuBulder.prototype.findForm = function(item) { + return $(item).closest('form') + } + + MenuBulder.prototype.getElementListItem = function(element) { + return $(element).closest('li') + } + + MenuBulder.prototype.getMenuBuilderControlElement = function(element) { + return $(element).closest('[data-control=builder-menu-editor]') + } + + MenuBulder.prototype.getTemplateMarkup = function(element, templateAttribute) { + var $builderControl = this.getMenuBuilderControlElement(element) + + return $builderControl.find('script['+templateAttribute+']').html() + } + + MenuBulder.prototype.getItemProperties = function(item) { + return $.parseJSON($(item).find('> input[data-inspector-values]').val()) + } + + MenuBulder.prototype.itemCodeExistsInList = function($list, code) { + var valueInputs = $list.find('> li.item > input[data-inspector-values]') + + for (var i=valueInputs.length-1; i>=0; i--) { + var value = String(valueInputs[i].value) + + if (value.length === 0) { + continue + } + + var properties = $.parseJSON(value) + + if (properties['code'] == code) { + return true + } + } + + return false + } + + MenuBulder.prototype.replacePropertyValue = function($item, property, value) { + var input = $item.find(' > input[data-inspector-values]'), + properties = $.parseJSON(input.val()) + + properties[property] = value + input.val(JSON.stringify(properties)) + } + + MenuBulder.prototype.generateItemCode = function($parentList, baseCode) { + var counter = 1, + code = baseCode + + while (this.itemCodeExistsInList($parentList, code)) { + counter ++ + code = baseCode + counter + } + + return code + } + + MenuBulder.prototype.updateItemVisualProperties = function(item) { + var properties = this.getItemProperties(item), + $item = $(item), + $form = this.findForm(item), + pluginCode = $form.find('input[name=plugin_code]').val() + + $item.find('> .item-container > span.title').attr('data-localization-key', properties.label) + + $.oc.builder.dataRegistry.getLocalizationString($item, pluginCode, properties.label, function(label){ + $item.find('> .item-container > span.title').text(label) + }) + + $item.find('> .item-container > i').attr('class', properties.icon) + } + + MenuBulder.prototype.findInspectorContainer = function($element) { + var $containerRoot = $element.closest('[data-inspector-container]') + + return $containerRoot.find('.inspector-container') + } + + // BUILDER API METHODS + // ============================ + + MenuBulder.prototype.addMainMenuItem = function(ev) { + var newItemMarkup = this.getTemplateMarkup(ev.currentTarget, 'data-main-menu-template'), + $item = $(newItemMarkup), + $list = this.getParentList(ev.currentTarget), + newCode = this.generateItemCode($list, 'main-menu-item') + + this.replacePropertyValue($item, 'code', newCode) + + this.getElementListItem(ev.currentTarget).before($item) + $(this.findForm(ev.currentTarget)).trigger('change') + } + + MenuBulder.prototype.addSideMenuItem = function(ev) { + var newItemMarkup = this.getTemplateMarkup(ev.currentTarget, 'data-side-menu-template'), + $item = $(newItemMarkup), + $list = this.getParentList(ev.currentTarget), + newCode = this.generateItemCode($list, 'side-menu-item') + + this.replacePropertyValue($item, 'code', newCode) + + this.getElementListItem(ev.currentTarget).before($item) + $(this.findForm(ev.currentTarget)).trigger('change') + } + + MenuBulder.prototype.getJson = function(form) { + var mainMenuItems = form.querySelectorAll('ul.builder-main-menu > li.item'), + result = [] + + for (var i=0,lenOuter=mainMenuItems.length; i < lenOuter; i++) { + var mainMenuItem = mainMenuItems[i], + mainMenuItemConfig = this.getItemProperties(mainMenuItem) + + if (mainMenuItemConfig['sideMenu'] !== undefined) { + delete mainMenuItemConfig['sideMenu'] + } + + var sideMenuItems = mainMenuItem.querySelectorAll('ul.builder-submenu > li.item') + for (var j=0,lenInner=sideMenuItems.length; j < lenInner; j++) { + var sideMenuItem = sideMenuItems[j], + sideMenuItemConfig = this.getItemProperties(sideMenuItem) + + if (mainMenuItemConfig['sideMenu'] === undefined) { + mainMenuItemConfig['sideMenu'] = [] + } + + mainMenuItemConfig['sideMenu'].push(sideMenuItemConfig) + } + + result.push(mainMenuItemConfig) + } + + return JSON.stringify(result) + } + + MenuBulder.prototype.deleteMenuItem = function(ev) { + var item = this.getElementListItem(ev.currentTarget) + + if ($(item).hasClass('inspector-open')) { + var $inspectorContainer = this.findInspectorContainer($(item)) + $.oc.foundation.controlUtils.disposeControls($inspectorContainer.get(0)) + } + + var subitems = item.get(0).querySelectorAll('li.inspector-open') + for (var i=subitems.length-1; i>=0; i--) { + var $inspectorContainer = this.findInspectorContainer($(subitems[i])) + $.oc.foundation.controlUtils.disposeControls($inspectorContainer.get(0)) + } + + $(this.findForm(ev.currentTarget)).trigger('change') + + $(item).remove() + } + + // EVENT HANDLERS + // ============================ + + MenuBulder.prototype.onItemLiveChange = function(ev) { + this.updateItemVisualProperties(ev.currentTarget) + + $(this.findForm(ev.currentTarget)).trigger('change') // Set modified state for the form + + ev.stopPropagation() + return false + } + + MenuBulder.prototype.onItemChange = function(ev) { + this.updateItemVisualProperties(ev.currentTarget) + + ev.stopPropagation() + return false + } + + MenuBulder.prototype.onItemDragged = function(ev) { + $(this.findForm(ev.target)).trigger('change') + } + + $(document).ready(function(){ + // There is a single instance of the form builder. All operations + // are stateless, so instance properties or DOM references are not needed. + $.oc.builder.menubuilder.controller = new MenuBulder() + }) + +}(window.jQuery); \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/menueditor/partials/_body.php b/plugins/rainlab/builder/formwidgets/menueditor/partials/_body.php new file mode 100644 index 0000000..f5bbcfb --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/menueditor/partials/_body.php @@ -0,0 +1,28 @@ +
    +
    +
    + +
    +
    +
    +
    + makePartial('mainmenuitems', ['items' => $items]) ?> +
    +
    +
    + + + + +
    + +
    + + +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/menueditor/partials/_mainmenuitem.php b/plugins/rainlab/builder/formwidgets/menueditor/partials/_mainmenuitem.php new file mode 100644 index 0000000..529d122 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/menueditor/partials/_mainmenuitem.php @@ -0,0 +1,17 @@ +
  • +
    + + getItemArrayProperty($item, 'label'))) ?> + + × +
    + + + + + makePartial('submenuitems', ['items' => $this->getItemArrayProperty($item, 'sideMenu')]) ?> +
  • \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/menueditor/partials/_mainmenuitems.php b/plugins/rainlab/builder/formwidgets/menueditor/partials/_mainmenuitems.php new file mode 100644 index 0000000..5661380 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/menueditor/partials/_mainmenuitems.php @@ -0,0 +1,15 @@ +
      + + makePartial('mainmenuitem', ['item' => $item]) ?> + + +
    • + + + + +
    • +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/menueditor/partials/_submenuitem.php b/plugins/rainlab/builder/formwidgets/menueditor/partials/_submenuitem.php new file mode 100644 index 0000000..673b4d4 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/menueditor/partials/_submenuitem.php @@ -0,0 +1,15 @@ +
  • +
    + + getItemArrayProperty($item, 'label'))) ?> + × +
    + + + +
  • \ No newline at end of file diff --git a/plugins/rainlab/builder/formwidgets/menueditor/partials/_submenuitems.php b/plugins/rainlab/builder/formwidgets/menueditor/partials/_submenuitems.php new file mode 100644 index 0000000..24ee8b5 --- /dev/null +++ b/plugins/rainlab/builder/formwidgets/menueditor/partials/_submenuitems.php @@ -0,0 +1,17 @@ +
      + + + makePartial('submenuitem', ['item' => $item]) ?> + + + +
    • + + + + +
    • +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/lang/cs.json b/plugins/rainlab/builder/lang/cs.json new file mode 100644 index 0000000..2e38a53 --- /dev/null +++ b/plugins/rainlab/builder/lang/cs.json @@ -0,0 +1,4 @@ +{ + "Builder": "Builder", + "Provides visual tools for building October plugins.": "Poskytuje vizuální nástroj pro tvorbu October pluginů." +} \ No newline at end of file diff --git a/plugins/rainlab/builder/lang/cs/lang.php b/plugins/rainlab/builder/lang/cs/lang.php new file mode 100644 index 0000000..2cc653d --- /dev/null +++ b/plugins/rainlab/builder/lang/cs/lang.php @@ -0,0 +1,621 @@ + [ + 'add' => 'Vytvořit plugin', + 'no_records' => 'Žádný plugin nenalezen', + 'no_description' => 'Tento plugin nemá žádný popisek', + 'no_name' => 'Bez jména', + 'search' => 'Vyhledávání...', + 'filter_description' => 'Zobrazit všechny pluginy, nebo pouze vaše.', + 'settings' => 'Nastavení', + 'entity_name' => 'Plugin', + 'field_name' => 'Název', + 'field_author' => 'Autor', + 'field_description' => 'Popis', + 'field_icon' => 'Ikona pluginu', + 'field_plugin_namespace' => 'Jmenný prostor pluginu', + 'field_author_namespace' => 'Jmenný prostor autora', + 'field_namespace_description' => 'Jmenný prostor může obsahovat pouze znaky, číslice a měl by začínat písmenem. Například Blog.', + 'field_author_namespace_description' => 'Zadaný jmenný prostor nebude možno přes Builder poté změnit. Příklad jmenného prostoru: JohnSmith.', + 'tab_general' => 'Základní parametry', + 'tab_description' => 'Popis', + 'field_homepage' => 'Domovská URL pluginu', + 'error_settings_not_editable' => 'Nastavení tohoto pluginu nelze přes Builder měnit, protože nemá soubor plugin.yaml.', + 'update_hint' => 'Překlad názvu a popisku můžete měnit v menu Lokalizace.', + 'manage_plugins' => 'Tvorba a úprava pluginů.', + ], + 'author_name' => [ + 'title' => 'Jméno autora', + 'description' => 'Výchozí jméno autora pro nově vytvořené pluginy. Toto jméno však můžete změnit při vytváření nového pluginu, nebo poté v editaci.', + ], + 'author_namespace' => [ + 'title' => 'Jmenný prostor autora', + 'description' => 'Pokud budete chtít plugin umístit na stránkách OctoberCMS, jmenný prostor by se měl být pro všechny vaše pluginy shodný. Více detailů najdete v dokumentaci publikace pluginů.', + ], + 'database' => [ + 'menu_label' => 'Databáze', + 'no_records' => 'Žádné tabulky nebyly nalezeny', + 'search' => 'Vyhledávání...', + 'confirmation_delete_multiple' => 'Opravdu chcete odstranit vybrané tabulky?', + 'field_name' => 'Název databázové tabulky', + 'tab_columns' => 'Sloupce', + 'column_name_name' => 'Sloupec', + 'column_name_required' => 'Zadejte prosím název sloupce', + 'column_name_type' => 'Typ', + 'column_type_required' => 'Vyberte prosím typ sloupce', + 'column_name_length' => 'Délka', + 'column_validation_length' => 'Délka by měla být zadaná číselně, nebo zadaná jako číslo a přesnost (10,2) pro desetinná čísla. Mezery nejsou povolené.', + 'column_validation_title' => 'V názvu sloupce mohou být pouze čísla, malá písmena a podtržítko.', + 'column_name_unsigned' => 'Bez znaménka', + 'column_name_nullable' => 'Nulový', + 'column_auto_increment' => 'AUTOINCR', + 'column_default' => 'Výchozí', + 'column_auto_primary_key' => 'PK', + 'tab_new_table' => 'Nová tabulka', + 'btn_add_column' => 'Přidat sloupec', + 'btn_delete_column' => 'Smazat sloupec', + 'confirm_delete' => 'Opravdu chcete smazat tuto tabulku?', + 'error_enum_not_supported' => 'Tabulka obsahuje sloupce s typem "enum" které Builder aktuálně nepodporuje.', + 'error_table_name_invalid_prefix' => 'Název tabulky by měl začínat prefixem pluginu: \':prefix\'.', + 'error_table_name_invalid_characters' => 'Formát názvu tabulky není správný, měl by obsahovat pouze písmena, číslice a nebo podtržítka. Název by měl začínat písmenem a neměl by obsahovat mezery.', + 'error_table_duplicate_column' => 'Takový název sloupce již existuje: \':column\'.', + 'error_table_auto_increment_in_compound_pk' => 'An auto-increment column cannot be a part of a compound primary key.', + 'error_table_mutliple_auto_increment' => 'Tabulka nemůže obsahovat více sloupců s auto-increment vlastností.', + 'error_table_auto_increment_non_integer' => 'Auto-increment sloupec by měl mít číselný typ.', + 'error_table_decimal_length' => 'Zápis délky pro typ :type by měl být ve formátu \'10,2\', bez mezer.', + 'error_table_length' => 'Zápis délky pro typ :type by měl být zadaný jako číslo.', + 'error_unsigned_type_not_int' => 'Chyba ve sloupci \':column\'. Přiznak \'bez znaménka\' můžete použít pouze pro číselné typy.', + 'error_integer_default_value' => 'Chybná výchozí hodnota pro číselný sloupec \':column\'. Povolené formáty jsou \'10\', \'-10\'.', + 'error_decimal_default_value' => 'Chybná výchozí hodnota pro desetinný sloupec \':column\'. Povolené formáty jsou \'1.00\', \'-1.00\'.', + 'error_boolean_default_value' => 'Chybná výchozí hodnota pro pravdivostní sloupec \':column\'. Povolené hodnoty jsou \'0\' and \'1\'.', + 'error_unsigned_negative_value' => 'Výchozí hodnota pro sloupec bez znaménka \':column\' nemůže být záporná.', + 'error_table_already_exists' => 'Tabulka \':name\' již v databázi existuje.', + ], + 'model' => [ + 'menu_label' => 'Modely', + 'entity_name' => 'Model', + 'no_records' => 'Žádný model nebyl nalezen', + 'search' => 'Vyhledávání...', + 'add' => 'Přidat...', + 'forms' => 'Formuláře', + 'lists' => 'Listování', + 'field_class_name' => 'Název třídy', + 'field_database_table' => 'Databazová tabulka', + 'error_class_name_exists' => 'Soubor modelu pro tuto třídu již existuje: :path', + 'add_form' => 'Přidat formulář', + 'add_list' => 'Přidat listování', + ], + 'form' => [ + 'saved' => 'Formulář byl úspěšně uložen.', + 'confirm_delete' => 'Opravdu chcete smazat tento formulář?', + 'tab_new_form' => 'Nový formulář', + 'property_label_title' => 'Popisek', + 'property_label_required' => 'Zadejte prosím popisek pole.', + 'property_span_title' => 'Zarovnání', + 'property_comment_title' => 'Komentář', + 'property_comment_above_title' => 'Komentář nad', + 'property_default_title' => 'Výchozí', + 'property_checked_default_title' => 'Ve výchozím stavu zaškrtnuto', + 'property_css_class_title' => 'CSS třída', + 'property_css_class_description' => 'Volitelná CSS třída která se přiřadí ke kontejneru pole.', + 'property_disabled_title' => 'Neaktivní', + 'property_hidden_title' => 'Skrytý', + 'property_required_title' => 'Povinný', + 'property_field_name_title' => 'Název pole', + 'property_placeholder_title' => 'Zástupný text', + 'property_default_from_title' => 'Default from', + 'property_stretch_title' => 'Stretch', + 'property_stretch_description' => 'Definuje jestli se toto pole zmenší tak, aby se vešlo to rodičovského prvku na výšku.', + 'property_context_title' => 'Kontext', + 'property_context_description' => 'Definuje jaký kontext bude zobrazen při zobrazení tohoto pole.', + 'property_context_create' => 'Vytvořit', + 'property_context_update' => 'Upravit', + 'property_context_preview' => 'Náhled', + 'property_dependson_title' => 'Závisí na', + 'property_trigger_action' => 'Akce', + 'property_trigger_show' => 'Zobrazit', + 'property_trigger_hide' => 'Schovat', + 'property_trigger_enable' => 'Aktivní', + 'property_trigger_disable' => 'Neaktivní', + 'property_trigger_empty' => 'Prázdný', + 'property_trigger_field' => 'Pole', + 'property_trigger_field_description' => 'Defines the other field name that will trigger the action.', + 'property_trigger_condition' => 'Podmínka', + 'property_trigger_condition_description' => 'Determines the condition the specified field should satisfy for the condition to be considered "true". Supported values: checked, unchecked, value[somevalue].', + 'property_trigger_condition_checked' => 'Zaškrtnuté', + 'property_trigger_condition_unchecked' => 'Nezaškrtnuté', + 'property_trigger_condition_somevalue' => 'value[enter-the-value-here]', + 'property_preset_title' => 'Preset', + 'property_preset_description' => 'Allows the field value to be initially set by the value of another field, converted using the input preset converter.', + 'property_preset_field' => 'Pole', + 'property_preset_field_description' => 'Defines the other field name to source the value from.', + 'property_preset_type' => 'Typ', + 'property_preset_type_description' => 'Specifies the conversion type', + 'property_attributes_title' => 'Atributy', + 'property_attributes_description' => 'Custom HTML attributes to add to the form field element.', + 'property_container_attributes_title' => 'Kontejnér atributů', + 'property_container_attributes_description' => 'Custom HTML attributes to add to the form field container element.', + 'property_group_advanced' => 'Pokročilé', + 'property_dependson_description' => 'A list of other field names this field depends on, when the other fields are modified, this field will update. One field per line.', + 'property_trigger_title' => 'Trigger', + 'property_trigger_description' => 'Allows to change elements attributes such as visibility or value, based on another elements\' state.', + 'property_default_from_description' => 'Takes the default value from the value of another field.', + 'property_field_name_required' => 'Název pole je povinný', + 'property_field_name_regex' => 'Název pole může obsahovat pouze písmena, číslice, podtržítka, pomlčky a hranaté závorky.', + 'property_attributes_size' => 'Velikost', + 'property_attributes_size_tiny' => 'Nejmenší', + 'property_attributes_size_small' => 'Malý', + 'property_attributes_size_large' => 'Normální', + 'property_attributes_size_huge' => 'Veliký', + 'property_attributes_size_giant' => 'Obrovský', + 'property_comment_position' => 'Zobrazit komentář', + 'property_comment_position_above' => 'Nad prvkem', + 'property_comment_position_below' => 'Pod prvkem', + 'property_hint_path' => 'Hint partial path', + 'property_hint_path_description' => 'Path to a partial file that contains the hint text. Use the $ symbol to refer the plugins root directory, for example: $/acme/blog/partials/_hint.htm', + 'property_hint_path_required' => 'Please enter the hint partial path', + 'property_partial_path' => 'Cesta k dílčímu souboru', + 'property_partial_path_description' => 'Path to a partial file. Use the $ symbol to refer the plugins root directory, for example: $/acme/blog/partials/_partial.htm', + 'property_partial_path_required' => 'Prosím zadejte cestu k dílčímu souboru', + 'property_code_language' => 'Jazyk', + 'property_code_theme' => 'Téma', + 'property_theme_use_default' => 'Použít výchozí téma', + 'property_group_code_editor' => 'Editor kódu', + 'property_gutter' => 'Výplň', + 'property_gutter_show' => 'Viditelný', + 'property_gutter_hide' => 'Skrytý', + 'property_wordwrap' => 'Word wrap', + 'property_wordwrap_wrap' => 'Wrap', + 'property_wordwrap_nowrap' => 'Don\'t wrap', + 'property_fontsize' => 'Velikost písma', + 'property_codefolding' => 'Code folding', + 'property_codefolding_manual' => 'Manual', + 'property_codefolding_markbegin' => 'Mark begin', + 'property_codefolding_markbeginend' => 'Mark begin and end', + 'property_autoclosing' => 'Automatické zavírání', + 'property_enabled' => 'Aktivní', + 'property_disabled' => 'Neaktivní', + 'property_soft_tabs' => 'Soft tabs', + 'property_tab_size' => 'Velikost záložky', + 'property_readonly' => 'Pouze pro čtení', + 'property_use_default' => 'Use default settings', + 'property_options' => 'Volby', + 'property_prompt' => 'Prompt', + 'property_prompt_description' => 'Text to display for the create button.', + 'property_prompt_default' => 'Přidat nový prvek', + 'property_available_colors' => 'Dostupné barvy', + 'property_available_colors_description' => 'List of available colors in hex format (#FF0000). Leave empty for the default color set. Enter one value per line.', + 'property_datepicker_mode' => 'Mód', + 'property_datepicker_mode_date' => 'Datum', + 'property_datepicker_mode_datetime' => 'Datum a čas', + 'property_datepicker_mode_time' => 'Čas', + 'property_datepicker_min_date' => 'Min datum', + 'property_datepicker_max_date' => 'Max datum', + 'property_fileupload_mode' => 'Mód', + 'property_fileupload_mode_file' => 'Soubor', + 'property_fileupload_mode_image' => 'Obrázek', + 'property_group_fileupload' => 'Nahrávání obrázků', + 'property_fileupload_image_width' => 'Šířka obrázku', + 'property_fileupload_image_width_description' => 'Optional parameter - images will be resized to this width. Applies to Image mode only.', + 'property_fileupload_invalid_dimension' => 'Invalid dimension value - please enter a number.', + 'property_fileupload_image_height' => 'Výška obrázku', + 'property_fileupload_image_height_description' => 'Optional parameter - images will be resized to this height. Applies to Image mode only.', + 'property_fileupload_file_types' => 'Typy souborů', + 'property_fileupload_file_types_description' => 'Optional comma separated list of file extensions that are accepted by the uploader. Eg: zip,txt', + 'property_fileupload_mime_types' => 'MIME typy', + 'property_fileupload_mime_types_description' => 'Optional comma separated list of MIME types that are accepted by the uploader, either as file extensions or fully qualified names. Eg: bin,txt', + 'property_fileupload_use_caption' => 'Použít popisek', + 'property_fileupload_use_caption_description' => 'Allows a title and description to be set for the file.', + 'property_fileupload_thumb_options' => 'Volby náhledu', + 'property_fileupload_thumb_options_description' => 'Manages options for the automatically generated thumbnails. Applies only for the Image mode.', + 'property_fileupload_thumb_mode' => 'Mód', + 'property_fileupload_thumb_auto' => 'Auto', + 'property_fileupload_thumb_exact' => 'Přesně', + 'property_fileupload_thumb_portrait' => 'Portrét', + 'property_fileupload_thumb_landscape' => 'Krajina', + 'property_fileupload_thumb_crop' => 'Crop', + 'property_fileupload_thumb_extension' => 'Přípona souboru', + 'property_name_from' => 'Name column', + 'property_name_from_description' => 'Relation column name to use for displaying a name.', + 'property_description_from' => 'Description column', + 'property_description_from_description' => 'Relation column name to use for displaying a description.', + 'property_recordfinder_prompt' => 'Prompt', + 'property_recordfinder_prompt_description' => 'Text to display when there is no record selected. The %s character represents the search icon. Leave empty for the default prompt.', + 'property_recordfinder_list' => 'List configuration', + 'property_recordfinder_list_description' => 'A reference to a list column definition file. Use the $ symbol to refer the plugins root directory, for example: $/acme/blog/lists/_list.yaml', + 'property_recordfinder_list_required' => 'Please provide a path to the list YAML file', + 'property_group_recordfinder' => 'Record finder', + 'property_mediafinder_mode' => 'Mód', + 'property_mediafinder_mode_file' => 'Soubor', + 'property_mediafinder_mode_image' => 'Obrázek', + 'property_group_relation' => 'Relace', + 'property_relation_prompt' => 'Prompt', + 'property_relation_prompt_description' => 'Text to display when there is no available selections.', + 'control_group_standard' => 'Standardní', + 'control_group_widgets' => 'Widgets', + 'click_to_add_control' => 'Přidat prvek', + 'loading' => 'Načítám...', + 'control_text' => 'Text', + 'control_text_description' => 'Single line text box', + 'control_password' => 'Heslo', + 'control_password_description' => 'Single line password text field', + 'control_checkbox' => 'Checkbox', + 'control_checkbox_description' => 'Single checkbox', + 'control_switch' => 'Přepínač', + 'control_switch_description' => 'Single switchbox, an alternative for checkbox', + 'control_textarea' => 'Víceřádkové textové pole', + 'control_textarea_description' => 'Multiline text box with controllable height', + 'control_dropdown' => 'Dropdown', + 'control_dropdown_description' => 'Dropdown list with static or dynamic options', + 'control_unknown' => 'Unknown control type: :type', + 'control_repeater' => 'Repeater', + 'control_repeater_description' => 'Outputs a repeating set of form controls', + 'control_number' => 'Číslo', + 'control_number_description' => 'Single line text box that takes numbers only', + 'control_hint' => 'Hint', + 'control_hint_description' => 'Outputs a partial contents in a box that can be hidden by the user', + 'control_partial' => 'Partial', + 'control_partial_description' => 'Outputs a partial contents', + 'control_section' => 'Sekce', + 'control_section_description' => 'Displays a form section with heading and subheading', + 'control_radio' => 'Radio list', + 'control_radio_description' => 'A list of radio options, where only one item can be selected at a time', + 'control_radio_option_1' => 'Volba 1', + 'control_radio_option_2' => 'Volba 2', + 'control_checkboxlist' => 'Checkbox list', + 'control_checkboxlist_description' => 'A list of checkboxes, where multiple items can be selected', + 'control_codeeditor' => 'Editor kódu', + 'control_codeeditor_description' => 'Plaintext editor for formatted code or markup', + 'control_colorpicker' => 'Výběr barvy', + 'control_colorpicker_description' => 'A field for selecting a hexadecimal color value', + 'control_datepicker' => 'Výběr data', + 'control_datepicker_description' => 'Text field used for selecting date and times', + 'control_richeditor' => 'Rich editor', + 'control_richeditor_description' => 'Visual editor for rich formatted text, also known as a WYSIWYG editor', + 'control_markdown' => 'Markdown editor', + 'control_markdown_description' => 'Basic editor for Markdown formatted text', + 'control_fileupload' => 'Nahrávání souborů', + 'control_fileupload_description' => 'File uploader for images or regular files', + 'control_recordfinder' => 'Record finder', + 'control_recordfinder_description' => 'Field with details of a related record with the record search feature', + 'control_mediafinder' => 'Media finder', + 'control_mediafinder_description' => 'Field for selecting an item from the Media Manager library', + 'control_relation' => 'Relace', + 'control_relation_description' => 'Displays either a dropdown or checkbox list for selecting a related record', + 'error_file_name_required' => 'Please enter the form file name.', + 'error_file_name_invalid' => 'The file name can contain only Latin letters, digits, underscores, dots and hashes.', + 'span_left' => 'Doleva', + 'span_right' => 'Doprava', + 'span_full' => 'Plná šířka', + 'span_auto' => 'Automaticky', + 'empty_tab' => 'Prázdná záložka', + 'confirm_close_tab' => 'The tab contains controls which will be deleted. Continue?', + 'tab' => 'Form tab', + 'tab_title' => 'Název', + 'controls' => 'Prvky formuláře', + 'property_tab_title_required' => 'Název záložky je povinný.', + 'tabs_primary' => 'Primární záložka', + 'tabs_secondary' => 'Vedlejší záložka', + 'tab_stretch' => 'Stretch', + 'tab_stretch_description' => 'Specifies if this tabs container stretches to fit the parent height.', + 'tab_css_class' => 'CSS třída', + 'tab_css_class_description' => 'Přiřadí CSS třídu kontejneru záložky.', + 'tab_name_template' => 'Záložka %s', + 'tab_already_exists' => 'Záložka s tímto názvem již existuje.', + ], + 'list' => [ + 'tab_new_list' => 'Nový list', + 'saved' => 'List byl úspěšně uložen.', + 'confirm_delete' => 'Opravdu chcete smazat tento list?', + 'tab_columns' => 'Sloupce', + 'btn_add_column' => 'Přidat sloupec', + 'btn_delete_column' => 'Smazat sloupec', + 'column_dbfield_label' => 'Field', + 'column_dbfield_required' => 'Please enter the model field', + 'column_name_label' => 'Popisek', + 'column_label_required' => 'Zadejte prosím popisek sloupce', + 'column_type_label' => 'Type', + 'column_type_required' => 'Zadejte prosím typ sloupce', + 'column_type_text' => 'Text', + 'column_type_number' => 'Číslo', + 'column_type_switch' => 'Switch', + 'column_type_datetime' => 'Datum a čas', + 'column_type_date' => 'Datum', + 'column_type_time' => 'Čas', + 'column_type_timesince' => 'Čas od', + 'column_type_timetense' => 'Čas do', + 'column_type_select' => 'Select', + 'column_type_partial' => 'Partial', + 'column_label_default' => 'Výchozí', + 'column_label_searchable' => 'Vyhledávání', + 'column_label_sortable' => 'Řazení', + 'column_label_invisible' => 'Neviditelný', + 'column_label_select' => 'Výběr', + 'column_label_relation' => 'Relace', + 'column_label_css_class' => 'CSS class', + 'column_label_width' => 'Šířka', + 'column_label_path' => 'Cesta', + 'column_label_format' => 'Formát', + 'column_label_value_from' => 'Hodnota od', + 'error_duplicate_column' => 'Duplicitní pole sloupce: \':column\'.', + ], + 'controller' => [ + 'menu_label' => 'Kontroléry', + 'no_records' => 'Žádné kontrolery nebyly nalezeny', + 'controller' => 'Kontrolér', + 'behaviors' => 'Chování', + 'new_controller' => 'Nový kontrolér', + 'error_controller_has_no_behaviors' => 'The controller doesn\'t have configurable behaviors.', + 'error_invalid_yaml_configuration' => 'Error loading behavior configuration file: :file', + 'behavior_form_controller' => 'Možnost vytvářet a měnit záznamy', + 'behavior_form_controller_description' => 'Přidá možnost vytvářet a měnit záznamy pomocí formulářů. Toto chování vytvoří tři pohledy pro tvorbu položky, úpravu a náhled.', + 'property_behavior_form_placeholder' => '--vyberte formulář--', + 'property_behavior_form_name' => 'Název', + 'property_behavior_form_name_description' => 'The name of the object being managed by this form', + 'property_behavior_form_name_required' => 'Please enter the form name', + 'property_behavior_form_file' => 'Form configuration', + 'property_behavior_form_file_description' => 'Reference to a form field definition file', + 'property_behavior_form_file_required' => 'Please enter a path to the form configuration file', + 'property_behavior_form_model_class' => 'Modelová třída', + 'property_behavior_form_model_class_description' => 'A model class name, the form data is loaded and saved against this model.', + 'property_behavior_form_model_class_required' => 'Please select a model class', + 'property_behavior_form_default_redirect' => 'Výchozí přesměrování', + 'property_behavior_form_default_redirect_description' => 'A page to redirect to by default when the form is saved or cancelled.', + 'property_behavior_form_create' => 'Create record page', + 'property_behavior_form_redirect' => 'Přesměrování', + 'property_behavior_form_redirect_description' => 'A page to redirect to when a record is created.', + 'property_behavior_form_redirect_close' => 'Close redirect', + 'property_behavior_form_redirect_close_description' => 'A page to redirect to when a record is created and the close post variable is sent with the request.', + 'property_behavior_form_flash_save' => 'Save flash message', + 'property_behavior_form_flash_save_description' => 'Flash message to display when record is saved.', + 'property_behavior_form_page_title' => 'Page title', + 'property_behavior_form_update' => 'Update record page', + 'property_behavior_form_update_redirect' => 'Přesměrování', + 'property_behavior_form_create_redirect_description' => 'A page to redirect to when a record is saved.', + 'property_behavior_form_flash_delete' => 'Delete flash message', + 'property_behavior_form_flash_delete_description' => 'Flash message to display when record is deleted.', + 'property_behavior_form_preview' => 'Preview record page', + 'behavior_list_controller' => 'Možnost listování záznamy', + 'behavior_list_controller_description' => 'Vytvoří tabulku s řazením a vyhledávání s možností definovat odkaz na detail jednotlivého záznamu. Chování automaticky vytvoří akci kontroléru "index".', + 'property_behavior_list_title' => 'List title', + 'property_behavior_list_title_required' => 'Please enter the list title', + 'property_behavior_list_placeholder' => '--select list--', + 'property_behavior_list_model_class' => 'Modelová třída', + 'property_behavior_list_model_class_description' => 'A model class name, the list data is loaded from this model.', + 'property_behavior_form_model_class_placeholder' => '--select model--', + 'property_behavior_list_model_class_required' => 'Please select a model class', + 'property_behavior_list_model_placeholder' => '--select model--', + 'property_behavior_list_file' => 'List configuration file', + 'property_behavior_list_file_description' => 'Reference to a list definition file', + 'property_behavior_list_file_required' => 'Please enter a path to the list configuration file', + 'property_behavior_list_record_url' => 'Record URL', + 'property_behavior_list_record_url_description' => 'Link each list record to another page. Eg: users/update:id. The :id part is replaced with the record identifier.', + 'property_behavior_list_no_records_message' => 'No records message', + 'property_behavior_list_no_records_message_description' => 'A message to display when no records are found', + 'property_behavior_list_recs_per_page' => 'Records per page', + 'property_behavior_list_recs_per_page_description' => 'Records to display per page, use 0 for no pages. Default: 0', + 'property_behavior_list_recs_per_page_regex' => 'Records per page should be an integer value', + 'property_behavior_list_show_setup' => 'Show setup button', + 'property_behavior_list_show_sorting' => 'Show sorting', + 'property_behavior_list_default_sort' => 'Default sorting', + 'property_behavior_form_ds_column' => 'Column', + 'property_behavior_form_ds_direction' => 'Direction', + 'property_behavior_form_ds_asc' => 'Ascending', + 'property_behavior_form_ds_desc' => 'Descending', + 'property_behavior_list_show_checkboxes' => 'Show checkboxes', + 'property_behavior_list_onclick' => 'On click handler', + 'property_behavior_list_onclick_description' => 'Custom JavaScript code to execute when clicking on a record.', + 'property_behavior_list_show_tree' => 'Show tree', + 'property_behavior_list_show_tree_description' => 'Displays a tree hierarchy for parent/child records.', + 'property_behavior_list_tree_expanded' => 'Tree expanded', + 'property_behavior_list_tree_expanded_description' => 'Determines if tree nodes should be expanded by default.', + 'property_behavior_list_toolbar' => 'Toolbar', + 'property_behavior_list_toolbar_buttons' => 'Buttons partial', + 'property_behavior_list_toolbar_buttons_description' => 'Reference to a controller partial file with the toolbar buttons. Eg: list_toolbar', + 'property_behavior_list_search' => 'Search', + 'property_behavior_list_search_prompt' => 'Search prompt', + 'property_behavior_list_filter' => 'Filter configuration', + 'error_controller_not_found' => 'Original controller file is not found.', + 'error_invalid_config_file_name' => 'The behavior :class configuration file name (:file) contains invalid characters and cannot be loaded.', + 'error_file_not_yaml' => 'The behavior :class configuration file (:file) is not a YAML file. Only YAML configuration files are supported.', + 'saved' => 'Kontrolér byl úspěšně uložen.', + 'controller_name' => 'Název kontroléru', + 'controller_name_description' => 'Název kontroléru definuje název třídy a URL kontroléru v administraci. Použijte prosím standardní pojmenování PHP tříd - první symbol je velkým písmenem a zbytek normálně, například: Categories, Posts, Products.', + 'base_model_class' => 'Rodičovská třída', + 'base_model_class_description' => 'Vyberte třídu modelu ze které bude tento kontrolér dědit. Chování kontroléru můžete nastavit později.', + 'base_model_class_placeholder' => '--vyberte model--', + 'controller_behaviors' => 'Chování', + 'controller_behaviors_description' => 'Vyberte chování, které má kontrolér implementovat. Builder automaticky vytvoří požadované soubory.', + 'controller_permissions' => 'Oprávnění', + 'controller_permissions_description' => 'Vyberte uživatelská práva potřebná pro tento kontrolér. Práva můžete nastavit v sekci Oprávnění v levém menu. Toto nastavení můžete později změnit v PHP skriptu.', + 'controller_permissions_no_permissions' => 'Plugin nemá vytvořena žádná oprávnění.', + 'menu_item' => 'Aktivní položka menu', + 'menu_item_description' => 'Vyberte položku menu, která bude aktivní pro tento kontrolér. Toto nastavení můžete kdykoli změnit v PHP skriptu.', + 'menu_item_placeholder' => '--vyberte položku menu--', + 'error_unknown_behavior' => 'Třída chování :class není registrovaná v knihovně všech chování.', + 'error_behavior_view_conflict' => 'The selected behaviors provide conflicting views (:view) and cannot be used together in a controller.', + 'error_behavior_config_conflict' => 'The selected behaviors provide conflicting configuration files (:file) and cannot be used together in a controller.', + 'error_behavior_view_file_not_found' => 'View template :view of the behavior :class cannot be found.', + 'error_behavior_config_file_not_found' => 'Configuration template :file of the behavior :class cannot be found.', + 'error_controller_exists' => 'Controller file already exists: :file.', + 'error_controller_name_invalid' => 'Invalid controller name format. The name can only contain digits and Latin letters. The first symbol should be a capital Latin letter.', + 'error_behavior_view_file_exists' => 'Controller view file already exists: :view.', + 'error_behavior_config_file_exists' => 'Behavior configuration file already exists: :file.', + 'error_save_file' => 'Error saving controller file: :file', + 'error_behavior_requires_base_model' => 'Behavior :behavior requires a base model class to be selected.', + 'error_model_doesnt_have_lists' => 'The selected model doesn\'t have any lists. Please create a list first.', + 'error_model_doesnt_have_forms' => 'The selected model doesn\'t have any forms. Please create a form first.', + ], + 'version' => [ + 'menu_label' => 'Verze', + 'no_records' => 'Žádné verze pluginu', + 'search' => 'Vyhledávání...', + 'tab' => 'Verze', + 'saved' => 'Verze byla úspěšně uložena.', + 'confirm_delete' => 'Opravdu chcete smazat vybranou verzi?', + 'tab_new_version' => 'Nová verze', + 'migration' => 'Migraci', + 'seeder' => 'Seeder', + 'custom' => 'Novou verzi', + 'apply_version' => 'Aplikovat tuto verzi', + 'applying' => 'Aplikování verze...', + 'rollback_version' => 'Vrátit na tuto verzi', + 'rolling_back' => 'Vracení zpět...', + 'applied' => 'Verze byla úspěšně aplikována.', + 'rolled_back' => 'Verze byla úspěšně vrácena zpět.', + 'hint_save_unapplied' => 'Byla uložena neaplikovaná verze. Neaplikované verze mohou být automaticky aplikovány po přihlášení do administrace jakýmkoli uživatelem a nebo pokud je databázová tabulka uložena v sekci Databáze.', + 'hint_rollback' => 'Vracení verze zpět rovněž vrátí zpět všechny novější verze. Neaplikované verze mohou být automaticky aplikovány po přihlášení do administrace jakýmkoli uživatelem a nebo pokud je databázová tabulka uložena v sekci Databáze.', + 'hint_apply' => 'Vracení verze zpět rovněž vrátí zpět všechny starší neaplikované verze.', + 'dont_show_again' => 'Znovu nezobrazovat', + 'save_unapplied_version' => 'Uložit neaplikovanou verzi', + ], + 'menu' => [ + 'menu_label' => 'Menu administrace', + 'tab' => 'Menu', + 'items' => 'Položky menu', + 'saved' => 'Menu byla úspěšně uložena.', + 'add_main_menu_item' => 'Přidat položku menu', + 'new_menu_item' => 'Položka menu', + 'add_side_menu_item' => 'Přidat pod-položku', + 'side_menu_item' => 'Side menu item', + 'property_label' => 'Popisek', + 'property_label_required' => 'Zadejte prosím popisek položky menu.', + 'property_url_required' => 'Zadejte prosím URL položky menu.', + 'property_url' => 'URL', + 'property_icon' => 'Ikona', + 'property_icon_required' => 'Vyberte prosím ikonu', + 'property_permissions' => 'Oprávnění', + 'property_order' => 'Pořadí', + 'property_order_invalid' => 'Zadejte prosím pořadí položky menu jako číslo.', + 'property_order_description' => 'Pořadí položek určuje jejich posloupnost v menu. Pokud není pořadí zadáno, automaticky se umístí položka nakonec. Výchozí hodnoty pořadí jsou násobky 100.', + 'property_attributes' => 'HTML attributy', + 'property_code' => 'Kód', + 'property_code_invalid' => 'Kód položky může obsahovat pouze písmena a číslice', + 'property_code_required' => 'Zadejte prosím kód položky menu.', + 'error_duplicate_main_menu_code' => 'Kód položky hlavního menu je duplicitní: \':code\'.', + 'error_duplicate_side_menu_code' => 'Kód položky postranního menu je duplicitní: \':code\'.', + ], + 'localization' => [ + 'menu_label' => 'Lokalizace', + 'language' => 'Zkratka jazyka', + 'strings' => 'Řetězce', + 'confirm_delete' => 'Opravdu chcete smazat soubor s překladem?', + 'tab_new_language' => 'Nový jazyk', + 'no_records' => 'Žádné jazyky nenalezeny', + 'saved' => 'Soubor s překladem byl úspěšně uložen.', + 'error_cant_load_file' => 'Nepodařilo se načíst požadovaný soubor protože neexistuje.', + 'error_bad_localization_file_contents' => 'Nepodařilo se načíst požadovaný soubor. Soubory s překladem mohou obsahovat pouze pole definující překlady řetězců.', + 'error_file_not_array' => 'Nepodařilo se načíst požadovaný soubor. Překladový soubor musí vrátit pole.', + 'save_error' => 'Chyba ukládání souboru \':name\'. Zkontrolujte prosím práva k zápisu.', + 'error_delete_file' => 'Chyba mazání překladového souboru.', + 'add_missing_strings' => 'Přidat chybějící řetězce', + 'copy' => 'Kopírovat', + 'add_missing_strings_label' => 'Vyberte jazyk ze kterého se zkopírují chybějící řetězce', + 'no_languages_to_copy_from' => 'Nejsou definovány žádné jazyky ze kterých bychom mohli zkopírovat řetězce.', + 'new_string_warning' => 'Nový řetězec nebo sekce', + 'structure_mismatch' => 'Struktura zdrojového jazykového souboru neodpovídá struktuře editovaného souboru. Některé nezávislé řetězce v editovaném souboru odpovídají sekcím ve zdrojovém souboru (nebo naopak) a nemohou být automaticky sloučeny.', + 'create_string' => 'Vytvořit nový řetězec', + 'string_key_label' => 'Klíč řetězce', + 'string_key_comment' => 'Zadejte klíč řetězce s použitím tečky jako oddělovače, například: plugin.search. Řetězec bude vytvořen ve výchozím jazykovém souboru pluginu.', + 'string_value' => 'Hodnota řetězce', + 'string_key_is_empty' => 'Musíte vyplnit klíč řetězce', + 'string_value_is_empty' => 'Musíte vyplnit hodnotu řetězce', + 'string_key_exists' => 'Takový klíč řetězce již existuje', + ], + 'permission' => [ + 'menu_label' => 'Oprávnění', + 'tab' => 'Oprávnění', + 'form_tab_permissions' => 'Oprávnění', + 'btn_add_permission' => 'Přidat oprávnění', + 'btn_delete_permission' => 'Smazat oprávnění', + 'column_permission_label' => 'Kód oprávnění', + 'column_permission_required' => 'Zadejte prosím kód oprávnění', + 'column_tab_label' => 'Název záložky', + 'column_tab_required' => 'Zadejte prosím název záložky oprávnění', + 'column_label_label' => 'Popisek', + 'column_label_required' => 'Zadejte prosím popisek oprávnění', + 'saved' => 'Oprávnění bylo úspěšně uloženo.', + 'error_duplicate_code' => 'Kód oprávnění je duplicitní: \':code\'.', + ], + 'yaml' => [ + 'save_error' => 'Chyba ukládání souboru \':name\'. Zkontrolujte prosím práva k zápisu.', + ], + 'common' => [ + 'error_file_exists' => 'Soubor již existuje: \':path\'.', + 'field_icon_description' => 'October používá ikony Font Autumn: http://octobercms.com/docs/ui/icon', + 'destination_dir_not_exists' => 'Cílový adresář neexistuje: \':path\'.', + 'error_make_dir' => 'Chyba vytváření adresáře: \':name\'.', + 'error_dir_exists' => 'Adresář již existuje: \':path\'.', + 'template_not_found' => 'Soubor šablony nebyl nalezen: \':name\'.', + 'error_generating_file' => 'Chyba vytváření souboru: \':path\'.', + 'error_loading_template' => 'Chyba načtení souboru šablony: \':name\'.', + 'select_plugin_first' => 'Nejdříve vyberte plugin. Pro zobrazení všech pluginů klikněte na symbol > na vrchu levého menu.', + 'plugin_not_selected' => 'Není vybrán žádný plugin', + 'add' => 'Přidat', + ], + 'migration' => [ + 'entity_name' => 'Migrace', + 'error_version_invalid' => 'The version should be specified in format 1.0.1', + 'field_version' => 'Verze', + 'field_description' => 'Popis migrace', + 'field_code' => 'Kód migrace', + 'save_and_apply' => 'Uložit a aplikovat', + 'error_version_exists' => 'Tato verze migrace již existuje.', + 'error_script_filename_invalid' => 'The migration script file name can contain only Latin letters, digits and underscores. The name should start with a Latin letter and could not contain spaces.', + 'error_cannot_change_version_number' => 'Cannot change version number for an applied version.', + 'error_file_must_define_class' => 'Migration code should define a migration or seeder class. Leave the code field blank if you only want to update the version number.', + 'error_file_must_define_namespace' => 'Migration code should define a namespace. Leave the code field blank if you only want to update the version number.', + 'no_changes_to_save' => 'Žádné změny k uložení.', + 'error_namespace_mismatch' => 'Migrační kód by měl používat jmenný prostor pluginu: :namespace', + 'error_migration_file_exists' => 'Migrační soubor :file již existuje. Zadejte prosím jiný název třídy.', + 'error_cant_delete_applied' => 'This version has already been applied and cannot be deleted. Please rollback the version first.', + ], + 'components' => [ + 'list_title' => 'Record list', + 'list_description' => 'Displays a list of records for a selected model', + 'list_page_number' => 'Číslo stránky', + 'list_page_number_description' => 'This value is used to determine what page the user is on.', + 'list_records_per_page' => 'Records per page', + 'list_records_per_page_description' => 'Number of records to display on a single page. Leave empty to disable pagination.', + 'list_records_per_page_validation' => 'Invalid format of the records per page value. The value should be a number.', + 'list_no_records' => 'No records message', + 'list_no_records_description' => 'Message to display in the list in case if there are no records. Used in the default component\'s partial.', + 'list_no_records_default' => 'Žádné záznamy nebyly nalezeny', + 'list_sort_column' => 'Sort by column', + 'list_sort_column_description' => 'Model column the records should be ordered by', + 'list_sort_direction' => 'Směr', + 'list_display_column' => 'Display column', + 'list_display_column_description' => 'Column to display in the list. Used in the default component\'s partial.', + 'list_display_column_required' => 'Please select a display column.', + 'list_details_page' => 'Details page', + 'list_details_page_description' => 'Page to display record details.', + 'list_details_page_no' => '--no details page--', + 'list_sorting' => 'Řazení', + 'list_pagination' => 'Stránkování', + 'list_order_direction_asc' => 'Vzestupně', + 'list_order_direction_desc' => 'Sestupně', + 'list_model' => 'Modelová třída', + 'list_scope' => 'Scope', + 'list_scope_description' => 'Optional model scope to fetch the records', + 'list_scope_default' => '--select a scope, optional--', + 'list_details_page_link' => 'Link to the details page', + 'list_details_key_column' => 'Details key column', + 'list_details_key_column_description' => 'Model column to use as a record identifier in the details page links.', + 'list_details_url_parameter' => 'URL parameter name', + 'list_details_url_parameter_description' => 'Name of the details page URL parameter which takes the record identifier.', + 'details_title' => 'Record details', + 'details_description' => 'Displays record details for a selected model', + 'details_model' => 'Modelová třída', + 'details_identifier_value' => 'Identifier value', + 'details_identifier_value_description' => 'Identifier value to load the record from the database. Specify a fixed value or URL parameter name.', + 'details_identifier_value_required' => 'The identifier value is required', + 'details_key_column' => 'Key column', + 'details_key_column_description' => 'Model column to use as a record identifier for fetching the record from the database.', + 'details_key_column_required' => 'The key column name is required', + 'details_display_column' => 'Display column', + 'details_display_column_description' => 'Model column to display on the details page. Used in the default component\'s partial.', + 'details_display_column_required' => 'Please select a display column.', + 'details_not_found_message' => 'Not found message', + 'details_not_found_message_description' => 'Message to display if the record is not found. Used in the default component\'s partial.', + 'details_not_found_message_default' => 'Záznam nebyl nalezen', + ], +]; diff --git a/plugins/rainlab/builder/lang/en.json b/plugins/rainlab/builder/lang/en.json new file mode 100644 index 0000000..0827897 --- /dev/null +++ b/plugins/rainlab/builder/lang/en.json @@ -0,0 +1,6 @@ +{ + "Builder": "Builder", + "Provides visual tools for building October plugins.": "Provides visual tools for building October plugins.", + "Options Method": "Options Method", + "Request options from this method name defined on the model or as a static method (Class::method).": "Request options from this method name defined on the model or as a static method (Class::method)." +} \ No newline at end of file diff --git a/plugins/rainlab/builder/lang/en/lang.php b/plugins/rainlab/builder/lang/en/lang.php new file mode 100644 index 0000000..9659141 --- /dev/null +++ b/plugins/rainlab/builder/lang/en/lang.php @@ -0,0 +1,823 @@ + [ + 'add' => 'Create Plugin', + 'no_records' => 'No plugins found', + 'no_name' => 'No Name', + 'search' => 'Search...', + 'filter_description' => 'Display all plugins or only your plugins.', + 'settings' => 'Settings', + 'entity_name' => 'Plugin', + 'field_name' => 'Name', + 'field_author' => 'Author', + 'field_description' => 'Description', + 'field_icon' => 'Plugin Icon', + 'field_plugin_namespace' => 'Plugin Namespace', + 'field_author_namespace' => 'Author Namespace', + 'field_namespace_description' => 'Namespace can contain only Latin letters and digits and should start with a Latin letter. Example plugin namespace: Blog', + 'field_author_namespace_description' => 'You cannot change the namespaces with Builder after you create the plugin. Example author namespace: JohnSmith', + 'tab_general' => 'General Parameters', + 'tab_description' => 'Description', + 'field_homepage' => 'Plugin Homepage (URL)', + 'no_description' => 'No description provided for this plugin', + 'error_settings_not_editable' => 'Settings of this plugin cannot be edited with Builder.', + 'update_hint' => 'You can edit localized plugin\'s name and description on the Localization tab.', + 'manage_plugins' => 'Create and edit plugins', + ], + 'author_name' => [ + 'title' => 'Author Name', + 'description' => 'Default author name to use for your new plugins. The author name is not fixed - you can change it in the plugins configuration at any time.', + ], + 'author_namespace' => [ + 'title' => 'Author Namespace', + 'description' => 'If you develop for the Marketplace, the namespace should match the author code and cannot be changed. Refer to the documentation for details.', + ], + 'config' => [ + 'use_table_comments_label' => 'Include Table Comments', + 'use_table_comments_comment' => 'Show comment field when defining table columns.', + ], + 'database' => [ + 'menu_label' => 'Database', + 'no_records' => 'No tables found', + 'search' => 'Search...', + 'confirmation_delete_multiple' => 'Delete the selected tables?', + 'field_name' => 'Table Name', + 'tab_columns' => 'Columns', + 'column_name_name' => 'Column', + 'column_name_required' => 'Please provide the column name', + 'column_name_type' => 'Type', + 'column_type_required' => 'Please select the column type', + 'column_name_length' => 'Length', + 'column_validation_length' => 'The Length value should be integer or specified as precision and scale (10,2) for decimal columns. Spaces are not allowed in the length column.', + 'column_validation_title' => 'Only digits, lower-case Latin letters and underscores are allowed in column names', + 'column_name_unsigned' => 'Unsigned', + 'column_name_nullable' => 'Nullable', + 'column_auto_increment' => 'AUTOINCR', + 'column_default' => 'Default', + 'column_comment' => 'Comment', + 'column_auto_primary_key' => 'PK', + 'tab_new_table' => 'New Table', + 'btn_add_column' => 'Add Column', + 'btn_delete_column' => 'Delete Column', + 'btn_add_id' => 'Add ID', + 'btn_add_timestamps' => 'Add Timestamps', + 'btn_add_soft_deleting' => 'Add Soft Deletes', + 'id_exists' => 'ID column already exists in the table.', + 'timestamps_exist' => 'created_at and deleted_at columns already exist in the table.', + 'soft_deleting_exist' => 'deleted_at column already exists in the table.', + 'confirm_delete' => 'Delete the table?', + 'error_enum_not_supported' => 'The table contains column(s) with type "enum" which is not currently supported by the Builder.', + 'error_table_name_invalid_prefix' => 'Table name should start with the plugin prefix: \':prefix\'.', + 'error_table_name_invalid_characters' => 'Invalid table name. Table names should contain only Latin letters, digits and underscores. Names should start with a Latin letter and could not contain spaces.', + 'error_table_duplicate_column' => 'Duplicate column name: \':column\'.', + 'error_table_auto_increment_in_compound_pk' => 'An auto-increment column cannot be a part of a compound primary key.', + 'error_table_mutliple_auto_increment' => 'The table cannot contain multiple auto-increment columns.', + 'error_table_auto_increment_non_integer' => 'Auto-increment columns should have integer type.', + 'error_table_decimal_length' => 'The Length parameter for :type type should be in format \'10,2\', without spaces.', + 'error_table_length' => 'The Length parameter for :type type should be specified as integer.', + 'error_unsigned_type_not_int' => 'Error in the \':column\' column. The Unsigned flag can be applied only to integer type columns.', + 'error_integer_default_value' => 'Invalid default value for the integer column \':column\'. The allowed formats are \'10\', \'-10\'.', + 'error_decimal_default_value' => 'Invalid default value for the decimal or double column \':column\'. The allowed formats are \'1.00\', \'-1.00\'.', + 'error_boolean_default_value' => 'Invalid default value for the boolean column \':column\'. The allowed values are \'0\' and \'1\', or \'true\' and \'false\'.', + 'error_unsigned_negative_value' => 'The default value for the unsigned column \':column\' can\'t be negative.', + 'error_table_already_exists' => 'The table \':name\' already exists in the database.', + 'error_table_name_too_long' => 'The table name should not be longer than 64 characters.', + 'error_column_name_too_long' => 'The column name \':column\' is too long. Column names should not be longer than 64 characters.', + ], + 'model' => [ + 'menu_label' => 'Models', + 'entity_name' => 'Model', + 'no_records' => 'No models found', + 'search' => 'Search...', + 'add' => 'Add...', + 'forms' => 'Forms', + 'lists' => 'Lists', + 'field_class_name' => 'Class Name', + 'field_database_table' => 'Database Table', + 'field_add_timestamps' => 'Add Timestamp Support', + 'field_add_timestamps_description' => 'The database table must have created_at and updated_at columns.', + 'field_add_soft_deleting' => 'Add Soft Deletes', + 'field_add_soft_deleting_description' => 'The database table must have deleted_at column.', + 'error_class_name_exists' => 'Model file already exists for the specified class name: :path', + 'error_timestamp_columns_must_exist' => 'The database table must have created_at and updated_at columns.', + 'error_deleted_at_column_must_exist' => 'The database table must have deleted_at column.', + 'add_form' => 'Add Form', + 'add_list' => 'Add List', + ], + 'form' => [ + 'saved' => 'Form saved', + 'confirm_delete' => 'Delete the form?', + 'tab_new_form' => 'New Form', + 'btn_add_database_fields' => 'Add Database Fields', + 'property_label_title' => 'Label', + 'property_label_required' => 'Please specify the control label.', + 'property_span_title' => 'Span', + 'property_comment_title' => 'Comment', + 'property_comment_above_title' => 'Comment Above', + 'property_default_title' => 'Default', + 'property_checked_default_title' => 'Checked by Default', + 'property_css_class_title' => 'CSS Class', + 'property_css_class_description' => 'Optional CSS class to assign to the field container.', + 'property_disabled_title' => 'Disabled', + 'property_read_only_title' => 'Read Only', + 'property_hidden_title' => 'Hidden', + 'property_required_title' => 'Required', + 'property_field_name_title' => 'Field Name', + 'property_placeholder_title' => 'Placeholder', + 'property_default_from_title' => 'Default From', + 'property_stretch_title' => 'Stretch', + 'property_stretch_description' => 'Specifies if this field stretches to fit the parent height.', + 'property_context_title' => 'Context', + 'property_context_description' => 'Specifies what form context should be used when displaying the field.', + 'property_context_create' => 'Create', + 'property_context_update' => 'Update', + 'property_context_preview' => 'Preview', + 'property_dependson_title' => 'Depends On', + 'property_trigger_action' => 'Action', + 'property_trigger_show' => 'Show', + 'property_trigger_hide' => 'Hide', + 'property_trigger_enable' => 'Enable', + 'property_trigger_disable' => 'Disable', + 'property_trigger_empty' => 'Empty', + 'property_trigger_field' => 'Field', + 'property_trigger_field_description' => 'Defines the other field name that will trigger the action.', + 'property_trigger_condition' => 'Condition', + 'property_trigger_condition_description' => 'Determines the condition the specified field should satisfy for the condition to be considered "true". Supported values: checked, unchecked, value[somevalue].', + 'property_trigger_condition_checked' => 'Checked', + 'property_trigger_condition_unchecked' => 'Unchecked', + 'property_trigger_condition_somevalue' => 'value[enter-the-value-here]', + 'property_preset_title' => 'Preset', + 'property_preset_description' => 'Allows the field value to be initially set by the value of another field, converted using the input preset converter.', + 'property_preset_field' => 'Field', + 'property_preset_field_description' => 'Defines the other field name to source the value from.', + 'property_preset_type' => 'Type', + 'property_preset_type_description' => 'Specifies the conversion type', + 'property_attributes_title' => 'Attributes', + 'property_attributes_description' => 'Custom HTML attributes to add to the form field element.', + 'property_container_attributes_title' => 'Container Attributes', + 'property_container_attributes_description' => 'Custom HTML attributes to add to the form field container element.', + 'property_group_advanced' => 'Advanced', + 'property_dependson_description' => 'A list of other field names this field depends on, when the other fields are modified, this field will update. One field per line.', + 'property_trigger_title' => 'Trigger', + 'property_trigger_description' => 'Allows to change elements attributes such as visibility or value, based on another elements\' state.', + 'property_default_from_description' => 'Takes the default value from the value of another field.', + 'property_field_name_required' => 'The field name is required', + 'property_field_name_regex' => 'The field name can contain only Latin letters, digits, underscores, dashes and square brackets.', + 'property_attributes_size' => 'Size', + 'property_attributes_size_tiny' => 'Tiny', + 'property_attributes_size_small' => 'Small', + 'property_attributes_size_large' => 'Large', + 'property_attributes_size_huge' => 'Huge', + 'property_attributes_size_giant' => 'Giant', + 'property_comment_position' => 'Comment Position', + 'property_comment_position_above' => 'Above', + 'property_comment_position_below' => 'Below', + 'property_hint_path' => 'Partial Path', + 'property_hint_path_description' => 'Path to a partial file that contains the hint text. Use the $ symbol to refer the plugins root directory, for example: $/acme/blog/partials/_hint.php', + 'property_hint_path_required' => 'Please enter the hint partial path', + 'property_partial_path' => 'Partial path', + 'property_partial_path_description' => 'Path to a partial file. Use the $ symbol to refer the plugins root directory, for example: $/acme/blog/partials/_partial.php', + 'property_partial_path_required' => 'Please enter the partial path', + 'property_code_language' => 'Language', + 'property_code_theme' => 'Theme', + 'property_theme_use_default' => 'Use Default Theme', + 'property_group_code_editor' => 'Code Editor', + 'property_gutter' => 'Gutter', + 'property_gutter_show' => 'Visible', + 'property_gutter_hide' => 'Hidden', + 'property_wordwrap' => 'Word Wrap', + 'property_wordwrap_wrap' => 'Wrap', + 'property_wordwrap_nowrap' => 'Don\'t wrap', + 'property_fontsize' => 'Font Size', + 'property_codefolding' => 'Code Folding', + 'property_codefolding_manual' => 'Manual', + 'property_codefolding_markbegin' => 'Mark Begin', + 'property_codefolding_markbeginend' => 'Mark Begin and End', + 'property_autoclosing' => 'Auto Closing', + 'property_enabled' => 'Enabled', + 'property_disabled' => 'Disabled', + 'property_soft_tabs' => 'Soft tabs', + 'property_tab_size' => 'Tab size', + 'property_readonly' => 'Read only', + 'property_use_default' => 'Use default settings', + 'property_options' => 'Options', + 'property_options_method' => 'Options Method', + 'property_options_method_description' => 'Request options from this method name defined on the model or as a static method (Class::method).', + 'property_prompt' => 'Prompt', + 'property_prompt_description' => 'Text to display for the create button.', + 'property_prompt_default' => 'Add new item', + 'property_datepicker_mode' => 'Mode', + 'property_datepicker_mode_date' => 'Date', + 'property_datepicker_mode_datetime' => 'Date and Time', + 'property_datepicker_mode_time' => 'Time', + 'property_datepicker_min_date' => 'Min Date', + 'property_datepicker_min_date_description' => 'The minimum/earliest date that can be selected. This may be any string accepted by Carbon. Leave empty for no minimum date.', + 'property_datepicker_max_date' => 'Max Date', + 'property_datepicker_max_date_description' => 'The maximum/latest date that can be selected. This may be any string accepted by Carbon. Leave empty for no maximum date.', + 'property_datepicker_year_range' => 'Year Range', + 'property_datepicker_year_range_description' => 'Number of years either side (eg 10) or array of upper/lower range (eg [1900,2015]). Leave empty for the default value (10).', + 'property_datepicker_year_range_invalid_format' => 'Invalid year range format. Use number (eg "10") or array of upper/lower range (eg "[1900,2015]")', + 'property_datepicker_first_day' => 'First Day', + 'property_datepicker_first_day_description' => 'First day of the week (0 - 7) where 0 is Sunday.', + 'property_datepicker_first_day_regex' => 'First day must be a number', + 'property_datepicker_twelve_hour' => 'Twelve Hour', + 'property_datepicker_twelve_hour_description' => 'Display a 12-hour clock for selecting time.', + 'property_datepicker_show_week_number' => 'Show Week Number', + 'property_datepicker_show_week_number_description' => 'Show week numbers at head of row.', + 'property_datepicker_format' => 'Format', + 'property_datepicker_year_format_description' => 'Define a custom date format. The default format is "Y-m-d"', + 'property_fileupload_mode' => 'Mode', + 'property_fileupload_mode_file' => 'File', + 'property_fileupload_mode_image' => 'Image', + 'property_group_fileupload' => 'File Upload', + 'property_fileupload_image_width' => 'Image width', + 'property_fileupload_image_width_description' => 'Optional parameter - images will be resized to this width. Applies to Image mode only.', + 'property_fileupload_invalid_dimension' => 'Invalid dimension value - please enter a number.', + 'property_fileupload_image_height' => 'Image height', + 'property_fileupload_image_height_description' => 'Optional parameter - images will be resized to this height. Applies to Image mode only.', + 'property_fileupload_file_types' => 'File types', + 'property_fileupload_file_types_description' => 'Optional comma separated list of file extensions that are accepted by the uploader. Eg: zip,txt', + 'property_fileupload_mime_types' => 'MIME types', + 'property_fileupload_maxfilesize' => 'Max file size', + 'property_fileupload_maxfilesize_description' => 'File size in Mb that are accepted by the uploader, optional.', + 'property_fileupload_invalid_maxfilesize' => 'Invalid Max file size value', + 'property_fileupload_maxfiles' => 'Max files', + 'property_fileupload_invalid_maxfiles' => 'Invalid Max files value', + 'property_fileupload_maxfiles_description' => 'Maximum number of files allowed to be uploaded', + 'property_fileupload_mime_types_description' => 'Optional comma separated list of MIME types that are accepted by the uploader, either as file extensions or fully qualified names. Eg: bin,txt', + 'property_fileupload_use_caption' => 'Use caption', + 'property_fileupload_use_caption_description' => 'Allows a title and description to be set for the file.', + 'property_fileupload_thumb_options' => 'Thumbnail options', + 'property_fileupload_thumb_options_description' => 'Manages options for the automatically generated thumbnails. Applies only for the Image mode.', + 'property_fileupload_thumb_mode' => 'Mode', + 'property_fileupload_thumb_auto' => 'Auto', + 'property_fileupload_thumb_exact' => 'Exact', + 'property_fileupload_thumb_portrait' => 'Portrait', + 'property_fileupload_thumb_landscape' => 'Landscape', + 'property_fileupload_thumb_crop' => 'Crop', + 'property_fileupload_thumb_extension' => 'File extension', + 'property_name_from' => 'Name column', + 'property_name_from_description' => 'Relation column name to use for displaying a name.', + 'property_relation_select' => 'Select', + 'property_relation_select_description' => 'CONCAT multiple columns together for displaying a name', + 'property_relation_scope' => 'Scope', + 'property_relation_scope_description' => 'Specifies a query scope method that\'s defined in the related form model to always apply to the list query.', + 'property_description_from' => 'Description Column', + 'property_description_from_description' => 'Relation column name to use for displaying a description.', + 'property_recordfinder_title' => 'Prompt', + 'property_recordfinder_title_description' => 'Text to display in the title section of the popup.', + 'property_recordfinder_list' => 'List Configuration', + 'property_recordfinder_list_description' => 'A reference to a list column definition file. Use the $ symbol to refer the plugins root directory, for example: $/acme/blog/lists/_list.yaml', + 'property_recordfinder_list_required' => 'Please provide a path to the list YAML file', + 'property_group_recordfinder' => 'Record Finder', + 'property_mediafinder_mode' => 'Mode', + 'property_mediafinder_mode_file' => 'File', + 'property_mediafinder_mode_image' => 'Image', + 'property_mediafinder_image_width_description' => 'If using image type, the preview image will be displayed to this width, optional.', + 'property_mediafinder_image_height_description' => 'If using image type, the preview image will be displayed to this height, optional.', + 'property_group_sensitive' => 'Sensitive', + 'property_group_taglist' => 'Tag List', + 'property_taglist_mode' => 'Mode', + 'property_taglist_mode_description' => 'Defines the format that this field\'s value is returned as', + 'property_taglist_mode_string' => 'String', + 'property_taglist_mode_array' => 'Array', + 'property_taglist_mode_relation' => 'Relation', + 'property_taglist_separator' => 'Separator', + 'property_taglist_separator_comma' => 'Commas', + 'property_taglist_separator_space' => 'Spaces', + 'property_taglist_options' => 'Predefined Tags', + 'property_taglist_custom_tags' => 'Custom Tags', + 'property_taglist_custom_tags_description' => 'Allow custom tags to be entered manually by the user.', + 'property_taglist_name_from' => 'Name From', + 'property_taglist_name_from_description' => 'Defines the relation model attribute displayed in the tag. Only used in "relation" mode.', + 'property_taglist_use_key' => 'Use Key', + 'property_taglist_use_key_description' => 'If checked, the tag list will use the key instead of the value for saving and reading data. Only used in "relation" mode.', + 'property_group_relation' => 'Relation', + 'property_relation_prompt' => 'Prompt', + 'property_relation_prompt_description' => 'Text to display when there is no available selections.', + 'property_empty_option' => 'Empty Option', + 'property_empty_option_description' => 'The empty option corresponds to the empty selection, but unlike the placeholder it can be reselected.', + 'property_show_search' => 'Show Search', + 'property_show_search_description' => 'Enables the search feature for this dropdown.', + 'property_title_from' => 'Title From', + 'property_title_from_description' => 'Specify a child field name to use the value of that field as the title for each repeater item.', + 'property_min_items' => 'Min Items', + 'property_min_items_description' => 'Minimum number of items that can be selected.', + 'property_min_items_integer' => 'Min items must be a positive integer.', + 'property_max_items' => 'Max Items', + 'property_max_items_description' => 'Maximum number of items that can be selected.', + 'property_max_items_integer' => 'Max items must be a positive integer.', + 'property_display_mode' => 'Display Mode', + 'property_display_mode_description' => 'Defines the display mode visually.', + 'control_group_standard' => 'Standard', + 'control_group_widgets' => 'Widgets', + 'control_group_ui' => 'UI', + 'click_to_add_control' => 'Add control', + 'loading' => 'Loading...', + 'control_text' => 'Text', + 'control_text_description' => 'Single line text box', + 'control_email' => 'Email', + 'control_email_description' => 'Single line text box that takes email addresses only', + 'control_password' => 'Password', + 'control_password_description' => 'Single line password text field', + 'control_checkbox' => 'Checkbox', + 'control_checkbox_description' => 'Single checkbox', + 'control_switch' => 'Switch', + 'control_switch_description' => 'Single light switch input, an alternative for checkbox', + 'control_textarea' => 'Text Area', + 'control_textarea_description' => 'Multiline text box with controllable height', + 'control_dropdown' => 'Dropdown', + 'control_dropdown_description' => 'Dropdown list with static or dynamic options', + 'control_balloon-selector' => 'Balloon Selector', + 'control_balloon-selector_description' => 'List where only one item can be selected at a time with static or dynamic options', + 'control_unknown' => 'Unknown control type: :type', + 'control_repeater' => 'Repeater', + 'control_repeater_description' => 'Outputs a repeating set of form controls', + 'property_repeater_show_reorder' => 'Show Reorder', + 'property_repeater_show_reorder_description' => 'Displays an interface for sorting items.', + 'property_repeater_show_duplicate' => 'Show Duplicate', + 'property_repeater_show_duplicate_description' => 'Displays an interface for cloning items.', + 'control_nestedform' => 'Nested Form', + 'control_nestedform_description' => 'Outputs a nested set of form controls', + 'property_nestedform_show_panel' => 'Show Panel', + 'property_nestedform_show_panel_description' => 'Places the form inside a panel container.', + 'property_nestedform_default_create' => 'Default Create', + 'property_nestedform_default_create_description' => 'If a related record is not found, attempt to create one.', + 'control_number' => 'Number', + 'control_number_description' => 'Single line text box that takes numbers only', + 'property_min' => 'Minimum', + 'property_min_description' => 'The client-side minimum value.', + 'property_min_number' => 'Minimum must be a number', + 'property_max' => 'Maximum', + 'property_max_description' => 'The client-side maximum value.', + 'property_max_number' => 'Maximum must be a number', + 'property_step' => 'Step', + 'property_step_description' => 'The client-side step increment.', + 'property_step_number' => 'Step must be a number', + 'control_hint' => 'Hint', + 'control_hint_description' => 'Outputs a partial contents in a box that can be hidden by the user', + 'control_partial' => 'Partial', + 'control_partial_description' => 'Outputs a partial contents', + 'control_section' => 'Section', + 'control_section_description' => 'Displays a form section with heading and subheading', + 'control_ruler' => 'Horizontal Rule', + 'control_ruler_description' => 'Displays a a horizontal rule to break up the contents', + 'control_radio' => 'Radio List', + 'control_radio_description' => 'A list of radio options, where only one item can be selected at a time', + 'control_radio_option_1' => 'Option 1', + 'control_radio_option_2' => 'Option 2', + 'control_checkboxlist' => 'Checkbox List', + 'control_checkboxlist_description' => 'A list of checkboxes, where multiple items can be selected', + 'property_quickselect' => 'Quick Select', + 'property_quickselect_description' => 'Show the quick selection buttons.', + 'property_inline_options' => 'Inline Options', + 'property_inline_options_description' => 'Display the options side-by-side instead of stacked, when less than 10 options.', + 'control_codeeditor' => 'Code Editor', + 'control_codeeditor_description' => 'Plaintext editor for formatted code or markup', + 'control_colorpicker' => 'Color Picker', + 'control_colorpicker_description' => 'A field for selecting a hexadecimal color value', + 'property_group_colorpicker' => 'Color Picker', + 'property_available_colors' => 'Available Colors', + 'property_available_colors_description' => 'List of available colors in hex format (#FF0000). Leave empty for the default color set. Enter one value per line.', + 'property_allow_empty' => 'Allow Empty', + 'property_allow_empty_description' => 'Allow empty input values.', + 'property_allow_custom' => 'Allow Custom', + 'property_allow_custom_description' => 'Allow selection of a custom color.', + 'property_show_alpha' => 'Show Alpha', + 'property_show_alpha_description' => 'Displays an opacity slider and sets an 8-digit hex code.', + 'property_show_input' => 'Show Input', + 'property_show_input_description' => 'Displays a text input next to the color picker and disables available colors.', + 'control_datatable' => 'Data Table', + 'control_datatable_description' => 'Renders an editable table of records, formatted as a grid', + 'property_group_datatable' => 'Data Table', + 'property_columns' => 'Columns', + 'property_columns_description' => 'Column configuration for the table', + 'property_datatable_type' => 'Type', + 'property_datatable_code' => 'Code', + 'property_datatable_code_regex' => 'A unique code is required for the column', + 'property_datatable_title' => 'Title', + 'property_datatable_width' => 'Width', + 'property_datatable_width_regex' => 'Width must be a number in pixels', + 'property_datatable_adding' => 'Allow Adding', + 'property_datatable_adding_description' => 'Allow records to be added.', + 'property_datatable_deleting' => 'Allow Adding', + 'property_datatable_deleting_description' => 'Allow records to be deleted.', + 'property_datatable_searching' => 'Searching', + 'property_datatable_searching_description' => 'Allow records to be searched.', + 'control_datepicker' => 'Date Picker', + 'control_datepicker_description' => 'Text field used for selecting date and times', + 'property_group_datepicker' => 'Date Picker', + 'control_richeditor' => 'Rich Editor', + 'control_richeditor_description' => 'Visual editor for rich formatted text, also known as a WYSIWYG editor', + 'control_pagefinder' => 'Page Finder', + 'control_pagefinder_description' => 'Renders a field for selecting a page link', + 'property_pagefinder_single_mode' => 'Single Mode', + 'property_pagefinder_single_mode_description' => 'Only allows items to be selected that resolve to a single URL.', + 'control_sensitive' => 'Sensitive', + 'control_sensitive_description' => 'Renders a revealable password field that can be used for sensitive information, such as API keys or secrets.', + 'allow_copy' => 'Allow Copy', + 'allow_copy_description' => 'Adds a copy action to the field, allowing the user to copy the password without revealing it.', + 'hidden_placeholder' => 'Hidden Placeholder', + 'hidden_placeholder_description' => 'Sets a placeholder string to emulate the unrevealed value. You can change this to a long or short string to emulate a different length.', + 'hide_on_tab_change' => 'Hide on Tab Change', + 'hide_on_tab_change_description' => 'Hides the field again if the user navigates to a different tab.', + 'property_group_rich_editor' => 'Rich Editor', + 'property_richeditor_toolbar_buttons' => 'Toolbar Buttons', + 'property_richeditor_toolbar_buttons_description' => 'Which buttons to show on the editor toolbar.', + 'control_markdown' => 'Markdown Editor', + 'control_markdown_description' => 'Basic editor for Markdown formatted text', + 'property_side_by_side' => 'Side By Side', + 'property_side_by_side_description' => 'Enables the side-by-side display mode by default', + 'control_taglist' => 'Tag List', + 'control_taglist_description' => 'Field for inputting a list of tags', + 'control_fileupload' => 'File Upload', + 'control_fileupload_description' => 'File uploader for images or regular files', + 'control_recordfinder' => 'Record Finder', + 'control_recordfinder_description' => 'Field with details of a related record with the record search feature', + 'control_mediafinder' => 'Media Finder', + 'control_mediafinder_description' => 'Field for selecting an item from the Media Manager library', + 'control_relation' => 'Relation', + 'control_relation_description' => 'Displays either a dropdown or checkbox list for selecting a related record', + 'control_widget_type' => 'Widget Type', + 'error_file_name_required' => 'Please enter the form file name.', + 'error_file_name_invalid' => 'The file name can contain only Latin letters, digits, underscores, dots and hashes.', + 'span_left' => 'Left', + 'span_right' => 'Right', + 'span_full' => 'Full', + 'span_auto' => 'Auto', + 'class_mode_tip' => 'Tip', + 'class_mode_info' => 'Info', + 'class_mode_warning' => 'Warning', + 'class_mode_danger' => 'Danger', + 'class_mode_success' => 'Success', + 'display_mode_builder' => 'Builder', + 'display_mode_accordion' => 'Accordion', + 'empty_tab' => 'Empty tab', + 'confirm_close_tab' => 'The tab contains controls which will be deleted. Continue?', + 'tab' => 'Form tab', + 'tab_title' => 'Title', + 'controls' => 'Controls', + 'property_tab_title_required' => 'The tab title is required.', + 'tabs_primary' => 'Primary tabs', + 'tabs_secondary' => 'Secondary tabs', + 'tab_stretch' => 'Stretch', + 'tab_stretch_description' => 'Specifies if this tabs container stretches to fit the parent height.', + 'tab_css_class' => 'CSS class', + 'tab_css_class_description' => 'Assigns a CSS class to the tabs container.', + 'tab_name_template' => 'Tab %s', + 'tab_already_exists' => 'Tab with the specified title already exists.', + ], + 'list' => [ + 'tab_new_list' => 'New List', + 'saved' => 'List saved', + 'confirm_delete' => 'Delete the list?', + 'tab_columns' => 'Columns', + 'btn_add_column' => 'Add Column', + 'btn_delete_column' => 'Delete Column', + 'column_dbfield_label' => 'Field', + 'column_dbfield_required' => 'Please enter the model field', + 'column_name_label' => 'Label', + 'column_label_required' => 'Please provide the column label', + 'column_type_label' => 'Type', + 'column_type_required' => 'Please provide the column type', + 'column_type_text' => 'Text', + 'column_type_number' => 'Number', + 'column_type_switch' => 'Switch', + 'column_type_datetime' => 'Datetime', + 'column_type_date' => 'Date', + 'column_type_time' => 'Time', + 'column_type_timesince' => 'Time Since', + 'column_type_timetense' => 'Time Tense', + 'column_type_select' => 'Select', + 'column_type_partial' => 'Partial', + 'column_label_default' => 'Default', + 'column_label_searchable' => 'Search', + 'column_label_sortable' => 'Sort', + 'column_label_invisible' => 'Invisible', + 'column_label_select' => 'Select', + 'column_label_relation' => 'Relation', + 'column_label_css_class' => 'CSS Class', + 'column_label_width' => 'Width', + 'column_label_path' => 'Path', + 'column_label_format' => 'Format', + 'column_label_value_from' => 'Value From', + 'error_duplicate_column' => 'Duplicate column field name: \':column\'.', + 'btn_add_database_columns' => 'Add Database Columns', + 'all_database_columns_exist' => 'All database columns are already defined in the list', + ], + 'controller' => [ + 'menu_label' => 'Controllers', + 'no_records' => 'No plugin controllers found', + 'controller' => 'Controller', + 'behaviors' => 'Behaviors', + 'new_controller' => 'New Controller', + 'error_controller_has_no_behaviors' => 'The controller doesn\'t have configurable behaviors.', + 'error_invalid_yaml_configuration' => 'Error loading behavior configuration file: :file', + 'behavior_form_controller' => 'Form Controller Behavior', + 'behavior_form_controller_description' => 'Adds form functionality to a back-end page. The behavior provides three pages called Create, Update and Preview.', + 'property_behavior_form_placeholder' => '--select form--', + 'property_behavior_form_name' => 'Name', + 'property_behavior_form_name_description' => 'The name of the object being managed by this form', + 'property_behavior_form_name_required' => 'Please enter the form name', + 'property_behavior_form_file' => 'Form Configuration', + 'property_behavior_form_file_description' => 'Reference to a form field definition file', + 'property_behavior_form_file_required' => 'Please enter a path to the form configuration file', + 'property_behavior_form_model_class' => 'Model Class', + 'property_behavior_form_model_class_description' => 'A model class name, the form data is loaded and saved against this model.', + 'property_behavior_form_model_class_required' => 'Please select a model class', + 'property_behavior_form_default_redirect' => 'Default Redirect', + 'property_behavior_form_default_redirect_description' => 'A page to redirect to by default when the form is saved or cancelled.', + 'property_behavior_form_create' => 'Create Record Page', + 'property_behavior_form_redirect' => 'Redirect', + 'property_behavior_form_redirect_description' => 'A page to redirect to when a record is created.', + 'property_behavior_form_redirect_close' => 'Close Redirect', + 'property_behavior_form_redirect_close_description' => 'A page to redirect to when a record is created and the close post variable is sent with the request.', + 'property_behavior_form_flash_save' => 'Save Flash Message', + 'property_behavior_form_flash_save_description' => 'Flash message to display when record is saved.', + 'property_behavior_form_page_title' => 'Page Title', + 'property_behavior_form_update' => 'Update Record Page', + 'property_behavior_form_update_redirect' => 'Redirect', + 'property_behavior_form_create_redirect_description' => 'A page to redirect to when a record is saved.', + 'property_behavior_form_flash_delete' => 'Delete Flash Message', + 'property_behavior_form_flash_delete_description' => 'Flash message to display when record is deleted.', + 'property_behavior_form_preview' => 'Preview Record Page', + 'behavior_list_controller' => 'List Controller Behavior', + 'behavior_list_controller_description' => 'Provides the sortable and searchable list with optional links on its records. The behavior automatically creates the controller action "index".', + 'property_behavior_list_title' => 'List Title', + 'property_behavior_list_title_required' => 'Please enter the list title', + 'property_behavior_list_placeholder' => '--select list--', + 'property_behavior_list_model_class' => 'Model Class', + 'property_behavior_list_model_class_description' => 'A model class name, the list data is loaded from this model.', + 'property_behavior_form_model_class_placeholder' => '--select model--', + 'property_behavior_list_model_class_required' => 'Please select a model class', + 'property_behavior_list_model_placeholder' => '--select model--', + 'property_behavior_list_file' => 'List Configuration File', + 'property_behavior_list_file_description' => 'Reference to a list definition file', + 'property_behavior_list_file_required' => 'Please enter a path to the list configuration file', + 'property_behavior_list_record_url' => 'Record URL', + 'property_behavior_list_record_url_description' => 'Link each list record to another page. Eg: users/update:id. The :id part is replaced with the record identifier.', + 'property_behavior_list_no_records_message' => 'No Records Message', + 'property_behavior_list_no_records_message_description' => 'A message to display when no records are found', + 'property_behavior_list_recs_per_page' => 'Records Per Page', + 'property_behavior_list_recs_per_page_description' => 'Records to display per page, use 0 for no pages. Default: 0', + 'property_behavior_list_recs_per_page_regex' => 'Records per page should be an integer value', + 'property_behavior_list_show_setup' => 'Show Setup Button', + 'property_behavior_list_structure' => 'Structure', + 'property_behavior_list_show_sorting' => 'Show Sorting', + 'property_behavior_list_show_reorder' => 'Show Reorder', + 'property_behavior_list_max_depth' => 'Max Depth', + 'property_behavior_list_max_depth_regex' => 'Max depth should be an integer value', + 'property_behavior_list_drag_row' => 'Draw Row', + 'property_behavior_list_default_sort' => 'Default Sorting', + 'property_behavior_form_ds_column' => 'Column', + 'property_behavior_form_ds_direction' => 'Direction', + 'property_behavior_form_ds_asc' => 'Ascending', + 'property_behavior_form_ds_desc' => 'Descending', + 'property_behavior_list_show_checkboxes' => 'Show Checkboxes', + 'property_behavior_list_onclick' => 'On Click Handler', + 'property_behavior_list_onclick_description' => 'Custom JavaScript code to execute when clicking on a record.', + 'property_behavior_list_show_tree' => 'Show Tree', + 'property_behavior_list_show_tree_description' => 'Displays a tree hierarchy for parent/child records.', + 'property_behavior_list_tree_expanded' => 'Tree Expanded', + 'property_behavior_list_tree_expanded_description' => 'Determines if tree nodes should be expanded by default.', + 'property_behavior_list_toolbar' => 'Toolbar', + 'property_behavior_list_toolbar_buttons' => 'Buttons Partial', + 'property_behavior_list_toolbar_buttons_description' => 'Reference to a controller partial file with the toolbar buttons. Eg: list_toolbar', + 'property_behavior_list_search' => 'Search', + 'property_behavior_list_search_prompt' => 'Search Prompt', + 'property_behavior_list_filter' => 'Filter Configuration', + 'behavior_import_export_controller' => 'Import Export Controller Behavior', + 'behavior_import_export_controller_description' => 'Provides features for importing and exporting records. The behavior automatically creates the controller actions "import" and "export".', + 'property_group_import' => 'Import', + 'property_group_export' => 'Export', + 'property_behavior_import_title' => 'Import Title', + 'property_behavior_export_title' => 'Export Title', + 'property_behavior_import_title_required' => 'Please enter a title', + 'property_behavior_import_model_class' => 'Import Model Class', + 'property_behavior_import_model_class_description' => 'A model class name for importing, extending the Backend\Models\ImportModel class.', + 'property_behavior_import_model_class_placeholder' => '--select model--', + 'property_behavior_export_model_class' => 'Export Model Class', + 'property_behavior_export_model_class_description' => 'A model class name for export, extending the Backend\Models\ExportModel class.', + 'property_behavior_import_model_class_required' => 'Please select a model class', + 'property_behavior_import_redirect' => 'Redirect', + 'property_behavior_import_redirect_description' => 'A page to redirect to by default when the process is complete.', + 'error_controller_not_found' => 'Original controller file is not found.', + 'error_invalid_config_file_name' => 'The behavior :class configuration file name (:file) contains invalid characters and cannot be loaded.', + 'error_file_not_yaml' => 'The behavior :class configuration file (:file) is not a YAML file. Only YAML configuration files are supported.', + 'saved' => 'Controller saved', + 'controller_name' => 'Controller Name', + 'controller_name_description' => 'Controller name defines the class name and URL of the controller\'s back-end pages. Standard PHP variable naming conventions apply. The first symbol should be a capital Latin letter. Examples: Categories, Posts, Products.', + 'base_model_class' => 'Base Model Class', + 'base_model_class_description' => 'Select a model class to use as a base model in behaviors that require or support models. You can configure the behaviors later.', + 'base_model_class_placeholder' => '--select model--', + 'controller_behaviors' => 'Behaviors', + 'controller_behaviors_description' => 'Select behaviors the controller should implement. Builder will create view files required for the behaviors automatically.', + 'controller_permissions' => 'Permissions', + 'controller_permissions_description' => 'Select user permissions that can access the controller views. Permissions can be defined on the Permissions tab of the Builder. You can change this option in the controller PHP script later.', + 'controller_permissions_no_permissions' => 'The plugin doesn\'t define any permissions.', + 'menu_item' => 'Active Menu Item', + 'menu_item_description' => 'Select a menu item to make active for the controller pages. You can change this option in the controller PHP script later.', + 'menu_item_placeholder' => '--select menu item--', + 'error_unknown_behavior' => 'The behavior class :class is not registered in the behavior library.', + 'error_behavior_view_conflict' => 'The selected behaviors provide conflicting views (:view) and cannot be used together in a controller.', + 'error_behavior_config_conflict' => 'The selected behaviors provide conflicting configuration files (:file) and cannot be used together in a controller.', + 'error_behavior_view_file_not_found' => 'View template :view of the behavior :class cannot be found.', + 'error_behavior_config_file_not_found' => 'Configuration template :file of the behavior :class cannot be found.', + 'error_controller_exists' => 'Controller file already exists: :file.', + 'error_controller_name_invalid' => 'Invalid controller name format. The name can only contain digits and Latin letters. The first symbol should be a capital Latin letter.', + 'error_behavior_view_file_exists' => 'Controller view file already exists: :view.', + 'error_behavior_config_file_exists' => 'Behavior configuration file already exists: :file.', + 'error_save_file' => 'Error saving controller file: :file', + 'error_behavior_requires_base_model' => 'Behavior :behavior requires a base model class to be selected.', + 'error_model_doesnt_have_lists' => 'The selected model doesn\'t have any lists. Please create a list first.', + 'error_model_doesnt_have_forms' => 'The selected model doesn\'t have any forms. Please create a form first.', + ], + 'version' => [ + 'menu_label' => 'Versions', + 'no_records' => 'No plugin versions found', + 'search' => 'Search...', + 'tab' => 'Versions', + 'saved' => 'Version saved', + 'confirm_delete' => 'Delete the version?', + 'tab_new_version' => 'New version', + 'migration' => 'Migration', + 'seeder' => 'Seeder', + 'custom' => 'Increase the version number', + 'apply_version' => 'Apply version', + 'applying' => 'Applying...', + 'rollback_version' => 'Rollback version', + 'rolling_back' => 'Rolling back...', + 'applied' => 'Version applied', + 'rolled_back' => 'Version rolled back', + 'hint_save_unapplied' => 'You saved an unapplied version. Unapplied versions could be automatically applied when you or another user migrates the database or when a database table is saved in the Database section of the Builder.', + 'hint_rollback' => 'Rolling back a version will also roll back all versions newer than this version. Please note that unapplied versions could be automatically applied by the system when you or another user logs into the back-end or when a database table is saved in the Database section of the Builder.', + 'hint_apply' => 'Applying a version will also apply all older unapplied versions of the plugin.', + 'dont_show_again' => 'Don\'t show again', + 'save_unapplied_version' => 'Save unapplied version', + 'sort_ascending' => 'Sort ascending', + 'sort_descending' => 'Sort descending', + ], + 'menu' => [ + 'menu_label' => 'Backend Menu', + 'tab' => 'Menus', + 'items' => 'Menu items', + 'saved' => 'Menus saved', + 'add_main_menu_item' => 'Add main menu item', + 'new_menu_item' => 'Menu Item', + 'add_side_menu_item' => 'Add sub-item', + 'side_menu_item' => 'Side menu item', + 'property_label' => 'Label', + 'property_label_required' => 'Please enter the menu item labels.', + 'property_url_required' => 'Please enter the menu item URL', + 'property_url' => 'URL', + 'property_icon' => 'Icon', + 'property_icon_required' => 'Please select an icon', + 'property_permissions' => 'Permissions', + 'property_order' => 'Order', + 'property_order_invalid' => 'Please enter the menu item order as integer value.', + 'property_order_description' => 'Menu item order manages its position in the menu. If the order is not provided, the item will be placed to the end of the menu. The default order values have the increment of 100.', + 'property_attributes' => 'HTML Attributes', + 'property_code' => 'Code', + 'property_code_invalid' => 'The code should contain only Latin letter and digits', + 'property_code_required' => 'Please enter the menu item code.', + 'error_duplicate_main_menu_code' => 'Duplicate main menu item code: \':code\'.', + 'error_duplicate_side_menu_code' => 'Duplicate side menu item code: \':code\'.', + 'icon_svg' => 'Icon (SVG)', + 'icon_svg_description' => 'An SVG icon to be used in place of the standard icon. The SVG icon should be a rectangle and can support colors', + 'counter' => 'Counter', + 'counter_description' => 'A numeric value to output near the menu icon. The value should be a number or a callable returning a number', + 'counter_label' => 'Counter Label', + 'counter_label_description' => 'A string value to describe the numeric reference in counter', + 'counter_group' => 'Counter', + ], + 'localization' => [ + 'menu_label' => 'Localization', + 'language' => 'Language', + 'strings' => 'Strings', + 'confirm_delete' => 'Delete the language?', + 'tab_new_language' => 'New language', + 'no_records' => 'No languages found', + 'saved' => 'Language file saved', + 'error_cant_load_file' => 'Cannot load the requested language file - file not found.', + 'error_bad_localization_file_contents' => 'Cannot load the requested language file. Language files can only contain array definitions and strings.', + 'error_file_not_array' => 'Cannot load the requested language file. Language files should return an array.', + 'save_error' => 'Error saving file \':name\'. Please check write permissions.', + 'error_delete_file' => 'Error deleting localization file.', + 'add_missing_strings' => 'Add Missing Strings', + 'copy' => 'Copy', + 'add_missing_strings_label' => 'Select language to copy missing strings from', + 'no_languages_to_copy_from' => 'There are no other languages to copy strings from.', + 'new_string_warning' => 'New string or section', + 'structure_mismatch' => 'The structure of the source language file doesn\'t match the structure of the file being edited. Some individual strings in the edited file correspond to sections in the source file (or vice versa) and cannot be merged automatically.', + 'create_string' => 'Create Language String', + 'string_key_label' => 'String Key', + 'string_key_comment' => 'Enter the string key using period as a section separator. For example: plugin.search. The string will be created in the plugin\'s default language localization file.', + 'string_value' => 'String Value', + 'string_key_is_empty' => 'String key should not be empty', + 'string_key_is_a_string' => ':key is a string and cannot contain other strings.', + 'string_value_is_empty' => 'String value should not be empty', + 'string_key_exists' => 'The string key already exists', + ], + 'permission' => [ + 'menu_label' => 'Permissions', + 'tab' => 'Permissions', + 'form_tab_permissions' => 'Permissions', + 'btn_add_permission' => 'Add Permission', + 'btn_delete_permission' => 'Delete Permission', + 'column_permission_label' => 'Permission Code', + 'column_permission_required' => 'Please enter the permission code', + 'column_tab_label' => 'Tab Title', + 'column_tab_required' => 'Please enter the permission tab title', + 'column_label_label' => 'Label', + 'column_label_required' => 'Please enter the permission label', + 'saved' => 'Permissions saved', + 'error_duplicate_code' => 'Duplicate permission code: \':code\'.', + ], + 'yaml' => [ + 'save_error' => 'Error saving file \':name\'. Please check write permissions.', + ], + 'common' => [ + 'error_file_exists' => 'File already exists: \':path\'.', + 'field_icon_description' => 'October CMS uses Font Awesome icons: http://octobercms.com/docs/ui/icon', + 'destination_dir_not_exists' => 'The destination directory doesn\'t exist: \':path\'.', + 'error_make_dir' => 'Error creating directory: \':name\'.', + 'error_dir_exists' => 'Directory already exists: \':path\'.', + 'template_not_found' => 'Template file is not found: \':name\'.', + 'error_generating_file' => 'Error generating file: \':path\'.', + 'error_loading_template' => 'Error loading template file: \':name\'.', + 'select_plugin_first' => 'Please select a plugin first. To see the plugin list click the > icon on the left sidebar.', + 'not_match' => 'The object you\'re trying to access doesn\'t belong to the plugin being edited. Please reload the page.', + 'plugin_not_selected' => 'Plugin is not selected', + 'add' => 'Add', + ], + 'migration' => [ + 'entity_name' => 'Migration', + 'error_version_invalid' => 'The version should be specified in format v1.0.1', + 'field_version' => 'Version', + 'field_description' => 'Description', + 'field_code' => 'Code', + 'save_and_apply' => 'Save & Apply', + 'error_version_exists' => 'The migration version already exists.', + 'error_script_filename_invalid' => 'The migration script file name can contain only Latin letters, digits and underscores. The name should start with a Latin letter and could not contain spaces.', + 'error_cannot_change_version_number' => 'Cannot change version number for an applied version.', + 'error_file_must_define_class' => 'Migration code should define a migration or seeder class. Leave the code field blank if you only want to update the version number.', + 'error_file_must_define_namespace' => 'Migration code should define a namespace. Leave the code field blank if you only want to update the version number.', + 'no_changes_to_save' => 'There are no changes to save.', + 'error_namespace_mismatch' => 'The migration code should use the plugin namespace: :namespace', + 'error_migration_file_exists' => 'Migration file :file already exists. Please use another class name.', + 'error_cant_delete_applied' => 'This version has already been applied and cannot be deleted. Please rollback the version first.', + ], + 'components' => [ + 'list_title' => 'Record list', + 'list_description' => 'Displays a list of records for a selected model', + 'list_page_number' => 'Page number', + 'list_page_number_description' => 'This value is used to determine what page the user is on.', + 'list_records_per_page' => 'Records per page', + 'list_records_per_page_description' => 'Number of records to display on a single page. Leave empty to disable pagination.', + 'list_records_per_page_validation' => 'Invalid format of the records per page value. The value should be a number.', + 'list_no_records' => 'No records message', + 'list_no_records_description' => 'Message to display in the list in case if there are no records. Used in the default component\'s partial.', + 'list_no_records_default' => 'No records found', + 'list_sort_column' => 'Sort by column', + 'list_sort_column_description' => 'Model column the records should be ordered by', + 'list_sort_direction' => 'Direction', + 'list_display_column' => 'Display column', + 'list_display_column_description' => 'Column to display in the list. Used in the default component\'s partial.', + 'list_display_column_required' => 'Please select a display column.', + 'list_details_page' => 'Details page', + 'list_details_page_description' => 'Page to display record details.', + 'list_details_page_no' => '--no details page--', + 'list_sorting' => 'Sorting', + 'list_pagination' => 'Pagination', + 'list_order_direction_asc' => 'Ascending', + 'list_order_direction_desc' => 'Descending', + 'list_model' => 'Model class', + 'list_scope' => 'Scope', + 'list_scope_description' => 'Optional model scope to fetch the records', + 'list_scope_default' => '--select a scope, optional--', + 'list_scope_value' => 'Scope value', + 'list_scope_value_description' => 'Optional value to pass to the model scope', + 'list_details_page_link' => 'Link to the details page', + 'list_details_key_column' => 'Details key column', + 'list_details_key_column_description' => 'Model column to use as a record identifier in the details page links.', + 'list_details_url_parameter' => 'URL parameter name', + 'list_details_url_parameter_description' => 'Name of the details page URL parameter which takes the record identifier.', + 'details_title' => 'Record details', + 'details_description' => 'Displays record details for a selected model', + 'details_model' => 'Model class', + 'details_identifier_value' => 'Identifier value', + 'details_identifier_value_description' => 'Identifier value to load the record from the database. Specify a fixed value or URL parameter name.', + 'details_identifier_value_required' => 'The identifier value is required', + 'details_key_column' => 'Key column', + 'details_key_column_description' => 'Model column to use as a record identifier for fetching the record from the database.', + 'details_key_column_required' => 'The key column name is required', + 'details_display_column' => 'Display column', + 'details_display_column_description' => 'Model column to display on the details page. Used in the default component\'s partial.', + 'details_display_column_required' => 'Please select a display column.', + 'details_not_found_message' => 'Not found message', + 'details_not_found_message_description' => 'Message to display if the record is not found. Used in the default component\'s partial.', + 'details_not_found_message_default' => 'Record not found', + ], + 'validation' => [ + 'reserved' => ':attribute cannot be a PHP reserved keyword', + ], +]; diff --git a/plugins/rainlab/builder/lang/es.json b/plugins/rainlab/builder/lang/es.json new file mode 100644 index 0000000..16fb070 --- /dev/null +++ b/plugins/rainlab/builder/lang/es.json @@ -0,0 +1,4 @@ +{ + "Builder": "Builder", + "Provides visual tools for building October plugins.": "Proporciona herramientas visuales para la construcción de plugins de October." +} \ No newline at end of file diff --git a/plugins/rainlab/builder/lang/es/lang.php b/plugins/rainlab/builder/lang/es/lang.php new file mode 100644 index 0000000..0e5adb6 --- /dev/null +++ b/plugins/rainlab/builder/lang/es/lang.php @@ -0,0 +1,642 @@ + [ + 'add' => 'Crear plugin', + 'no_records' => 'No se encuentran plugins', + 'no_name' => 'Sin nombre', + 'search' => 'Buscar...', + 'filter_description' => 'Mostrar todos los plugins o sólo tus plugins.', + 'settings' => 'Configuración', + 'entity_name' => 'Plugin', + 'field_name' => 'Nombre', + 'field_author' => 'Autor', + 'field_description' => 'Descripción', + 'field_icon' => 'Icono plugin', + 'field_plugin_namespace' => 'Espacio de nombres de plugin', + 'field_author_namespace' => 'Espacio de nombres de autor', + 'field_namespace_description' => 'Namespace can contain only Latin letters and digits and should start with a Latin letter. Example plugin namespace: Blog', + 'field_author_namespace_description' => 'You cannot change the namespaces with Builder after you create the plugin. Example author namespace: JohnSmith', + 'tab_general' => 'Parametros generales', + 'tab_description' => 'Descripción', + 'field_homepage' => 'Plugin Homepage (URL)', + 'no_description' => 'No hay descripción proporcionada para este plugin', + 'error_settings_not_editable' => 'Configuración de este plugin no se pueden editar con el Builder.', + 'update_hint' => 'Puedes editar el nombre de plugins y descripción localizada en la pestaña de localizaciones.', + 'manage_plugins' => 'Crear y editar plugins', + ], + 'author_name' => [ + 'title' => 'Nombre del autor', + 'description' => 'Por defecto el nombre del autor a utilizar para sus nuevos plugins. El nombre del autor no es fijo - se puede cambiar en la configuración de los plugins en cualquier momento.', + ], + 'author_namespace' => [ + 'title' => 'Espacio de nombres', + 'description' => 'Si desarrolla para el Marketplace, el espacio de nombres debe coincidir con el código de autor y no puede ser cambiado. Consulte la documentación para más detalles.', + ], + 'database' => [ + 'menu_label' => 'Base de datos', + 'no_records' => 'Tablas no encontradas', + 'search' => 'Buscar...', + 'confirmation_delete_multiple' => '¿Eliminar las tablas seleccionadas?', + 'field_name' => 'Nombre de la tabla', + 'tab_columns' => 'Columnas', + 'column_name_name' => 'Columna', + 'column_name_required' => 'Por favor ingrese el nombre de la columna', + 'column_name_type' => 'Tipo', + 'column_type_required' => 'Please select the column type', + 'column_name_length' => 'Length', + 'column_validation_length' => 'The Length value should be integer or specified as precision and scale (10,2) for decimal columns. Spaces are not allowed in the length column.', + 'column_validation_title' => 'Only digits, lower-case Latin letters and underscores are allowed in column names', + 'column_name_unsigned' => 'Unsigned', + 'column_name_nullable' => 'Nullable', + 'column_auto_increment' => 'AUTOINCR', + 'column_default' => 'Default', + 'column_auto_primary_key' => 'PK', + 'tab_new_table' => 'Nueva tabla', + 'btn_add_column' => 'Añadir columna', + 'btn_delete_column' => 'Borrar columna', + 'btn_add_id' => 'Añadir ID', + 'btn_add_timestamps' => 'Añadir timestamps', + 'btn_add_soft_deleting' => 'Añadir columna para soft delete', + 'confirm_delete' => '¿Borrar la tabla?', + 'error_enum_not_supported' => 'The table contains column(s) with type "enum" which is not currently supported by the Builder.', + 'error_table_name_invalid_prefix' => 'Table name should start with the plugin prefix: \':prefix\'.', + 'error_table_name_invalid_characters' => 'Invalid table name. Table names should contain only Latin letters, digits and underscores. Names should start with a Latin letter and could not contain spaces.', + 'error_table_duplicate_column' => 'Nombre de columna duplicada: \':column\'.', + 'error_table_auto_increment_in_compound_pk' => 'An auto-increment column cannot be a part of a compound primary key.', + 'error_table_mutliple_auto_increment' => 'La tabla no puede contener más de una columna auto-incrementable.', + 'error_table_auto_increment_non_integer' => 'Las columnas Auto-incrementables deben ser de tipo numerico.', + 'error_table_decimal_length' => 'The Length parameter for :type type should be in format \'10,2\', without spaces.', + 'error_table_length' => 'The Length parameter for :type type should be specified as integer.', + 'error_unsigned_type_not_int' => 'Error in the \':column\' column. The Unsigned flag can be applied only to integer type columns.', + 'error_integer_default_value' => 'Invalid default value for the integer column \':column\'. The allowed formats are \'10\', \'-10\'.', + 'error_decimal_default_value' => 'Invalid default value for the decimal or double column \':column\'. The allowed formats are \'1.00\', \'-1.00\'.', + 'error_boolean_default_value' => 'Invalid default value for the boolean column \':column\'. The allowed values are \'0\' and \'1\'.', + 'error_unsigned_negative_value' => 'The default value for the unsigned column \':column\' can\'t be negative.', + 'error_table_already_exists' => 'La tabla \':name\' ya existe en la base de datos.', + ], + 'model' => [ + 'menu_label' => 'Modelos', + 'entity_name' => 'Modelo', + 'no_records' => 'Modelos no encontrados', + 'search' => 'Buscar...', + 'add' => 'Añadir...', + 'forms' => 'Formularios', + 'lists' => 'Listas', + 'field_class_name' => 'Nombre Clase', + 'field_database_table' => 'Tabla de base de datos', + 'error_class_name_exists' => 'Ya existe el archivo modelo para el nombre de clase especificado: :path', + 'add_form' => 'Añadir formulario', + 'add_list' => 'Añadir lista', + ], + 'form' => [ + 'saved' => 'Formulario guardado', + 'confirm_delete' => '¿Borrar el formulario?', + 'tab_new_form' => 'Nuevo formulario', + 'property_label_title' => 'Etiqueta', + 'property_label_required' => 'Por favor especifique la etiqueta del control.', + 'property_span_title' => 'Span', + 'property_comment_title' => 'Commentario', + 'property_comment_above_title' => 'Comentario encima', + 'property_default_title' => 'Default', + 'property_checked_default_title' => 'Checked by default', + 'property_css_class_title' => 'CSS class', + 'property_css_class_description' => 'Optional CSS class to assign to the field container.', + 'property_disabled_title' => 'deshabilitado', + 'property_hidden_title' => 'Oculto', + 'property_required_title' => 'Requerido', + 'property_field_name_title' => 'Nombre del campo', + 'property_placeholder_title' => 'Placeholder', + 'property_default_from_title' => 'Default from', + 'property_stretch_title' => 'Stretch', + 'property_stretch_description' => 'Specifies if this field stretches to fit the parent height.', + 'property_context_title' => 'Context', + 'property_context_description' => 'Specifies what form context should be used when displaying the field.', + 'property_context_create' => 'Create', + 'property_context_update' => 'Update', + 'property_context_preview' => 'Preview', + 'property_dependson_title' => 'Depends on', + 'property_trigger_action' => 'Action', + 'property_trigger_show' => 'Show', + 'property_trigger_hide' => 'Hide', + 'property_trigger_enable' => 'Enable', + 'property_trigger_disable' => 'Disable', + 'property_trigger_empty' => 'Vacio', + 'property_trigger_field' => 'Campo', + 'property_trigger_field_description' => 'Defines the other field name that will trigger the action.', + 'property_trigger_condition' => 'Condition', + 'property_trigger_condition_description' => 'Determines the condition the specified field should satisfy for the condition to be considered "true". Supported values: checked, unchecked, value[somevalue].', + 'property_trigger_condition_checked' => 'Checked', + 'property_trigger_condition_unchecked' => 'Unchecked', + 'property_trigger_condition_somevalue' => 'value[enter-the-value-here]', + 'property_preset_title' => 'Preset', + 'property_preset_description' => 'Allows the field value to be initially set by the value of another field, converted using the input preset converter.', + 'property_preset_field' => 'Field', + 'property_preset_field_description' => 'Defines the other field name to source the value from.', + 'property_preset_type' => 'Type', + 'property_preset_type_description' => 'Specifies the conversion type', + 'property_attributes_title' => 'Atributos', + 'property_attributes_description' => 'Custom HTML attributes to add to the form field element.', + 'property_container_attributes_title' => 'Container attributes', + 'property_container_attributes_description' => 'Custom HTML attributes to add to the form field container element.', + 'property_group_advanced' => 'Avanzado', + 'property_dependson_description' => 'A list of other field names this field depends on, when the other fields are modified, this field will update. One field per line.', + 'property_trigger_title' => 'Trigger', + 'property_trigger_description' => 'Allows to change elements attributes such as visibility or value, based on another elements\' state.', + 'property_default_from_description' => 'Takes the default value from the value of another field.', + 'property_field_name_required' => 'El campo nombre es requerido', + 'property_field_name_regex' => 'The field name can contain only Latin letters, digits, underscores, dashes and square brackets.', + 'property_attributes_size' => 'Tamaño', + 'property_attributes_size_tiny' => 'Diminuto', + 'property_attributes_size_small' => 'Pequeño', + 'property_attributes_size_large' => 'Grande', + 'property_attributes_size_huge' => 'Enorme', + 'property_attributes_size_giant' => 'Gigante', + 'property_comment_position' => 'Posición del comentario', + 'property_comment_position_above' => 'Arriba', + 'property_comment_position_below' => 'Abajo', + 'property_hint_path' => 'Hint partial path', + 'property_hint_path_description' => 'Path to a partial file that contains the hint text. Use the $ symbol to refer the plugins root directory, for example: $/acme/blog/partials/_hint.htm', + 'property_hint_path_required' => 'Por favor ingresa la ruta hacia el archivo parcial de la pista', + 'property_partial_path' => 'Partial path', + 'property_partial_path_description' => 'Path to a partial file. Use the $ symbol to refer the plugins root directory, for example: $/acme/blog/partials/_partial.htm', + 'property_partial_path_required' => 'Please enter the partial path', + 'property_code_language' => 'Idioma', + 'property_code_theme' => 'Tema', + 'property_theme_use_default' => 'Usar tema por defecto', + 'property_group_code_editor' => 'Code editor', + 'property_gutter' => 'Gutter', + 'property_gutter_show' => 'Visible', + 'property_gutter_hide' => 'Hidden', + 'property_wordwrap' => 'Word wrap', + 'property_wordwrap_wrap' => 'Wrap', + 'property_wordwrap_nowrap' => 'Don\'t wrap', + 'property_fontsize' => 'Font size', + 'property_codefolding' => 'Code folding', + 'property_codefolding_manual' => 'Manual', + 'property_codefolding_markbegin' => 'Mark begin', + 'property_codefolding_markbeginend' => 'Mark begin and end', + 'property_autoclosing' => 'Auto closing', + 'property_enabled' => 'Habilitado', + 'property_disabled' => 'Deshabilitado', + 'property_soft_tabs' => 'Soft tabs', + 'property_tab_size' => 'Tamaño de la pestaña', + 'property_readonly' => 'Solo lectura', + 'property_use_default' => 'Use default settings', + 'property_options' => 'Opciones', + 'property_prompt' => 'Prompt', + 'property_prompt_description' => 'Texto que se mostrará para el botón creado', + 'property_prompt_default' => 'Añadir nuevo item', + 'property_available_colors' => 'Colores disponibles', + 'property_available_colors_description' => 'List of available colors in hex format (#FF0000). Leave empty for the default color set. Enter one value per line.', + 'property_datepicker_mode' => 'Modo', + 'property_datepicker_mode_date' => 'Fecha', + 'property_datepicker_mode_datetime' => 'Fecha y hora', + 'property_datepicker_mode_time' => 'Hora', + 'property_datepicker_min_date' => 'Fecha mínima', + 'property_datepicker_max_date' => 'Fecha máxima', + 'property_fileupload_mode' => 'Mode', + 'property_fileupload_mode_file' => 'Archivo', + 'property_fileupload_mode_image' => 'Imágen', + 'property_group_fileupload' => 'File upload', + 'property_fileupload_image_width' => 'Ancho de la imagen (width)', + 'property_fileupload_image_width_description' => 'Optional parameter - images will be resized to this width. Applies to Image mode only.', + 'property_fileupload_invalid_dimension' => 'Invalid dimension value - please enter a number.', + 'property_fileupload_image_height' => 'Alto de la imagen (height)', + 'property_fileupload_image_height_description' => 'Optional parameter - images will be resized to this height. Applies to Image mode only.', + 'property_fileupload_file_types' => 'File types', + 'property_fileupload_file_types_description' => 'Optional comma separated list of file extensions that are accepted by the uploader. Eg: zip,txt', + 'property_fileupload_mime_types' => 'MIME types', + 'property_fileupload_mime_types_description' => 'Optional comma separated list of MIME types that are accepted by the uploader, either as file extensions or fully qualified names. Eg: bin,txt', + 'property_fileupload_use_caption' => 'Use caption', + 'property_fileupload_use_caption_description' => 'Allows a title and description to be set for the file.', + 'property_fileupload_thumb_options' => 'Thumbnail options', + 'property_fileupload_thumb_options_description' => 'Manages options for the automatically generated thumbnails. Applies only for the Image mode.', + 'property_fileupload_thumb_mode' => 'Mode', + 'property_fileupload_thumb_auto' => 'Auto', + 'property_fileupload_thumb_exact' => 'Exact', + 'property_fileupload_thumb_portrait' => 'Portrait', + 'property_fileupload_thumb_landscape' => 'Landscape', + 'property_fileupload_thumb_crop' => 'Crop', + 'property_fileupload_thumb_extension' => 'Extensión del archivo', + 'property_name_from' => 'Name column', + 'property_name_from_description' => 'Relation column name to use for displaying a name.', + 'property_relation_select' => 'Select', + 'property_relation_select_description' => 'CONCAT multiple columns together for displaying a name', + 'property_description_from' => 'Description column', + 'property_description_from_description' => 'Relation column name to use for displaying a description.', + 'property_recordfinder_prompt' => 'Prompt', + 'property_recordfinder_prompt_description' => 'Text to display when there is no record selected. The %s character represents the search icon. Leave empty for the default prompt.', + 'property_recordfinder_list' => 'List configuration', + 'property_recordfinder_list_description' => 'A reference to a list column definition file. Use the $ symbol to refer the plugins root directory, for example: $/acme/blog/lists/_list.yaml', + 'property_recordfinder_list_required' => 'Please provide a path to the list YAML file', + 'property_group_recordfinder' => 'Record finder', + 'property_mediafinder_mode' => 'Modo', + 'property_mediafinder_mode_file' => 'Archivo', + 'property_mediafinder_mode_image' => 'Imagen', + 'property_group_relation' => 'Relation', + 'property_relation_prompt' => 'Prompt', + 'property_relation_prompt_description' => 'Text to display when there is no available selections.', + 'control_group_standard' => 'Standard', + 'control_group_widgets' => 'Widgets', + 'click_to_add_control' => 'Añadir control', + 'loading' => 'Cargando...', + 'control_text' => 'Texto', + 'control_text_description' => 'Campo de texto de una linea', + 'control_password' => 'Contraseña', + 'control_password_description' => 'Campo de contraseña de una linea', + 'control_checkbox' => 'Checkbox', + 'control_checkbox_description' => 'Checkbox único', + 'control_switch' => 'Switch', + 'control_switch_description' => 'Control switch único, una alternativa al checkbox', + 'control_textarea' => 'Text area', + 'control_textarea_description' => 'Campo de texto multilinea con altura personalizable', + 'control_dropdown' => 'Dropdown', + 'control_dropdown_description' => 'Dropdown list with static or dynamic options', + 'control_unknown' => 'Unknown control type: :type', + 'control_repeater' => 'Repeater', + 'control_repeater_description' => 'Outputs a repeating set of form controls', + 'control_number' => 'Número', + 'control_number_description' => 'Campo de texto de una linea el cual sólo permite números', + 'control_hint' => 'Pista', + 'control_hint_description' => 'Despliega un contenido parcial en una caja que puede ser ocultado por el usuario', + 'control_partial' => 'Partial', + 'control_partial_description' => 'Incluye un contenido parcial', + 'control_section' => 'Section', + 'control_section_description' => 'Displays a form section with heading and subheading', + 'control_radio' => 'Lista de radios', + 'control_radio_description' => 'Una lista de radio buttons, donde solo un item puede ser seleccionado al mismo tiempo', + 'control_radio_option_1' => 'Opción 1', + 'control_radio_option_2' => 'Opción 2', + 'control_checkboxlist' => 'Lista de Checkbox', + 'control_checkboxlist_description' => 'Una lista de checkboxs, donde mas de un item puede ser seleccionado', + 'control_codeeditor' => 'Editor de código', + 'control_codeeditor_description' => 'Plaintext editor for formatted code or markup', + 'control_colorpicker' => 'Selector de color', + 'control_colorpicker_description' => 'Un campo para seleccionar un valor de color en hexadecimal', + 'control_datepicker' => 'Selector de fecha', + 'control_datepicker_description' => 'Un campo de texto para seleccionar fecha/hora', + 'control_richeditor' => 'Editor enriquecido', + 'control_richeditor_description' => 'Editor visual para texto enriquecido, también conocido como editor WYSIWYG', + 'control_markdown' => 'Editor Markdown', + 'control_markdown_description' => 'Editor básico para texto formateado en Markdown', + 'control_fileupload' => 'File upload', + 'control_fileupload_description' => 'File uploader for images or regular files', + 'control_recordfinder' => 'Record finder', + 'control_recordfinder_description' => 'Field with details of a related record with the record search feature', + 'control_mediafinder' => 'Media finder', + 'control_mediafinder_description' => 'Field for selecting an item from the Media Manager library', + 'control_relation' => 'Relation', + 'control_relation_description' => 'Despliega un Dropdown o una lista de Checkboxs para seleccionar el registro relacionado', + 'error_file_name_required' => 'Por favor ingresa el nombre del archivo del formulario.', + 'error_file_name_invalid' => 'El nombre de este archivo sólo puede contener letras, digitos, guiones (bajo y medio) y puntos.', + 'span_left' => 'Izquierda', + 'span_right' => 'Derecha', + 'span_full' => 'Completo', + 'span_auto' => 'Automático', + 'empty_tab' => 'Pestaña vacia', + 'confirm_close_tab' => 'La pestaña contiene controles que serán eliminados, ¿continuar?', + 'tab' => 'Pestaña de formulario', + 'tab_title' => 'Titulo', + 'controls' => 'Controles', + 'property_tab_title_required' => 'el campo titulo es requerido', + 'tabs_primary' => 'Pestañas primarias', + 'tabs_secondary' => 'Pestañas secundarias', + 'tab_stretch' => 'Stretch', + 'tab_stretch_description' => 'Especifica si el contenedor de esta pestaña se estira para ajustarse al alto del elemento padre.', + 'tab_css_class' => 'Clase CSS', + 'tab_css_class_description' => 'Asigna una clase CSS al contenedor de la pestaña.', + 'tab_name_template' => 'Pestaña %s', + 'tab_already_exists' => 'Ya existe una pestaña con el nombre especificado.', + ], + 'list' => [ + 'tab_new_list' => 'Nueva lista', + 'saved' => 'Lista guardada', + 'confirm_delete' => '¿Borrar la lista?', + 'tab_columns' => 'Columnas', + 'btn_add_column' => 'Añadir columna', + 'btn_delete_column' => 'Borrar columna', + 'column_dbfield_label' => 'Campo', + 'column_dbfield_required' => 'Por favor proporcione el campo del modelo', + 'column_name_label' => 'Etiqueta', + 'column_label_required' => 'Por favor proporcione la etiqueta de columna', + 'column_type_label' => 'Tipo', + 'column_type_required' => 'Por favor indique el tipo de columna', + 'column_type_text' => 'Texto', + 'column_type_number' => 'Numero', + 'column_type_switch' => 'Switch', + 'column_type_datetime' => 'Datetime', + 'column_type_date' => 'Fecha', + 'column_type_time' => 'Hora', + 'column_type_timesince' => 'Tine since', + 'column_type_timetense' => 'Tine tense', + 'column_type_select' => 'Select', + 'column_type_partial' => 'Partial', + 'column_label_default' => 'Default', + 'column_label_searchable' => 'Buscable', + 'column_label_sortable' => 'Ordenable', + 'column_label_invisible' => 'Invisible', + 'column_label_select' => 'Select', + 'column_label_relation' => 'Relation', + 'column_label_css_class' => 'CSS class', + 'column_label_width' => 'Width', + 'column_label_path' => 'Path', + 'column_label_format' => 'Format', + 'column_label_value_from' => 'Value from', + 'error_duplicate_column' => 'Nombre del campo duplicado: \':column\'.', + 'btn_add_database_columns' => 'Añadir columnas desde la base de datos', + ], + 'controller' => [ + 'menu_label' => 'Controladores', + 'no_records' => 'No se encuentran controladores del plugin', + 'controller' => 'Controlador', + 'behaviors' => 'Comportamientos', + 'new_controller' => 'Nuevo controlador', + 'error_controller_has_no_behaviors' => 'El controlador no tiene un behaviors configurado.', + 'error_invalid_yaml_configuration' => 'Error loading behavior configuration file: :file', + 'behavior_form_controller' => 'Form controller behavior', + 'behavior_form_controller_description' => 'Adds form functionality to a back-end page. The behavior provides three pages called Create, Update and Preview.', + 'property_behavior_form_placeholder' => '--select form--', + 'property_behavior_form_name' => 'Nombre', + 'property_behavior_form_name_description' => 'The name of the object being managed by this form', + 'property_behavior_form_name_required' => 'Por favor ingrese el nombre del formulario', + 'property_behavior_form_file' => 'Configuración del formulario', + 'property_behavior_form_file_description' => 'Reference to a form field definition file', + 'property_behavior_form_file_required' => 'Please enter a path to the form configuration file', + 'property_behavior_form_model_class' => 'Model class', + 'property_behavior_form_model_class_description' => 'A model class name, the form data is loaded and saved against this model.', + 'property_behavior_form_model_class_required' => 'Please select a model class', + 'property_behavior_form_default_redirect' => 'Default redirect', + 'property_behavior_form_default_redirect_description' => 'A page to redirect to by default when the form is saved or cancelled.', + 'property_behavior_form_create' => 'Create record page', + 'property_behavior_form_redirect' => 'Redirect', + 'property_behavior_form_redirect_description' => 'Una página a la que redirigir una vez el registro sea creado', + 'property_behavior_form_redirect_close' => 'Close redirect', + 'property_behavior_form_redirect_close_description' => 'A page to redirect to when a record is created and the close post variable is sent with the request.', + 'property_behavior_form_flash_save' => 'Save flash message', + 'property_behavior_form_flash_save_description' => 'Flash message to display when record is saved.', + 'property_behavior_form_page_title' => 'Page title', + 'property_behavior_form_update' => 'Update record page', + 'property_behavior_form_update_redirect' => 'Redirect', + 'property_behavior_form_create_redirect_description' => 'A page to redirect to when a record is saved.', + 'property_behavior_form_flash_delete' => 'Delete flash message', + 'property_behavior_form_flash_delete_description' => 'Flash message to display when record is deleted.', + 'property_behavior_form_preview' => 'Preview record page', + 'behavior_list_controller' => 'List controller behavior', + 'behavior_list_controller_description' => 'Provides the sortable and searchable list with optional links on its records. The behavior automatically creates the controller action "index".', + 'property_behavior_list_title' => 'List title', + 'property_behavior_list_title_required' => 'Please enter the list title', + 'property_behavior_list_placeholder' => '--select list--', + 'property_behavior_list_model_class' => 'Model class', + 'property_behavior_list_model_class_description' => 'A model class name, the list data is loaded from this model.', + 'property_behavior_form_model_class_placeholder' => '--select model--', + 'property_behavior_list_model_class_required' => 'Please select a model class', + 'property_behavior_list_model_placeholder' => '--select model--', + 'property_behavior_list_file' => 'List configuration file', + 'property_behavior_list_file_description' => 'Reference to a list definition file', + 'property_behavior_list_file_required' => 'Please enter a path to the list configuration file', + 'property_behavior_list_record_url' => 'Record URL', + 'property_behavior_list_record_url_description' => 'Link each list record to another page. Eg: users/update:id. The :id part is replaced with the record identifier.', + 'property_behavior_list_no_records_message' => 'No records message', + 'property_behavior_list_no_records_message_description' => 'A message to display when no records are found', + 'property_behavior_list_recs_per_page' => 'Records per page', + 'property_behavior_list_recs_per_page_description' => 'Records to display per page, use 0 for no pages. Default: 0', + 'property_behavior_list_recs_per_page_regex' => 'Records per page should be an integer value', + 'property_behavior_list_show_setup' => 'Show setup button', + 'property_behavior_list_show_sorting' => 'Show sorting', + 'property_behavior_list_default_sort' => 'Default sorting', + 'property_behavior_form_ds_column' => 'Columna', + 'property_behavior_form_ds_direction' => 'Direction', + 'property_behavior_form_ds_asc' => 'Ascending', + 'property_behavior_form_ds_desc' => 'Descending', + 'property_behavior_list_show_checkboxes' => 'Show checkboxes', + 'property_behavior_list_onclick' => 'On click handler', + 'property_behavior_list_onclick_description' => 'Custom JavaScript code to execute when clicking on a record.', + 'property_behavior_list_show_tree' => 'Show tree', + 'property_behavior_list_show_tree_description' => 'Displays a tree hierarchy for parent/child records.', + 'property_behavior_list_tree_expanded' => 'Tree expanded', + 'property_behavior_list_tree_expanded_description' => 'Determines if tree nodes should be expanded by default.', + 'property_behavior_list_toolbar' => 'Toolbar', + 'property_behavior_list_toolbar_buttons' => 'Buttons partial', + 'property_behavior_list_toolbar_buttons_description' => 'Reference to a controller partial file with the toolbar buttons. Eg: list_toolbar', + 'property_behavior_list_search' => 'Buscar', + 'property_behavior_list_search_prompt' => 'Search prompt', + 'property_behavior_list_filter' => 'Filter configuration', + 'behavior_reorder_controller' => 'Reorder controller behavior', + 'behavior_reorder_controller_description' => 'Provides features for sorting and reordering on its records. The behavior automatically creates the controller action "reorder".', + 'property_behavior_reorder_title' => 'Reorder title', + 'property_behavior_reorder_title_required' => 'Please enter the reorder title', + 'property_behavior_reorder_name_from' => 'Attribute name', + 'property_behavior_reorder_name_from_description' => 'Model\'s attribute that should be used as a label for each record.', + 'property_behavior_reorder_name_from_required' => 'Please enter the attribute name', + 'property_behavior_reorder_model_class' => 'Model class', + 'property_behavior_reorder_model_class_description' => 'A model class name, the reorder data is loaded from this model.', + 'property_behavior_reorder_model_class_placeholder' => '--select model--', + 'property_behavior_reorder_model_class_required' => 'Please select a model class', + 'property_behavior_reorder_model_placeholder' => '--select model--', + 'property_behavior_reorder_toolbar' => 'Toolbar', + 'property_behavior_reorder_toolbar_buttons' => 'Buttons partial', + 'property_behavior_reorder_toolbar_buttons_description' => 'Reference to a controller partial file with the toolbar buttons. Eg: reorder_toolbar', + 'error_controller_not_found' => 'Original controller file is not found.', + 'error_invalid_config_file_name' => 'The behavior :class configuration file name (:file) contains invalid characters and cannot be loaded.', + 'error_file_not_yaml' => 'The behavior :class configuration file (:file) is not a YAML file. Only YAML configuration files are supported.', + 'saved' => 'Controlador guardado', + 'controller_name' => 'Nombre del controlador', + 'controller_name_description' => 'El nombre del controlador define el nombre de la clase y la URL del controlador en el backend. Se aplican Las convenciones estándar de nombramiento de variables. El primer simbolo debe ser una letra Mayúscula: Ejemplo: Categories, Posts, Products', + 'base_model_class' => 'Clase de modelo base', + 'base_model_class_description' => 'Selecciona la clase del modelo para usarla como modelo base en los behaviors que se requieran o soporte el modelo. Puedes configurar los behaviors más adelante.', + 'base_model_class_placeholder' => '--selecciona el modelo--', + 'controller_behaviors' => 'Behaviors', + 'controller_behaviors_description' => 'Selecciona los behaviors que el controlador debe implementar. El Plugin Builder creará las vistas requeridas para los behaviors automáticamente.', + 'controller_permissions' => 'Permisos', + 'controller_permissions_description' => 'Select user permissions that can access the controller views. Permissions can be defined on the Permissions tab of the Builder. You can change this option in the controller PHP script later.', + 'controller_permissions_no_permissions' => 'El plugin no define ningún permiso.', + 'menu_item' => 'Item activo del menú', + 'menu_item_description' => 'Selecciona un item del menú para se active para las páginas de este controlador. Puedes cambiar esta opción en el script de PHP del controlador mas adelante.', + 'menu_item_placeholder' => '--selecciona el item del menú--', + 'error_unknown_behavior' => 'La clase :class del behavior no está registrado en la librería de behaviors.', + 'error_behavior_view_conflict' => 'El behaviors seleccionado provee vistas que ocasionan un conflicto (:view) y no pueden utilizarse juntas en un controlador.', + 'error_behavior_config_conflict' => 'El behaviors seleccionado provee archivos de configuración que ocasionan un conflicto (:file) y no pueden utilizarse juntas en un controlador.', + 'error_behavior_view_file_not_found' => 'View template :view of the behavior :class cannot be found.', + 'error_behavior_config_file_not_found' => 'Configuration template :file of the behavior :class cannot be found.', + 'error_controller_exists' => 'Controller file already exists: :file.', + 'error_controller_name_invalid' => 'Formato del nombre del controlador invalido. El nombre solo puede contener letras y digitos. El primer simbolo debe ser una mayúscula.', + 'error_behavior_view_file_exists' => 'El archivo de la vista del controlador ya existe: :view.', + 'error_behavior_config_file_exists' => 'El archivo de configuración de este Behavior ya existe: :file.', + 'error_save_file' => 'Error guardando el archivo del controlador: :file', + 'error_behavior_requires_base_model' => 'El Behavior :behavior require de un modelo base para ser seleccionado.', + 'error_model_doesnt_have_lists' => 'El modelo seleccionado no tiene ninguna lista. Favor de primero crear una lista.', + 'error_model_doesnt_have_forms' => 'El modelo seleccionado no tiene ningún formulario. Favor de primero crear un formulario.', + ], + 'version' => [ + 'menu_label' => 'Versiones', + 'no_records' => 'Versiones del plugin no encontradas', + 'search' => 'Buscar...', + 'tab' => 'Versiones', + 'saved' => 'Versión guardada', + 'confirm_delete' => '¿Borrar esta versión?', + 'tab_new_version' => 'Nueva versión', + 'migration' => 'Migración', + 'seeder' => 'Seeder', + 'custom' => 'Increase the verison number', + 'apply_version' => 'Apply version', + 'applying' => 'Applying...', + 'rollback_version' => 'Rollback versión', + 'rolling_back' => 'Rolling back...', + 'applied' => 'Version applied', + 'rolled_back' => 'Version rolled back', + 'hint_save_unapplied' => 'You saved an unapplied version. Unapplied versions could be automatically applied when you or another user logs into the back-end or when a database table is saved in the Database section of the Builder.', + 'hint_rollback' => 'Rolling back a version will also roll back all versions newer than this version. Please note that unapplied versions could be automatically applied by the system when you or another user logs into the back-end or when a database table is saved in the Database section of the Builder.', + 'hint_apply' => 'Applying a version will also apply all older unapplied versions of the plugin.', + 'dont_show_again' => 'Don\'t show again', + 'save_unapplied_version' => 'Save unapplied version', + ], + 'menu' => [ + 'menu_label' => 'Backend Menu', + 'tab' => 'Menus', + 'items' => 'Items del menú', + 'saved' => 'Menues guardados', + 'add_main_menu_item' => 'Añadir item al menú principal', + 'new_menu_item' => 'Menu Item', + 'add_side_menu_item' => 'Agregar sub-item', + 'side_menu_item' => 'Item de menú lateral', + 'property_label' => 'Etiqueta', + 'property_label_required' => 'Por favor ingrese la etiqueta para el item del menú.', + 'property_url_required' => 'Por favor ingrese la URL para el item del menú', + 'property_url' => 'URL', + 'property_icon' => 'Icono', + 'property_icon_required' => 'Por favor seleccione un ícono', + 'property_permissions' => 'Permisos', + 'property_order' => 'Orden', + 'property_order_invalid' => 'Por favor ingrese el orden el item del menú como un valor numérico.', + 'property_order_description' => 'Menu item order manages its position in the menu. If the order is not provided, the item will be placed to the end of the menu. The default order values have the increment of 100.', + 'property_attributes' => 'Atributos HTML', + 'property_code' => 'Código', + 'property_code_invalid' => 'El código sólo puede contener letras y números', + 'property_code_required' => 'Please enter the menu item code.', + 'error_duplicate_main_menu_code' => 'Duplicate main menu item code: \':code\'.', + 'error_duplicate_side_menu_code' => 'Duplicate side menu item code: \':code\'.', + ], + 'localization' => [ + 'menu_label' => 'Localización', + 'language' => 'Lenguaje', + 'strings' => 'Cadenas', + 'confirm_delete' => '¿Borrar el lenguaje?', + 'tab_new_language' => 'Nuevo lenguaje', + 'no_records' => 'Lenguajes no encontrados', + 'saved' => 'Archivo de lenguaje guardado', + 'error_cant_load_file' => 'Cannot load the requested language file - file not found.', + 'error_bad_localization_file_contents' => 'Cannot load the requested language file. Language files can only contain array definitions and strings.', + 'error_file_not_array' => 'Cannot load the requested language file. Language files should return an array.', + 'save_error' => 'Error saving file \':name\'. Please check write permissions.', + 'error_delete_file' => 'Error deleting localization file.', + 'add_missing_strings' => 'Añadir cadenas que faltan', + 'copy' => 'Copiar', + 'add_missing_strings_label' => 'Select language to copy missing strings from', + 'no_languages_to_copy_from' => 'There are no other languages to copy strings from.', + 'new_string_warning' => 'Nueva cadena o sección', + 'structure_mismatch' => 'The structure of the source language file doesn\'t match the structure of the file being edited. Some individual strings in the edited file correspond to sections in the source file (or vice versa) and cannot be merged automatically.', + 'create_string' => 'Create new string', + 'string_key_label' => 'String key', + 'string_key_comment' => 'Enter the string key using period as a section separator. For example: plugin.search. The string will be created in the plugin\'s default language localization file.', + 'string_value' => 'String value', + 'string_key_is_empty' => 'String key should not be empty', + 'string_value_is_empty' => 'String value should not be empty', + 'string_key_exists' => 'The string key already exists', + ], + 'permission' => [ + 'menu_label' => 'Permisos', + 'tab' => 'Permisos', + 'form_tab_permissions' => 'Permisos', + 'btn_add_permission' => 'Añadir permisos', + 'btn_delete_permission' => 'Borrar permisos', + 'column_permission_label' => 'Código del permiso', + 'column_permission_required' => 'Por favor ingrese el código del permiso', + 'column_tab_label' => 'Titulo pestaña', + 'column_tab_required' => 'Por favor introduzca el permiso de el título de la pestaña', + 'column_label_label' => 'Etiqueta', + 'column_label_required' => 'Por favor introduzca permiso de etiqueta', + 'saved' => 'Permisos guardados', + 'error_duplicate_code' => 'Código de permiso duplicado: \':code\'.', + ], + 'yaml' => [ + 'save_error' => 'Error al guardar el archivo \':name\'. Consulte permisos de escritura.', + ], + 'common' => [ + 'error_file_exists' => 'El archivo ya existe: \':path\'.', + 'field_icon_description' => 'October usa Font Autumn icons: http://octobercms.com/docs/ui/icon', + 'destination_dir_not_exists' => 'El directorio de destino no existe: \':path\'.', + 'error_make_dir' => 'Error al crear directorio: \':name\'.', + 'error_dir_exists' => 'El directorio ya existe!: \':path\'.', + 'template_not_found' => 'Archivo de plantilla no encontrado: \':name\'.', + 'error_generating_file' => 'Error al generar el archivo: \':path\'.', + 'error_loading_template' => 'Error al cargar el archivo plantilla: \':name\'.', + 'select_plugin_first' => 'Seleccione primero un plugin. Para ver la lista de plugin, haga clic en el icono > en la barra lateral izquierda.', + 'plugin_not_selected' => 'Plugin no seleccionado', + 'add' => 'Añadir', + ], + 'migration' => [ + 'entity_name' => 'Migración', + 'error_version_invalid' => 'La versión debe ser especificada en el siguiente formato: 1.0.1', + 'field_version' => 'Versión', + 'field_description' => 'Descripción', + 'field_code' => 'Código', + 'save_and_apply' => 'Guardar y Aplicar', + 'error_version_exists' => 'La versión de la migración ya existe.', + 'error_script_filename_invalid' => 'El nombre del archivo de migración sólo puede contener letras, digitos y guiones bajos. El nombre de comenzar con el nombre debe comenzar con una letra y no puede contener espacios.', + 'error_cannot_change_version_number' => 'No se puede cambiar el número de la versión para una versión ya aplicada.', + 'error_file_must_define_class' => 'El código de la migración debe definir una clase de migración o de seeder. Dejar en blanco si solo quieres actualizar el número de la versión.', + 'error_file_must_define_namespace' => 'La migración debe definir un namespace. Deja el campo de código en blanco si solo quieres actualizar el número de la versión.', + 'no_changes_to_save' => 'No hay cambios que guardar.', + 'error_namespace_mismatch' => 'El código de la migración debe utilizar el namespace del plugin :namespace', + 'error_migration_file_exists' => 'El archivo de migración :file ya existe. Favor usa otro nombre para la clase.', + 'error_cant_delete_applied' => 'Esta versión ya ha sido aplicada y no puede ser eliminada. Favor haz un rollback a la versión primero.', + ], + 'components' => [ + 'list_title' => 'Lista de registros', + 'list_description' => 'Mostrar una lista de registros para el modelo seleccionado', + 'list_page_number' => 'Número de página', + 'list_page_number_description' => 'Este valor es usado para determinar en qué página se encuentra el usuario.', + 'list_records_per_page' => 'Registros por página', + 'list_records_per_page_description' => 'Número de registros a mostrar en una página. Dejar en blanco para desactivar paginación.', + 'list_records_per_page_validation' => 'Invalid format of the records per page value. The value should be a number.', + 'list_no_records' => 'No records message', + 'list_no_records_description' => 'Message to display in the list in case if there are no records. Used in the default component\'s partial.', + 'list_no_records_default' => 'No se han encontrado registros', + 'list_sort_column' => 'Ordenar por columna', + 'list_sort_column_description' => 'Model column the records should be ordered by', + 'list_sort_direction' => 'Dirección', + 'list_display_column' => 'Columna para mostrar', + 'list_display_column_description' => 'Column to display in the list. Used in the default component\'s partial.', + 'list_display_column_required' => 'Por favor, selecciona una columna para mostrar.', + 'list_details_page' => 'Página de detalles', + 'list_details_page_description' => 'Página para desplegar el registro de detalles.', + 'list_details_page_no' => '--No hay página de detalles--', + 'list_sorting' => 'Sorting', + 'list_pagination' => 'Paginación', + 'list_order_direction_asc' => 'Ascendente', + 'list_order_direction_desc' => 'Descendente', + 'list_model' => 'Model class', + 'list_scope' => 'Scope', + 'list_scope_description' => 'Optional model scope to fetch the records', + 'list_scope_default' => '--select a scope, optional--', + 'list_details_page_link' => 'Enlace a la página de detalles', + 'list_details_key_column' => 'Details key column', + 'list_details_key_column_description' => 'Model column to use as a record identifier in the details page links.', + 'list_details_url_parameter' => 'URL parameter name', + 'list_details_url_parameter_description' => 'Name of the details page URL parameter which takes the record identifier.', + 'details_title' => 'Detalles de un registro', + 'details_description' => 'Despliega el detalle de un registro para el modelo seleccionado', + 'details_model' => 'Clase del modelo', + 'details_identifier_value' => 'Identifier value', + 'details_identifier_value_description' => 'Identifier value to load the record from the database. Specify a fixed value or URL parameter name.', + 'details_identifier_value_required' => 'The identifier value is required', + 'details_key_column' => 'Key column', + 'details_key_column_description' => 'Model column to use as a record identifier for fetching the record from the database.', + 'details_key_column_required' => 'The key column name is required', + 'details_display_column' => 'Display column', + 'details_display_column_description' => 'Model column to display on the details page. Used in the default component\'s partial.', + 'details_display_column_required' => 'Por favor selecciona una columna para mostrar.', + 'details_not_found_message' => 'Mensaje registro no encontrado', + 'details_not_found_message_description' => 'Mensaje que se mostrará si el registro no fue encontrado. Usado en el partial del componente por defecto.', + 'details_not_found_message_default' => 'Registro no encontrado', + ], +]; diff --git a/plugins/rainlab/builder/lang/fa.json b/plugins/rainlab/builder/lang/fa.json new file mode 100644 index 0000000..8fafe6a --- /dev/null +++ b/plugins/rainlab/builder/lang/fa.json @@ -0,0 +1,4 @@ +{ + "Builder": "افزونه ساز", + "Provides visual tools for building October plugins.": "ساخت افزونه های اکتبر به صورت دیداری" +} \ No newline at end of file diff --git a/plugins/rainlab/builder/lang/fa/lang.php b/plugins/rainlab/builder/lang/fa/lang.php new file mode 100644 index 0000000..3675efa --- /dev/null +++ b/plugins/rainlab/builder/lang/fa/lang.php @@ -0,0 +1,622 @@ + [ + 'add' => 'ایجاد افزونه', + 'no_records' => 'افزونه ای یافت نشد', + 'no_description' => 'توضیحی برای این افزونه وارد نشده است', + 'no_name' => 'بدون نام', + 'search' => 'جستجو...', + 'filter_description' => 'نمایش تمام افزونه ها و یا افزونه های نوشته شده توسط شما', + 'settings' => 'تنظیمات', + 'entity_name' => 'افزونه', + 'field_name' => 'نام', + 'field_author' => 'صاحب امتیاز', + 'field_description' => 'توضحات', + 'field_icon' => 'آیکن افزونه', + 'field_plugin_namespace' => 'نیم اسپیس افزونه', + 'field_author_namespace' => 'نیم اسپیس صاحب امتیاز', + 'field_namespace_description' => 'نیم اسپیس میتواند شامل حروف لاتین و اعداد باشد و باید با یک حرف لاتین آغاز شود مانند: Blog', + 'field_author_namespace_description' => 'امکان تغییر نیم پس از ایجاد آن توسط افزونه ساز وجود ندارد نمونه ای از نیم اسپیس صاحب امتیاز: OctoberFa', + 'tab_general' => 'پارامتر های عمومی', + 'tab_description' => 'توضیحات', + 'field_homepage' => 'آدرس وب افزونه', + 'error_settings_not_editable' => 'تنظیمات این افزونه توسط افزونه ساز قابل ویرایش نمی باشد.', + 'update_hint' => 'امکان ترجمه نام و توضیحات افزونه در بخش ترجمه وجود دارد', + ], + 'author_name' => [ + 'title' => 'نام صاحب امتیاز', + 'description' => 'نام صاحب امتیاز به هنگام ایجاد افزونه جدید، این نام را همیشه میتوان در تنظیمات افزونه ویرایش کرد.', + ], + 'author_namespace' => [ + 'title' => 'نیم اسپیس صاحب امتیاز', + 'description' => 'اگر شما در فروشگاه افزونه ها حساب کاربری دارید این گزینه باید با نیم اسپیس آن حساب یکی باشد.', + ], + 'database' => [ + 'menu_label' => 'پایگاه داده', + 'no_records' => 'جدولی یافت نشد', + 'search' => 'جستجو...', + 'confirmation_delete_multiple' => 'آیا از حذف جدول های انتخاب شده اطمینان دارید؟', + 'field_name' => 'نام جدول', + 'tab_columns' => 'ستون ها', + 'column_name_name' => 'ستون', + 'column_name_required' => 'لطفا نام ستون را وارد نمایید', + 'column_name_type' => 'نوع', + 'column_type_required' => 'لطفا نوع ستون را وارد نمایید', + 'column_name_length' => 'طول', + 'column_validation_length' => 'مقدار این گزینه باید یک عدد صحیح بوده و برای داده های اعشاری در بازه 2 تا 10 باشد.', + 'column_validation_title' => 'این گزینه باید فقط شامل اعداد، حروف لاتین و خط زیر باشد.', + 'column_name_unsigned' => 'بدون علامت', + 'column_name_nullable' => 'nullable', + 'column_auto_increment' => 'افزایشی خودکار', + 'column_default' => 'پیشفرض', + 'column_auto_primary_key' => 'PK', + 'tab_new_table' => 'جدول جدید', + 'btn_add_column' => 'افزودن ستون', + 'btn_delete_column' => 'حذف ستون', + 'confirm_delete' => 'آیا از حذف ان جدول اطمینان دارید؟', + 'error_enum_not_supported' => 'جدول حاوی ستون(ها) ای با نوع enum می باشد که در حال حاظر توسط افزونه ساز پشتیبانی نمیشود.', + 'error_table_name_invalid_prefix' => 'نام جدول باید با پیشوند افزونه \':prefix\' آغاز شود. ', + 'error_table_name_invalid_characters' => 'نام جدول صحیح نمی باشد. نام جدول میتواند حاوی حروف لاتین، اعداد و خط زیر باشد و باید با حرف لاتین شروع شود. همچنین نام جدول نمیتواند شامل فاصله باشد.', + 'error_table_duplicate_column' => 'نام ستون \':column\' تکراری می باشد.', + 'error_table_auto_increment_in_compound_pk' => 'ستون افزایشی خودکار نمیتواند بخشی از کلید اصلی مرکب باشد', + 'error_table_mutliple_auto_increment' => 'جدول فقط میتواند شامل یک ستون افزایشی باشد.', + 'error_table_auto_increment_non_integer' => 'نوع ستون افزایشی باید عدد صحیح (integer) باشد.', + 'error_table_decimal_length' => 'طول نوع :type باید در قالب \'10,2\' بدون فاصله باشد.', + 'error_table_length' => 'طول نوع :type باید یک عدد صحیح باشد.', + 'error_unsigned_type_not_int' => 'خطا در ایجاد ستون \':column\'، فقط ستون هایی از نوع عدد صحیح میتوانند نشانه بدون علامت داشته باشند.', + 'error_integer_default_value' => 'مقدار پیشفرض وارد شده برای ستون \':column\' باید یک مقدار صحیح باشد.', + 'error_decimal_default_value' => 'مقدار پیشفرض وارد شده برای ستون \':column\' باید یک عدد اعشاری باشد.', + 'error_boolean_default_value' => 'مقدار پیشفرض ستون \':column\' باید 0 ویا 1 باشد', + 'error_unsigned_negative_value' => 'مقدار پیشفرض ستون \':column\' باید یک عدد صحیح مثبت باشد.', + 'error_table_already_exists' => 'نام جدول \':name\' تکراری می باشد.', + ], + 'model' => [ + 'menu_label' => 'مدل ها', + 'entity_name' => 'مدل', + 'no_records' => 'مدلی یافت نشد', + 'search' => 'جستجو...', + 'add' => 'افزودن...', + 'forms' => 'فرم ها', + 'lists' => 'لیست ها', + 'field_class_name' => 'نام کلاس', + 'field_database_table' => 'نام پایگاه داده', + 'error_class_name_exists' => 'نام مدل برای کلاس وارد شده :path تکاریست', + 'add_form' => 'فرم جدید', + 'add_list' => 'لیست جدید', + ], + 'form' => [ + 'saved' => 'فرم با موفقیت ذخیره شد.', + 'confirm_delete' => 'آیا از حذف این فرم اطمینان دارید؟', + 'tab_new_form' => 'فرم جدید', + 'property_label_title' => 'برچسب', + 'property_label_required' => 'لطفا برچسب را وارد نمایید', + 'property_span_title' => 'موقعیت', + 'property_comment_title' => 'توضیح', + 'property_comment_above_title' => 'توضیح بالا', + 'property_default_title' => 'پیشفرض', + 'property_checked_default_title' => 'انتخاب شده (پیشفرض)', + 'property_css_class_title' => 'کلاس CSS', + 'property_css_class_description' => 'کلاس CSS اختیاری جهت والد فیلد', + 'property_disabled_title' => 'غیر فعال', + 'property_hidden_title' => 'مخفی', + 'property_required_title' => 'اجباری', + 'property_field_name_title' => 'نام فیلد', + 'property_placeholder_title' => 'پیش نوشته (Placeholder)', + 'property_default_from_title' => 'فرم پیشفرض', + 'property_stretch_title' => 'کامل', + 'property_stretch_description' => 'اگر میخواهید طول فیلد درون والد خود کامل باشد این گزینه را انتخاب نمایید.', + 'property_context_title' => 'بخش', + 'property_context_description' => 'مشخص کننده نمایش فیلد در حالت های فرم', + 'property_context_create' => 'ایجاد', + 'property_context_update' => 'به روز رسانی', + 'property_context_preview' => 'پیش نمایش', + 'property_dependson_title' => 'وابستگی', + 'property_trigger_action' => 'عمل', + 'property_trigger_show' => 'نمایش', + 'property_trigger_hide' => 'عدم نمایش', + 'property_trigger_enable' => 'فعال', + 'property_trigger_disable' => 'غیر فعال', + 'property_trigger_empty' => 'خالی', + 'property_trigger_field' => 'فیلد', + 'property_trigger_field_description' => 'نام فیلدی را که عمل را اجرا میکند وارد نمایید', + 'property_trigger_condition' => 'شرط', + 'property_trigger_condition_description' => 'شرطی که در صورت درستی عمل انجام میشود. مقادیر پشتیبانی شده این فیلد: checked، unchecked، value[somevalue].', + 'property_trigger_condition_checked' => 'Checked', + 'property_trigger_condition_unchecked' => 'Unchecked', + 'property_trigger_condition_somevalue' => 'value[enter-the-value-here]', + 'property_preset_title' => 'از پیش تایین شده', + 'property_preset_description' => 'این امکان را میدهد که نام فیلد توسط فیلد دیگری مقدار دهی شده و با مبدل از پیش تعریف شده ای تبدیل شود.', + 'property_preset_field' => 'فیلد', + 'property_preset_field_description' => 'فیلد منبعی که مقدار از آن گرفته میشود را وارد نمایید.', + 'property_preset_type' => 'نوع', + 'property_preset_type_description' => 'مشخص کردن نوع تبدیل', + 'property_attributes_title' => 'ویژگی ها', + 'property_attributes_description' => 'ویژگی های HTML ای را که میخواهید به فیلد بدهید را وارد نمایید', + 'property_container_attributes_title' => 'ویژگی های والد', + 'property_container_attributes_description' => 'ویژگی های HTML ای که والد فیلد باید داشته باشد را وارد نمایید.', + 'property_group_advanced' => 'پیشرفته', + 'property_dependson_description' => 'فیلد های دیگری را که این فیلد به آنها وابسته می باشد و به هنگام تغییر آن ها این فیلد نیز تغییر پیدا میکند را وارد نمایید. هر فیلد در یک خط تعریف می شود.', + 'property_trigger_title' => 'عکس العمل', + 'property_trigger_description' => 'به فیلد این اجاره را میدهد که با تغییر فیلد دیگری ویژگی های خود را مانند حالت نمایش و مقدار خود کنترل نماید', + 'property_default_from_description' => 'مقدار پیشفرض را از مقدار فیلد دیگری بگیر.', + 'property_field_name_required' => 'ورود نام فیلد اجباریست', + 'property_field_name_regex' => 'نام فیلد میتواند شامل حروف لاتین، اعداد، خط زیر، خط تیره و کروشه باشد.', + 'property_attributes_size' => 'اندازه', + 'property_attributes_size_tiny' => 'خیلی کوچک', + 'property_attributes_size_small' => 'کوچک', + 'property_attributes_size_large' => 'متوسط', + 'property_attributes_size_huge' => 'بزرک', + 'property_attributes_size_giant' => 'خیلی بزرگ', + 'property_comment_position' => 'محل قرارگیری توضیح', + 'property_comment_position_above' => 'قبل', + 'property_comment_position_below' => 'بعد', + 'property_hint_path' => 'آدرس فایل بخش راهنما', + 'property_hint_path_description' => 'آدرس فایل بخشی که شامل متن راهنما می باشد. علامت $ به پوشه افزونه ها اشاره میکند برای مثال: $/acme/blog/partials/_hint.htm', + 'property_hint_path_required' => 'لطفا مسیر بخش راهنما را وارد نمایید.', + 'property_partial_path' => 'مسیر بخش', + 'property_partial_path_description' => 'مسیر فال مربوط به بخش را وارد نمایید. علامت $ به پوشه پلاگین ها اشاره میکند برای مثال: $/acme/blog/partials/_hint.htm', + 'property_partial_path_required' => 'لطفا مسیر فایل بخش را وارد نمایید.', + 'property_code_language' => 'زبان', + 'property_code_theme' => 'قالب', + 'property_theme_use_default' => 'استفاده از قالب پیشفرض', + 'property_group_code_editor' => 'ویرایشگر کد', + 'property_gutter' => 'شیار', + 'property_gutter_show' => 'قابل مشاهده', + 'property_gutter_hide' => 'مخقی', + 'property_wordwrap' => 'Word wrap', + 'property_wordwrap_wrap' => 'Wrap', + 'property_wordwrap_nowrap' => 'Don\'t wrap', + 'property_fontsize' => 'اندازه فونت', + 'property_codefolding' => 'Code folding', + 'property_codefolding_manual' => 'دستی', + 'property_codefolding_markbegin' => 'علامت گذازی آغاز', + 'property_codefolding_markbeginend' => 'علامت گذاری آغاز و پایان', + 'property_autoclosing' => 'بستن خودکار', + 'property_enabled' => 'فعال', + 'property_disabled' => 'غیر فعال', + 'property_soft_tabs' => 'استفاده از فاصله به جای Tab', + 'property_tab_size' => 'اندازه Tab', + 'property_readonly' => 'فقط خواندنی', + 'property_use_default' => 'استفاده از تنظیمات پیشفرض', + 'property_options' => 'گزینه ها', + 'property_prompt' => 'متن', + 'property_prompt_description' => 'متن نمایش داده شده برای دکمه ایجاد', + 'property_prompt_default' => 'افزودن گزینه جدید', + 'property_available_colors' => 'رنگ های موجود', + 'property_available_colors_description' => 'لیست رنگ های موجود در قالب هگزادسیمال (#FF0000). برای استفاده از رنگ های پیشفرض این گزینه را خالی رها کنید. در هر خط یک رنگ وارد نمایید.', + 'property_datepicker_mode' => 'نحوه نمایش', + 'property_datepicker_mode_date' => 'تاریخ', + 'property_datepicker_mode_datetime' => 'تاریخ و ساعت', + 'property_datepicker_mode_time' => 'ساعت', + 'property_datepicker_min_date' => 'کمترین تاریخ', + 'property_datepicker_max_date' => 'بیشترین تاریخ', + 'property_fileupload_mode' => 'نحوه نمایش', + 'property_fileupload_mode_file' => 'فایل', + 'property_fileupload_mode_image' => 'تصویر', + 'property_group_fileupload' => 'ارسال فایل', + 'property_fileupload_image_width' => 'عرض تصویر', + 'property_fileupload_image_width_description' => 'گزینه اختیاری جهت تغییر اندازه عرض تصویر که فقط در حالت تصویر مورد استفاده قرار میگیرد.', + 'property_fileupload_invalid_dimension' => 'مقدار وارد شده صحیح نیست. لطفا یک عدد وارد نمایید', + 'property_fileupload_image_height' => 'طول تصویر', + 'property_fileupload_image_height_description' => 'گزینه اختیاری جهت تغییر اندازه طول تصویر که فقط در حالت تصویر مورد استفاده قرار میگیرد.', + 'property_fileupload_file_types' => 'نوع فایل ها', + 'property_fileupload_file_types_description' => 'گزینه اختیاری جهت تایین پسوند فایل های ارسالی که با کاما از هم جدا شنده اند برای مثال: zip,txt', + 'property_fileupload_mime_types' => 'MIME types', + 'property_fileupload_mime_types_description' => 'لیست اختیاری از MIME Type های مجاز جهت ارسال فایل که با کاما از هم جدا شده اند برای مثال: bin,txt', + 'property_fileupload_use_caption' => 'از عنوان استفاده شود', + 'property_fileupload_use_caption_description' => 'اجازه ورود عنوان و توضیحات برای فایل ارسالی.', + 'property_fileupload_thumb_options' => 'گزینه های تصویر بند انگشتی', + 'property_fileupload_thumb_options_description' => 'مدیریت گزینه های تولید خودکار تصویر بند انگشتی که فقط در حالت تصویر مورد استفاده قرار میگیرد.', + 'property_fileupload_thumb_mode' => 'حالت نمایش', + 'property_fileupload_thumb_auto' => 'خودکار', + 'property_fileupload_thumb_exact' => 'دقیقا', + 'property_fileupload_thumb_portrait' => 'Portrait', + 'property_fileupload_thumb_landscape' => 'Landscape', + 'property_fileupload_thumb_crop' => 'Crop', + 'property_fileupload_thumb_extension' => 'پسوند فایل', + 'property_name_from' => 'نام ستون', + 'property_name_from_description' => 'نام ستون ارتباطی جهت نمایش نام.', + 'property_description_from' => 'ستون توضیحات', + 'property_description_from_description' => 'نام ستون ارتباطی جهت نمایش توضیحات.', + 'property_recordfinder_prompt' => 'متن', + 'property_recordfinder_prompt_description' => 'متنی که به هنگام نبود هیچ رکوردی به نمایش در می آید. %s بیانگر آیکن جستجو می باشد. جهت استفاده از مقدار پیشفرض این گزینه را خالی رها کنید.', + 'property_recordfinder_list' => 'تنظیمات لیست', + 'property_recordfinder_list_description' => 'مرجعی برای تعریف ستون های لیست. علامت $ به پوشه افزونه ها اشاره میکند برای مثال: $/acme/blog/lists/_list.yaml', + 'property_recordfinder_list_required' => 'لطفا آدرس فایل YAML را وارد نمایید', + 'property_group_recordfinder' => 'انتخابگر رکورد', + 'property_mediafinder_mode' => 'حالت نمایش', + 'property_mediafinder_mode_file' => 'فایل', + 'property_mediafinder_mode_image' => 'تصویر', + 'property_group_relation' => 'ارتباط', + 'property_relation_select' => 'تحديد', + 'property_relation_select_description' => 'كونكات أعمدة متعددة معا لعرض اسم', + 'property_relation_prompt' => 'متن', + 'property_relation_prompt_description' => 'متنی که به هنگام موجود نبودن موردی جهت انتخاب نمایش داده میشود.', + 'control_group_standard' => 'استاندارد', + 'control_group_widgets' => 'ابزارک ها', + 'click_to_add_control' => 'افزودن کنترل', + 'loading' => 'درحال بارگذاری...', + 'control_text' => 'متن', + 'control_text_description' => 'ابزار ورود متن تک خطی', + 'control_password' => 'کلمه عبور', + 'control_password_description' => 'ابزار ورود کلمه عبور', + 'control_checkbox' => 'چک باکس', + 'control_checkbox_description' => 'یک چک باکس', + 'control_switch' => 'سویچ', + 'control_switch_description' => 'سوئیچ روشن و خاموش که میتواند جایگزین چک باکس شود.', + 'control_textarea' => 'متن چند خطی', + 'control_textarea_description' => 'ابزار ورود متن چند خطی', + 'control_dropdown' => 'لیست بازشونده', + 'control_dropdown_description' => 'لیست بازشونده با موارد مشخص و یا متغیر', + 'control_unknown' => 'نوع ابزار :type یافت نشد', + 'control_repeater' => 'تکرار کننده', + 'control_repeater_description' => 'تکرار کننده مجموعه ای از ابزار ها', + 'control_number' => 'عدد', + 'control_number_description' => 'ابزار تک خطی جهت ورود عدد.', + 'control_hint' => 'هشدار', + 'control_hint_description' => 'نشان دهنده یک بخش به عنوان هشدار و یا راهنمایی که میتواند توسط کاربر مخفی شود.', + 'control_partial' => 'بخش', + 'control_partial_description' => 'نشان دهنده محتوی یک بخش', + 'control_section' => 'قسمت', + 'control_section_description' => 'نمایش یک قسمت از فرم با عنوان و زیر عنوان', + 'control_radio' => 'لیست رادیویی', + 'control_radio_description' => 'لیستی از انتخاب گر های رادیویی که در هر لحظه فقط یک مورد میتواند انتخاب شود.', + 'control_radio_option_1' => 'گزینه 1', + 'control_radio_option_2' => 'گزینه 2', + 'control_checkboxlist' => 'لیست چک باکس', + 'control_checkboxlist_description' => 'لیستی از چک باکس', + 'control_codeeditor' => 'ادیتور کد', + 'control_codeeditor_description' => 'ادیتور کد که جهت ورود کد مورد استفاده قرار میگیرد', + 'control_colorpicker' => 'انتخابگر رنگ', + 'control_colorpicker_description' => 'فیلدی جهت انتخاب کد هگزادسیمال رنگ', + 'control_datepicker' => 'انتخابگر تاریخ', + 'control_datepicker_description' => 'ابزاری جهت انتخای تاریخ و زمان', + 'control_richeditor' => 'ویرایشگر متن', + 'control_richeditor_description' => 'ابزاری جهت ویرایش و فرمت بندی متن', + 'control_markdown' => 'ویرایشگر مارک داون', + 'control_markdown_description' => 'ویرایشگر ابتدایی جهت ورود و ویرایش متن در قالب مارک داون', + 'control_fileupload' => 'ارسال فایل', + 'control_fileupload_description' => 'ارسال کننده فایل جهت ارسال تصویر و یا فایل', + 'control_recordfinder' => 'انتخاب گر موارد', + 'control_recordfinder_description' => 'ابزاری جهت انتخاب موارد مرتبط در پایگاه داده با امکان جستجو', + 'control_mediafinder' => 'انتخابگر چند رسانه ای', + 'control_mediafinder_description' => 'ابزاری جهت انتخاب فایل های چند رسانه ای در ابزار مدیریت چند رسانه ای', + 'control_relation' => 'ارتباط', + 'control_relation_description' => 'نمایش لیست بازشونده و یا لیست چک باکس جهت انتخاب ارتباطات پایگاه داده', + 'error_file_name_required' => 'لطفا نام فایل فرم را وارد نمایید.', + 'error_file_name_invalid' => 'نام فایل میتواند شامل حروف لاتین، اعداد، خط زیر، خط تیره و یا نقطه باشد.', + 'span_left' => 'چپ', + 'span_right' => 'راست', + 'span_full' => 'کامل', + 'span_auto' => 'خودکار', + 'empty_tab' => 'بخش خالی', + 'confirm_close_tab' => 'بخش حاوی ابزار هایی می باشد که پاک خواهند شد. آیا میخواهید ادامه دهید؟', + 'tab' => 'بخش فرم', + 'tab_title' => 'عنوان', + 'controls' => 'ابزار ها', + 'property_tab_title_required' => 'وارد کردن عنوان بخش اجباریست', + 'tabs_primary' => 'بخش اصلی', + 'tabs_secondary' => 'بخش ثانویه', + 'tab_stretch' => 'کامل', + 'tab_stretch_description' => 'مشخص میکند که طول بخش برابر با طول والد خود باشد یا خیر', + 'tab_css_class' => 'کلاس CSS', + 'tab_css_class_description' => 'مقدار دهی خاصیت کلاس دربرگیرنده ابزار', + 'tab_name_template' => 'بخش %s', + 'tab_already_exists' => 'بخشی با نام مشخص شده وجود دارد', + ], + 'list' => [ + 'tab_new_list' => 'لیست جدید', + 'saved' => 'لیست با موفقیت ذخیره شد.', + 'confirm_delete' => 'آیا از حذف این لیست اطمینان دارید؟', + 'tab_columns' => 'ستون ها', + 'btn_add_column' => 'ستون جدید', + 'btn_delete_column' => 'حذف ستون', + 'column_dbfield_label' => 'فیلد', + 'column_dbfield_required' => 'لطفا فیلد مدل را وارد نمایید', + 'column_name_label' => 'عنوان', + 'column_label_required' => 'لطفا عنوان ستون را وارد نمایید.', + 'column_type_label' => 'نوع', + 'column_type_required' => 'لطفا نوع ستون را وارد نمایید.', + 'column_type_text' => 'متن', + 'column_type_number' => 'عدد', + 'column_type_switch' => 'سوییچ', + 'column_type_datetime' => 'تاریخ و زمان', + 'column_type_date' => 'تاریخ', + 'column_type_time' => 'زمان', + 'column_type_timesince' => 'تفاوت زمانی', + 'column_type_timetense' => 'تفاوت زمانی', + 'column_type_select' => 'انتخاب', + 'column_type_partial' => 'بخش', + 'column_label_default' => 'پیشفرض', + 'column_label_searchable' => 'قابلیت جستجو', + 'column_label_sortable' => 'قابلیت مرتب سازی', + 'column_label_invisible' => 'مخفی', + 'column_label_select' => 'انتخاب', + 'column_label_relation' => 'ارتباط پایگاه داده', + 'column_label_css_class' => 'کلاس CSS', + 'column_label_width' => 'عرض', + 'column_label_path' => 'مسیر', + 'column_label_format' => 'قالب', + 'column_label_value_from' => 'مقدار گرفته شده از', + 'error_duplicate_column' => 'نام \':column\' برای ستون تکراری میباشد.', + ], + 'controller' => [ + 'menu_label' => 'کنترلر ها', + 'no_records' => 'کنترلری در افزونه یافت نشد.', + 'controller' => 'کنترلر', + 'behaviors' => 'کنترل کننده رفتار از پیش تایین شده', + 'new_controller' => 'کنترلر جدید', + 'error_controller_has_no_behaviors' => 'کنترلر حاوی کنترل کننده رفتار از پیش تایین شده که حاوی تنظیمات باشد ندارد', + 'error_invalid_yaml_configuration' => 'خطایی در بارگذاری فایل :file مربوط به تنظیمات کنترل کننده رفتار از پیش تایین شده به وجود آمده است', + 'behavior_form_controller' => 'کنترل کننده رفتار از پیش تایین شده فرم', + 'behavior_form_controller_description' => 'افزودن امکان مدیریت فرم ها به صفحه مدیریت. این امکان سه صفحه ایجاد، به روزرسانی و پیش نمایش را اضافه میکند.', + 'property_behavior_form_placeholder' => '--انتخاب فرم--', + 'property_behavior_form_name' => 'نام', + 'property_behavior_form_name_description' => 'نام شی ای که توسط فرم مدیریت می شود', + 'property_behavior_form_name_required' => 'لطفا نام فرم را وارد نمایید.', + 'property_behavior_form_file' => 'تنظیمات فرم', + 'property_behavior_form_file_description' => 'به یک فایل تعریف فرم اشاره میکند.', + 'property_behavior_form_file_required' => 'لطفا آدرس فایل تنظیمات فرم را وارد نمایید.', + 'property_behavior_form_model_class' => 'کلاس مدل', + 'property_behavior_form_model_class_description' => 'نام کلاس مدل که داده ها از آن بارگذاری شده و ذخیره می شوند.', + 'property_behavior_form_model_class_required' => 'لطفا نام کلاس مدل را وارد نمایید', + 'property_behavior_form_default_redirect' => 'مسیر انتقال پیشفرض', + 'property_behavior_form_default_redirect_description' => 'آدرس صفحه ای جهت انتقال به هنگامی که فرم ذخیره میشود یا کاربر از ادامه کار انصراف می دهد.', + 'property_behavior_form_create' => 'صفحه ایجاد', + 'property_behavior_form_redirect' => 'انتقال', + 'property_behavior_form_redirect_description' => 'آدرس صفحه ای که به هنگام ایجاد مورد جدید به آن انتقال داده میشود', + 'property_behavior_form_redirect_close' => 'انتقال به هنگام خروج', + 'property_behavior_form_redirect_close_description' => 'آدرس صفحه ای که به هنگام کلیک دکمه انتقال و خروج به آن انتقال داده می شود.', + 'property_behavior_form_flash_save' => 'پیغام نمایش داده شده به هنگام ذخیره', + 'property_behavior_form_flash_save_description' => 'پیغامی که به هنگام ذخیره مورد نمایش داده می شود.', + 'property_behavior_form_page_title' => 'عنوان صفحه', + 'property_behavior_form_update' => 'صفحه ویرایش', + 'property_behavior_form_update_redirect' => 'انتقال', + 'property_behavior_form_create_redirect_description' => 'صفحه ای که به هنگام ذخیره مورد به آن انتقال داده می شود.', + 'property_behavior_form_flash_delete' => 'پیغام حذف', + 'property_behavior_form_flash_delete_description' => 'پیغامی که به هنگام حذف نمایش داده میشود.', + 'property_behavior_form_preview' => 'صفحه پیش نمایش', + 'behavior_list_controller' => 'کنترل کننده رفتار از پیش تایین شده لیست', + 'behavior_list_controller_description' => 'امکان نمایش لیستی با قابلیت جستجو و مرتب سازی را به کنترلر اظافه میکند. این امکان صفحه اصلی (index) را در کنترلر ایجاد میکند.', + 'property_behavior_list_title' => 'عنوان لیست', + 'property_behavior_list_title_required' => 'لطفا عنوان لیست را وارد نمایید', + 'property_behavior_list_placeholder' => '--انتخاب لیست--', + 'property_behavior_list_model_class' => 'کلاس مدل', + 'property_behavior_list_model_class_description' => 'نام کلاس مدلی که اطلاعات لیست از آن بارگذاری میشود.', + 'property_behavior_form_model_class_placeholder' => '--انتخاب مدل--', + 'property_behavior_list_model_class_required' => 'لطفا کلاس مدل را انتخاب نمایید', + 'property_behavior_list_model_placeholder' => '--انتخاب مدل--', + 'property_behavior_list_file' => 'فایل تنظیمات لیست', + 'property_behavior_list_file_description' => 'به یک فایل تعریف لیست اشاره میکند', + 'property_behavior_list_file_required' => 'لطفا مسیر فایل تنظیمات لیست را وارد نمایید.', + 'property_behavior_list_record_url' => 'آدرس مورد', + 'property_behavior_list_record_url_description' => 'آدرس صفحه هر مورد در لیست که در آن :id به مشخصه لیست اشاره میکند برای مثال: users/update:id', + 'property_behavior_list_no_records_message' => 'پیغام خالی بودن لیست', + 'property_behavior_list_no_records_message_description' => 'پیغامی که به هنگام خالی بودن لیست به نمایش در می آید.', + 'property_behavior_list_recs_per_page' => 'تعداد موارد در هر صفحه', + 'property_behavior_list_recs_per_page_description' => 'تعداد موارد در هر صفحه را مشخص میکند برای نمایش تمام موارد در یک صفحه این مقدار را 0 قرار دهید. مقدار پیشفرض: 0', + 'property_behavior_list_recs_per_page_regex' => 'مقدار تعداد موارد در هر صفحه باید یک عدد صحیح باشد.', + 'property_behavior_list_show_setup' => 'نمایش دکمه تنظیمات', + 'property_behavior_list_show_sorting' => 'نمایش مرتب سازی', + 'property_behavior_list_default_sort' => 'مرتب سازی پیشفرض', + 'property_behavior_form_ds_column' => 'ستون', + 'property_behavior_form_ds_direction' => 'جهت مرتب سازی', + 'property_behavior_form_ds_asc' => 'صعودی', + 'property_behavior_form_ds_desc' => 'نزولی', + 'property_behavior_list_show_checkboxes' => 'نمایش چک باکس', + 'property_behavior_list_onclick' => 'کنترل کننده کلیک', + 'property_behavior_list_onclick_description' => 'کد شخصی سازی شده جاوا اسکریپت به هنگام کلیک هر رکورد.', + 'property_behavior_list_show_tree' => 'نمایش درخت وار', + 'property_behavior_list_show_tree_description' => 'نمایش درخت وار موارد والد و فرزندی.', + 'property_behavior_list_tree_expanded' => 'درخت باز شده', + 'property_behavior_list_tree_expanded_description' => 'آیا تمامی موارد درخت به صورت پیشفرض باز باشند؟', + 'property_behavior_list_toolbar' => 'نوار ابزار', + 'property_behavior_list_toolbar_buttons' => 'بخش دکمه ها', + 'property_behavior_list_toolbar_buttons_description' => 'به یک فایل بخش موجود در کنترلر اشاره میکند. به عنوان مثال: list_toolbar', + 'property_behavior_list_search' => 'جستجو', + 'property_behavior_list_search_prompt' => 'متن جستجو', + 'property_behavior_list_filter' => 'تنظیمات فیلتر', + 'error_controller_not_found' => 'فایل کنترلر یافت نشد', + 'error_invalid_config_file_name' => 'تعریف فایل (:file) مربوط به کنترل کننده از پیش تایین شده :class صحیح نمی باشد.', + 'error_file_not_yaml' => 'فایل تنطیمات (:file) مربوط به کنترل کننده از پیش تایین شده باید از نوع YAML باشد.', + 'saved' => 'کنترلر با موفقیت ذخیره شدو', + 'controller_name' => 'نام کنترلر', + 'controller_name_description' => 'نام کنترلر مشخص کننده نام و آدرس آن در صفحه مدیریت می باشد و باید از استاندارد های نامگذاری متغیر در PHP پیروی کند. همچنین نام باید با حرف بزرگ لاتین شروع شود برای مثال: Categories', + 'base_model_class' => 'کلاس مدل', + 'base_model_class_description' => 'نام کلاس مدلی را که جهت استفاده توسط کنترل کننده های رفتار از پیش تایین شده مورد استفاده قرار میگیرد را وارد نمایید.', + 'base_model_class_placeholder' => '--انتخاب مدل--', + 'controller_behaviors' => 'کنترل کننده های رفتار از پیش تایین شده', + 'controller_behaviors_description' => 'لطفا کنترل کننده های رفتار از پیش تایین شده برای کنترلر را انتخاب نمایید. سازنده فایل های نمایش مربوط به هر یک از آنها را به صورت خودکار ایجاد میکند.', + 'controller_permissions' => 'مجوزهای دسترسی', + 'controller_permissions_description' => 'مجوز های دسترسی برای هر یک از بخش های کنترلر را وارد نمایید. مجوز ها در بخش مجوز ها قابل تعریف میباشند و شما میتوانید آنها را بعدا در کد PHP ویرایش نمایید.', + 'controller_permissions_no_permissions' => 'این افزونه دارای مجوزی نمی باشد.', + 'menu_item' => 'منوی فعال', + 'menu_item_description' => 'منو ای را که میخواهید به هنگام نمایش صفحه کنترلر فعال شود انتخاب نمایید. این گزینه بعدا در کد PHP کنترلر قابل تغییر می باشد.', + 'menu_item_placeholder' => '--انتخاب منو--', + 'error_unknown_behavior' => 'کنترل کننده رفتار از پیش تایین شده :class در شی مدیریت این موارد اضافه نشده است.', + 'error_behavior_view_conflict' => 'کنترل کننده های رفتار از پیش تایین شده انتخاب شده دارای موارد تداخلی (:view) می باشد و نمیتواند همزمان استفاده شود.', + 'error_behavior_config_conflict' => 'کنترل کننده های رفتار انتخاب شده حاوی فایل تنظیمات (:file) تداخلی بود و نمی توانند همزمان استفاده شوند.', + 'error_behavior_view_file_not_found' => 'قالب نمایشی :view در کنترل کننده رفتار از پیش تایین شده :class یافت نشد.', + 'error_behavior_config_file_not_found' => 'قالب فایل تنظیمات :file در کنترل کننده رفتار از پیش تایین شده :class یافت نشد.', + 'error_controller_exists' => 'فایل کنترلر :file قبلا ایجاد شده است.', + 'error_controller_name_invalid' => 'نام کنترلر صحیح نمی باشد. نام میتواند شامل حروف لاتین و اعداد بوده و باید با یک حرف بزرگ لاتین شروع شود.', + 'error_behavior_view_file_exists' => 'فایل نمایشی کنترلر :view قبلا ایجاد شده است.', + 'error_behavior_config_file_exists' => 'فایل تنظیمات :file مربوط به کنترل کننده رفتار از پیش تایین شده قبلا ایجاد شده است.', + 'error_save_file' => 'خطا به هنگام ذخیره فایل کنترلر: :file', + 'error_behavior_requires_base_model' => 'کنترل کننده رفتار از پیش تایین شده :behavior نیاز به انتخاب شدن کلاس مدل دارد.', + 'error_model_doesnt_have_lists' => 'مدل انتخاب شده حاوی لیستی نمی باشد. لطفا یک لیست برای آن ایجاد کنید.', + 'error_model_doesnt_have_forms' => 'مدل انتخاب شده حاوی فرمی نمی باشد. لطفا یک فرم برای آن ایجاد کنید.', + ], + 'version' => [ + 'menu_label' => 'ویرایش ها', + 'no_records' => 'ویرایشی برای افزونه یافت نشد', + 'search' => 'جستجو...', + 'tab' => 'ویرایش ها', + 'saved' => 'ویرایش با موفقیت ذخیره شد.', + 'confirm_delete' => 'آیا از حذف این ویرایش اطمینان دارید؟', + 'tab_new_version' => 'ویرایش جدید', + 'migration' => 'ساختار پایگاه داده', + 'seeder' => 'داده های پایگاه داده', + 'custom' => 'افزودن عدد ویرایش', + 'apply_version' => 'اعمال ویرایش', + 'applying' => 'درحال اعمال...', + 'rollback_version' => 'عقب گرد ویرایش', + 'rolling_back' => 'درحال عقبگرد...', + 'applied' => 'ویرایش با موفقیت اعمال شد.', + 'rolled_back' => 'ویرایش با موفقیت به عقب بازگشت.', + 'hint_save_unapplied' => 'شما یک نسخه اعمال نشده را ذخیره کردید. این نسخه ها به هنگام ورود شما و یا کاربر دیگری و یا ذخیره جدولی در پایگاه داده به صورت خودکار اعمال خواهند شد.', + 'hint_rollback' => 'ویرایش های قبلی و بازگشت داده شده به صورت خودکار در هنگام اعمال ویرایش جدید تر، ورود به بخش مدیریت و یا ایجاد و ذخیره جدولی در پایگاه داده به صورت خودکار اعمال خواهند شد.', + 'hint_apply' => 'اعمال یک ویرایش تمامی ویرایش های قبلی اعمال نشده را نیز اعمال خواهد کرد', + 'dont_show_again' => 'مجددا نمایش نده.', + 'save_unapplied_version' => 'ذخیره ویرایش اعمال نشده', + ], + 'menu' => [ + 'menu_label' => 'منوی مدیریت', + 'tab' => 'منو ها', + 'items' => 'موارد منو', + 'saved' => 'این منو با موفقیت ذخیره شد.', + 'add_main_menu_item' => 'افزودن منوی جدید در ریشه', + 'new_menu_item' => 'مورد منو', + 'add_side_menu_item' => 'افزودن زیر منو', + 'side_menu_item' => 'مورد منوی کناری', + 'property_label' => 'عنوان', + 'property_label_required' => 'لطفا عنوان منو را وارد نمایید', + 'property_url_required' => 'لطفا آدرس منو را وارد نمایید', + 'property_url' => 'آدرس', + 'property_icon' => 'آیکن', + 'property_icon_required' => 'لطفا آیکن منو را وارد نمایید', + 'property_permissions' => 'مجوز ها', + 'property_order' => 'ترتیب', + 'property_order_invalid' => 'مقدار وارد شده برای ترتیب منو باید عدد صحیح باشد.', + 'property_order_description' => 'ترتیب منو مشخص کننده ترتیب قرارگیری آن می باشد و اگر وارد نشود منو در انتهای لیست قرار میگیرد. مقدار این مورد بهتر است بیش از عدد 100 باشد.', + 'property_attributes' => 'خصوصیات HTML', + 'property_code' => 'کد', + 'property_code_invalid' => 'کد میتواند حاوی حروف لاتین و اعداد باشد.', + 'property_code_required' => 'لطفا کد مربوط به منو را وارد نمایید.', + 'error_duplicate_main_menu_code' => 'کد \':code\' وارد شده برای منوی اصلی تکراریست.', + 'error_duplicate_side_menu_code' => 'کد \':code\' وارد شده برای منوی کناری تکراریست.', + ], + 'localization' => [ + 'menu_label' => 'بومی سازی', + 'language' => 'زبان', + 'strings' => 'رشته های متنی', + 'confirm_delete' => 'آیا از حذف این زبان اطمینان دارید؟', + 'tab_new_language' => 'ربان جدید', + 'no_records' => 'زبانی یافت نشد.', + 'saved' => 'فایل زبان با موفقیت ذخیره شد.', + 'error_cant_load_file' => 'فایل زبان مورد درخواست یافت نشد.', + 'error_bad_localization_file_contents' => 'خطا در بارگذاری فایل زبان. فایل زبان میتواند شامل تعریف آرایه و رشته های متنی باشد.', + 'error_file_not_array' => 'خطا در بارگذاری فایل زبان. فایل زبان باید یک آرایه بازگرداند/', + 'save_error' => 'خطا در ذخیره فایل \':name\'. لطفا مجوز خای ذخیره فایل را بررسی نمایید.', + 'error_delete_file' => 'خطا در حذف فایل زبان.', + 'add_missing_strings' => 'افزودن رشته های جدید', + 'copy' => 'کپی', + 'add_missing_strings_label' => 'زبانی را که حاوی رشته جدید میباشد را انتخاب نمایید.', + 'no_languages_to_copy_from' => 'زبان دیگری جهت کپی رشته های جدید موجود نمی باشد.', + 'new_string_warning' => 'رشته یا بخش جدید', + 'structure_mismatch' => 'ساختار فایل منبع زبان با فایلی که در حال ویرایش می باشد مطابقت ندارد. برخی رشته ها در فایل در حال ویرایش فایل منبع را دچار مشکل میکند و فایل ها به صورت خودکار قابلیت تجمیع ندارند. ', + 'create_string' => 'ایجاد رشته متنی جدید', + 'string_key_label' => 'کلید رشته متنی', + 'string_key_comment' => 'کلید رشته متنی را که از نقطه به عنوان جدا کننده بخش ها استفاده میکند وارد نمایید. به عنوان مثال: plugin.search. رشته متنی در زبان پیشفرض بومی سازی افزونه ذخیره خواهد شد.', + 'string_value' => 'مقدار رشته متنی', + 'string_key_is_empty' => 'ورود کلید رشته متنی اجباریست.', + 'string_value_is_empty' => 'ورود مقدار رشته متنی اجباریست.', + 'string_key_exists' => 'کلید رشته وارد شده تکراری می باشد.', + ], + 'permission' => [ + 'menu_label' => 'مجوز های دسترسی', + 'tab' => 'مجوز های دسترسی', + 'form_tab_permissions' => 'مجوز های دسترسی', + 'btn_add_permission' => 'مجوز دسترسی جدید', + 'btn_delete_permission' => 'حذف مجوز دسترسی', + 'column_permission_label' => 'کد مجوز دسترسی', + 'column_permission_required' => 'لطفا کد مجوز دسترسی را وارد نمایید', + 'column_tab_label' => 'عنوان بخش', + 'column_tab_required' => 'لطفا عنوان بخش مجوز دسترسی را وارد نمایید', + 'column_label_label' => 'عنوان', + 'column_label_required' => 'لطفا عنوان مجوز دسترسی را وارد نمایید.', + 'saved' => 'مجوز های دسترسی با موفقیت ذخیره شدند.', + 'error_duplicate_code' => 'کد وارد شده \':code\' برای مجوز دسترسی تکراری می باشد.', + ], + 'yaml' => [ + 'save_error' => 'خطا در ذخیره فایل \':name\'. لطفا مجوزهای مربوط به نوشتن بر روی دیسک را بررسی نمایید.', + ], + 'common' => [ + 'error_file_exists' => 'فایل \':path\' قبلا ایجاد شده است.', + 'field_icon_description' => 'اکتبر از آیکن فونت خود به آدری http://daftspunk.github.io/Font-Autumn استفاده می نماید', + 'destination_dir_not_exists' => 'پوشه هدف به آدرس \':path\' یافت نشد.', + 'error_make_dir' => 'خطا در ایجاد پوشه به آدرس \':name\'', + 'error_dir_exists' => 'پوشه \':path\' قبلا ایجاد شده است.', + 'template_not_found' => 'فایل قالب \':name\' یافت نشد.', + 'error_generating_file' => 'خطا در تولید فایل \':path\'.', + 'error_loading_template' => 'خطا در بارگذاری قالب \':name\'.', + 'select_plugin_first' => 'لطفا افزونه ای را انتخاب نمایید. جهت انتخاب افزونه بر روی آیکون > در سمت راست منوی کناری کلیک نمایید.', + 'plugin_not_selected' => 'افزونه ای انتخاب نشده است', + 'add' => 'افرودن', + ], + 'migration' => [ + 'entity_name' => 'ساختار بانک اطلاعاتی', + 'error_version_invalid' => 'ویرایش باید در این قالب وارد شود: 1.0.1', + 'field_version' => 'ویرایش', + 'field_description' => 'توضیحات', + 'field_code' => 'کد', + 'save_and_apply' => 'ذخیره و اعمال', + 'error_version_exists' => 'فایل ساختار بانک اطلاعاتی قبلا تعریف شده است.', + 'error_script_filename_invalid' => 'نام فایل ساختار بانک اطلاعاتی فقط میتواند حاوی حروف لاتین، اعداد و خط زیر باشد و با یک حرف لاتین بزرگ شروع شود.', + 'error_cannot_change_version_number' => 'شماره ویرایش اعمال شده قابل تغییر نمی باشد.', + 'error_file_must_define_class' => 'کد ساختار بانک اطلاعاتی باید کلاس migration و یا seeder را تعریف کند. اگر فقط میخواهید فقط نسخه را افزایش دهید کد را خالی بگذارید.', + 'error_file_must_define_namespace' => 'ساختار بانک اطلاعاتی باشد شامل نیم اسپیس باشد. اگر فقط میخواهید شماره ویرایش را افزایش دهید کد را خالی بگذارید.', + 'no_changes_to_save' => 'تغییراتی جهت ذخیره وجود ندارد.', + 'error_namespace_mismatch' => 'کد ساختار بانک اطلاعاتی باید از نیم اسپیس افزونه :namespace استفاده نماید.', + 'error_migration_file_exists' => 'فایل ساختار بانک اطلاعات :file وجود دارد لطفا نام دیگری را وارد نمایید.', + 'error_cant_delete_applied' => 'این ویرایش اعمال شده است و شما نمیتوانید آن را حذف کنید لطفا جهت حذف آن ویرایش را به عقب باز گردانید.', + ], + 'components' => [ + 'list_title' => 'لیست موارد', + 'list_description' => 'نمایش لیستی از موارد مدل انتخاب شده', + 'list_page_number' => 'شماره صفحه', + 'list_page_number_description' => 'این مقدار جهت تعیین صفحه ای که کاربر در آن می باشد مورد استفاده قرار میگیرد.', + 'list_records_per_page' => 'تعداد موارد در هر صفحه', + 'list_records_per_page_description' => 'تعداد مواردی که در هر صفحه به نمایش در می آیند. جهت استفاده نکردن از خاصیت چند صفحه ای این مورد را خالی بگذارید.', + 'list_records_per_page_validation' => 'مقدار وارد شده در تعداد موارد در هر صفحه باید یک عدد صحیح باشد.', + 'list_no_records' => 'پیغام خالی بودن لیست', + 'list_no_records_description' => 'پیغامی که به هنگام نبودن موردی جهت نمایش به نمایش در می آید.', + 'list_no_records_default' => 'موردی یافت نشد', + 'list_sort_column' => 'مرتب سازی بر اساس', + 'list_sort_column_description' => 'ستونی که موارد بر اساس آن باید مرتب شوند', + 'list_sort_direction' => 'ترتیب مرتب سازی', + 'list_display_column' => 'نمایش ستون', + 'list_display_column_description' => 'ستونی که در لیست به نمایش در می آید.', + 'list_display_column_required' => 'لطفا ستونی را جهت نمایش انتخاب کنید.', + 'list_details_page' => 'صفحه جزییات', + 'list_details_page_description' => 'صفحه ای جهت نمایش جزییات موارد', + 'list_details_page_no' => '--صفحه جزییات موجود نیست--', + 'list_sorting' => 'مرتب سازی', + 'list_pagination' => 'صفحه بندی', + 'list_order_direction_asc' => 'صعودی', + 'list_order_direction_desc' => 'نزولی', + 'list_model' => 'کلاس مدل', + 'list_scope' => 'محدوده', + 'list_scope_description' => 'محدوده اختیاری کلاس مدل جهت واکشی موارد', + 'list_scope_default' => '--محدوده را انتخاب نمایید، اختیاری--', + 'list_details_page_link' => 'آدرس صفحه جزییات', + 'list_details_key_column' => 'ستون کلید جزییات', + 'list_details_key_column_description' => 'ستونی در مدل به عنوان کلید که مورد جهت نمایش جزییات از طریق آن در پایگاه داده یافت می شود.', + 'list_details_url_parameter' => 'پارامتر نام آدرس', + 'list_details_url_parameter_description' => 'نام پارامتر آدرس صفحه جزییات که کلید مورد را دریافت میکند.', + 'details_title' => 'جزییات مورد', + 'details_description' => 'نمایش جزییات مورد از مدل انتخاب شده', + 'details_model' => 'کلاس مدل', + 'details_identifier_value' => 'مقدار مشخصه', + 'details_identifier_value_description' => 'مقدار مشخصه جهت بارگذاری مورد از پایگاه داده. میتواند یک مقدار ثابت و یا پارامتر آدرس باشد.', + 'details_identifier_value_required' => 'وارد کردن مقدار مشخصه اجباریست', + 'details_key_column' => 'ستون کلید', + 'details_key_column_description' => 'ستونی در مدل که به عنوان مشخصه برای واکشی مورد در پایگاه داده مورد استفاده قرار میگیرد.', + 'details_key_column_required' => 'وارد کردن ستون کلید اجباریست', + 'details_display_column' => 'ستون نمایشی', + 'details_display_column_description' => 'ستونی در مدل که جهت نمایش در صفحه جزییات مورد استفاده قرار میگیرد.', + 'details_display_column_required' => 'وارد کردن ستون نمایشی اجباریست', + 'details_not_found_message' => 'موردی یافت نشد', + 'details_not_found_message_description' => 'پیغامی که به هنگام یافت نشدن مورد مورد استفاده قرار میگیرد.', + 'details_not_found_message_default' => 'موردی یافت نشد.', + ], +]; diff --git a/plugins/rainlab/builder/lang/nl.json b/plugins/rainlab/builder/lang/nl.json new file mode 100644 index 0000000..12b1912 --- /dev/null +++ b/plugins/rainlab/builder/lang/nl.json @@ -0,0 +1,4 @@ +{ + "Builder": "Builder", + "Provides visual tools for building October plugins.": "Stelt visuele hulpmiddelen beschikbaar om October plugins te maken." +} \ No newline at end of file diff --git a/plugins/rainlab/builder/lang/nl/lang.php b/plugins/rainlab/builder/lang/nl/lang.php new file mode 100644 index 0000000..a414140 --- /dev/null +++ b/plugins/rainlab/builder/lang/nl/lang.php @@ -0,0 +1,639 @@ + [ + 'add' => 'Maak plugin', + 'no_records' => 'Geen plugins aanwezig', + 'no_name' => 'Geen naam', + 'search' => 'Zoeken...', + 'filter_description' => 'Toon alle plugins of alleen eigen plugins.', + 'settings' => 'Instellingen', + 'entity_name' => 'Plugin', + 'field_name' => 'Naam', + 'field_author' => 'Auteur', + 'field_description' => 'Omschrijving', + 'field_icon' => 'Icoon', + 'field_plugin_namespace' => 'Plugin namespace', + 'field_author_namespace' => 'Auteur namespace', + 'field_namespace_description' => 'Een namespace kan alleen latijnse letters en cijfers bevatten en mag ook alleen met een letter beginnen. Bijvoorbeeld: Blog', + 'field_author_namespace_description' => 'Je kan de namespace van een Builder plugin niet meer wijzigen nadat je de plugin hebt gemaakt. Bijvoorbeeld: JohnSmith', + 'tab_general' => 'Algemeen', + 'tab_description' => 'Details', + 'field_homepage' => 'Plugin homepagina URL', + 'no_description' => 'Er is geen omschrijving opgegeven voor deze plugin.', + 'error_settings_not_editable' => 'De instellingen van deze plugin kunnen niet met Builder worden gewijzigd.', + 'update_hint' => 'Je kan de naam en omschrijving van de plugin vertalen in de \'Vertalen\' tab.', + ], + 'author_name' => [ + 'title' => 'Auteursnaam', + 'description' => 'Dit is de standaard auteursnaam die wordt gebruikt bij het maken van plugins. Deze naam staat niet vast, je kan hem altijd wijzigen in de instellingen van de plugin.', + ], + 'author_namespace' => [ + 'title' => 'Auteur namespace', + 'description' => 'Als je plugins maakt voor de Marketplace, dan moet de namespace gelijk zijn aan de auteur code en niet gewijzigd worden. Raadpleeg de documentatie voor aanvullende details.', + ], + 'database' => [ + 'menu_label' => 'Database', + 'no_records' => 'Geen database tabellen aanwezig', + 'search' => 'Zoeken...', + 'confirmation_delete_multiple' => 'Weet je zeker dat je de geselecteerde tabellen wilt verwijderen?', + 'field_name' => 'Tabelnaam', + 'tab_columns' => 'Kolommen', + 'column_name_name' => 'Kolom', + 'column_name_required' => 'Geef kolomnaam op', + 'column_name_type' => 'Type', + 'column_type_required' => 'Selecteer kolomtype', + 'column_name_length' => 'Lengte', + 'column_validation_length' => 'Lengte moet een getal zijn of een getal met dicimalen (10,2). Spaties zijn niet toegestaan.', + 'column_validation_title' => 'Alleen getallen, kleine letters en underscores zijn toegestaan in kolomnamen', + 'column_name_unsigned' => 'Unsigned', + 'column_name_nullable' => 'Nullable', + 'column_auto_increment' => 'AUTOINCR', + 'column_default' => 'Standaardwaarde', + 'column_auto_primary_key' => 'PK', + 'tab_new_table' => 'Nieuwe tabel', + 'btn_add_column' => 'Kolom toevoegen', + 'btn_delete_column' => 'Kolom verwijderen', + 'confirm_delete' => 'Do you really want to delete the table?', + 'error_enum_not_supported' => 'De tabel bevat kolom(men) van het type "enum", deze worden momenteel niet ondersteund door Builder.', + 'error_table_name_invalid_prefix' => 'De tabelnaam moet starten met de plugin prefix: \':prefix\'.', + 'error_table_name_invalid_characters' => 'Ongeldige tabelnaam. Tabelnamen mogen alleen latijnse letters, cijfers en underscores bevatten. Tabelnamen moeten beginnen met een letter en mogen geen spaties bevatten.', + 'error_table_duplicate_column' => 'Kolomnaam bestaat reeds: \':column\'.', + 'error_table_auto_increment_in_compound_pk' => 'Een `auto-increment` kolom kan geen deel uitmaken van een `compound primary key`.', + 'error_table_mutliple_auto_increment' => 'De tabel kan niet meerdere `auto-increment` kolommen bevatten.', + 'error_table_auto_increment_non_integer' => 'Auto-increment kolommen moeten van het type `integer` zijn.', + 'error_table_decimal_length' => 'De lengte voor type `:type` moet voldoen aan het formaat \'10,2\', zonder spaties.', + 'error_table_length' => 'De lengte voor type `:type` moet als een integer worden gespecificeerd.', + 'error_unsigned_type_not_int' => 'Fout gevonden in kolomdefinitie \':column\'. De `unsigned` vlag mag alleen op type `integer` kolommen worden toegepast.', + 'error_integer_default_value' => 'Ongeldige standaardwaarde voor kolom \':column\'. Toegestane waardes zijn \'10\', \'-10\'.', + 'error_decimal_default_value' => 'Ongeldige standaardwaarde voor kolom \':column\'. Toegestane waardes zijn \'1.00\', \'-1.00\'.', + 'error_boolean_default_value' => 'Ongeldige standaardwaarde voor kolom \':column\'. Toegestane waardes zijn \'0\' and \'1\'.', + 'error_unsigned_negative_value' => 'De standaardwaarde voor de kolom \':column\' mag niet negatief zijn.', + 'error_table_already_exists' => 'De tabel \':name\' bestaat reeds in de database.', + ], + 'model' => [ + 'menu_label' => 'Models', + 'entity_name' => 'Model', + 'no_records' => 'Geen models aanwezig', + 'search' => 'Zoeken...', + 'add' => 'Toevoegen...', + 'forms' => 'Formulieren', + 'lists' => 'Lijsten', + 'field_class_name' => 'Klasse naam', + 'field_database_table' => 'Database tabel', + 'error_class_name_exists' => 'Model bestand bestaat reeds voor de opgegeven klasse naam: :path', + 'add_form' => 'Fomulier toevoegen', + 'add_list' => 'Lijst toevoegen', + ], + 'form' => [ + 'saved' => 'Het formulier is succesvol opgeslagen.', + 'confirm_delete' => 'Weet je zeker dat je het formulier wilt verwijderen?', + 'tab_new_form' => 'Nieuw formulier', + 'property_label_title' => 'Label', + 'property_label_required' => 'Voor waarde voor label in.', + 'property_span_title' => 'Uitlijning', + 'property_comment_title' => 'Toelichting', + 'property_comment_above_title' => 'Toelichting (boven)', + 'property_default_title' => 'Standaard', + 'property_checked_default_title' => 'Standaard aangevinkt', + 'property_css_class_title' => 'CSS klassenaam', + 'property_css_class_description' => 'Optionele CSS klassenaam die wordt toegewezen aan het veld element.', + 'property_disabled_title' => 'Uitgeschakeld', + 'property_hidden_title' => 'Verborgen', + 'property_required_title' => 'Verplicht', + 'property_field_name_title' => 'Veldnaam', + 'property_placeholder_title' => 'Tijdelijke aanduiding', + 'property_default_from_title' => 'Waarde van', + 'property_stretch_title' => 'Uitrekken', + 'property_stretch_description' => 'Geeft aan of dit veld uitrekt naar de breedte van het bovenliggende element.', + 'property_context_title' => 'Context', + 'property_context_description' => 'Geeft aan welk formulier context gebruikt moet worden om het veld weer te geven.', + 'property_context_create' => 'Aanmaken', + 'property_context_update' => 'Wijzigen', + 'property_context_preview' => 'Voorvertoning', + 'property_dependson_title' => 'Afhankelijk van', + 'property_trigger_action' => 'Actie', + 'property_trigger_show' => 'Weergeven', + 'property_trigger_hide' => 'Verbergen', + 'property_trigger_enable' => 'Inschakelen', + 'property_trigger_disable' => 'Uitschakelen', + 'property_trigger_empty' => 'Leeg', + 'property_trigger_field' => 'Veld', + 'property_trigger_field_description' => 'Geeft het veld aan wat de actie veroorzaakt.', + 'property_trigger_condition' => 'Voorwaarde', + 'property_trigger_condition_description' => 'Bepaald de voorwaarde waaraan het betreffende veld aan moet voldoen. Ondersteunde waarden: checked, unchecked, value[waarde].', + 'property_trigger_condition_checked' => 'Aangevinkt: checked', + 'property_trigger_condition_unchecked' => 'Uitgevinkt: unchecked', + 'property_trigger_condition_somevalue' => 'Waarde: value[waarde]', + 'property_preset_title' => 'Voorinstelling', + 'property_preset_description' => 'Zorgt ervoor dat de veldwaarde initieel wordt gevuld met de waarde van een ander veld, al dan niet geconverteerd.', + 'property_preset_field' => 'Veld', + 'property_preset_field_description' => 'Het veld waarvan de waarde moet overgenomen worden.', + 'property_preset_type' => 'Type', + 'property_preset_type_description' => 'Conversie type', + 'property_attributes_title' => 'Attributen', + 'property_attributes_description' => 'Custom HTML attributen die aan het formulier veld moeten worden toegevoegd.', + 'property_container_attributes_title' => 'Container attributen', + 'property_container_attributes_description' => 'Custom HTML attributen die aan het formulier veld container moeten worden toegevoegd.', + 'property_group_advanced' => 'Geavanceerd', + 'property_dependson_description' => 'Een lijst van veldnamen waar dit veld van afhankelijk is. Als die velden een andere waarde krijgen, zal dit veld worden bijgewerkt. Een veld per regel.', + 'property_trigger_title' => 'Trigger', + 'property_trigger_description' => 'Zorgt ervoor dat veld eigenschappen veranderen, zoals bijvoorbeeld zichtbaarheid of waarde, gebaseerd op de staat van een ander veld.', + 'property_default_from_description' => 'Neemt de standaardwaarde over van een ander veld.', + 'property_field_name_required' => 'Veldnaam is verplicht', + 'property_field_name_regex' => 'Veldnaam kan alleen latijnse karakters bevatten of _ - [ ] .', + 'property_attributes_size' => 'Grootte', + 'property_attributes_size_tiny' => 'Kleiner', + 'property_attributes_size_small' => 'Klein', + 'property_attributes_size_large' => 'Groter', + 'property_attributes_size_huge' => 'Groot', + 'property_attributes_size_giant' => 'Grootst', + 'property_comment_position' => 'Toelichting positie', + 'property_comment_position_above' => 'Boven', + 'property_comment_position_below' => 'Beneden', + 'property_hint_path' => 'Pad naar hint-sjabloon', + 'property_hint_path_description' => 'Pad naar sjabloon bestand die de hint tekst bevat. Gebruik het $ symbool om het hoofdpad van de plugin aan te geven. Voorbeeld: $/acme/blog/partials/_partial.htm', + 'property_hint_path_required' => 'Geef het hint-sjabloon pad op', + 'property_partial_path' => 'Pad naar sjabloon', + 'property_partial_path_description' => 'Pad naar sjabloon bestand. Gebruik het $ symbool om het hoofdpad van de plugin aan te geven. Voorbeeld: $/acme/blog/partials/_partial.htm', + 'property_partial_path_required' => 'Geef het sjabloon pad op', + 'property_code_language' => 'Taal', + 'property_code_theme' => 'Thema', + 'property_theme_use_default' => 'Gebruik standaard thema', + 'property_group_code_editor' => 'Code editor', + 'property_gutter' => 'Goot', + 'property_gutter_show' => 'Weergeven', + 'property_gutter_hide' => 'Verbergen', + 'property_wordwrap' => 'Woordafbreking', + 'property_wordwrap_wrap' => 'Afbreken', + 'property_wordwrap_nowrap' => 'Niet afbreken', + 'property_fontsize' => 'Grootte lettertype', + 'property_codefolding' => 'Code inklappen', + 'property_codefolding_manual' => 'Handmatig', + 'property_codefolding_markbegin' => 'Begin markeren', + 'property_codefolding_markbeginend' => 'Begin en einde markeren', + 'property_autoclosing' => 'Automatisch sluiten', + 'property_enabled' => 'Ingeschakeld', + 'property_disabled' => 'Uitgeschakeld', + 'property_soft_tabs' => 'Zachte tabs', + 'property_tab_size' => 'Tab grootte', + 'property_readonly' => 'Alleen-lezen', + 'property_use_default' => 'Standaard instelling', + 'property_options' => 'Opties', + 'property_prompt' => 'Invoer', + 'property_prompt_description' => 'Tekst op de toevoegknop.', + 'property_prompt_default' => 'Nieuw item', + 'property_available_colors' => 'Beschikbare kleuren', + 'property_available_colors_description' => 'Lijst van beschikbare kleuren in HEX formaat (#FF0000). Laat leeg voor standaard kleuren set. Een waarde per regel.', + 'property_datepicker_mode' => 'Modus', + 'property_datepicker_mode_date' => 'Datum', + 'property_datepicker_mode_datetime' => 'Datum en tijd', + 'property_datepicker_mode_time' => 'Tijd', + 'property_datepicker_min_date' => 'Minimale datum', + 'property_datepicker_max_date' => 'Maximale datum', + 'property_fileupload_mode' => 'Modus', + 'property_fileupload_mode_file' => 'Bestand', + 'property_fileupload_mode_image' => 'Afbeelding', + 'property_group_fileupload' => 'Bestandsupload', + 'property_fileupload_image_width' => 'Breedte afbeelding', + 'property_fileupload_image_width_description' => 'Afbeeldingen zullen geschaald worden naar deze breedte (optioneel).', + 'property_fileupload_invalid_dimension' => 'Ongeldige waarde voor breedte/hoogte afbeelding, geef een getal in.', + 'property_fileupload_image_height' => 'Hoogte afbeelding', + 'property_fileupload_image_height_description' => 'Afbeeldingen zullen geschaald worden naar deze hoogte (optioneel).', + 'property_fileupload_file_types' => 'Bestandstypes', + 'property_fileupload_file_types_description' => 'Komma gescheiden lijst van toegestane bestandsextenties, bijvoorbeeld: zip,txt (optioneel).', + 'property_fileupload_mime_types' => 'MIME typen', + 'property_fileupload_mime_types_description' => 'Komma gescheiden lijst van toegestane MIME-typen; bestandsextenties of volledige namen, bijvoorbeeld: zip,txt', + 'property_fileupload_use_caption' => 'Gebruik annotatie', + 'property_fileupload_use_caption_description' => 'Staat toe dat er een titel en omschrijving kunnen worden opgegeven voor het bestand.', + 'property_fileupload_thumb_options' => 'Miniatuurweergave opties', + 'property_fileupload_thumb_options_description' => 'Beheer opties voor de automatisch gegenereerde miniatuurweergaven. Alleen van toepassing bij Afbeelding modus.', + 'property_fileupload_thumb_mode' => 'Modus', + 'property_fileupload_thumb_auto' => 'Automatisch', + 'property_fileupload_thumb_exact' => 'Exact', + 'property_fileupload_thumb_portrait' => 'Staand', + 'property_fileupload_thumb_landscape' => 'Liggend', + 'property_fileupload_thumb_crop' => 'Uitsnijden', + 'property_fileupload_thumb_extension' => 'Bestandsextentie', + 'property_name_from' => 'Kolomnaam', + 'property_name_from_description' => 'Gerelateerde kolomnaam die gebruikt moet worden voor het weergeven van een naam.', + 'property_description_from' => 'Omschrijving kolom', + 'property_description_from_description' => 'Gerelateerde kolomnaam die gebruikt moet worden voor het weergeven van een omschrijving.', + 'property_recordfinder_prompt' => 'Prompt', + 'property_recordfinder_prompt_description' => 'Text to display when there is no record selected. The %s character represents the search icon. Leave empty for the default prompt.', + 'property_recordfinder_list' => 'Lijst configuratie', + 'property_recordfinder_list_description' => 'Een referentie naar een lijstkolom definitie bestand. Gebruik het $ symbool om te refereren naar de plugin map, bijvoorbeeld: $/acme/blog/lists/_list.yaml', + 'property_recordfinder_list_required' => 'Geef een pad op naar het YAML bestand', + 'property_group_recordfinder' => 'Record zoeker', + 'property_mediafinder_mode' => 'Modus', + 'property_mediafinder_mode_file' => 'Bestand', + 'property_mediafinder_mode_image' => 'Afbeelding', + 'property_group_relation' => 'Relatie', + 'property_relation_select' => 'kiezen', + 'property_relation_select_description' => 'CONCAT meerdere kolommen samen voor het weergeven van een naam', + 'property_relation_prompt' => 'Prompt', + 'property_relation_prompt_description' => 'Tekst om weer te geven als er geen selecties beschikbaar zijn.', + 'property_max_items' => 'Maximum aantal', + 'property_max_items_description' => 'Maximum toegelaten aantal items in de herhaler.', + 'control_group_standard' => 'Standaard', + 'control_group_widgets' => 'Widgets', + 'click_to_add_control' => 'Element toevoegen', + 'loading' => 'Bezig met laden...', + 'control_text' => 'Tekst', + 'control_text_description' => 'Invoerveld voor één regel tekst.', + 'control_password' => 'Wachtwoord', + 'control_password_description' => 'Invoerveld voor een wachtwoord.', + 'control_checkbox' => 'Keuzevakje', + 'control_checkbox_description' => 'Enkelvoudig keuzevakje.', + 'control_switch' => 'Schakelaar', + 'control_switch_description' => 'Enkelvoudige schakelaar, een alternatief voor het keuzevakje.', + 'control_textarea' => 'Tekst', + 'control_textarea_description' => 'Tekstvak voor meerdere regels met instelbare hoogte.', + 'control_dropdown' => 'Selectieveld', + 'control_dropdown_description' => 'Een selectie lijst met vaste of dynamische opties.', + 'control_unknown' => 'Onbekend element type: :type', + 'control_repeater' => 'Herhaler', + 'control_repeater_description' => 'Toont een set van herhalende formulier elementen.', + 'control_number' => 'Nummer', + 'control_number_description' => 'Invoerveld voor een nummer.', + 'control_hint' => 'Tip', + 'control_hint_description' => 'Toont een tip in een vakje die verborgen kan worden door een gebruiker.', + 'control_partial' => 'Partial', + 'control_partial_description' => 'Toont inhoud van een zgn. partial.', + 'control_section' => 'Sectie', + 'control_section_description' => 'Toont een formuliersectie met een kop- en subkoptekst.', + 'control_radio' => 'Lijst van invoerrondjes', + 'control_radio_description' => 'Een lijst van invoerrondjes, er kan maar één invoerrondje geselecteerd worden.', + 'control_radio_option_1' => 'Optie 1', + 'control_radio_option_2' => 'Optie 2', + 'control_checkboxlist' => 'Lijst van keuzevakjes', + 'control_checkboxlist_description' => 'Een lijst van keuzevakjes, er kunnen meerdere keuzevakjes geselecteerd worden.', + 'control_codeeditor' => 'Code editor', + 'control_codeeditor_description' => 'Een editor voor het bewerken van geformatteerde code of opmaakcode.', + 'control_colorpicker' => 'Kleur kiezer', + 'control_colorpicker_description' => 'Een veld met de mogelijkheid voor het selecteren van een hexadecimale kleurcode.', + 'control_datepicker' => 'Datum kiezer', + 'control_datepicker_description' => 'Een veld met de mogelijkheid voor het selecteren van een datum en tijd.', + 'control_richeditor' => 'WYSIWYG editor', + 'control_richeditor_description' => 'Een editor voor het bewerken van uitgebreide opgemaakte tekst.', + 'control_markdown' => 'Markdown editor', + 'control_markdown_description' => 'Een editor voor het bewerken van tekst in het Markdown formaat.', + 'control_fileupload' => 'Bestand uploader', + 'control_fileupload_description' => 'Een bestandsuploader voor afbeeldingen of reguliere bestanden.', + 'control_recordfinder' => 'Record veld', + 'control_recordfinder_description' => 'Een zoekveld met details van een gerelateerd record.', + 'control_mediafinder' => 'Media veld', + 'control_mediafinder_description' => 'Een veld die een item uit de Media bibliotheek kan bevatten.', + 'control_relation' => 'Relatie', + 'control_relation_description' => 'Toont een selectieveld of een lijst van keuzevakjes om een gerelateerd record te selecteren.', + 'error_file_name_required' => 'Voer bestandsnaam in van het formulier.', + 'error_file_name_invalid' => 'Bestandsnaam kan alleen latijnse karakters, cijfers of een van de volgende tekens bevatten: _ - #', + 'span_left' => 'Links', + 'span_right' => 'Rechts', + 'span_full' => 'Volledige breedte', + 'span_auto' => 'Automatisch', + 'empty_tab' => 'Leeg tabblad', + 'confirm_close_tab' => 'Het tabblad bevat elementen die verwijderd zullen worden. Doorgaan?', + 'tab' => 'Formulier tabblad', + 'tab_title' => 'Titel', + 'controls' => 'Elementen', + 'property_tab_title_required' => 'De titel van het tabblad is verplicht.', + 'tabs_primary' => 'Primaire tabs', + 'tabs_secondary' => 'Secundaire tabs', + 'tab_stretch' => 'Uitrekken', + 'tab_stretch_description' => 'Met deze optie geef je aan dat de inhoud van het tabblad meerekt naar de hoogte van het bovenliggende element.', + 'tab_css_class' => 'CSS class', + 'tab_css_class_description' => 'Wijst een CSS class toe aan de inhoud van het tabblad.', + 'tab_name_template' => 'Tabblad %s', + 'tab_already_exists' => 'Tabblad met opgegeven titel bestaat reeds.', + ], + 'list' => [ + 'tab_new_list' => 'Nieuwe lijst', + 'saved' => 'De lijst is succesvol opgeslagen.', + 'confirm_delete' => 'Weet je zeker dat je de lijst wilt verwijderen?', + 'tab_columns' => 'Kolommen', + 'btn_add_column' => 'Kolom toevoegen', + 'btn_delete_column' => 'Kolom verwijderen', + 'column_dbfield_label' => 'Veld', + 'column_dbfield_required' => 'Geef Model veld op', + 'column_name_label' => 'Label', + 'column_label_required' => 'Geef kolom label op', + 'column_type_label' => 'Type', + 'column_type_required' => 'Geef kolomtype op', + 'column_type_text' => 'Tekst', + 'column_type_number' => 'Numeriek', + 'column_type_switch' => 'Schakelaar', + 'column_type_datetime' => 'Datum & Tijd', + 'column_type_date' => 'Datum', + 'column_type_time' => 'Tijd', + 'column_type_timesince' => 'Datum & tijd sinds', + 'column_type_timetense' => 'Datum & tijd afgekort', + 'column_type_select' => 'Keuze', + 'column_type_partial' => 'Partial', + 'column_label_default' => 'Standaard', + 'column_label_searchable' => 'Zoeken', + 'column_label_sortable' => 'Sorteerbaar', + 'column_label_invisible' => 'Onzichtbaar', + 'column_label_select' => 'Select', + 'column_label_relation' => 'Relatie', + 'column_label_css_class' => 'CSS class', + 'column_label_width' => 'Breedte', + 'column_label_path' => 'Pad', + 'column_label_format' => 'Formaat', + 'column_label_value_from' => 'Waarde van', + 'error_duplicate_column' => 'Kolom veldnaam bestaat reeds: \':column\'.', + ], + 'controller' => [ + 'menu_label' => 'Controllers', + 'no_records' => 'Geen controllers aanwezig', + 'controller' => 'Controller', + 'behaviors' => 'Behaviors', + 'new_controller' => 'Nieuwe controller', + 'error_controller_has_no_behaviors' => 'De controller heeft geen configureerbare behaviors.', + 'error_invalid_yaml_configuration' => 'Fout bij laden behavior configuratie bestand: :file', + 'behavior_form_controller' => 'Formulier controller behavior', + 'behavior_form_controller_description' => 'Voegt formulier functionaliteit toe aan een back-end pagina. Deze behavior bevat drie pagina\'s: Create (aanmaken), Update (wijzigen) en Preview (voorbeeldweergave).', + 'property_behavior_form_placeholder' => '-- Selecteer formulier --', + 'property_behavior_form_name' => 'Naam', + 'property_behavior_form_name_description' => 'De naam van het object wat beheerd wordt door dit formulier.', + 'property_behavior_form_name_required' => 'Geef de naam van het formulier op', + 'property_behavior_form_file' => 'Formulier configuratie', + 'property_behavior_form_file_description' => 'Referentie naar het formulieren veld definitie bestand.', + 'property_behavior_form_file_required' => 'Geef het pad op naar het configuratiebestand van het formulier', + 'property_behavior_form_model_class' => 'Model class', + 'property_behavior_form_model_class_description' => 'Klassenaam van een model, de data van het formulier wordt geladen en opgeslagen met dit model.', + 'property_behavior_form_model_class_required' => 'Selecteer een model class', + 'property_behavior_form_default_redirect' => 'Standaard redirect', + 'property_behavior_form_default_redirect_description' => 'De standaard pagina waarnaar verwezen wordt nadat het formulier is opgeslagen.', + 'property_behavior_form_create' => 'Maak record pagina', + 'property_behavior_form_redirect' => 'Redirect', + 'property_behavior_form_redirect_description' => 'Een pagina waarnaar verwezen wordt wanneer een record is aangemaakt.', + 'property_behavior_form_redirect_close' => 'Sluiten redirect', + 'property_behavior_form_redirect_close_description' => 'Een pagina waarnaar verwezen wordt wanneer er gekozen is voor \'Opslaan en sluiten\'.', + 'property_behavior_form_flash_save' => 'Bericht bij opslaan', + 'property_behavior_form_flash_save_description' => 'Bericht om weer te geven nadat een record is opgeslagen.', + 'property_behavior_form_page_title' => 'Paginatitel', + 'property_behavior_form_update' => 'Record bijwerken pagina', + 'property_behavior_form_update_redirect' => 'Redirect', + 'property_behavior_form_create_redirect_description' => 'Een pagina waarnaar verwezen wordt als een record wordt opgeslagen.', + 'property_behavior_form_flash_delete' => 'Delete flash message', + 'property_behavior_form_flash_delete_description' => 'Flash message to display when record is deleted.', + 'property_behavior_form_preview' => 'Voorbeeldweergave record pagina', + 'behavior_list_controller' => 'Lijst controller behavior', + 'behavior_list_controller_description' => 'Stelt een sorteerbare en doorzoekbare lijst beschikbaar. De \'behavior\' maakt de controller action "index" beschikbaar.', + 'property_behavior_list_title' => 'Titel lijst', + 'property_behavior_list_title_required' => 'Geeft de titel van de lijst op', + 'property_behavior_list_placeholder' => '-- Selecteer lijst --', + 'property_behavior_list_model_class' => 'Model class', + 'property_behavior_list_model_class_description' => 'Klassenaam van een model, de lijst wordt geladen m.b.v. dit model.', + 'property_behavior_form_model_class_placeholder' => '-- Selecteer model --', + 'property_behavior_list_model_class_required' => 'Selecteer een model class', + 'property_behavior_list_model_placeholder' => '-- Selecteer model --', + 'property_behavior_list_file' => 'Configuratiebestand lijst', + 'property_behavior_list_file_description' => 'Referentie naar een definitiebestand van een lijst.', + 'property_behavior_list_file_required' => 'Geeft het pad op naar het configuratiebestand van de lijst', + 'property_behavior_list_record_url' => 'Record URL', + 'property_behavior_list_record_url_description' => 'Koppel elk record van de lijst aan een andere pagina. Bijv. users/update:id. Het :id gedeelte wordt vervangen met het identificatie nummer van het record.', + 'property_behavior_list_no_records_message' => 'Bericht bij geen records', + 'property_behavior_list_no_records_message_description' => 'Het bericht wat moet worden weergegeven als er geen records gevonden zijn.', + 'property_behavior_list_recs_per_page' => 'Records per pagina', + 'property_behavior_list_recs_per_page_description' => 'Aantal records wat weergegeven moet worden per pagina. Geef 0 op om geen paginatie te gebruiken. Standaardwaarde: 0', + 'property_behavior_list_recs_per_page_regex' => 'Het aantal records per pagina moet een numerieke waarde zijn', + 'property_behavior_list_show_setup' => 'Toon setup knop', + 'property_behavior_list_show_sorting' => 'Toon sorteren', + 'property_behavior_list_default_sort' => 'Standaard sortering', + 'property_behavior_form_ds_column' => 'Kolom', + 'property_behavior_form_ds_direction' => 'Richting', + 'property_behavior_form_ds_asc' => 'Oplopend', + 'property_behavior_form_ds_desc' => 'Aflopend', + 'property_behavior_list_show_checkboxes' => 'Toon keuzevakjes', + 'property_behavior_list_onclick' => 'Klik handler', + 'property_behavior_list_onclick_description' => 'JavaScript code wat uitgevoerd moet worden als er op een record wordt geklikt.', + 'property_behavior_list_show_tree' => 'Toon hiërarchie', + 'property_behavior_list_show_tree_description' => 'Toont een hiërarchie boom voor ouder/kind-records.', + 'property_behavior_list_tree_expanded' => 'Uitgeklapte weergave', + 'property_behavior_list_tree_expanded_description' => 'Geeft aan of de hiërarchische boom standaard uitgeklapt moet worden weergegeven.', + 'property_behavior_list_toolbar' => 'Toolbar', + 'property_behavior_list_toolbar_buttons' => 'Knoppen partial bestand', + 'property_behavior_list_toolbar_buttons_description' => 'Referentie naar een partial bestand met de toolbar knoppen. Bijv. list_toolbar', + 'property_behavior_list_search' => 'Zoeken', + 'property_behavior_list_search_prompt' => 'Zoek prompt', + 'property_behavior_list_filter' => 'Filter configuratie', + 'behavior_reorder_controller' => 'Reorder controller behavior', + 'behavior_reorder_controller_description' => 'Stelt functies beschikbaar voor het sorteren en rangschikken van records. De behavior maakt automatisch de "reorder" controller actie aan.', + 'property_behavior_reorder_title' => 'Rangschik titel', + 'property_behavior_reorder_title_required' => 'De rangschik titel is verplicht.', + 'property_behavior_reorder_name_from' => 'Attribuut naam', + 'property_behavior_reorder_name_from_description' => 'Attribuut van het model wat als weergavenaam van het record moet worden gebruikt.', + 'property_behavior_reorder_name_from_required' => 'De attribuut naam is verplicht.', + 'property_behavior_reorder_model_class' => 'Model class', + 'property_behavior_reorder_model_class_description' => 'Model klassenaam, de rangschik data wordt geladen uit dit model.', + 'property_behavior_reorder_model_class_placeholder' => '-- Selecteer model --', + 'property_behavior_reorder_model_class_required' => 'Selecteer een model class', + 'property_behavior_reorder_model_placeholder' => '-- Selecteer model --', + 'property_behavior_reorder_toolbar' => 'Toolbar', + 'property_behavior_reorder_toolbar_buttons' => 'Knoppen partial bestand', + 'property_behavior_reorder_toolbar_buttons_description' => 'Referentie naar een partial bestand met de toolbar knoppen. Bijv. reorder_toolbar', + 'error_controller_not_found' => 'Het originele controller bestand kan niet gevonden worden.', + 'error_invalid_config_file_name' => 'De bestandsnaam van configuratiebestand :fil) (van behavior :class) bevat ongeldige karakters en kan daarom niet worden geladen.', + 'error_file_not_yaml' => 'Het configuratiebestad :file (van behavior :class) is geen YAML-bestand. Alleen YAML-bestanden worden ondersteund.', + 'saved' => 'De controller is succesvol opgeslagen.', + 'controller_name' => 'Naam controller', + 'controller_name_description' => 'De naam van de controller bepaald de uiteindelijk URL waarmee de controller beschikbaar is in de back-end. De standaard PHP conventies zijn van toepassing. Het eerste karakter moet een hoofdletter zijn. Voorbeelden van geldige namen: Categories, Posts of Products.', + 'base_model_class' => 'Basis model class', + 'base_model_class_description' => 'Selecteer een model class om te gebruiken als basis model in behaviors die models vereisen of ondersteunen. Je kan de behaviors later configureren.', + 'base_model_class_placeholder' => '-- Selecteer model --', + 'controller_behaviors' => 'Behaviors', + 'controller_behaviors_description' => 'Seleteer de behaviors die de controller moet implementeren. De view bestanden, die vereist zijn voor de behaviors, zullen automatisch worden aangemaakt.', + 'controller_permissions' => 'Toegangsrechten', + 'controller_permissions_description' => 'Selecteer de gebruikersrechten die toegang hebben tot de controller view. Toegangsrechten kunnen aangemaakt worden via het tabblad Toegangsrechten in het linkermenu. Je kunt deze optie ook later aanpassen in de PHP-code van de controller.', + 'controller_permissions_no_permissions' => 'De plugin heeft (nog) geen toegangsrechten gedefinieerd.', + 'menu_item' => 'Actief menu item', + 'menu_item_description' => 'Selecteer een menu item dat geactiveerd moet worden voor de pagina\'s van deze controller. Je kunt deze optie ook later aanpassen in de PHP-code van de controller.', + 'menu_item_placeholder' => '-- Selecteer menu item --', + 'error_unknown_behavior' => 'De behavior class :class is niet geregistreerd in de behavior bibliotheek.', + 'error_behavior_view_conflict' => 'De geselecteerde behaviors leveren conflicterende views (:view) en kunnen daarom niet samen worden gebruikt in een controller.', + 'error_behavior_config_conflict' => 'De geselecteerde behaviors leveren conflicterende configuratiebestanden op (:file) en kunnen daarom niet samen worden gebruikt in een controller.', + 'error_behavior_view_file_not_found' => 'De view template :view van behavior :class kan niet worden gevonden.', + 'error_behavior_config_file_not_found' => 'Het configuratiebestand template :file van behavior :class kan niet worden gevonden.', + 'error_controller_exists' => 'Het controller bestand :file bestaat reeds.', + 'error_controller_name_invalid' => 'Ongeldigde controllernaam. Voorbeelden van geldige namen: Posts, Categories of Products.', + 'error_behavior_view_file_exists' => 'De view :view bestaat reeds voor deze controller.', + 'error_behavior_config_file_exists' => 'Het behavior configuratiebestand: file bestaat reeds.', + 'error_save_file' => 'Fout bij opslaan van het controller bestand :file.', + 'error_behavior_requires_base_model' => 'Er moet een basis model class worden geselecteer voor behavior :behavior.', + 'error_model_doesnt_have_lists' => 'Het geselecteerde model heeft geen lijsten. Maak eerst een lijst.', + 'error_model_doesnt_have_forms' => 'Het geselecteerde model heeft geen formulieren. Maak eerst een formulier.', + ], + 'version' => [ + 'menu_label' => 'Versies', + 'no_records' => 'Geen plugin versies aanwezig', + 'search' => 'Zoeken...', + 'tab' => 'Versies', + 'saved' => 'De versie is succesvol opgeslagen.', + 'confirm_delete' => 'Weet je zeker dat je deze versie wilt verwijderen?', + 'tab_new_version' => 'Nieuwe versie', + 'migration' => 'Migratie', + 'seeder' => 'Seeder', + 'custom' => 'Versienummer ophogen', + 'apply_version' => 'Versie toepassen', + 'applying' => 'Bezig met toepassen...', + 'rollback_version' => 'Versie terugzetten', + 'rolling_back' => 'Bezig met terugzerren...', + 'applied' => 'De versie is succesvol toegepast.', + 'rolled_back' => 'De versie is succesvol teruggezet.', + 'hint_save_unapplied' => 'Je hebt een nog niet geactiveerde versie opgeslagen. Niet geactiveerde versies kunnen automatisch worden geactiveerd als jij of een andere gebruiker inlogd op de back-end. Of als een database tabel wordt opgeslagen binnen de Database sectie van de Builder plugin.', + 'hint_rollback' => 'Het terugzetten van een versie zal ook alle versies nieuwer dan deze versie terugzetten. Wees je ervan bewust dat niet geactiveerde versies automatisch geactiveerd kunnen worden, als jij of een andere gebruiker inlogd op de back-end. Of als een database tabel wordt opgeslagen binnen de Database sectie van de Builder plugin.', + 'hint_apply' => 'Het activeren van een versie zal ook oudere niet geactiveerde versies activeren.', + 'dont_show_again' => 'Laat niet meer zien', + 'save_unapplied_version' => 'Niet geactiveerde versie opslaan', + ], + 'menu' => [ + 'menu_label' => 'Backend menu', + 'tab' => 'Menu\'s', + 'items' => 'Menu items', + 'saved' => 'De menu\'s zijn succesvol opgeslagen.', + 'add_main_menu_item' => 'Hoofdmenu item toevoegen', + 'new_menu_item' => 'Menu item', + 'add_side_menu_item' => 'Sub-item toevoegen', + 'side_menu_item' => 'Linker menu item', + 'property_label' => 'Label', + 'property_label_required' => 'Voer label in van menu item.', + 'property_url_required' => 'Voer URL in van menu item.', + 'property_url' => 'URL', + 'property_icon' => 'Icoon', + 'property_icon_required' => 'Selecteer een icoon.', + 'property_permissions' => 'Toegangsrechten', + 'property_order' => 'Volgorde', + 'property_order_invalid' => 'Geef de volgorde aan met een getal.', + 'property_order_description' => 'De volgorde bepaalde de positie van het menu item. Als de volgorde niet is opgegeven zal het item aan het einde van het menu worden toegevoegd. De standaardwaarden van de volgordes worden elke keer opgehoogd met 100.', + 'property_attributes' => 'HTML attributen', + 'property_code' => 'Code', + 'property_code_invalid' => 'De code mag alleen bestaan uit letters en cijfers.', + 'property_code_required' => 'Geef menu item code op.', + 'error_duplicate_main_menu_code' => 'Dupliceer hoofdmenu item code: \':code\'.', + 'error_duplicate_side_menu_code' => 'Dupliceer linker menu item code: \':code\'.', + ], + 'localization' => [ + 'menu_label' => 'Vertalen', + 'language' => 'Taal', + 'strings' => 'Taallabels', + 'confirm_delete' => 'Weet je zeker dat je deze taal wilt verwijderen?', + 'tab_new_language' => 'Nieuwe taal', + 'no_records' => 'Geen talen aanwezig', + 'saved' => 'Het taalbestand is succesvol opgeslagen.', + 'error_cant_load_file' => 'Kan het taalbestand niet laden, bestand is niet gevonden.', + 'error_bad_localization_file_contents' => 'Kan het taalbestand niet laden. Taalbestanden kunnen alleen array-definities en teksten bevatten.', + 'error_file_not_array' => 'Kan het taalbestand niet laden. Taalbestanden moeten een array teruggeven.', + 'save_error' => 'Fout bij opslaan van bestand \':name\'. Controleer schrijfrechten.', + 'error_delete_file' => 'Fout bij verwijderen van taalbestand.', + 'add_missing_strings' => 'Toevoegen van ontbrekende taallabels.', + 'copy' => 'Kopiëren', + 'add_missing_strings_label' => 'Selecteer een taal waarvan de taallabels gekopiëerd moeten worden.', + 'no_languages_to_copy_from' => 'Er zijn geen andere talen waar de taallabels van gekopiëerd kunnen worden.', + 'new_string_warning' => 'Nieuwe taallabel of sectie', + 'structure_mismatch' => 'De structuur van het bron taalbestand komt niet overeen met het bestand wat nu wordt gewijzigd. Een aantal taallabels in het gewijzigde bestand corresponderen met secties in het bronbestand (of vice versa) en kunnen daarom niet automatisch worden samengevoegd.', + 'create_string' => 'Nieuw taallabel toevoegen', + 'string_key_label' => 'Taallabel ID', + 'string_key_comment' => 'Geef het taallabel ID op gescheiden met een punt, bijvoorbeeld: plugin.search. De taallabel zal worden aangemaakt in het standaard taalbestand van de plugin.', + 'string_value' => 'Taallabel waarde', + 'string_key_is_empty' => 'Het taallabel ID mag niet leeg zijn.', + 'string_value_is_empty' => 'Taallabel waarde mag niet leeg zijn.', + 'string_key_exists' => 'Het taallabel ID bestaat reeds. Geef een ander ID op.', + ], + 'permission' => [ + 'menu_label' => 'Toegangsrechten', + 'tab' => 'Toegangsrechten', + 'form_tab_permissions' => 'Toegangsrechten', + 'btn_add_permission' => 'Toegangsrechten toevoegen', + 'btn_delete_permission' => 'Toegangsrechten verwijderen', + 'column_permission_label' => 'Code', + 'column_permission_required' => 'Geef de code op.', + 'column_tab_label' => 'Tabblad titel', + 'column_tab_required' => 'Geef tabblad titel op.', + 'column_label_label' => 'Label', + 'column_label_required' => 'Geef een label op.', + 'saved' => 'Toegangsrechten zijn succesvol opgeslagen.', + 'error_duplicate_code' => 'Dupliceer code: \':code\'.', + ], + 'yaml' => [ + 'save_error' => 'Fout bij opslaan bestan \':name\'. Controleer schrijfrechten.', + ], + 'common' => [ + 'error_file_exists' => 'Het bestand bestaat reeds: \':path\'.', + 'field_icon_description' => 'OctoberCMS gebruikt Font Autumn iconen, zie: http://octobercms.com/docs/ui/icon', + 'destination_dir_not_exists' => 'De doel directory bestaat niet: \':path\'.', + 'error_make_dir' => 'Fout bij aanmaken van directory: \':name\'.', + 'error_dir_exists' => 'Directory bestaat reeds: \':path\'.', + 'template_not_found' => 'Template-bestand kan niet worden gevonden: \':name\'.', + 'error_generating_file' => 'Fout bij genreren van bestand: \':path\'.', + 'error_loading_template' => 'Fout bij laden van template-bestand: \':name\'.', + 'select_plugin_first' => 'Selecteer eerst een plugin. Om een lijst van plugins te tonen, klik op het > icoon in de linker zijbalk.', + 'plugin_not_selected' => 'Plugin is niet geselecteerd.', + 'add' => 'Toevoegen', + ], + 'migration' => [ + 'entity_name' => 'Migratie', + 'error_version_invalid' => 'Het versienummer moet voldoen aan het formaat 1.0.1', + 'field_version' => 'Versie', + 'field_description' => 'Omschrijving', + 'field_code' => 'Code', + 'save_and_apply' => 'Opslaan & toepassen', + 'error_version_exists' => 'De migratie-versie bestaat reeds.', + 'error_script_filename_invalid' => 'De bestandsnaam van de migratie kan alleen letters, getallen en underscores bevatten. De naam moet beginnen met een letter en mag geen spaties bevatten.', + 'error_cannot_change_version_number' => 'Kan het versienummer niet aanpassen voor een reeds toegepaste versie.', + 'error_file_must_define_class' => 'De migratie code moet een migratie of een seeder class definieren. Laat het code veld leeg als je alleen het versienummer wilt bijwerken.', + 'error_file_must_define_namespace' => 'De migratie code moet een namespace definieren. Laat het code veld leeg als je alleen het versienummer wilt bijwerken.', + 'no_changes_to_save' => 'Er zijn geen wijzigingen om op te slaan.', + 'error_namespace_mismatch' => 'The migratie code moet de plugin namespace :namespace gebruiken.', + 'error_migration_file_exists' => 'Het migratie bestand :file bestaat reeds. Gebruik een andere klasse naam.', + 'error_cant_delete_applied' => 'Deze versie is reeds toegepast en kan daarom niet worden verwijderd. Ga eerst terug naar deze versie (rollback).', + ], + 'components' => [ + 'list_title' => 'Record lijst', + 'list_description' => 'Toont een lijst van records voor geselecteerde model.', + 'list_page_number' => 'Paginanummer', + 'list_page_number_description' => 'De waarde hiervan wordt gebruikt om te bepalen op welke pagina de gebruiker zit.', + 'list_records_per_page' => 'Records per pagina', + 'list_records_per_page_description' => 'Het aantal records wat per pagina moet worden weergegeven. Laat leeg om paginatie uit te schakelen.', + 'list_records_per_page_validation' => 'Ongeldige waarde. Het aantal records per pagina moet worden aangegeven met een nummer.', + 'list_no_records' => 'Bericht bij geen records', + 'list_no_records_description' => 'Bericht wat moet worden weergegeven als er geen records zijn.', + 'list_no_records_default' => 'Geen records gevonden', + 'list_sort_column' => 'Sorteer op kolom', + 'list_sort_column_description' => 'Kolom van model waarop de records gesorteerd moeten worden.', + 'list_sort_direction' => 'Sorteerrichting', + 'list_display_column' => 'Weergave kolom', + 'list_display_column_description' => 'Kolom die moet worden weergegeven in de lijst.', + 'list_display_column_required' => 'Selecteer een weergave kolom.', + 'list_details_page' => 'Detailpagina', + 'list_details_page_description' => 'Pagina waarop record details worden weergegeven.', + 'list_details_page_no' => '-- Geen detailpagina --', + 'list_sorting' => 'Sortering', + 'list_pagination' => 'Paginatie', + 'list_order_direction_asc' => 'Oplopend', + 'list_order_direction_desc' => 'Aflopend', + 'list_model' => 'Model class', + 'list_scope' => 'Scope', + 'list_scope_description' => 'Model scope waarin de records moeten worden opgevraagd (optioneel).', + 'list_scope_default' => '-- Selecteer een scope (optioneel) --', + 'list_details_page_link' => 'Link naar de detailpagina', + 'list_details_key_column' => 'Detail sleutelkolom', + 'list_details_key_column_description' => 'Model kolom die moet worden gebruikt als record ID in de detailpagina links.', + 'list_details_url_parameter' => 'URL parameter naam', + 'list_details_url_parameter_description' => 'Naam van de detailpagina URL parameter. De parameter bevat het record ID.', + 'details_title' => 'Record details', + 'details_description' => 'Toont record details voor een geselecteerd model.', + 'details_model' => 'Model class', + 'details_identifier_value' => 'ID-waarde', + 'details_identifier_value_description' => 'ID-waarde waarmee het record wordt opgevraagd uit de database. Geef een vaste waarde op of een parameter naam voor in de URL.', + 'details_identifier_value_required' => 'De ID-waarde mag niet leeg zijn.', + 'details_key_column' => 'Sleutelkolom', + 'details_key_column_description' => 'De kolom die gebruikt moet worden om het record (met ID-waarde) uit de database te kunnen opvragen.', + 'details_key_column_required' => 'De sleutelkolom mag niet leeg zijn.', + 'details_display_column' => 'Weergave kolom', + 'details_display_column_description' => 'De kolom uit het model die moet worden weergegeven op de detailpagina.', + 'details_display_column_required' => 'Selecteer de weergave kolom.', + 'details_not_found_message' => 'Bericht voor niet gevonden', + 'details_not_found_message_description' => 'Bericht wat moet worden weergegeven als het record niet is gevonden.', + 'details_not_found_message_default' => 'Record niet gevonden', + ], +]; diff --git a/plugins/rainlab/builder/lang/pl.json b/plugins/rainlab/builder/lang/pl.json new file mode 100644 index 0000000..3456ec1 --- /dev/null +++ b/plugins/rainlab/builder/lang/pl.json @@ -0,0 +1,3 @@ +{ + "Provides visual tools for building October plugins.": "Wizualne narzędzia do tworzenia wtyczek dla October CMS." +} \ No newline at end of file diff --git a/plugins/rainlab/builder/lang/pl/lang.php b/plugins/rainlab/builder/lang/pl/lang.php new file mode 100644 index 0000000..9931000 --- /dev/null +++ b/plugins/rainlab/builder/lang/pl/lang.php @@ -0,0 +1,688 @@ + [ + 'add' => 'Utwórz wtyczkę', + 'no_records' => 'Nie znaleziono wtyczek', + 'no_name' => 'Brak nazwy', + 'search' => 'Szukaj...', + 'filter_description' => 'Wyświetl wszystkie wtyczki lub tylko twoje wtyczki.', + 'settings' => 'Ustawienia', + 'entity_name' => 'Wtyczka', + 'field_name' => 'Nazwa', + 'field_author' => 'Autor', + 'field_description' => 'Opis', + 'field_icon' => 'Ikona wtyczki', + 'field_plugin_namespace' => 'Przestrzeń nazw wtyczki', + 'field_author_namespace' => 'Przestrzeń nazw autora', + 'field_namespace_description' => 'Przestrzeń nazw może zawierać tylko litery alfabetu łacińskiego oraz cyfry i powinna się zaczynać na literę z alfabetu łacińskiego. Przykładowa przestrzeń nazw: Blog', + 'field_author_namespace_description' => 'Nie możesz zmienić przestrzeni nazw za pomocą Buildera po utworzeniu wtyczki. Przykładowa przestrzeń nazw autora: JohnSmith', + 'tab_general' => 'Parametry ogólne', + 'tab_description' => 'Opis', + 'field_homepage' => 'Strona domowa wtyczki', + 'no_description' => 'Brak opisu dla tej wtyczki', + 'error_settings_not_editable' => 'Ustawienia tej wtyczki nie mogą być zmienione za pomocą Buildera.', + 'update_hint' => 'Możesz zmienić zlokalizowaną nazwę oraz opis wtyczki w zakładce Lokalizacja.', + 'manage_plugins' => 'Twórz i edytuj wtyczki', + ], + 'author_name' => [ + 'title' => 'Autor', + 'description' => 'Domyślna nazwa autora używana przy tworzeniu nowych wtyczek. Nazwa autora nie jest stała - możesz ją zmienić podczas konfiguracji wtyczek w dowolnym momencie.', + ], + 'author_namespace' => [ + 'title' => 'Przestrzeń nazw autora', + 'description' => 'Jeżeli tworzysz wtyczki dla Marketplace, przestrzeń nazw powinna być zgodna z kodem autora i nie można jej zmienić. Szczegółowe informacje na ten temat można znaleźć w dokumentacji.', + ], + 'database' => [ + 'menu_label' => 'Baza danych', + 'no_records' => 'Nie znaleziono tabel', + 'search' => 'Szukaj...', + 'confirmation_delete_multiple' => 'Usunąć wybrane tabele?', + 'field_name' => 'Nazwa tabeli', + 'tab_columns' => 'Kolumny', + 'column_name_name' => 'Kolumna', + 'column_name_required' => 'Podaj nazwę kolumny', + 'column_name_type' => 'Typ', + 'column_type_required' => 'Please typ kolumny', + 'column_name_length' => 'Długość', + 'column_validation_length' => 'Długość powinna być liczbą całkowitą lub być określona poprzez dokładność i skalę (10,2) dla kolumn typu Decimal. Spacje nie są dozwolone w tej kolumnie.', + 'column_validation_title' => 'Tylko cyfry, małe litery alfabetu łacińskiego oraz podkreślenia są dozwolone w nazwach kolumn', + 'column_default' => 'Wartość domyślna', + 'tab_new_table' => 'Nowa tabela', + 'btn_add_column' => 'Dodaj kolumnę', + 'btn_delete_column' => 'Usuń kolumnę', + 'btn_add_timestamps' => 'Dodaj znaczniki czasu (Timestamps)', + 'btn_add_soft_deleting' => 'Dodaj obsługę miękkiego usuwania (Soft deleting)', + 'timestamps_exist' => 'Kolumny created_at oraz deleted_at istnieją już w tabeli.', + 'soft_deleting_exist' => 'Kolumna deleted_at istnieje już w tabeli.', + 'confirm_delete' => 'Usunąć tabelę?', + 'error_enum_not_supported' => 'Tabela zawiera przynajmniej jedną kolumnę typu "enum", który nie jest aktualnie obsługiwany przez Buildera.', + 'error_table_name_invalid_prefix' => 'Nazwa tabeli powinna się zaczynać od prefiksu wtyczki: \':prefix\'.', + 'error_table_name_invalid_characters' => 'Nieprawidłowa nazwa tabeli. Nazwy tabel powinny zawierać tylko małe litery alfabetu łacińskiego, cyfry oraz podkreślenia. Nazwy powinny zaczynać się od litery alfabetu łacińskiego i nie powinny zawierać spacji.', + 'error_table_duplicate_column' => 'Kolumna \':column\' już istnieje.', + 'error_table_auto_increment_in_compound_pk' => 'Kolumna Auto-increment nie może być częścią złożonego klucza głównego.', + 'error_table_mutliple_auto_increment' => 'Tabela nie może zawierać więcej niż jednej kolumny Auto-increment.', + 'error_table_auto_increment_non_integer' => 'Kolumna Auto-increment powinna być typu integer.', + 'error_table_decimal_length' => 'Długośc dla typu :type powinna być w formacie \'10,2\' i nie zawierać spacji.', + 'error_table_length' => 'Długość dla typu :type powinna być podana jako liczba całkowita.', + 'error_unsigned_type_not_int' => 'Błąd kolumny \':column\'. Flaga Unsigned może być ustawiona tylko dla kolumn typu integer.', + 'error_integer_default_value' => 'Niepoprawna wartość domyślna dla kolumny \':column\'. Dozwolone formaty to \'10\', \'-10\'.', + 'error_decimal_default_value' => 'Niepoprawna wartość domyślna dla kolumny \':column\'. Dozwolone formaty to \'1.00\', \'-1.00\'.', + 'error_boolean_default_value' => 'Niepoprawna wartość domyślna dla kolumny \':column\'. Dozwolone wartości to \'0\' oraz \'1\'.', + 'error_unsigned_negative_value' => 'Wartość domyślna dla kolumny \':column\' z flagą Unsigned nie może być ujemna.', + 'error_table_already_exists' => 'Tabela o nazwie \':name\' już istnieje w bazie danych', + 'error_table_name_too_long' => 'Nazwa tabeli nie powinna być dłuższa nić 64 znaki.', + 'error_column_name_too_long' => 'Nazwa kolumny \':column\' jest za długa. Nazwy kolumn nie powinny być dłuższe niż 64 znaki.', + ], + 'model' => [ + 'menu_label' => 'Modele', + 'entity_name' => 'Model', + 'no_records' => 'Nie znaleziono modeli', + 'search' => 'Szukaj...', + 'add' => 'Dodaj...', + 'forms' => 'Formularze', + 'lists' => 'Listy', + 'field_class_name' => 'Nazwa klasy', + 'field_database_table' => 'Tabela bazy danych', + 'field_add_timestamps' => 'Dodaj wsparcie dla znaczników czasu (Timestamps)', + 'field_add_timestamps_description' => 'Tabela musi posiadać kolumny created_at oraz updated_at.', + 'field_add_soft_deleting' => 'Dodaj wsparcie dla miękkiego usuwania (Soft deleting).', + 'field_add_soft_deleting_description' => 'Tabela musi posiadać kolumnę deleted_at.', + 'error_class_name_exists' => 'Istnieje już model o podanej nazwie klasy.: :path', + 'error_timestamp_columns_must_exist' => 'Tabela musi posiadać kolumny created_at oraz updated_at.', + 'error_deleted_at_column_must_exist' => 'Tabela musi posiadać kolumnę deleted_at.', + 'add_form' => 'Dodaj formularz', + 'add_list' => 'Dodaj listę', + ], + 'form' => [ + 'saved' => 'Zapisano formularz', + 'confirm_delete' => 'Usunąć formularz?', + 'tab_new_form' => 'Nowy formularz', + 'property_label_title' => 'Etykieta', + 'property_label_required' => 'Podaj tekst etykiety elementu.', + 'property_span_title' => 'Rozpiętość', + 'property_comment_title' => 'Komentarz', + 'property_comment_above_title' => 'Komentarz górny', + 'property_default_title' => 'Wartość domyślna', + 'property_checked_default_title' => 'Domyślnie zaznaczone', + 'property_css_class_title' => 'Klasa CSS', + 'property_css_class_description' => 'Opcjonalna klasa CSS dla kontenera.', + 'property_disabled_title' => 'Wyłączone', + 'property_read_only_title' => 'Tylko do odczytu', + 'property_hidden_title' => 'Ukryte', + 'property_required_title' => 'Wymagane', + 'property_field_name_title' => 'Nazwa pola', + 'property_placeholder_title' => 'Symbol zastępczy', + 'property_default_from_title' => 'Wartość domyślna z', + 'property_stretch_title' => 'Stretch', + 'property_stretch_description' => 'Specifies if this field stretches to fit the parent height.', + 'property_context_title' => 'Kontekst', + 'property_context_description' => 'Określa w jakim kontekście pole formularza będzie widoczne.', + 'property_context_create' => 'Stwórz', + 'property_context_update' => 'Edytuj', + 'property_context_preview' => 'Podgląd', + 'property_dependson_title' => 'Zależy od', + 'property_trigger_action' => 'Akcja', + 'property_trigger_show' => 'Pokaż', + 'property_trigger_hide' => 'Ukryj', + 'property_trigger_enable' => 'Włącz', + 'property_trigger_disable' => 'Wyłącz', + 'property_trigger_empty' => 'Puste', + 'property_trigger_field' => 'Pole', + 'property_trigger_field_description' => 'Określa nazwę drugiego pola które wyzwoli akcję.', + 'property_trigger_condition' => 'Warunek', + 'property_trigger_condition_description' => 'Określa warunek, który pole powinno spełniać, aby warunek był uznany za prawdziwy (true). Obsługiwane wartości to: checked, unchedked, value[wartość].', + 'property_trigger_condition_checked' => 'Zaznaczony', + 'property_trigger_condition_unchecked' => 'Odznaczony', + 'property_trigger_condition_somevalue' => 'value[wprowadź-wartość-tutaj]', + 'property_preset_title' => 'Preset', + 'property_preset_description' => 'Umożliwia ustawienie początkowej wartości pola na podstawie wartości innego pola przy użyciu wybranego konwertera.', + 'property_preset_field' => 'Pole', + 'property_preset_field_description' => 'Określa nazwę pola, z którego będzie pobierana wartość.', + 'property_preset_type' => 'Typ', + 'property_preset_type_description' => 'Określa typ konwertera', + 'property_attributes_title' => 'Atrybuty', + 'property_attributes_description' => 'Niestandardowe atrybuty HTML, które będą dodane do elementu formularza.', + 'property_container_attributes_title' => 'Atrybuty kontenera', + 'property_container_attributes_description' => 'Niestandardowe atrybuty HTML, które będą dodane do kontenera elementu.', + 'property_group_advanced' => 'Zaawansowane', + 'property_dependson_description' => 'Lista nazw pól, od których zależy to pole. Po ich zmianie to pole zostanie zaktualizowane. Jedno pole na linię.', + 'property_trigger_title' => 'Wyzwalacz', + 'property_trigger_description' => 'Pozwala zmieniać atrybuty elementów, takie jak widocznośc lub wartość, w zależności od stanu innych elementów.', + 'property_default_from_description' => 'Pobiera wartość domyślną z wartości innego pola.', + 'property_field_name_required' => 'Nazwa pola jest wymagana', + 'property_field_name_regex' => 'Nazwa pola może zawierać tylko litery alfabetu łacińskiego, cyfry, podkreślenia, myślniki oraz nawiasy prostokątne.', + 'property_attributes_size' => 'Rozmiar', + 'property_attributes_size_tiny' => 'Malutki', + 'property_attributes_size_small' => 'Mały', + 'property_attributes_size_large' => 'Duży', + 'property_attributes_size_huge' => 'Ogromny', + 'property_attributes_size_giant' => 'Gigantyczny', + 'property_comment_position' => 'Pozycja komentarza', + 'property_comment_position_above' => 'Powyżej', + 'property_comment_position_below' => 'Poniżej', + 'property_hint_path' => 'Ścieżka fragmentu podpowiedzi', + 'property_hint_path_description' => 'Ścieżka do pliku fragmentu zawierającego tekst podpowiedzi. Użyj symbolu $ aby odnieść się do katalogu głównego wtyczek, np.: $/acme/blog/parts/_partial.htm', + 'property_hint_path_required' => 'Podaj ścieżkę do pliku fragmentu z podpowiedzią', + 'property_partial_path' => 'Ścieżka fragmentu', + 'property_partial_path_description' => 'Ścieżka do pliku fragmentu. Użyj symbolu $ aby odnieść się do katalogu głównego wtyczek, np.: $/acme/blog/parts/_partial.htm', + 'property_partial_path_required' => 'Podaj ścieżkę do pliku fragmentu', + 'property_code_language' => 'Język', + 'property_code_theme' => 'Motyw', + 'property_theme_use_default' => 'Użyj domyślnego motywu', + 'property_group_code_editor' => 'Edytor kodu', + 'property_gutter' => 'Odstęp', + 'property_gutter_show' => 'Widoczny', + 'property_gutter_hide' => 'Ukryty', + 'property_wordwrap' => 'Zawijanie tekstu', + 'property_wordwrap_wrap' => 'Zawijaj', + 'property_wordwrap_nowrap' => 'Nie zawijaj', + 'property_fontsize' => 'Rozmiar czcionki', + 'property_codefolding' => 'Zwijanie kodu', + 'property_codefolding_manual' => 'Ręczne', + 'property_codefolding_markbegin' => 'Zaznacz początek', + 'property_codefolding_markbeginend' => 'Zaznacz początek i koniec', + 'property_autoclosing' => 'Auto zamykanie', + 'property_enabled' => 'Włączone', + 'property_disabled' => 'Wyłączone', + 'property_soft_tabs' => '"Miękkie" karty', + 'property_tab_size' => 'Rozmiar karty', + 'property_readonly' => 'Tylko do odczytu', + 'property_use_default' => 'Użyj domyślnych ustawień', + 'property_options' => 'Opcje', + 'property_prompt' => 'Zachęta', + 'property_prompt_description' => 'Tekst do wyświetlenia na przycisku utwórz.', + 'property_prompt_default' => 'Dodaj nowy element', + 'property_available_colors' => 'Dostępne kolory', + 'property_available_colors_description' => 'Lista dostępnych kolorów w formacie heksadecymalnym (#FF0000). Pozostaw puste dla domyślnego zestawu kolorów. Jedna wartość na wiersz.', + 'property_datepicker_mode' => 'Tryb', + 'property_datepicker_mode_date' => 'Data', + 'property_datepicker_mode_datetime' => 'Data i czas', + 'property_datepicker_mode_time' => 'Czas', + 'property_datepicker_min_date' => 'Najwcześniejsza data', + 'property_datepicker_max_date' => 'Najpóźniejsza data', + 'property_datepicker_year_range' => 'Zakres lat', + 'property_datepicker_year_range_description' => 'Liczba lat z obu stron zakresu (np. "10") lub dolny i górny zakres w tablicy (np. "[1900,2015]"). Pozostaw puste dla wartości domyślnej (10).', + 'property_datepicker_year_range_invalid_format' => 'Nieprawidłowy format zakresu lat. Użyj liczby (np. "10") lub dolnego i górnego zakresu w tablicy (np. "[1900,2015]")', + 'property_datepicker_format' => 'Format', + 'property_datepicker_year_format_description' => 'Zdefiniuj niestandardowy format daty. Domyślny format to "Y-m-d"', + 'property_fileupload_mode' => 'Tryb', + 'property_fileupload_mode_file' => 'Plik', + 'property_fileupload_mode_image' => 'Obraz', + 'property_group_fileupload' => 'Przesyłanie pliku', + 'property_fileupload_image_width' => 'Szerokość obrazu', + 'property_fileupload_image_width_description' => 'Opcjonalne. Obrazy będą przeskalowane do tej szerokości. Dotyczy tylko trybu Obraz.', + 'property_fileupload_invalid_dimension' => 'Niepoprawny rozmiar - wprowadź liczbę.', + 'property_fileupload_image_height' => 'Wysokość obrazu', + 'property_fileupload_image_height_description' => 'Opcjonalne. obrazy będą przeskalowane do tej wysokości. Dotyczy tylko trybu Obraz.', + 'property_fileupload_file_types' => 'Rozszerzenia plików', + 'property_fileupload_file_types_description' => 'Opcjonalne. Lista akceptowanych rozszerzeń plików rozdzielona przecinkami. Przykład: zip,txt', + 'property_fileupload_mime_types' => 'Typy MIME', + 'property_fileupload_mime_types_description' => 'Opcjonalne. Lista akceptowanych typów MIME rozdzielona przecinkami, podane jako rozszerzenia plików lub pełne nazwy. Przykład: bin,txt', + 'property_fileupload_use_caption' => 'Użyj podpisu', + 'property_fileupload_use_caption_description' => 'Umożliwia ustawienie tytułu i opisu pliku.', + 'property_fileupload_thumb_options' => 'Opcje miniatur', + 'property_fileupload_thumb_options_description' => 'Zarządza opcjami automatycznie generowanych miniatur. Dotyczy tylko trybu Obraz.', + 'property_fileupload_thumb_mode' => 'Tryb', + 'property_fileupload_thumb_auto' => 'Automatyczny', + 'property_fileupload_thumb_exact' => 'Dokładny', + 'property_fileupload_thumb_portrait' => 'Pionowy', + 'property_fileupload_thumb_landscape' => 'Poziomy', + 'property_fileupload_thumb_crop' => 'Przytnij', + 'property_fileupload_thumb_extension' => 'Rozszerzenie pliku', + 'property_name_from' => 'Kolumna nazwy', + 'property_name_from_description' => 'Nazwa kolumny w relacji używana do wyświetlania nazwy', + 'property_relation_select' => 'Wybierz', + 'property_relation_select_description' => 'Połącz (CONCAT) wiele kolumn do wyświetlania nazwy', + 'property_description_from' => 'Kolumna opisu', + 'property_description_from_description' => 'Nazwa kolumny w relacji używana do wyświetlania opisu', + 'property_recordfinder_prompt' => 'Zachęta', + 'property_recordfinder_prompt_description' => 'Tekst, który zostanie wyświetlony, gdy nie wybrano żadnego rekordu. Znak %s reprezentuje ikonę wyszukiwania. Pozostaw puste dla domyślnej zachęty.', + 'property_recordfinder_list' => 'Konfiguracja listy', + 'property_recordfinder_list_description' => 'Ścieżka do pliku konfiguracyjnego kolumny listy. Użyj symbolu $ aby odnieść się do katalogu głównego wtyczek, np.: $/acme/blog/parts/_partial.htm', + 'property_recordfinder_list_required' => 'Podaj ścieżkę do pliku YAML listy', + 'property_group_recordfinder' => 'Wyszukiwarka rekordów', + 'property_mediafinder_mode' => 'Tryb', + 'property_mediafinder_mode_file' => 'Plik', + 'property_mediafinder_mode_image' => 'Obraz', + 'property_mediafinder_image_width_description' => 'Opcjonalne. Jeżeli używasz trybu "Obraz", pogląd zostanie wyświetlony do tej szerokości.', + 'property_mediafinder_image_height_description' => 'Opcjonalne. Jeżeli używasz trybu "Obraz", pogląd zostanie wyświetlony do tej wysokości.', + 'property_group_taglist' => 'Lista tagów', + 'property_taglist_mode' => 'Tryb', + 'property_taglist_mode_description' => 'Określa format w jakim zwracana jest wartość pola', + 'property_taglist_mode_string' => 'Ciąg znaków', + 'property_taglist_mode_array' => 'Tablica', + 'property_taglist_mode_relation' => 'Relacja', + 'property_taglist_separator' => 'Separator', + 'property_taglist_separator_comma' => 'Przecinki', + 'property_taglist_separator_space' => 'Spacje', + 'property_taglist_options' => 'Predefiniowane tagi', + 'property_taglist_custom_tags' => 'Niestandardowe tagi', + 'property_taglist_custom_tags_description' => 'Zezwala na ręczne wprowadzanie niestandardowych tagów przez użytkownika.', + 'property_taglist_name_from' => 'Nazwa z', + 'property_taglist_name_from_description' => 'Określa atrybut modelu relacji wyświetlany w znaczniku. Używany tylko w trybie "Relacja".', + 'property_taglist_use_key' => 'Użyj klucza', + 'property_taglist_use_key_description' => 'Jeśli zaznaczone, lista tagów użyje klucza zamiast wartości do zapisu i odczytu danych. Używany tylko w trybie "Relacja".', + 'property_group_relation' => 'Relacja', + 'property_relation_prompt' => 'Zachęta', + 'property_relation_prompt_description' => 'Tekst wyświetlany, gdy nie ma dostępnych opcji.', + 'property_empty_option' => 'Pusta opcja', + 'property_empty_option_description' => 'Pusta opcja odpowiada pustemu wyborowi, jednakże w przeciwieństwie do niego może być ponownie wybrana.', + 'property_show_search' => 'Włącz wyszukiwanie', + 'property_show_search_description' => 'Włącza funkcję wyszukiwania dla tej listy.', + 'property_max_items' => 'Maksymalna liczba elementów', + 'property_max_items_description' => 'Maksymalna liczba elementów dozwolona w repeaterze.', + 'control_group_standard' => 'Standardowe kontrolki', + 'control_group_widgets' => 'Widżety', + 'click_to_add_control' => 'Dodaj kontrolkę', + 'loading' => 'Ładowanie...', + 'control_text' => 'Tekst', + 'control_text_description' => 'Jednowierszowe pole tekstowe', + 'control_password' => 'Hasło', + 'control_password_description' => 'Jednowierszowe pole hasła', + 'control_checkbox' => 'Pole wyboru', + 'control_checkbox_description' => 'Pojedyncze pole wyboru', + 'control_switch' => 'Przełącznik', + 'control_switch_description' => 'Pojedynczy przełącznik. Alternatywa dla pola wyboru', + 'control_textarea' => 'Pole tekstowe', + 'control_textarea_description' => 'Wielowierszowe pole tekstowe o kontrolowanej wysokości', + 'control_dropdown' => 'Lista rozwijana', + 'control_dropdown_description' => 'Lista rozwijana ze statycznymi lub dynamicznie ładowanymi opcjami', + 'control_balloon-selector' => 'Selektor typu Balloon', + 'control_balloon-selector_description' => 'Lista ze statycznymi lub dynamicznie ładowanymi opcjami, w której jednocześnie może być wybrany tylko jeden element', + 'control_unknown' => 'Nieznany rodzaj elementu: :type', + 'control_repeater' => 'Repeater', + 'control_repeater_description' => 'Wyświetla zestaw powtarzających się elementów formularza', + 'control_number' => 'Numer', + 'control_number_description' => 'Jednowierszowe pole tekstowe, przyjmujące jedynie liczby', + 'control_hint' => 'Podpowiedź', + 'control_hint_description' => 'Wyświetla zawartość fragmentu w elemencie, który może być ukryty przez użytkownika', + 'control_partial' => 'Fragment', + 'control_partial_description' => 'Wyświetla zawartość fragmentu', + 'control_section' => 'Sekcja', + 'control_section_description' => 'Wyświetla sekcję z tytułem i podtytułem', + 'control_radio' => 'Lista pól opcji', + 'control_radio_description' => 'Lista pól opcji, w której jednocześnie może być wybrany tylko jeden element', + 'control_radio_option_1' => 'Opcja 1', + 'control_radio_option_2' => 'Opcja 2', + 'control_checkboxlist' => 'Lista pól wyboru', + 'control_checkboxlist_description' => 'Lista pól wyboru, w której jednocześnie może być wybrane kilka elementów', + 'control_codeeditor' => 'Edytor kodu', + 'control_codeeditor_description' => 'Edytor tekstowy sformatowanego kodu lub znaczników', + 'control_colorpicker' => 'Próbnik koloru', + 'control_colorpicker_description' => 'Pole wyboru koloru w wartości heksadecymalnej', + 'control_datepicker' => 'Wybór daty', + 'control_datepicker_description' => 'Pole tekstowe używane do wyboru daty i godziny', + 'control_richeditor' => 'Edytor WYSYWIG', + 'control_richeditor_description' => 'Edytor wizualny tekstu sformatowanego', + 'control_markdown' => 'Edytor Markdown', + 'control_markdown_description' => 'Edytor tekstu sformatowanego za pomocą Markdown', + 'control_taglist' => 'Lista tagów', + 'control_taglist_description' => 'Pole do wprowadzania listy tagów', + 'control_fileupload' => 'Prześlij plik', + 'control_fileupload_description' => 'Pole do przesyłania obrazów lub zwykłych plików', + 'control_recordfinder' => 'Wyszukiwarka rekordów', + 'control_recordfinder_description' => 'Pole ze szcegółami powiązanego rekordu z funkcją wyszukiwania rekordów', + 'control_mediafinder' => 'Wyszukiwarka mediów', + 'control_mediafinder_description' => 'Pole wyboru elementu z biblioteki mediów', + 'control_relation' => 'Relacja', + 'control_relation_description' => 'Wyświetla listę rozwijaną lub listę pól wyboru w celu wybrania powiązanego rekordu', + 'error_file_name_required' => 'Wprowadź nazwę pliku formularza.', + 'error_file_name_invalid' => 'Nazwa pliku może zawierać jedynie litery alfabetu łacińskiego, cyfry, podkreślenia, kropki i krzyżyki.', + 'span_left' => 'Lewo', + 'span_right' => 'Prawo', + 'span_full' => 'Cała szerokość', + 'span_auto' => 'Auto', + 'empty_tab' => 'Pusta karta', + 'confirm_close_tab' => 'Zakładka zawiera elementy, które zostaną usunięte. Czy kontynuować?', + 'tab' => 'Karta formularza', + 'tab_title' => 'Tytuł', + 'controls' => 'Kontrolki', + 'property_tab_title_required' => 'Tytuł karty jest wymagany.', + 'tabs_primary' => 'Zakładki główne', + 'tabs_secondary' => 'Zakładki dodatkowe', + 'tab_stretch' => 'Rozciągnięcie', + 'tab_stretch_description' => 'Określa czy kontener kart rozciąga się, aby pasować do wysokości rodzica.', + 'tab_css_class' => 'Klasa CSS', + 'tab_css_class_description' => 'Przypisuje klasę CSS do kontenera kart.', + 'tab_name_template' => 'Karta %s', + 'tab_already_exists' => 'Tab with the specified title already exists.', + ], + 'list' => [ + 'tab_new_list' => 'Nowa lista', + 'saved' => 'Zapisano listę', + 'confirm_delete' => 'Usunąć listę?', + 'tab_columns' => 'Kolumny', + 'btn_add_column' => 'Dodaj kolumnę', + 'btn_delete_column' => 'Usuń kolumnę', + 'column_dbfield_label' => 'Pola', + 'column_dbfield_required' => 'Podaj pole modelu', + 'column_name_label' => 'Etykieta', + 'column_label_required' => 'Podaj etykietę kolumny', + 'column_type_label' => 'Type', + 'column_type_required' => 'Podaj typ kolumny', + 'column_type_text' => 'Tekst', + 'column_type_number' => 'Numer', + 'column_type_switch' => 'Przełącznik', + 'column_type_datetime' => 'Data/Czas', + 'column_type_date' => 'Data', + 'column_type_time' => 'Czas', + 'column_type_timesince' => 'Czas od', + 'column_type_timetense' => 'Określenie czasu', + 'column_type_select' => 'Lista elementów', + 'column_type_partial' => 'Fragment', + 'column_label_default' => 'Domyślny', + 'column_label_searchable' => 'Szukaj', + 'column_label_sortable' => 'Sortuj', + 'column_label_invisible' => 'Niewidoczny', + 'column_label_select' => 'Wybierz', + 'column_label_relation' => 'Relacja', + 'column_label_css_class' => 'Klasa CSS', + 'column_label_width' => 'Szerokość', + 'column_label_path' => 'Ścieżka', + 'column_label_format' => 'Format', + 'column_label_value_from' => 'Wartość z', + 'error_duplicate_column' => 'Kolumna \':column\' już istnieje.', + 'btn_add_database_columns' => 'Dodaj kolumny z bazy danych', + 'all_database_columns_exist' => 'Wszystkie kolumny są już zdefiniowane na liście', + ], + 'controller' => [ + 'menu_label' => 'Kontrolery', + 'no_records' => 'Nie znaleziono kontrolerów', + 'controller' => 'Kontroler', + 'behaviors' => 'Zachowania', + 'new_controller' => 'Nowy kontroler', + 'error_controller_has_no_behaviors' => 'Kontroler nie posiada konfigurowalnych zachowań.', + 'error_invalid_yaml_configuration' => 'Wystąpił błąd podczas ładowania pliku konfiguracji zachowania :file', + 'behavior_form_controller' => 'Zachowanie - Form Controller', + 'behavior_form_controller_description' => 'Dodaje funkcjonalność do strony backendu. Zapewnia strony Utwórz, Edytuj, Podgląd.', + 'property_behavior_form_placeholder' => '--wybierz formularz--', + 'property_behavior_form_name' => 'Nazwa', + 'property_behavior_form_name_description' => 'Nazwa obiektu zarządzanego przez ten formularz', + 'property_behavior_form_name_required' => 'Wprowadź nazwę formularza', + 'property_behavior_form_file' => 'Konfiguracja formularza', + 'property_behavior_form_file_description' => 'Odwołanie do pliku konfiguracyjnego formularza', + 'property_behavior_form_file_required' => 'Wprowadź ścieżkę do pliku konfiguracyjnego formularza', + 'property_behavior_form_model_class' => 'Klasa modelu', + 'property_behavior_form_model_class_description' => 'Nazwa klasy modelu. Dane formularza są ładowane i zapisywane używając tego modelu.', + 'property_behavior_form_model_class_required' => 'Wybierz klasę modelu', + 'property_behavior_form_default_redirect' => 'Domyślne przekierowanie', + 'property_behavior_form_default_redirect_description' => 'Strona, na którą zostanie przekierowany użytkownik po zapisaniu lub anulowaniu formularza.', + 'property_behavior_form_create' => 'Stwórz stronę rekordu', + 'property_behavior_form_redirect' => 'Przekierowanie', + 'property_behavior_form_redirect_description' => 'Strona, na którą zostanie przekierowany użytkownik po utworzeniu rekordu.', + 'property_behavior_form_redirect_close' => 'Przekierowanie po zamknięciu', + 'property_behavior_form_redirect_close_description' => 'Strona na którą zostanie przekierowany użytkownik po utworzeniu rekordu, gdy zmienna "close" w tablicy POST jest obecna.', + 'property_behavior_form_flash_save' => 'Komunikat Flash - Zapisano', + 'property_behavior_form_flash_save_description' => 'Komunikat do wyświetlenia po zapisaniu rekordu.', + 'property_behavior_form_page_title' => 'Tytuł strony', + 'property_behavior_form_update' => 'Aktualizuj stronę rekordu', + 'property_behavior_form_update_redirect' => 'Przekierowanie', + 'property_behavior_form_create_redirect_description' => 'Strona, na którą zostanie przekierowany użytkownik po zapisaniu rekordu.', + 'property_behavior_form_flash_delete' => 'Komunikat Flash - Usunięto', + 'property_behavior_form_flash_delete_description' => 'Komunikat do wyświetlenia po usunięciu rekordu.', + 'property_behavior_form_preview' => 'Strona podglądu rekordu', + 'behavior_list_controller' => 'Zachowanie - List Controller', + 'behavior_list_controller_description' => 'Dodaje funkcjonalność do strony backendu. Zapewnia listę z możliwością sortowania i przeszukiwania i opcjonalnymi linkami do rekordów. Automatycznie tworzy akcję kontrolera "index".', + 'property_behavior_list_title' => 'Tytuł listy', + 'property_behavior_list_title_required' => 'Wprowadź tytuł listy', + 'property_behavior_list_placeholder' => '--wybierz listę--', + 'property_behavior_list_model_class' => 'Klasa modelu', + 'property_behavior_list_model_class_description' => 'Nazwa klasy modelu, dane są ładowane z tego modelu.', + 'property_behavior_form_model_class_placeholder' => '--wybierz model--', + 'property_behavior_list_model_class_required' => 'Wybierz klasę modelu', + 'property_behavior_list_model_placeholder' => '--wybierz model--', + 'property_behavior_list_file' => 'Plik konfiguracyjny listy', + 'property_behavior_list_file_description' => 'Odwołanie do pliku konfiguracyjnego listy', + 'property_behavior_list_file_required' => 'Wprowadź ścieżkę do pliku konfiguracyjnego listy', + 'property_behavior_list_record_url' => 'Adres URL rekordu', + 'property_behavior_list_record_url_description' => 'Połącz każdy rekord z unikatową stroną. Np.: "users/update/:id". Parametr ":id" będzie zastąpiony identyfikatorem rekordu.', + 'property_behavior_list_no_records_message' => 'Komunikat o braku rekordów', + 'property_behavior_list_no_records_message_description' => 'Komunikat, który zostanie wyświetlony w przypadku braku rekordów.', + 'property_behavior_list_recs_per_page' => 'Rekordy na stronę', + 'property_behavior_list_recs_per_page_description' => 'Liczba rekordów do wyświetlenia na stronie. Wpisz 0 aby wyłączyć paginację. Wartość domyślna: 0', + 'property_behavior_list_recs_per_page_regex' => 'Liczba rekordów na stronę powinna być liczbą całkowitą', + 'property_behavior_list_show_setup' => 'Pokaż przycisk konfiguracji', + 'property_behavior_list_show_sorting' => 'Pokaż sortowanie', + 'property_behavior_list_default_sort' => 'Domyślne sortowanie', + 'property_behavior_form_ds_column' => 'Kolumna', + 'property_behavior_form_ds_direction' => 'Kierunek', + 'property_behavior_form_ds_asc' => 'Rosnąco', + 'property_behavior_form_ds_desc' => 'Malejąco', + 'property_behavior_list_show_checkboxes' => 'Pokaż pola wyboru', + 'property_behavior_list_onclick' => 'Kod JS po kliknięciu', + 'property_behavior_list_onclick_description' => 'Dodatkowy kod JavaScript do wykonania po kliknięciu rekordu.', + 'property_behavior_list_show_tree' => 'Pokaż drzewo', + 'property_behavior_list_show_tree_description' => 'Wyświetla hierarchię dla rekordów nadrzędnych / podrzędnych.', + 'property_behavior_list_tree_expanded' => 'Rozwinięte drzewo', + 'property_behavior_list_tree_expanded_description' => 'Określa czy gałęzie drzewa powinny być domyślnie rozwinięte.', + 'property_behavior_list_toolbar' => 'Pasek narzędzi', + 'property_behavior_list_toolbar_buttons' => 'Fragment z przyciskami', + 'property_behavior_list_toolbar_buttons_description' => 'Odwołanie do pliku fragmentu z przyciskami paska narzędzi. Np.: list_toolbar', + 'property_behavior_list_search' => 'Szukaj', + 'property_behavior_list_search_prompt' => 'Zachęta wyszukiwarki', + 'property_behavior_list_filter' => 'Konfiguracja filtrów', + 'behavior_reorder_controller' => 'Zachowanie - Reorder Controller', + 'behavior_reorder_controller_description' => 'Dodaje funkcjonalność do strony backendu. Zapewnia możliwość sortowania i zmiany kolejności rekordów. Automatycznie tworzy akcję kontrolera "reorder".', + 'property_behavior_reorder_title' => 'Tekst zmiany kolejności', + 'property_behavior_reorder_title_required' => 'Wprowadź tekst zmiany kolejności', + 'property_behavior_reorder_name_from' => 'Nazwa atrybutu', + 'property_behavior_reorder_name_from_description' => 'Atrybut modelu, który zostanie użyty jako etykieta rekordu.', + 'property_behavior_reorder_name_from_required' => 'Wprowadź nazwę atrybutu', + 'property_behavior_reorder_model_class' => 'Klasa modelu', + 'property_behavior_reorder_model_class_description' => 'Nazwa klasy modelu. Dane są ładowane z tego modelu.', + 'property_behavior_reorder_model_class_placeholder' => '--wybierz model--', + 'property_behavior_reorder_model_class_required' => 'Wybierz klasę modelu', + 'property_behavior_reorder_model_placeholder' => '--wybierz klasę modelu--', + 'property_behavior_reorder_toolbar' => 'Pasek narzędzi', + 'property_behavior_reorder_toolbar_buttons' => 'Fragment z przyciskami', + 'property_behavior_reorder_toolbar_buttons_description' => 'Odwołanie do pliku fragmentu z przyciskami paska narzędzi. Np.: reorder_toolbar', + 'error_controller_not_found' => 'Plik kontrolera nie został znaleziony.', + 'error_invalid_config_file_name' => 'Plik konfiguracyjny zachowania :class (:file) zawiera nieprawidłowe znaki i nie może zostać załadowany.', + 'error_file_not_yaml' => 'Plik konfiguracyjny zachowania :class (:file) nie jest plikiem YAML. Obsługiwane są tylko pliki konfiguracyjne YAML.', + 'saved' => 'Zapisano kontroler', + 'controller_name' => 'Nazwa kontrolera', + 'controller_name_description' => 'Nazwa kontrolera określa nazwę klasy i adres URL stron w backendzie. Obowiązują standardowe konwencje nazewnictwa zmiennych w PHP. Pierwszym znakiem powinna być duża litera alfabetu łacińskiego. Przykłady: Categories, Posts, Products.', + 'base_model_class' => 'Bazowa klasa modelu', + 'base_model_class_description' => 'Wybierz klasę modelu, która ma być używana jako model bazowy w zachowaniach które go wymagają lub wspierają. Zachowania możesz skonfigurować później.', + 'base_model_class_placeholder' => '--wybierz model--', + 'controller_behaviors' => 'Zachowania', + 'controller_behaviors_description' => 'Wybierz zachowania, które chcesz zaimplementować w kontrolerze. Builder automatycznie utworzy pliki widoków wymaganych przez zachowania.', + 'controller_permissions' => 'Uprawnienia', + 'controller_permissions_description' => 'Wybierz uprawnienia, które pozwolą na dostęp do widoków kontrolera. Uprawnienia można zdefiniować w zakładce "Uprawnienia". Możesz zmienić tę opcję później edytując skrypt PHP kontrolera.', + 'controller_permissions_no_permissions' => 'Wtyczka nie definiuje żadnych uprawnień.', + 'menu_item' => 'Aktywny element menu', + 'menu_item_description' => 'Wybierz element menu dla stron tego kontrolera. Możesz zmienić tę opcję później edytując skrypt PHP kontrolera.', + 'menu_item_placeholder' => '--wybierz element menu--', + 'error_unknown_behavior' => 'Klasa zachowania :class nie jest zarejestrowana w bibliotece zachowań.', + 'error_behavior_view_conflict' => 'Wybrane zachowania implementują sprzeczne ze sobą widoki (:view) i nie mogą być używane razem w jednym kontrolerze.', + 'error_behavior_config_conflict' => 'Wybrane zachowania implementują sprzeczne pliki konfiguracyjne (:file) i nie mogą być używane razem w jednym kontrolerze.', + 'error_behavior_view_file_not_found' => 'Nie można znaleźć szablonu widoku zachowania :class w lokalizacji :file.', + 'error_behavior_config_file_not_found' => 'Nie można znaleźć szablonu konfiguracji zachowania :class w lokalizacji :file.', + 'error_controller_exists' => 'Plik kontrolera :file już istnieje.', + 'error_controller_name_invalid' => 'Nieprawidłowy format nazwy kontrolera. Nazwa powinna zawierać tylko cyfry i litery alfabetu łacińskiego. Pierwszym symbolem powinna być duża litera alfabetu łacińskiego.', + 'error_behavior_view_file_exists' => 'Widok kontrolera :view już istnieje.', + 'error_behavior_config_file_exists' => 'Plik konfiguracyjny zachowania :file już istnieje.', + 'error_save_file' => 'Błąd podczas zapisu pliku kontrolera: :file', + 'error_behavior_requires_base_model' => 'Zachowanie :behavior wymaga wybranej bazowej klasy modelu.', + 'error_model_doesnt_have_lists' => 'Wybrany model nie posiada żadnych list. Najpierw utwórz listę.', + 'error_model_doesnt_have_forms' => 'Wybrany model nie posiada żadnych formularzy. Najpierw utwórz formularz.', + ], + 'version' => [ + 'menu_label' => 'Wersje', + 'no_records' => 'Nie znaleziono żadnej wersji wtyczki', + 'search' => 'Szukaj...', + 'tab' => 'Wersje', + 'saved' => 'Zapisano wersję', + 'confirm_delete' => 'Usunąć wersję?', + 'tab_new_version' => 'Nowa wersja', + 'migration' => 'Migracja', + 'seeder' => 'Seeder', + 'custom' => 'Zwiększ numer wersji', + 'apply_version' => 'Zastosuj wersję', + 'applying' => 'Zastosowywanie...', + 'rollback_version' => 'Wycofaj wersję', + 'rolling_back' => 'Wycofywanie...', + 'applied' => 'Zastosowano wersję', + 'rolled_back' => 'Wycofano wersję', + 'hint_save_unapplied' => 'Zapisałeś niezastosowaną wersję. Należy pamiętać, że niezastosowane wersje mogą być automatycznie zastosowane przez system, gdy Ty lub inny użytkownik loguje się do backendu lub gdy tabela bazy danych jest zapisywana w sekcji Baza danych Buildera.', + 'hint_rollback' => 'Wycofanie wersji spowoduje wycofanie wszystkich nowszych wersji niż ta. Należy pamiętać, że niezastosowane wersje mogą być automatycznie zastosowane przez system, gdy Ty lub inny użytkownik loguje się do backendu lub gdy tabela bazy danych jest zapisywana w sekcji Baza danych Buildera.', + 'hint_apply' => 'Zastosowanie wersji spowoduje zastosowanie wszystkich poprzednich niezastosowanych wersji', + 'dont_show_again' => 'Nie pokazuj ponownie', + 'save_unapplied_version' => 'Zapisz niezastosowaną wersję', + ], + 'menu' => [ + 'menu_label' => 'Menu Back-End', + 'tab' => 'Menu', + 'items' => 'Elementy menu', + 'saved' => 'Zapisano menu', + 'add_main_menu_item' => 'Dodaj element menu głównego', + 'new_menu_item' => 'Element menu', + 'add_side_menu_item' => 'Dodaj element podrzędny', + 'side_menu_item' => 'Element menu bocznego', + 'property_label' => 'Etykieta', + 'property_label_required' => 'Podaj etykietę elementu menu.', + 'property_url_required' => 'Podaj adres URL elementu menu', + 'property_url' => 'URL', + 'property_icon' => 'Ikona', + 'property_icon_required' => 'Wybierz ikonę', + 'property_permissions' => 'Uprawnienia', + 'property_order' => 'Kolejność', + 'property_order_invalid' => 'Podaj kolejność elementu menu jako liczbę całkowitą.', + 'property_order_description' => 'Kolejność elementu menu ustala jego pozycje w menu. Jeśli kolejność nie jest podana, element zostanie ustawiony na końcu menu. Domyślne wartości kolejności są wielokrotnością liczby 100.', + 'property_attributes' => 'Atrybuty HTML', + 'property_code' => 'Kod', + 'property_code_invalid' => 'Kod powinien zawierać tylko litery alfabetu łacińskiego i cyfry.', + 'property_code_required' => 'Podaj kod elementu menu.', + 'error_duplicate_main_menu_code' => 'Kod \':code\' istnieje już w menu głównym.', + 'error_duplicate_side_menu_code' => 'Kod \':code\' istnieje już w menu bocznym.', + ], + 'localization' => [ + 'menu_label' => 'Lokalizacja', + 'language' => 'Język', + 'strings' => 'Ciągi znaków', + 'confirm_delete' => 'Usunąć język?', + 'tab_new_language' => 'Nowy język', + 'no_records' => 'Nie znaleziono języków', + 'saved' => 'Zapisano plik języka', + 'error_cant_load_file' => 'Nie można załadować pliku tekstowego - nie znaleziono pliku.', + 'error_bad_localization_file_contents' => 'Nie można załadować pliku tekstowego. Pliki językowe powinny zawierać jedynie definicje tablicy i ciągi znaków.', + 'error_file_not_array' => 'Nie można załadować pliku tekstowego. Pliki językowe powinny zwracać tablicę.', + 'save_error' => 'Błąd podczas zapisywania pliku \':name\'. Sprawdź uprawnienia do zapisu.', + 'error_delete_file' => 'Nie można usunąć pliku językowego.', + 'add_missing_strings' => 'Dodaj brakujące ciągi znaków', + 'copy' => 'Kopiuj', + 'add_missing_strings_label' => 'Wybierz język, z którego chcesz skopiować brakujące ciągi znaków', + 'no_languages_to_copy_from' => 'Nie ma języków, z których można skopiować ciągi znaków.', + 'new_string_warning' => 'Nowy ciąg znaków lub sekcja', + 'structure_mismatch' => 'Struktura pliku języka źródłowego nie zgadza się ze strukturą edytowanego pliku. Niektóre pojedyncze ciągi znaków w edytowanym pliku odpowiadają sekcjom w pliku źródłowym (lub odwrotnie) ie nie można ich scalić automatycznie.', + 'create_string' => 'Utwórz nowy ciąg znaków', + 'string_key_label' => 'Klucz', + 'string_key_comment' => 'Wprowadź klucz używając kropki jako separatora sekcji. Na przykład plugin.search. Ciąg znaków zostanie utworzony w domyślnym pliku językowym wtyczki.', + 'string_value' => 'Wartość', + 'string_key_is_empty' => 'Klucz nie powinien być pusty', + 'string_key_is_a_string' => ':key jest ciągiem znaków i nie może zawierać innych ciągów znaków.', + 'string_value_is_empty' => 'Wartość nie powinna być pusta', + 'string_key_exists' => 'Klucz już istnieje', + ], + 'permission' => [ + 'menu_label' => 'Uprawnienia', + 'tab' => 'Uprawnienia', + 'form_tab_permissions' => 'Uprawnienia', + 'btn_add_permission' => 'Dodaj uprawnienie', + 'btn_delete_permission' => 'Usuń uprawnienie', + 'column_permission_label' => 'Kod uprawnienia', + 'column_permission_required' => 'Podaj kod uprawnienia', + 'column_tab_label' => 'Tytuł karty', + 'column_tab_required' => 'Podaj nazwę karty uprawnienia', + 'column_label_label' => 'Etykieta', + 'column_label_required' => 'Podaj etykietę uprawnienia', + 'saved' => 'Zapisano uprawnienie', + 'error_duplicate_code' => 'Kod uprawnienia \':code\' już istnieje.', + ], + 'yaml' => [ + 'save_error' => 'Błąd podczas zapisywania pliku \':name\'. Sprawdź uprawnienia do zapisu.', + ], + 'common' => [ + 'error_file_exists' => 'Plik już istnieje: \':path\'.', + 'field_icon_description' => 'October używa ikon Font Autumn: http://octobercms.com/docs/ui/icon', + 'destination_dir_not_exists' => 'Folder docelowy nie istnieje: \':path\'.', + 'error_make_dir' => 'Błąd podczas tworzenia folderu: \':name\'.', + 'error_dir_exists' => 'Folder już istnieje: \':path\'.', + 'template_not_found' => 'Nie znaleziono pliku szablonu: \':name\'.', + 'error_generating_file' => 'Błąd podczas tworzenia pliku: \':path\'.', + 'error_loading_template' => 'Błąd podczas ładowania pliku szablonu: \':name\'.', + 'select_plugin_first' => 'Najpierw wybierz wtyczkę. Aby zobaczyć listę wtyczek kliknij ikonę > w lewym pasku bocznym.', + 'plugin_not_selected' => 'Nie wybrano wtyczki', + 'add' => 'Dodaj', + ], + 'migration' => [ + 'entity_name' => 'Migracja', + 'error_version_invalid' => 'Wersja powinna być w formacie 1.0.1', + 'field_version' => 'Wersja', + 'field_description' => 'Opis', + 'field_code' => 'Kod', + 'save_and_apply' => 'Zapisz & Zastosuj', + 'error_version_exists' => 'Wersja już istnieje.', + 'error_script_filename_invalid' => 'Nazwa pliku migracji może zawierać tylko litery z alfabetu łacińskiego, cyfry i podkreślenia. Nazwa powinna zaczynać się od litery z alfabetu łacińskiego i nie może zawierać spacji.', + 'error_cannot_change_version_number' => 'Nie można zmienić numeru wersji dla zastosowanej wersji', + 'error_file_must_define_class' => 'Kod migracji powinien definiować klasę migracji lub seedera. Pozostaw pole puste jeśli chcesz tylko zaktualizować numer wersji.', + 'error_file_must_define_namespace' => 'Kod migracji powinien definiować przestrzeń nazw. Pozostaw pole puste, jeśli chcesz tylko zaktualizować numer wersji.', + 'no_changes_to_save' => 'Brak zmian do zapisania.', + 'error_namespace_mismatch' => 'Kod migracji powinien używać przestrzeni nazw wtyczki: :namespace', + 'error_migration_file_exists' => 'Plik migracji :file już istnieje. Użyj innej nazwy klasy.', + 'error_cant_delete_applied' => 'Ta wersja została już zastosowana i nie może być usunięta. Wycofaj ją w celu usunięcia.', + ], + 'components' => [ + 'list_title' => 'Lista rekordów', + 'list_description' => 'Wyświetla listę rekordów dla wybranego modelu', + 'list_page_number' => 'Numer strony', + 'list_page_number_description' => 'Wartość jest używana aby określić, na której stronie znajduje się użytkownik.', + 'list_records_per_page' => 'Rekordy na stronę', + 'list_records_per_page_description' => 'Liczba rekordów do wyświetlenia na stronie. Zostaw puste aby wyłączyć paginację.', + 'list_records_per_page_validation' => 'Nieprawidłowy format liczby rekordów na stronę. Wartość powinna być liczbą.', + 'list_no_records' => 'Komunikat o braku rekordów', + 'list_no_records_description' => 'Komunikat, który zostanie wyświetlony w przypadku braku rekordów. Używany w domyślnym fragmencie komponentu.', + 'list_no_records_default' => 'Nie znaleziono rekordów', + 'list_sort_column' => 'Sortuj wg kolumny', + 'list_sort_column_description' => 'Kolumna modelu wg której będą sortowane rekordy', + 'list_sort_direction' => 'Kierunek', + 'list_display_column' => 'Kolumna do wyświetlenia', + 'list_display_column_description' => 'Kolumna do wyświetlenia na liście. Używana w domyślnym fragmencie komponentu.', + 'list_display_column_required' => 'Wybierz kolumnę do wyświetlenia.', + 'list_details_page' => 'Strona szczegółów', + 'list_details_page_description' => 'Strona do wyświetlania szczegółów rekordu.', + 'list_details_page_no' => '--brak strony szczegółów--', + 'list_sorting' => 'Sortowanie', + 'list_pagination' => 'Paginacja', + 'list_order_direction_asc' => 'Rosnąco', + 'list_order_direction_desc' => 'Malejąco', + 'list_model' => 'Klasa modelu', + 'list_scope' => 'Zakres', + 'list_scope_description' => 'Zakres modelu do pobierania rekordów. Opcjonalne', + 'list_scope_default' => '--wybierz zakres, opcjonalne--', + 'list_scope_value' => 'Wartość zakresu', + 'list_scope_value_description' => 'Opcjonalna wartość do przekazania do zakresu modelu.', + 'list_details_page_link' => 'Link do strony szczegółów', + 'list_details_key_column' => 'Kolumna klucza szczegółów', + 'list_details_key_column_description' => 'Kolumna modelu używana jako identyfikator rekordu w linkach na stronie szczegółów.', + 'list_details_url_parameter' => 'Nazwa parametru URL', + 'list_details_url_parameter_description' => 'Nazwa parametru adresu URL strony ze szczegółami, który służy jako identyfikator rekordu.', + 'details_title' => 'Szczegóły rekordu', + 'details_description' => 'Wyświetla szczegóły rekordu dla wybranego modelu', + 'details_model' => 'Klasa modelu', + 'details_identifier_value' => 'Identyfikator', + 'details_identifier_value_description' => 'Wartość identyfikatora, na podstawie której będzie ładowany rekord z bazy danych. Podaj wartość lub nazwę parametru adresu URL.', + 'details_identifier_value_required' => 'Identyfikator jest wymagany', + 'details_key_column' => 'Kolumna klucza', + 'details_key_column_description' => 'Kolumna używana jako identyfikator do pobierania rekordu z bazy danych.', + 'details_key_column_required' => 'Nazwa kolumny klucza jest wymagana', + 'details_display_column' => 'Kolumna do wyświetlenia', + 'details_display_column_description' => 'Kolumna modelu do wyświetlenia na stronie szczegółów. Używana w domyślnym fragmencie komponentu.', + 'details_display_column_required' => 'Wybierz kolumnę do wyświetlenia.', + 'details_not_found_message' => 'Komunikat o braku rekordu', + 'details_not_found_message_description' => 'Komunikat, który zostanie wyświetlony w przypadku nieznalezienia rekordu. Używany w domyślnym fragmencie komponentu.', + 'details_not_found_message_default' => 'Nie znaleziono rekordu', + ], + 'validation' => [ + 'reserved' => ':attribute nie może być zarezerwowanym słowem kluczowym PHP', + ], +]; diff --git a/plugins/rainlab/builder/lang/pt-br.json b/plugins/rainlab/builder/lang/pt-br.json new file mode 100644 index 0000000..cd304ef --- /dev/null +++ b/plugins/rainlab/builder/lang/pt-br.json @@ -0,0 +1,4 @@ +{ + "Builder": "Builder", + "Provides visual tools for building October plugins.": "Provê ferramentas visuais para construir plugins para October CMS." +} \ No newline at end of file diff --git a/plugins/rainlab/builder/lang/pt-br/lang.php b/plugins/rainlab/builder/lang/pt-br/lang.php new file mode 100644 index 0000000..4e248b8 --- /dev/null +++ b/plugins/rainlab/builder/lang/pt-br/lang.php @@ -0,0 +1,669 @@ + [ + 'add' => 'Criar plugin', + 'no_records' => 'Nenhum plugins encontrado', + 'no_name' => 'Sem nome', + 'search' => 'Buscar...', + 'filter_description' => 'Exibe todos os plugins ou apenas os seus plugins.', + 'settings' => 'Configurações', + 'entity_name' => 'Plugin', + 'field_name' => 'Nome', + 'field_author' => 'Autor', + 'field_description' => 'Descrição', + 'field_icon' => 'Ícone do Plugin', + 'field_plugin_namespace' => 'Namespace Plugin', + 'field_author_namespace' => 'Namespace Autor', + 'field_namespace_description' => 'Namespace pode conter apenas letras latinas, numeros e deve começar com uma letra latina. Exemplo de namespace plugin: Blog', + 'field_author_namespace_description' => 'Você não pode alterar o namespace com Builder depois que você criar o plugin. Exemplo de namespace autor: JohnSmith', + 'tab_general' => 'Parâmetros gerais', + 'tab_description' => 'Descrição', + 'field_homepage' => 'URL da homepage do Plugin', + 'no_description' => 'Nenhuma descrição informada para este plugin', + 'error_settings_not_editable' => 'Configurações deste plugin não podem ser editadas com Builder.', + 'update_hint' => 'Você pode editar nome e descrição dos plugins localizados na aba localização.', + 'manage_plugins' => 'Criar e editar plugins', + ], + 'author_name' => [ + 'title' => 'Nome do autor', + 'description' => 'Nome padrão de autor para usar para seus novos plugins. O nome do autor não é fixo - você pode alterá-lo nas configurações do plugin a qualquer hora.', + ], + 'author_namespace' => [ + 'title' => 'Namespace Autor', + 'description' => 'Se você desenvolve para a Marketplace, o namespace deve combinar com o código de autor e não pode ser mudado. Veja a documentação para mais detalhes.', + ], + 'database' => [ + 'menu_label' => 'Banco de Dados', + 'no_records' => 'Nenhuma tabela encontrada', + 'search' => 'Buscar...', + 'confirmation_delete_multiple' => 'Deletar as tabelas selecionadas?', + 'field_name' => 'Nome da tabela', + 'tab_columns' => 'Colunas', + 'column_name_name' => 'Coluna', + 'column_name_required' => 'Por favor, informe um nome da tabela', + 'column_name_type' => 'Tipo', + 'column_type_required' => 'Por favor, selecione o tipo da coluna', + 'column_name_length' => 'Tamanho', + 'column_validation_length' => 'O valor do tamanho deve ser integer ou especificado como precisão e escala (10,2) para colunas decimais. Espaços não são permitidos na coluna tamanho.', + 'column_validation_title' => 'Apenas números, letras latinas minúsculas e underlines são permitidos nos nomes das colunas', + 'column_name_unsigned' => 'Somente positivos', + 'column_name_nullable' => 'Nulo', + 'column_auto_increment' => 'AUTOINCR', + 'column_default' => 'Padrão', + 'column_auto_primary_key' => 'Primary Key', + 'tab_new_table' => 'Nova Tabela', + 'btn_add_column' => 'Acrescentar coluna', + 'btn_delete_column' => 'Deletar coluna', + 'btn_add_timestamps' => 'Acrescentar timestamps', + 'btn_add_soft_deleting' => 'Acrescentar suporte a soft deleting', + 'timestamps_exist' => 'Colunas created_at e deleted_at já existem na tabela.', + 'soft_deleting_exist' => 'Coluna deleted_at já existe na tabela.', + 'confirm_delete' => 'Deletar a tabela?', + 'error_enum_not_supported' => 'A tabela contém coluna(s) com tipo "enum" que não é atualmente suportado pelo Builder.', + 'error_table_name_invalid_prefix' => 'Nome da tabela deve começar com o prefixo do plugin: \':prefix\'.', + 'error_table_name_invalid_characters' => 'Nome de tabela inválido. Nomes de tabelas devem conter apenas letras latinas, números e underlines. Nomes devem começar com uma letra latina e não podem conter espaços.', + 'error_table_duplicate_column' => 'Nome de coluna duplicado: \':column\'.', + 'error_table_auto_increment_in_compound_pk' => 'Uma coluna auto-increment não pode ser parte de uma chave primária composta.', + 'error_table_mutliple_auto_increment' => 'A tabela não pode conter multiplas colunas auto-increment.', + 'error_table_auto_increment_non_integer' => 'Colunas auto-increment devem ser do tipo integer.', + 'error_table_decimal_length' => 'O parâmetro de tamanho para o tipo :type deve ser no formato \'10,2\', sem espaços.', + 'error_table_length' => 'O parâmetro de tamanho para o tipo :type deve ser especificado como integer.', + 'error_unsigned_type_not_int' => 'Erro na coluna \':column\'. A opção Somente Positivos só pode ser aplicada a colunas do tipo integer.', + 'error_integer_default_value' => 'Valor padrão inválido para a coluna integer \':column\'. Os formatos permitidos são \'10\', \'-10\'.', + 'error_decimal_default_value' => 'Valor padrão inválido para a coluna decimal ou double \':column\'. Os formatos permitodos são \'1.00\', \'-1.00\'.', + 'error_boolean_default_value' => 'Valor padrão inválido para a coluna booleana \':column\'. Os valores permitidos são \'0\' e \'1\'.', + 'error_unsigned_negative_value' => 'O valor padrão para a coluna somente positivos \':column\' não pode ser negativo.', + 'error_table_already_exists' => 'A tabela \':name\' já existe no banco de dados.', + 'error_table_name_too_long' => 'O nome da tabela não deve ser maior que 64 caracteres.', + 'error_column_name_too_long' => 'O nome da coluna \':column\' é muito longo. Nomes de colunas não podem ser maiores que 64 caracteres.', + ], + 'model' => [ + 'menu_label' => 'Models', + 'entity_name' => 'Model', + 'no_records' => 'Nenhum model encontrado', + 'search' => 'Buscar...', + 'add' => 'Acrescentar...', + 'forms' => 'Formulários', + 'lists' => 'Listas', + 'field_class_name' => 'Nome da classe', + 'field_database_table' => 'Nome do Banco de dados', + 'field_add_timestamps' => 'Acrescentar suporte a timestamp', + 'field_add_timestamps_description' => 'A tabela do banco de dados precisa conter as colunas created_at e updated_at.', + 'field_add_soft_deleting' => 'Acrescentar suporte a soft deleting', + 'field_add_soft_deleting_description' => 'A tabela do banco de dados precisa conter a coluna deleted_at.', + 'error_class_name_exists' => 'Arquivo Model já existe para o nome da classe especificada: :path', + 'error_timestamp_columns_must_exist' => 'A tabela do banco de dados precisa conter as colunas created_at e updated_at.', + 'error_deleted_at_column_must_exist' => 'A tabela do banco de dados precisa conter a coluna deleted_at.', + 'add_form' => 'Acrescentar formulário', + 'add_list' => 'Acrescentar lista', + ], + 'form' => [ + 'saved' => 'Formulário Salvo', + 'confirm_delete' => 'Deletar o formulário?', + 'tab_new_form' => 'Novo formulário', + 'property_label_title' => 'Título', + 'property_label_required' => 'Por favor, especifique o título do control.', + 'property_span_title' => 'Span', + 'property_comment_title' => 'Comentário', + 'property_comment_above_title' => 'Comentário a cima', + 'property_default_title' => 'Padrão', + 'property_checked_default_title' => 'Marcado por padrão', + 'property_css_class_title' => 'Classe CSS', + 'property_css_class_description' => 'Classe CSS opcional para assinar o campo container.', + 'property_disabled_title' => 'Desabilitado', + 'property_hidden_title' => 'Oculto', + 'property_required_title' => 'Obrigatório', + 'property_field_name_title' => 'Nome do campo', + 'property_placeholder_title' => 'Placeholder', + 'property_default_from_title' => 'Padrão de', + 'property_stretch_title' => 'Estender', + 'property_stretch_description' => 'Especifica se este campo se estende para se ajustar à altura dos pais.', + 'property_context_title' => 'Contexto', + 'property_context_description' => 'Especifica que conceito de formulário deve ser usado quando exibir o campo.', + 'property_context_create' => 'Criar', + 'property_context_update' => 'Atualizar', + 'property_context_preview' => 'Preview', + 'property_dependson_title' => 'Depende de', + 'property_trigger_action' => 'Ação', + 'property_trigger_show' => 'Exibir', + 'property_trigger_hide' => 'Ocultar', + 'property_trigger_enable' => 'Habilitar', + 'property_trigger_disable' => 'Desabilitar', + 'property_trigger_empty' => 'Vazio', + 'property_trigger_field' => 'Campo', + 'property_trigger_field_description' => 'Define o outro nome de campo que dispara a ação.', + 'property_trigger_condition' => 'Condição', + 'property_trigger_condition_description' => 'Determina a condição que especifica o campo deve satisfazer a condição a ser considerada "true". Valores suportados: marcado, não marcado, valor[algumvalor].', + 'property_trigger_condition_checked' => 'Marcado', + 'property_trigger_condition_unchecked' => 'Não marcado', + 'property_trigger_condition_somevalue' => 'valor[digite-o-valor-aqui]', + 'property_preset_title' => 'Pré-configurado', + 'property_preset_description' => 'Permite o valor do campo a ser inicalmente configurado pelo valor de outro campo, convertido usando a entrada de conversor pré-configurada.', + 'property_preset_field' => 'Campo', + 'property_preset_field_description' => 'Define o nome do campo pelo valor de fonte de outro campo.', + 'property_preset_type' => 'Tipo', + 'property_preset_type_description' => 'Especifica o tipo de conversão', + 'property_attributes_title' => 'Atributos', + 'property_attributes_description' => 'Atributos HTML customizados para acrescentar ao elemento do campo do formulário.', + 'property_container_attributes_title' => 'Atributos do container', + 'property_container_attributes_description' => 'Atributos HTML customizados para adicionar ao elemento container do campo do formulário.', + 'property_group_advanced' => 'Avançado', + 'property_dependson_description' => 'Uma lista de outros nomes de campos dos quais este campo depende, quando os outros campos são modificados, este campo será atualizado. Um campo por linha.', + 'property_trigger_title' => 'Gatilho (Trigger)', + 'property_trigger_description' => 'Permite mudar os atributos do elemento assim como visibilidade ou valor, baseado no estado de outros elementos.', + 'property_default_from_description' => 'Pega o valor padrão do valor de outro campo.', + 'property_field_name_required' => 'O nome do campo é obrigatório', + 'property_field_name_regex' => 'O nome do campo apenas pode conter letras latinas, números, underlines, traços e colchetes.', + 'property_attributes_size' => 'Tamanho', + 'property_attributes_size_tiny' => 'Minúsculo', + 'property_attributes_size_small' => 'Pequeno', + 'property_attributes_size_large' => 'Largo', + 'property_attributes_size_huge' => 'Grande', + 'property_attributes_size_giant' => 'Gigante', + 'property_comment_position' => 'Posição do Comentário', + 'property_comment_position_above' => 'A cima', + 'property_comment_position_below' => 'A baixo', + 'property_hint_path' => 'Caminho sugerido do partial', + 'property_hint_path_description' => 'Caminho para um arquivo partial que contenha o texto sugerido. Use o simbolo $ para referenciar à raiz do diretório, por exemplo: $/acme/blog/partials/_sugestao.htm', + 'property_hint_path_required' => 'Por favor, digite a sugestão de caminho para o partial', + 'property_partial_path' => 'Caminho para o partial', + 'property_partial_path_description' => 'Caminho para um arquivo partial. Use o simbolo $ para referenciar ao diretório raiz dos plugins, por exemplo: $/acme/blog/partials/_partial.htm', + 'property_partial_path_required' => 'Por favor, digite o caminho do partial', + 'property_code_language' => 'Linguagem', + 'property_code_theme' => 'Tema', + 'property_theme_use_default' => 'Use o tema padrão', + 'property_group_code_editor' => 'Editor de código', + 'property_gutter' => 'Gutter', + 'property_gutter_show' => 'Visível', + 'property_gutter_hide' => 'Oculto', + 'property_wordwrap' => 'Abreviar palavra', + 'property_wordwrap_wrap' => 'Abreviar', + 'property_wordwrap_nowrap' => 'Não abreviar', + 'property_fontsize' => 'Tamanho da fonte', + 'property_codefolding' => 'Duplicar código', + 'property_codefolding_manual' => 'Manual', + 'property_codefolding_markbegin' => 'Marcar início', + 'property_codefolding_markbeginend' => 'Marcar início e fim', + 'property_autoclosing' => 'Auto encerrar', + 'property_enabled' => 'Habilitado', + 'property_disabled' => 'Desabilitado', + 'property_soft_tabs' => 'Tabelas suaves', + 'property_tab_size' => 'Tamanho da tabela', + 'property_readonly' => 'Somente leitura', + 'property_use_default' => 'Usar configurações padrão', + 'property_options' => 'Opções', + 'property_prompt' => 'Pronto', + 'property_prompt_description' => 'Texto a exibir para o botão criar.', + 'property_prompt_default' => 'Acrescentar novo item', + 'property_available_colors' => 'Cores disponíveis', + 'property_available_colors_description' => 'Lista de cores disponíveis no frmato hexadecimal (#FF0000). Deixe em branco para a configuração padrão de cores. Digite um valor por linha.', + 'property_datepicker_mode' => 'Modo', + 'property_datepicker_mode_date' => 'Data', + 'property_datepicker_mode_datetime' => 'Data e hora', + 'property_datepicker_mode_time' => 'Hora', + 'property_datepicker_min_date' => 'Data mínima', + 'property_datepicker_max_date' => 'Data máxima', + 'property_datepicker_year_range' => 'Alcançe de Anos', + 'property_datepicker_year_range_description' => 'Número de anos que cada lado (ex. 10) ou array de alcançe superior/inferior (ex. [1900,2015]). Deixe em branco para o valor padrão (10).', + 'property_datepicker_year_range_invalid_format' => 'Formato de alcançe de anos inválido. Use Números (ex. "10") ou array de alcançe superior/inferior (ex. "[1900,2015]")', + 'property_fileupload_mode' => 'Modo', + 'property_fileupload_mode_file' => 'Arquivo', + 'property_fileupload_mode_image' => 'Imagem', + 'property_group_fileupload' => 'Upload de arquivo', + 'property_fileupload_image_width' => 'Largura da imagem', + 'property_fileupload_image_width_description' => 'Parâmetro opcional - imagens serão redimensionadas para esta largura. Aplica-se apenas ao modo Imagem.', + 'property_fileupload_invalid_dimension' => 'Valor de dimensão inválido - por favor, digite um número.', + 'property_fileupload_image_height' => 'Altura da imagem', + 'property_fileupload_image_height_description' => 'Parâmetro opcional - imagens serão redimensionadas para esta altura. Aplica-se apenas ao modo Imagem.', + 'property_fileupload_file_types' => 'Tipos de arquivos', + 'property_fileupload_file_types_description' => 'Lista opcional separada por vírgula das extensões de arquivos que são aceitas pelo uploaded. Ex: zip, txt', + 'property_fileupload_mime_types' => 'Tipos MIME', + 'property_fileupload_mime_types_description' => 'Lista opcional separada por vírgula dos tipos MIME que são aceitas pelo uploader, assim como extensões ou nomes totalmente qualificados. Ex: bin, txt', + 'property_fileupload_use_caption' => 'Usar legenda', + 'property_fileupload_use_caption_description' => 'Permite um título e descrição a serem configurados para o arquivo.', + 'property_fileupload_thumb_options' => 'Opções de miniatua', + 'property_fileupload_thumb_options_description' => 'Gerencia opções para as miniaturas geradas automaticamente. Aplica-se apenas ao modo imagem.', + 'property_fileupload_thumb_mode' => 'Modo', + 'property_fileupload_thumb_auto' => 'Automático', + 'property_fileupload_thumb_exact' => 'Exato', + 'property_fileupload_thumb_portrait' => 'Retrato', + 'property_fileupload_thumb_landscape' => 'Paisagem', + 'property_fileupload_thumb_crop' => 'Cropar', + 'property_fileupload_thumb_extension' => 'Extensão de arquivo', + 'property_name_from' => 'Nome da coluna', + 'property_name_from_description' => 'Relação de nome de coluna a usar para exibir um nome.', + 'property_relation_select' => 'Selecionar', + 'property_relation_select_description' => 'CONCATENA multiplas colunas para exibir um nome', + 'property_description_from' => 'Coluna Descrição', + 'property_description_from_description' => 'Relação de nome de coluna a usar para exibir uma descrição.', + 'property_recordfinder_prompt' => 'Pronto', + 'property_recordfinder_prompt_description' => 'Texto para exibir quando não há gravação selecionada. O caractere %s representa o ícone buscar. Deixe em branco para o padrão pronto.', + 'property_recordfinder_list' => 'Configuração de lista', + 'property_recordfinder_list_description' => 'Uma referencia a um arquivo de definições de listas de colunas. Use o simbolo $ para referenciar a raiz de diretório do plugin, por exemplo: $/acme/blog/lists/_lista.yaml', + 'property_recordfinder_list_required' => 'Por favor, forneça um caminho para a lista de arquivos YAML', + 'property_group_recordfinder' => 'Gravar buscador', + 'property_mediafinder_mode' => 'Modo', + 'property_mediafinder_mode_file' => 'Arquivo', + 'property_mediafinder_mode_image' => 'Imagem', + 'property_mediafinder_image_width_description' => 'Se estiver usando o tipo imagem, o preview de imagem será exibido nesta largura, opcional.', + 'property_mediafinder_image_height_description' => 'Se estiver usando o modo imagem, o preview de imagem será exibido nesta altura, opcional.', + 'property_group_relation' => 'Relação', + 'property_relation_prompt' => 'Pronto', + 'property_relation_prompt_description' => 'Texto a exibir quando não há seleções disponíveis.', + 'property_empty_option' => 'Opção Vazia', + 'property_empty_option_description' => 'A opção Vazia corresponde a seleção vazia, mas ao contrário do marcador, ele pode ser selecionado novamente.', + 'property_max_items' => 'Máximo de itens', + 'property_max_items_description' => 'Número máximo de itens a permitir com o repetidor.', + 'control_group_standard' => 'Comum', + 'control_group_widgets' => 'Widgets', + 'click_to_add_control' => 'Acrescentar control', + 'loading' => 'Carregando...', + 'control_text' => 'Texto', + 'control_text_description' => 'Caixa de texto único', + 'control_password' => 'Senha', + 'control_password_description' => 'Campo de texto para senha de linha única', + 'control_checkbox' => 'Checkbox', + 'control_checkbox_description' => 'Único checkbox', + 'control_switch' => 'Switch', + 'control_switch_description' => 'Switchbox único, uma alternativa ao checkbox', + 'control_textarea' => 'Text area', + 'control_textarea_description' => 'Multiplas caixas de texto com altura controlável', + 'control_dropdown' => 'Dropdown', + 'control_dropdown_description' => 'Lista dropdown com opções estáticas ou dinâmicas', + 'control_balloon-selector' => 'Balloon Selector', + 'control_balloon-selector_description' => 'Lista onde somente um item pode ser selecionado por vez, com opções estáticas ou dinâmicas', + 'control_unknown' => 'Tipo de control desconhecido: :type', + 'control_repeater' => 'Repetidor', + 'control_repeater_description' => 'Exibe um conjunto de repetições de form controls', + 'control_number' => 'Número', + 'control_number_description' => 'Text box de linha única que aceita apenas números', + 'control_hint' => 'Aviso', + 'control_hint_description' => 'Exibe o conteúdo de uma partial em uma caixa que pode ser ocultada pelo usuário', + 'control_partial' => 'Partial', + 'control_partial_description' => 'Exibe o conteúdo de um partial', + 'control_section' => 'Seção', + 'control_section_description' => 'Exibe uma seção de formulário com cabeçalho e sub-cabeçalho', + 'control_radio' => 'Lista Radio', + 'control_radio_description' => 'Uma lista de opções radio, onde apenas um item pode ser selecionado por vez', + 'control_radio_option_1' => 'Opção 1', + 'control_radio_option_2' => 'Opção 2', + 'control_checkboxlist' => 'Lista Checkbox', + 'control_checkboxlist_description' => 'Uma lista de checkboxes, onde múltiplos itens podem ser selecionados', + 'control_codeeditor' => 'Editor de códigos', + 'control_codeeditor_description' => 'Editor modo texto para código formatado ou de marcação', + 'control_colorpicker' => 'Seletor de cor', + 'control_colorpicker_description' => 'Um campo para selecionar um valor haxadecimal de cor', + 'control_datepicker' => 'Seletor Data', + 'control_datepicker_description' => 'Campo texto usado para selecionar data e hora', + 'control_richeditor' => 'Editor Rico', + 'control_richeditor_description' => 'Editor visual para formatação rica de texto, também conhecido como um editor WYSIWYG', + 'control_markdown' => 'Editor Markdown', + 'control_markdown_description' => 'Editor básico para formatação de texto Markdown', + 'control_fileupload' => 'Upload de arquivo', + 'control_fileupload_description' => 'Uploader de arquivos para imagens ou arquivos comuns', + 'control_recordfinder' => 'Buscador de registro', + 'control_recordfinder_description' => 'Campo com detalhes de um registro relacionado com o recurso de pesquisa de registro', + 'control_mediafinder' => 'Buscador de mídia', + 'control_mediafinder_description' => 'Campo para selecionar um item de uma biblioteca do gerenciador de mídia', + 'control_relation' => 'Relação', + 'control_relation_description' => 'Exibe tanto um dropdown ou uma lista checkbox para selecionar um registro relacionado', + 'error_file_name_required' => 'Por favor, digite o nome de arquivo do formulário.', + 'error_file_name_invalid' => 'O nome de arquivo pode conter apenas letras latinas, números, underlines, pontos e barras.', + 'span_left' => 'Esquerda', + 'span_right' => 'Direita', + 'span_full' => 'Completo', + 'span_auto' => 'Automático', + 'empty_tab' => 'Aba vazia', + 'confirm_close_tab' => 'A aba contém controles que serão deletados. Continuar?', + 'tab' => 'Aba formulário', + 'tab_title' => 'Título', + 'controls' => 'Controles', + 'property_tab_title_required' => 'A aba título é obrigatória.', + 'tabs_primary' => 'Abas primárias', + 'tabs_secondary' => 'Abas secundárias', + 'tab_stretch' => 'Extender', + 'tab_stretch_description' => 'Especifica se este contêiner de guias se estende para se ajustar à altura pai.', + 'tab_css_class' => 'Classe CSS', + 'tab_css_class_description' => 'Assinala uma classe CSS ao contêiner de abas.', + 'tab_name_template' => 'Aba %s', + 'tab_already_exists' => 'Aba com o título especificado já existe.', + ], + 'list' => [ + 'tab_new_list' => 'Nova lista', + 'saved' => 'Lista salva', + 'confirm_delete' => 'Deletar a lista?', + 'tab_columns' => 'Colunas', + 'btn_add_column' => 'Acrescentar coluna', + 'btn_delete_column' => 'Deletar coluna', + 'column_dbfield_label' => 'Campo', + 'column_dbfield_required' => 'Por favor, digite um campo model', + 'column_name_label' => 'Rótulo', + 'column_label_required' => 'Por favor, informe o rótulo da coluna', + 'column_type_label' => 'Tipo', + 'column_type_required' => 'Por favor, informe o tipo da coluna', + 'column_type_text' => 'Texto', + 'column_type_number' => 'Número', + 'column_type_switch' => 'Switch', + 'column_type_datetime' => 'Data e Hora', + 'column_type_date' => 'Data', + 'column_type_time' => 'Hora', + 'column_type_timesince' => 'Tempo Passado', + 'column_type_timetense' => 'Tempo por Extenso', + 'column_type_select' => 'Seleção', + 'column_type_partial' => 'Partial', + 'column_label_default' => 'Padrão', + 'column_label_searchable' => 'Buscar', + 'column_label_sortable' => 'Classificável', + 'column_label_invisible' => 'Invisível', + 'column_label_select' => 'Seleção', + 'column_label_relation' => 'Relação', + 'column_label_css_class' => 'Classe CSS', + 'column_label_width' => 'Largura', + 'column_label_path' => 'Caminho', + 'column_label_format' => 'Formato', + 'column_label_value_from' => 'Valor de', + 'error_duplicate_column' => 'Campo nome de coluna duplicado: \':column\'.', + 'btn_add_database_columns' => 'Acrescentar colunas ao banco de dados', + 'all_database_columns_exist' => 'Todas as colunas do banco de dados já estão definidas na lista', + ], + 'controller' => [ + 'menu_label' => 'Controllers', + 'no_records' => 'Nenhum controller de plugin encontrado', + 'controller' => 'Controller', + 'behaviors' => 'Comportamentos', + 'new_controller' => 'Novo controller', + 'error_controller_has_no_behaviors' => 'O controller não possui nenhum comportamento configurável.', + 'error_invalid_yaml_configuration' => 'Erro ao carregar arquivo de configuração de comportamento: :file', + 'behavior_form_controller' => 'Comportamento de controller de formulários', + 'behavior_form_controller_description' => 'Acrescentar funcionalidade de formulários a uma página back-end. O comportamento provê três páginas chamadas Create, Update e Preview.', + 'property_behavior_form_placeholder' => '--selecionar formulário--', + 'property_behavior_form_name' => 'Nome', + 'property_behavior_form_name_description' => 'O nome do objeto gerenciado por este formulário', + 'property_behavior_form_name_required' => 'Por favor, digite o nome do formulário', + 'property_behavior_form_file' => 'Configuração de formulário', + 'property_behavior_form_file_description' => 'Refere-se a um arquivo de definição de campos de formulário', + 'property_behavior_form_file_required' => 'Por favor, digite um caminho para o arquivo de configuração do formulário', + 'property_behavior_form_model_class' => 'Classe Model', + 'property_behavior_form_model_class_description' => 'Um nome de classe model, os dados do formulário são carregados e salvos neste model.', + 'property_behavior_form_model_class_required' => 'Por favor, selecione uma classe de model', + 'property_behavior_form_default_redirect' => 'Redirecionamento padrão', + 'property_behavior_form_default_redirect_description' => 'Uma página para redirecionar por padrão quando o formulário for salvo ou cancelado.', + 'property_behavior_form_create' => 'Criar registrar página', + 'property_behavior_form_redirect' => 'Redirecionar', + 'property_behavior_form_redirect_description' => 'Uma página para redirecionar quando um registro é criado.', + 'property_behavior_form_redirect_close' => 'Encerrar redirecionamento', + 'property_behavior_form_redirect_close_description' => 'Uma página para redirecionar quando um registro é criado e a variável encerrar é enviada com o requerimento.', + 'property_behavior_form_flash_save' => 'Salvar menságem rápida', + 'property_behavior_form_flash_save_description' => 'Menságem rápida para exibir quando o registro é salvo.', + 'property_behavior_form_page_title' => 'Título da página', + 'property_behavior_form_update' => 'Atualizar registro da página', + 'property_behavior_form_update_redirect' => 'Redirecionar', + 'property_behavior_form_create_redirect_description' => 'Uma página para redirecionar quando um registro é salvo.', + 'property_behavior_form_flash_delete' => 'Deletar mensagem rápida', + 'property_behavior_form_flash_delete_description' => 'Mensagem rápida para exibir quando o registro é deletado.', + 'property_behavior_form_preview' => 'Preview registro da página', + 'behavior_list_controller' => 'Controller de Lista Comportamento', + 'behavior_list_controller_description' => 'Provê a lista classificável e buscável com links opcionais em seus registros. O comportamento cria automaticamente a ação controller "index".', + 'property_behavior_list_title' => 'Título da lista', + 'property_behavior_list_title_required' => 'Por favor, digite o título da lista', + 'property_behavior_list_placeholder' => '--Selecione a lista--', + 'property_behavior_list_model_class' => 'Classe Model', + 'property_behavior_list_model_class_description' => 'Um nome de classe model, os dados da lista são carregados deste model.', + 'property_behavior_form_model_class_placeholder' => '--selecione o model--', + 'property_behavior_list_model_class_required' => 'Por favor, selecione uma classe model', + 'property_behavior_list_model_placeholder' => '--selecione o model--', + 'property_behavior_list_file' => 'Arquivo de configuração de lista', + 'property_behavior_list_file_description' => 'Refere-se a um arquivo de definição de lista', + 'property_behavior_list_file_required' => 'Por favor, digite um caminho para o arquivo de configuração de lista', + 'property_behavior_list_record_url' => 'Gravar URL', + 'property_behavior_list_record_url_description' => 'Link cada lista de registro para outra página. Ex: users/update:id. A :id parte é substituída com o identificador de registro.', + 'property_behavior_list_no_records_message' => 'Nenhum registro de mensagem', + 'property_behavior_list_no_records_message_description' => 'Uma mensagem a exibir quando nenhum registro for encontrado', + 'property_behavior_list_recs_per_page' => 'Registros por página', + 'property_behavior_list_recs_per_page_description' => 'Registros a exibir por página, use 0 para nenhuma página. O padrão é: 0', + 'property_behavior_list_recs_per_page_regex' => 'Registros por página devem ser um valor integer', + 'property_behavior_list_show_setup' => 'Exibe botão configurações', + 'property_behavior_list_show_sorting' => 'Exibir classificação', + 'property_behavior_list_default_sort' => 'Classificação padrão', + 'property_behavior_form_ds_column' => 'Coluna', + 'property_behavior_form_ds_direction' => 'Direção', + 'property_behavior_form_ds_asc' => 'Ascendente', + 'property_behavior_form_ds_desc' => 'Descendente', + 'property_behavior_list_show_checkboxes' => 'Exibir checkboxes', + 'property_behavior_list_onclick' => 'Manusear On click', + 'property_behavior_list_onclick_description' => 'Customiza código JavaScript para executar quando clicar em um registro.', + 'property_behavior_list_show_tree' => 'Exibir árvore', + 'property_behavior_list_show_tree_description' => 'Exibe uma árvore de hierarquia para registros pai/filho.', + 'property_behavior_list_tree_expanded' => 'Expandir árvore', + 'property_behavior_list_tree_expanded_description' => 'Determina se os nós da árvore devem ser expandidos por padrão.', + 'property_behavior_list_toolbar' => 'Barra de ferramentas', + 'property_behavior_list_toolbar_buttons' => 'Partial Botões', + 'property_behavior_list_toolbar_buttons_description' => 'Refere-se a um arquivo controller partial com os botões da barra de ferramentas. Ex: lista_BarradeFerramentas', + 'property_behavior_list_search' => 'Buscar', + 'property_behavior_list_search_prompt' => 'Buscar pronto', + 'property_behavior_list_filter' => 'Configurar filtros', + 'behavior_reorder_controller' => 'Reordenar comportamento do controller', + 'behavior_reorder_controller_description' => 'Fornece recursos para classificar e reordenar seus registros. O comportamento cria automaticamente a ação "reorder" do controller.', + 'property_behavior_reorder_title' => 'Título do reordenador', + 'property_behavior_reorder_title_required' => 'Por favor, digite o título do reordenador', + 'property_behavior_reorder_name_from' => 'Nome do atributo', + 'property_behavior_reorder_name_from_description' => 'Atributo do model que pode ser usado como um rótulo para cada registro.', + 'property_behavior_reorder_name_from_required' => 'Por favor, digite o nome do atributo', + 'property_behavior_reorder_model_class' => 'Classe Model', + 'property_behavior_reorder_model_class_description' => 'Um nome de classe model, o dado registrado é carregado deste model.', + 'property_behavior_reorder_model_class_placeholder' => '--selecionar model--', + 'property_behavior_reorder_model_class_required' => 'Por favor, selecione uma classe model', + 'property_behavior_reorder_model_placeholder' => '--selecione o model--', + 'property_behavior_reorder_toolbar' => 'Bara de ferramentas', + 'property_behavior_reorder_toolbar_buttons' => 'Botões da Partial', + 'property_behavior_reorder_toolbar_buttons_description' => 'Refere-se ao arquivo partial controller com os botões da barra de ferramentas. Ex: reordenar_BarradeFerramentas', + 'error_controller_not_found' => 'Arquivo original do controller não foi encontrado.', + 'error_invalid_config_file_name' => 'O nome do arquivo (:file) de configuração do comportamento :class contém caracteres inválidos e não pode ser carregado.', + 'error_file_not_yaml' => 'O nome do arquivo (:file) de configuração do comportamento :class não é um arquivo YAML. Somente arquivos de configuração YAML são suportados.', + 'saved' => 'Controller salvo', + 'controller_name' => 'Nome do Controller', + 'controller_name_description' => 'O nome do controller define o nome da classe e URL das páginas back-end do controller. Convenções de nomenclatura de variáveis PHP padrão se aplicam. O primeiro símbolo deve ser uma letra latina maiúscula. Exemplos: Categorias, Postagens, Produtos.', + 'base_model_class' => 'Classe model base', + 'base_model_class_description' => 'Selecione uma classe model para usar como um model base no comportamento que necessita ou suporta models. Você pode configurar o comportamento depois.', + 'base_model_class_placeholder' => '--Selecione o model--', + 'controller_behaviors' => 'Comportamentos', + 'controller_behaviors_description' => 'Selecione os comportamentos que o controller deve implementar. O Builder criará arquivos de view necessários para os comportamentos automaticamente.', + 'controller_permissions' => 'Permissões', + 'controller_permissions_description' => 'Selecione permissões de usuário que podem acessar as views dos controllers. As permissões podem ser definidas na guia Permissões do Builder. Você pode alterar essa opção no script PHP do controller mais tarde.', + 'controller_permissions_no_permissions' => 'O plugin não definiu nenhuma permissão.', + 'menu_item' => 'Item de menu ativo', + 'menu_item_description' => 'Selecione um item de menu para tornar ativo para as páginas do controller. Você pode alterar essa opção no script PHP do controlador mais tarde.', + 'menu_item_placeholder' => '--selecione o item de menu--', + 'error_unknown_behavior' => 'A classe de comportamento :class não está registrada na biblioteca de comportamento.', + 'error_behavior_view_conflict' => 'Os comportamentos selecionados fornecem visualizações conflitantes (:view) e não podem ser usadas junto a um controller.', + 'error_behavior_config_conflict' => 'Os comportamentos selecionados fornecem arquivos de configuração conflitantes (:file) e não podem ser usadas junto a um controller.', + 'error_behavior_view_file_not_found' => 'A view do template :view do comportamento :class não pode ser localizado.', + 'error_behavior_config_file_not_found' => 'O template de configuração :file do comportamento :class não pode ser localizado.', + 'error_controller_exists' => 'O arquivo do controlador :file já existe.', + 'error_controller_name_invalid' => 'Formato de nome de controller inválido. O nome deve conter apenas letras latinas e números. O primeiro simbolo deve ser uma letra latina maiúscula.', + 'error_behavior_view_file_exists' => 'O arquivo de configuração do controller :view já existe.', + 'error_behavior_config_file_exists' => 'O arquivo de configuração do comportamento :file já existe.', + 'error_save_file' => 'Erro ao salvar o arquivo de controller :file', + 'error_behavior_requires_base_model' => 'O comportamento :behavior necessita que seja selecionado uma classe model base.', + 'error_model_doesnt_have_lists' => 'O model selecionado não possui nenhuma lista. Por favor, crie primeiro uma lista.', + 'error_model_doesnt_have_forms' => 'O model selecionado não possui nenhum formulário. Por favor, crie primeiro um formulário.', + ], + 'version' => [ + 'menu_label' => 'Versões', + 'no_records' => 'Nenhuma versão de plugin encontrada', + 'search' => 'Buscar...', + 'tab' => 'Versões', + 'saved' => 'Versão salva', + 'confirm_delete' => 'Deletar a versão?', + 'tab_new_version' => 'Nova versão', + 'migration' => 'Migração', + 'seeder' => 'Semeador', + 'custom' => 'Aumente o número da versão', + 'apply_version' => 'Aplicar versão', + 'applying' => 'Aplicando...', + 'rollback_version' => 'Reverter versão', + 'rolling_back' => 'Revertendo...', + 'applied' => 'Versão aplicada', + 'rolled_back' => 'Versão revertida', + 'hint_save_unapplied' => 'Você salvou uma versão não aplicada. As versões não aplicadas podem ser aplicadas automaticamente quando você ou outro usuário faz o login no back-end ou quando uma tabela de banco de dados é salva na seção Banco de Dados do Builder.', + 'hint_rollback' => 'Reverter uma versão também reverterá todas as versões mais recentes que esta. Observe que versões não aplicadas podem ser aplicadas automaticamente pelo sistema quando você ou outro usuário faz o login no back-end ou quando uma tabela do banco de dados é salva na seção Banco de Dados do Builder.', + 'hint_apply' => 'A aplicação de uma versão também aplicará todas as versões antigas não aplicadas do plug-in.', + 'dont_show_again' => 'Não mostrar novamente', + 'save_unapplied_version' => 'Salvar versão não aplicada', + ], + 'menu' => [ + 'menu_label' => 'Menu Backend', + 'tab' => 'Menus', + 'items' => 'Itens de Menu', + 'saved' => 'Menus salvos', + 'add_main_menu_item' => 'Acrescentar item de menu principal', + 'new_menu_item' => 'Item de menu', + 'add_side_menu_item' => 'Acrescentar sub-item', + 'side_menu_item' => 'Item de menu lateral', + 'property_label' => 'Rótulo', + 'property_label_required' => 'Por favor, digite os rótulos dos itens de menu.', + 'property_url_required' => 'Por favor, digite a URL do item de menu', + 'property_url' => 'URL', + 'property_icon' => 'Ícone', + 'property_icon_required' => 'Por favor, selecione um ícone', + 'property_permissions' => 'Permissões', + 'property_order' => 'Ordenar', + 'property_order_invalid' => 'Por favor, insira a ordem do item de menu como valor integer.', + 'property_order_description' => 'A ordem do item de menu gerencia sua posição no menu. Se a ordem não for fornecida, o item será colocado no final do menu. Os valores de ordem padrão têm o incremento de 100.', + 'property_attributes' => 'Atributos HTML', + 'property_code' => 'Código', + 'property_code_invalid' => 'O código deve conter apenas letra latina e números', + 'property_code_required' => 'Por favor, insira o código do item de menu.', + 'error_duplicate_main_menu_code' => 'Código de item de menu \':code\' duplicado.', + 'error_duplicate_side_menu_code' => 'Código de item de menu lateral \':code\' duplicado.', + ], + 'localization' => [ + 'menu_label' => 'Idiomas', + 'language' => 'Idioma', + 'strings' => 'Strings', + 'confirm_delete' => 'Deletar o idioma?', + 'tab_new_language' => 'Novo idioma', + 'no_records' => 'Nenhum idioma encontrado', + 'saved' => 'Arquivo de idioma salvo', + 'error_cant_load_file' => 'Não é possível carregar o arquivo de idioma solicitado - arquivo não encontrado.', + 'error_bad_localization_file_contents' => 'Não é possível carregar o arquivo de idioma solicitado. Os arquivos de idiomas podem conter apenas definições e strings de array.', + 'error_file_not_array' => 'Não é possível carregar o arquivo de idioma solicitado. Arquivos de idioma devem retornar um array.', + 'save_error' => 'Erro ao salvar o arquivo \':name\'. Por favor, verifique as permissões de escrita.', + 'error_delete_file' => 'Erro ao deletar arquivo de idioma.', + 'add_missing_strings' => 'Acrescentar strings faltantes', + 'copy' => 'Copiar', + 'add_missing_strings_label' => 'Selecione o idioma para copiar as strings faltantes', + 'no_languages_to_copy_from' => 'Não há outro idioma para copiar strings.', + 'new_string_warning' => 'Nova string ou seção', + 'structure_mismatch' => 'A estrutura do arquivo fonte do idioma não combina com a estrutura do arquivo que está sendo editado. Algumas strings individuais do arquivo editado correspondente a seções no arquivo fonte (ou vice versa) e não pode ser mesclado automaticamente.', + 'create_string' => 'Criar nova string', + 'string_key_label' => 'Chave de String', + 'string_key_comment' => 'Insira a chave de string usando o ponto como um separador de seção. For example: plugin.buscar. A string será criada no arquivo de localização do idioma padrão do plugin.', + 'string_value' => 'Valor da string', + 'string_key_is_empty' => 'Chave de string não pode ser vazio', + 'string_key_is_a_string' => ':key é uma string e não pode conter outras strings.', + 'string_value_is_empty' => 'Valor da string não pode ser vazio', + 'string_key_exists' => 'A chave de string já existe', + ], + 'permission' => [ + 'menu_label' => 'Permissões', + 'tab' => 'Permissões', + 'form_tab_permissions' => 'Permissões', + 'btn_add_permission' => 'Acrescentar permissão', + 'btn_delete_permission' => 'Deletar permissão', + 'column_permission_label' => 'Código de permissão', + 'column_permission_required' => 'Por favor, digite o código de permissão', + 'column_tab_label' => 'Título da aba', + 'column_tab_required' => 'Por favor, digite o título da aba permissão', + 'column_label_label' => 'Rótulo', + 'column_label_required' => 'Por favor, digite o rótulo da permissão', + 'saved' => 'Permissões salvas', + 'error_duplicate_code' => 'Código de permissão \':code\' duplicado.', + ], + 'yaml' => [ + 'save_error' => 'Erro ao salvar o arquivo \':name\'. Por favor, verifique permissões de escrita.', + ], + 'common' => [ + 'error_file_exists' => 'Arquivo \':path\' já existe.', + 'field_icon_description' => 'October usa ícones Font Autumn: http://octobercms.com/docs/ui/icon', + 'destination_dir_not_exists' => 'O diretório de destino \':path\' não existe.', + 'error_make_dir' => 'Erro ao criar diretório: \':name\'.', + 'error_dir_exists' => 'Diretório \':path\' já existe.', + 'template_not_found' => 'Arquivo de template \':name\' não encontrado.', + 'error_generating_file' => 'Erro ao gerar arquivo: \':path\'.', + 'error_loading_template' => 'Erro ao carregar arquivo de template: \':name\'.', + 'select_plugin_first' => 'Por favor, selecione um plugin primeiro. Para ver a lista de plugins, clique no ícone > na barra lateral esquerda.', + 'plugin_not_selected' => 'Plugin não selecionado', + 'add' => 'Acrescentar', + ], + 'migration' => [ + 'entity_name' => 'Migration', + 'error_version_invalid' => 'A versão deve ser especificada no formato 1.0.1', + 'field_version' => 'Versão', + 'field_description' => 'Descrição', + 'field_code' => 'Código', + 'save_and_apply' => 'Salvar e aplicar', + 'error_version_exists' => 'A versão da migration já existe.', + 'error_script_filename_invalid' => 'O nome do arquivo de script do migration pode conter apenas letras latinas, números e underlines. O nome deve começar com uma letra latina e não pode conter espaços.', + 'error_cannot_change_version_number' => 'Não é possível alterar o número da versão para uma versão aplicada.', + 'error_file_must_define_class' => 'O código de migração deve definir uma migration ou classe de semeador. Deixe o campo de código em branco se você quiser apenas atualizar o número da versão.', + 'error_file_must_define_namespace' => 'O código do migration deve definir um namespace. Deixe o campo de código em branco se você quiser apenas atualizar o número da versão.', + 'no_changes_to_save' => 'Não há mudanças para salvar.', + 'error_namespace_mismatch' => 'O código do migration deve usar o namespace :namespace do plugin', + 'error_migration_file_exists' => 'O arquivo migration :file já existe. Por favor, use outro nome de classe.', + 'error_cant_delete_applied' => 'Esta versão já foi aplicada e não pode ser excluída. Por favor, reverter a versão primeiro.', + ], + 'components' => [ + 'list_title' => 'Lista de registros', + 'list_description' => 'Exibe uma lista de registros para um model selecionado', + 'list_page_number' => 'Número da página', + 'list_page_number_description' => 'Este valor é usado para determinar em qual página o usuário está.', + 'list_records_per_page' => 'Registros por página', + 'list_records_per_page_description' => 'Número de registros para exibir em uma única página. Deixe em branco para desabilitar a ação.', + 'list_records_per_page_validation' => 'Formato inválido dos registros por valor de página. O valor deve ser um número.', + 'list_no_records' => 'Nenhuma mensagem de registro', + 'list_no_records_description' => 'Mensagem a exibir na lista, em caso de não haver registros. Usado na partial padrão do componente.', + 'list_no_records_default' => 'Nenhum registro encontrado', + 'list_sort_column' => 'Classificar por coluna', + 'list_sort_column_description' => 'A coluna modela como os registros devem ser classificados', + 'list_sort_direction' => 'Direção', + 'list_display_column' => 'Exibir coluna', + 'list_display_column_description' => 'Coluna para exibir na lista. Usado no partial padrão do componente.', + 'list_display_column_required' => 'Por favor, selecione uma coluna exibida.', + 'list_details_page' => 'Página detalhes', + 'list_details_page_description' => 'Página para exibir detalhes dos registros.', + 'list_details_page_no' => '--nenhuma página de detalhes--', + 'list_sorting' => 'Classificação', + 'list_pagination' => 'Paginação', + 'list_order_direction_asc' => 'Ascendente', + 'list_order_direction_desc' => 'Descendente', + 'list_model' => 'Classe Model', + 'list_scope' => 'Escopo', + 'list_scope_description' => 'Escopo do modelo opcional para buscar os registros', + 'list_scope_default' => '--selecione um escopo, opcional--', + 'list_scope_value' => 'Valor do escopo', + 'list_scope_value_description' => 'Valor opcional para passar para o escopo do modelo', + 'list_details_page_link' => 'Link para a página de detalhes', + 'list_details_key_column' => 'Coluna chave de detalhes', + 'list_details_key_column_description' => 'Coluna Modelo para usar como um identificador de registro nos links da página de detalhes.', + 'list_details_url_parameter' => 'Nome do parâmetro de URL ', + 'list_details_url_parameter_description' => 'Nome do parâmetro de URL da página de detalhes que leva o identificador de registro.', + 'details_title' => 'Detalhes de registros', + 'details_description' => 'Exibe detalhes de registros para um modelo selecionado', + 'details_model' => 'Classe Model', + 'details_identifier_value' => 'Valor do identificador', + 'details_identifier_value_description' => 'Valor identificador para carregar os registros do banco de dados. Especifique um valor fixo ou nome de parâmetro URL.', + 'details_identifier_value_required' => 'O valor do identificador é obrigatório', + 'details_key_column' => 'Coluna chave', + 'details_key_column_description' => 'Coluna model para usar como um identificador de registro para buscar os registros do banco de dados.', + 'details_key_column_required' => 'O nome de coluna chave é obrigatório', + 'details_display_column' => 'Exibir coluna', + 'details_display_column_description' => 'Coluna model para exibir na página de detalhes. Usado no partial padrão do componente.', + 'details_display_column_required' => 'Por favor, selecione uma coluna de exibição.', + 'details_not_found_message' => 'Mensagem não encontrada', + 'details_not_found_message_description' => 'Mensagem para exibir se o registro não for encontrado. Usado no partial padrão do componente.', + 'details_not_found_message_default' => 'Registro não encontrado', + ], + 'validation' => [ + 'reserved' => ':attribute não pode ser uma palavra reservada do PHP', + ], +]; diff --git a/plugins/rainlab/builder/lang/zh-cn.json b/plugins/rainlab/builder/lang/zh-cn.json new file mode 100644 index 0000000..3420ab0 --- /dev/null +++ b/plugins/rainlab/builder/lang/zh-cn.json @@ -0,0 +1,4 @@ +{ + "Builder": "构造器", + "Provides visual tools for building October plugins.": "提供用于构建October插件的可视化工具." +} \ No newline at end of file diff --git a/plugins/rainlab/builder/lang/zh-cn/lang.php b/plugins/rainlab/builder/lang/zh-cn/lang.php new file mode 100644 index 0000000..b0cd3f0 --- /dev/null +++ b/plugins/rainlab/builder/lang/zh-cn/lang.php @@ -0,0 +1,735 @@ + [ + 'add' => '创建插件', + 'no_records' => '找不到插件', + 'no_name' => '没有名称', + 'search' => '搜索...', + 'filter_description' => '显示所有插件或只显示您的插件.', + 'settings' => '设置', + 'entity_name' => '插件', + 'field_name' => '名称', + 'field_author' => '作者', + 'field_description' => '描述', + 'field_icon' => '插件图标', + 'field_plugin_namespace' => '插件命名空间', + 'field_author_namespace' => '作者命名空间', + 'field_namespace_description' => '命名空间只能包含拉丁字母和数字,并且应该以拉丁字母开头。示例插件命名空间:Blog', + 'field_author_namespace_description' => '创建插件后,不能使用Builder更改命名空间。示例作者名称空间:JohnSmith', + 'tab_general' => '常规参数', + 'tab_description' => '描述', + 'field_homepage' => '插件主页', + 'no_description' => '常规参数没有为此插件提供说明', + 'error_settings_not_editable' => '无法使用生成器编辑此插件的设置.', + 'update_hint' => '您可以在“本地化”选项卡上编辑本地化插件的名称和说明.', + 'manage_plugins' => '创建和编辑插件', + ], + 'author_name' => [ + 'title' => '作者名称', + 'description' => '用于新插件的默认作者名称。作者名不是固定的-你可以在插件配置中随时更改它.', + ], + 'author_namespace' => [ + 'title' => '作者命名空间', + 'description' => '如果您是为市场开发的,命名空间应该与作者代码匹配,并且不能更改。有关详细信息,请参阅文档.', + ], + 'database' => [ + 'menu_label' => '数据库', + 'no_records' => '未找到数据库表', + 'search' => '搜索...', + 'confirmation_delete_multiple' => '删除选中的数据库表?', + 'field_name' => '数据库表名', + 'tab_columns' => '列', + 'column_name_name' => '列', + 'column_name_required' => '请提供列名', + 'column_name_type' => '类型', + 'column_type_required' => '请选择列类型', + 'column_name_length' => '长度', + 'column_validation_length' => '对于十进制列,长度值应为整数或指定为精度和小数位数(10,2)。长度列中不允许有空格.', + 'column_validation_title' => '列名中只允许数字、小写拉丁字母和下划线', + 'column_name_unsigned' => '符号', + 'column_name_nullable' => '可为NULL', + 'column_auto_increment' => '自增', + 'column_default' => '默认', + 'column_comment' => '注释', + 'column_auto_primary_key' => '键', + 'tab_new_table' => '新增表', + 'btn_add_column' => '新增列', + 'btn_delete_column' => '删除列', + 'btn_add_id' => '添加ID', + 'btn_add_timestamps' => '添加时间戳', + 'btn_add_soft_deleting' => '添加软删除支持', + 'id_exists' => '表中已存在ID列.', + 'timestamps_exist' => '表中已存在created_at列和deleted_at列.', + 'soft_deleting_exist' => '表中已存在deleted_at列.', + 'confirm_delete' => '删除表?', + 'error_enum_not_supported' => '表包含生成器当前不支持的类型为“enum”的列.', + 'error_table_name_invalid_prefix' => '表名应以插件前缀开头: \':prefix\'.', + 'error_table_name_invalid_characters' => '表名无效。表名只能包含拉丁字母、数字和下划线。名称应以拉丁字母开头,不能包含空格.', + 'error_table_duplicate_column' => '重复列名: \':column\'.', + 'error_table_auto_increment_in_compound_pk' => '自动递增列不能是复合主键的一部分.', + 'error_table_mutliple_auto_increment' => '表不能包含多个自动递增列.', + 'error_table_auto_increment_non_integer' => '自动递增列应具有整数类型.', + 'error_table_decimal_length' => ':type 的Length参数的格式应为“10,2”,不带空格.', + 'error_table_length' => ':type 长度参数应指定为整数.', + 'error_unsigned_type_not_int' => '\':column\' 列出错。无符号标志只能应用于整数类型列.', + 'error_integer_default_value' => '整数列 \':column\' 的默认值无效。允许的格式为“10”、“-10”.', + 'error_decimal_default_value' => '十进制或双精度列的默认值无效 \':column\'. 允许的格式为\'1.00\',\'1.00\'.', + 'error_boolean_default_value' => '布尔列的默认值无效 \':column\'. 允许的值为“0”和“1”,或“true”和“false”.', + 'error_unsigned_negative_value' => '无符号列 \':column\' 的默认值不能为负.', + 'error_table_already_exists' => '数据库中已存在表 \':name\'.', + 'error_table_name_too_long' => '表名的长度不应超过64个字符.', + 'error_column_name_too_long' => '列名 \':column\' 太长。列名的长度不应超过64个字符.', + ], + 'model' => [ + 'menu_label' => '模型', + 'entity_name' => '模型', + 'no_records' => '未找到模型', + 'search' => '搜索...', + 'add' => '添加...', + 'forms' => '表单', + 'lists' => '列表', + 'field_class_name' => '类名', + 'field_database_table' => '数据库表', + 'field_add_timestamps' => '添加时间戳支持', + 'field_add_timestamps_description' => '数据库表必须存在 created_at 和 updated_at 字段.', + 'field_add_soft_deleting' => '添加软删除支持', + 'field_add_soft_deleting_description' => '数据库表必须存在 deleted_at 字段.', + 'error_class_name_exists' => '指定类名的模型文件已存在: :path', + 'error_timestamp_columns_must_exist' => '数据库表必须存在 created_at 和 updated_at 字段.', + 'error_deleted_at_column_must_exist' => '数据库表必须存在 deleted_at 字段.', + 'add_form' => '添加表单', + 'add_list' => '添加列表', + ], + 'form' => [ + 'saved' => '表单已保存', + 'confirm_delete' => '删除表单?', + 'tab_new_form' => '新表单', + 'btn_add_database_fields' => '添加数据库字段', + 'property_label_title' => '标签', + 'property_label_required' => '请指定控制标签.', + 'property_span_title' => '跨度', + 'property_comment_title' => '注释', + 'property_comment_above_title' => '在注释上', + 'property_default_title' => '默认', + 'property_checked_default_title' => '默认选中', + 'property_css_class_title' => 'CSS 类名', + 'property_css_class_description' => '分配给字段容器的可选CSS类.', + 'property_disabled_title' => '禁止', + 'property_read_only_title' => '仅读', + 'property_hidden_title' => '隐藏', + 'property_required_title' => '必填', + 'property_field_name_title' => '字段名', + 'property_placeholder_title' => '占位符', + 'property_default_from_title' => '默认来源', + 'property_stretch_title' => '伸展', + 'property_stretch_description' => '指定此字段是否拉伸以适合父级高度.', + 'property_context_title' => '上下文', + 'property_context_description' => '指定显示字段时应使用的窗体上下文.', + 'property_context_create' => '创建', + 'property_context_update' => '更新', + 'property_context_preview' => '预览', + 'property_dependson_title' => '依赖', + 'property_trigger_action' => '行为', + 'property_trigger_show' => '显示', + 'property_trigger_hide' => '隐藏', + 'property_trigger_enable' => '开启', + 'property_trigger_disable' => '禁止', + 'property_trigger_empty' => '空', + 'property_trigger_field' => '字段', + 'property_trigger_field_description' => '定义将触发操作的其他字段名.', + 'property_trigger_condition' => '条件', + 'property_trigger_condition_description' => '确定指定字段应满足的条件,以便将条件视为“true”。支持的值:选中、未选中、值[somevalue].', + 'property_trigger_condition_checked' => '已选中', + 'property_trigger_condition_unchecked' => '未选中', + 'property_trigger_condition_somevalue' => '值[在此处输入值]', + 'property_preset_title' => '预设', + 'property_preset_description' => '允许字段值最初由另一个字段的值设置,使用输入预置转换器进行转换.', + 'property_preset_field' => '字段', + 'property_preset_field_description' => '定义要从中获取值的其他字段名.', + 'property_preset_type' => '类型', + 'property_preset_type_description' => '指定转换类型', + 'property_attributes_title' => '属性', + 'property_attributes_description' => '要添加到表单字段元素的自定义HTML属性.', + 'property_container_attributes_title' => '容器属性', + 'property_container_attributes_description' => '要添加到表单域容器元素的自定义HTML属性.', + 'property_group_advanced' => '高级', + 'property_dependson_description' => '此字段所依赖的其他字段名的列表,当其他字段被修改时,此字段将更新。每行一个字段.', + 'property_trigger_title' => '触发', + 'property_trigger_description' => '允许根据其他元素的状态更改元素属性,如可见性或值.', + 'property_default_from_description' => '从另一个字段的值中获取默认值.', + 'property_field_name_required' => '字段名是必需的', + 'property_field_name_regex' => '字段名只能包含拉丁字母、数字、下划线、短划线和方括号.', + 'property_attributes_size' => '大小', + 'property_attributes_size_tiny' => '微小的', + 'property_attributes_size_small' => '小', + 'property_attributes_size_large' => '大', + 'property_attributes_size_huge' => '巨大的', + 'property_attributes_size_giant' => '特大的', + 'property_comment_position' => '注释位置', + 'property_comment_position_above' => '在上面', + 'property_comment_position_below' => '在下面', + 'property_hint_path' => '提示部分路径', + 'property_hint_path_description' => '包含提示文本的部分文件的路径。使用$符号来引用插件根目录,例如:$/acme/blog/partials/_hint.htm', + 'property_hint_path_required' => '请输入提示部分路径', + 'property_partial_path' => '部分路径', + 'property_partial_path_description' => '部分文件的路径。使用$符号来引用插件根目录,例如:$/acme/blog/partials/_partial.htm', + 'property_partial_path_required' => '请输入部分路径', + 'property_code_language' => '语言', + 'property_code_theme' => '主题', + 'property_theme_use_default' => '使用默认主题', + 'property_group_code_editor' => '代码编辑器', + 'property_gutter' => 'Gutter', + 'property_gutter_show' => '可见', + 'property_gutter_hide' => '隐藏', + 'property_wordwrap' => '自动换行', + 'property_wordwrap_wrap' => '换行', + 'property_wordwrap_nowrap' => '不换行', + 'property_fontsize' => '字体大小', + 'property_codefolding' => '代码目录', + 'property_codefolding_manual' => '指南', + 'property_codefolding_markbegin' => '标记开始', + 'property_codefolding_markbeginend' => '标记开始和结束', + 'property_autoclosing' => '自动关闭', + 'property_enabled' => '开启', + 'property_disabled' => '禁止', + 'property_soft_tabs' => '软标签', + 'property_tab_size' => '标签大小', + 'property_readonly' => '仅读', + 'property_use_default' => '使用默认设置', + 'property_options' => '选项', + 'property_prompt' => '提示', + 'property_prompt_description' => '“创建”按钮显示的文本.', + 'property_prompt_default' => '添加新项', + 'property_available_colors' => '可用颜色', + 'property_available_colors_description' => '十六进制格式的可用颜色列表(#FF0000)。将默认颜色集保留为空。每行输入一个值.', + 'property_datepicker_mode' => '模式', + 'property_datepicker_mode_date' => '日期', + 'property_datepicker_mode_datetime' => '日期时间', + 'property_datepicker_mode_time' => '时间', + 'property_datepicker_min_date' => '最小日期', + 'property_datepicker_min_date_description' => '可以选择的最小/最早日期。默认值为空(2000-01-01).', + 'property_datepicker_max_date' => '最大日期', + 'property_datepicker_max_date_description' => '可选择的最大/最晚日期。将默认值留空(2020-12-31).', + 'property_datepicker_date_invalid_format' => '无效的日期格式。使用格式YYYY-MM-DD.', + 'property_datepicker_year_range' => '年份范围', + 'property_datepicker_year_range_description' => '两边的年数(如10)或上下范围的数组(如[19002015])。将默认值留空(10).', + 'property_datepicker_year_range_invalid_format' => '年份范围格式无效。使用数字(如“10”)或上限/下限数组(如“[19002015]”)', + 'property_datepicker_format' => '格式', + 'property_datepicker_year_format_description' => '定义自定义日期格式。默认格式为“Y-m-d”', + 'property_fileupload_mode' => '模式', + 'property_fileupload_mode_file' => '文件', + 'property_fileupload_mode_image' => '图片', + 'property_group_fileupload' => '上传文件', + 'property_fileupload_image_width' => '图片宽度', + 'property_fileupload_image_width_description' => '可选参数-图像大小将调整为此宽度。仅适用于图像模式.', + 'property_fileupload_invalid_dimension' => '维度值无效-请输入一个数字.', + 'property_fileupload_image_height' => '图片高度', + 'property_fileupload_image_height_description' => '可选参数-图像大小将调整到此高度。仅适用于图像模式.', + 'property_fileupload_file_types' => '文件类型', + 'property_fileupload_file_types_description' => '上传可接受的文件扩展名的可选逗号分隔列表。如: zip,txt', + 'property_fileupload_mime_types' => 'MIME 类型', + 'property_fileupload_maxfilesize' => '最大文件大小', + 'property_fileupload_maxfilesize_description' => '上传者接受的文件大小(以 Mb 为单位),可选。', + 'property_fileupload_invalid_maxfilesize' => '最大文件大小值无效', + 'property_fileupload_maxfiles' => '最大文件数量', + 'property_fileupload_invalid_maxfiles' => '最大文件数量值无效', + 'property_fileupload_maxfiles_description' => '允许上传的最大文件数量', + 'property_fileupload_mime_types_description' => '上传接受的可选逗号分隔的MIME类型列表,可以是文件扩展名,也可以是完全限定名. 如: bin,txt', + 'property_fileupload_use_caption' => '使用说明', + 'property_fileupload_use_caption_description' => '允许为文件设置标题和说明.', + 'property_fileupload_thumb_options' => '缩略图选项', + 'property_fileupload_thumb_options_description' => '管理自动生成的缩略图的选项。仅适用于图像模式.', + 'property_fileupload_thumb_mode' => '模式', + 'property_fileupload_thumb_auto' => '自动', + 'property_fileupload_thumb_exact' => '扩展', + 'property_fileupload_thumb_portrait' => '纵向', + 'property_fileupload_thumb_landscape' => '横向', + 'property_fileupload_thumb_crop' => '裁切', + 'property_fileupload_thumb_extension' => '文件扩展名', + 'property_name_from' => '列名', + 'property_name_from_description' => '用于显示名称的关系列名.', + 'property_relation_select' => '选择', + 'property_relation_select_description' => '将多个列合并在一起以显示名称', + 'property_relation_scope' => '范围', + 'property_relation_scope_description' => '指定在相关表单模型中定义的查询范围方法,以始终应用于列表查询', + 'property_description_from' => '列描述', + 'property_description_from_description' => '用于显示说明的关系列名称.', + 'property_recordfinder_prompt' => '提示', + 'property_recordfinder_prompt_description' => '未选择记录时要显示的文本。%s字符表示搜索图标。为默认提示保留为空.', + 'property_recordfinder_list' => '列表配置', + 'property_recordfinder_list_description' => '对列表列定义文件的引用。使用$符号来引用插件根目录,例如:$/acme/blog/lists/_list.yaml', + 'property_recordfinder_list_required' => '请提供列表YAML文件的路径', + 'property_group_recordfinder' => '查找记录', + 'property_mediafinder_mode' => '模式', + 'property_mediafinder_mode_file' => '文件', + 'property_mediafinder_mode_image' => '图片', + 'property_mediafinder_image_width_description' => '如果使用图像类型,预览图像将按此宽度显示(可选).', + 'property_mediafinder_image_height_description' => '如果使用图像类型,预览图像将显示到此高度(可选).', + 'property_group_taglist' => '标签列表', + 'property_taglist_mode' => '模式', + 'property_taglist_mode_description' => '定义此字段的值作为返回格式', + 'property_taglist_mode_string' => '字符串', + 'property_taglist_mode_array' => '数组', + 'property_taglist_mode_relation' => '关联', + 'property_taglist_separator' => '分割符', + 'property_taglist_separator_comma' => '分割符号', + 'property_taglist_separator_space' => '空格', + 'property_taglist_options' => '预定义的标记', + 'property_taglist_custom_tags' => '自定义标签', + 'property_taglist_custom_tags_description' => '允许用户手动输入自定义标记.', + 'property_taglist_name_from' => '来源名称', + 'property_taglist_name_from_description' => '定义标记中显示的关系模型属性。仅用于“关联”模式.', + 'property_taglist_use_key' => '使用密钥', + 'property_taglist_use_key_description' => '如果选中,标记列表将使用键而不是值来保存和读取数据。仅用于“关联”模式.', + 'property_group_relation' => '关联', + 'property_relation_prompt' => '提示', + 'property_relation_prompt_description' => '没有可用选择时要显示的文本.', + 'property_empty_option' => '空选项', + 'property_empty_option_description' => 'empty选项对应于空选择,但与占位符不同,它可以重新选择.', + 'property_show_search' => '显示搜索', + 'property_show_search_description' => '启用此下拉列表的搜索功能.', + 'property_title_from' => '标题来自', + 'property_title_from_description' => '指定一个子字段名称以使用该字段的值作为每个转发器项目的标题。', + 'property_min_items' => '最小项', + 'property_min_items_description' => '转发器内允许的最小项目数。', + 'property_min_items_integer' => '最小项目必须是正整数。', + 'property_max_items' => '最大项', + 'property_max_items_description' => '转发器中允许的最大项目数。', + 'property_max_items_integer' => '最大项目必须是正整数。', + 'property_display_mode' => '风格', + 'property_display_mode_description' => '定义应用到这个转发器的行为。', + 'property_switch_label_on' => 'ON标题', + 'property_switch_label_on_description' => '为“ON”开关状态设置自定义标题', + 'property_switch_label_off' => 'OFF标题', + 'property_switch_label_off_description' => '为“OFF”开关状态设置自定义标题', + 'control_group_standard' => '标准', + 'control_group_widgets' => '控件', + 'click_to_add_control' => '添加控件', + 'loading' => '加载中...', + 'control_text' => '文本', + 'control_text_description' => '单行文本框', + 'control_password' => '密码', + 'control_password_description' => '单行密码文本字段', + 'control_checkbox' => '复选框', + 'control_checkbox_description' => '单选框', + 'control_switch' => '开关', + 'control_switch_description' => '单选开关盒,复选框的替代品', + 'control_textarea' => '文本域', + 'control_textarea_description' => '高度可控的多行文本框', + 'control_dropdown' => '下拉框', + 'control_dropdown_description' => '带有静态或动态选项的下拉列表', + 'control_balloon-selector' => '气球选择器', + 'control_balloon-selector_description' => '一次只能使用静态或动态选项选择一个项目的列表', + 'control_unknown' => '未知控件类型: :type', + 'control_repeater' => '循环组件', + 'control_repeater_description' => '输出一组重复的窗体控件', + 'control_number' => '数值', + 'control_number_description' => '只接受数字的单行文本框', + 'control_hint' => '提示', + 'control_hint_description' => '输出可由用户隐藏的框中的部分内容', + 'control_partial' => '部分', + 'control_partial_description' => '输出部分内容', + 'control_section' => '切片', + 'control_section_description' => '显示带有标题和副标题的窗体节', + 'control_radio' => '单选框列表', + 'control_radio_description' => '单选选项列表,一次只能选择一个项目', + 'control_radio_option_1' => '选项 1', + 'control_radio_option_2' => '选项 2', + 'control_checkboxlist' => '复选框列表', + 'control_checkboxlist_description' => '复选框列表,可在其中选择多个项目', + 'control_codeeditor' => '代码编辑器', + 'control_codeeditor_description' => '用于格式化代码或标记的纯文本编辑器', + 'control_colorpicker' => '颜色选择器', + 'control_colorpicker_description' => '用于选择十六进制颜色值的字段', + 'control_datepicker' => '日期选择器', + 'control_datepicker_description' => '用于选择日期和时间的文本字段', + 'control_richeditor' => '富文本编辑器', + 'control_richeditor_description' => '富格式文本的可视化编辑器,也称为所见即所得编辑器', + 'property_group_rich_editor' => '富文本编辑器', + 'property_richeditor_toolbar_buttons' => '工具栏按钮', + 'property_richeditor_toolbar_buttons_description' => '在编辑器工具栏上显示哪些按钮', + 'control_markdown' => 'Markdown 编辑器', + 'control_markdown_description' => '标记格式文本的基本编辑器', + 'control_taglist' => '标签列表', + 'control_taglist_description' => '用于输入标签列表的字段', + 'control_fileupload' => '文件上传', + 'control_fileupload_description' => '图像或常规文件的文件上传', + 'control_recordfinder' => '记录查找', + 'control_recordfinder_description' => '具有记录搜索功能的相关记录的详细信息的字段', + 'control_mediafinder' => '媒体查找器', + 'control_mediafinder_description' => '从媒体管理器库中选择项目的字段', + 'control_relation' => '关联', + 'control_relation_description' => '显示用于选择相关记录的下拉列表或复选框列表', + 'control_widget_type' => '小部件类型', + 'error_file_name_required' => '请输入表单文件名.', + 'error_file_name_invalid' => '文件名只能包含拉丁字母、数字、下划线、点和哈希.', + 'span_left' => '左边', + 'span_right' => '右边', + 'span_full' => '铺满', + 'span_auto' => '自动', + 'style_default' => '默认', + 'style_collapsed' => '折叠', + 'style_accordion' => '手风琴', + 'empty_tab' => '空标签', + 'confirm_close_tab' => '选项卡包含将被删除的控件。继续?', + 'tab' => '表单选项卡', + 'tab_title' => '标题', + 'controls' => '控件', + 'property_tab_title_required' => '选项卡标题不能为空.', + 'tabs_primary' => '主选项卡', + 'tabs_secondary' => '辅助选项卡', + 'tab_stretch' => '标准', + 'tab_stretch_description' => '指定此选项卡容器是否拉伸以适合父级高度.', + 'tab_css_class' => 'CSS 类', + 'tab_css_class_description' => '将CSS类分配给tabs容器.', + 'tab_name_template' => '选项卡 %s', + 'tab_already_exists' => '具有指定标题的选项卡已存在.', + ], + 'list' => [ + 'tab_new_list' => '新列表', + 'saved' => '列表已保存', + 'confirm_delete' => '删除列表?', + 'tab_columns' => '列', + 'btn_add_column' => '添加列', + 'btn_delete_column' => '删除列', + 'column_dbfield_label' => '字段', + 'column_dbfield_required' => '请输入模型字段', + 'column_name_label' => '标签', + 'column_label_required' => '请输入列标签', + 'column_type_label' => '类型', + 'column_type_required' => '请输入列类型', + 'column_type_text' => '文本', + 'column_type_number' => '数值', + 'column_type_switch' => '开关', + 'column_type_datetime' => '日期时间', + 'column_type_date' => '日期', + 'column_type_time' => '时间', + 'column_type_timesince' => '开始时间', + 'column_type_timetense' => '结束时间', + 'column_type_select' => '选择', + 'column_type_partial' => '部分', + 'column_label_default' => '默认', + 'column_label_searchable' => '搜索', + 'column_label_sortable' => '排序', + 'column_label_invisible' => '隐形的', + 'column_label_select' => '选择', + 'column_label_relation' => '关系', + 'column_label_css_class' => 'CSS 类', + 'column_label_width' => '宽度', + 'column_label_path' => '路径', + 'column_label_format' => '格式', + 'column_label_value_from' => '来源值', + 'error_duplicate_column' => '重复的列字段名: \':column\'.', + 'btn_add_database_columns' => '添加数据库列', + 'all_database_columns_exist' => '列表中已定义所有数据库列', + ], + 'controller' => [ + 'menu_label' => '控制器', + 'no_records' => '找不到插件控制器', + 'controller' => '控制器', + 'behaviors' => '行为', + 'new_controller' => '新控制器', + 'error_controller_has_no_behaviors' => '控制器没有可配置的行为.', + 'error_invalid_yaml_configuration' => '加载行为配置文件时出错: :file', + 'behavior_form_controller' => '窗体控制器行为', + 'behavior_form_controller_description' => '向后端页面添加表单功能。该行为提供了三个页面,分别称为Create、Update和Preview.', + 'property_behavior_form_placeholder' => '--选择表单--', + 'property_behavior_form_name' => '名称', + 'property_behavior_form_name_description' => '此窗体管理的对象的名称', + 'property_behavior_form_name_required' => '请输入表单名称', + 'property_behavior_form_file' => '表单配置', + 'property_behavior_form_file_description' => '对表单域定义文件的引用', + 'property_behavior_form_file_required' => '请输入表单配置文件的路径', + 'property_behavior_form_model_class' => '模型类', + 'property_behavior_form_model_class_description' => '一个模型类名,表单数据将根据此模型加载和保存.', + 'property_behavior_form_model_class_required' => '请选择一个模型类', + 'property_behavior_form_default_redirect' => '默认重定向', + 'property_behavior_form_default_redirect_description' => '保存或取消表单时默认重定向到的页面.', + 'property_behavior_form_create' => '创建记录页', + 'property_behavior_form_redirect' => '重定向', + 'property_behavior_form_redirect_description' => '创建记录时要重定向到的页.', + 'property_behavior_form_redirect_close' => '关闭重定向', + 'property_behavior_form_redirect_close_description' => '创建记录并随请求一起发送close post变量时要重定向到的页面.', + 'property_behavior_form_flash_save' => '保存闪存消息', + 'property_behavior_form_flash_save_description' => '保存记录时要显示的闪存消息.', + 'property_behavior_form_page_title' => '页面标题', + 'property_behavior_form_update' => '更新记录页', + 'property_behavior_form_update_redirect' => '重定向', + 'property_behavior_form_create_redirect_description' => '保存记录时要重定向到的页.', + 'property_behavior_form_flash_delete' => '删除闪存消息', + 'property_behavior_form_flash_delete_description' => '删除记录时显示的闪烁消息.', + 'property_behavior_form_preview' => '预览记录页', + 'behavior_list_controller' => '列表控制器行为', + 'behavior_list_controller_description' => '提供可排序和可搜索的列表,其记录上有可选链接。行为自动创建控制器操作“index”.', + 'property_behavior_list_title' => '列表标题', + 'property_behavior_list_title_required' => '请输入列表标题', + 'property_behavior_list_placeholder' => '--选择列表--', + 'property_behavior_list_model_class' => '模型类', + 'property_behavior_list_model_class_description' => '模型类名,列表数据从此模型加载.', + 'property_behavior_form_model_class_placeholder' => '--选择模型--', + 'property_behavior_list_model_class_required' => '请输入一个模型名称', + 'property_behavior_list_model_placeholder' => '--选择模型--', + 'property_behavior_list_file' => '列表配置文件', + 'property_behavior_list_file_description' => '对列表定义文件的引用', + 'property_behavior_list_file_required' => '请输入列表配置文件的路径', + 'property_behavior_list_record_url' => '记录 URL', + 'property_behavior_list_record_url_description' => '将每个列表记录链接到另一页。例:用户/更新:id:id部分替换为记录标识符.', + 'property_behavior_list_no_records_message' => '无记录消息', + 'property_behavior_list_no_records_message_description' => '找不到记录时要显示的消息', + 'property_behavior_list_recs_per_page' => '每一页记录', + 'property_behavior_list_recs_per_page_description' => '每页要显示的记录,使用0表示没有页。默认值:0', + 'property_behavior_list_recs_per_page_regex' => '每页记录数应为整数值', + 'property_behavior_list_show_setup' => '显示设置按钮', + 'property_behavior_list_show_sorting' => '显示排序', + 'property_behavior_list_default_sort' => '默认排序', + 'property_behavior_form_ds_column' => '列', + 'property_behavior_form_ds_direction' => '方向', + 'property_behavior_form_ds_asc' => '升序', + 'property_behavior_form_ds_desc' => '降序', + 'property_behavior_list_show_checkboxes' => '显示复选框', + 'property_behavior_list_onclick' => '点击处理程序', + 'property_behavior_list_onclick_description' => '单击记录时要执行的自定义JavaScript代码.', + 'property_behavior_list_show_tree' => '显示树', + 'property_behavior_list_show_tree_description' => '显示父/子记录的树层次结构.', + 'property_behavior_list_tree_expanded' => '树已展开', + 'property_behavior_list_tree_expanded_description' => '确定默认情况下是否应展开树节点.', + 'property_behavior_list_toolbar' => '工具栏', + 'property_behavior_list_toolbar_buttons' => '按钮部分', + 'property_behavior_list_toolbar_buttons_description' => '使用工具栏按钮引用控制器部分文件。例如:列表工具栏', + 'property_behavior_list_search' => '搜索', + 'property_behavior_list_search_prompt' => '搜索提示', + 'property_behavior_list_filter' => '筛选配置', + 'behavior_reorder_controller' => '重新排序控制器行为', + 'behavior_reorder_controller_description' => '提供对其记录进行排序和重新排序的功能。该行为会自动创建控制器操作“重新排序”.', + 'property_behavior_reorder_title' => '重新排序标题', + 'property_behavior_reorder_title_required' => '请输入重新排序标题', + 'property_behavior_reorder_name_from' => '属性名称', + 'property_behavior_reorder_name_from_description' => '应用作每个记录的标签的模型属性.', + 'property_behavior_reorder_name_from_required' => '请输入属性名称', + 'property_behavior_reorder_model_class' => '模型类', + 'property_behavior_reorder_model_class_description' => '模型类名,重新排序数据从此模型加载.', + 'property_behavior_reorder_model_class_placeholder' => '--选择模型--', + 'property_behavior_reorder_model_class_required' => '请选择模型类', + 'property_behavior_reorder_model_placeholder' => '--选择模型--', + 'property_behavior_reorder_toolbar' => '工具栏', + 'property_behavior_reorder_toolbar_buttons' => '按钮部分', + 'property_behavior_reorder_toolbar_buttons_description' => '使用工具栏按钮引用控制器部分文件。例如:重新排序工具栏', + 'error_controller_not_found' => '找不到原始控制器文件.', + 'error_invalid_config_file_name' => '行为 :class 配置文件名 (:file) 包含无效字符,造成不能假装.', + 'error_file_not_yaml' => '行为 :class 配置文件 (:file) 不是一个YAML文件. 仅支持YAML配置文件.', + 'saved' => '控制器已保存', + 'controller_name' => '控制器名称', + 'controller_name_description' => '控制器名称定义控制器后端页的类名和URL。应用标准的PHP变量命名约定。第一个符号应该是大写拉丁字母。示例:Build、News、Case.', + 'base_model_class' => '基本模型类', + 'base_model_class_description' => '选择要在需要或支持模型的行为中用作基础模型的模型类。您可以稍后配置这些行为.', + 'base_model_class_placeholder' => '--选择模型--', + 'controller_behaviors' => '行为', + 'controller_behaviors_description' => '选择控制器应该实现的行为。生成器将自动创建行为所需的视图文件.', + 'controller_permissions' => '权限', + 'controller_permissions_description' => '选择可以访问控制器视图的用户权限。权限可以在生成器的“权限”选项卡上定义。稍后可以在控制器PHP脚本中更改此选项.', + 'controller_permissions_no_permissions' => '插件没有定义任何权限.', + 'menu_item' => '活动菜单项', + 'menu_item_description' => '选择要激活控制器页面的菜单项。稍后可以在控制器PHP脚本中更改此选项.', + 'menu_item_placeholder' => '--选择菜单项--', + 'error_unknown_behavior' => '行为类 :class 没有在行为类库注册.', + 'error_behavior_view_conflict' => '所选行为提供了冲突的视图 (:view) 不能在控制器中一起使用.', + 'error_behavior_config_conflict' => '所选行为提供冲突的配置文件 (:file) 无法在控制器中一起使用.', + 'error_behavior_view_file_not_found' => '行为 :class 的视图模板 :view 没有找到.', + 'error_behavior_config_file_not_found' => '行为 :class 的配置文件 :file 没有找到.', + 'error_controller_exists' => '控制器文件已存在: :file.', + 'error_controller_name_invalid' => '无效格式的控制名称. 名称只能包含数字和拉丁字母。第一个符号应该是大写拉丁字母.', + 'error_behavior_view_file_exists' => '控制器视图文件已存在: :view.', + 'error_behavior_config_file_exists' => '行为配置文件已存在: :file.', + 'error_save_file' => '保存控制器文件错误: :file', + 'error_behavior_requires_base_model' => '行为 :behavior 必须选择一个基础模型类.', + 'error_model_doesnt_have_lists' => '所选模型没有任何列表。请先创建列表.', + 'error_model_doesnt_have_forms' => '所选模型没有任何窗体。请先创建表单.', + ], + 'version' => [ + 'menu_label' => '版本', + 'no_records' => '找不到插件版本', + 'search' => '搜索...', + 'tab' => '版本', + 'saved' => '已保存版本', + 'confirm_delete' => '删除版本?', + 'tab_new_version' => '新奔奔', + 'migration' => '迁移', + 'seeder' => '填充', + 'custom' => '增加版本号', + 'apply_version' => '应用版本', + 'applying' => '应用中...', + 'rollback_version' => '回滚版本', + 'rolling_back' => '回滚中...', + 'applied' => '应用的版本', + 'rolled_back' => '版本已回滚', + 'hint_save_unapplied' => '您保存了一个未应用的版本。当您或其他用户登录到后端或数据库表保存在生成器的数据库部分时,可以自动应用未应用的版本.', + 'hint_rollback' => '回滚某个版本也将回滚比此版本更新的所有版本。请注意,当您或其他用户登录到后端或数据库表保存在生成器的数据库部分时,系统会自动应用未应用的版本.', + 'hint_apply' => '应用一个版本也会应用插件的所有旧版本.', + 'dont_show_again' => '不再显示', + 'save_unapplied_version' => '保存未应用的版本', + 'sort_ascending' => '升序排序', + 'sort_descending' => '降序排序', + ], + 'menu' => [ + 'menu_label' => '后台菜单', + 'tab' => '菜单', + 'items' => '菜单选项', + 'saved' => '已保存菜单', + 'add_main_menu_item' => '添加主菜单项', + 'new_menu_item' => '菜单选项', + 'add_side_menu_item' => '添加子项', + 'side_menu_item' => '侧边栏菜单项', + 'property_label' => '标签', + 'property_label_required' => '请输入菜单项标签.', + 'property_url_required' => '请输入菜单项URL', + 'property_url' => 'URL', + 'property_icon' => '图标', + 'property_icon_required' => '请选择一个图标', + 'property_permissions' => '权限', + 'property_order' => '顺序', + 'property_order_invalid' => '请以整数值形式输入菜单项顺序。', + 'property_order_description' => '菜单项顺序管理其在菜单中的位置。如果没有提供订单,该项目将被放在菜单的末尾。默认订单值的增量为100.', + 'property_attributes' => 'HTML属性', + 'property_code' => '代码', + 'property_code_invalid' => '代码只能包含拉丁字母和数字', + 'property_code_required' => '请输入菜单项代码.', + 'error_duplicate_main_menu_code' => '主菜单项代码重复: \':code\'.', + 'error_duplicate_side_menu_code' => '重复的侧边栏菜单项代码: \':code\'.', + 'icon_svg' => 'SVG图标', + 'icon_svg_description' => '用于代替标准图标的SVG图标,SVG图标应该是一个矩形并且可以支持颜色', + 'counter' => '通知内容', + 'counter_description' => '要在菜单图标附近输出的数值。 该值应该是一个数字或一个返回数字的可调用对象', + 'counter_label' => '通知描述', + 'counter_label_description' => '一个字符串值,用于描述计数器中的数字引用', + 'counter_group' => '通知气泡', + ], + 'localization' => [ + 'menu_label' => '本地化', + 'language' => '语言', + 'strings' => '字符串', + 'confirm_delete' => '删除语言?', + 'tab_new_language' => '新语言', + 'no_records' => '未找到语言', + 'saved' => '语言文件已保存', + 'error_cant_load_file' => '无法加载请求的语言文件-找不到文件.', + 'error_bad_localization_file_contents' => '无法加载请求的语言文件。语言文件只能包含数组定义和字符串.', + 'error_file_not_array' => '无法加载请求的语言文件。语言文件应该返回一个数组.', + 'save_error' => '保存文件错误 \':name\'. 请检查写入权限.', + 'error_delete_file' => '删除本地化文件时出错.', + 'add_missing_strings' => '添加缺少的字符串', + 'copy' => '复制', + 'add_missing_strings_label' => '选择要从中复制缺少字符串的语言', + 'no_languages_to_copy_from' => '没有其他语言可用于复制字符串.', + 'new_string_warning' => '新字符串或节', + 'structure_mismatch' => '源语言文件的结构与正在编辑的文件的结构不匹配。编辑文件中的某些单独字符串与源文件中的节相对应(反之亦然),因此无法自动合并.', + 'create_string' => '创建新的字符串', + 'string_key_label' => '字符串键', + 'string_key_comment' => '使用句点作为节分隔符输入字符串键。例如:plugin.search. 字符串将在插件的默认语言本地化文件中创建.', + 'string_value' => '字符串值', + 'string_key_is_empty' => '字符串键不应为空', + 'string_key_is_a_string' => ':key 是字符串,不能包含其他字符串.', + 'string_value_is_empty' => '字符串值不应为空', + 'string_key_exists' => '字符串键已存在', + ], + 'permission' => [ + 'menu_label' => '权限', + 'tab' => '权限', + 'form_tab_permissions' => '权限', + 'btn_add_permission' => '添加权限', + 'btn_delete_permission' => '删除权限', + 'column_permission_label' => '权限代码', + 'column_permission_required' => '请输入权限代码', + 'column_tab_label' => '选项卡标题', + 'column_tab_required' => '请输入权限选项卡标题', + 'column_label_label' => '标签', + 'column_label_required' => '请输入选项卡标签', + 'saved' => '权限已保存', + 'error_duplicate_code' => '权限代码重复: \':code\'.', + ], + 'yaml' => [ + 'save_error' => '保存文件错误 \':name\'. 请检查写入权限.', + ], + 'common' => [ + 'error_file_exists' => '文件已存在: \':path\'.', + 'field_icon_description' => 'October 使用字体图标: http://octobercms.com/docs/ui/icon', + 'destination_dir_not_exists' => '目标目录不存在: \':path\'.', + 'error_make_dir' => '创建目录错误: \':name\'.', + 'error_dir_exists' => '目录已存在: \':path\'.', + 'template_not_found' => '模板文件未找到: \':name\'.', + 'error_generating_file' => '生成文件错误: \':path\'.', + 'error_loading_template' => '加载模板文件错误: \':name\'.', + 'select_plugin_first' => '请先选择一个插件。要查看插件列表,请单击左侧边栏上的>图标。.', + 'plugin_not_selected' => '未选择插件', + 'add' => '添加', + ], + 'migration' => [ + 'entity_name' => '迁移', + 'error_version_invalid' => '版本格式应参照:1.0.1', + 'field_version' => '版本', + 'field_description' => '描述', + 'field_code' => '代码', + 'save_and_apply' => '保存 & 应用', + 'error_version_exists' => '迁移版本已存在.', + 'error_script_filename_invalid' => '迁移脚本文件名只能包含拉丁字母、数字和下划线。名称应以拉丁字母开头,不能包含空格.', + 'error_cannot_change_version_number' => '无法更改应用版本的版本号.', + 'error_file_must_define_class' => '迁移代码应该定义迁移或种子类。如果只想更新版本号,请将“代码”字段留空.', + 'error_file_must_define_namespace' => '应该定义一个代码迁移。如果只想更新版本号,请将“代码”字段留空.', + 'no_changes_to_save' => '没有要保存的更改.', + 'error_namespace_mismatch' => '迁移代码应该使用插件名称空间: :namespace', + 'error_migration_file_exists' => '迁移文件 :file 已存在. 请使用其他的文件名称.', + 'error_cant_delete_applied' => '此版本已应用,无法删除。请先回滚版本.', + ], + 'components' => [ + 'list_title' => '记录列表', + 'list_description' => '显示选定模型的记录列表', + 'list_page_number' => '页数', + 'list_page_number_description' => '此值用于确定用户所在的页面.', + 'list_records_per_page' => '每页记录', + 'list_records_per_page_description' => '要在单个页面上显示的记录数。保留为空可禁用分页.', + 'list_records_per_page_validation' => '每页记录值的格式无效。值应为数字.', + 'list_no_records' => '无记录消息', + 'list_no_records_description' => '如果没有记录,则在列表中显示的消息。在默认组件的.', + 'list_no_records_default' => '找不到记录', + 'list_sort_column' => '列排序', + 'list_sort_column_description' => '记录排序依据的模型列', + 'list_sort_direction' => '方向', + 'list_display_column' => '显示列', + 'list_display_column_description' => '要在列表中显示的列。在默认组件的.', + 'list_display_column_required' => '请选择显示列.', + 'list_details_page' => '详情页', + 'list_details_page_description' => '显示记录详细信息的页面.', + 'list_details_page_no' => '--无详细信息页--', + 'list_sorting' => '排序', + 'list_pagination' => '分页', + 'list_order_direction_asc' => '升序', + 'list_order_direction_desc' => '倒叙', + 'list_model' => '模型类', + 'list_scope' => '范围', + 'list_scope_description' => '获取记录的可选模型范围', + 'list_scope_default' => '--选择范围,可选--', + 'list_scope_value' => '范围值', + 'list_scope_value_description' => '传递给模型范围的可选值', + 'list_details_page_link' => '链接到详细信息页', + 'list_details_key_column' => '详细信息键列', + 'list_details_key_column_description' => '要用作详细信息页链接中的记录标识符的模型列.', + 'list_details_url_parameter' => 'URL 参数名称', + 'list_details_url_parameter_description' => '采用记录标识符的详细信息页URL参数的名称.', + 'details_title' => '记录详情', + 'details_description' => '显示选定模型的记录详细信息', + 'details_model' => '模型类', + 'details_identifier_value' => '标识符值', + 'details_identifier_value_description' => '从数据库加载记录的标识符值。指定固定值或URL参数名称.', + 'details_identifier_value_required' => '标识符值是必需的', + 'details_key_column' => '键列', + 'details_key_column_description' => '要用作从数据库提取记录的记录标识符的模型列.', + 'details_key_column_required' => '键列名是必需的', + 'details_display_column' => '显示列', + 'details_display_column_description' => '要在详细信息页面上显示的模型列。在默认组件的.', + 'details_display_column_required' => '请选择显示列.', + 'details_not_found_message' => '未找到消息', + 'details_not_found_message_description' => '未找到记录时要显示的消息。在默认组件的.', + 'details_not_found_message_default' => '记录未找到', + ], + 'validation' => [ + 'reserved' => ':attribute 不能是PHP保留关键字', + ], +]; diff --git a/plugins/rainlab/builder/models/BaseModel.php b/plugins/rainlab/builder/models/BaseModel.php new file mode 100644 index 0000000..c2f042e --- /dev/null +++ b/plugins/rainlab/builder/models/BaseModel.php @@ -0,0 +1,163 @@ +updatedData = []; + + foreach ($attributes as $key => $value) { + if (!in_array($key, static::$fillable)) { + continue; + } + + $methodName = 'set'.ucfirst($key); + if (method_exists($this, $methodName)) { + $this->$methodName($value); + } + else { + if (is_scalar($value) && strpos($value, ' ') !== false) { + $value = trim($value); + } + + $this->$key = $value; + } + + $this->updatedData[$key] = $value; + } + } + + /** + * validate + */ + public function validate() + { + $existingData = []; + foreach (static::$fillable as $field) { + $existingData[$field] = $this->$field; + } + + $validation = Validator::make( + array_merge($existingData, $this->updatedData), + $this->validationRules, + $this->validationMessages + ); + + if ($validation->fails()) { + throw new ValidationException($validation); + } + + if (!$this->isNewModel()) { + $this->validateBeforeCreate(); + } + } + + /** + * isNewModel + */ + public function isNewModel() + { + return $this->exists === false; + } + + /** + * Sets a string code of a plugin the model is associated with + * @param string $code Specifies the plugin code + */ + public function setPluginCode($code) + { + $this->pluginCodeObj = new PluginCode($code); + } + + /** + * Sets a code object of a plugin the model is associated with + * @param PluginCode $obj Specifies the plugin code object + */ + public function setPluginCodeObj($obj) + { + $this->pluginCodeObj = $obj; + } + + /** + * validateBeforeCreate + */ + protected function validateBeforeCreate() + { + } + + /** + * getModelPluginName + */ + public function getModelPluginName() + { + $pluginCodeObj = $this->getPluginCodeObj(); + $pluginCode = $pluginCodeObj->toCode(); + + $vector = PluginVector::createFromPluginCode($pluginCode); + if ($vector) { + return $vector->getPluginName(); + } + + return null; + } + + /** + * getPluginCodeObj + */ + public function getPluginCodeObj() + { + if (!$this->pluginCodeObj) { + throw new SystemException(sprintf('The active plugin is not set in the %s object.', get_class($this))); + } + + return $this->pluginCodeObj; + } +} diff --git a/plugins/rainlab/builder/models/CodeFileModel.php b/plugins/rainlab/builder/models/CodeFileModel.php new file mode 100644 index 0000000..c8ef7d9 --- /dev/null +++ b/plugins/rainlab/builder/models/CodeFileModel.php @@ -0,0 +1,282 @@ +allowedExtensions = self::getEditableExtensions(); + } + + /** + * load a single template by its file name. + * + * @param string $fileName + * @return mixed|static + */ + public function load($fileName) + { + $filePath = $this->getFilePath($fileName); + + if (!File::isFile($filePath)) { + return null; + } + + if (($content = @File::get($filePath)) === false) { + return null; + } + + $this->fileName = $fileName; + $this->originalFileName = $fileName; + $this->mtime = File::lastModified($filePath); + $this->content = $content; + $this->exists = true; + + return $this; + } + + /** + * Sets the object attributes. + * @param array $attributes A list of attributes to set. + */ + public function fill(array $attributes) + { + foreach ($attributes as $key => $value) { + if (!in_array($key, static::$fillable)) { + throw new ApplicationException(Lang::get( + 'cms::lang.cms_object.invalid_property', + ['name' => $key] + )); + } + + $this->$key = $value; + } + } + + /** + * Saves the object to the disk. + */ + public function save() + { + $this->validateFileName(); + + $fullPath = $this->getFilePath(); + + if (File::isFile($fullPath) && $this->originalFileName !== $this->fileName) { + throw new ApplicationException(Lang::get( + 'cms::lang.cms_object.file_already_exists', + ['name' => $this->fileName] + )); + } + + $dirPath = base_path($this->dirName); + if (!file_exists($dirPath) || !is_dir($dirPath)) { + if (!File::makeDirectory($dirPath, 0777, true, true)) { + throw new ApplicationException(Lang::get( + 'cms::lang.cms_object.error_creating_directory', + ['name' => $dirPath] + )); + } + } + + if (($pos = strpos($this->fileName, '/')) !== false) { + $dirPath = dirname($fullPath); + + if (!is_dir($dirPath) && !File::makeDirectory($dirPath, 0777, true, true)) { + throw new ApplicationException(Lang::get( + 'cms::lang.cms_object.error_creating_directory', + ['name' => $dirPath] + )); + } + } + + $newFullPath = $fullPath; + if (@File::put($fullPath, $this->content) === false) { + throw new ApplicationException(Lang::get( + 'cms::lang.cms_object.error_saving', + ['name' => $this->fileName] + )); + } + + if (strlen($this->originalFileName) && $this->originalFileName !== $this->fileName) { + $fullPath = $this->getFilePath($this->originalFileName); + + if (File::isFile($fullPath)) { + @unlink($fullPath); + } + } + + clearstatcache(); + + $this->mtime = @File::lastModified($newFullPath); + $this->originalFileName = $this->fileName; + $this->exists = true; + } + + /** + * delete + */ + public function delete() + { + $fileName = Request::input('fileName'); + $fullPath = $this->getFilePath($fileName); + + $this->validateFileName($fileName); + + if (File::exists($fullPath)) { + if (!@File::delete($fullPath)) { + throw new ApplicationException(Lang::get( + 'cms::lang.asset.error_deleting_file', + ['name' => $fileName] + )); + } + } + } + + /** + * validateFileName validates the supplied filename, extension and path. + * @param string $fileName + */ + protected function validateFileName($fileName = null) + { + if ($fileName === null) { + $fileName = $this->fileName; + } + + $fileName = trim($fileName); + + if (!strlen($fileName)) { + throw new ValidationException(['fileName' => + Lang::get('cms::lang.cms_object.file_name_required', [ + 'allowed' => implode(', ', $this->allowedExtensions), + 'invalid' => pathinfo($fileName, PATHINFO_EXTENSION) + ]) + ]); + } + + if (!FileHelper::validateExtension($fileName, $this->allowedExtensions, false)) { + throw new ValidationException(['fileName' => + Lang::get('cms::lang.cms_object.invalid_file_extension', [ + 'allowed' => implode(', ', $this->allowedExtensions), + 'invalid' => pathinfo($fileName, PATHINFO_EXTENSION) + ]) + ]); + } + + if (!FileHelper::validatePath($fileName, null)) { + throw new ValidationException(['fileName' => + Lang::get('cms::lang.cms_object.invalid_file', [ + 'name' => $fileName + ]) + ]); + } + } + + /** + * getFileName returns the file name. + * @return string + */ + public function getFileName() + { + return $this->fileName; + } + + /** + * getFilePath returns the absolute file path. + * @param string $fileName Specifies the file name to return the path to. + * @return string + */ + public function getFilePath($fileName = null) + { + if ($fileName === null) { + $fileName = $this->fileName; + } + + $pluginPath = $this->getPluginCodeObj()->toFilesystemPath(); + + return base_path($this->dirName.'/'.$pluginPath.'/'.$fileName); + } + + /** + * getEditableExtensions returns a list of editable asset extensions. + * The list can be overridden with the cms.editableAssetTypes configuration option. + * @return array + */ + public static function getEditableExtensions() + { + $defaultTypes = ['js', 'jsx', 'css', 'sass', 'scss', 'less', 'php', 'htm', 'html', 'yaml', 'md', 'txt']; + + $configTypes = Config::get('rainlab.builder::editable_code_types'); + if (!$configTypes) { + return $defaultTypes; + } + + return $configTypes; + } +} diff --git a/plugins/rainlab/builder/models/ControllerModel.php b/plugins/rainlab/builder/models/ControllerModel.php new file mode 100644 index 0000000..cf42958 --- /dev/null +++ b/plugins/rainlab/builder/models/ControllerModel.php @@ -0,0 +1,572 @@ + ['regex:/^[A-Z]+[a-zA-Z0-9_]+$/'] + ]; + + /** + * load + */ + public function load($controller) + { + if (!$this->validateFileName($controller)) { + throw new SystemException("Invalid controller file name: {$controller}"); + } + + $this->controller = $this->trimExtension($controller); + $this->loadControllerBehaviors(); + $this->exists = true; + } + + /** + * save + */ + public function save() + { + if (!$this->controllerName) { + $this->controllerName = $this->controller; + } + + if ($this->isNewModel()) { + $this->generateController(); + } + else { + $this->saveController(); + } + } + + /** + * fill + */ + public function fill(array $attributes) + { + parent::fill($attributes); + + if (is_array($this->behaviors)) { + // Convert [1,2,3] to [1=>[], 2=>[], 3=>[]] + if (Arr::isList($this->behaviors)) { + $this->behaviors = array_combine($this->behaviors, array_fill(0, count($this->behaviors), [])); + } + + foreach ($this->behaviors as $class => &$configuration) { + if (is_scalar($configuration)) { + $configuration = json_decode($configuration, true); + } + } + } + } + + /** + * listPluginControllers + */ + public static function listPluginControllers($pluginCodeObj) + { + $controllersDirectoryPath = $pluginCodeObj->toPluginDirectoryPath().'/controllers'; + + $controllersDirectoryPath = File::symbolizePath($controllersDirectoryPath); + + if (!File::isDirectory($controllersDirectoryPath)) { + return []; + } + + $result = []; + foreach (new DirectoryIterator($controllersDirectoryPath) as $fileInfo) { + if ($fileInfo->isDir()) { + continue; + } + + if ($fileInfo->getExtension() !== 'php') { + continue; + } + + $result[] = $fileInfo->getBasename('.php'); + } + + return $result; + } + + /** + * getBaseModelClassNameOptions + */ + public function getBaseModelClassNameOptions() + { + $models = ModelModel::listPluginModels($this->getPluginCodeObj()); + + $result = []; + foreach ($models as $model) { + $result[$model->className] = $model->className; + } + + return $result; + } + + /** + * getBehaviorsOptions + */ + public function getBehaviorsOptions() + { + $library = ControllerBehaviorLibrary::instance(); + $behaviors = $library->listBehaviors(); + + $result = []; + foreach ($behaviors as $behaviorClass => $behaviorInfo) { + $result[$behaviorClass] = [ + $behaviorInfo['name'], + $behaviorInfo['description'] + ]; + } + + // Support for this is added via import tool + unset($result[\Backend\Behaviors\ImportExportController::class]); + + return $result; + } + + /** + * getPermissionsOptions + */ + public function getPermissionsOptions() + { + $model = new PermissionsModel(); + + $model->loadPlugin($this->getPluginCodeObj()->toCode()); + + $result = []; + + foreach ($model->permissions as $permissionInfo) { + if (!isset($permissionInfo['label']) || !isset($permissionInfo['permission'])) { + continue; + } + + $result[$permissionInfo['permission']] = Lang::get($permissionInfo['label']); + } + + return $result; + } + + /** + * getMenuItemOptions + */ + public function getMenuItemOptions() + { + $model = new MenusModel(); + + $model->loadPlugin($this->getPluginCodeObj()->toCode()); + + $result = []; + + foreach ($model->menus as $itemInfo) { + if (!isset($itemInfo['label']) || !isset($itemInfo['code'])) { + continue; + } + + $itemCode = $itemInfo['code']; + $result[$itemCode] = Lang::get($itemInfo['label']); + + if (!isset($itemInfo['sideMenu'])) { + continue; + } + + foreach ($itemInfo['sideMenu'] as $itemInfo) { + if (!isset($itemInfo['label']) || !isset($itemInfo['code'])) { + continue; + } + + $subItemCode = $itemInfo['code']; + + $result[$itemCode.'||'.$subItemCode] = str_repeat(' ', 4).Lang::get($itemInfo['label']); + } + } + + return $result; + } + + /** + * getControllerFilePath + */ + public function getControllerFilePath($controllerFilesDirectory = false) + { + $pluginCodeObj = $this->getPluginCodeObj(); + $controllersDirectoryPath = File::symbolizePath($pluginCodeObj->toPluginDirectoryPath().'/controllers'); + + if (!$controllerFilesDirectory) { + return $controllersDirectoryPath.'/'.$this->controller.'.php'; + } + + return $controllersDirectoryPath.'/'.strtolower($this->controller); + } + + /** + * getPluginRegistryData + */ + public static function getPluginRegistryData($pluginCode, $subtype) + { + $pluginCodeObj = new PluginCode($pluginCode); + $urlBase = $pluginCodeObj->toUrl().'/'; + + $controllers = self::listPluginControllers($pluginCodeObj); + $result = []; + + foreach ($controllers as $controller) { + $controllerPath = strtolower(basename($controller)); + + $url = $urlBase.$controllerPath; + + $result[$url] = $url; + } + + return $result; + } + + /** + * saveController + */ + protected function saveController() + { + $this->validate(); + + $controllerPath = $this->getControllerFilePath(); + if (!File::isFile($controllerPath)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_controller_not_found')); + } + + if (!is_array($this->behaviors)) { + throw new SystemException('The behaviors data should be an array.'); + } + + $fileContents = File::get($controllerPath); + + $parser = new ControllerFileParser($fileContents); + + $behaviors = $parser->listBehaviors(); + if (!$behaviors) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_controller_has_no_behaviors')); + } + + $library = ControllerBehaviorLibrary::instance(); + foreach ($behaviors as $behaviorClass) { + $behaviorInfo = $library->getBehaviorInfo($behaviorClass); + + if (!$behaviorInfo) { + continue; + } + + $propertyName = $behaviorInfo['configPropertyName']; + $propertyValue = $parser->getStringPropertyValue($propertyName); + if (!strlen($propertyValue)) { + continue; + } + + if (array_key_exists($behaviorClass, $this->behaviors)) { + $this->saveBehaviorConfiguration($propertyValue, $this->behaviors[$behaviorClass], $behaviorClass); + } + } + } + + /** + * generateController + */ + protected function generateController() + { + $this->validationMessages = [ + 'controller.regex' => Lang::get('rainlab.builder::lang.controller.error_controller_name_invalid') + ]; + + $this->validationRules['controller'][] = 'required'; + + $this->validate(); + + $generator = new ControllerGenerator($this); + $generator->generate(); + } + + /** + * loadControllerBehaviors + */ + protected function loadControllerBehaviors() + { + $filePath = $this->getControllerFilePath(); + if (!File::isFile($filePath)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_controller_not_found')); + } + + $fileContents = File::get($filePath); + + $parser = new ControllerFileParser($fileContents); + + $behaviors = $parser->listBehaviors(); + if (!$behaviors) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_controller_has_no_behaviors')); + } + + $library = ControllerBehaviorLibrary::instance(); + $this->behaviors = []; + foreach ($behaviors as $behaviorClass) { + $behaviorInfo = $library->getBehaviorInfo($behaviorClass); + if (!$behaviorInfo) { + continue; + } + + $propertyName = $behaviorInfo['configPropertyName']; + $propertyValue = $parser->getStringPropertyValue($propertyName); + if (!strlen($propertyValue)) { + continue; + } + + $configuration = $this->loadBehaviorConfiguration($propertyValue, $behaviorClass); + if ($configuration === false) { + continue; + } + + $this->behaviors[$behaviorClass] = $configuration; + } + } + + /** + * loadBehaviorConfiguration + */ + protected function loadBehaviorConfiguration($fileName, $behaviorClass) + { + if (!preg_match('/^[a-z0-9\.\-_]+$/i', $fileName)) { + return false; + } + + $extension = pathinfo($fileName, PATHINFO_EXTENSION); + if (strlen($extension) && $extension != 'yaml') { + return false; + } + + $controllerPath = $this->getControllerFilePath(true); + $filePath = $controllerPath.'/'.$fileName; + + if (!File::isFile($filePath)) { + return false; + } + + try { + $configuration = Yaml::parse(File::get($filePath)); + if ($behaviorClass === \Backend\Behaviors\ImportExportController::class) { + $this->processImportExportBehaviorConfig($configuration, true); + } + return $configuration; + } + catch (Exception $ex) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_invalid_yaml_configuration', ['file'=>$fileName])); + } + } + + /** + * saveBehaviorConfiguration + */ + protected function saveBehaviorConfiguration($fileName, $configuration, $behaviorClass) + { + if (!preg_match('/^[a-z0-9\.\-_]+$/i', $fileName)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_invalid_config_file_name', ['file'=>$fileName, 'class'=>$behaviorClass])); + } + + $extension = pathinfo($fileName, PATHINFO_EXTENSION); + if (strlen($extension) && $extension != 'yaml') { + throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_file_not_yaml', ['file'=>$fileName, 'class'=>$behaviorClass])); + } + + $controllerPath = $this->getControllerFilePath(true); + $filePath = $controllerPath.'/'.$fileName; + + $fileDirectory = dirname($filePath); + if (!File::isDirectory($fileDirectory)) { + if (!File::makeDirectory($fileDirectory, 0777, true, true)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.common.error_make_dir', ['name'=>$fileDirectory])); + } + } + + if ($behaviorClass === \Backend\Behaviors\ImportExportController::class) { + $this->processImportExportBehaviorConfig($configuration); + } + elseif ($behaviorClass === \Backend\Behaviors\ListController::class) { + $this->processListBehaviorConfig($configuration); + } + + if ($configuration !== null) { + $yamlData = Yaml::render($configuration); + } + else { + $yamlData = ''; + } + + if (@File::put($filePath, $yamlData) === false) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.yaml.save_error', ['name'=>$filePath])); + } + + @File::chmod($filePath); + } + + /** + * trimExtension + */ + protected function trimExtension($fileName) + { + if (substr($fileName, -4) == '.php') { + return substr($fileName, 0, -4); + } + + return $fileName; + } + + /** + * validateFileName + */ + protected function validateFileName($fileName) + { + if (!preg_match('/^[a-z0-9\.\-_]+$/i', $fileName)) { + return false; + } + + $extension = pathinfo($fileName, PATHINFO_EXTENSION); + if (strlen($extension) && $extension != 'php') { + return false; + } + + return true; + } + + /** + * processListBehaviorConfig converts booleans + */ + protected function processListBehaviorConfig(array &$configuration, $isLoad = false) + { + if (!isset($configuration['structure'])) { + return; + } + + $booleanFields = [ + 'showTree', + 'treeExpanded', + 'showReorder', + 'showSorting', + 'dragRow', + ]; + + foreach ($booleanFields as $booleanField) { + if (!array_key_exists($booleanField, $configuration['structure'])) { + continue; + } + + $value = $configuration['structure'][$booleanField]; + if ($value == '1' || $value == 'true') { + $value = true; + } + else { + $value = false; + } + + + $configuration['structure'][$booleanField] = $value; + } + + $numericFields = [ + 'maxDepth' + ]; + + foreach ($numericFields as $numericField) { + if (!array_key_exists($numericField, $configuration['structure'])) { + continue; + } + + $configuration['structure'][$numericField] = +$configuration['structure'][$numericField]; + } + } + + /** + * processImportExportBehaviorConfig converts import. and export. keys to and from their config + */ + protected function processImportExportBehaviorConfig(array &$configuration, $isLoad = false) + { + if ($isLoad) { + foreach ($configuration as $key => $value) { + if (!is_array($value) || !in_array($key, ['import', 'export'])) { + continue; + } + + foreach ($value as $k => $v) { + $configuration[$key.'.'.$k] = $v; + } + + unset($configuration[$key]); + } + } + else { + foreach ($configuration as $key => $value) { + if (starts_with($key, ['import.', 'export.'])) { + array_set($configuration, $key, array_pull($configuration, $key)); + } + } + } + } +} diff --git a/plugins/rainlab/builder/models/DatabaseTableModel.php b/plugins/rainlab/builder/models/DatabaseTableModel.php new file mode 100644 index 0000000..b7d243d --- /dev/null +++ b/plugins/rainlab/builder/models/DatabaseTableModel.php @@ -0,0 +1,477 @@ + ['required', 'regex:/^[a-z]+[a-z0-9_]+$/', 'tablePrefix', 'uniqueTableName', 'max:64'] + ]; + + /** + * @var \Doctrine\DBAL\Schema\Table Table details loaded from the database. + */ + protected $tableInfo; + + /** + * @var \Doctrine\DBAL\Schema\AbstractSchemaManager Contains the database schema + */ + protected static $schemaManager = null; + + /** + * @var \Doctrine\DBAL\Schema\Schema Contains the database schema + */ + protected static $schema = null; + + /** + * listPluginTables + */ + public static function listPluginTables($pluginCode) + { + $pluginCodeObj = new PluginCode($pluginCode); + $prefix = $pluginCodeObj->toDatabasePrefix(true); + + $tables = self::getSchemaManager()->listTableNames(); + + $foundTables = array_filter($tables, function ($item) use ($prefix) { + return Str::startsWith($item, $prefix); + }); + + $unprefixedTables = array_map(function($table) { + return substr($table, mb_strlen(Db::getTablePrefix())); + }, $foundTables); + + return $unprefixedTables; + } + + /** + * tableExists + */ + public static function tableExists($name) + { + return self::getSchema()->hasTable(Db::getTablePrefix() . $name); + } + + /** + * Loads the table from the database. + * @param string $name Specifies the table name. + */ + public function load($name) + { + if (!self::tableExists($name)) { + throw new SystemException(sprintf('The table with name %s doesn\'t exist', $name)); + } + + $schema = self::getSchemaManager()->createSchema(); + + $this->name = $name; + $this->tableInfo = $schema->getTable($this->getFullTableName()); + $this->loadColumnsFromTableInfo(); + $this->exists = true; + } + + /** + * getFullTableName + */ + protected function getFullTableName() + { + return Db::getTablePrefix() . $this->name; + } + + /** + * validate + */ + public function validate() + { + $pluginDbPrefix = $this->getPluginCodeObj()->toDatabasePrefix(); + + if (!strlen($pluginDbPrefix)) { + throw new SystemException('Error saving the table model - the plugin database prefix is not set for the object.'); + } + + $prefix = $pluginDbPrefix.'_'; + + $this->validationMessages = [ + 'name.table_prefix' => Lang::get('rainlab.builder::lang.database.error_table_name_invalid_prefix', [ + 'prefix' => $prefix + ]), + 'name.regex' => Lang::get('rainlab.builder::lang.database.error_table_name_invalid_characters'), + 'name.unique_table_name' => Lang::get('rainlab.builder::lang.database.error_table_already_exists', ['name'=>$this->name]), + 'name.max' => Lang::get('rainlab.builder::lang.database.error_table_name_too_long') + ]; + + Validator::extend('tablePrefix', function ($attribute, $value, $parameters) use ($prefix) { + $value = trim($value); + + if (!Str::startsWith($value, $prefix)) { + return false; + } + + return true; + }); + + Validator::extend('uniqueTableName', function ($attribute, $value, $parameters) { + $value = trim($value); + + $schema = $this->getSchema(); + if ($this->isNewModel()) { + return !$schema->hasTable($value); + } + + if ($value != $this->tableInfo->getName()) { + return !$schema->hasTable($value); + } + + return true; + }); + + $this->validateColumns(); + + return parent::validate(); + } + + /** + * generateCreateOrUpdateMigration + */ + public function generateCreateOrUpdateMigration() + { + $schemaCreator = new DatabaseTableSchemaCreator(); + $existingSchema = $this->tableInfo; + $newTableName = $this->name; + $tableName = $existingSchema ? $existingSchema->getName() : $this->name; + + $newSchema = $schemaCreator->createTableSchema($tableName, $this->columns); + + $codeGenerator = new TableMigrationCodeGenerator(); + $migrationCode = $codeGenerator->createOrUpdateTable($newSchema, $existingSchema, $newTableName); + if ($migrationCode === false) { + return $migrationCode; + } + + $description = $existingSchema ? 'Updated table %s' : 'Created table %s'; + return $this->createMigrationObject($migrationCode, sprintf($description, $tableName)); + } + + /** + * generateDropMigration + */ + public function generateDropMigration() + { + $existingSchema = $this->tableInfo; + $codeGenerator = new TableMigrationCodeGenerator(); + $migrationCode = $codeGenerator->dropTable($existingSchema); + + return $this->createMigrationObject($migrationCode, sprintf('Drop table %s', $this->name)); + } + + /** + * getSchema + */ + public static function getSchema() + { + if (!self::$schema) { + self::$schema = self::getSchemaManager()->createSchema(); + } + + return self::$schema; + } + + /** + * validateColumns + */ + protected function validateColumns() + { + $this->validateColumnNameLengths(); + $this->validateDuplicateColumns(); + $this->validateDuplicatePrimaryKeys(); + $this->validateAutoIncrementColumns(); + $this->validateColumnsLengthParameter(); + $this->validateUnsignedColumns(); + $this->validateDefaultValues(); + } + + /** + * validateColumnNameLengths + */ + protected function validateColumnNameLengths() + { + foreach ($this->columns as $column) { + $name = trim($column['name']); + + if (Str::length($name) > 64) { + throw new ValidationException([ + 'columns' => Lang::get( + 'rainlab.builder::lang.database.error_column_name_too_long', + ['column' => $name] + ) + ]); + } + } + } + + /** + * validateDuplicateColumns + */ + protected function validateDuplicateColumns() + { + foreach ($this->columns as $outerIndex => $outerColumn) { + foreach ($this->columns as $innerIndex => $innerColumn) { + if ($innerIndex != $outerIndex && $innerColumn['name'] == $outerColumn['name']) { + throw new ValidationException([ + 'columns' => Lang::get( + 'rainlab.builder::lang.database.error_table_duplicate_column', + ['column' => $outerColumn['name']] + ) + ]); + } + } + } + } + + /** + * validateDuplicatePrimaryKeys + */ + protected function validateDuplicatePrimaryKeys() + { + $keysFound = 0; + $autoIncrementsFound = 0; + foreach ($this->columns as $column) { + if ($column['primary_key']) { + $keysFound++; + } + + if ($column['auto_increment']) { + $autoIncrementsFound++; + } + } + + if ($keysFound > 1 && $autoIncrementsFound) { + throw new ValidationException([ + 'columns' => Lang::get('rainlab.builder::lang.database.error_table_auto_increment_in_compound_pk') + ]); + } + } + + /** + * validateAutoIncrementColumns + */ + protected function validateAutoIncrementColumns() + { + $autoIncrement = null; + foreach ($this->columns as $column) { + if (!$column['auto_increment']) { + continue; + } + + if ($autoIncrement) { + throw new ValidationException([ + 'columns' => Lang::get('rainlab.builder::lang.database.error_table_mutliple_auto_increment') + ]); + } + + $autoIncrement = $column; + } + + if (!$autoIncrement) { + return; + } + + if (!in_array($autoIncrement['type'], MigrationColumnType::getIntegerTypes())) { + throw new ValidationException([ + 'columns' => Lang::get('rainlab.builder::lang.database.error_table_auto_increment_non_integer') + ]); + } + } + + /** + * validateUnsignedColumns + */ + protected function validateUnsignedColumns() + { + foreach ($this->columns as $column) { + if (!$column['unsigned']) { + continue; + } + + if (!in_array($column['type'], MigrationColumnType::getIntegerTypes())) { + throw new ValidationException([ + 'columns' => Lang::get('rainlab.builder::lang.database.error_unsigned_type_not_int', ['column'=>$column['name']]) + ]); + } + } + } + + /** + * validateColumnsLengthParameter + */ + protected function validateColumnsLengthParameter() + { + foreach ($this->columns as $column) { + try { + MigrationColumnType::validateLength($column['type'], $column['length']); + } + catch (Exception $ex) { + throw new ValidationException([ + 'columns' => $ex->getMessage() + ]); + } + } + } + + /** + * validateDefaultValues + */ + protected function validateDefaultValues() + { + foreach ($this->columns as $column) { + if (!strlen($column['default'])) { + continue; + } + + $default = trim($column['default']); + + if (in_array($column['type'], MigrationColumnType::getIntegerTypes())) { + if (!preg_match('/^\-?[0-9]+$/', $default)) { + throw new ValidationException([ + 'columns' => Lang::get('rainlab.builder::lang.database.error_integer_default_value', ['column'=>$column['name']]) + ]); + } + + if ($column['unsigned'] && $default < 0) { + throw new ValidationException([ + 'columns' => Lang::get('rainlab.builder::lang.database.error_unsigned_negative_value', ['column'=>$column['name']]) + ]); + } + + continue; + } + + if (in_array($column['type'], MigrationColumnType::getDecimalTypes())) { + if (!preg_match('/^\-?([0-9]+\.[0-9]+|[0-9]+)$/', $default)) { + throw new ValidationException([ + 'columns' => Lang::get('rainlab.builder::lang.database.error_decimal_default_value', ['column'=>$column['name']]) + ]); + } + + continue; + } + + if ($column['type'] == MigrationColumnType::TYPE_BOOLEAN) { + if (!preg_match('/^0|1|true|false$/i', $default)) { + throw new ValidationException([ + 'columns' => Lang::get('rainlab.builder::lang.database.error_boolean_default_value', ['column'=>$column['name']]) + ]); + } + } + } + } + + /** + * getSchemaManager + */ + protected static function getSchemaManager() + { + if (!self::$schemaManager) { + self::$schemaManager = Schema::getConnection()->getDoctrineSchemaManager(); + + Type::addType('enumdbtype', \RainLab\Builder\Classes\EnumDbType::class); + + // Fixes the problem with enum column type not supported + // by Doctrine (https://github.com/laravel/framework/issues/1346) + $platform = self::$schemaManager->getDatabasePlatform(); + $platform->registerDoctrineTypeMapping('enum', 'enumdbtype'); + $platform->registerDoctrineTypeMapping('json', 'text'); + } + + return self::$schemaManager; + } + + /** + * loadColumnsFromTableInfo + */ + protected function loadColumnsFromTableInfo() + { + $this->columns = []; + $columns = $this->tableInfo->getColumns(); + + $primaryKey = $this->tableInfo->getPrimaryKey(); + $primaryKeyColumns =[]; + if ($primaryKey) { + $primaryKeyColumns = $primaryKey->getColumns(); + } + + foreach ($columns as $column) { + $columnName = $column->getName(); + $typeName = $column->getType()->getName(); + + if ($typeName == EnumDbType::TYPENAME) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.database.error_enum_not_supported')); + } + + $item = [ + 'name' => $columnName, + 'type' => MigrationColumnType::toMigrationMethodName($typeName, $columnName), + 'length' => MigrationColumnType::doctrineLengthToMigrationLength($column), + 'unsigned' => $column->getUnsigned(), + 'allow_null' => !$column->getNotnull(), + 'auto_increment' => $column->getAutoincrement(), + 'primary_key' => in_array($columnName, $primaryKeyColumns), + 'default' => $column->getDefault(), + 'comment' => $column->getComment(), + 'id' => $columnName, + ]; + + $this->columns[] = $item; + } + } + + /** + * createMigrationObject + */ + protected function createMigrationObject($code, $description) + { + $migration = new MigrationModel(); + $migration->setPluginCodeObj($this->getPluginCodeObj()); + + $migration->code = $code; + $migration->version = $migration->getNextVersion(); + $migration->description = $description; + + return $migration; + } +} diff --git a/plugins/rainlab/builder/models/ImportsModel.php b/plugins/rainlab/builder/models/ImportsModel.php new file mode 100644 index 0000000..564488a --- /dev/null +++ b/plugins/rainlab/builder/models/ImportsModel.php @@ -0,0 +1,270 @@ +blueprints)) { + foreach ($this->blueprints as &$configuration) { + if (is_scalar($configuration)) { + $configuration = json_decode($configuration, true); + } + } + } + } + + /** + * setBlueprintContext + */ + public function setBlueprintContext($blueprint, $config) + { + $this->activeBlueprint = $blueprint; + $this->activeConfig = $config; + } + + /** + * getBlueprintObject + */ + public function getBlueprintObject() + { + return $this->activeBlueprint; + } + + /** + * getBlueprintConfig + */ + public function getBlueprintConfig($name = null, $default = null) + { + if ($name === null) { + return $this->activeConfig; + } + + return array_key_exists($name, $this->activeConfig) + ? $this->activeConfig[$name] + : $default; + } + + /** + * loadPlugin + */ + public function loadPlugin($pluginCode) + { + $this->pluginName = $pluginCode; + } + + /** + * getPluginName + */ + public function getPluginName() + { + return Lang::get($this->pluginName); + } + + /** + * import runs the import + */ + public function import() + { + if (!$this->blueprints || !is_array($this->blueprints)) { + throw new ApplicationException(__("There are no blueprints to import, please select a blueprint and try again.")); + } + + $generator = new BlueprintGenerator($this); + $generator->generate(); + } + + /** + * inspect a blueprint before import + */ + public function inspect($blueprint): array + { + if (!$this->blueprints || !is_array($this->blueprints)) { + return []; + } + + $generator = new BlueprintGenerator($this); + + return $generator->inspect($blueprint); + } + + /** + * getBlueprintUuidOptions + */ + public function getBlueprintUuidOptions() + { + $result = []; + + foreach (EntryBlueprint::listInProject() as $blueprint) { + if (!isset($this->blueprints[$blueprint->uuid])) { + $result[$blueprint->uuid] = $blueprint->handle; + } + } + + foreach (GlobalBlueprint::listInProject() as $blueprint) { + if (!isset($this->blueprints[$blueprint->uuid])) { + $result[$blueprint->uuid] = $blueprint->handle; + } + } + + asort($result); + + return $result; + } + + /** + * getPluginFilePath + */ + public function getPluginFilePath($path) + { + $pluginDir = $this->getPluginCodeObj()->toPluginDirectoryPath(); + + return File::symbolizePath("{$pluginDir}/{$path}"); + } + + /** + * getPluginVersionInformation + */ + public function getPluginVersionInformation() + { + $versionObj = new PluginVersion; + + return $versionObj->getPluginVersionInformation($this->getPluginCodeObj()); + } + + /** + * getBlueprintFieldset + */ + public function getBlueprintFieldset($blueprint = null) + { + $blueprint = $blueprint ?: $this->getBlueprintObject(); + + $uuid = $blueprint->uuid ?? '???'; + + $fieldset = BlueprintIndexer::instance()->findContentFieldset($uuid); + if (!$fieldset) { + throw new ApplicationException("Unable to find content fieldset definition with UUID of '{$uuid}'."); + } + + return $fieldset; + } + + /** + * useListController + */ + public function useListController(): bool + { + if ( + $this->activeBlueprint instanceof SingleBlueprint || + $this->activeBlueprint instanceof GlobalBlueprint + ) { + return false; + } + + return true; + } + + /** + * useSettingModel + */ + public function useSettingModel(): bool + { + if ($this->activeBlueprint instanceof GlobalBlueprint) { + return true; + } + + return false; + } + + /** + * wantsDatabaseMigration + */ + public function wantsDatabaseMigration(): bool + { + if ($this->useSettingModel()) { + return false; + } + + return true; + } + + /** + * useMultisite + */ + public function useMultisite() + { + return $this->activeBlueprint->useMultisite(); + } + + /** + * useStructure + */ + public function useStructure() + { + if ($this->activeBlueprint instanceof StructureBlueprint) { + return true; + } + + return false; + } +} diff --git a/plugins/rainlab/builder/models/LocalizationModel.php b/plugins/rainlab/builder/models/LocalizationModel.php new file mode 100644 index 0000000..8d37458 --- /dev/null +++ b/plugins/rainlab/builder/models/LocalizationModel.php @@ -0,0 +1,439 @@ + ['required', 'regex:/^[a-z0-9\.\-]+$/i'] + ]; + + protected $originalStringArray = []; + + public function load($language) + { + $this->language = $language; + + $this->originalLanguage = $language; + + $filePath = $this->getFilePath(); + + if (!File::isFile($filePath)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.localization.error_cant_load_file')); + } + + if (!$this->validateFileContents($filePath)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.localization.error_bad_localization_file_contents')); + } + + $strings = include($filePath); + if (!is_array($strings)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.localization.error_file_not_array')); + } + + $this->originalStringArray = $strings; + + if (count($strings) > 0) { + $dumper = new YamlDumper(); + $this->strings = $dumper->dump($strings, 20, 0, false, true); + } + else { + $this->strings = ''; + } + + $this->exists = true; + } + + public static function initModel($pluginCode, $language) + { + $model = new self(); + $model->setPluginCode($pluginCode); + $model->language = $language; + + return $model; + } + + public function save() + { + $data = $this->modelToLanguageFile(); + $this->validate(); + + $filePath = File::symbolizePath($this->getFilePath()); + $isNew = $this->isNewModel(); + + if (File::isFile($filePath)) { + if ($isNew || $this->originalLanguage != $this->language) { + throw new ValidationException(['fileName' => Lang::get('rainlab.builder::lang.common.error_file_exists', ['path'=>$this->language.'/'.basename($filePath)])]); + } + } + + $fileDirectory = dirname($filePath); + if (!File::isDirectory($fileDirectory)) { + if (!File::makeDirectory($fileDirectory, 0777, true, true)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.common.error_make_dir', ['name'=>$fileDirectory])); + } + } + + if (@File::put($filePath, $data) === false) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.localization.save_error', ['name'=>$filePath])); + } + + @File::chmod($filePath); + + if (!$this->isNewModel() && strlen($this->originalLanguage) > 0 && $this->originalLanguage != $this->language) { + $this->originalFilePath = $this->getFilePath($this->originalLanguage); + @File::delete($this->originalFilePath); + } + + $this->originalLanguage = $this->language; + $this->exists = true; + } + + public function deleteModel() + { + if ($this->isNewModel()) { + throw new ApplicationException('Cannot delete language file which is not saved yet.'); + } + + $filePath = File::symbolizePath($this->getFilePath()); + if (File::isFile($filePath)) { + if (!@unlink($filePath)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.localization.error_delete_file')); + } + } + } + + public function initContent() + { + $templatePath = '$/rainlab/builder/models/localizationmodel/templates/lang.php'; + $templatePath = File::symbolizePath($templatePath); + + $strings = include($templatePath); + $dumper = new YamlDumper(); + $this->strings = $dumper->dump($strings, 20, 0, false, true); + } + + public static function listPluginLanguages($pluginCodeObj) + { + $languagesDirectoryPath = $pluginCodeObj->toPluginDirectoryPath().'/lang'; + + $languagesDirectoryPath = File::symbolizePath($languagesDirectoryPath); + + if (!File::isDirectory($languagesDirectoryPath)) { + return []; + } + + $result = []; + foreach (new DirectoryIterator($languagesDirectoryPath) as $fileInfo) { + if (!$fileInfo->isDir() || $fileInfo->isDot()) { + continue; + } + + $langFilePath = $fileInfo->getPathname().'/lang.php'; + + if (File::isFile($langFilePath)) { + $result[] = $fileInfo->getFilename(); + } + } + + return $result; + } + + public function copyStringsFrom($destinationText, $sourceLanguageCode) + { + $sourceLanguageModel = new self(); + $sourceLanguageModel->setPluginCodeObj($this->getPluginCodeObj()); + $sourceLanguageModel->load($sourceLanguageCode); + + $srcArray = $sourceLanguageModel->getOriginalStringsArray(); + + $languageMixer = new LanguageMixer(); + + return $languageMixer->addStringsFromAnotherLanguage($destinationText, $srcArray); + } + + public function getOriginalStringsArray() + { + return $this->originalStringArray; + } + + public function createStringAndSave($stringKey, $stringValue) + { + $stringKey = trim($stringKey, '.'); + + if (!strlen($stringKey)) { + throw new ValidationException(['key' => Lang::get('rainlab.builder::lang.localization.string_key_is_empty')]); + } + + if (!strlen($stringValue)) { + throw new ValidationException(['value' => Lang::get('rainlab.builder::lang.localization.string_value_is_empty')]); + } + + $originalStringArray = $this->getOriginalStringsArray(); + $languagePrefix = strtolower($this->getPluginCodeObj()->toCode()).'::lang.'; + + $existingStrings = self::convertToStringsArray($originalStringArray, $languagePrefix); + if (array_key_exists($languagePrefix.$stringKey, $existingStrings)) { + throw new ValidationException(['key' => Lang::get('rainlab.builder::lang.localization.string_key_exists')]); + } + + $existingSections = self::convertToSectionsArray($originalStringArray); + if (array_key_exists($stringKey.'.', $existingSections)) { + throw new ValidationException(['key' => Lang::get('rainlab.builder::lang.localization.string_key_exists')]); + } + + $sectionArray = []; + self::createStringSections($sectionArray, $stringKey, $stringValue) ; + + $this->checkKeyWritable($stringKey, $existingStrings, $languagePrefix); + $newStrings = LanguageMixer::arrayMergeRecursive($originalStringArray, $sectionArray); + + $dumper = new YamlDumper(); + $this->strings = $dumper->dump($newStrings, 20, 0, false, true); + + $this->save(); + + return $languagePrefix.$stringKey; + } + + public static function getDefaultLanguage() + { + $language = Config::get('app.locale'); + + if (!$language) { + throw new ApplicationException('The default language is not defined in the application configuration (app.locale).'); + } + + return $language; + } + + public static function getPluginRegistryData($pluginCode, $subtype) + { + $defaultLanguage = self::getDefaultLanguage(); + + $model = new self(); + $model->setPluginCode($pluginCode); + $model->language = $defaultLanguage; + + $filePath = $model->getFilePath(); + if (!File::isFile($filePath)) { + return []; + } + + $model->load($defaultLanguage); + + $array = $model->getOriginalStringsArray(); + $languagePrefix = strtolower($model->getPluginCodeObj()->toCode()).'::lang.'; + + if ($subtype !== 'sections') { + return self::convertToStringsArray($array, $languagePrefix); + } + + return self::convertToSectionsArray($array); + } + + public static function languageFileExists($pluginCode, $language) + { + $model = new self(); + $model->setPluginCode($pluginCode); + $model->language = $language; + + $filePath = $model->getFilePath(); + return File::isFile($filePath); + } + + protected static function createStringSections(&$arr, $path, $value) + { + $keys = explode('.', $path); + + while ($key = array_shift($keys)) { + $arr = &$arr[$key]; + } + + $arr = $value; + } + + protected static function convertToStringsArray($stringsArray, $prefix, $currentKey = '') + { + $result = []; + + foreach ($stringsArray as $key => $value) { + $newKey = strlen($currentKey) ? $currentKey.'.'.$key : $key; + + if (is_scalar($value)) { + $result[$prefix.$newKey] = $value; + } + else { + $result = array_merge($result, self::convertToStringsArray($value, $prefix, $newKey)); + } + } + + return $result; + } + + protected static function convertToSectionsArray($stringsArray, $currentKey = '') + { + $result = []; + + foreach ($stringsArray as $key => $value) { + $newKey = strlen($currentKey) ? $currentKey.'.'.$key : $key; + + if (is_scalar($value)) { + $result[$currentKey.'.'] = $currentKey.'.'; + } + else { + $result = array_merge($result, self::convertToSectionsArray($value, $newKey)); + } + } + + return $result; + } + + protected function validateLanguage($language) + { + return preg_match('/^[a-z0-9\.\-]+$/i', $language); + } + + protected function getFilePath($language = null) + { + if ($language === null) { + $language = $this->language; + } + + $language = trim($language); + + if (!strlen($language)) { + throw new SystemException('The form model language is not set.'); + } + + if (!$this->validateLanguage($language)) { + throw new SystemException('Invalid language file name: '.$language); + } + + $path = $this->getPluginCodeObj()->toPluginDirectoryPath().'/lang/'.$language.'/lang.php'; + return File::symbolizePath($path); + } + + protected function modelToLanguageFile() + { + $this->strings = trim($this->strings); + + if (!strlen($this->strings)) { + return "getSanitizedPHPStrings(Yaml::parse($this->strings)); + + $phpData = var_export($data, true); + $phpData = preg_replace('/^(\s+)\),/m', '$1],', $phpData); + $phpData = preg_replace('/^(\s+)array\s+\(/m', '$1[', $phpData); + $phpData = preg_replace_callback('/^(\s+)/m', function ($matches) { + return str_repeat($matches[1], 2); // Increase indentation + }, $phpData); + $phpData = preg_replace('/\n\s+\[/m', '[', $phpData); + $phpData = preg_replace('/^array\s\(/', '[', $phpData); + $phpData = preg_replace('/^\)\Z/m', ']', $phpData); + + return "getMessage())); + } + } + + protected function validateFileContents($path) + { + $fileContents = File::get($path); + + $stream = new PhpSourceStream($fileContents); + + $invalidTokens = [ + T_CLASS, + T_FUNCTION, + T_INCLUDE, + T_INCLUDE_ONCE, + T_REQUIRE, + T_REQUIRE_ONCE, + T_EVAL, + T_ECHO, + T_GOTO, + T_HALT_COMPILER, + T_STRING // Unescaped strings - function names, etc. + ]; + + while ($stream->forward()) { + $tokenCode = $stream->getCurrentCode(); + + if (in_array($tokenCode, $invalidTokens)) { + return false; + } + } + + return true; + } + + protected function getSanitizedPHPStrings($strings) + { + array_walk_recursive($strings, function (&$item, $key) { + if (!is_scalar($item)) { + return; + } + + // In YAML single quotes are escaped with two single quotes + // http://yaml.org/spec/current.html#id2534365 + $item = str_replace("''", "'", $item); + }); + + return $strings; + } + + protected function checkKeyWritable($stringKey, $existingStrings, $languagePrefix) + { + $sectionList = explode('.', $stringKey); + + $lastElement = array_pop($sectionList); + while (strlen($lastElement)) { + if (count($sectionList) > 0) { + $fullKey = implode('.', $sectionList).'.'.$lastElement; + } + else { + $fullKey = $lastElement; + } + + if (array_key_exists($languagePrefix.$fullKey, $existingStrings)) { + throw new ValidationException(['key' => Lang::get('rainlab.builder::lang.localization.string_key_is_a_string', ['key'=>$fullKey])]); + } + + $lastElement = array_pop($sectionList); + } + } +} diff --git a/plugins/rainlab/builder/models/MenusModel.php b/plugins/rainlab/builder/models/MenusModel.php new file mode 100644 index 0000000..1a661a6 --- /dev/null +++ b/plugins/rainlab/builder/models/MenusModel.php @@ -0,0 +1,242 @@ +menus as $mainMenuItem) { + $mainMenuItem = $this->trimMenuProperties($mainMenuItem); + + if (!isset($mainMenuItem['code'])) { + throw new ApplicationException('Cannot save menus - the main menu item code should not be empty.'); + } + + if (isset($mainMenuItem['sideMenu'])) { + $sideMenuItems = []; + + foreach ($mainMenuItem['sideMenu'] as $sideMenuItem) { + $sideMenuItem = $this->trimMenuProperties($sideMenuItem); + + if (!isset($sideMenuItem['code'])) { + throw new ApplicationException('Cannot save menus - the side menu item code should not be empty.'); + } + + $code = $sideMenuItem['code']; + unset($sideMenuItem['code']); + + $sideMenuItems[$code] = $sideMenuItem; + } + + $mainMenuItem['sideMenu'] = $sideMenuItems; + } + + $code = $mainMenuItem['code']; + unset($mainMenuItem['code']); + + $fileMenus[$code] = $mainMenuItem; + } + + return $fileMenus; + } + + /** + * validate + */ + public function validate() + { + parent::validate(); + + $this->validateDuplicateMenus(); + } + + /** + * fill + */ + public function fill(array $attributes) + { + if (!is_array($attributes['menus'])) { + $attributes['menus'] = json_decode($attributes['menus'], true); + + if ($attributes['menus'] === null) { + throw new SystemException('Cannot decode menus JSON string.'); + } + } + + return parent::fill($attributes); + } + + /** + * setPluginCodeObj + */ + public function setPluginCodeObj($pluginCodeObj) + { + $this->pluginCodeObj = $pluginCodeObj; + } + + /** + * yamlArrayToModel loads the model's data from an array. + * @param array $array An array to load the model fields from. + */ + protected function yamlArrayToModel($array) + { + $fileMenus = $array; + $menus = []; + $index = 0; + + foreach ($fileMenus as $code => $mainMenuItem) { + $mainMenuItem['code'] = $code; + + if (isset($mainMenuItem['sideMenu'])) { + $sideMenuItems = []; + + foreach ($mainMenuItem['sideMenu'] as $code => $sideMenuItem) { + $sideMenuItem['code'] = $code; + $sideMenuItems[] = $sideMenuItem; + } + + $mainMenuItem['sideMenu'] = $sideMenuItems; + } + + $menus[] = $mainMenuItem; + } + + $this->menus = $menus; + } + + /** + * trimMenuProperties + */ + protected function trimMenuProperties($menu) + { + array_walk($menu, function ($value, $key) { + if (!is_scalar($value)) { + return $value; + } + + return trim($value); + }); + + return $menu; + } + + /** + * getFilePath returns a file path to save the model to. + * @return string Returns a path. + */ + protected function getFilePath() + { + if ($this->pluginCodeObj === null) { + throw new SystemException('Error saving plugin menus model - the plugin code object is not set.'); + } + + return $this->pluginCodeObj->toPluginFilePath(); + } + + /** + * validateDuplicateMenus + */ + protected function validateDuplicateMenus() + { + foreach ($this->menus as $outerIndex => $mainMenuItem) { + $mainMenuItem = $this->trimMenuProperties($mainMenuItem); + + if (!isset($mainMenuItem['code'])) { + continue; + } + + if ($this->codeExistsInList($outerIndex, $mainMenuItem['code'], $this->menus)) { + throw new ValidationException([ + 'permissions' => Lang::get( + 'rainlab.builder::lang.menu.error_duplicate_main_menu_code', + ['code' => $mainMenuItem['code']] + ) + ]); + } + + if (isset($mainMenuItem['sideMenu'])) { + foreach ($mainMenuItem['sideMenu'] as $innerIndex => $sideMenuItem) { + $sideMenuItem = $this->trimMenuProperties($sideMenuItem); + + if (!isset($sideMenuItem['code'])) { + continue; + } + + if ($this->codeExistsInList($innerIndex, $sideMenuItem['code'], $mainMenuItem['sideMenu'])) { + throw new ValidationException([ + 'permissions' => Lang::get( + 'rainlab.builder::lang.menu.error_duplicate_side_menu_code', + ['code' => $sideMenuItem['code']] + ) + ]); + } + } + } + } + } + + /** + * codeExistsInList + */ + protected function codeExistsInList($codeIndex, $code, $list) + { + foreach ($list as $index => $item) { + if (!isset($item['code'])) { + continue; + } + + if ($index == $codeIndex) { + continue; + } + + if ($code == $item['code']) { + return true; + } + } + + return false; + } +} diff --git a/plugins/rainlab/builder/models/MigrationModel.php b/plugins/rainlab/builder/models/MigrationModel.php new file mode 100644 index 0000000..38e7aee --- /dev/null +++ b/plugins/rainlab/builder/models/MigrationModel.php @@ -0,0 +1,614 @@ + ['required', 'regex:/^[0-9]+\.[0-9]+\.[0-9]+$/', 'uniqueVersion'], + 'description' => ['required'], + 'scriptFileName' => ['regex:/^[a-z]+[a-z0-9_]+$/'] + ]; + + /** + * validate + */ + public function validate() + { + $isNewModel = $this->isNewModel(); + + $this->validationMessages = [ + 'version.regex' => Lang::get('rainlab.builder::lang.migration.error_version_invalid'), + 'version.unique_version' => Lang::get('rainlab.builder::lang.migration.error_version_exists'), + 'scriptFileName.regex' => Lang::get('rainlab.builder::lang.migration.error_script_filename_invalid') + ]; + + $versionInformation = $this->getPluginVersionInformation(); + + Validator::extend('uniqueVersion', function ($attribute, $value, $parameters) use ($versionInformation, $isNewModel) { + if ($isNewModel || $this->version != $this->originalVersion) { + return !array_key_exists($value, $versionInformation); + } + return true; + }); + + if (!$isNewModel && $this->version != $this->originalVersion && $this->isApplied()) { + throw new ValidationException([ + 'version' => Lang::get('rainlab.builder::lang.migration.error_cannot_change_version_number') + ]); + } + + return parent::validate(); + } + + /** + * getNextVersion + */ + public function getNextVersion() + { + $versionInformation = $this->getPluginVersionInformation(); + + if (!count($versionInformation)) { + return '1.0.0'; + } + + $versions = array_keys($versionInformation); + $latestVersion = end($versions); + + $versionNumbers = []; + if (!preg_match('/^([0-9]+)\.([0-9]+)\.([0-9]+)$/', $latestVersion, $versionNumbers)) { + throw new SystemException(sprintf('Cannot parse the latest plugin version number: %s.', $latestVersion)); + } + + return $versionNumbers[1].'.'.$versionNumbers[2].'.'.($versionNumbers[3]+1); + } + + /** + * save the migration and applies all outstanding migrations for the plugin. + */ + public function save($executeOnSave = true) + { + $this->validate(); + + if (!strlen($this->scriptFileName) || !$this->isNewModel()) { + $this->assignFileName(); + } + + $originalFileContents = $this->saveScriptFile(); + + try { + $originalVersionData = $this->insertOrUpdateVersion(); + } + catch (Exception $ex) { + // Remove the script file, but don't rollback + // the version.yaml. + $this->rollbackSaving(null, $originalFileContents); + + throw $ex; + } + + try { + if ($executeOnSave) { + VersionManager::instance()->updatePlugin($this->getPluginCodeObj()->toCode(), $this->version); + } + } + catch (Throwable $e) { + // Remove the script file, and rollback + // the version.yaml. + $this->rollbackSaving($originalVersionData, $originalFileContents); + + throw $e; + } + + $this->originalVersion = $this->version; + $this->exists = true; + } + + /** + * load + */ + public function load($versionNumber) + { + $versionNumber = trim($versionNumber); + + if (!strlen($versionNumber)) { + throw new ApplicationException('Cannot load the the version model - the version number should not be empty.'); + } + + $pluginVersions = $this->getPluginVersionInformation(); + if (!array_key_exists($versionNumber, $pluginVersions)) { + throw new ApplicationException('The requested version does not exist in the version information file.'); + } + + $this->version = $versionNumber; + $this->originalVersion = $this->version; + $this->exists = true; + + $versionInformation = $pluginVersions[$versionNumber]; + if (!is_array($versionInformation)) { + $this->description = $versionInformation; + } + else { + $cnt = count($versionInformation); + + if ($cnt > 2) { + throw new ApplicationException('The requested version cannot be edited with Builder as it refers to multiple PHP scripts.'); + } + + if ($cnt > 0) { + $this->description = $versionInformation[0]; + } + + if ($cnt > 1) { + $this->scriptFileName = pathinfo(trim($versionInformation[1]), PATHINFO_FILENAME); + $this->code = $this->loadScriptFile(); + } + } + + $this->originalScriptFileName = $this->scriptFileName; + } + + /** + * initVersion + */ + public function initVersion($versionType) + { + $versionTypes = ['migration', 'seeder', 'custom']; + + if (!in_array($versionType, $versionTypes)) { + throw new SystemException('Unknown version type.'); + } + + $this->version = $this->getNextVersion(); + + if ($versionType == 'custom') { + $this->scriptFileName = null; + return; + } + + $templateFiles = [ + 'migration' => 'migration.php.tpl', + 'seeder' => 'seeder.php.tpl' + ]; + + $templatePath = '$/rainlab/builder/models/migrationmodel/templates/'.$templateFiles[$versionType]; + $templatePath = File::symbolizePath($templatePath); + + $fileContents = File::get($templatePath); + $scriptFileName = $versionType.str_replace('.', '-', $this->version); + + $pluginCodeObj = $this->getPluginCodeObj(); + $this->code = TextParser::parse($fileContents, [ + 'className' => Str::studly($scriptFileName), + 'namespace' => $pluginCodeObj->toUpdatesNamespace(), + 'tableNamePrefix' => $pluginCodeObj->toDatabasePrefix() + ]); + + $this->scriptFileName = $scriptFileName; + } + + /** + * makeScriptFileNameUnique + */ + public function makeScriptFileNameUnique() + { + $updatesPath = $this->getPluginUpdatesPath(); + $baseFileName = $fileName = $this->scriptFileName; + + $counter = 2; + while (File::isFile($updatesPath.'/'.$fileName.'.php')) { + $fileName = $baseFileName.'_'.$counter; + $counter++; + } + + return $this->scriptFileName = $fileName; + } + + /** + * deleteModel + */ + public function deleteModel() + { + if ($this->isApplied()) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.migration.error_cant_delete_applied')); + } + + $this->deleteVersion(); + $this->removeScriptFile(); + } + + /** + * isApplied + */ + public function isApplied() + { + if ($this->isNewModel()) { + return false; + } + + $versionManager = VersionManager::instance(); + $unappliedVersions = $versionManager->listNewVersions($this->pluginCodeObj->toCode()); + + return !array_key_exists($this->originalVersion, $unappliedVersions); + } + + /** + * apply + */ + public function apply() + { + if ($this->isApplied()) { + return; + } + + $versionManager = VersionManager::instance(); + $versionManager->updatePlugin($this->pluginCodeObj->toCode(), $this->version); + } + + /** + * rollback + */ + public function rollback() + { + if (!$this->isApplied()) { + return; + } + + $versionManager = VersionManager::instance(); + $versionManager->removePlugin($this->pluginCodeObj->toCode(), $this->version); + } + + /** + * assignFileName + */ + protected function assignFileName() + { + $code = trim($this->code); + + if (!strlen($code)) { + $this->scriptFileName = null; + return; + } + + /* + * The file name is based on the migration class name. + */ + $parser = new MigrationFileParser(); + $migrationInfo = $parser->extractMigrationInfoFromSource($code); + + if (!$migrationInfo || !array_key_exists('class', $migrationInfo)) { + throw new ValidationException([ + 'code' => Lang::get('rainlab.builder::lang.migration.error_file_must_define_class') + ]); + } + + if (!array_key_exists('namespace', $migrationInfo)) { + throw new ValidationException([ + 'code' => Lang::get('rainlab.builder::lang.migration.error_file_must_define_namespace') + ]); + } + + $pluginCodeObj = $this->getPluginCodeObj(); + $pluginNamespace = $pluginCodeObj->toUpdatesNamespace(); + + if ($migrationInfo['namespace'] != $pluginNamespace) { + throw new ValidationException([ + 'code' => Lang::get('rainlab.builder::lang.migration.error_namespace_mismatch', ['namespace'=>$pluginNamespace]) + ]); + } + + $this->scriptFileName = $this->makeScriptFileName($migrationInfo['class']); + + /* + * Validate that a file with the generated name does not exist yet. + */ + if ($this->scriptFileName != $this->originalScriptFileName) { + $fileName = $this->scriptFileName.'.php'; + $filePath = $this->getPluginUpdatesPath($fileName); + + if (File::isFile($filePath)) { + throw new ValidationException([ + 'code' => Lang::get('rainlab.builder::lang.migration.error_migration_file_exists', ['file'=>$fileName]) + ]); + } + } + } + + /** + * saveScriptFile + */ + protected function saveScriptFile() + { + $originalFileContents = $this->getOriginalFileContents(); + + if (strlen($this->scriptFileName)) { + $scriptFilePath = $this->getPluginUpdatesPath($this->scriptFileName.'.php'); + + if (!File::put($scriptFilePath, $this->code)) { + throw new SystemException(sprintf('Error saving file %s', $scriptFilePath)); + } + + @File::chmod($scriptFilePath); + } + + if (strlen($this->originalScriptFileName) && $this->scriptFileName != $this->originalScriptFileName) { + $originalScriptFilePath = $this->getPluginUpdatesPath($this->originalScriptFileName.'.php'); + if (File::isFile($originalScriptFilePath)) { + @unlink($originalScriptFilePath); + } + } + + return $originalFileContents; + } + + /** + * getOriginalFileContents + */ + protected function getOriginalFileContents() + { + if (!strlen($this->originalScriptFileName)) { + return null; + } + + $scriptFilePath = $this->getPluginUpdatesPath($this->originalScriptFileName.'.php'); + if (File::isFile($scriptFilePath)) { + return File::get($scriptFilePath); + } + } + + /** + * loadScriptFile + */ + protected function loadScriptFile() + { + $scriptFilePath = $this->getPluginUpdatesPath($this->scriptFileName.'.php'); + + if (!File::isFile($scriptFilePath)) { + throw new ApplicationException(sprintf('Version file %s is not found.', $scriptFilePath)); + } + + return File::get($scriptFilePath); + } + + /** + * removeScriptFile + */ + protected function removeScriptFile() + { + $scriptFilePath = $this->getPluginUpdatesPath($this->scriptFileName.'.php'); + + // Using unlink instead of File::remove() is safer here. + @unlink($scriptFilePath); + } + + /** + * rollbackScriptFile + */ + protected function rollbackScriptFile($fileContents) + { + $scriptFilePath = $this->getPluginUpdatesPath($this->originalScriptFileName.'.php'); + + @File::put($scriptFilePath, $fileContents); + + if ($this->scriptFileName != $this->originalScriptFileName) { + $scriptFilePath = $this->getPluginUpdatesPath($this->scriptFileName.'.php'); + @unlink($scriptFilePath); + } + } + + /** + * rollbackSaving + */ + protected function rollbackSaving($originalVersionData, $originalScriptFileContents) + { + if ($originalVersionData) { + $this->rollbackVersionFile($originalVersionData); + } + + if ($this->isNewModel()) { + $this->removeScriptFile(); + } + else { + $this->rollbackScriptFile($originalScriptFileContents); + } + } + + /** + * insertOrUpdateVersion + */ + protected function insertOrUpdateVersion() + { + $versionFilePath = $this->getPluginUpdatesPath('version.yaml'); + + $versionInformation = $this->getPluginVersionInformation(); + if (!$versionInformation) { + $versionInformation = []; + } + + $originalFileContents = File::get($versionFilePath); + if (!$originalFileContents) { + throw new SystemException(sprintf('Error loading file %s', $versionFilePath)); + } + + $versionInformation[$this->version] = [ + $this->description + ]; + + if (strlen($this->scriptFileName)) { + $versionInformation[$this->version][] = $this->scriptFileName.'.php'; + } + + if (!$this->isNewModel() && $this->version != $this->originalVersion) { + if (array_key_exists($this->originalVersion, $versionInformation)) { + unset($versionInformation[$this->originalVersion]); + } + } + + // Add "v" to the version information + $versionInformation = $this->normalizeVersions((array) $versionInformation); + + $yamlData = Yaml::render($versionInformation); + + if (!File::put($versionFilePath, $yamlData)) { + throw new SystemException(sprintf('Error saving file %s', $versionFilePath)); + } + + @File::chmod($versionFilePath); + + return $originalFileContents; + } + + /** + * deleteVersion + */ + protected function deleteVersion() + { + $versionInformation = $this->getPluginVersionInformation(); + if (!$versionInformation) { + $versionInformation = []; + } + + if (array_key_exists($this->version, $versionInformation)) { + unset($versionInformation[$this->version]); + } + + $versionFilePath = $this->getPluginUpdatesPath('version.yaml'); + $yamlData = Yaml::render($versionInformation); + + if (!File::put($versionFilePath, $yamlData)) { + throw new SystemException(sprintf('Error saving file %s', $versionFilePath)); + } + + @File::chmod($versionFilePath); + } + + /** + * rollbackVersionFile + */ + protected function rollbackVersionFile($fileData) + { + $versionFilePath = $this->getPluginUpdatesPath('version.yaml'); + File::put($versionFilePath, $fileData); + } + + /** + * getPluginUpdatesPath + */ + protected function getPluginUpdatesPath($fileName = null) + { + $pluginCodeObj = $this->getPluginCodeObj(); + + $filePath = '$/'.$pluginCodeObj->toFilesystemPath().'/updates'; + $filePath = File::symbolizePath($filePath); + + if ($fileName !== null) { + return $filePath .= '/'.$fileName; + } + + return $filePath; + } + + /** + * getPluginVersionInformation + */ + protected function getPluginVersionInformation() + { + $versionObj = new PluginVersion; + return $versionObj->getPluginVersionInformation($this->getPluginCodeObj()); + } + + /** + * makeScriptFileName will ensure the last digit in the script contains an underscore, + * for consistency with other areas. + * + * eg: Some123Script3 → Some123Script_3 + */ + protected function makeScriptFileName($value): string + { + $value = Str::snake($value); + + $value = preg_replace_callback('/[0-9]+$/u', function ($match) { + $numericSuffix = $match[0]; + + return '_' . $numericSuffix; + }, $value); + + return $value; + } + + /** + * normalizeVersions checks some versions start with v and others not + */ + protected function normalizeVersions(array $versions): array + { + $result = []; + foreach ($versions as $key => $value) { + $version = rtrim(ltrim((string) $key, 'v'), '.'); + $result['v'.$version] = $value; + } + return $result; + } +} diff --git a/plugins/rainlab/builder/models/ModelFilterModel.php b/plugins/rainlab/builder/models/ModelFilterModel.php new file mode 100644 index 0000000..a641d6c --- /dev/null +++ b/plugins/rainlab/builder/models/ModelFilterModel.php @@ -0,0 +1,213 @@ + ['required', 'regex:/^[a-z0-9\.\-_]+$/i'] + ]; + + /** + * loadForm + */ + public function loadForm($path) + { + $this->fileName = $path; + + return parent::load($this->getFilePath()); + } + + /** + * fill + */ + public function fill(array $attributes) + { + if (!is_array($attributes['scopes'])) { + $attributes['scopes'] = json_decode($attributes['scopes'], true); + + if ($attributes['scopes'] === null) { + throw new SystemException('Cannot decode scopes JSON string.'); + } + } + + return parent::fill($attributes); + } + + /** + * validateFileIsModelType + */ + public static function validateFileIsModelType($fileContentsArray) + { + $modelRootNodes = [ + 'scopes' + ]; + + foreach ($modelRootNodes as $node) { + if (array_key_exists($node, $fileContentsArray)) { + return true; + } + } + + return false; + } + + /** + * validate + */ + public function validate() + { + parent::validate(); + + $this->validateDuplicateScopes(); + + if (!$this->scopes) { + throw new ValidationException(['scopes' => 'Please create at least one scope.']); + } + } + + /** + * initDefaults + */ + public function initDefaults() + { + $this->fileName = 'scopes.yaml'; + } + + /** + * validateDuplicateScopes + */ + protected function validateDuplicateScopes() + { + foreach ($this->scopes as $outerIndex => $outerScope) { + foreach ($this->scopes as $innerIndex => $innerScope) { + if ($innerIndex != $outerIndex && $innerScope['field'] == $outerScope['field']) { + throw new ValidationException([ + 'scopes' => Lang::get( + 'rainlab.builder::lang.list.error_duplicate_scope', + ['scope' => $outerScope['field']] + ) + ]); + } + } + } + } + + /** + * modelToYamlArray converts the model's data to an array before it's saved to a YAML file. + * @return array + */ + protected function modelToYamlArray() + { + $fileScopes = []; + + foreach ($this->scopes as $scope) { + if (!isset($scope['field'])) { + throw new ApplicationException('Cannot save the list - the scope field name should not be empty.'); + } + + $scopeName = $scope['field']; + unset($scope['field']); + + if (array_key_exists('id', $scope)) { + unset($scope['id']); + } + + $scope = $this->preprocessScopeDataBeforeSave($scope); + + $fileScopes[$scopeName] = $scope; + } + + return [ + 'scopes'=>$fileScopes + ]; + } + + /** + * yamlArrayToModel loads the model's data from an array. + * @param array $array An array to load the model fields from. + */ + protected function yamlArrayToModel($array) + { + $fileScopes = $array['scopes']; + $scopes = []; + $index = 0; + + foreach ($fileScopes as $scopeName => $scope) { + if (!is_array($scope)) { + // Handle the case when a scope is defined as + // scope: Title + $scope = [ + 'label' => $scope + ]; + } + + $scope['id'] = $index; + $scope['field'] = $scopeName; + + $scopes[] = $scope; + + $index++; + } + + $this->scopes = $scopes; + } + + /** + * preprocessScopeDataBeforeSave + */ + protected function preprocessScopeDataBeforeSave($scope) + { + // Filter empty values + $scope = array_filter($scope, function ($value) { + return !is_array($value) && strlen($value) > 0; + }); + + // Cast booleans + $booleanFields = []; + + foreach ($booleanFields as $booleanField) { + if (!array_key_exists($booleanField, $scope)) { + continue; + } + + $value = $scope[$booleanField]; + if ($value == '1' || $value == 'true') { + $value = true; + } + else { + $value = false; + } + + + $scope[$booleanField] = $value; + } + + return $scope; + } +} diff --git a/plugins/rainlab/builder/models/ModelFormModel.php b/plugins/rainlab/builder/models/ModelFormModel.php new file mode 100644 index 0000000..d792f39 --- /dev/null +++ b/plugins/rainlab/builder/models/ModelFormModel.php @@ -0,0 +1,124 @@ + ['required', 'regex:/^[a-z0-9\.\-_]+$/i'] + ]; + + /** + * loadForm + */ + public function loadForm($path) + { + $this->fileName = $path; + + return parent::load($this->getFilePath()); + } + + /** + * fill + */ + public function fill(array $attributes) + { + if (!is_array($attributes['controls'])) { + $attributes['controls'] = json_decode($attributes['controls'], true); + + if ($attributes['controls'] === null) { + throw new SystemException('Cannot decode controls JSON string.'); + } + } + + return parent::fill($attributes); + } + + /** + * validateFileIsModelType + */ + public static function validateFileIsModelType($fileContentsArray) + { + $modelRootNodes = [ + 'fields', + 'tabs', + 'secondaryTabs' + ]; + + foreach ($modelRootNodes as $node) { + if (array_key_exists($node, $fileContentsArray)) { + return true; + } + } + + return false; + } + + /** + * validate + */ + public function validate() + { + parent::validate(); + + if (!$this->controls) { + throw new ValidationException(['controls' => 'Please create at least one field.']); + } + } + + /** + * initDefaults + */ + public function initDefaults() + { + $this->fileName = 'fields.yaml'; + } + + /** + * modelToYamlArray converts the model's data to an array before it's saved to a YAML file. + * @return array + */ + protected function modelToYamlArray() + { + return array_merge((array) $this->originals, $this->controls); + } + + /** + * yamlArrayToModel loads the model's data from an array. + * @param array $array An array to load the model fields from. + */ + protected function yamlArrayToModel($array) + { + $this->originals = array_except($array, 'fields'); + + $this->controls = $array; + } +} diff --git a/plugins/rainlab/builder/models/ModelListModel.php b/plugins/rainlab/builder/models/ModelListModel.php new file mode 100644 index 0000000..c119702 --- /dev/null +++ b/plugins/rainlab/builder/models/ModelListModel.php @@ -0,0 +1,217 @@ + ['required', 'regex:/^[a-z0-9\.\-_]+$/i'] + ]; + + /** + * loadForm + */ + public function loadForm($path) + { + $this->fileName = $path; + + return parent::load($this->getFilePath()); + } + + /** + * fill + */ + public function fill(array $attributes) + { + if (!is_array($attributes['columns'])) { + $attributes['columns'] = json_decode($attributes['columns'], true); + + if ($attributes['columns'] === null) { + throw new SystemException('Cannot decode columns JSON string.'); + } + } + + return parent::fill($attributes); + } + + /** + * validateFileIsModelType + */ + public static function validateFileIsModelType($fileContentsArray) + { + $modelRootNodes = [ + 'columns' + ]; + + foreach ($modelRootNodes as $node) { + if (array_key_exists($node, $fileContentsArray)) { + return true; + } + } + + return false; + } + + /** + * validate + */ + public function validate() + { + parent::validate(); + + $this->validateDuplicateColumns(); + + if (!$this->columns) { + throw new ValidationException(['columns' => 'Please create at least one column.']); + } + } + + /** + * initDefaults + */ + public function initDefaults() + { + $this->fileName = 'columns.yaml'; + } + + /** + * validateDuplicateColumns + */ + protected function validateDuplicateColumns() + { + foreach ($this->columns as $outerIndex => $outerColumn) { + foreach ($this->columns as $innerIndex => $innerColumn) { + if ($innerIndex != $outerIndex && $innerColumn['field'] == $outerColumn['field']) { + throw new ValidationException([ + 'columns' => Lang::get( + 'rainlab.builder::lang.list.error_duplicate_column', + ['column' => $outerColumn['field']] + ) + ]); + } + } + } + } + + /** + * Converts the model's data to an array before it's saved to a YAML file. + * @return array + */ + protected function modelToYamlArray() + { + $fileColumns = []; + + foreach ($this->columns as $column) { + if (!isset($column['field'])) { + throw new ApplicationException('Cannot save the list - the column field name should not be empty.'); + } + + $columnName = $column['field']; + unset($column['field']); + + if (array_key_exists('id', $column)) { + unset($column['id']); + } + + $column = $this->preprocessColumnDataBeforeSave($column); + + $fileColumns[$columnName] = $column; + } + + return [ + 'columns'=>$fileColumns + ]; + } + + /** + * Load the model's data from an array. + * @param array $array An array to load the model fields from. + */ + protected function yamlArrayToModel($array) + { + $fileColumns = $array['columns']; + $columns = []; + $index = 0; + + foreach ($fileColumns as $columnName => $column) { + if (!is_array($column)) { + // Handle the case when a column is defined as + // column: Title + $column = [ + 'label' => $column + ]; + } + + $column['id'] = $index; + $column['field'] = $columnName; + + $columns[] = $column; + + $index++; + } + + $this->columns = $columns; + } + + /** + * preprocessColumnDataBeforeSave + */ + protected function preprocessColumnDataBeforeSave($column) + { + // Filter empty values, if not array + $column = array_filter($column, function ($value) { + return !is_array($value) && strlen($value) > 0; + }); + + // Cast booleans + $booleanFields = [ + 'searchable', + 'invisible', + 'sortable' + ]; + + foreach ($booleanFields as $booleanField) { + if (!array_key_exists($booleanField, $column)) { + continue; + } + + $value = $column[$booleanField]; + if ($value == '1' || $value == 'true') { + $value = true; + } + else { + $value = false; + } + + + $column[$booleanField] = $value; + } + + return $column; + } +} diff --git a/plugins/rainlab/builder/models/ModelModel.php b/plugins/rainlab/builder/models/ModelModel.php new file mode 100644 index 0000000..34bc47a --- /dev/null +++ b/plugins/rainlab/builder/models/ModelModel.php @@ -0,0 +1,500 @@ + ['required', 'regex:' . self::UNQUALIFIED_CLASS_NAME_PATTERN, 'uniqModelName'], + 'databaseTable' => ['required'], + 'addTimestamps' => ['timestampColumnsMustExist'], + 'addSoftDeleting' => ['deletedAtColumnMustExist'] + ]; + + /** + * listPluginModels + */ + public static function listPluginModels($pluginCodeObj) + { + $modelsDirectoryPath = $pluginCodeObj->toPluginDirectoryPath().'/models'; + $pluginNamespace = $pluginCodeObj->toPluginNamespace(); + + $modelsDirectoryPath = File::symbolizePath($modelsDirectoryPath); + if (!File::isDirectory($modelsDirectoryPath)) { + return []; + } + + $parser = new ModelFileParser(); + $result = []; + foreach (new DirectoryIterator($modelsDirectoryPath) as $fileInfo) { + if (!$fileInfo->isFile()) { + continue; + } + + if ($fileInfo->getExtension() != 'php') { + continue; + } + + $filePath = $fileInfo->getPathname(); + $contents = File::get($filePath); + + $modelInfo = $parser->extractModelInfoFromSource($contents); + if (!$modelInfo) { + continue; + } + + if (!Str::startsWith($modelInfo['namespace'], $pluginNamespace.'\\')) { + continue; + } + + $model = new ModelModel(); + $model->className = $modelInfo['class']; + $model->databaseTable = isset($modelInfo['table']) ? $modelInfo['table'] : null; + + $result[] = $model; + } + + return $result; + } + + /** + * save + */ + public function save() + { + $this->validate(); + + $modelFilePath = $this->getFilePath(); + $namespace = $this->getPluginCodeObj()->toPluginNamespace().'\\Models'; + $templateFile = $this->baseClassName === \System\Models\SettingModel::class + ? 'settingmodel.php.tpl' + : 'model.php.tpl'; + + $structure = [ + $modelFilePath => $templateFile + ]; + + $variables = [ + 'namespace' => $namespace, + 'classname' => $this->className, + 'baseclass' => $this->baseClassName, + 'baseclassname' => class_basename($this->baseClassName), + 'table' => $this->databaseTable + ]; + + $generator = new FilesystemGenerator('$', $structure, '$/rainlab/builder/models/modelmodel/templates'); + $generator->setVariables($variables); + + // Trait contents + if ($this->addSoftDeleting) { + $this->traits[] = \October\Rain\Database\Traits\SoftDelete::class; + } + + usort($this->traits, function($a, $b) { return strlen($a) > strlen($b); }); + + $traitContents = []; + foreach ($this->traits as $trait) { + $traitContents[] = " use \\{$trait};"; + } + $generator->setVariable('traitContents', implode(PHP_EOL, $traitContents)); + + // Dynamic contents + $dynamicContents = []; + + if ($this->addSoftDeleting) { + $dynamicContents[] = $generator->getTemplateContents('soft-delete.php.tpl'); + } + + if (!$this->addTimestamps) { + $dynamicContents[] = $generator->getTemplateContents('no-timestamps.php.tpl'); + } + + $dynamicContents = array_merge($dynamicContents, (array) $this->injectedRawContents); + + $generator->setVariable('dynamicContents', implode('', $dynamicContents)); + + // Validation contents + $validationDefinitions = (array) $this->validationDefinitions; + foreach ($validationDefinitions as $type => &$definitions) { + foreach ($definitions as $field => &$rule) { + // Cannot process anything other than string at this time + if (!is_string($rule)) { + unset($definitions[$field]); + } + } + } + + $validationTemplate = File::get(__DIR__.'/modelmodel/templates/validation-definitions.php.tpl'); + + $validationContents = Twig::parse($validationTemplate, ['validation' => $validationDefinitions]); + + $generator->setVariable('validationContents', $validationContents); + + // Relation contents + $relationContents = []; + + $relationTemplate = File::get(__DIR__.'/modelmodel/templates/relation-definitions.php.tpl'); + + foreach ((array) $this->relationDefinitions as $relationType => $definitions) { + if (!$definitions) { + continue; + } + + $relationVars = [ + 'relationType' => $relationType, + 'relations' => [], + ]; + + foreach ($definitions as $relationName => $definition) { + $definition = (array) $definition; + $modelClass = array_shift($definition); + + $props = $definition; + foreach ($props as &$prop) { + $prop = var_export($prop, true); + } + + $relationVars['relations'][$relationName] = [ + 'class' => $modelClass, + 'props' => $props + ]; + } + + $relationContents[] = Twig::parse($relationTemplate, $relationVars); + } + + $generator->setVariable('relationContents', implode(PHP_EOL, $relationContents)); + + // Multisite contents + $multisiteTemplate = File::get(__DIR__.'/modelmodel/templates/multisite-definitions.php.tpl'); + + $multisiteContents = Twig::parse($multisiteTemplate, ['multisite' => $this->multisiteDefinition]); + + $generator->setVariable('multisiteContents', $multisiteContents); + + $generator->generate(); + } + + /** + * validate + */ + public function validate() + { + $path = File::symbolizePath('$/'.$this->getFilePath()); + + $this->validationMessages = [ + 'className.uniq_model_name' => Lang::get('rainlab.builder::lang.model.error_class_name_exists', ['path'=>$path]), + 'addTimestamps.timestamp_columns_must_exist' => Lang::get('rainlab.builder::lang.model.error_timestamp_columns_must_exist'), + 'addSoftDeleting.deleted_at_column_must_exist' => Lang::get('rainlab.builder::lang.model.error_deleted_at_column_must_exist') + ]; + + Validator::extend('uniqModelName', function ($attribute, $value, $parameters) use ($path) { + $value = trim($value); + + if (!$this->isNewModel()) { + // Editing models is not supported at the moment, + // so no validation is required. + return true; + } + + return !File::isFile($path); + }); + + $columns = $this->isNewModel() ? Schema::getColumnListing($this->databaseTable) : []; + Validator::extend('timestampColumnsMustExist', function ($attribute, $value, $parameters) use ($columns) { + return $this->validateColumnsExist($value, $columns, ['created_at', 'updated_at']); + }); + + Validator::extend('deletedAtColumnMustExist', function ($attribute, $value, $parameters) use ($columns) { + return $this->validateColumnsExist($value, $columns, ['deleted_at']); + }); + + if ($this->skipDbValidation) { + unset( + $this->validationRules['addTimestamps'], + $this->validationRules['addSoftDeleting'] + ); + } + + parent::validate(); + } + + /** + * addRawContentToModel + */ + public function addRawContentToModel($content) + { + $this->injectedRawContents[] = $content; + } + + /** + * getDatabaseTableOptions + */ + public function getDatabaseTableOptions() + { + $pluginCode = $this->getPluginCodeObj()->toCode(); + + $tables = DatabaseTableModel::listPluginTables($pluginCode); + return array_combine($tables, $tables); + } + + /** + * getTableNameFromModelClass + */ + private static function getTableNameFromModelClass($pluginCodeObj, $modelClassName) + { + if (!self::validateModelClassName($modelClassName)) { + throw new SystemException('Invalid model class name: '.$modelClassName); + } + + $modelsDirectoryPath = File::symbolizePath($pluginCodeObj->toPluginDirectoryPath().'/models'); + if (!File::isDirectory($modelsDirectoryPath)) { + return ''; + } + + $modelFilePath = $modelsDirectoryPath.'/'.$modelClassName.'.php'; + if (!File::isFile($modelFilePath)) { + return ''; + } + + $parser = new ModelFileParser(); + $modelInfo = $parser->extractModelInfoFromSource(File::get($modelFilePath)); + if (!$modelInfo || !isset($modelInfo['table'])) { + return ''; + } + + return $modelInfo['table']; + } + + /** + * getModelFields + */ + public static function getModelFields($pluginCodeObj, $modelClassName) + { + $tableName = self::getTableNameFromModelClass($pluginCodeObj, $modelClassName); + + // Currently we return only table columns, + // but eventually we might want to return relations as well. + + return Schema::getColumnListing($tableName); + } + + /** + * getModelColumnsAndTypes + */ + public static function getModelColumnsAndTypes($pluginCodeObj, $modelClassName) + { + $tableName = self::getTableNameFromModelClass($pluginCodeObj, $modelClassName); + + if (!DatabaseTableModel::tableExists($tableName)) { + throw new ApplicationException('Database table not found: '.$tableName); + } + + $schema = DatabaseTableModel::getSchema(); + $tableInfo = $schema->getTable($tableName); + + $columns = $tableInfo->getColumns(); + $result = []; + foreach ($columns as $column) { + $columnName = $column->getName(); + $typeName = $column->getType()->getName(); + + if ($typeName == EnumDbType::TYPENAME) { + continue; + } + + $item = [ + 'name' => $columnName, + 'type' => MigrationColumnType::toMigrationMethodName($typeName, $columnName) + ]; + + $result[] = $item; + } + + return $result; + } + + /** + * getPluginRegistryData + */ + public static function getPluginRegistryData($pluginCode, $subtype) + { + $pluginCodeObj = new PluginCode($pluginCode); + + $models = self::listPluginModels($pluginCodeObj); + $result = []; + foreach ($models as $model) { + $fullClassName = $pluginCodeObj->toPluginNamespace().'\\Models\\'.$model->className; + + $result[$fullClassName] = $model->className; + } + + return $result; + } + + /** + * getPluginRegistryDataColumns + */ + public static function getPluginRegistryDataColumns($pluginCode, $modelClassName) + { + $classParts = explode('\\', $modelClassName); + if (!$classParts) { + return []; + } + + $modelClassName = array_pop($classParts); + + if (!self::validateModelClassName($modelClassName)) { + return []; + } + + $pluginCodeObj = new PluginCode($pluginCode); + $columnNames = self::getModelFields($pluginCodeObj, $modelClassName); + + $result = []; + foreach ($columnNames as $columnName) { + $result[$columnName] = $columnName; + } + + return $result; + } + + /** + * validateModelClassName + */ + public static function validateModelClassName($modelClassName) + { + return class_exists($modelClassName) || !!preg_match(self::UNQUALIFIED_CLASS_NAME_PATTERN, $modelClassName); + } + + /** + * getModelFilePath + */ + public function getModelFilePath() + { + return File::symbolizePath($this->getPluginCodeObj()->toPluginDirectoryPath().'/models/'.$this->className.'.php'); + } + + /** + * getFilePath + */ + protected function getFilePath() + { + return $this->getPluginCodeObj()->toFilesystemPath().'/models/'.$this->className.'.php'; + } + + /** + * validateColumnsExist + */ + protected function validateColumnsExist($value, $columns, $columnsToCheck) + { + if (!strlen(trim($this->databaseTable))) { + return true; + } + + if (!$this->isNewModel()) { + // Editing models is not supported at the moment, + // so no validation is required. + return true; + } + + if (!$value) { + return true; + } + + return count(array_intersect($columnsToCheck, $columns)) == count($columnsToCheck); + } +} diff --git a/plugins/rainlab/builder/models/ModelYamlModel.php b/plugins/rainlab/builder/models/ModelYamlModel.php new file mode 100644 index 0000000..c554b68 --- /dev/null +++ b/plugins/rainlab/builder/models/ModelYamlModel.php @@ -0,0 +1,250 @@ +fileName)) { + $this->fileName = $this->addExtension($this->fileName); + } + } + + /** + * setModelClassName + */ + public function setModelClassName($className) + { + if (!preg_match('/^[a-zA-Z]+[0-9a-z\_]*$/', $className)) { + throw new SystemException('Invalid class name: '.$className); + } + + $this->modelClassName = $className; + } + + /** + * validate + */ + public function validate() + { + $this->validationMessages = [ + 'fileName.required' => Lang::get('rainlab.builder::lang.form.error_file_name_required'), + 'fileName.regex' => Lang::get('rainlab.builder::lang.form.error_file_name_invalid') + ]; + + return parent::validate(); + } + + /** + * getDisplayName returns a string suitable for displaying in the Builder UI tabs. + */ + public function getDisplayName($nameFallback) + { + $fileName = $this->fileName; + + if (substr($fileName, -5) == '.yaml') { + $fileName = substr($fileName, 0, -5); + } + + if (!strlen($fileName)) { + $fileName = $nameFallback; + } + + return $this->getModelClassName().'/'.$fileName; + } + + /** + * listModelFiles + */ + public static function listModelFiles($pluginCodeObj, $modelClassName) + { + if (!self::validateModelClassName($modelClassName)) { + throw new SystemException('Invalid model class name: '.$modelClassName); + } + + $modelDirectoryPath = $pluginCodeObj->toPluginDirectoryPath().'/models/'.strtolower($modelClassName); + + $modelDirectoryPath = File::symbolizePath($modelDirectoryPath); + + if (!File::isDirectory($modelDirectoryPath)) { + return []; + } + + $result = []; + foreach (new DirectoryIterator($modelDirectoryPath) as $fileInfo) { + if (!$fileInfo->isFile() || $fileInfo->getExtension() != 'yaml') { + continue; + } + + try { + $fileContents = Yaml::parseFile($fileInfo->getPathname()); + } + catch (Exception $ex) { + continue; + } + + if (!is_array($fileContents)) { + $fileContents = []; + } + + if (!static::validateFileIsModelType($fileContents)) { + continue; + } + + $result[] = $fileInfo->getBasename(); + } + + return $result; + } + + /** + * getPluginRegistryData + */ + public static function getPluginRegistryData($pluginCode, $modelClassName) + { + $pluginCodeObj = new PluginCode($pluginCode); + + $classParts = explode('\\', $modelClassName); + if (!$classParts) { + return []; + } + + $modelClassName = array_pop($classParts); + + if (!self::validateModelClassName($modelClassName)) { + return []; + } + + $models = self::listModelFiles($pluginCodeObj, $modelClassName); + $modelDirectoryPath = $pluginCodeObj->toPluginDirectoryPath().'/models/'.strtolower($modelClassName).'/'; + + $result = []; + foreach ($models as $fileName) { + $fullFilePath = $modelDirectoryPath.$fileName; + + $result[$fullFilePath] = $fileName; + } + + return $result; + } + + /** + * getPluginRegistryDataAllRecords + */ + public static function getPluginRegistryDataAllRecords($pluginCode) + { + $pluginCodeObj = new PluginCode($pluginCode); + $pluginDirectoryPath = $pluginCodeObj->toPluginDirectoryPath(); + + $models = ModelModel::listPluginModels($pluginCodeObj); + $result = []; + foreach ($models as $model) { + $modelRecords = self::listModelFiles($pluginCodeObj, $model->className); + $modelDirectoryPath = $pluginDirectoryPath.'/models/'.strtolower($model->className).'/'; + + foreach ($modelRecords as $fileName) { + $label = $model->className.'/'.$fileName; + $key = $modelDirectoryPath.$fileName; + + $result[$key] = $label; + } + } + + return $result; + } + + /** + * validateFileIsModelType + */ + public static function validateFileIsModelType($fileContentsArray) + { + return false; + } + + /** + * validateModelClassName + */ + protected static function validateModelClassName($modelClassName) + { + return preg_match('/^[A-Z]+[a-zA-Z0-9_]+$/i', $modelClassName); + } + + /** + * getModelClassName + */ + protected function getModelClassName() + { + if ($this->modelClassName === null) { + throw new SystemException('The model class name is not set.'); + } + + return $this->modelClassName; + } + + /** + * getYamlFilePath + */ + public function getYamlFilePath() + { + $fileName = $this->addExtension(trim($this->fileName)); + + return File::symbolizePath($this->getPluginCodeObj()->toPluginDirectoryPath().'/models/'.strtolower($this->getModelClassName()).'/'.$fileName); + } + + /** + * getFilePath returns a file path to save the model to. + * @return string Returns a path. + */ + protected function getFilePath() + { + $fileName = trim($this->fileName); + if (!strlen($fileName)) { + throw new SystemException('The form model file name is not set.'); + } + + $fileName = $this->addExtension($fileName); + + return $this->getPluginCodeObj()->toPluginDirectoryPath().'/models/'.strtolower($this->getModelClassName()).'/'.$fileName; + } + + /** + * addExtension + */ + protected function addExtension($fileName) + { + if (substr($fileName, -5) !== '.yaml') { + $fileName .= '.yaml'; + } + + return $fileName; + } +} diff --git a/plugins/rainlab/builder/models/PermissionsModel.php b/plugins/rainlab/builder/models/PermissionsModel.php new file mode 100644 index 0000000..6a6f551 --- /dev/null +++ b/plugins/rainlab/builder/models/PermissionsModel.php @@ -0,0 +1,234 @@ +pluginCodeObj = $pluginCodeObj; + } + + /** + * modelToYamlArray converts the model's data to an array before it's saved to a YAML file. + * @return array + */ + protected function modelToYamlArray() + { + $filePermissions = []; + + foreach ($this->permissions as $permission) { + if (array_key_exists('id', $permission)) { + unset($permission['id']); + } + + $permission = $this->trimPermissionProperties($permission); + + if ($this->isEmptyRow($permission)) { + continue; + } + + if (!isset($permission['permission'])) { + throw new ApplicationException('Cannot save permissions - the permission code should not be empty.'); + } + + $code = $permission['permission']; + unset($permission['permission']); + + $filePermissions[$code] = $permission; + } + + return $filePermissions; + } + + /** + * validate + */ + public function validate() + { + parent::validate(); + + $this->validateDuplicatePermissions(); + $this->validateRequiredProperties(); + } + + /** + * getPluginRegistryData + */ + public static function getPluginRegistryData($pluginCode) + { + $model = new PermissionsModel(); + + $model->loadPlugin($pluginCode); + + $result = []; + + foreach ($model->permissions as $permissionInfo) { + if (!isset($permissionInfo['permission']) || !isset($permissionInfo['label'])) { + continue; + } + + $key = $permissionInfo['permission']; + $result[$key] = $key.' - '.Lang::get($permissionInfo['label']); + } + + return $result; + } + + /** + * validateDuplicatePermissions + */ + protected function validateDuplicatePermissions() + { + foreach ($this->permissions as $outerIndex => $outerPermission) { + if (!isset($outerPermission['permission'])) { + continue; + } + + foreach ($this->permissions as $innerIndex => $innerPermission) { + if (!isset($innerPermission['permission'])) { + continue; + } + + $outerCode = trim($outerPermission['permission']); + $innerCode = trim($innerPermission['permission']); + + if ($innerIndex != $outerIndex && $outerCode == $innerCode && strlen($outerCode)) { + throw new ValidationException([ + 'permissions' => Lang::get( + 'rainlab.builder::lang.permission.error_duplicate_code', + ['code' => $outerCode] + ) + ]); + } + } + } + } + + /** + * validateRequiredProperties + */ + protected function validateRequiredProperties() + { + foreach ($this->permissions as $permission) { + if (array_key_exists('id', $permission)) { + unset($permission['id']); + } + + $permission = $this->trimPermissionProperties($permission); + + if ($this->isEmptyRow($permission)) { + continue; + } + + if (!strlen($permission['permission'])) { + throw new ValidationException([ + 'permissions' => Lang::get('rainlab.builder::lang.permission.column_permission_required') + ]); + } + + if (!strlen($permission['label'])) { + throw new ValidationException([ + 'permissions' => Lang::get('rainlab.builder::lang.permission.column_label_required') + ]); + } + + if (!strlen($permission['tab'])) { + throw new ValidationException([ + 'permissions' => Lang::get('rainlab.builder::lang.permission.column_tab_required') + ]); + } + } + } + + /** + * trimPermissionProperties + */ + protected function trimPermissionProperties($permission) + { + array_walk($permission, function ($value, $key) { + return trim($value); + }); + + return $permission; + } + + /** + * isEmptyRow + */ + protected function isEmptyRow($permission) + { + return !isset($permission['tab']) || !isset($permission['permission']) || !isset($permission['label']); + } + + /** + * yamlArrayToModel loads the model's data from an array. + * @param array $array An array to load the model fields from. + */ + protected function yamlArrayToModel($array) + { + $filePermissions = $array; + $permissions = []; + $index = 0; + + foreach ($filePermissions as $code => $permission) { + $permission['permission'] = $code; + + $permissions[] = $permission; + } + + $this->permissions = $permissions; + } + + /** + * getFilePath returns a file path to save the model to. + * @return string Returns a path. + */ + protected function getFilePath() + { + if ($this->pluginCodeObj === null) { + throw new SystemException('Error saving plugin permission model - the plugin code object is not set.'); + } + + return $this->pluginCodeObj->toPluginFilePath(); + } +} diff --git a/plugins/rainlab/builder/models/PluginBaseModel.php b/plugins/rainlab/builder/models/PluginBaseModel.php new file mode 100644 index 0000000..a9d9e82 --- /dev/null +++ b/plugins/rainlab/builder/models/PluginBaseModel.php @@ -0,0 +1,259 @@ + 'required', + 'author' => ['required'], + 'namespace' => ['required', 'regex:/^[a-z]+[a-z0-9]+$/i', 'reserved'], + 'author_namespace' => ['required', 'regex:/^[a-z]+[a-z0-9]+$/i', 'reserved'], + 'homepage' => 'url' + ]; + + /** + * getIconOptions + */ + public function getIconOptions() + { + return IconList::getList(); + } + + public function initDefaults() + { + $settings = PluginSettings::instance(); + $this->author = $settings->author_name; + $this->author_namespace = $settings->author_namespace; + } + + public function getPluginCode() + { + return $this->author_namespace.'.'.$this->namespace; + } + + public static function listAllPluginCodes() + { + $plugins = PluginManager::instance()->getPlugins(); + + return array_keys($plugins); + } + + protected function initPropertiesFromPluginCodeObject($pluginCodeObj) + { + $this->author_namespace = $pluginCodeObj->getAuthorCode(); + $this->namespace = $pluginCodeObj->getPluginCode(); + } + + /** + * Converts the model's data to an array before it's saved to a YAML file. + * @return array + */ + protected function modelToYamlArray() + { + return [ + 'name' => $this->name, + 'description' => $this->description, + 'author' => $this->author, + 'icon' => $this->icon, + 'homepage' => $this->homepage + ]; + } + + /** + * Load the model's data from an array. + * @param array $array An array to load the model fields from. + */ + protected function yamlArrayToModel($array) + { + $this->name = $this->getArrayKeySafe($array, 'name'); + $this->description = $this->getArrayKeySafe($array, 'description'); + $this->author = $this->getArrayKeySafe($array, 'author'); + $this->icon = $this->getArrayKeySafe($array, 'icon'); + $this->homepage = $this->getArrayKeySafe($array, 'homepage'); + } + + protected function beforeCreate() + { + $this->localizedName = $this->name; + $this->localizedDescription = $this->description; + + $pluginCode = strtolower($this->author_namespace.'.'.$this->namespace); + + $this->name = $pluginCode.'::lang.plugin.name'; + $this->description = $pluginCode.'::lang.plugin.description'; + } + + protected function afterCreate() + { + try { + $this->initPluginStructure(); + $this->forcePluginRegistration(); + $this->initBuilderSettings(); + } + catch (Exception $ex) { + $this->rollbackPluginCreation(); + throw $ex; + } + } + + protected function initPluginStructure() + { + $basePath = $this->getPluginPath(); + + $defaultLanguage = LocalizationModel::getDefaultLanguage(); + + $structure = [ + $basePath.'/Plugin.php' => 'plugin.php.tpl', + $basePath.'/updates/version.yaml' => 'version.yaml.tpl', + $basePath.'/classes', + $basePath.'/lang/'.$defaultLanguage.'/lang.php' => 'lang.php.tpl' + ]; + + $variables = [ + 'authorNamespace' => $this->author_namespace, + 'pluginNamespace' => $this->namespace, + 'pluginNameSanitized' => $this->sanitizePHPString($this->localizedName), + 'pluginDescriptionSanitized' => $this->sanitizePHPString($this->localizedDescription), + ]; + + $generator = new FilesystemGenerator('$', $structure, '$/rainlab/builder/models/pluginbasemodel/templates'); + $generator->setVariables($variables); + $generator->generate(); + } + + protected function forcePluginRegistration() + { + PluginManager::instance()->loadPlugins(); + UpdateManager::instance()->update(); + } + + protected function rollbackPluginCreation() + { + $basePath = '$/'.$this->getPluginPath(); + $basePath = File::symbolizePath($basePath); + + if (basename($basePath) == strtolower($this->namespace)) { + File::deleteDirectory($basePath); + } + } + + protected function sanitizePHPString($str) + { + return str_replace("'", "\'", $str); + } + + /** + * Returns a file path to save the model to. + * @return string Returns a path. + */ + protected function getFilePath() + { + return $this->getPluginPathObj()->toPluginFilePath(); + } + + protected function getPluginPath() + { + return $this->getPluginPathObj()->toFilesystemPath(); + } + + protected function getPluginPathObj() + { + return new PluginCode($this->getPluginCode()); + } + + protected function initBuilderSettings() + { + // Initialize Builder configuration - author name and namespace + // if it was not set yet. + + $settings = PluginSettings::instance(); + if (strlen($settings->author_name) || strlen($settings->author_namespace)) { + return; + } + + $settings->author_name = $this->author; + $settings->author_namespace = $this->author_namespace; + + $settings->save(); + } +} diff --git a/plugins/rainlab/builder/models/PluginYamlModel.php b/plugins/rainlab/builder/models/PluginYamlModel.php new file mode 100644 index 0000000..5239348 --- /dev/null +++ b/plugins/rainlab/builder/models/PluginYamlModel.php @@ -0,0 +1,85 @@ +initPropertiesFromPluginCodeObject($pluginCodeObj); + + $result = parent::load($filePath); + + $this->loadCommonProperties(); + + return $result; + } + + /** + * getPluginName + */ + public function getPluginName() + { + return Lang::get($this->pluginName); + } + + /** + * loadCommonProperties + */ + protected function loadCommonProperties() + { + if (!array_key_exists('plugin', $this->originalFileData)) { + return; + } + + $pluginData = $this->originalFileData['plugin']; + + if (array_key_exists('name', $pluginData)) { + $this->pluginName = $pluginData['name']; + } + } + + /** + * initPropertiesFromPluginCodeObject + */ + protected function initPropertiesFromPluginCodeObject($pluginCodeObj) + { + } + + /** + * pluginSettingsFileExists + */ + protected static function pluginSettingsFileExists($pluginCodeObj) + { + $filePath = File::symbolizePath($pluginCodeObj->toPluginFilePath()); + if (File::isFile($filePath)) { + return $filePath; + } + + return false; + } +} diff --git a/plugins/rainlab/builder/models/Settings.php b/plugins/rainlab/builder/models/Settings.php new file mode 100644 index 0000000..14590fc --- /dev/null +++ b/plugins/rainlab/builder/models/Settings.php @@ -0,0 +1,38 @@ + 'required', + 'author_namespace' => ['required', 'regex:/^[a-z]+[a-z0-9]+$/i', 'reserved'] + ]; +} diff --git a/plugins/rainlab/builder/models/YamlModel.php b/plugins/rainlab/builder/models/YamlModel.php new file mode 100644 index 0000000..85c0384 --- /dev/null +++ b/plugins/rainlab/builder/models/YamlModel.php @@ -0,0 +1,252 @@ +validate(); + + if ($this->isNewModel()) { + $this->beforeCreate(); + } + + $data = $this->modelToYamlArray(); + + if ($this->yamlSection) { + $fileData = $this->originalFileData; + + // Save the section data only if the section is not empty. + if ($data) { + $originalData = $this->preserveOriginal === true ? ($fileData[$this->yamlSection] ?? []) : []; + $fileData[$this->yamlSection] = $this->arrayMergeMany($originalData, $data); + } + else { + if (array_key_exists($this->yamlSection, $fileData)) { + unset($fileData[$this->yamlSection]); + } + } + + $data = $fileData; + } + + $dumper = new YamlDumper(); + + if ($data !== null) { + $yamlData = $dumper->dump($data, 20, 0, false, true); + } + else { + $yamlData = ''; + } + + $filePath = File::symbolizePath($this->getFilePath()); + $isNew = $this->isNewModel(); + + if (File::isFile($filePath)) { + if ($isNew || $this->originalFilePath != $filePath) { + throw new ValidationException(['fileName' => Lang::get('rainlab.builder::lang.common.error_file_exists', ['path'=>basename($filePath)])]); + } + } + + $fileDirectory = dirname($filePath); + if (!File::isDirectory($fileDirectory)) { + if (!File::makeDirectory($fileDirectory, 0777, true, true)) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.common.error_make_dir', ['name'=>$fileDirectory])); + } + } + + if (@File::put($filePath, $yamlData) === false) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.yaml.save_error', ['name'=>$filePath])); + } + + @File::chmod($filePath); + + if ($this->isNewModel()) { + $this->afterCreate(); + } + + if ($this->yamlSection) { + $this->originalFileData = $data; + } + + if (strlen($this->originalFilePath) > 0 && $this->originalFilePath != $filePath) { + @File::delete($this->originalFilePath); + } + + $this->originalFilePath = $filePath; + } + + /** + * load + */ + protected function load($filePath) + { + $filePath = File::symbolizePath($filePath); + + if (!File::isFile($filePath)) { + throw new ApplicationException('Cannot load the model - the original file is not found: '.basename($filePath)); + } + + try { + $data = Yaml::parse(File::get($filePath)); + } + catch (Exception $ex) { + throw new ApplicationException(sprintf('Cannot parse the YAML file %s: %s', basename($filePath), $ex->getMessage())); + } + + $this->originalFilePath = $filePath; + + if ($this->yamlSection) { + $this->originalFileData = $data; + if (!is_array($this->originalFileData)) { + $this->originalFileData = []; + } + + if (array_key_exists($this->yamlSection, $data)) { + $data = $data[$this->yamlSection]; + } + else { + $data = []; + } + } + + $this->yamlArrayToModel($data); + } + + /** + * deleteModel + */ + public function deleteModel() + { + if (!File::isFile($this->originalFilePath)) { + throw new ApplicationException('Cannot load the model - the original file is not found: '.$filePath); + } + + if (strtolower(substr($this->originalFilePath, -5)) !== '.yaml') { + throw new ApplicationException('Cannot delete the model - the original file should be a YAML document'); + } + + File::delete($this->originalFilePath); + } + + /** + * initDefaults + */ + public function initDefaults() + { + } + + /** + * isNewModel + */ + public function isNewModel() + { + return !strlen($this->originalFilePath); + } + + /** + * beforeCreate + */ + protected function beforeCreate() + { + } + + /** + * afterCreate + */ + protected function afterCreate() + { + } + + /** + * getArrayKeySafe + */ + protected function getArrayKeySafe($array, $key, $default = null) + { + return array_key_exists($key, $array) ? $array[$key] : $default; + } + + /** + * arrayMergeMany is a deep array merge function used to preserve existing + * YAML properties and splicing in new ones from builder. + */ + protected function arrayMergeMany($arr1, $arr2) + { + $arrMerge = array_merge($arr1, $arr2); + + foreach ($arrMerge as $key => $val) { + if (!is_array($val) || !$this->isArrayAssociative($val)) { + continue; + } + + if (isset($arr1[$key]) && isset($arr2[$key])) { + $arrMerge[$key] = $this->arrayMergeMany($arr1[$key], $arr2[$key]); + } + } + + return $arrMerge; + } + + /** + * isArrayAssociative retruns true if the array is associative + */ + protected function isArrayAssociative($arr) + { + return is_array($arr) && array_keys($arr) !== range(0, count($arr) - 1); + } + + /** + * Converts the model's data to an array before it's saved to a YAML file. + * @return array + */ + abstract protected function modelToYamlArray(); + + /** + * Load the model's data from an array. + * @param array $array An array to load the model fields from. + */ + abstract protected function yamlArrayToModel($array); + + /** + * Returns a file path to save the model to. + * @return string Returns a path. + */ + abstract protected function getFilePath(); +} diff --git a/plugins/rainlab/builder/models/codefilemodel/fields.yaml b/plugins/rainlab/builder/models/codefilemodel/fields.yaml new file mode 100644 index 0000000..614b9d1 --- /dev/null +++ b/plugins/rainlab/builder/models/codefilemodel/fields.yaml @@ -0,0 +1,21 @@ +# =================================== +# Form Field Definitions +# =================================== + +fields: + fileName: + label: cms::lang.editor.filename + attributes: + default-focus: 1 + + toolbar: + type: partial + path: $/rainlab/builder/behaviors/indexcodeoperations/partials/_toolbar.php + cssClass: collapse-visible + +secondaryTabs: + stretch: true + fields: + content: + stretch: true + type: codeeditor diff --git a/plugins/rainlab/builder/models/controllermodel/fields.yaml b/plugins/rainlab/builder/models/controllermodel/fields.yaml new file mode 100644 index 0000000..1d0bf30 --- /dev/null +++ b/plugins/rainlab/builder/models/controllermodel/fields.yaml @@ -0,0 +1,23 @@ +# =================================== +# Field Definitions +# =================================== + +fields: + controller: + label: rainlab.builder::lang.controller.controller + attributes: + readonly: true + + toolbar: + type: partial + path: $/rainlab/builder/behaviors/indexcontrolleroperations/partials/_toolbar.php + cssClass: collapse-visible + +secondaryTabs: + stretch: true + fields: + formBuilder: + type: RainLab\Builder\FormWidgets\ControllerBuilder + stretch: true + cssClass: layout + tab: rainlab.builder::lang.controller.behaviors diff --git a/plugins/rainlab/builder/models/controllermodel/fields_new_controller.yaml b/plugins/rainlab/builder/models/controllermodel/fields_new_controller.yaml new file mode 100644 index 0000000..ba06469 --- /dev/null +++ b/plugins/rainlab/builder/models/controllermodel/fields_new_controller.yaml @@ -0,0 +1,37 @@ +# =================================== +# Field Definitions +# =================================== + +fields: + controller: + label: rainlab.builder::lang.controller.controller_name + commentAbove: rainlab.builder::lang.controller.controller_name_description + required: true + attributes: + default-focus: 1 + + baseModelClassName: + label: rainlab.builder::lang.controller.base_model_class + commentAbove: rainlab.builder::lang.controller.base_model_class_description + placeholder: rainlab.builder::lang.controller.base_model_class_placeholder + span: left + type: dropdown + + menuItem: + label: rainlab.builder::lang.controller.menu_item + commentAbove: rainlab.builder::lang.controller.menu_item_description + placeholder: rainlab.builder::lang.controller.menu_item_placeholder + span: right + type: dropdown + +tabs: + fields: + behaviors: + commentAbove: rainlab.builder::lang.controller.controller_behaviors_description + tab: rainlab.builder::lang.controller.controller_behaviors + type: checkboxlist + permissions: + commentAbove: rainlab.builder::lang.controller.controller_permissions_description + tab: rainlab.builder::lang.controller.controller_permissions + type: checkboxlist + placeholder: rainlab.builder::lang.controller.controller_permissions_no_permissions diff --git a/plugins/rainlab/builder/models/databasetablemodel/fields.yaml b/plugins/rainlab/builder/models/databasetablemodel/fields.yaml new file mode 100644 index 0000000..8631b05 --- /dev/null +++ b/plugins/rainlab/builder/models/databasetablemodel/fields.yaml @@ -0,0 +1,91 @@ +# =================================== +# Form Field Definitions +# =================================== + +fields: + name: + label: rainlab.builder::lang.database.field_name + attributes: + default-focus: 1 + spellcheck: 'false' + + toolbar: + type: partial + path: $/rainlab/builder/behaviors/indexdatabasetableoperations/partials/_toolbar.php + cssClass: collapse-visible + +tabs: + stretch: true + cssClass: master-area + fields: + columns: + stretch: true + cssClass: frameless + tab: rainlab.builder::lang.database.tab_columns + type: datatable + btnAddRowLabel: rainlab.builder::lang.database.btn_add_column + btnDeleteRowLabel: rainlab.builder::lang.database.btn_delete_column + height: 100 + dynamicHeight: true + columns: + name: + title: rainlab.builder::lang.database.column_name_name + validation: + required: + message: rainlab.builder::lang.database.column_name_required + regex: + pattern: ^[0-9_a-z]+$ + message: rainlab.builder::lang.database.column_validation_title + type: + title: rainlab.builder::lang.database.column_name_type + type: dropdown + options: + integer: Integer + smallInteger: Small Integer + bigInteger: Big Integer + date: Date + time: Time + dateTime: Date and Time + timestamp: Timestamp + string: String + text: Text + binary: Binary + boolean: Boolean + decimal: Decimal + double: Double + validation: + required: + message: rainlab.builder::lang.database.column_type_required + length: + title: rainlab.builder::lang.database.column_name_length + validation: + regex: + pattern: (^[0-9]+$)|(^[0-9]+,[0-9]+$) + message: rainlab.builder::lang.database.column_validation_length + width: 8% + + default: + title: rainlab.builder::lang.database.column_default + + unsigned: + title: rainlab.builder::lang.database.column_name_unsigned + type: checkbox + width: 8% + + allow_null: + title: rainlab.builder::lang.database.column_name_nullable + type: checkbox + width: 8% + + auto_increment: + title: rainlab.builder::lang.database.column_auto_increment + type: checkbox + width: 8% + + primary_key: + title: rainlab.builder::lang.database.column_auto_primary_key + type: checkbox + width: 8% + + comment: + title: rainlab.builder::lang.database.column_comment diff --git a/plugins/rainlab/builder/models/databasetablemodel/templates/full-migration-code.php.tpl b/plugins/rainlab/builder/models/databasetablemodel/templates/full-migration-code.php.tpl new file mode 100644 index 0000000..61009c1 --- /dev/null +++ b/plugins/rainlab/builder/models/databasetablemodel/templates/full-migration-code.php.tpl @@ -0,0 +1,9 @@ + [ + 'name' => 'Plugin name', + 'description' => 'Plugin description.' + ] +]; diff --git a/plugins/rainlab/builder/models/menusmodel/fields.yaml b/plugins/rainlab/builder/models/menusmodel/fields.yaml new file mode 100644 index 0000000..756a532 --- /dev/null +++ b/plugins/rainlab/builder/models/menusmodel/fields.yaml @@ -0,0 +1,17 @@ +# =================================== +# Form Field Definitions +# =================================== + +fields: + toolbar: + type: partial + path: $/rainlab/builder/behaviors/indexmenusoperations/partials/_toolbar.php + cssClass: collapse-visible + +secondaryTabs: + stretch: true + fields: + menus: + stretch: true + tab: rainlab.builder::lang.menu.items + type: RainLab\Builder\FormWidgets\MenuEditor \ No newline at end of file diff --git a/plugins/rainlab/builder/models/migrationmodel/fields.yaml b/plugins/rainlab/builder/models/migrationmodel/fields.yaml new file mode 100644 index 0000000..cff6f49 --- /dev/null +++ b/plugins/rainlab/builder/models/migrationmodel/fields.yaml @@ -0,0 +1,9 @@ +fields: + version: + label: rainlab.builder::lang.migration.field_version + description: + label: rainlab.builder::lang.migration.field_description + code: + label: rainlab.builder::lang.migration.field_code + type: codeeditor + language: php diff --git a/plugins/rainlab/builder/models/migrationmodel/management-fields.yaml b/plugins/rainlab/builder/models/migrationmodel/management-fields.yaml new file mode 100644 index 0000000..8c52588 --- /dev/null +++ b/plugins/rainlab/builder/models/migrationmodel/management-fields.yaml @@ -0,0 +1,31 @@ +# =================================== +# Form Field Definitions +# =================================== + +fields: + version: + span: left + label: rainlab.builder::lang.migration.field_version + attributes: + default-focus: 1 + spellcheck: 'false' + cssClass: size-quarter + + description: + span: right + label: rainlab.builder::lang.migration.field_description + cssClass: size-three-quarter + + toolbar: + type: partial + path: $/rainlab/builder/behaviors/indexversionsoperations/partials/_toolbar.php + cssClass: collapse-visible + +secondaryTabs: + stretch: true + fields: + code: + tab: rainlab.builder::lang.migration.field_code + stretch: true + type: codeeditor + language: php diff --git a/plugins/rainlab/builder/models/migrationmodel/templates/migration.php.tpl b/plugins/rainlab/builder/models/migrationmodel/templates/migration.php.tpl new file mode 100644 index 0000000..c53eb39 --- /dev/null +++ b/plugins/rainlab/builder/models/migrationmodel/templates/migration.php.tpl @@ -0,0 +1,19 @@ + [ + \{{ relation.class }}::class, +{% for prop, value in relation.props %} + '{{ prop }}' => {{ value|raw }}{% if not loop.last %}, +{% endif %} +{% endfor %} + + ]{% if not loop.last %}, +{% endif %} +{% endfor %} + + ]; \ No newline at end of file diff --git a/plugins/rainlab/builder/models/modelmodel/templates/settingmodel.php.tpl b/plugins/rainlab/builder/models/modelmodel/templates/settingmodel.php.tpl new file mode 100644 index 0000000..81f97cf --- /dev/null +++ b/plugins/rainlab/builder/models/modelmodel/templates/settingmodel.php.tpl @@ -0,0 +1,23 @@ + '{{ value }}'{% if not loop.last %}, +{% endif %} +{% endfor %} + + ]; +{% endif %}{% if validation.attributeNames %} + + /** + * @var array attributeNames for validation. + */ + public $attributeNames = [ +{% for attr, value in validation.attributeNames %} + '{{ attr }}' => '{{ value }}'{% if not loop.last %}, +{% endif %} +{% endfor %} + + ]; +{% endif %}{% if validation.customMessages %} + + /** + * @var array customMessages for validation. + */ + public $customMessages = [ +{% for msg, value in validation.customMessages %} + '{{ msg }}' => '{{ value }}'{% if not loop.last %}, +{% endif %} +{% endfor %} + + ]; +{% endif %}{% else %} + + /** + * @var array rules for validation. + */ + public $rules = [ + ]; +{% endif %} \ No newline at end of file diff --git a/plugins/rainlab/builder/models/permissionsmodel/fields.yaml b/plugins/rainlab/builder/models/permissionsmodel/fields.yaml new file mode 100644 index 0000000..597d121 --- /dev/null +++ b/plugins/rainlab/builder/models/permissionsmodel/fields.yaml @@ -0,0 +1,31 @@ +# =================================== +# Form Field Definitions +# =================================== + +fields: + toolbar: + type: partial + path: $/rainlab/builder/behaviors/indexpermissionsoperations/partials/_toolbar.php + cssClass: collapse-visible + +tabs: + cssClass: master-area + stretch: true + fields: + permissions: + stretch: true + cssClass: frameless + tab: rainlab.builder::lang.permission.form_tab_permissions + type: datatable + btnAddRowLabel: rainlab.builder::lang.permission.btn_add_permission + btnDeleteRowLabel: rainlab.builder::lang.permission.btn_delete_permission + columns: + permission: + title: rainlab.builder::lang.permission.column_permission_label + type: string + tab: + title: rainlab.builder::lang.permission.column_tab_label + type: builderLocalization + label: + title: rainlab.builder::lang.permission.column_label_label + type: builderLocalization diff --git a/plugins/rainlab/builder/models/pluginbasemodel/fields.yaml b/plugins/rainlab/builder/models/pluginbasemodel/fields.yaml new file mode 100644 index 0000000..48ef103 --- /dev/null +++ b/plugins/rainlab/builder/models/pluginbasemodel/fields.yaml @@ -0,0 +1,57 @@ +tabs: + fields: + content: + type: hint + path: $/rainlab/builder/behaviors/indexpluginoperations/partials/_plugin-update-hint.php + tab: rainlab.builder::lang.plugin.tab_general + context: [update] + + name: + span: left + label: rainlab.builder::lang.plugin.field_name + required: true + tab: rainlab.builder::lang.plugin.tab_general + + author: + span: right + label: rainlab.builder::lang.plugin.field_author + tab: rainlab.builder::lang.plugin.tab_general + required: true + + namespace: + context: [create] + span: left + label: rainlab.builder::lang.plugin.field_plugin_namespace + commentAbove: rainlab.builder::lang.plugin.field_namespace_description + tab: rainlab.builder::lang.plugin.tab_general + required: true + preset: + field: name + type: namespace + + author_namespace: + context: [create] + span: right + label: rainlab.builder::lang.plugin.field_author_namespace + commentAbove: rainlab.builder::lang.plugin.field_author_namespace_description + tab: rainlab.builder::lang.plugin.tab_general + required: true + preset: + field: author + type: namespace + + icon: + type: dropdown + label: rainlab.builder::lang.plugin.field_icon + commentAbove: rainlab.builder::lang.common.field_icon_description + tab: rainlab.builder::lang.plugin.tab_general + + description: + label: rainlab.builder::lang.plugin.field_description + type: textarea + size: tiny + tab: rainlab.builder::lang.plugin.tab_description + + homepage: + label: rainlab.builder::lang.plugin.field_homepage + tab: rainlab.builder::lang.plugin.tab_description \ No newline at end of file diff --git a/plugins/rainlab/builder/models/pluginbasemodel/templates/lang.php.tpl b/plugins/rainlab/builder/models/pluginbasemodel/templates/lang.php.tpl new file mode 100644 index 0000000..54894bc --- /dev/null +++ b/plugins/rainlab/builder/models/pluginbasemodel/templates/lang.php.tpl @@ -0,0 +1,6 @@ + [ + 'name' => '{pluginNameSanitized}', + 'description' => '{pluginDescriptionSanitized}' + ] +]; \ No newline at end of file diff --git a/plugins/rainlab/builder/models/pluginbasemodel/templates/plugin.php.tpl b/plugins/rainlab/builder/models/pluginbasemodel/templates/plugin.php.tpl new file mode 100644 index 0000000..9f41fa4 --- /dev/null +++ b/plugins/rainlab/builder/models/pluginbasemodel/templates/plugin.php.tpl @@ -0,0 +1,37 @@ + + + The coding standard for October CMS Plugins. + + + + + + + + + + + */tests/* + + + + + + + . + */assets/* + diff --git a/plugins/rainlab/builder/phpunit.xml b/plugins/rainlab/builder/phpunit.xml new file mode 100644 index 0000000..db31479 --- /dev/null +++ b/plugins/rainlab/builder/phpunit.xml @@ -0,0 +1,23 @@ + + + + + ./tests/unit + + + + + + + + \ No newline at end of file diff --git a/plugins/rainlab/builder/rainlab-builder.mix.js b/plugins/rainlab/builder/rainlab-builder.mix.js new file mode 100644 index 0000000..e58f4fa --- /dev/null +++ b/plugins/rainlab/builder/rainlab-builder.mix.js @@ -0,0 +1,36 @@ +/* + |-------------------------------------------------------------------------- + | Mix Asset Management + |-------------------------------------------------------------------------- + | + | Mix provides a clean, fluent API for defining some Webpack build steps + | for your theme assets. By default, we are compiling the CSS + | file for the application as well as bundling up all the JS files. + | + */ + +module.exports = (mix) => { + mix.less('plugins/rainlab/builder/assets/less/builder.less', 'plugins/rainlab/builder/assets/css/'); + + mix.combine([ + 'plugins/rainlab/builder/assets/js/builder.dataregistry.js', + 'plugins/rainlab/builder/assets/js/builder.index.entity.base.js', + 'plugins/rainlab/builder/assets/js/builder.index.entity.plugin.js', + 'plugins/rainlab/builder/assets/js/builder.index.entity.databasetable.js', + 'plugins/rainlab/builder/assets/js/builder.index.entity.model.js', + 'plugins/rainlab/builder/assets/js/builder.index.entity.modelform.js', + 'plugins/rainlab/builder/assets/js/builder.index.entity.modellist.js', + 'plugins/rainlab/builder/assets/js/builder.index.entity.permission.js', + 'plugins/rainlab/builder/assets/js/builder.index.entity.menus.js', + 'plugins/rainlab/builder/assets/js/builder.index.entity.imports.js', + 'plugins/rainlab/builder/assets/js/builder.index.entity.code.js', + 'plugins/rainlab/builder/assets/js/builder.index.entity.version.js', + 'plugins/rainlab/builder/assets/js/builder.index.entity.localization.js', + 'plugins/rainlab/builder/assets/js/builder.index.entity.controller.js', + 'plugins/rainlab/builder/assets/js/builder.index.js', + 'plugins/rainlab/builder/assets/js/builder.localizationinput.js', + 'plugins/rainlab/builder/assets/js/builder.inspector.editor.localization.js', + 'plugins/rainlab/builder/assets/js/builder.table.processor.localization.js', + 'plugins/rainlab/builder/assets/js/builder.codelist.js' + ], 'plugins/rainlab/builder/assets/js/build-min.js'); +} diff --git a/plugins/rainlab/builder/rules/Reserved.php b/plugins/rainlab/builder/rules/Reserved.php new file mode 100644 index 0000000..8b4eb10 --- /dev/null +++ b/plugins/rainlab/builder/rules/Reserved.php @@ -0,0 +1,140 @@ +passes($attribute, $value); + } + + /** + * Determine if the validation rule passes. + * + * @param string $attribute + * @param mixed $value + * @return bool + */ + public function passes($attribute, $value) + { + return !in_array(strtolower($value), $this->reserved); + } + + /** + * Get the validation error message. + * + * @return string + */ + public function message() + { + return Lang::get('rainlab.builder::lang.validation.reserved'); + } +} diff --git a/plugins/rainlab/builder/tests/TestCase.php b/plugins/rainlab/builder/tests/TestCase.php new file mode 100644 index 0000000..c441f6c --- /dev/null +++ b/plugins/rainlab/builder/tests/TestCase.php @@ -0,0 +1,2 @@ +cleanUp(); + } + + public function tearDown() : void + { + $this->cleanUp(); + } + + public function testGenerate() + { + $generatedDir = $this->getFixturesDir('temporary/generated'); + $this->assertFileNotExists($generatedDir); + + File::makeDirectory($generatedDir, 0777, true, true); + $this->assertFileExists($generatedDir); + + $structure = [ + 'author', + 'author/plugin', + 'author/plugin/plugin.php' => 'plugin.php.tpl', + 'author/plugin/classes' + ]; + + $templatesDir = $this->getFixturesDir('templates'); + $generator = new FilesystemGenerator($generatedDir, $structure, $templatesDir); + + $variables = [ + 'authorNamespace' => 'Author', + 'pluginNamespace' => 'Plugin' + ]; + $generator->setVariables($variables); + $generator->setVariable('className', 'TestClass'); + + $generator->generate(); + + $this->assertFileExists($generatedDir.'/author/plugin/plugin.php'); + $this->assertFileExists($generatedDir.'/author/plugin/classes'); + + $content = file_get_contents($generatedDir.'/author/plugin/plugin.php'); + $this->assertContains('Author\Plugin', $content); + $this->assertContains('TestClass', $content); + } + + /** + * @expectedException October\Rain\Exception\SystemException + * @expectedExceptionMessage exists + */ + public function testDestNotExistsException() + { + $dir = $this->getFixturesDir('temporary/null'); + $generator = new FilesystemGenerator($dir, []); + $generator->generate(); + } + + /** + * @expectedException October\Rain\Exception\ApplicationException + * @expectedExceptionMessage exists + */ + public function testDirExistsException() + { + $generatedDir = $this->getFixturesDir('temporary/generated'); + $this->assertFileNotExists($generatedDir); + + File::makeDirectory($generatedDir.'/plugin', 0777, true, true); + $this->assertFileExists($generatedDir.'/plugin'); + + $structure = [ + 'plugin' + ]; + + $generator = new FilesystemGenerator($generatedDir, $structure); + $generator->generate(); + } + + /** + * @expectedException October\Rain\Exception\ApplicationException + * @expectedExceptionMessage exists + */ + public function testFileExistsException() + { + $generatedDir = $this->getFixturesDir('temporary/generated'); + $this->assertFileNotExists($generatedDir); + + File::makeDirectory($generatedDir, 0777, true, true); + $this->assertFileExists($generatedDir); + + File::put($generatedDir.'/plugin.php', 'contents'); + $this->assertFileExists($generatedDir.'/plugin.php'); + + $structure = [ + 'plugin.php' => 'plugin.php.tpl' + ]; + + $generator = new FilesystemGenerator($generatedDir, $structure); + $generator->generate(); + } + + /** + * @expectedException October\Rain\Exception\SystemException + * @expectedExceptionMessage found + */ + public function testTemplateNotFound() + { + $generatedDir = $this->getFixturesDir('temporary/generated'); + $this->assertFileNotExists($generatedDir); + + File::makeDirectory($generatedDir, 0777, true, true); + $this->assertFileExists($generatedDir); + + $structure = [ + 'plugin.php' => 'null.tpl' + ]; + + $generator = new FilesystemGenerator($generatedDir, $structure); + $generator->generate(); + } + + protected function getFixturesDir($subdir) + { + $result = __DIR__.'/../../fixtures/filesystemgenerator'; + + if (strlen($subdir)) { + $result .= '/'.$subdir; + } + + return $result; + } + + protected function cleanUp() + { + $generatedDir = $this->getFixturesDir('temporary/generated'); + File::deleteDirectory($generatedDir); + } +} diff --git a/plugins/rainlab/builder/tests/unit/classes/ModelModelTest.php b/plugins/rainlab/builder/tests/unit/classes/ModelModelTest.php new file mode 100644 index 0000000..8556a2f --- /dev/null +++ b/plugins/rainlab/builder/tests/unit/classes/ModelModelTest.php @@ -0,0 +1,68 @@ +assertTrue(ModelModel::validateModelClassName($unQualifiedClassName)); + + $qualifiedClassName = 'RainLab\Builder\Models\Settings'; + $this->assertTrue(ModelModel::validateModelClassName($qualifiedClassName)); + + $fullyQualifiedClassName = '\RainLab\Builder\Models\Settings'; + $this->assertTrue(ModelModel::validateModelClassName($fullyQualifiedClassName)); + + $qualifiedClassNameStartingWithLowerCase = 'rainLab\Builder\Models\Settings'; + $this->assertTrue(ModelModel::validateModelClassName($qualifiedClassNameStartingWithLowerCase)); + } + + public function testInvalidateModelClassName() + { + $unQualifiedClassName = 'myClassName'; // starts with lower case + $this->assertFalse(ModelModel::validateModelClassName($unQualifiedClassName)); + + $qualifiedClassName = 'MyNameSpace\MyPlugin\Models\MyClassName'; // namespace\class doesn't exist + $this->assertFalse(ModelModel::validateModelClassName($qualifiedClassName)); + + $fullyQualifiedClassName = '\MyNameSpace\MyPlugin\Models\MyClassName'; // namespace\class doesn't exist + $this->assertFalse(ModelModel::validateModelClassName($fullyQualifiedClassName)); + } + + public function testGetModelFields() + { + // Invalid Class Name + try { + ModelModel::getModelFields(null, 'myClassName'); + } catch (SystemException $e) { + $this->assertEquals($e->getMessage(), 'Invalid model class name: myClassName'); + return; + } + + // Directory Not Found + $pluginCodeObj = PluginCode::createFromNamespace('MyNameSpace\MyPlugin\Models\MyClassName'); + $this->assertEquals([], ModelModel::getModelFields($pluginCodeObj, 'MyClassName')); + + // Directory Found, but Class Not Found + $pluginCodeObj = PluginCode::createFromNamespace('RainLab\Builder\Models\MyClassName'); + $this->assertEquals([], ModelModel::getModelFields($pluginCodeObj, 'MyClassName')); + + // Model without Table Name + $pluginCodeObj = PluginCode::createFromNamespace('RainLab\Builder\Models\Settings'); + $this->assertEquals([], ModelModel::getModelFields($pluginCodeObj, 'Settings')); + + // Model with Table Name + copy(__DIR__."/../../fixtures/MyMock.php", __DIR__."/../../../models/MyMock.php"); + $pluginCodeObj = PluginCode::createFromNamespace('RainLab\Builder\Models\MyMock'); + $this->assertEquals([], ModelModel::getModelFields($pluginCodeObj, 'MyMock')); + } +} diff --git a/plugins/rainlab/builder/tests/unit/phpunit.xml b/plugins/rainlab/builder/tests/unit/phpunit.xml new file mode 100644 index 0000000..43f7f24 --- /dev/null +++ b/plugins/rainlab/builder/tests/unit/phpunit.xml @@ -0,0 +1,23 @@ + + + + + ./ + + + + + + + + \ No newline at end of file diff --git a/plugins/rainlab/builder/updates/version.yaml b/plugins/rainlab/builder/updates/version.yaml new file mode 100644 index 0000000..580232d --- /dev/null +++ b/plugins/rainlab/builder/updates/version.yaml @@ -0,0 +1,46 @@ +v1.0.1: Initialize plugin. +v1.0.2: Fixes the problem with selecting a plugin. Minor localization corrections. Configuration files in the list and form behaviors are now autocomplete. +v1.0.3: Improved handling of the enum data type. +v1.0.4: Added user permissions to work with the Builder. +v1.0.5: Fixed permissions registration. +v1.0.6: Fixed front-end record ordering in the Record List component. +v1.0.7: Builder settings are now protected with user permissions. The database table column list is scrollable now. Minor code cleanup. +v1.0.8: Added the Reorder Controller behavior. +v1.0.9: Minor API and UI updates. +v1.0.10: Minor styling update. +v1.0.11: Fixed a bug where clicking placeholder in a repeater would open Inspector. Fixed a problem with saving forms with repeaters in tabs. Minor style fix. +v1.0.12: Added support for the Trigger property to the Media Finder widget configuration. Names of form fields and list columns definition files can now contain underscores. +v1.0.13: Minor styling fix on the database editor. +v1.0.14: Added support for published_at timestamp field +v1.0.15: Fixed a bug where saving a localization string in Inspector could cause a JavaScript error. Added support for Timestamps and Soft Deleting for new models. +v1.0.16: Fixed a bug when saving a form with the Repeater widget in a tab could create invalid fields in the form's outside area. Added a check that prevents creating localization strings inside other existing strings. +v1.0.17: Added support Trigger attribute support for RecordFinder and Repeater form widgets. +v1.0.18: Fixes a bug where '::class' notations in a model class definition could prevent the model from appearing in the Builder model list. Added emptyOption property support to the dropdown form control. +v1.0.19: Added a feature allowing to add all database columns to a list definition. Added max length validation for database table and column names. +v1.0.20: Fixes a bug where form the builder could trigger the "current.hasAttribute is not a function" error. +v1.0.21: Back-end navigation sort order updated. +v1.0.22: Added scopeValue property to the RecordList component. +v1.0.23: Added support for balloon-selector field type, added Brazilian Portuguese translation, fixed some bugs +v1.0.24: Added support for tag list field type, added read only toggle for fields. Prevent plugins from using reserved PHP keywords for class names and namespaces +v1.0.25: Allow editing of migration code in the "Migration" popup when saving changes in the database editor. +v1.0.26: Allow special default values for columns and added new "Add ID column" button to database editor. +v1.0.27: Added ability to use 'scope' in a form relation field, added ability to change the sort order of versions and added additional properties for repeater widget in form builder. Added Polish translation. +v1.0.28: Fixes support for PHP 8 +v1.0.29: Disable touch device detection +v1.0.30: Minor styling improvements +v1.0.31: Added support for more rich editor and file upload properties +v1.0.32: Minor styling improvements +v1.1.0: Adds feature for adding database fields to a form definition. +v1.1.1: Adds DBAL timestamp column type. Adds database prefix support. Fixes various bugs. +v1.1.2: Compatibility with October CMS v2.2 +v1.1.3: Adds comment support to database tables. +v1.1.4: Fixes duplication bug saving backend menu permissions. +v1.2.0: Improve support with October v3.0 +v1.2.2: Compatibility updates. +v1.2.3: Fixes issue when removing items from permissions and menus. +v1.2.5: Fixes validator conflict with other plugins. +v1.2.6: Compatibility with October v3.1 +v2.0.1: Adds Tailor blueprint importer and code editor. +v2.0.2: Fixes visual bug when tab fields overflow. +v2.0.3: Fixes missing import in CMS components. +v2.0.4: Fixes bad method name in controller model. diff --git a/plugins/rainlab/builder/widgets/CodeList.php b/plugins/rainlab/builder/widgets/CodeList.php new file mode 100644 index 0000000..91bbc73 --- /dev/null +++ b/plugins/rainlab/builder/widgets/CodeList.php @@ -0,0 +1,821 @@ +alias = $alias; + $this->selectionInputName = 'file'; + $this->assetExtensions = FileDefinitions::get('assetExtensions'); + + parent::__construct($controller, []); + + if (!Request::ajax()) { + $this->resetSelection(); + } + + $this->bindToController(); + } + + /** + * Renders the widget. + * @return string + */ + public function render() + { + return $this->makePartial('body', [ + 'items' => $this->getData(), + 'pluginCode' => $this->getPluginCode() + ]); + } + + /** + * onOpenDirectory + */ + public function onOpenDirectory() + { + $path = Input::get('path'); + if (!$this->validatePath($path)) { + throw new ApplicationException(Lang::get('cms::lang.asset.invalid_path')); + } + + $this->putSession('currentPath', $path); + + return [ + '#'.$this->getId('code-list') => $this->makePartial('items', ['items' => $this->getData()]) + ]; + } + + /** + * refreshActivePlugin + */ + public function refreshActivePlugin() + { + $this->plugin = null; + + return [ + '#'.$this->getId('body') => $this->makePartial('widget-contents', [ + 'items' => $this->getData(), + 'pluginCode' => $this->getPluginCode() + ]) + ]; + } + + /** + * onRefresh + */ + public function onRefresh() + { + return [ + '#'.$this->getId('code-list') => $this->makePartial('items', ['items' => $this->getData()]) + ]; + } + + /** + * onUpdate + */ + public function onUpdate() + { + $this->extendSelection(); + + return $this->onRefresh(); + } + + /** + * onDeleteFiles + */ + public function onDeleteFiles() + { + $fileList = Request::input('file'); + $error = null; + $deleted = []; + + try { + $assetsPath = $this->getAssetsPath(); + + foreach ($fileList as $path => $selected) { + if ($selected) { + if (!$this->validatePath($path)) { + throw new ApplicationException(Lang::get('cms::lang.asset.invalid_path')); + } + + $fullPath = $assetsPath.'/'.$path; + if (File::exists($fullPath)) { + if (!File::isDirectory($fullPath)) { + if (!@File::delete($fullPath)) { + throw new ApplicationException(Lang::get( + 'cms::lang.asset.error_deleting_file', + ['name' => $path] + )); + } + } + else { + $empty = File::isDirectoryEmpty($fullPath); + if ($empty === false) { + throw new ApplicationException(Lang::get( + 'cms::lang.asset.error_deleting_dir_not_empty', + ['name' => $path] + )); + } + + if (!@rmdir($fullPath)) { + throw new ApplicationException(Lang::get( + 'cms::lang.asset.error_deleting_dir', + ['name' => $path] + )); + } + } + + $deleted[] = $path; + $this->removeSelection($path); + } + } + } + } + catch (Exception $ex) { + $error = $ex->getMessage(); + } + + return [ + 'deleted' => $deleted, + 'error' => $error, + 'plugin_code' => Request::input('plugin_code') + ]; + } + + /** + * onLoadRenamePopup + */ + public function onLoadRenamePopup() + { + $path = Input::get('renamePath'); + if (!$this->validatePath($path)) { + throw new ApplicationException(Lang::get('cms::lang.asset.invalid_path')); + } + + $this->vars['originalPath'] = $path; + $this->vars['name'] = basename($path); + + return $this->makePartial('rename_form'); + } + + /** + * onApplyName + */ + public function onApplyName() + { + $newName = trim(Input::get('name')); + if (!strlen($newName)) { + throw new ApplicationException(Lang::get('cms::lang.asset.name_cant_be_empty')); + } + + if (!$this->validatePath($newName)) { + throw new ApplicationException(Lang::get('cms::lang.asset.invalid_path')); + } + + if (!$this->validateName($newName)) { + throw new ApplicationException(Lang::get('cms::lang.asset.invalid_name')); + } + + $originalPath = Input::get('originalPath'); + if (!$this->validatePath($originalPath)) { + throw new ApplicationException(Lang::get('cms::lang.asset.invalid_path')); + } + + $originalFullPath = $this->getFullPath($originalPath); + if (!file_exists($originalFullPath)) { + throw new ApplicationException(Lang::get('cms::lang.asset.original_not_found')); + } + + if (!is_dir($originalFullPath) && !$this->validateFileType($newName)) { + throw new ApplicationException(Lang::get( + 'cms::lang.asset.type_not_allowed', + ['allowed_types' => implode(', ', $this->assetExtensions)] + )); + } + + $newFullPath = $this->getFullPath(dirname($originalPath).'/'.$newName); + if (file_exists($newFullPath) && $newFullPath !== $originalFullPath) { + throw new ApplicationException(Lang::get('cms::lang.asset.already_exists')); + } + + if (!@rename($originalFullPath, $newFullPath)) { + throw new ApplicationException(Lang::get('cms::lang.asset.error_renaming')); + } + + return [ + '#'.$this->getId('code-list') => $this->makePartial('items', ['items' => $this->getData()]) + ]; + } + + /** + * onLoadNewDirPopup + */ + public function onLoadNewDirPopup() + { + return $this->makePartial('new_dir_form'); + } + + /** + * onNewDirectory + */ + public function onNewDirectory() + { + $newName = trim(Input::get('name')); + if (!strlen($newName)) { + throw new ApplicationException(Lang::get('cms::lang.asset.name_cant_be_empty')); + } + + if (!$this->validatePath($newName)) { + throw new ApplicationException(Lang::get('cms::lang.asset.invalid_path')); + } + + if (!$this->validateName($newName)) { + throw new ApplicationException(Lang::get('cms::lang.asset.invalid_name')); + } + + $newFullPath = $this->getCurrentPath().'/'.$newName; + if (file_exists($newFullPath)) { + throw new ApplicationException(Lang::get('cms::lang.asset.already_exists')); + } + + if (!File::makeDirectory($newFullPath)) { + throw new ApplicationException(Lang::get( + 'cms::lang.cms_object.error_creating_directory', + ['name' => $newName] + )); + } + + return [ + '#'.$this->getId('code-list') => $this->makePartial('items', ['items' => $this->getData()]) + ]; + } + + /** + * onLoadMovePopup + */ + public function onLoadMovePopup() + { + $fileList = Request::input('file'); + $directories = []; + + $selectedList = array_filter($fileList, function ($value) { + return $value == 1; + }); + + $this->listDestinationDirectories($directories, $selectedList); + + $this->vars['directories'] = $directories; + $this->vars['selectedList'] = base64_encode(json_encode(array_keys($selectedList))); + + return $this->makePartial('move_form'); + } + + /** + * onMove + */ + public function onMove() + { + $selectedList = Input::get('selectedList'); + if (!strlen($selectedList)) { + throw new ApplicationException(Lang::get('cms::lang.asset.selected_files_not_found')); + } + + $destinationDir = Input::get('dest'); + if (!strlen($destinationDir)) { + throw new ApplicationException(Lang::get('cms::lang.asset.select_destination_dir')); + } + + $destinationFullPath = $this->getFullPath($destinationDir); + if (!file_exists($destinationFullPath) || !is_dir($destinationFullPath)) { + throw new ApplicationException(Lang::get('cms::lang.asset.destination_not_found')); + } + + $list = @json_decode(@base64_decode($selectedList)); + if ($list === false) { + throw new ApplicationException(Lang::get('cms::lang.asset.selected_files_not_found')); + } + + foreach ($list as $path) { + if (!$this->validatePath($path)) { + throw new ApplicationException(Lang::get('cms::lang.asset.invalid_path')); + } + + $basename = basename($path); + $originalFullPath = $this->getFullPath($path); + $newFullPath = realpath(rtrim($destinationFullPath, '/')) . '/' . $basename; + $safeDir = $this->getAssetsPath(); + + if ($originalFullPath == $newFullPath) { + continue; + } + + if (!starts_with($newFullPath, $safeDir)) { + throw new ApplicationException(Lang::get( + 'cms::lang.asset.error_moving_file', + ['file' => $basename] + )); + } + + if (is_file($originalFullPath)) { + if (!@File::move($originalFullPath, $newFullPath)) { + throw new ApplicationException(Lang::get( + 'cms::lang.asset.error_moving_file', + ['file' => $basename] + )); + } + } + elseif (is_dir($originalFullPath)) { + if (!@File::copyDirectory($originalFullPath, $newFullPath)) { + throw new ApplicationException(Lang::get( + 'cms::lang.asset.error_moving_directory', + ['dir' => $basename] + )); + } + + if (strpos($originalFullPath, '../') !== false) { + throw new ApplicationException(Lang::get( + 'cms::lang.asset.error_deleting_directory', + ['dir' => $basename] + )); + } + + if (strpos($originalFullPath, $safeDir) !== 0) { + throw new ApplicationException(Lang::get( + 'cms::lang.asset.error_deleting_directory', + ['dir' => $basename] + )); + } + + if (!@File::deleteDirectory($originalFullPath)) { + throw new ApplicationException(Lang::get( + 'cms::lang.asset.error_deleting_directory', + ['dir' => $basename] + )); + } + } + } + + return [ + '#'.$this->getId('code-list') => $this->makePartial('items', ['items' => $this->getData()]) + ]; + } + + /** + * onSearch + */ + public function onSearch() + { + $this->setSearchTerm(Input::get('search')); + + $this->extendSelection(); + + return $this->onRefresh(); + } + + /** + * getData + */ + protected function getData() + { + $assetsPath = $this->getAssetsPath(); + + if (!file_exists($assetsPath) || !is_dir($assetsPath)) { + if (!File::makeDirectory($assetsPath)) { + throw new ApplicationException(Lang::get( + 'cms::lang.cms_object.error_creating_directory', + ['name' => $assetsPath] + )); + } + } + + $searchTerm = Str::lower($this->getSearchTerm()); + + if (!strlen($searchTerm)) { + $currentPath = $this->getCurrentPath(); + return $this->getDirectoryContents( + new DirectoryIterator($currentPath) + ); + } + + return $this->findFiles(); + } + + /** + * getAssetsPath + */ + protected function getAssetsPath() + { + return base_path('plugins/'.$this->getActivePluginObj()?->toFilesystemPath()); + } + + /** + * getPluginFileUrl + */ + protected function getPluginFileUrl($path) + { + return Url::to('plugins/'.$this->getActivePluginObj()?->toFilesystemPath().$path); + } + + /** + * getCurrentRelativePath + */ + public function getCurrentRelativePath() + { + $path = $this->getSession('currentPath', '/'); + + if (!$this->validatePath($path)) { + return null; + } + + if ($path == '.') { + return null; + } + + return ltrim($path, '/'); + } + + /** + * getCurrentPath + */ + protected function getCurrentPath() + { + $assetsPath = $this->getAssetsPath(); + + $path = $assetsPath.'/'.$this->getCurrentRelativePath(); + if (!is_dir($path)) { + return $assetsPath; + } + + return $path; + } + + /** + * getRelativePath + */ + protected function getRelativePath($path) + { + $prefix = $this->getAssetsPath(); + + if (substr($path, 0, strlen($prefix)) == $prefix) { + $path = substr($path, strlen($prefix)); + } + + return $path; + } + + /** + * getFullPath + */ + protected function getFullPath($path) + { + return $this->getAssetsPath().'/'.ltrim($path, '/'); + } + + /** + * validatePath + */ + protected function validatePath($path) + { + if (!preg_match('/^[0-9a-z\.\s_\-\/]+$/i', $path)) { + return false; + } + + if (strpos($path, '..') !== false || strpos($path, './') !== false) { + return false; + } + + return true; + } + + /** + * validateName + */ + protected function validateName($name) + { + if (!preg_match('/^[0-9a-z\.\s_\-]+$/i', $name)) { + return false; + } + + if (strpos($name, '..') !== false) { + return false; + } + + return true; + } + + /** + * getDirectoryContents + */ + protected function getDirectoryContents($dir) + { + $editableAssetTypes = CodeFileModel::getEditableExtensions(); + + $result = []; + $files = []; + + foreach ($dir as $node) { + if (substr($node->getFileName(), 0, 1) == '.') { + continue; + } + + if ($node->isDir() && !$node->isDot()) { + $result[$node->getFilename()] = (object)[ + 'type' => 'directory', + 'path' => File::normalizePath($this->getRelativePath($node->getPathname())), + 'name' => $node->getFilename(), + 'editable' => false + ]; + } + elseif ($node->isFile()) { + $files[] = (object)[ + 'type' => 'file', + 'path' => File::normalizePath($this->getRelativePath($node->getPathname())), + 'name' => $node->getFilename(), + 'editable' => in_array(strtolower($node->getExtension()), $editableAssetTypes) + ]; + } + } + + foreach ($files as $file) { + $result[] = $file; + } + + return $result; + } + + /** + * listDestinationDirectories + */ + protected function listDestinationDirectories(&$result, $excludeList, $startDir = null, $level = 0) + { + if ($startDir === null) { + $startDir = $this->getAssetsPath(); + + $result['/'] = 'assets'; + $level = 1; + } + + $dirs = new DirectoryIterator($startDir); + foreach ($dirs as $node) { + if (substr($node->getFileName(), 0, 1) == '.') { + continue; + } + + if ($node->isDir() && !$node->isDot()) { + $fullPath = $node->getPathname(); + $relativePath = $this->getRelativePath($fullPath); + if (array_key_exists($relativePath, $excludeList)) { + continue; + } + + $result[$relativePath] = str_repeat(' ', $level * 4).$node->getFilename(); + + $this->listDestinationDirectories($result, $excludeList, $fullPath, $level+1); + } + } + } + + /** + * getSearchTerm + */ + protected function getSearchTerm() + { + return $this->searchTerm !== false ? $this->searchTerm : $this->getSession('search'); + } + + /** + * isSearchMode + */ + protected function isSearchMode() + { + return strlen($this->getSearchTerm()); + } + + /** + * getUpPath + */ + protected function getUpPath() + { + $path = $this->getCurrentRelativePath(); + if (!strlen(rtrim(ltrim($path, '/'), '/'))) { + return null; + } + + return dirname($path); + } + + /** + * getPluginCode + */ + protected function getPluginCode() + { + return $this->getActivePluginObj()?->toCode(); + } + + /** + * getActivePluginObj + */ + protected function getActivePluginObj() + { + if ($this->plugin !== null) { + return $this->plugin; + } + + $activePluginVector = $this->controller->getBuilderActivePluginVector(); + if (!$activePluginVector) { + return null; + } + + return $this->plugin = $activePluginVector->pluginCodeObj; + } + + /** + * validateFileType checks for valid asset file extension + * @param string + * @return bool + */ + protected function validateFileType($name) + { + $extension = strtolower(File::extension($name)); + + if (!in_array($extension, $this->assetExtensions)) { + return false; + } + + return true; + } + + public function onUpload() + { + $fileName = null; + + try { + $uploadedFile = Input::file('file_data'); + + if (!is_object($uploadedFile)) { + return; + } + + $fileName = $uploadedFile->getClientOriginalName(); + + // Check valid upload + if (!$uploadedFile->isValid()) { + throw new ApplicationException(Lang::get('cms::lang.asset.file_not_valid')); + } + + // Check file size + $maxSize = UploadedFile::getMaxFilesize(); + if ($uploadedFile->getSize() > $maxSize) { + throw new ApplicationException(Lang::get( + 'cms::lang.asset.too_large', + ['max_size' => File::sizeToString($maxSize)] + )); + } + + // Check for valid file extensions + if (!$this->validateFileType($fileName)) { + throw new ApplicationException(Lang::get( + 'cms::lang.asset.type_not_allowed', + ['allowed_types' => implode(', ', $this->assetExtensions)] + )); + } + + // Accept the uploaded file + $uploadedFile = $uploadedFile->move($this->getCurrentPath(), $uploadedFile->getClientOriginalName()); + + File::chmod($uploadedFile->getRealPath()); + + $response = Response::make('success'); + } + catch (Exception $ex) { + $message = $fileName !== null + ? Lang::get('cms::lang.asset.error_uploading_file', ['name' => $fileName, 'error' => $ex->getMessage()]) + : $ex->getMessage(); + + $response = Response::make($message); + } + + // Override the controller response + $this->controller->setResponse($response); + } + + /** + * setSearchTerm + */ + protected function setSearchTerm($term) + { + $this->searchTerm = trim($term); + $this->putSession('search', $this->searchTerm); + } + + /** + * findFiles + */ + protected function findFiles() + { + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($this->getAssetsPath(), RecursiveDirectoryIterator::SKIP_DOTS), + RecursiveIteratorIterator::SELF_FIRST, + RecursiveIteratorIterator::CATCH_GET_CHILD + ); + + $editableAssetTypes = CodeFileModel::getEditableExtensions(); + $searchTerm = Str::lower($this->getSearchTerm()); + $words = explode(' ', $searchTerm); + + $result = []; + foreach ($iterator as $item) { + if (!$item->isDir()) { + if (substr($item->getFileName(), 0, 1) == '.') { + continue; + } + + $path = $this->getRelativePath($item->getPathname()); + + if ($this->pathMatchesSearch($words, $path)) { + $result[] = (object)[ + 'type' => 'file', + 'path' => File::normalizePath($path), + 'name' => $item->getFilename(), + 'editable' => in_array(strtolower($item->getExtension()), $editableAssetTypes) + ]; + } + } + } + + return $result; + } + + /** + * pathMatchesSearch + */ + protected function pathMatchesSearch(&$words, $path) + { + foreach ($words as $word) { + $word = trim($word); + if (!strlen($word)) { + continue; + } + + if (!Str::contains(Str::lower($path), $word)) { + return false; + } + } + + return true; + } +} diff --git a/plugins/rainlab/builder/widgets/ControllerList.php b/plugins/rainlab/builder/widgets/ControllerList.php new file mode 100644 index 0000000..515303e --- /dev/null +++ b/plugins/rainlab/builder/widgets/ControllerList.php @@ -0,0 +1,124 @@ +alias = $alias; + + parent::__construct($controller, []); + $this->bindToController(); + } + + /** + * render the widget. + * @return string + */ + public function render() + { + return $this->makePartial('body', $this->getRenderData()); + } + + /** + * updateList + */ + public function updateList() + { + return [ + '#'.$this->getId('plugin-controller-list') => $this->makePartial('items', $this->getRenderData()) + ]; + } + + /** + * refreshActivePlugin + */ + public function refreshActivePlugin() + { + return [ + '#'.$this->getId('body') => $this->makePartial('widget-contents', $this->getRenderData()) + ]; + } + + /** + * onUpdate + */ + public function onUpdate() + { + return $this->updateList(); + } + + /** + * onSearch + */ + public function onSearch() + { + $this->setSearchTerm(Input::get('search')); + return $this->updateList(); + } + + /** + * getControllerList + */ + protected function getControllerList($pluginCode) + { + $result = ControllerModel::listPluginControllers($pluginCode); + + return $result; + } + + /** + * getRenderData + */ + protected function getRenderData() + { + $activePluginVector = $this->controller->getBuilderActivePluginVector(); + if (!$activePluginVector) { + return [ + 'pluginVector' => null, + 'items' => [] + ]; + } + + $items = $this->getControllerList($activePluginVector->pluginCodeObj); + + $searchTerm = Str::lower($this->getSearchTerm()); + if (strlen($searchTerm)) { + $words = explode(' ', $searchTerm); + $result = []; + + foreach ($items as $controller) { + if ($this->textMatchesSearch($words, $controller)) { + $result[] = $controller; + } + } + + $items = $result; + } + + return [ + 'pluginVector' => $activePluginVector, + 'items' => $items + ]; + } +} diff --git a/plugins/rainlab/builder/widgets/DatabaseTableList.php b/plugins/rainlab/builder/widgets/DatabaseTableList.php new file mode 100644 index 0000000..a0fa092 --- /dev/null +++ b/plugins/rainlab/builder/widgets/DatabaseTableList.php @@ -0,0 +1,118 @@ +alias = $alias; + + parent::__construct($controller, []); + $this->bindToController(); + } + + /** + * Renders the widget. + * @return string + */ + public function render() + { + return $this->makePartial('body', $this->getRenderData()); + } + + public function updateList() + { + return ['#'.$this->getId('database-table-list') => $this->makePartial('items', $this->getRenderData())]; + } + + public function refreshActivePlugin() + { + return ['#'.$this->getId('body') => $this->makePartial('widget-contents', $this->getRenderData())]; + } + + /* + * Event handlers + */ + + public function onUpdate() + { + return $this->updateList(); + } + + public function onSearch() + { + $this->setSearchTerm(Input::get('search')); + return $this->updateList(); + } + + /* + * Methods for the internal use + */ + + protected function getData($pluginVector) + { + if (!$pluginVector) { + return []; + } + + $pluginCode = $pluginVector->pluginCodeObj->toCode(); + + if (!$pluginCode) { + return []; + } + + $tables = $this->getTableList($pluginCode); + $searchTerm = Str::lower($this->getSearchTerm()); + + // Apply the search + // + if (strlen($searchTerm)) { + $words = explode(' ', $searchTerm); + $result = []; + + foreach ($tables as $table) { + if ($this->textMatchesSearch($words, $table)) { + $result[] = $table; + } + } + + $tables = $result; + } + + return $tables; + } + + protected function getTableList($pluginCode) + { + $result = DatabaseTableModel::listPluginTables($pluginCode); + + return $result; + } + + protected function getRenderData() + { + $activePluginVector = $this->controller->getBuilderActivePluginVector(); + + return [ + 'pluginVector'=>$activePluginVector, + 'items'=>$this->getData($activePluginVector) + ]; + } +} diff --git a/plugins/rainlab/builder/widgets/DefaultBehaviorDesignTimeProvider.php b/plugins/rainlab/builder/widgets/DefaultBehaviorDesignTimeProvider.php new file mode 100644 index 0000000..f8fe86f --- /dev/null +++ b/plugins/rainlab/builder/widgets/DefaultBehaviorDesignTimeProvider.php @@ -0,0 +1,218 @@ + 'form-controller', + \Backend\Behaviors\ListController::class => 'list-controller', + \Backend\Behaviors\ImportExportController::class => 'import-export-controller' + ]; + + /** + * Renders behavior body. + * @param string $class Specifies the behavior class to render. + * @param array $properties Behavior property values. + * @param \RainLab\Builder\FormWidgets\ControllerBuilder $controllerBuilder ControllerBuilder widget instance. + * @return string Returns HTML markup string. + */ + public function renderBehaviorBody($class, $properties, $controllerBuilder) + { + if (!array_key_exists($class, $this->defaultBehaviorClasses)) { + return $this->renderUnknownBehavior($class, $properties); + } + + $partial = $this->defaultBehaviorClasses[$class]; + + return $this->makePartial('behavior-'.$partial, [ + 'properties'=>$properties, + 'controllerBuilder' => $controllerBuilder + ]); + } + + /** + * Returns default behavior configuration as an array. + * @param string $class Specifies the behavior class name. + * @param string $controllerModel Controller model. + * @param mixed $controllerGenerator Controller generator object. + * @return array Returns the behavior configuration array. + */ + public function getDefaultConfiguration($class, $controllerModel, $controllerGenerator) + { + if (!array_key_exists($class, $this->defaultBehaviorClasses)) { + throw new SystemException('Unknown behavior class: '.$class); + } + + switch ($class) { + case \Backend\Behaviors\FormController::class: + return $this->getFormControllerDefaultConfiguration($controllerModel, $controllerGenerator); + case \Backend\Behaviors\ListController::class: + return $this->getListControllerDefaultConfiguration($controllerModel, $controllerGenerator); + case \Backend\Behaviors\ImportExportController::class: + return $this->getImportExportControllerDefaultConfiguration($controllerModel, $controllerGenerator); + } + } + + /** + * renderUnknownControl + */ + protected function renderUnknownControl($class, $properties) + { + return $this->makePartial('behavior-unknown', [ + 'properties'=>$properties, + 'class'=>$class + ]); + } + + /** + * getFormControllerDefaultConfiguration + */ + protected function getFormControllerDefaultConfiguration($controllerModel, $controllerGenerator) + { + if (!$controllerModel->baseModelClassName) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_behavior_requires_base_model', [ + 'behavior' => 'Form Controller' + ])); + } + + $pluginCodeObj = $controllerModel->getPluginCodeObj(); + + $forms = ModelFormModel::listModelFiles($pluginCodeObj, $controllerModel->baseModelClassName); + if (!$forms) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_model_doesnt_have_forms')); + } + + $controllerUrl = $this->getControllerUrl($pluginCodeObj, $controllerModel->controller); + + $result = [ + 'name' => $controllerModel->controllerName, + 'form' => $this->getModelFilePath($pluginCodeObj, $controllerModel->baseModelClassName, $forms[0]), + 'modelClass' => $this->getFullModelClass($pluginCodeObj, $controllerModel->baseModelClassName), + 'defaultRedirect' => $controllerUrl, + 'create' => [ + 'redirect' => $controllerUrl.'/update/:id', + 'redirectClose' => $controllerUrl + ], + 'update' => [ + 'redirect' => $controllerUrl, + 'redirectClose' => $controllerUrl + ] + ]; + + return $result; + } + + /** + * getListControllerDefaultConfiguration + */ + protected function getListControllerDefaultConfiguration($controllerModel, $controllerGenerator) + { + if (!$controllerModel->baseModelClassName) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_behavior_requires_base_model', [ + 'behavior' => 'List Controller' + ])); + } + + $pluginCodeObj = $controllerModel->getPluginCodeObj(); + + $lists = ModelListModel::listModelFiles($pluginCodeObj, $controllerModel->baseModelClassName); + if (!$lists) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_model_doesnt_have_lists')); + } + + $result = [ + 'list' => $this->getModelFilePath($pluginCodeObj, $controllerModel->baseModelClassName, $lists[0]), + 'modelClass' => $this->getFullModelClass($pluginCodeObj, $controllerModel->baseModelClassName), + 'title' => $controllerModel->controller, + 'noRecordsMessage' => 'backend::lang.list.no_records', + 'showSetup' => true, + 'showCheckboxes' => true, + 'recordsPerPage' => 20, + 'toolbar' => [ + 'buttons' => 'list_toolbar', + 'search' => [ + 'prompt' => 'backend::lang.list.search_prompt' + ] + ] + ]; + + if (array_key_exists(\Backend\Behaviors\FormController::class, $controllerModel->behaviors)) { + $updateUrl = $this->getControllerUrl($pluginCodeObj, $controllerModel->controller).'/update/:id'; + $createUrl = $this->getControllerUrl($pluginCodeObj, $controllerModel->controller).'/create'; + + $result['recordUrl'] = $updateUrl; + + $controllerGenerator->setTemplateVariable('hasFormBehavior', true); + $controllerGenerator->setTemplateVariable('createUrl', $createUrl); + } + + if (in_array(\Backend\Behaviors\ImportExportController::class, $controllerModel->behaviors)) { + $importUrl = $this->getControllerUrl($pluginCodeObj, $controllerModel->controller).'/import'; + $exportUrl = $this->getControllerUrl($pluginCodeObj, $controllerModel->controller).'/export'; + $controllerGenerator->setTemplateVariable('hasImportExportBehavior', true); + $controllerGenerator->setTemplateVariable('importUrl', $importUrl); + $controllerGenerator->setTemplateVariable('exportUrl', $exportUrl); + } + + return $result; + } + + /** + * getImportExportControllerDefaultConfiguration + */ + protected function getImportExportControllerDefaultConfiguration($controllerModel, $controllerGenerator) + { + if (!$controllerModel->baseModelClassName) { + throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_behavior_requires_base_model', [ + 'behavior' => 'Import Export Controller' + ])); + } + + $pluginCodeObj = $controllerModel->getPluginCodeObj(); + + $result = [ + 'import.title' => $controllerModel->controller, + 'import.modelClass' => $this->getFullModelClass($pluginCodeObj, $controllerModel->baseModelClassName), + 'export.title' => $controllerModel->controller, + 'export.modelClass' => $this->getFullModelClass($pluginCodeObj, $controllerModel->baseModelClassName), + ]; + + return $result; + } + + /** + * getFullModelClass + */ + protected function getFullModelClass($pluginCodeObj, $modelClassName) + { + return $pluginCodeObj->toPluginNamespace().'\\Models\\'.$modelClassName; + } + + /** + * getModelFilePath + */ + protected function getModelFilePath($pluginCodeObj, $modelClassName, $file) + { + return '$/' . $pluginCodeObj->toFilesystemPath() . '/models/' . strtolower($modelClassName) . '/' . $file; + } + + /** + * getControllerUrl + */ + protected function getControllerUrl($pluginCodeObj, $controller) + { + return $pluginCodeObj->toUrl().'/'.strtolower($controller); + } +} diff --git a/plugins/rainlab/builder/widgets/DefaultBlueprintDesignTimeProvider.php b/plugins/rainlab/builder/widgets/DefaultBlueprintDesignTimeProvider.php new file mode 100644 index 0000000..af66833 --- /dev/null +++ b/plugins/rainlab/builder/widgets/DefaultBlueprintDesignTimeProvider.php @@ -0,0 +1,123 @@ + 'entry', + \Tailor\Classes\Blueprint\StreamBlueprint::class => 'entry', + \Tailor\Classes\Blueprint\SingleBlueprint::class => 'entry', + \Tailor\Classes\Blueprint\StructureBlueprint::class => 'entry', + \Tailor\Classes\Blueprint\GlobalBlueprint::class => 'global', + ]; + + /** + * renderBlueprintBody + * @param string $class Specifies the blueprint class to render. + * @param array $properties Blueprint property values. + * @param object $blueprintObj + * @return string Returns HTML markup string. + */ + public function renderBlueprintBody($class, $properties, $blueprintObj) + { + if (!array_key_exists($class, $this->defaultBlueprintClasses)) { + return $this->renderUnknownBlueprint($class, $properties); + } + + $partial = $this->defaultBlueprintClasses[$class]; + + return $this->makePartial('blueprint-'.$partial, [ + 'properties' => $properties, + 'blueprintObj' => $blueprintObj + ]); + } + + /** + * getDefaultConfiguration returns default blueprint configuration as an array. + * @param string $class Specifies the blueprint class name. + * @param string $blueprintObj + * @param mixed $importsModel + * @return array + */ + public function getDefaultConfiguration($class, $blueprintObj, $importsModel) + { + if (!array_key_exists($class, $this->defaultBlueprintClasses)) { + throw new SystemException('Unknown blueprint class: '.$class); + } + + switch ($class) { + case \Tailor\Classes\Blueprint\EntryBlueprint::class: + case \Tailor\Classes\Blueprint\StreamBlueprint::class: + case \Tailor\Classes\Blueprint\SingleBlueprint::class: + case \Tailor\Classes\Blueprint\StructureBlueprint::class: + return $this->getEntryBlueprintDefaultConfiguration($blueprintObj, $importsModel); + case \Tailor\Classes\Blueprint\GlobalBlueprint::class: + return $this->getGlobalBlueprintDefaultConfiguration($blueprintObj, $importsModel); + } + } + + /** + * renderUnknownBlueprint + */ + protected function renderUnknownBlueprint($class, $properties) + { + return $this->makePartial('blueprint-unknown', [ + 'properties' => $properties, + 'class' => $class + ]); + } + + /** + * getEntryBlueprintDefaultConfiguration + */ + protected function getEntryBlueprintDefaultConfiguration($blueprintObj, $importsModel) + { + $handleBase = class_basename($blueprintObj->handle); + $dbPrefix = $importsModel->getPluginCodeObj()->toDatabasePrefix().'_'; + $permissionPrefix = $importsModel->getPluginCodeObj()->toPermissionPrefix().'.manage_'; + + $result = [ + 'name' => $blueprintObj->name, + 'controllerClass' => Str::plural($handleBase), + 'modelClass' => Str::singular($handleBase), + 'tableName' => $dbPrefix . Str::snake($handleBase), + 'permissionCode' => $permissionPrefix . Str::snake($handleBase), + 'menuCode' => Str::snake($handleBase), + ]; + + return $result; + } + + /** + * getGlobalBlueprintDefaultConfiguration + */ + protected function getGlobalBlueprintDefaultConfiguration($blueprintObj, $importsModel) + { + $handleBase = class_basename($blueprintObj->handle); + $dbPrefix = $importsModel->getPluginCodeObj()->toDatabasePrefix().'_'; + $permissionPrefix = $importsModel->getPluginCodeObj()->toPermissionPrefix().'.manage_'; + + $result = [ + 'name' => $blueprintObj->name, + 'controllerClass' => Str::plural($handleBase), + 'modelClass' => Str::singular($handleBase), + 'tableName' => $dbPrefix . Str::snake($handleBase), + 'permissionCode' => $permissionPrefix . Str::snake($handleBase), + 'menuCode' => Str::snake($handleBase), + ]; + + return $result; + } +} diff --git a/plugins/rainlab/builder/widgets/DefaultControlDesignTimeProvider.php b/plugins/rainlab/builder/widgets/DefaultControlDesignTimeProvider.php new file mode 100644 index 0000000..70cc7a8 --- /dev/null +++ b/plugins/rainlab/builder/widgets/DefaultControlDesignTimeProvider.php @@ -0,0 +1,135 @@ +defaultControlsTypes)) { + return $this->renderUnknownControl($type, $properties); + } + + return $this->makePartial('control-'.$type, [ + 'properties' => $properties, + 'formBuilder' => $formBuilder + ]); + } + + /** + * renderControlStaticBody renders control static body. + * The control static body is never updated with AJAX during the form editing. + * @param string $type Specifies the control type to render. + * @param array $properties Control property values preprocessed for the Inspector. + * @param array $controlConfiguration Raw control property values. + * @param \RainLab\Builder\FormWidgets\FormBuilder $formBuilder FormBuilder widget instance. + * @return string Returns HTML markup string. + */ + public function renderControlStaticBody($type, $properties, $controlConfiguration, $formBuilder) + { + if (!in_array($type, $this->defaultControlsTypes)) { + return null; + } + + $partialName = 'control-'.$type.'-static'; + $partialPath = $this->getViewPath('_'.$partialName.'.php'); + + if (!File::exists($partialPath)) { + return null; + } + + return $this->makePartial($partialName, [ + 'properties' => $properties, + 'controlConfiguration' => $controlConfiguration, + 'formBuilder' => $formBuilder + ]); + } + + /** + * controlHasLabels determines whether a control supports default labels and comments. + * @param string $type Specifies the control type. + * @return boolean + */ + public function controlHasLabels($type) + { + if (in_array($type, ['checkbox', 'switch', 'hint', 'partial', 'section', 'ruler'])) { + return false; + } + + return true; + } + + /** + * getPropertyValue + */ + protected function getPropertyValue($properties, $property) + { + if (array_key_exists($property, $properties)) { + return $properties[$property]; + } + + return null; + } + + /** + * renderUnknownControl + */ + protected function renderUnknownControl($type, $properties) + { + return $this->makePartial('control-unknowncontrol', [ + 'properties'=>$properties, + 'type'=>$type + ]); + } +} diff --git a/plugins/rainlab/builder/widgets/LanguageList.php b/plugins/rainlab/builder/widgets/LanguageList.php new file mode 100644 index 0000000..539de94 --- /dev/null +++ b/plugins/rainlab/builder/widgets/LanguageList.php @@ -0,0 +1,104 @@ +alias = $alias; + + parent::__construct($controller, []); + $this->bindToController(); + } + + /** + * Renders the widget. + * @return string + */ + public function render() + { + return $this->makePartial('body', $this->getRenderData()); + } + + public function updateList() + { + return ['#'.$this->getId('plugin-language-list') => $this->makePartial('items', $this->getRenderData())]; + } + + public function refreshActivePlugin() + { + return ['#'.$this->getId('body') => $this->makePartial('widget-contents', $this->getRenderData())]; + } + + /* + * Event handlers + */ + + public function onUpdate() + { + return $this->updateList(); + } + + public function onSearch() + { + $this->setSearchTerm(Input::get('search')); + return $this->updateList(); + } + + /* + * Methods for the internal use + */ + + protected function getLanguageList($pluginCode) + { + $result = LocalizationModel::listPluginLanguages($pluginCode); + + return $result; + } + + protected function getRenderData() + { + $activePluginVector = $this->controller->getBuilderActivePluginVector(); + if (!$activePluginVector) { + return [ + 'pluginVector'=>null, + 'items' => [] + ]; + } + + $items = $this->getLanguageList($activePluginVector->pluginCodeObj); + + $searchTerm = Str::lower($this->getSearchTerm()); + if (strlen($searchTerm)) { + $words = explode(' ', $searchTerm); + $result = []; + + foreach ($items as $language) { + if ($this->textMatchesSearch($words, $language)) { + $result[] = $language; + } + } + + $items = $result; + } + + return [ + 'pluginVector'=>$activePluginVector, + 'items'=>$items + ]; + } +} diff --git a/plugins/rainlab/builder/widgets/ModelList.php b/plugins/rainlab/builder/widgets/ModelList.php new file mode 100644 index 0000000..cf44707 --- /dev/null +++ b/plugins/rainlab/builder/widgets/ModelList.php @@ -0,0 +1,129 @@ +alias = $alias; + + parent::__construct($controller, []); + $this->bindToController(); + } + + /** + * Renders the widget. + * @return string + */ + public function render() + { + return $this->makePartial('body', $this->getRenderData()); + } + + public function updateList() + { + return ['#'.$this->getId('plugin-model-list') => $this->makePartial('items', $this->getRenderData())]; + } + + public function refreshActivePlugin() + { + return ['#'.$this->getId('body') => $this->makePartial('widget-contents', $this->getRenderData())]; + } + + /* + * Event handlers + */ + + public function onUpdate() + { + return $this->updateList(); + } + + public function onSearch() + { + $this->setSearchTerm(Input::get('search')); + return $this->updateList(); + } + + /* + * Methods for the internal use + */ + + protected function getData($pluginVector) + { + if (!$pluginVector) { + return []; + } + + $pluginCode = $pluginVector->pluginCodeObj; + + if (!$pluginCode) { + return []; + } + + $models = $this->getModelList($pluginCode); + $searchTerm = Str::lower($this->getSearchTerm()); + + // Apply the search + // + if (strlen($searchTerm)) { + $words = explode(' ', $searchTerm); + $result = []; + + foreach ($models as $modelInfo) { + if ($this->textMatchesSearch($words, $modelInfo['model']->className)) { + $result[] = $modelInfo; + } + } + + $models = $result; + } + + return $models; + } + + protected function getModelList($pluginCode) + { + $models = ModelModel::listPluginModels($pluginCode); + $result = []; + + foreach ($models as $model) { + $result[] = [ + 'model' => $model, + 'forms' => ModelFormModel::listModelFiles($pluginCode, $model->className), + 'lists' => ModelListModel::listModelFiles($pluginCode, $model->className) + ]; + } + + return $result; + } + + protected function getRenderData() + { + $activePluginVector = $this->controller->getBuilderActivePluginVector(); + + return [ + 'pluginVector'=>$activePluginVector, + 'items'=>$this->getData($activePluginVector) + ]; + } +} diff --git a/plugins/rainlab/builder/widgets/PluginList.php b/plugins/rainlab/builder/widgets/PluginList.php new file mode 100644 index 0000000..205c151 --- /dev/null +++ b/plugins/rainlab/builder/widgets/PluginList.php @@ -0,0 +1,233 @@ +alias = $alias; + + parent::__construct($controller, []); + $this->bindToController(); + } + + /** + * render the widget. + * @return string + */ + public function render() + { + return $this->makePartial('body', $this->getRenderData()); + } + + /** + * setActivePlugin + */ + public function setActivePlugin($pluginCode) + { + $pluginCodeObj = new PluginCode($pluginCode); + + $this->putSession('activePlugin', $pluginCodeObj->toCode()); + } + + /** + * getActivePluginVector + */ + public function getActivePluginVector() + { + $pluginCode = $this->getActivePluginCode(); + + try { + if (strlen($pluginCode)) { + $pluginCodeObj = new PluginCode($pluginCode); + $path = $pluginCodeObj->toPluginInformationFilePath(); + if (!File::isFile(File::symbolizePath($path))) { + return null; + } + + $plugins = PluginManager::instance()->getPlugins(); + foreach ($plugins as $code => $plugin) { + if ($code == $pluginCode) { + return new PluginVector($plugin, $pluginCodeObj); + } + } + } + } + catch (Exception $ex) { + return null; + } + + return null; + } + + /** + * updateList + */ + public function updateList() + { + return ['#'.$this->getId('plugin-list') => $this->makePartial('items', $this->getRenderData())]; + } + + /** + * onUpdate + */ + public function onUpdate() + { + return $this->updateList(); + } + + /** + * onSearch + */ + public function onSearch() + { + $this->setSearchTerm(Input::get('search')); + return $this->updateList(); + } + + /** + * onToggleFilter + */ + public function onToggleFilter() + { + $mode = $this->getFilterMode(); + $this->setFilterMode($mode == 'my' ? 'all' : 'my'); + + $result = $this->updateList(); + $result['#'.$this->getId('toolbar-buttons')] = $this->makePartial('toolbar-buttons'); + + return $result; + } + + /** + * getData + */ + protected function getData() + { + $plugins = $this->getPluginList(); + $searchTerm = Str::lower($this->getSearchTerm()); + + // Apply the search + // + if (strlen($searchTerm)) { + $words = explode(' ', $searchTerm); + $result = []; + + foreach ($plugins as $code => $plugin) { + if ($this->textMatchesSearch($words, $plugin['full-text'])) { + $result[$code] = $plugin; + } + } + + $plugins = $result; + } + + // Apply the my plugins / all plugins filter + // + $mode = $this->getFilterMode(); + if ($mode == 'my') { + $namespace = PluginSettings::instance()->author_namespace; + + $result = []; + foreach ($plugins as $code => $plugin) { + if (strcasecmp($plugin['namespace'], $namespace) === 0) { + $result[$code] = $plugin; + } + } + + $plugins = $result; + } + + return $plugins; + } + + /** + * getPluginList + */ + protected function getPluginList() + { + $plugins = PluginManager::instance()->getPlugins(); + + $result = []; + foreach ($plugins as $code => $plugin) { + $pluginInfo = $plugin->pluginDetails(); + + $itemInfo = [ + 'name' => isset($pluginInfo['name']) ? $pluginInfo['name'] : 'rainlab.builder::lang.plugin.no_name', + 'description' => isset($pluginInfo['description']) ? $pluginInfo['description'] : 'rainlab.builder::lang.plugin.no_description', + 'icon' => isset($pluginInfo['icon']) ? $pluginInfo['icon'] : null + ]; + + list($namespace) = explode('\\', get_class($plugin)); + $itemInfo['namespace'] = trim($namespace); + $itemInfo['full-text'] = trans($itemInfo['name']).' '.trans($itemInfo['description']); + + $result[$code] = $itemInfo; + } + + uasort($result, function($a, $b) { + return strcmp(trans($a['name']), trans($b['name'])); + }); + + return $result; + } + + /** + * setFilterMode + */ + protected function setFilterMode($mode) + { + $this->putSession('filter', $mode); + } + + /** + * getFilterMode + */ + protected function getFilterMode() + { + return $this->getSession('filter', 'my'); + } + + /** + * getActivePluginCode + */ + protected function getActivePluginCode() + { + return $this->getSession('activePlugin'); + } + + /** + * getRenderData + */ + protected function getRenderData() + { + return [ + 'items'=>$this->getData() + ]; + } +} diff --git a/plugins/rainlab/builder/widgets/VersionList.php b/plugins/rainlab/builder/widgets/VersionList.php new file mode 100644 index 0000000..08eab99 --- /dev/null +++ b/plugins/rainlab/builder/widgets/VersionList.php @@ -0,0 +1,155 @@ +alias = $alias; + + parent::__construct($controller, []); + + $this->config->sort = $this->getSession('sort', 'asc'); + + $this->bindToController(); + } + + /** + * render the widget. + * @return string + */ + public function render() + { + return $this->makePartial('body', $this->getRenderData()); + } + + /** + * updateList + */ + public function updateList() + { + return ['#'.$this->getId('plugin-version-list') => $this->makePartial('items', $this->getRenderData())]; + } + + /** + * refreshActivePlugin + */ + public function refreshActivePlugin() + { + return ['#'.$this->getId('body') => $this->makePartial('widget-contents', $this->getRenderData())]; + } + + /** + * onUpdate + */ + public function onUpdate() + { + return $this->updateList(); + } + + /** + * onSearch + */ + public function onSearch() + { + $this->setSearchTerm(Input::get('search')); + return $this->updateList(); + } + + /** + * onSort + */ + public function onSort() + { + $this->config->sort = Input::input('sort'); + + $this->putSession('sort', $this->config->sort); + + return ['#' . $this->getId('body') => $this->makePartial('widget-contents', $this->getRenderData())]; + } + + /** + * getRenderData + */ + protected function getRenderData() + { + $activePluginVector = $this->controller->getBuilderActivePluginVector(); + if (!$activePluginVector) { + return [ + 'pluginVector'=>null, + 'items' => [], + 'unappliedVersions' => [] + ]; + } + + $versionObj = new PluginVersion(); + $items = $versionObj->getPluginVersionInformation($activePluginVector->pluginCodeObj); + + $searchTerm = Str::lower($this->getSearchTerm()); + if (strlen($searchTerm)) { + $words = explode(' ', $searchTerm); + $result = []; + + foreach ($items as $version => $versionInfo) { + $description = $this->getVersionDescription($versionInfo); + + if ( + $this->textMatchesSearch($words, $version) || + (strlen($description) && $this->textMatchesSearch($words, $description)) + ) { + $result[$version] = $versionInfo; + } + } + + $items = $result; + } + + if ($this->getConfig('sort', 'asc') === 'desc') { + $items = array_reverse($items, false); + } + + $versionManager = VersionManager::instance(); + $unappliedVersions = $versionManager->listNewVersions($activePluginVector->pluginCodeObj->toCode()); + return [ + 'pluginVector'=>$activePluginVector, + 'items'=>$items, + 'unappliedVersions'=>$unappliedVersions + ]; + } + + /** + * getVersionDescription + */ + protected function getVersionDescription($versionInfo) + { + if (is_array($versionInfo)) { + if (array_key_exists(0, $versionInfo)) { + return $versionInfo[0]; + } + } + + if (is_scalar($versionInfo)) { + return $versionInfo; + } + + return null; + } +} diff --git a/plugins/rainlab/builder/widgets/codelist/partials/_body.php b/plugins/rainlab/builder/widgets/codelist/partials/_body.php new file mode 100644 index 0000000..7a3f9c2 --- /dev/null +++ b/plugins/rainlab/builder/widgets/codelist/partials/_body.php @@ -0,0 +1,3 @@ +
    + makePartial('widget-contents', ['pluginCode'=>$pluginCode, 'items'=>$items]) ?> +
    diff --git a/plugins/rainlab/builder/widgets/codelist/partials/_files.php b/plugins/rainlab/builder/widgets/codelist/partials/_files.php new file mode 100644 index 0000000..b0e04f1 --- /dev/null +++ b/plugins/rainlab/builder/widgets/codelist/partials/_files.php @@ -0,0 +1,7 @@ +
    +
    +
    + makePartial('items', ['items' => $items]) ?> +
    +
    +
    diff --git a/plugins/rainlab/builder/widgets/codelist/partials/_items.php b/plugins/rainlab/builder/widgets/codelist/partials/_items.php new file mode 100644 index 0000000..8f74444 --- /dev/null +++ b/plugins/rainlab/builder/widgets/codelist/partials/_items.php @@ -0,0 +1,54 @@ +isSearchMode(); +?> +getUpPath()) !== null && !$searchMode): ?> +

    + getCurrentRelativePath() ?> +

    + +
    + + + +

    noRecordsMessage)) ?>

    + +
    diff --git a/plugins/rainlab/builder/widgets/codelist/partials/_move_form.php b/plugins/rainlab/builder/widgets/codelist/partials/_move_form.php new file mode 100644 index 0000000..b774168 --- /dev/null +++ b/plugins/rainlab/builder/widgets/codelist/partials/_move_form.php @@ -0,0 +1,40 @@ +$this->getEventHandler('onMove'), + 'data-request-success'=>"\$(this).trigger('close.oc.popup')", + 'data-stripe-load-indicator'=>1, + 'id'=>'asset-move-popup-form' +]) ?> + + + + diff --git a/plugins/rainlab/builder/widgets/codelist/partials/_new_dir_form.php b/plugins/rainlab/builder/widgets/codelist/partials/_new_dir_form.php new file mode 100644 index 0000000..14ebf9c --- /dev/null +++ b/plugins/rainlab/builder/widgets/codelist/partials/_new_dir_form.php @@ -0,0 +1,45 @@ +$this->getEventHandler('onNewDirectory'), + 'data-request-success'=>"\$(this).trigger('close.oc.popup')", + 'data-stripe-load-indicator'=>1, + 'id'=>'asset-new-dir-popup-form' +]) ?> + + + + + + + + diff --git a/plugins/rainlab/builder/widgets/codelist/partials/_rename_form.php b/plugins/rainlab/builder/widgets/codelist/partials/_rename_form.php new file mode 100644 index 0000000..2801d29 --- /dev/null +++ b/plugins/rainlab/builder/widgets/codelist/partials/_rename_form.php @@ -0,0 +1,46 @@ +getEventHandler('onApplyName'), [ + 'success' => "\$el.trigger('close.oc.popup');", + 'data-stripe-load-indicator' => 1, + 'id' => 'asset-rename-popup-form' +]) ?> + + + + + + + + diff --git a/plugins/rainlab/builder/widgets/codelist/partials/_toolbar.php b/plugins/rainlab/builder/widgets/codelist/partials/_toolbar.php new file mode 100644 index 0000000..b68e459 --- /dev/null +++ b/plugins/rainlab/builder/widgets/codelist/partials/_toolbar.php @@ -0,0 +1,74 @@ +
    +
    +
    +
    + + +
    +
    + + +
    + +
    + +
    +
    diff --git a/plugins/rainlab/builder/widgets/codelist/partials/_widget-contents.php b/plugins/rainlab/builder/widgets/codelist/partials/_widget-contents.php new file mode 100644 index 0000000..bf54926 --- /dev/null +++ b/plugins/rainlab/builder/widgets/codelist/partials/_widget-contents.php @@ -0,0 +1,27 @@ + +
    +
    + +
    +
    + + + + + makePartial('toolbar') ?> +
    +
    +
    + makePartial('files', ['items' => $items]) ?> +
    +
    +
    + +
    +
    +
    +

    +
    +
    +
    + \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/controllerlist/partials/_body.php b/plugins/rainlab/builder/widgets/controllerlist/partials/_body.php new file mode 100644 index 0000000..46306d3 --- /dev/null +++ b/plugins/rainlab/builder/widgets/controllerlist/partials/_body.php @@ -0,0 +1,3 @@ +
    + makePartial('widget-contents', ['pluginVector'=>$pluginVector, 'items'=>$items]) ?> +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/controllerlist/partials/_controller-list.php b/plugins/rainlab/builder/widgets/controllerlist/partials/_controller-list.php new file mode 100644 index 0000000..c99bfa9 --- /dev/null +++ b/plugins/rainlab/builder/widgets/controllerlist/partials/_controller-list.php @@ -0,0 +1,13 @@ +
    +
    +
    +
    + makePartial('items', ['items'=>$items, 'pluginVector'=>$pluginVector]) ?> +
    +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/controllerlist/partials/_items.php b/plugins/rainlab/builder/widgets/controllerlist/partials/_items.php new file mode 100644 index 0000000..c7e04ff --- /dev/null +++ b/plugins/rainlab/builder/widgets/controllerlist/partials/_items.php @@ -0,0 +1,20 @@ + +
      + pluginCodeObj->toCode(); + foreach ($items as $controller): + $dataId = 'controller-'.e($pluginCode).'-'.$controller; + ?> +
    • + data-id=""> + + + +
    • + +
    + +

    noRecordsMessage)) ?>

    + diff --git a/plugins/rainlab/builder/widgets/controllerlist/partials/_toolbar.php b/plugins/rainlab/builder/widgets/controllerlist/partials/_toolbar.php new file mode 100644 index 0000000..5ce9f57 --- /dev/null +++ b/plugins/rainlab/builder/widgets/controllerlist/partials/_toolbar.php @@ -0,0 +1,25 @@ +
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/controllerlist/partials/_widget-contents.php b/plugins/rainlab/builder/widgets/controllerlist/partials/_widget-contents.php new file mode 100644 index 0000000..14affab --- /dev/null +++ b/plugins/rainlab/builder/widgets/controllerlist/partials/_widget-contents.php @@ -0,0 +1,28 @@ +
    +
    + + getPluginName())) ?> + + + +
    +
    + + + makePartial('toolbar') ?> +
    +
    +
    + makePartial('controller-list', ['items'=>$items, 'pluginVector'=>$pluginVector]) ?> +
    +
    +
    + +
    +
    +
    +

    +
    +
    +
    + \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/databasetablelist/partials/_body.php b/plugins/rainlab/builder/widgets/databasetablelist/partials/_body.php new file mode 100644 index 0000000..46306d3 --- /dev/null +++ b/plugins/rainlab/builder/widgets/databasetablelist/partials/_body.php @@ -0,0 +1,3 @@ +
    + makePartial('widget-contents', ['pluginVector'=>$pluginVector, 'items'=>$items]) ?> +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/databasetablelist/partials/_items.php b/plugins/rainlab/builder/widgets/databasetablelist/partials/_items.php new file mode 100644 index 0000000..90c821f --- /dev/null +++ b/plugins/rainlab/builder/widgets/databasetablelist/partials/_items.php @@ -0,0 +1,18 @@ + + + +

    noRecordsMessage)) ?>

    + \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/databasetablelist/partials/_table-list.php b/plugins/rainlab/builder/widgets/databasetablelist/partials/_table-list.php new file mode 100644 index 0000000..0f711cd --- /dev/null +++ b/plugins/rainlab/builder/widgets/databasetablelist/partials/_table-list.php @@ -0,0 +1,13 @@ +
    +
    +
    +
    + makePartial('items', ['items'=>$items]) ?> +
    +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/databasetablelist/partials/_toolbar.php b/plugins/rainlab/builder/widgets/databasetablelist/partials/_toolbar.php new file mode 100644 index 0000000..b268611 --- /dev/null +++ b/plugins/rainlab/builder/widgets/databasetablelist/partials/_toolbar.php @@ -0,0 +1,24 @@ +
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/databasetablelist/partials/_widget-contents.php b/plugins/rainlab/builder/widgets/databasetablelist/partials/_widget-contents.php new file mode 100644 index 0000000..e529225 --- /dev/null +++ b/plugins/rainlab/builder/widgets/databasetablelist/partials/_widget-contents.php @@ -0,0 +1,28 @@ +
    +
    + + getPluginName())) ?> + + + +
    +
    + + + makePartial('toolbar') ?> +
    +
    +
    + makePartial('table-list', ['items'=>$items]) ?> +
    +
    +
    + +
    +
    +
    +

    +
    +
    +
    + \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultbehaviordesigntimeprovider/partials/_behavior-form-controller.php b/plugins/rainlab/builder/widgets/defaultbehaviordesigntimeprovider/partials/_behavior-form-controller.php new file mode 100644 index 0000000..c0b7bd4 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultbehaviordesigntimeprovider/partials/_behavior-form-controller.php @@ -0,0 +1,23 @@ +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultbehaviordesigntimeprovider/partials/_behavior-import-export-controller.php b/plugins/rainlab/builder/widgets/defaultbehaviordesigntimeprovider/partials/_behavior-import-export-controller.php new file mode 100644 index 0000000..bee9d63 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultbehaviordesigntimeprovider/partials/_behavior-import-export-controller.php @@ -0,0 +1,19 @@ +
    +
    + + + + + + + + + + + + + + +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultbehaviordesigntimeprovider/partials/_behavior-list-controller.php b/plugins/rainlab/builder/widgets/defaultbehaviordesigntimeprovider/partials/_behavior-list-controller.php new file mode 100644 index 0000000..e2b1bd2 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultbehaviordesigntimeprovider/partials/_behavior-list-controller.php @@ -0,0 +1,41 @@ +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultbehaviordesigntimeprovider/partials/_behavior-unknown.php b/plugins/rainlab/builder/widgets/defaultbehaviordesigntimeprovider/partials/_behavior-unknown.php new file mode 100644 index 0000000..1a0e7af --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultbehaviordesigntimeprovider/partials/_behavior-unknown.php @@ -0,0 +1 @@ +Unknown behavior \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultblueprintdesigntimeprovider/partials/_blueprint-entry.php b/plugins/rainlab/builder/widgets/defaultblueprintdesigntimeprovider/partials/_blueprint-entry.php new file mode 100644 index 0000000..f900cf3 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultblueprintdesigntimeprovider/partials/_blueprint-entry.php @@ -0,0 +1,51 @@ + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Namename) ?>
    Handlehandle) ?>
    Controllercontrollers/
    Models + + models/ + +
    Migrations + + updates/ + +
    Error
    +
    +
    diff --git a/plugins/rainlab/builder/widgets/defaultblueprintdesigntimeprovider/partials/_blueprint-global.php b/plugins/rainlab/builder/widgets/defaultblueprintdesigntimeprovider/partials/_blueprint-global.php new file mode 100644 index 0000000..f900cf3 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultblueprintdesigntimeprovider/partials/_blueprint-global.php @@ -0,0 +1,51 @@ + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Namename) ?>
    Handlehandle) ?>
    Controllercontrollers/
    Models + + models/ + +
    Migrations + + updates/ + +
    Error
    +
    +
    diff --git a/plugins/rainlab/builder/widgets/defaultblueprintdesigntimeprovider/partials/_blueprint-unknown.php b/plugins/rainlab/builder/widgets/defaultblueprintdesigntimeprovider/partials/_blueprint-unknown.php new file mode 100644 index 0000000..abddc94 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultblueprintdesigntimeprovider/partials/_blueprint-unknown.php @@ -0,0 +1 @@ +Unknown blueprint \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-balloon-selector.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-balloon-selector.php new file mode 100644 index 0000000..f834507 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-balloon-selector.php @@ -0,0 +1,16 @@ +
    +
      + +
    • + +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-checkbox.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-checkbox.php new file mode 100644 index 0000000..0b68995 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-checkbox.php @@ -0,0 +1,9 @@ +getPropertyValue($properties, 'label'); + $comment = $this->getPropertyValue($properties, 'oc.comment'); +?> + +
    +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-checkboxlist.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-checkboxlist.php new file mode 100644 index 0000000..ef4c056 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-checkboxlist.php @@ -0,0 +1,16 @@ +
    +
      + +
    • + +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-codeeditor.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-codeeditor.php new file mode 100644 index 0000000..297f2e9 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-codeeditor.php @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-colorpicker.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-colorpicker.php new file mode 100644 index 0000000..5ed57b6 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-colorpicker.php @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-datatable.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-datatable.php new file mode 100644 index 0000000..aba343d --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-datatable.php @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-datepicker.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-datepicker.php new file mode 100644 index 0000000..4cf196f --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-datepicker.php @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-dropdown.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-dropdown.php new file mode 100644 index 0000000..9b0fa20 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-dropdown.php @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-email.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-email.php new file mode 100644 index 0000000..557f21c --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-email.php @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-fileupload.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-fileupload.php new file mode 100644 index 0000000..4988ad8 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-fileupload.php @@ -0,0 +1,6 @@ +
    + + getPropertyValue($properties, 'mode') != 'image'): ?> + + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-hint.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-hint.php new file mode 100644 index 0000000..fcd7858 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-hint.php @@ -0,0 +1,7 @@ +
    + + getPropertyValue($properties, 'path'); + echo strlen($path) ? ' - '.$path : null; + ?> +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-markdown.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-markdown.php new file mode 100644 index 0000000..404c61c --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-markdown.php @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-mediafinder.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-mediafinder.php new file mode 100644 index 0000000..14d7ec8 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-mediafinder.php @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-nestedform-static.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-nestedform-static.php new file mode 100644 index 0000000..5f2e08a --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-nestedform-static.php @@ -0,0 +1,11 @@ +
    + + + renderControlList($controls) ?> +
    diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-nestedform.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-nestedform.php new file mode 100644 index 0000000..2b947a8 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-nestedform.php @@ -0,0 +1 @@ +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-number.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-number.php new file mode 100644 index 0000000..7a9ae7f --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-number.php @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-pagefinder.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-pagefinder.php new file mode 100644 index 0000000..d6930b6 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-pagefinder.php @@ -0,0 +1,3 @@ +
    + +
    diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-partial.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-partial.php new file mode 100644 index 0000000..f43bf7e --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-partial.php @@ -0,0 +1,7 @@ +
    + + getPropertyValue($properties, 'path'); + echo strlen($path) ? ' - '.$path : null; + ?> +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-password.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-password.php new file mode 100644 index 0000000..d684156 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-password.php @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-radio.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-radio.php new file mode 100644 index 0000000..6685f86 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-radio.php @@ -0,0 +1,16 @@ +
    +
      + +
    • + +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-recordfinder.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-recordfinder.php new file mode 100644 index 0000000..85f0d48 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-recordfinder.php @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-relation.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-relation.php new file mode 100644 index 0000000..4bbfc9d --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-relation.php @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-repeater-static.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-repeater-static.php new file mode 100644 index 0000000..5f2e08a --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-repeater-static.php @@ -0,0 +1,11 @@ +
    + + + renderControlList($controls) ?> +
    diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-repeater.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-repeater.php new file mode 100644 index 0000000..d6c577d --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-repeater.php @@ -0,0 +1,9 @@ +
    + getPropertyValue($properties, 'prompt'); + if (!strlen($prompt)) { + $prompt = 'rainlab.builder::lang.form.property_prompt_default'; + } + ?> +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-richeditor.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-richeditor.php new file mode 100644 index 0000000..e56619b --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-richeditor.php @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-ruler.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-ruler.php new file mode 100644 index 0000000..0fd8f18 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-ruler.php @@ -0,0 +1 @@ +
    diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-section.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-section.php new file mode 100644 index 0000000..a9d75b3 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-section.php @@ -0,0 +1,9 @@ +getPropertyValue($properties, 'label'); + $comment =$this->getPropertyValue($properties, 'oc.comment'); +?> + +
    +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-sensitive.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-sensitive.php new file mode 100644 index 0000000..72fa918 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-sensitive.php @@ -0,0 +1,3 @@ +
    + +
    diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-switch.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-switch.php new file mode 100644 index 0000000..2d2adc4 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-switch.php @@ -0,0 +1,9 @@ +getPropertyValue($properties, 'label'); + $comment = $this->getPropertyValue($properties, 'oc.comment'); +?> + +
    +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-taglist.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-taglist.php new file mode 100644 index 0000000..c2a2281 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-taglist.php @@ -0,0 +1,3 @@ +
    + +
    diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-text.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-text.php new file mode 100644 index 0000000..308339e --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-text.php @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-textarea.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-textarea.php new file mode 100644 index 0000000..c9fd1f0 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-textarea.php @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-unknowncontrol.php b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-unknowncontrol.php new file mode 100644 index 0000000..fd2af48 --- /dev/null +++ b/plugins/rainlab/builder/widgets/defaultcontroldesigntimeprovider/partials/_control-unknowncontrol.php @@ -0,0 +1,4 @@ +
    + $type])) ?> +
    + \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/languagelist/partials/_body.php b/plugins/rainlab/builder/widgets/languagelist/partials/_body.php new file mode 100644 index 0000000..46306d3 --- /dev/null +++ b/plugins/rainlab/builder/widgets/languagelist/partials/_body.php @@ -0,0 +1,3 @@ +
    + makePartial('widget-contents', ['pluginVector'=>$pluginVector, 'items'=>$items]) ?> +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/languagelist/partials/_items.php b/plugins/rainlab/builder/widgets/languagelist/partials/_items.php new file mode 100644 index 0000000..cb2e0b4 --- /dev/null +++ b/plugins/rainlab/builder/widgets/languagelist/partials/_items.php @@ -0,0 +1,20 @@ + +
      + pluginCodeObj->toCode(); + foreach ($items as $language): + $dataId = 'localization-'.e($pluginCode).'-'.$language; + ?> +
    • + data-id=""> + + + +
    • + +
    + +

    noRecordsMessage)) ?>

    + \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/languagelist/partials/_language-list.php b/plugins/rainlab/builder/widgets/languagelist/partials/_language-list.php new file mode 100644 index 0000000..ef3df47 --- /dev/null +++ b/plugins/rainlab/builder/widgets/languagelist/partials/_language-list.php @@ -0,0 +1,13 @@ +
    +
    +
    +
    + makePartial('items', ['items'=>$items, 'pluginVector'=>$pluginVector]) ?> +
    +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/languagelist/partials/_toolbar.php b/plugins/rainlab/builder/widgets/languagelist/partials/_toolbar.php new file mode 100644 index 0000000..d8b409b --- /dev/null +++ b/plugins/rainlab/builder/widgets/languagelist/partials/_toolbar.php @@ -0,0 +1,24 @@ +
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/languagelist/partials/_widget-contents.php b/plugins/rainlab/builder/widgets/languagelist/partials/_widget-contents.php new file mode 100644 index 0000000..2a9b2f9 --- /dev/null +++ b/plugins/rainlab/builder/widgets/languagelist/partials/_widget-contents.php @@ -0,0 +1,28 @@ +
    +
    + + getPluginName())) ?> + + + +
    +
    + + + makePartial('toolbar') ?> +
    +
    +
    + makePartial('language-list', ['items'=>$items, 'pluginVector'=>$pluginVector]) ?> +
    +
    +
    + +
    +
    +
    +

    +
    +
    +
    + \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/modellist/partials/_body.php b/plugins/rainlab/builder/widgets/modellist/partials/_body.php new file mode 100644 index 0000000..46306d3 --- /dev/null +++ b/plugins/rainlab/builder/widgets/modellist/partials/_body.php @@ -0,0 +1,3 @@ +
    + makePartial('widget-contents', ['pluginVector'=>$pluginVector, 'items'=>$items]) ?> +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/modellist/partials/_items.php b/plugins/rainlab/builder/widgets/modellist/partials/_items.php new file mode 100644 index 0000000..b2196c4 --- /dev/null +++ b/plugins/rainlab/builder/widgets/modellist/partials/_items.php @@ -0,0 +1,94 @@ + +
      + className; + + $modelGroup = $model->className; + $formsGroup = $modelGroup.'-forms'; + $listsGroup = $modelGroup.'-lists'; + $modelGroupStatus = $this->getCollapseStatus($modelGroup); + $formsGroupStatus = $this->getCollapseStatus($formsGroup); + $listsGroupStatus = $this->getCollapseStatus($listsGroup); + ?> +
    • +

      className) ?>

      +
        +
      • +

        +
        + +
        + +
          + className.'-'.$modelForm; + ?> +
        • + +
        • + +
        +
      • +
      • +

        +
        + +
        + +
          + className.'-'.$modelList; + ?> +
        • + +
        • + +
        +
      • +
      + +
    • + +
    + +

    noRecordsMessage)) ?>

    + diff --git a/plugins/rainlab/builder/widgets/modellist/partials/_model-list.php b/plugins/rainlab/builder/widgets/modellist/partials/_model-list.php new file mode 100644 index 0000000..d1ab5d9 --- /dev/null +++ b/plugins/rainlab/builder/widgets/modellist/partials/_model-list.php @@ -0,0 +1,14 @@ +
    +
    +
    +
    + makePartial('items', ['items'=>$items]) ?> +
    +
    +
    +
    diff --git a/plugins/rainlab/builder/widgets/modellist/partials/_toolbar.php b/plugins/rainlab/builder/widgets/modellist/partials/_toolbar.php new file mode 100644 index 0000000..346057f --- /dev/null +++ b/plugins/rainlab/builder/widgets/modellist/partials/_toolbar.php @@ -0,0 +1,24 @@ +
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/modellist/partials/_widget-contents.php b/plugins/rainlab/builder/widgets/modellist/partials/_widget-contents.php new file mode 100644 index 0000000..f87cd74 --- /dev/null +++ b/plugins/rainlab/builder/widgets/modellist/partials/_widget-contents.php @@ -0,0 +1,28 @@ +
    +
    + + getPluginName())) ?> + + + +
    +
    + + + makePartial('toolbar') ?> +
    +
    +
    + makePartial('model-list', ['items'=>$items]) ?> +
    +
    +
    + +
    +
    +
    +

    +
    +
    +
    + \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/pluginlist/partials/_body.php b/plugins/rainlab/builder/widgets/pluginlist/partials/_body.php new file mode 100644 index 0000000..0040fb2 --- /dev/null +++ b/plugins/rainlab/builder/widgets/pluginlist/partials/_body.php @@ -0,0 +1,8 @@ +makePartial('toolbar') ?> +
    +
    +
    + makePartial('plugin-list', ['items'=>$items]) ?> +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/pluginlist/partials/_items.php b/plugins/rainlab/builder/widgets/pluginlist/partials/_items.php new file mode 100644 index 0000000..b304288 --- /dev/null +++ b/plugins/rainlab/builder/widgets/pluginlist/partials/_items.php @@ -0,0 +1,35 @@ + + getActivePluginCode(); ?> + + +

    noRecordsMessage)) ?>

    + \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/pluginlist/partials/_plugin-list.php b/plugins/rainlab/builder/widgets/pluginlist/partials/_plugin-list.php new file mode 100644 index 0000000..eab0976 --- /dev/null +++ b/plugins/rainlab/builder/widgets/pluginlist/partials/_plugin-list.php @@ -0,0 +1,13 @@ +
    +
    +
    +
    + makePartial('items', ['items'=>$items]) ?> +
    +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/pluginlist/partials/_toolbar-buttons.php b/plugins/rainlab/builder/widgets/pluginlist/partials/_toolbar-buttons.php new file mode 100644 index 0000000..d2226d8 --- /dev/null +++ b/plugins/rainlab/builder/widgets/pluginlist/partials/_toolbar-buttons.php @@ -0,0 +1,14 @@ + + +getFilterMode(); ?> + \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/pluginlist/partials/_toolbar.php b/plugins/rainlab/builder/widgets/pluginlist/partials/_toolbar.php new file mode 100644 index 0000000..69d6269 --- /dev/null +++ b/plugins/rainlab/builder/widgets/pluginlist/partials/_toolbar.php @@ -0,0 +1,22 @@ +
    +
    +
    +
    + makePartial("toolbar-buttons") ?> +
    +
    +
    + +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/versionlist/partials/_body.php b/plugins/rainlab/builder/widgets/versionlist/partials/_body.php new file mode 100644 index 0000000..b39cdd0 --- /dev/null +++ b/plugins/rainlab/builder/widgets/versionlist/partials/_body.php @@ -0,0 +1,3 @@ +
    + makePartial('widget-contents', ['pluginVector'=>$pluginVector, 'items'=>$items, 'unappliedVersions'=>$unappliedVersions]) ?> +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/versionlist/partials/_items.php b/plugins/rainlab/builder/widgets/versionlist/partials/_items.php new file mode 100644 index 0000000..940a482 --- /dev/null +++ b/plugins/rainlab/builder/widgets/versionlist/partials/_items.php @@ -0,0 +1,35 @@ + +
      + pluginCodeObj->toCode(); + foreach ($items as $versionNumber=>$versionInfo): + $dataId = 'version-'.e($pluginCode).'-'.$versionNumber; + $description = $this->getVersionDescription($versionInfo); + $applied = !array_key_exists($versionNumber, $unappliedVersions); + ?> +
    • + data-id=""> + + + + + + + + + + + + + + +
    • + +
    + +

    noRecordsMessage)) ?>

    + \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/versionlist/partials/_sort.php b/plugins/rainlab/builder/widgets/versionlist/partials/_sort.php new file mode 100644 index 0000000..d84feb0 --- /dev/null +++ b/plugins/rainlab/builder/widgets/versionlist/partials/_sort.php @@ -0,0 +1,11 @@ +getConfig('sort', 'asc') === 'asc'): ?> + + + + diff --git a/plugins/rainlab/builder/widgets/versionlist/partials/_toolbar.php b/plugins/rainlab/builder/widgets/versionlist/partials/_toolbar.php new file mode 100644 index 0000000..f019738 --- /dev/null +++ b/plugins/rainlab/builder/widgets/versionlist/partials/_toolbar.php @@ -0,0 +1,35 @@ +
    +
    +
    +
    + + makePartial('sort'); ?> +
    +
    +
    + +
    +
    +
    diff --git a/plugins/rainlab/builder/widgets/versionlist/partials/_version-list.php b/plugins/rainlab/builder/widgets/versionlist/partials/_version-list.php new file mode 100644 index 0000000..6d480c9 --- /dev/null +++ b/plugins/rainlab/builder/widgets/versionlist/partials/_version-list.php @@ -0,0 +1,13 @@ +
    +
    +
    +
    + makePartial('items', ['items'=>$items, 'unappliedVersions'=>$unappliedVersions, 'pluginVector'=>$pluginVector]) ?> +
    +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/builder/widgets/versionlist/partials/_widget-contents.php b/plugins/rainlab/builder/widgets/versionlist/partials/_widget-contents.php new file mode 100644 index 0000000..a2813ef --- /dev/null +++ b/plugins/rainlab/builder/widgets/versionlist/partials/_widget-contents.php @@ -0,0 +1,28 @@ +
    +
    + + getPluginName())) ?> + + + +
    +
    + + + makePartial('toolbar') ?> +
    +
    +
    + makePartial('version-list', ['items'=>$items, 'unappliedVersions'=>$unappliedVersions, 'pluginVector'=>$pluginVector]) ?> +
    +
    +
    + +
    +
    +
    +

    +
    +
    +
    + diff --git a/plugins/rainlab/pages/.github/ISSUE_TEMPLATE/1_BUG_REPORT.md b/plugins/rainlab/pages/.github/ISSUE_TEMPLATE/1_BUG_REPORT.md new file mode 100644 index 0000000..5a58d17 --- /dev/null +++ b/plugins/rainlab/pages/.github/ISSUE_TEMPLATE/1_BUG_REPORT.md @@ -0,0 +1,15 @@ +--- +name: "🐛 Bug Report" +about: 'Report a general Pages Plugin issue' +labels: 'Status: Review Needed, Type: Unconfirmed Bug' +--- + +- OctoberCMS Build: ### +- RainLab Pages Plugin Version: ### +- PHP Version: + +### Description: + + +### Steps To Reproduce: + diff --git a/plugins/rainlab/pages/.github/ISSUE_TEMPLATE/2_GENERAL_SUPPORT.md b/plugins/rainlab/pages/.github/ISSUE_TEMPLATE/2_GENERAL_SUPPORT.md new file mode 100644 index 0000000..935714f --- /dev/null +++ b/plugins/rainlab/pages/.github/ISSUE_TEMPLATE/2_GENERAL_SUPPORT.md @@ -0,0 +1,13 @@ +--- +name: "⚠️ General Support" +about: 'This repository is only for reporting bugs or problems. If you need help using RainLab Pages, see: https://octobercms.com/support' +--- + +This repository is only for reporting bugs or problems with the RainLab Pages plugin. If you need support, please use +the following options: + +- Forum: https://octobercms.com/forum +- Discord: https://discord.com/invite/gEKgwSZ +- Stack Overflow: https://stackoverflow.com/questions/tagged/octobercms + +Thanks! diff --git a/plugins/rainlab/pages/.gitignore b/plugins/rainlab/pages/.gitignore new file mode 100644 index 0000000..3d72576 --- /dev/null +++ b/plugins/rainlab/pages/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +.idea \ No newline at end of file diff --git a/plugins/rainlab/pages/LICENCE.md b/plugins/rainlab/pages/LICENCE.md new file mode 100644 index 0000000..e49b459 --- /dev/null +++ b/plugins/rainlab/pages/LICENCE.md @@ -0,0 +1,21 @@ +# MIT license + +Copyright (c) 2014-2022 Responsiv Pty Ltd, October 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/plugins/rainlab/pages/Plugin.php b/plugins/rainlab/pages/Plugin.php new file mode 100644 index 0000000..a10f8e5 --- /dev/null +++ b/plugins/rainlab/pages/Plugin.php @@ -0,0 +1,260 @@ + 'rainlab.pages::lang.plugin.name', + 'description' => 'rainlab.pages::lang.plugin.description', + 'author' => 'Alexey Bobkov, Samuel Georges', + 'icon' => 'icon-files-o', + 'homepage' => 'https://github.com/rainlab/pages-plugin' + ]; + } + + public function registerComponents() + { + return [ + \RainLab\Pages\Components\ChildPages::class => 'childPages', + \RainLab\Pages\Components\StaticPage::class => 'staticPage', + \RainLab\Pages\Components\StaticMenu::class => 'staticMenu', + \RainLab\Pages\Components\StaticBreadcrumbs::class => 'staticBreadcrumbs' + ]; + } + + public function registerPermissions() + { + return [ + 'rainlab.pages.manage_pages' => [ + 'tab' => 'rainlab.pages::lang.page.tab', + 'order' => 200, + 'label' => 'rainlab.pages::lang.page.manage_pages' + ], + 'rainlab.pages.manage_menus' => [ + 'tab' => 'rainlab.pages::lang.page.tab', + 'order' => 200, + 'label' => 'rainlab.pages::lang.page.manage_menus' + ], + 'rainlab.pages.manage_content' => [ + 'tab' => 'rainlab.pages::lang.page.tab', + 'order' => 200, + 'label' => 'rainlab.pages::lang.page.manage_content' + ], + 'rainlab.pages.access_snippets' => [ + 'tab' => 'rainlab.pages::lang.page.tab', + 'order' => 200, + 'label' => 'rainlab.pages::lang.page.access_snippets' + ] + ]; + } + + public function registerNavigation() + { + return [ + 'pages' => [ + 'label' => 'rainlab.pages::lang.plugin.name', + 'url' => Backend::url('rainlab/pages'), + 'icon' => 'icon-files-o', + 'iconSvg' => 'plugins/rainlab/pages/assets/images/pages-icon.svg', + 'permissions' => ['rainlab.pages.*'], + 'order' => 200, + 'useDropdown' => false, + + 'sideMenu' => [ + 'pages' => [ + 'label' => 'rainlab.pages::lang.page.menu_label', + 'icon' => 'icon-files-o', + 'url' => 'javascript:;', + 'attributes' => ['data-menu-item'=>'pages'], + 'permissions' => ['rainlab.pages.manage_pages'] + ], + 'menus' => [ + 'label' => 'rainlab.pages::lang.menu.menu_label', + 'icon' => 'icon-sitemap', + 'url' => 'javascript:;', + 'attributes' => ['data-menu-item'=>'menus'], + 'permissions' => ['rainlab.pages.manage_menus'] + ], + 'content' => [ + 'label' => 'rainlab.pages::lang.content.menu_label', + 'icon' => 'icon-file-text-o', + 'url' => 'javascript:;', + 'attributes' => ['data-menu-item'=>'content'], + 'permissions' => ['rainlab.pages.manage_content'] + ], + 'snippets' => [ + 'label' => 'rainlab.pages::lang.snippet.menu_label', + 'icon' => 'icon-newspaper-o', + 'url' => 'javascript:;', + 'attributes' => ['data-menu-item'=>'snippet'], + 'permissions' => ['rainlab.pages.access_snippets'] + ] + ] + ] + ]; + } + + public function registerFormWidgets() + { + return [ + FormWidgets\PagePicker::class => 'staticpagepicker', + FormWidgets\MenuPicker::class => 'staticmenupicker', + ]; + } + + public function boot() + { + Event::listen('cms.router.beforeRoute', function($url) { + return Controller::instance()->initCmsPage($url); + }); + + Event::listen('cms.page.beforeRenderPage', function($controller, $page) { + /* + * Before twig renders + */ + $twig = $controller->getTwig(); + $loader = $controller->getLoader(); + Controller::instance()->injectPageTwig($page, $loader, $twig); + + /* + * Get rendered content + */ + $contents = Controller::instance()->getPageContents($page); + if (strlen($contents)) { + return $contents; + } + }); + + Event::listen('cms.page.initComponents', function($controller, $page) { + Controller::instance()->initPageComponents($controller, $page); + }); + + Event::listen('cms.block.render', function($blockName, $blockContents) { + $page = CmsController::getController()->getPage(); + + if (!isset($page->apiBag['staticPage'])) { + return; + } + + $contents = Controller::instance()->getPlaceholderContents($page, $blockName, $blockContents); + if (strlen($contents)) { + return $contents; + } + }); + + Event::listen('cms.pageLookup.listTypes', function() { + return [ + 'static-page' => 'rainlab.pages::lang.menuitem.static_page', + 'all-static-pages' => ['rainlab.pages::lang.menuitem.all_static_pages', true] + ]; + }); + + Event::listen('pages.menuitem.listTypes', function() { + return [ + 'static-page' => 'rainlab.pages::lang.menuitem.static_page', + 'all-static-pages' => 'rainlab.pages::lang.menuitem.all_static_pages' + ]; + }); + + Event::listen(['cms.pageLookup.getTypeInfo', 'pages.menuitem.getTypeInfo'], function($type) { + if ($type == 'url') { + return []; + } + + if ($type == 'static-page'|| $type == 'all-static-pages') { + return StaticPage::getMenuTypeInfo($type); + } + }); + + Event::listen(['cms.pageLookup.resolveItem', 'pages.menuitem.resolveItem'], function($type, $item, $url, $theme) { + if ($type == 'static-page' || $type == 'all-static-pages') { + return StaticPage::resolveMenuItem($item, $url, $theme); + } + }); + + Event::listen('backend.form.extendFieldsBefore', function($formWidget) { + if ($formWidget->model instanceof \Cms\Classes\Partial) { + Snippet::extendPartialForm($formWidget); + } + }); + + Event::listen('cms.template.getTemplateToolbarSettingsButtons', function($extension, $dataHolder) { + if ($dataHolder->templateType === 'partial') { + Snippet::extendEditorPartialToolbar($dataHolder); + } + }); + + Event::listen('cms.template.save', function($controller, $template, $type) { + Plugin::clearCache(); + }); + + Event::listen('cms.template.processSettingsBeforeSave', function($controller, $dataHolder) { + $dataHolder->settings = Snippet::processTemplateSettingsArray($dataHolder->settings); + }); + + Event::listen('cms.template.processSettingsAfterLoad', function($controller, $template, $context = null) { + Snippet::processTemplateSettings($template, $context); + }); + + Event::listen('cms.template.processTwigContent', function($template, $dataHolder) { + if ($template instanceof \Cms\Classes\Layout) { + $dataHolder->content = Controller::instance()->parseSyntaxFields($dataHolder->content); + } + }); + + Event::listen('backend.richeditor.listTypes', function () { + return [ + 'static-page' => 'rainlab.pages::lang.menuitem.static_page', + ]; + }); + + Event::listen('backend.richeditor.getTypeInfo', function ($type) { + if ($type === 'static-page') { + return StaticPage::getRichEditorTypeInfo($type); + } + }); + + Event::listen('system.console.theme.sync.getAvailableModelClasses', function () { + return [ + Classes\Menu::class, + Classes\Page::class, + ]; + }); + } + + /** + * Register new Twig variables + * @return array + */ + public function registerMarkupTags() + { + return [ + 'filters' => [ + 'staticPage' => [\RainLab\Pages\Classes\Page::class, 'url'] + ] + ]; + } + + public static function clearCache() + { + $theme = Theme::getEditTheme(); + + $router = new Router($theme); + $router->clearCache(); + + StaticPage::clearMenuCache($theme); + SnippetManager::clearCache($theme); + } +} diff --git a/plugins/rainlab/pages/README.md b/plugins/rainlab/pages/README.md new file mode 100644 index 0000000..ccb9768 --- /dev/null +++ b/plugins/rainlab/pages/README.md @@ -0,0 +1,91 @@ +# Pages plugin + +This plugin allows end users to create and edit static pages and menus with a simple WYSIWYG user interface. + +## Managing static pages + +Static pages are managed on the Pages tab of the Static Pages plugin. Static pages have three required parameters - **Title**, **URL** and **Layout**. The URL is generated automatically when the Title is entered, but it could be changed manually. URLs must start with the forward slash character. The Layout drop-down allows to select a layout created with the CMS. Only layouts that include the `staticPage` component are displayed in the drop-down. + +![image](https://raw.githubusercontent.com/rainlab/pages-plugin/master/docs/images/static-page.png) {.img-responsive .frame} + +Pages are hierarchical. The page hierarchy is used when a new page URL is generated, but as URLs can be changed manually, the hierarchy doesn't really affect the routing process. The only place where the page hierarchy matters is the generated Menus. The generated menus reflect the page hierarchy. You can manage the page hierarchy by dragging pages in the page tree. The page drag handle appears when you move the mouse cursor over page item in the tree. + +Optional properties of static pages are **Hidden** and **Hide in navigation**. The **Hidden** checkbox allows to hide a page from the front-end. Hidden pages are still visible for administrators who are logged into the back-end. The **Hide in navigation** checkbox allows to hide a page from generated menus and breadcrumbs. + +## Placeholders + +If a static layout contains [placeholders](https://octobercms.com/docs/cms/layouts#placeholders), the static page editor will show tabs for editing the placeholder contents. The plugin automatically detects text and HTML placeholders and displays a corresponding editor for them - the WYSIWYG editor for HTML placeholders and a text editor for text placeholders. + +## Snippets + +Snippets are elements that can be added by a Static Page, in the rich text editor. They allow to inject complex (and interactive) areas to pages. There are many possible applications and examples of using Snippets: + +* Google Maps snippet - outputs a map centered on specific coordinates with predefined zoom factor. That snippet would be great for static pages that explain directions. +* Universal commenting system - allows visitors to post comments to any static page. +* Third-party integrations - for example with Yelp or TripAdvisor for displaying extra information on a static page. + +Snippets are displayed in the sidebar list on the Static Pages and can be added into a rich editor with a mouse click. Snippets are configurable and have properties that users can manage with the Inspector. + +![image](https://raw.githubusercontent.com/rainlab/pages-plugin/master/docs/images/snippets-backend.png) + +![image](https://raw.githubusercontent.com/rainlab/pages-plugin/master/docs/images/snippets-frontend.png) + +## Managing menus + +You can manage menus on the Menus tab of the Static Pages plugin. A website can contain multiple menus, for example the main menu, footer menu, sidebar menu, etc. A theme developer can include menus on a page layout with the `staticMenu` component. + +Menus have two required properties - the menu **Name** and menu **Code**. The menu name is displayed in the menu list in the back-end. The menu code is required for referring menus in the layout code, it's the API parameter. + +![image](https://raw.githubusercontent.com/rainlab/pages-plugin/master/docs/images/menu-management.png) {.img-responsive .frame} + +Menus can contain multiple **menu items**, and menu items can be nested. Each menu item has a number of properties. There are properties common for all menu item types, and some properties depend on the item type. The common menu item properties are **Title** and **Type**. The Title defines the menu item text. The Type is a drop-down list which displays all menu item types available in your OctoberCMS copy. + +![image](https://raw.githubusercontent.com/rainlab/pages-plugin/master/docs/images/menu-item.png) {.img-responsive .frame} + +#### Standard menu item types +The available menu item types depend on the installed plugins, but there are three basic item types that are supported out of the box. + +###### Header {.subheader} +Items of this type are used for displaying text and don't link to anything. The text could be used as a category heading for other menu items. This type will only show a title property. + +###### URL {.subheader} +Items of this type are links to a specific fixed URL. That could be an URL of an or internal page. Items of this type don't have any other properties - just the title and URL. + +###### Static Page {.subheader} +Items of this type refer to static pages. The static page should be selected in the **Reference** drop-down list described below. + +###### All Static Pages {.subheader} +Items of this type expand to create links to all static pages defined in the theme. Nested pages are represented with nested menu items. + +#### Custom menu item types +Other plugins can supply new menu item types. For example, the [Blog plugin](https://octobercms.com/plugin/rainlab-blog) by [RainLab](https://octobercms.com/author/RainLab) supplies two more types: + +###### Blog Category {.subheader} +An item of this type represents a link to a specific blog category. The category should be selected in the **Reference** drop-down. This menu type also requires selecting a **CMS page** that outputs a blog category. + +###### All Blog Categories {.subheader} +An item of this time expands into multiple items representing all blog existing categories. This menu type also requires selecting a **CMS page**. + +#### Menu item properties +Depending on the selected menu item time you might need to provide other properties of the menu item. The available properties are described below. + +###### Reference {.subheader} +A drop-down list of objects the menu item should refer to. The list content depends on the menu item type. For the **Static page** item type the list displays all static pages defined in the system. For the **Blog category** item type the list displays a list of blog categories. + +###### Allow nested items {.subheader} +This checkbox is available only for menu item types that suppose nested objects. For example, static pages are hierarchical, and this property is available for the **Static page** item type. On the other hand, blog categories are not hierarchical, and the checkbox is hidden. + +###### Replace this item with its generated children {.subheader} +A checkbox determining whether the menu item should be replaced with generated menu items. This property is available only for menu item types that suppose automatic item generating, for example for the **Static page** menu item type. The **Blog category** menu item type doesn't have this property because blog categories cannot be nested and menu items of this type always point to a specific blog category. This property is very handy when you want to include generated menu items to the root of the menu. For example, you can create the **All blog categories** menu item and enable the replacing. As a result you will get a menu that lists all blog categories on the first level of the menu. If you didn't enable the replacing, there would be a root menu item, with blog categories listed under it. + +###### CMS Page {.subheader} +This drop-down is available for menu item types that require a special CMS page to refer to. For example, the **Blog category** menu item type requires a CMS page that hosts the `blogPosts` component. The CMS Page drop-down for this item type will only display pages that include this component. + +###### Code {.subheader} +The Code field allows to assign the API code that you can use to set the active menu item explicitly in the page's `onInit()` handler described in the documentation. + +## See also + +Read the [Getting started with Static Pages](https://octobercms.com/blog/post/getting-started-static-pages) tutorial in the Blog. + +Read the [documentation](/docs/documentation.md). diff --git a/plugins/rainlab/pages/assets/css/pages.css b/plugins/rainlab/pages/assets/css/pages.css new file mode 100644 index 0000000..4e5bf28 --- /dev/null +++ b/plugins/rainlab/pages/assets/css/pages.css @@ -0,0 +1 @@ +.control-filelist.menu-list li>a{position:relative}.control-filelist.menu-list li>a:before{background-image:url(../images/menu-icons.png);background-position:0 0;background-repeat:no-repeat;background-size:36px auto;content:" ";height:18px;left:17px;position:absolute;top:18px;width:18px}.control-filelist.menu-list li.active>a:before,.control-filelist.menu-list li>a:hover:before{background-position:0 -60px}.control-filelist.content li>a{position:relative}.control-filelist.content li>a:before{background-image:url(../images/content-icons.png);background-position:0 0;background-repeat:no-repeat;background-size:34px auto;content:" ";height:22px;left:18px;position:absolute;top:10px;width:18px}.control-filelist.content li.active>a:before,.control-filelist.content li>a:hover:before{background-position:0 -27px}.control-filelist.content li.group ul li>a:before{left:34px}.control-filelist.snippet-list li>a{color:#808c8d;position:relative}.control-filelist.snippet-list li>a:before{background-image:url(../images/snippet-icons.png);background-position:0 0;background-repeat:no-repeat;background-size:34px auto;content:" ";height:19px;left:18px;position:absolute;top:13px;top:12px;width:17px}.control-filelist.snippet-list li>a:hover:before{background-position:0 -21px}.control-filelist.snippet-list li.group ul li>a:before{left:34px}@media only screen and (-moz-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-filelist.menu-list li>a:before{background-position:0 -11px;background-size:18px auto}.control-filelist.menu-list li.active>a:before,.control-filelist.menu-list li>a:hover:before{background-position:0 -40px}.control-filelist.content li a:before{background-position:0 -27px;background-size:17px auto}.control-filelist.content li a:hover:before,.control-filelist.content li.active a:before{background-position:0 -52px}.control-filelist.snippet-list li a:before{background-position:0 -21px;background-size:17px auto}.control-filelist.snippet-list li a:hover:before{background-position:0 -41px}}.fancy-layout .pagesTextEditor{border-left:1px solid #cfd7e1!important}.control-richeditor [data-snippet]:before{content:attr(data-name)}.control-richeditor [data-snippet]:after{background-image:url(../images/snippet-icons.png);background-position:0 0;background-repeat:no-repeat;background-size:34px auto;content:" ";height:19px;left:18px;left:11px;position:absolute;top:13px;top:12px;width:17px}.control-richeditor [data-snippet].loading:after{-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite;background-image:url(../images/loader-transparent.svg);background-position:50% 50%;background-size:15px 15px;content:" ";height:15px;position:absolute;top:13px;width:15px}@media only screen and (-moz-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-richeditor [data-snippet]:after{background-position:0 -21px;background-size:17px auto}} diff --git a/plugins/rainlab/pages/assets/css/treeview.css b/plugins/rainlab/pages/assets/css/treeview.css new file mode 100644 index 0000000..ae3024d --- /dev/null +++ b/plugins/rainlab/pages/assets/css/treeview.css @@ -0,0 +1 @@ +.control-treeview{margin-bottom:40px}.control-treeview ol{background:#fff;list-style:none;margin:0;padding:0}.control-treeview ol>li{transition:width 1s}.control-treeview ol>li>div{background:#fff;border-bottom:1px solid #f0f4f8;font-size:14px;font-weight:400;position:relative}.control-treeview ol>li>div>a{box-sizing:border-box;color:#2b3e50;display:block;line-height:150%;padding:11px 45px 10px 61px;text-decoration:none}.control-treeview ol>li>div:before{background-image:url(../images/treeview-icons.png);background-position:0 -28px;background-repeat:no-repeat;background-size:42px auto;content:" ";height:22px;left:28px;position:absolute;top:15px;width:21px}.control-treeview ol>li>div span.comment{color:#95a5a6;display:block;font-size:13px;font-weight:400;margin-top:2px;overflow:hidden;text-overflow:ellipsis}.control-treeview ol>li>div>span.expand{background-color:transparent;border:0;color:transparent;color:#bdc3c7;cursor:pointer;display:none;font:0/0 a;height:20px;left:2px;position:absolute;text-shadow:none;top:19px;transition:transform .1s ease;width:20px}.control-treeview ol>li>div>span.expand:before{-webkit-font-smoothing:antialiased;content:"\f0da";font-family:FontAwesome;font-size:15px;font-style:normal;font-weight:400;left:8px;line-height:100%;position:relative;text-decoration:inherit;top:2px}.control-treeview ol>li>div>span.drag-handle{background-color:transparent;border:0;bottom:0;color:transparent;color:#bdc3c7;cursor:move;font:0/0 a;height:19px;opacity:0;position:absolute;right:9px;text-shadow:none;transition:opacity .4s;width:18px}.control-treeview ol>li>div>span.drag-handle:before{-webkit-font-smoothing:antialiased;content:"\f0c9";font-family:FontAwesome;font-size:18px;font-style:normal;font-weight:400;text-decoration:inherit}.control-treeview ol>li>div span.borders{font-size:0}.control-treeview ol>li>div>ul.submenu{background-color:#7476f8;border-bottom-left-radius:8px;border-bottom-right-radius:8px;bottom:-26.9px;box-shadow:inset 0 3px 3px -3px rgba(0,0,0,.2);display:none;height:27px;left:20px;list-style:none;margin-left:15px;padding:0;position:absolute;z-index:200}.control-treeview ol>li>div>ul.submenu [data-control=create-object]{padding-left:15px;padding-right:15px}.control-treeview ol>li>div>ul.submenu li{font-size:12px}.control-treeview ol>li>div>ul.submenu li a{color:#fff;display:block;outline:none;padding:4px 3px 0;text-decoration: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-color:#5254f6}.control-treeview ol>li>div .checkbox{position:absolute;right:0;top:-2px}.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:#6a6cf7!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>span.drag-handle,.control-treeview ol>li>div.popover-highlight>ul.submenu{display:none!important}.control-treeview ol>li.dragged div,.control-treeview ol>li>div:hover{background-color:#6a6cf7!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{bottom:0!important;top: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}.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:#5254f6!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:.3!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;height:26px;left:26px;width:23px}.control-treeview ol>li.has-subitems>div.popover-highlight:before,.control-treeview ol>li.has-subitems>div:hover:before{background-position:0 -52px}.control-treeview ol>li.has-subitems>div span.expand{display:block}.control-treeview ol>li.placeholder{opacity:.5;position:relative}.control-treeview ol>li.dragged{opacity:.25;position:absolute;z-index:2000}.control-treeview ol>li.dragged>div{border-radius:3px}.control-treeview ol>li.drop-target>div{background-color:#2581b8!important}.control-treeview ol>li.drop-target>div>a,.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{transform:rotate(90deg) translate(0)}.control-treeview ol>li.drag-ghost{background-color:transparent;box-sizing:content-box}.control-treeview ol>li.active>div{background:#6bc48d}.control-treeview ol>li.active>div>a,.control-treeview ol>li.active>div>a>span.comment,.control-treeview ol>li.active>div>a>span.expand,.control-treeview ol>li.active>div>span.expand{color:#fff}.control-treeview ol>li.active>div>span.borders:after,.control-treeview ol>li.active>div>span.borders:before{background-color:#6bc48d;content:" ";display:block;height:1px;left:0;position:absolute;width:100%}.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.active>div:before{background-position:0 -80px}.control-treeview ol>li.active.has-subitems>div:before{background-position:0 -52px}.control-treeview ol>li.no-data{color:#666;font-size:14px;font-weight:400;margin:0;padding:18px 0;text-align:center}.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{color:#666;font-size:14px;font-weight:400;margin:0;padding:18px 0;text-align:center}.control-treeview a.menu-control{border:2px dotted #ebebeb;border-radius:5px;color:#bdc3c7;display:block;font-size:12px;font-weight:600;margin:20px;padding:13px 15px;text-transform:uppercase;vertical-align:middle}.control-treeview a.menu-control:focus,.control-treeview a.menu-control:hover{background-color:#6a6cf7;border:none;color:#fff;padding:15px 17px;text-decoration:none}.control-treeview a.menu-control:active{background:#5254f6;color:#fff}.control-treeview a.menu-control i{font-size:14px;margin-right:10px}.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-bottom:10px;padding-top:10px}.control-treeview.treeview-light ol>li>div span.expand{top:19px}.control-treeview.treeview-light ol>li>div>span.drag-handle{background:#8284f8;bottom:auto;height:100%;right:0;top:0;transition:none!important;width:60px}.control-treeview.treeview-light ol>li>div>span.drag-handle:before{left:50%;margin-left:-6px;position:absolute;top:50%}.control-treeview.treeview-light ol>li>div>ul.submenu{background:transparent;bottom:auto;font-size:0;height:100%;left:auto;margin:0;right:60px;top:0;white-space:nowrap}.control-treeview.treeview-light ol>li>div>ul.submenu:after,.control-treeview.treeview-light ol>li>div>ul.submenu:before{display:none}.control-treeview.treeview-light ol>li>div>ul.submenu li{background:#8284f8;border-right:1px solid #6a6cf7;display:inline-block;height:100%}.control-treeview.treeview-light ol>li>div>ul.submenu li p{display:table;height:100%;margin:0;padding:0}.control-treeview.treeview-light ol>li>div>ul.submenu li p a{box-sizing:border-box;display:table-cell;font-size:13px;height:100%;padding:0 20px;vertical-align:middle}.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:20px;transition:padding 1s}body.dragging .control-treeview ol.dragging ol>li>div,body.dragging .control-treeview ol.dragging>li>div{margin-right:0;transition:margin 1s}body.dragging .control-treeview ol.dragging ol>li>div .custom-checkbox,body.dragging .control-treeview ol.dragging>li>div .custom-checkbox{opacity:0;transition:opacity .5s}body.dragging .control-treeview.treeview-light ol.dragging ol>li>div,body.dragging .control-treeview.treeview-light ol.dragging>li>div{background-color:#f9f9f9}@media 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.active>div:before,.control-treeview ol>li.has-subitems>div.popover-highlight:before,.control-treeview ol>li.has-subitems>div:hover:before{background-position:0 -102px}.control-treeview ol>li.active>div:before,.control-treeview ol>li.dragged li>div:before,.control-treeview ol>li.dragged>div:before,.control-treeview ol>li>div.popover-highlight:before,.control-treeview ol>li>div:hover: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}} diff --git a/plugins/rainlab/pages/assets/images/content-icons.png b/plugins/rainlab/pages/assets/images/content-icons.png new file mode 100644 index 0000000..893dc71 Binary files /dev/null and b/plugins/rainlab/pages/assets/images/content-icons.png differ diff --git a/plugins/rainlab/pages/assets/images/loader-transparent.svg b/plugins/rainlab/pages/assets/images/loader-transparent.svg new file mode 100644 index 0000000..cf84589 --- /dev/null +++ b/plugins/rainlab/pages/assets/images/loader-transparent.svg @@ -0,0 +1,20 @@ + + + +]> + + + + + + + + diff --git a/plugins/rainlab/pages/assets/images/menu-icons.png b/plugins/rainlab/pages/assets/images/menu-icons.png new file mode 100644 index 0000000..f3641e9 Binary files /dev/null and b/plugins/rainlab/pages/assets/images/menu-icons.png differ diff --git a/plugins/rainlab/pages/assets/images/pages-icon.svg b/plugins/rainlab/pages/assets/images/pages-icon.svg new file mode 100644 index 0000000..f17deac --- /dev/null +++ b/plugins/rainlab/pages/assets/images/pages-icon.svg @@ -0,0 +1,31 @@ + + + + pages-icon + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/rainlab/pages/assets/images/snippet-icons.png b/plugins/rainlab/pages/assets/images/snippet-icons.png new file mode 100644 index 0000000..3d0b66f Binary files /dev/null and b/plugins/rainlab/pages/assets/images/snippet-icons.png differ diff --git a/plugins/rainlab/pages/assets/images/treeview-icons.png b/plugins/rainlab/pages/assets/images/treeview-icons.png new file mode 100644 index 0000000..a08c70b Binary files /dev/null and b/plugins/rainlab/pages/assets/images/treeview-icons.png differ diff --git a/plugins/rainlab/pages/assets/images/treeview-submenu-tabs.png b/plugins/rainlab/pages/assets/images/treeview-submenu-tabs.png new file mode 100644 index 0000000..6c39867 Binary files /dev/null and b/plugins/rainlab/pages/assets/images/treeview-submenu-tabs.png differ diff --git a/plugins/rainlab/pages/assets/js/october.treeview.js b/plugins/rainlab/pages/assets/js/october.treeview.js new file mode 100644 index 0000000..f443429 --- /dev/null +++ b/plugins/rainlab/pages/assets/js/october.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 (october.treelist.js) + * + */ ++function ($) { "use strict"; + var Base = $.oc.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) + + $.oc.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 div.tab-content > div.tab-pane[data-modified]', this.$masterTabs).each(function(){ + var inputType = $('> form > input[name=objectType]', this).val() + counters[inputType].count++ + }) + + $.each(counters, function(type, data){ + $.oc.sideNav.setCounter('pages/' + data.menu, data.count); + }) + } + + /* + * Triggered when a tab is displayed. Updated the current selection in the sidebar and sets focus on an editor. + */ + PagesPage.prototype.onTabShown = function(e) { + var $tabControl = $(e.target).closest('[data-control=tab]') + + if ($tabControl.attr('id') == 'pages-master-tabs') { + var dataId = $(e.target).closest('li').attr('data-tab-id'), + title = $(e.target).attr('title') + + if (title) + this.setPageTitle(title) + + this.$pageTree.treeView('markActive', dataId) + $('[data-control=filelist]', this.$sidePanel).fileList('markActive', dataId) + $(window).trigger('resize') + } else if ($tabControl.hasClass('secondary')) { + // TODO: Focus the code or rich editor here + } + } + + /* + * Triggered when all master tabs are closed. + */ + PagesPage.prototype.onAllTabsClosed = function() { + this.$pageTree.treeView('markActive', null) + $('[data-control=filelist]', this.$sidePanel).fileList('markActive', null) + this.setPageTitle('') + } + + /* + * Triggered when a master tab is closed. + */ + PagesPage.prototype.onTabClosed = function() { + this.updateModifiedCounter() + } + + /* + * Handles AJAX errors in the master tab forms. Processes the mtime mismatch condition (concurrency). + */ + PagesPage.prototype.onAjaxError = function(event, context, message, data, jqXHR) { + if (context.handler != 'onSave') + return + + if (jqXHR.responseText == 'mtime-mismatch') { + event.preventDefault() + this.handleMtimeMismatch(event.target) + } + } + + /* + * Handles successful AJAX request in the master tab forms. Updates the UI elements and resets the mtime value. + */ + PagesPage.prototype.onAjaxSuccess = function(event, context, data) { + var $form = $(event.currentTarget), + $tabPane = $form.closest('.tab-pane') + + // Update the visibilities of the commit & reset buttons + $('[data-control=commit-button]', $form).toggleClass('oc-hide hide', !data.canCommit) + $('[data-control=reset-button]', $form).toggleClass('oc-hide hide', !data.canReset) + + if (data.objectPath !== undefined) { + $('input[name=objectPath]', $form).val(data.objectPath) + $('input[name=objectMtime]', $form).val(data.objectMtime) + $('[data-control=delete-button]', $form).removeClass('oc-hide hide') + $('[data-control=preview-button]', $form).removeClass('oc-hide hide') + + if (data.pageUrl !== undefined) + $('[data-control=preview-button]', $form).attr('href', data.pageUrl) + } + + if (data.tabTitle !== undefined) { + this.$masterTabs.ocTab('updateTitle', $tabPane, data.tabTitle) + this.setPageTitle(data.tabTitle) + } + + var tabId = $('input[name=objectType]', $form).val() + '-' + + $('input[name=theme]', $form).val() + '-' + + $('input[name=objectPath]', $form).val(); + + this.$masterTabs.ocTab('updateIdentifier', $tabPane, tabId) + this.$pageTree.treeView('markActive', tabId) + $('[data-control=filelist]', this.$sidePanel).fileList('markActive', tabId) + + var objectType = $('input[name=objectType]', $form).val() + if (objectType.length > 0 && + (context.handler == 'onSave' || context.handler == 'onCommit' || context.handler == 'onReset') + ) + + this.updateObjectList(objectType); + + if (context.handler == 'onSave' && (!data['X_OCTOBER_ERROR_FIELDS'] && !data['X_OCTOBER_ERROR_MESSAGE'])) + $form.trigger('unchange.oc.changeMonitor') + + // Reload the form if the server has requested it + if (data.forceReload) { + this.reloadForm($form) + } + } + + PagesPage.prototype.onBeforeSaveContent = function(e, data) { + var form = e.currentTarget, + $tabPane = $(form).closest('.tab-pane') + + this.updateContentEditorMode($tabPane, false) + } + + PagesPage.prototype.onDeletePageSingle = function(el) { + var $el = $(el); + + $el.request('onDelete', { + success: function(data) { + $.oc.pagesPage.closeTabs(data, 'page'); + $.oc.pagesPage.updateObjectList('page'); + $(this).trigger('close.oc.tab', [{force: true}]); + } + }); + } + + /* + * Updates the browser title when an object is saved. + */ + PagesPage.prototype.setPageTitle = function(title) { + $.oc.layout.setPageTitle(title.length ? (title + ' | ') : title) + } + + /* + * Updates the sidebar object list. + */ + PagesPage.prototype.updateObjectList = function(objectType) { + var $form = $('form[data-object-type='+objectType+']', this.$sidePanel), + objectList = objectType + 'List', + self = this + + $.oc.stripeLoadIndicator.show() + $form.request(objectList + '::onUpdate', { + complete: function(data) { + $('button[data-control=delete-object], button[data-control=delete-template]', $form).trigger('oc.triggerOn.update') + } + }).always(function(){ + $.oc.stripeLoadIndicator.hide() + }); + } + + /* + * Closes deleted page tabs in the editor area. + */ + PagesPage.prototype.closeTabs = function(data, type) { + var self = this + + $.each(data.deletedObjects, function(){ + var tabId = type + '-' + data.theme + '-' + this, + tab = self.masterTabsObj.findByIdentifier(tabId) + + $(tab).trigger('close.oc.tab', [{force: true}]) + }) + } + + /* + * Triggered when an item is clicked in the sidebar. Opens the item in the editor. + * If the item is already opened, activate its tab in the editor. + */ + PagesPage.prototype.onSidebarItemClick = function(e) { + var self = this, + $item = $(e.relatedTarget), + $form = $item.closest('form'), + theme = $('input[name=theme]', $form).val(), + data = { + type: $form.data('object-type'), + theme: theme, + path: $item.data('item-path') + }, + tabId = data.type + '-' + data.theme + '-' + data.path + + if ($item.data('type') == 'snippet') { + this.snippetManager.onSidebarSnippetClick($item); + return; + } + + /* + * Find if the tab is already opened + */ + + if (this.masterTabsObj.goTo(tabId)) { + return false; + } + + /* + * Open a new tab + */ + + $.oc.stripeLoadIndicator.show() + $form.request('onOpen', { + data: data + }).done(function(data) { + self.$masterTabs.ocTab('addTab', data.tabTitle, data.tab, tabId, $form.data('type-icon')); + }).always(function() { + $.oc.stripeLoadIndicator.hide(); + }) + + return false + } + + /* + * Triggered when the Add button is clicked on the sidebar + */ + PagesPage.prototype.onCreateObject = function(e) { + var self = this, + $button = $(e.target), + $form = $button.closest('form'), + parent = $button.data('parent') !== undefined ? $button.data('parent') : null, + type = $form.data('object-type') ? $form.data('object-type') : $form.data('template-type'), + tabId = type + Math.random() + + $.oc.stripeLoadIndicator.show() + $form.request('onCreateObject', { + data: { + type: type, + parent: parent + } + }).done(function(data){ + self.$masterTabs.ocTab('addTab', data.tabTitle, data.tab, tabId, $form.data('type-icon') + ' new-template') + $('#layout-side-panel').trigger('close.oc.sidePanel') + self.setPageTitle(data.tabTitle) + }).always(function(){ + $.oc.stripeLoadIndicator.hide() + }) + + e.stopPropagation() + + return false; + } + + /* + * Triggered when an item is clicked in the sidebar submenu + */ + PagesPage.prototype.onSidebarSubmenuItemClick = function(e) { + if ($(e.clickEvent.target).data('control') == 'create-object') { + this.onCreateObject(e.clickEvent); + } + + return false; + } + + /* + * Triggered when the Delete button is clicked on the sidebar + */ + PagesPage.prototype.onDeleteObject = function(e) { + var $el = $(e.target), + $form = $el.closest('form'), + objectType = $form.data('object-type'), + self = this + + if (!confirm($el.data('confirmation'))) + return + + $form.request('onDeleteObjects', { + data: { + type: objectType + }, + success: function(data) { + $.each(data.deleted, function(index, path){ + var tabId = objectType + '-' + data.theme + '-' + path, + tab = self.masterTabsObj.findByIdentifier(tabId) + + self.$masterTabs.ocTab('closeTab', tab, true) + }) + + if (data.error !== undefined && $.type(data.error) === 'string' && data.error.length) + $.oc.flashMsg({text: data.error, 'class': 'error'}) + }, + complete: function() { + self.updateObjectList(objectType) + } + }) + + return false + } + + /* + * Triggered when a static page layout changes + */ + PagesPage.prototype.onLayoutChanged = function(e) { + var + self = this, + $el = $(e.target), + $form = $el.closest('form'), + $pane = $form.closest('.tab-pane'), + data = { + type: $('[name=objectType]', $form).val(), + theme: $('[name=theme]', $form).val(), + path: $('[name=objectPath]', $form).val() + }, + tab = $pane.data('tab') + + // $form.trigger('unchange.oc.changeMonitor') + $form.changeMonitor('dispose') + + $.oc.stripeLoadIndicator.show() + + $form + .request('onUpdatePageLayout', { + data: data + }) + .done(function(data){ + self.$masterTabs.ocTab('updateTab', tab, data.tabTitle, data.tab) + }) + .always(function(){ + $.oc.stripeLoadIndicator.hide() + $('form:first', $pane).changeMonitor().trigger('change') + }) + } + + /* + * Triggered when a new tab is added to the Editor + */ + PagesPage.prototype.onInitTab = function(e, data) { + if ($(e.target).attr('id') != 'pages-master-tabs') + return + + var $collapseIcon = $(''), + $panel = $('.form-tabless-fields', data.pane), + $secondaryPanel = $('.control-tabs.secondary-tabs', data.pane), + $primaryPanel = $('.control-tabs.primary-tabs', data.pane), + hasSecondaryTabs = $secondaryPanel.length > 0 + + $secondaryPanel.addClass('secondary-content-tabs') + + // Disable fancy layout on nested forms + $('.form-tabless-fields', $secondaryPanel).addClass('not-fancy'); + + $panel.append($collapseIcon) + + if (!hasSecondaryTabs) { + $primaryPanel.parent().removeClass('min-size'); + } + + $secondaryPanel.find('> .tab-content > .tab-pane').not(':has(>.form-group[data-field-name=markup],>div>div.stretch)').addClass('padded-pane'); + $secondaryPanel.find('> .layout-row > .nav-tabs > li:gt(0)').addClass('tab-content-bg'); + + $collapseIcon.click(function(){ + $panel.toggleClass('collapsed') + + if (typeof(localStorage) !== 'undefined') + localStorage.ocPagesTablessCollapsed = $panel.hasClass('collapsed') ? 1 : 0 + + window.setTimeout(function(){ + $(window).trigger('oc.updateUi') + }, 500) + + return false + }) + + var $primaryCollapseIcon = $('') + + if ($primaryPanel.length > 0) { + $secondaryPanel.append($primaryCollapseIcon) + + $primaryCollapseIcon.click(function(){ + $primaryPanel.toggleClass('collapsed') + $secondaryPanel.toggleClass('primary-collapsed') + $(window).trigger('oc.updateUi') + if (typeof(localStorage) !== 'undefined') + localStorage.ocPagesPrimaryCollapsed = $primaryPanel.hasClass('collapsed') ? 1 : 0 + return false + }) + } else { + $secondaryPanel.addClass('primary-collapsed') + } + + if (typeof(localStorage) !== 'undefined') { + if (!$('a', data.tab).hasClass('new-template') && localStorage.ocPagesTablessCollapsed == 1) + $panel.addClass('collapsed') + + if (localStorage.ocPagesPrimaryCollapsed == 1 && hasSecondaryTabs) { + $primaryPanel.addClass('collapsed') + $secondaryPanel.addClass('primary-collapsed') + } + } + + var $form = $('form', data.pane), + self = this, + $panel = $('.form-tabless-fields', data.pane) + + this.updateContentEditorMode(data.pane, true) + + $form.on('changed.oc.changeMonitor', function() { + $panel.trigger('modified.oc.tab') + $panel.find('[data-control=commit-button]').addClass('oc-hide hide'); + $panel.find('[data-control=reset-button]').addClass('oc-hide hide'); + self.updateModifiedCounter() + }) + + $form.on('unchanged.oc.changeMonitor', function() { + $panel.trigger('unmodified.oc.tab') + self.updateModifiedCounter() + }) + } + + /* + * Triggered before a menu is saved + */ + PagesPage.prototype.onSaveMenu = function(e, data) { + var form = e.currentTarget, + items = [], + $items = $('div[data-control=treeview] > ol > li', form) + + var iterator = function(items) { + var result = [] + + $.each(items, function() { + var item = $(this).data('menu-item') + + var $subitems = $('> ol >li', this) + if ($subitems.length) + item['items'] = iterator($subitems) + + result.push(item) + }) + + return result + } + + data.options.data['itemData'] = JSON.stringify(iterator($items)) + } + + /* + * Updates the content editor to correspond to the content file extension + */ + PagesPage.prototype.updateContentEditorMode = function(pane, initialization) { + if ($('[data-toolbar-type]', pane).data('toolbar-type') !== 'content') + return + + var extension = this.getContentExtension(pane), + mode = 'html', + editor = $('[data-control=codeeditor]', pane) + + if (extension == 'html') + extension = 'htm' + + if (initialization) + $(pane).data('prev-extension', extension) + + if (extension == 'htm') { + $('[data-field-name=markup]', pane).hide() + $('[data-field-name=markup_html]', pane).show() + + if (!initialization && $(pane).data('prev-extension') != 'htm') { + var val = editor.codeEditor('getContent') + $('div[data-control=richeditor]', pane).richEditor('setContent', val) + } + } + else { + $('[data-field-name=markup]', pane).show() + $('[data-field-name=markup_html]', pane).hide() + + if (!initialization && $(pane).data('prev-extension') == 'htm') { + var val = $('div[data-control=richeditor]', pane).richEditor('getContent') + editor.codeEditor('setContent', val) + } + + var modes = $.oc.codeEditorExtensionModes + + if (modes[extension] !== undefined) + mode = modes[extension]; + + var setEditorMode = function() { + window.setTimeout(function(){ + editor.codeEditor('getEditorObject') + .getSession() + .setMode({ path: 'ace/mode/'+mode }) + }, 200) + } + + if (initialization) + editor.on('oc.codeEditorReady', setEditorMode) + else + setEditorMode() + } + + if (!initialization) + $(pane).data('prev-extension', extension) + } + + /* + * Returns the content file extension + */ + PagesPage.prototype.getContentExtension = function(form) { + var $input = $('input[name=fileName]', form), + fileName = $input.length ? $input.val() : '', + parts = fileName.split('.') + + if (parts.length >= 2) + return parts.pop().toLowerCase() + + return 'htm' + } + + $(document).ready(function(){ + $.oc.pagesPage = new PagesPage() + }) + +}(window.jQuery); diff --git a/plugins/rainlab/pages/assets/js/pages-snippets.js b/plugins/rainlab/pages/assets/js/pages-snippets.js new file mode 100644 index 0000000..16fd3be --- /dev/null +++ b/plugins/rainlab/pages/assets/js/pages-snippets.js @@ -0,0 +1,213 @@ +/* + * Handles snippet operations on the Pages main page + */ ++function ($) { "use strict"; + if ($.oc.pages === undefined) + $.oc.pages = {} + + var SnippetManager = function ($masterTabs) { + this.$masterTabs = $masterTabs + + var self = this + + $(document).on('hidden.oc.inspector', '.field-richeditor [data-snippet]', function() { + self.syncEditorCode(this) + }) + + $(document).on('init.oc.richeditor', '.field-richeditor textarea', function(ev, richeditor) { + self.initSnippets(richeditor.getElement()) + }) + + $(document).on('setContent.oc.richeditor', '.field-richeditor textarea', function(ev, richeditor) { + if (!richeditor.isCodeViewActive()) { + self.initSnippets(richeditor.getElement()) + } + }) + + $(document).on('syncContent.oc.richeditor', '.field-richeditor textarea', function(ev, richeditor, container) { + self.syncPageMarkup(ev, container) + }) + + $(document).on('figureKeydown.oc.richeditor', '.field-richeditor textarea', function(ev, originalEv, richeditor) { + self.editorKeyDown(ev, originalEv, richeditor) + }) + + $(document).on('click', '[data-snippet]', function() { + if ($(this).hasClass('inspector-open')) { + return + } + + $.oc.inspector.manager.createInspector(this) + return false + }) + } + + SnippetManager.prototype.onSidebarSnippetClick = function($sidebarItem) { + var $pageForm = $('div.tab-content > .tab-pane.active form[data-object-type=page]', this.$masterTabs) + + if (!$pageForm.length) { + $.oc.alert('Snippets can only be added to Pages. Please open or create a Page first.') + return + } + + var $activeEditorTab = $('.control-tabs.secondary-tabs .tab-pane.active', $pageForm), + $textarea = $activeEditorTab.find('[data-control="richeditor"] textarea'), + $richeditorNode = $textarea.closest('[data-control="richeditor"]'), + $snippetNode = $('
     
    '), + componentClass = $sidebarItem.attr('data-component-class'), + snippetCode = $sidebarItem.data('snippet') + + if (!$textarea.length) { + $.oc.alert('Snippets can only be added to page Content or HTML placeholders.') + return + } + + if (componentClass) { + $snippetNode.attr({ + 'data-component': componentClass, + 'data-inspector-class': componentClass + }) + + // If a component-based snippet was added, make sure that + // its code is unique, as it will be used as a component + // alias. + + snippetCode = this.generateUniqueComponentSnippetCode(componentClass, snippetCode, $pageForm) + } + + $snippetNode.attr({ + 'data-snippet': snippetCode, + 'data-name': $sidebarItem.data('snippet-name'), + 'tabindex': '0', + 'draggable': 'true', + 'data-ui-block': 'true' + }) + + $snippetNode.addClass('fr-draggable') + + $richeditorNode.richEditor('insertUiBlock', $snippetNode) + } + + SnippetManager.prototype.generateUniqueComponentSnippetCode = function(componentClass, originalCode, $pageForm) { + var updatedCode = originalCode, + counter = 1, + snippetFound = false + + do { + snippetFound = false + + $('[data-control="richeditor"] textarea', $pageForm).each(function(){ + var $textarea = $(this), + $codeDom = $('
    ' + $textarea.val() + '
    ') + + if ($codeDom.find('[data-snippet="'+updatedCode+'"][data-component]').length > 0) { + snippetFound = true + updatedCode = originalCode + counter + counter++ + + return false + } + }) + + } while (snippetFound) + + return updatedCode + } + + SnippetManager.prototype.syncEditorCode = function(inspectable) { + // Race condition + setTimeout(function() { + var $richeditor = $(inspectable).closest('[data-control=richeditor]') + $richeditor.richEditor('syncContent') + inspectable.focus() + }, 0) + } + + SnippetManager.prototype.initSnippets = function($editor) { + var snippetCodes = [] + + $('.fr-view [data-snippet]', $editor).each(function(){ + var $snippet = $(this), + snippetCode = $snippet.attr('data-snippet'), + componentClass = $snippet.attr('data-component') + + if (componentClass) + snippetCode += '|' + componentClass + + snippetCodes.push(snippetCode) + + $snippet + .addClass('loading') + .addClass('fr-draggable') + .attr({ + 'data-inspector-css-class': 'hero', + 'data-name': 'Loading...', + 'data-ui-block': 'true', + 'draggable': 'true', + 'tabindex': '0' + }) + .html(' ') + + if (componentClass) { + $snippet.attr('data-inspector-class', componentClass) + } + + this.contentEditable = false + }) + + if (snippetCodes.length > 0) { + var request = $editor.request('onGetSnippetNames', { + data: { + codes: snippetCodes + } + }).done(function(data) { + if (data.names !== undefined) { + $.each(data.names, function(code){ + $('[data-snippet="'+code+'"]', $editor) + .attr('data-name', this) + .removeClass('loading') + }) + } + }) + } + } + + SnippetManager.prototype.syncPageMarkup = function(ev, container) { + var $domTree = $('
    '+container.html+'
    ') + + $('[data-snippet]', $domTree).each(function(){ + var $snippet = $(this) + + $snippet.removeAttr('contenteditable data-name tabindex data-inspector-css-class data-inspector-class data-property-inspectorclassname data-property-inspectorproperty data-ui-block draggable') + $snippet.removeClass('fr-draggable fr-dragging') + + if (!$snippet.attr('class')) { + $snippet.removeAttr('class') + } + }) + + container.html = $domTree.html() + } + + SnippetManager.prototype.editorKeyDown = function(ev, originalEv, richeditor) { + if (richeditor.getTextarea() === undefined) + return + + if (originalEv.target && $(originalEv.target).attr('data-snippet') !== undefined) { + this.snippetKeyDown(originalEv, originalEv.target) + } + } + + SnippetManager.prototype.snippetKeyDown = function(ev, snippet) { + if (ev.which == 32) { + switch (ev.which) { + case 32: + // Space key + $.oc.inspector.manager.createInspector(snippet) + break + } + } + } + + $.oc.pages.snippetManager = SnippetManager +}(window.jQuery); diff --git a/plugins/rainlab/pages/assets/less/pages.less b/plugins/rainlab/pages/assets/less/pages.less new file mode 100644 index 0000000..107a35d --- /dev/null +++ b/plugins/rainlab/pages/assets/less/pages.less @@ -0,0 +1,209 @@ +@import "../../../../../modules/backend/assets/less/core/boot.less"; + +.control-filelist.menu-list { + li { + > a { + position: relative; + + &:before { + position: absolute; + width: 18px; + height: 18px; + left: 17px; + top: 18px; + + content: ' '; + + background-image: url(../images/menu-icons.png); + background-position: 0 0; + background-repeat: no-repeat; + background-size: 36px auto; + } + + &:hover { + &:before { + background-position: 0 -60px; + } + } + } + + &.active > a:before { + background-position: 0 -60px; + } + } +} + +.control-filelist.content { + li > a { + position: relative; + + &:before { + position: absolute; + width: 18px; + height: 22px; + left: 18px; + top: 10px; + + content: ' '; + + background-image: url(../images/content-icons.png); + background-position: 0 0; + background-repeat: no-repeat; + background-size: 34px auto; + } + + &:hover { + &:before { + background-position: 0 -27px; + } + } + } + + li.active > a:before { + background-position: 0 -27px; + } + + li.group ul li > a:before { + left: 34px; + } +} + +.page-snippet-icon() { + position: absolute; + width: 17px; + height: 19px; + left: 18px; + top: 13px; + + content: ' '; + + background-image: url(../images/snippet-icons.png); + background-position: 0 0; + background-repeat: no-repeat; + background-size: 34px auto; +} + +.control-filelist.snippet-list { + li > a { + position: relative; + color: #808c8d; + + &:before { + .page-snippet-icon(); + + left: 18px; + top: 12px; + } + + &:hover { + &:before { + background-position: 0 -21px; + } + } + } + + li.group ul li > a:before { + left: 34px; + } +} + +@media only screen and (-moz-min-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-filelist.menu-list { + li { + > a { + &:before { + background-position: 0px -11px; + background-size: 18px auto; + } + + &:hover { + &:before { + background-position: 0px -40px; + } + } + } + + &.active > a:before { + background-position: 0px -40px; + } + } + } + + .control-filelist.content { + li { + a { + &:before { + background-position: 0px -27px; + background-size: 17px auto; + } + + &:hover { + &:before { + background-position: 0px -52px; + } + } + } + + &.active a:before { + background-position: 0px -52px; + } + } + } + + .control-filelist.snippet-list { + li { + a { + &:before { + background-position: 0px -21px; + background-size: 17px auto; + } + + &:hover { + &:before { + background-position: 0px -41px; + } + } + } + } + } +} + +.fancy-layout { + .pagesTextEditor { + border-left: 1px solid @color-form-field-border!important; + } +} + +.control-richeditor { + [data-snippet] { + &:before { + content: attr(data-name); + } + + &:after { + .page-snippet-icon(); + + left: 11px; + top: 12px; + } + + &.loading:after { + background-image:url(../images/loader-transparent.svg); + background-size: 15px 15px; + background-position: 50% 50%; + position: absolute; + width: 15px; + height: 15px; + top: 13px; + content: ' '; + .animation(spin 1s linear infinite); + } + } +} + +@media only screen and (-moz-min-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-richeditor [data-snippet]:after { + background-position: 0px -21px; + background-size: 17px auto; + } +} diff --git a/plugins/rainlab/pages/assets/less/treeview.less b/plugins/rainlab/pages/assets/less/treeview.less new file mode 100644 index 0000000..906d991 --- /dev/null +++ b/plugins/rainlab/pages/assets/less/treeview.less @@ -0,0 +1,629 @@ +@import "../../../../../modules/backend/assets/less/core/boot.less"; + +@color-treeview-item-bg: #ffffff; +@color-treeview-item-title: #2b3e50; +@color-treeview-item-comment: #95a5a6; +@color-treeview-control: #bdc3c7; +@color-treeview-hover-bg: @brand-primary; +@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: #ffffff; +@color-treeview-light-submenu-bg: lighten(@brand-primary, 5%); +@color-treeview-light-submenu-border: @brand-primary; +@color-panel-light: #f0f4f8; +@font-size-base: 14px; + +.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; + } + + > 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: -26.9px; + padding: 0; + list-style: none; + z-index: 200; + height: 27px; + display: none; + margin-left: 15px; + background-color: lighten(@color-treeview-hover-bg, 2%); + .border-bottom-radius(8px); + .box-shadow(~"inset 0 3px 3px -3px rgba(0, 0, 0, 0.2)"); + + [data-control="create-object"] { + padding-left: 15px; + padding-right: 15px; + } + + li { + font-size: @font-size-base - 2; + + a { + display: block; + padding: 4px 3px 0 3px; + color: #fff; + text-decoration: none; + outline: none; + + i { + margin-right: 5px; + } + } + } + } + + &:hover { + > ul.submenu { + display: block; + } + } + + &:active { + > ul.submenu { + background-color: @color-treeview-active-bg; + } + } + + .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; + } + + &.dragged { + position: absolute; + z-index: 2000; + opacity: .25; + + > div { + .border-radius(3px); + } + } + + &.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-filelist-active; + + > a { + color: @color-treeview-item-active-comment; + + > span.comment, > span.expand { + color: @color-treeview-item-active-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-filelist-active; + } + + &:before {top: -1px;} + &:after {bottom: -1px;} + } + + &:before { + background-position: 0px -80px; + } + } + + &.has-subitems > div:before { + background-position: 0px -52px; + } + } + + &.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: 20px; + .transition(padding 1s); + + > 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;} + } + } + + &.active > div { + &:before {background-position: 0px -102px;} + } + } + + &.dragged > div, &.dragged li > div, > div:hover, &.active > div, > 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/plugins/rainlab/pages/classes/Content.php b/plugins/rainlab/pages/classes/Content.php new file mode 100644 index 0000000..776999a --- /dev/null +++ b/plugins/rainlab/pages/classes/Content.php @@ -0,0 +1,35 @@ +getBaseFileName()); + $title = ucwords(str_replace(['-', '_'], ' ', $title)); + return $title; + } +} diff --git a/plugins/rainlab/pages/classes/Controller.php b/plugins/rainlab/pages/classes/Controller.php new file mode 100644 index 0000000..579e36f --- /dev/null +++ b/plugins/rainlab/pages/classes/Controller.php @@ -0,0 +1,123 @@ +theme = Theme::getActiveTheme(); + if (!$this->theme) { + throw new CmsException(Lang::get('cms::lang.theme.active.not_found')); + } + } + + /** + * Creates a CMS page from a static page and configures it. + * @param string $url Specifies the static page URL. + * @return \Cms\Classes\Page Returns the CMS page object or NULL of the requested page was not found. + */ + public function initCmsPage($url) + { + $router = new Router($this->theme); + $page = $router->findByUrl($url); + + if (!$page) { + return null; + } + + $viewBag = $page->viewBag; + + $cmsPage = CmsPage::inTheme($this->theme); + $cmsPage->url = $url; + $cmsPage->apiBag['staticPage'] = $page; + + /* + * Transfer specific values from the content view bag to the page settings object. + */ + $viewBagToSettings = ['title', 'layout', 'meta_title', 'meta_description', 'is_hidden']; + + foreach ($viewBagToSettings as $property) { + $cmsPage->settings[$property] = array_get($viewBag, $property); + } + + // Transer page ID to CMS page + $cmsPage->settings['id'] = $page->getId(); + + return $cmsPage; + } + + public function injectPageTwig($page, $loader, $twig) + { + if (!isset($page->apiBag['staticPage'])) { + return; + } + + $staticPage = $page->apiBag['staticPage']; + + CmsException::mask($staticPage, 400); + $loader->setObject($staticPage); + $template = $twig->load($staticPage->getFilePath()); + $template->render([]); + CmsException::unmask(); + } + + public function getPageContents($page) + { + if (!isset($page->apiBag['staticPage'])) { + return; + } + + return $page->apiBag['staticPage']->getProcessedMarkup(); + } + + public function getPlaceholderContents($page, $placeholderName, $placeholderContents) + { + if (!isset($page->apiBag['staticPage'])) { + return; + } + + return $page->apiBag['staticPage']->getProcessedPlaceholderMarkup($placeholderName, $placeholderContents); + } + + public function initPageComponents($cmsController, $page) + { + if (!isset($page->apiBag['staticPage'])) { + return; + } + + $page->apiBag['staticPage']->initCmsComponents($cmsController); + } + + public function parseSyntaxFields($content) + { + try { + return SyntaxParser::parse($content, [ + 'varPrefix' => 'extraData.', + 'tagPrefix' => 'page:' + ])->toTwig(); + } + catch (Exception $ex) { + return $content; + } + } +} diff --git a/plugins/rainlab/pages/classes/Menu.php b/plugins/rainlab/pages/classes/Menu.php new file mode 100644 index 0000000..bc0808c --- /dev/null +++ b/plugins/rainlab/pages/classes/Menu.php @@ -0,0 +1,300 @@ + 'required|regex:/^[0-9a-z\-\_]+$/i', + ]; + + /** + * @var array The array of custom error messages. + */ + public $customMessages = [ + 'required' => 'rainlab.pages::lang.menu.code_required', + 'regex' => 'rainlab.pages::lang.menu.invalid_code', + ]; + + /** + * Returns the menu code. + * @return string + */ + public function getCodeAttribute() + { + return $this->getBaseFileName(); + } + + /** + * Sets the menu code. + * @param string $code Specifies the file code. + * @return \Cms\Classes\CmsObject Returns the object instance. + */ + public function setCodeAttribute($code) + { + $code = trim($code); + + if (strlen($code)) { + $this->fileName = $code.'.yaml'; + $this->attributes = array_merge($this->attributes, ['code' => $code]); + } + + return $this; + } + + /** + * Returns a default value for items attribute. + * Items are objects of the \RainLab\Pages\Classes\MenuItem class. + * @return array + */ + public function getItemsAttribute() + { + $items = []; + if (!empty($this->attributes['items'])) { + $items = MenuItem::initFromArray($this->attributes['items']); + } + + return $items; + } + + /** + * Store the itemData in the items attribute + * + * @param array $data + * @return void + */ + public function setItemDataAttribute($data) + { + $this->items = $data; + return $this; + } + + /** + * Processes the content attribute to an array of menu data. + * @return array|null + */ + protected function parseContent() + { + $parsedData = parent::parseContent(); + + if (!array_key_exists('name', $parsedData)) { + throw new SystemException(sprintf('The content of the %s file is invalid: the name element is not found.', $this->fileName)); + } + + return $parsedData; + } + + /** + * Initializes a cache item. + * @param array &$item The cached item array. + */ + public static function initCacheItem(&$item) + { + $obj = new static($item); + $item['name'] = $obj->name; + $item['items'] = $obj->items; + } + + /** + * Returns the menu item references. + * This function is used on the front-end. + * @param Cms\Classes\Page $page The current page object. + * @return array Returns an array of the \RainLab\Pages\Classes\MenuItemReference objects. + */ + public function generateReferences($page) + { + $currentUrl = Request::path(); + + if (!strlen($currentUrl)) { + $currentUrl = '/'; + } + + $currentUrl = Str::lower(Url::to($currentUrl)); + + $activeMenuItem = $page->activeMenuItem ?: false; + $iterator = function($items) use ($currentUrl, &$iterator, $activeMenuItem) { + $result = []; + + foreach ($items as $item) { + $parentReference = new MenuItemReference; + $parentReference->type = $item->type; + $parentReference->title = $item->title; + $parentReference->code = $item->code; + $parentReference->viewBag = $item->viewBag; + + /* + * If the item type is URL, assign the reference the item's URL and compare the current URL with the item URL + * to determine whether the item is active. + */ + if ($item->type == 'url') { + $parentReference->url = $item->url; + $parentReference->isActive = $currentUrl == Str::lower(Url::to($item->url)) || $activeMenuItem === $item->code; + } + else { + /* + * If the item type is not URL, use the API to request the item type's provider to + * return the item URL, subitems and determine whether the item is active. + */ + $apiResult = Event::fire('pages.menuitem.resolveItem', [$item->type, $item, $currentUrl, $this->theme]); + if (is_array($apiResult)) { + foreach ($apiResult as $itemInfo) { + if (!is_array($itemInfo)) { + continue; + } + + if (!$item->replace && isset($itemInfo['url'])) { + $parentReference->url = $itemInfo['url']; + $parentReference->isActive = $itemInfo['isActive'] || $activeMenuItem === $item->code; + } + + if (isset($itemInfo['items'])) { + $itemIterator = function($items) use (&$itemIterator, $parentReference) { + $result = []; + + foreach ($items as $item) { + $reference = new MenuItemReference; + $reference->type = isset($item['type']) ? $item['type'] : null; + $reference->title = isset($item['title']) ? $item['title'] : '--no title--'; + $reference->url = isset($item['url']) ? $item['url'] : '#'; + $reference->isActive = isset($item['isActive']) ? $item['isActive'] : false; + $reference->viewBag = isset($item['viewBag']) ? $item['viewBag'] : []; + $reference->code = isset($item['code']) ? $item['code'] : null; + + if (!strlen($parentReference->url)) { + $parentReference->url = $reference->url; + $parentReference->isActive = $reference->isActive; + } + + if (isset($item['items'])) { + $reference->items = $itemIterator($item['items']); + } + + $result[] = $reference; + } + + return $result; + }; + + $parentReference->items = $itemIterator($itemInfo['items']); + } + } + } + } + + if ($item->items) { + $parentReference->items = $iterator($item->items); + } + + if (!$item->replace) { + $result[] = $parentReference; + } + else { + foreach ($parentReference->items as $subItem) { + $result[] = $subItem; + } + } + } + + return $result; + }; + + $items = $iterator($this->items); + + /* + * Populate the isChildActive property + */ + $hasActiveChild = function($items) use (&$hasActiveChild) { + foreach ($items as $item) { + if ($item->isActive) { + return true; + } + + $result = $hasActiveChild($item->items); + if ($result) { + return $result; + } + } + }; + + $iterator = function($items) use (&$iterator, &$hasActiveChild) { + foreach ($items as $item) { + $item->isChildActive = $hasActiveChild($item->items); + + $iterator($item->items); + } + }; + + $iterator($items); + + /* + * @event pages.menu.referencesGenerated + * Provides opportunity to dynamically change menu entries right after reference generation. + * + * For example you can use it to filter menu entries for user groups from RainLab.User + * Before doing so you have to add custom field 'group' to menu viewBag using backend.form.extendFields event + * where the group can be selected by the user. See how to do this here: + * https://octobercms.com/docs/backend/forms#extend-form-fields + * + * Parameter provided is `$items` - a collection of the MenuItemReference objects passed by reference + * + * For example to hide entries where group is not 'registered' you can use the following code. It can + * be used to show different menus for different user groups. + * + * Event::listen('pages.menu.referencesGenerated', function (&$items) { + * $iterator = function ($menuItems) use (&$iterator, $clusterRepository) { + * $result = []; + * foreach ($menuItems as $item) { + * if (isset($item->viewBag['group']) && $item->viewBag['group'] !== "registered") { + * $item->viewBag['isHidden'] = "1"; + * } + * if ($item->items) { + * $item->items = $iterator($item->items); + * } + * $result[] = $item; + * } + * return $result; + * }; + * $items = $iterator($items); + * }); + */ + Event::fire('pages.menu.referencesGenerated', [&$items]); + + return $items; + } +} diff --git a/plugins/rainlab/pages/classes/MenuItem.php b/plugins/rainlab/pages/classes/MenuItem.php new file mode 100644 index 0000000..4b3e2b3 --- /dev/null +++ b/plugins/rainlab/pages/classes/MenuItem.php @@ -0,0 +1,211 @@ + $value) { + if ($name != 'items') { + if (property_exists($obj, $name)) { + $obj->$name = $value; + } + } + else { + $obj->items = self::initFromArray($value); + } + } + + $result[] = $obj; + } + + return $result; + } + + /** + * Returns a list of registered menu item types + * @return array Returns an array of registered item types + */ + public function getTypeOptions($keyValue = null) + { + /* + * Baked in types + */ + $result = [ + 'url' => 'URL', + 'header' => 'Header', + ]; + + $apiResult = Event::fire('pages.menuitem.listTypes'); + + if (is_array($apiResult)) { + foreach ($apiResult as $typeList) { + if (!is_array($typeList)) { + continue; + } + + foreach ($typeList as $typeCode => $typeName) { + $result[$typeCode] = $typeName; + } + } + } + + return $result; + } + + public function getCmsPageOptions($keyValue = null) + { + return []; // CMS Pages are loaded client-side + } + + public function getReferenceOptions($keyValue = null) + { + return []; // References are loaded client-side + } + + public static function getTypeInfo($type) + { + $result = []; + $apiResult = Event::fire('pages.menuitem.getTypeInfo', [$type]); + + if (is_array($apiResult)) { + foreach ($apiResult as $typeInfo) { + if (!is_array($typeInfo)) { + continue; + } + + foreach ($typeInfo as $name => $value) { + if ($name == 'cmsPages') { + $cmsPages = []; + + foreach ($value as $page) { + $baseName = $page->getBaseFileName(); + $pos = strrpos($baseName, '/'); + + $dir = $pos !== false ? substr($baseName, 0, $pos).' / ' : null; + $cmsPages[$baseName] = strlen($page->title) + ? $dir.$page->title + : $baseName; + } + + $value = $cmsPages; + } + + $result[$name] = $value; + } + } + } + + return $result; + } + + /** + * Converts the menu item data to an array + * @return array Returns the menu item data as array + */ + public function toArray() + { + $result = []; + + foreach ($this->fillable as $property) { + $result[$property] = $this->$property; + } + + return $result; + } +} diff --git a/plugins/rainlab/pages/classes/MenuItemReference.php b/plugins/rainlab/pages/classes/MenuItemReference.php new file mode 100644 index 0000000..7ee4b7a --- /dev/null +++ b/plugins/rainlab/pages/classes/MenuItemReference.php @@ -0,0 +1,58 @@ + 'required', + 'url' => ['required', 'regex:/^\/[a-z0-9\/_\-\.]*$/i', 'uniqueUrl'] + ]; + + /** + * @var array The array of custom attribute names. + */ + public $attributeNames = [ + 'title' => 'title', + 'url' => 'url', + ]; + + /** + * @var array Attributes that support translation, if available. + */ + public $translatable = [ + 'code', + 'markup', + 'viewBag[title]', + 'viewBag[meta_title]', + 'viewBag[meta_description]', + ]; + + /** + * @var string Translation model used for translation, if available. + */ + public $translatableModel = 'RainLab\Translate\Classes\MLStaticPage'; + + /** + * @var string Contains the page parent file name. + * This property is used by the page editor internally. + */ + public $parentFileName; + + /** + * @var mixed menuTreeCache + */ + protected static $menuTreeCache = null; + + /** + * @var mixed parentCache + */ + protected $parentCache = null; + + /** + * @var mixed childrenCache + */ + protected $childrenCache = null; + + /** + * @var mixed processedMarkupCache + */ + protected $processedMarkupCache = false; + + /** + * @var mixed processedBlockMarkupCache + */ + protected $processedBlockMarkupCache = []; + + /** + * __construct an instance of the object and associates it with a CMS theme. + * @param array $attributes + */ + public function __construct(array $attributes = []) + { + parent::__construct($attributes); + + $this->customMessages = [ + 'url.regex' => 'rainlab.pages::lang.page.invalid_url', + 'url.unique_url' => 'rainlab.pages::lang.page.url_not_unique', + ]; + } + + // + // CMS Object + // + + /** + * Sets the object attributes. + * @param array $attributes A list of attributes to set. + */ + public function fill(array $attributes) + { + parent::fill($attributes); + + /* + * When the page is saved, copy setting properties to the view bag. + * This is required for the back-end editors. + */ + if (array_key_exists('settings', $attributes) && array_key_exists('viewBag', $attributes['settings'])) { + $this->getViewBag()->setProperties($attributes['settings']['viewBag']); + $this->fillViewBagArray(); + } + } + + /** + * Returns the attributes used for validation. + * @return array + */ + protected function getValidationAttributes() + { + return $this->getAttributes() + $this->viewBag; + } + + /** + * Validates the object properties. + * Throws a ValidationException in case of an error. + */ + public function beforeValidate() + { + $pages = Page::listInTheme($this->theme, true); + + Validator::extend('uniqueUrl', function($attribute, $value, $parameters) use ($pages) { + $value = trim(strtolower($value)); + + foreach ($pages as $existingPage) { + if ( + $existingPage->getBaseFileName() !== $this->getBaseFileName() && + strtolower($existingPage->getViewBag()->property('url')) == $value + ) { + return false; + } + } + + return true; + }); + } + + /** + * Triggered before a new object is saved. + */ + public function beforeCreate() + { + $this->fileName = $this->generateFilenameFromCode(); + } + + /** + * Triggered after a new object is saved. + */ + public function afterCreate() + { + $this->appendToMeta(); + } + + /** + * Adds this page to the meta index. + */ + protected function appendToMeta() + { + $pageList = new PageList($this->theme); + $pageList->appendPage($this); + } + + /** + * generateFilenameFromCode based on the URL + */ + protected function generateFilenameFromCode() + { + $dir = rtrim($this->getFilePath(''), '/'); + + $fileName = trim(str_slug(str_replace('/', '-', $this->getViewBag()->property('url')), '-')); + if (strlen($fileName) > 200) { + $fileName = substr($fileName, 0, 200); + } + + if (!strlen($fileName)) { + $fileName = 'index'; + } + + $curName = trim($fileName).'.htm'; + $counter = 2; + + while (File::exists($dir.'/'.$curName)) { + $curName = $fileName.'-'.$counter.'.htm'; + $counter++; + } + + return $curName; + } + + /** + * delete the object from the disk. + * Recursively deletes subpages. Returns a list of file names of deleted pages. + * @return array + */ + public function delete() + { + $result = []; + + /* + * Delete subpages + */ + foreach ($this->getChildren() as $subPage) { + $result = array_merge($result, $subPage->delete()); + } + + /* + * Delete the object + */ + $result = array_merge($result, [$this->getBaseFileName()]); + + parent::delete(); + + /* + * Remove from meta + */ + $this->removeFromMeta(); + + return $result; + } + + /** + * Removes this page to the meta index. + */ + protected function removeFromMeta() + { + $pageList = new PageList($this->theme); + $pageList->removeSubtree($this); + } + + // + // Public API + // + + /** + * Helper that makes a URL for a static page in the active theme. + * + * Guide for the page reference: + * - chairs -> content/static-pages/chairs.htm + * + * @param mixed $page Specifies the Content file name. + * @return string + */ + public static function url($name) + { + if (empty($name) || !$page = static::find($name)) { + return null; + } + + $url = array_get($page->attributes, 'viewBag.url'); + + return Cms::url($url); + } + + /** + * Determine the default layout for a new page + * @param \RainLab\Pages\Classes\Page $parentPage + */ + public function setDefaultLayout($parentPage) + { + // Check parent page for a defined child layout + if ($parentPage && $parentPage->layout) { + $layout = Layout::load($this->theme, $parentPage->layout); + $component = $layout ? $layout->getComponent('staticPage') : null; + $childLayoutName = $component ? $component->property('childLayout', null) : null; + if ($childLayoutName) { + $this->getViewBag()->setProperty('layout', $childLayoutName); + $this->fillViewBagArray(); + return; + } + } + + // Check theme layouts for one marked as the default + foreach (Layout::listInTheme($this->theme) as $layout) { + $component = $layout->getComponent('staticPage'); + if ($component && $component->property('default', false)) { + $this->getViewBag()->setProperty('layout', $layout->getBaseFileName()); + $this->fillViewBagArray(); + return; + } + } + } + + // + // Getters + // + + /** + * Returns the parent page that belongs to this one, or null. + * @return mixed + */ + public function getParent() + { + if ($this->parentCache !== null) { + return $this->parentCache; + } + + $pageList = new PageList($this->theme); + + $parent = null; + if ($fileName = $pageList->getPageParent($this)) { + $parent = static::load($this->theme, $fileName); + } + + return $this->parentCache = $parent; + } + + /** + * Returns all the child pages that belong to this one. + * @return array + */ + public function getChildren() + { + if ($this->childrenCache !== null) { + return $this->childrenCache; + } + + $children = []; + $pageList = new PageList($this->theme); + + $subtree = $pageList->getPageSubTree($this); + + foreach ($subtree as $fileName => $subPages) { + $subPage = static::load($this->theme, $fileName); + if ($subPage) { + $children[] = $subPage; + } + } + + return $this->childrenCache = $children; + } + + /** + * Returns a list of layouts available in the theme. + * This method is used by the form widget. + * @return array Returns an array of strings. + */ + public function getLayoutOptions() + { + $result = []; + $layouts = Layout::listInTheme($this->theme, true); + + foreach ($layouts as $layout) { + if (!$layout->hasComponent('staticPage')) { + continue; + } + + $baseName = $layout->getBaseFileName(); + $result[$baseName] = strlen($layout->description) ? $layout->description : $baseName; + } + + if (!$result) { + $result[null] = Lang::get('rainlab.pages::lang.page.layouts_not_found'); + } + + return $result; + } + + /** + * Looks up the Layout Cms object for this page. + * @return Cms\Classes\Layout + */ + public function getLayoutObject() + { + $viewBag = $this->getViewBag(); + $layout = $viewBag->property('layout'); + + if (!$layout) { + $layouts = $this->getLayoutOptions(); + $layout = count($layouts) ? array_keys($layouts)[0] : null; + } + + if (!$layout) { + return null; + } + + $layout = Layout::load($this->theme, $layout); + if (!$layout) { + return null; + } + + return $layout; + } + + /** + * Returns the Twig content string + */ + public function getTwigContent() + { + return $this->code; + } + + // + // Syntax field processing + // + + public function listLayoutSyntaxFields() + { + if (!$layout = $this->getLayoutObject()) { + return []; + } + + $syntax = SyntaxParser::parse($layout->markup, ['tagPrefix' => 'page:']); + $result = $syntax->toEditor(); + + return $result; + } + + // + // Placeholder processing + // + + /** + * Returns information about placeholders defined in the page layout. + * @return array Returns an associative array of the placeholder name and codes. + */ + public function listLayoutPlaceholders() + { + if (!$layout = $this->getLayoutObject()) { + return []; + } + + $result = []; + $bodyNode = $layout->getTwigNodeTree()->getNode('body')->getNode(0); + $nodes = $this->flattenTwigNode($bodyNode); + + foreach ($nodes as $node) { + if (!$node instanceof \Cms\Twig\PlaceholderNode) { + continue; + } + + $title = $node->hasAttribute('title') ? trim($node->getAttribute('title')) : null; + if (!strlen($title)) { + $title = $node->getAttribute('name'); + } + + $type = $node->hasAttribute('type') ? trim($node->getAttribute('type')) : null; + $ignore = $node->hasAttribute('ignore') ? trim($node->getAttribute('ignore')) : false; + if ($type === 'hidden') { + $ignore = true; + } + + $placeholderInfo = [ + 'title' => $title, + 'type' => $type ?: 'html', + 'ignore' => $ignore + ]; + + $result[$node->getAttribute('name')] = $placeholderInfo; + } + + return $result; + } + + /** + * Recursively flattens a twig node and children + * @param $node + * @return array A flat array of twig nodes + */ + protected function flattenTwigNode($node) + { + $result = []; + if (!$node instanceof TwigNode) { + return $result; + } + + foreach ($node as $subNode) { + $flatNodes = $this->flattenTwigNode($subNode); + $result = array_merge($result, [$subNode], $flatNodes); + } + + return $result; + } + + /** + * Parses the page placeholder {% put %} tags and extracts the placeholder values. + * @return array Returns an associative array of the placeholder names and values. + */ + public function getPlaceholdersAttribute() + { + if (!strlen($this->code)) { + return []; + } + + if ($placeholders = array_get($this->attributes, 'placeholders')) { + return $placeholders; + } + + $bodyNode = $this->getTwigNodeTree($this->code)->getNode('body')->getNode(0); + if ($bodyNode instanceof \Cms\Twig\PutNode) { + $bodyNode = [$bodyNode]; + } + + $result = []; + foreach ($bodyNode as $node) { + if (!$node instanceof \Cms\Twig\PutNode) { + continue; + } + + // October CMS v2.2 and above + if (class_exists('System') && version_compare(\System::VERSION, '2.1') === 1) { + $names = $node->getNode('names'); + $values = $node->getNode('values'); + $isCapture = $node->getAttribute('capture'); + if ($isCapture) { + $name = $names->getNode(0); + $result[$name->getAttribute('name')] = trim($values->getAttribute('data')); + } + } + // Legacy PutNode support + else { + $values = $node->getNode('body'); + $result[$node->getAttribute('name')] = trim($values->getAttribute('data')); + } + } + + $this->attributes['placeholders'] = $result; + + return $result; + } + + /** + * Takes an array of placeholder data (key: code, value: content) and renders + * it as a single string of Twig markup against the "code" attribute. + * @param array $value + * @return void + */ + public function setPlaceholdersAttribute($value) + { + if (!is_array($value)) { + return; + } + + // Prune any attempt at setting a placeholder that + // is not actually defined by this pages layout. + $placeholders = array_intersect_key($value, $this->listLayoutPlaceholders()); + + $result = ''; + + foreach ($placeholders as $code => $content) { + if (!strlen(trim($content))) { + continue; + } + + $result .= '{% put '.$code.' %}'.PHP_EOL; + $result .= $content.PHP_EOL; + $result .= '{% endput %}'.PHP_EOL; + $result .= PHP_EOL; + } + + $this->attributes['code'] = trim($result); + $this->attributes['placeholders'] = $placeholders; + } + + /** + * getProcessedMarkup will return the processed markup of a page + */ + public function getProcessedMarkup() + { + if ($this->processedMarkupCache !== false) { + return $this->processedMarkupCache; + } + + /* + * Process snippets + */ + $markup = Snippet::processPageMarkup( + $this->getFileName(), + $this->theme, + $this->markup + ); + + /* + * Inject global view variables + */ + $globalVars = ViewHelper::getGlobalVars(); + if (!empty($globalVars)) { + $markup = TextParser::parse($markup, $globalVars); + } + + /* + * Process content using core parser + */ + if (class_exists(\Cms\Classes\PageLookup::class)) { + $markup = \Cms\Classes\PageLookup::processMarkup($markup); + } + + /* + * Event hook + */ + Event::fire('pages.page.getProcessedMarkup', [&$markup]); + + return $this->processedMarkupCache = $markup; + } + + public function getProcessedPlaceholderMarkup($placeholderName, $placeholderContents) + { + if (array_key_exists($placeholderName, $this->processedBlockMarkupCache)) { + return $this->processedBlockMarkupCache[$placeholderName]; + } + + /* + * Process snippets + */ + $markup = Snippet::processPageMarkup( + $this->getFileName().md5($placeholderName), + $this->theme, + $placeholderContents + ); + + /* + * Inject global view variables + */ + $globalVars = ViewHelper::getGlobalVars(); + if (!empty($globalVars)) { + $markup = TextParser::parse($markup, $globalVars); + } + + /* + * Event hook + */ + Event::fire('pages.page.getProcessedPlaceholderMarkup', [&$markup]); + + return $this->processedBlockMarkupCache[$placeholderName] = $markup; + } + + // + // Snippets + // + + /** + * Initializes CMS components associated with the page. + */ + public function initCmsComponents($cmsController) + { + $snippetComponents = Snippet::listPageComponents( + $this->getFileName(), + $this->theme, + $this->markup.$this->code + ); + + $componentManager = ComponentManager::instance(); + foreach ($snippetComponents as $componentInfo) { + // Register components for snippet-based components + // if they're not defined yet. This is required because + // not all snippet components are registered as components, + // but it's safe to register them in render-time. + + if (!$componentManager->hasComponent($componentInfo['class'])) { + $componentManager->registerComponent($componentInfo['class'], $componentInfo['alias']); + } + + $cmsController->addComponent( + $componentInfo['class'], + $componentInfo['alias'], + $componentInfo['properties'] + ); + } + } + + // + // Static Menu API + // + + /** + * Returns a cache key for this record. + */ + protected static function getMenuCacheKey($theme) + { + $key = crc32($theme->getPath()).'static-page-menu'; + /** + * @event pages.page.getMenuCacheKey + * Enables modifying the key used to reference cached RainLab.Pages menu trees + * + * Example usage: + * + * Event::listen('pages.page.getMenuCacheKey', function (&$key) { + * $key = $key . '-' . App::getLocale(); + * }); + * + */ + Event::fire('pages.page.getMenuCacheKey', [&$key]); + return $key; + } + + /** + * Returns whether the specified URLs are equal. + */ + protected static function urlsAreEqual($url, $other) + { + return rawurldecode($url) === rawurldecode($other); + } + + /** + * Clears the menu item cache + * @param \Cms\Classes\Theme $theme Specifies the current theme. + */ + public static function clearMenuCache($theme) + { + Cache::forget(self::getMenuCacheKey($theme)); + } + + /** + * Handler for the pages.menuitem.getTypeInfo event. + * Returns a menu item type information. The type information is returned as array + * with the following elements: + * - references - a list of the item type reference options. The options are returned in the + * ["key"] => "title" format for options that don't have sub-options, and in the format + * ["key"] => ["title"=>"Option title", "items"=>[...]] for options that have sub-options. Optional, + * required only if the menu item type requires references. + * - nesting - Boolean value indicating whether the item type supports nested items. Optional, + * false if omitted. + * - dynamicItems - Boolean value indicating whether the item type could generate new menu items. + * Optional, false if omitted. + * - cmsPages - a list of CMS pages (objects of the Cms\Classes\Page class), if the item type requires a CMS page reference to + * resolve the item URL. + * @param string $type Specifies the menu item type + * @return array Returns an array + */ + public static function getMenuTypeInfo($type) + { + if ($type == 'all-static-pages') { + return [ + 'dynamicItems' => true + ]; + } + + if ($type == 'static-page') { + return [ + 'references' => self::listStaticPageMenuOptions(), + 'nesting' => true, + 'dynamicItems' => true + ]; + } + } + + /** + * Handler for the pages.menuitem.resolveItem event. + * Returns information about a menu item. The result is an array + * with the following keys: + * - url - the menu item URL. Not required for menu item types that return all available records. + * The URL should be returned relative to the website root and include the subdirectory, if any. + * Use the Cms::url() helper to generate the URLs. + * - isActive - determines whether the menu item is active. Not required for menu item types that + * return all available records. + * - items - an array of arrays with the same keys (url, isActive, items) + the title key. + * The items array should be added only if the $item's $nesting property value is TRUE. + * @param \RainLab\Pages\Classes\MenuItem $item Specifies the menu item. + * @param \Cms\Classes\Theme $theme Specifies the current theme. + * @param string $url Specifies the current page URL, normalized, in lower case + * The URL is specified relative to the website root, it includes the subdirectory name, if any. + * @return mixed Returns an array. Returns null if the item cannot be resolved. + */ + public static function resolveMenuItem($item, $url, $theme) + { + $tree = self::buildMenuTree($theme); + + if ($item->type == 'static-page' && !isset($tree[$item->reference])) { + return; + } + + $result = []; + + if ($item->type == 'static-page') { + $pageInfo = $tree[$item->reference]; + $result['url'] = Cms::url($pageInfo['url']); + $result['mtime'] = $pageInfo['mtime']; + $result['isActive'] = self::urlsAreEqual($result['url'], $url); + } + + if ($item->nesting || $item->type == 'all-static-pages') { + $iterator = function($items) use (&$iterator, &$tree, $url) { + $branch = []; + + foreach ($items as $itemName) { + if (!isset($tree[$itemName])) { + continue; + } + + $itemInfo = $tree[$itemName]; + + if ($itemInfo['navigation_hidden']) { + continue; + } + + $branchItem = []; + $branchItem['url'] = Cms::url($itemInfo['url']); + $branchItem['isActive'] = self::urlsAreEqual($branchItem['url'], $url); + $branchItem['title'] = $itemInfo['title']; + $branchItem['mtime'] = $itemInfo['mtime']; + + if ($itemInfo['items']) { + $branchItem['items'] = $iterator($itemInfo['items']); + } + + $branch[] = $branchItem; + } + + return $branch; + }; + + $result['items'] = $iterator($item->type == 'static-page' ? $pageInfo['items'] : $tree['--root-pages--']); + } + + return $result; + } + + /** + * Handler for the backend.richeditor.getTypeInfo event. + * Returns a menu item type information. The type information is returned as array + * + * @param string $type Specifies the page link type + * @return array Array of available link targets keyed by URL ['https://example.com/' => 'Homepage] + */ + public static function getRichEditorTypeInfo($type) + { + if ($type == 'static-page') { + + $pages = self::listStaticPageMenuOptions(); + + $iterator = function($pages) use (&$iterator) { + $result = []; + foreach ($pages as $pageFile => $page) { + $url = self::url($pageFile); + + if (is_array($page)) { + $result[$url] = [ + 'title' => array_get($page, 'title', []), + 'links' => $iterator(array_get($page, 'items', [])) + ]; + } + else { + $result[$url] = $page; + } + } + + return $result; + }; + + return $iterator($pages); + } + + return []; + } + + /** + * Builds and caches a menu item tree. + * This method is used internally for menu items and breadcrumbs. + * @param \Cms\Classes\Theme $theme Specifies the current theme. + * @return array Returns an array containing the page information + */ + public static function buildMenuTree($theme) + { + if (self::$menuTreeCache !== null) { + return self::$menuTreeCache; + } + + $key = self::getMenuCacheKey($theme); + + $cached = Cache::get($key, false); + $unserialized = $cached ? @unserialize($cached) : false; + + if ($unserialized !== false) { + return self::$menuTreeCache = $unserialized; + } + + $menuTree = [ + '--root-pages--' => [] + ]; + + $iterator = function($items, $parent, $level) use (&$menuTree, &$iterator) { + $result = []; + + foreach ($items as $item) { + $viewBag = $item->page->viewBag; + $pageCode = $item->page->getBaseFileName(); + $pageUrl = Str::lower(RouterHelper::normalizeUrl(array_get($viewBag, 'url'))); + + $itemData = [ + 'url' => $pageUrl, + 'title' => array_get($viewBag, 'title'), + 'mtime' => $item->page->mtime, + 'items' => $iterator($item->subpages, $pageCode, $level+1), + 'parent' => $parent, + 'navigation_hidden' => array_get($viewBag, 'navigation_hidden') + ]; + + if ($level == 0) { + $menuTree['--root-pages--'][] = $pageCode; + } + + $result[] = $pageCode; + $menuTree[$pageCode] = $itemData; + } + + return $result; + }; + + $pageList = new PageList($theme); + $iterator($pageList->getPageTree(), null, 0); + + self::$menuTreeCache = $menuTree; + $comboConfig = Config::get('cms.parsedPageCacheTTL', Config::get('cms.template_cache_ttl', 10)); + $expiresAt = now()->addMinutes($comboConfig); + Cache::put($key, serialize($menuTree), $expiresAt); + + return self::$menuTreeCache; + } + + /** + * Returns a list of options for the Reference drop-down menu in the + * menu item configuration form, when the Static Page item type is selected. + * @return array Returns an array + */ + protected static function listStaticPageMenuOptions() + { + $theme = Theme::getEditTheme(); + + $pageList = new PageList($theme); + $pageTree = $pageList->getPageTree(true); + + $iterator = function($pages) use (&$iterator) { + $result = []; + + foreach ($pages as $pageInfo) { + $pageName = $pageInfo->page->getViewBag()->property('title'); + $fileName = $pageInfo->page->getBaseFileName(); + + if (!$pageInfo->subpages) { + $result[$fileName] = $pageName; + } + else { + $result[$fileName] = [ + 'title' => $pageName, + 'items' => $iterator($pageInfo->subpages) + ]; + } + } + + return $result; + }; + + return $iterator($pageTree); + } + + /** + * Disables safe mode check for static pages. + * + * This allows developers to use placeholders in layouts even if safe mode is enabled. + * + * @return void + */ + protected function checkSafeMode() + { + } +} diff --git a/plugins/rainlab/pages/classes/PageList.php b/plugins/rainlab/pages/classes/PageList.php new file mode 100644 index 0000000..c4f14a1 --- /dev/null +++ b/plugins/rainlab/pages/classes/PageList.php @@ -0,0 +1,236 @@ +theme = $theme; + } + + /** + * Returns a list of static pages in the specified theme. + * This method is used internally by the system. + * @param boolean $skipCache Indicates if objects should be reloaded from the disk bypassing the cache. + * @return object Returns an array of static pages. + */ + public function listPages($skipCache = false) + { + return Page::listInTheme($this->theme, $skipCache); + } + + /** + * Returns a list of top-level pages with subpages. + * The method uses the theme's meta/static-pages.yaml file to build the hierarchy. The pages are returned + * in the order defined in the YAML file. The result of the method is used for building the back-end UI + * and for generating the menus. + * @param boolean $skipCache Indicates if objects should be reloaded from the disk bypassing the cache. + * @return array Returns a nested array of objects: object('page': $pageObj, 'subpages'=>[...]) + */ + public function getPageTree($skipCache = false) + { + $pages = $this->listPages($skipCache); + $config = $this->getPagesConfig(); + + // Make the $pages collection an associative array for performance + $pagesArray = $pages->keyBy(function ($page) { + return $page->getBaseFileName(); + })->all(); + + $iterator = function($configPages) use (&$iterator, $pagesArray) { + $result = []; + + foreach ($configPages as $fileName => $subpages) { + if (isset($pagesArray[$fileName])) { + $result[] = (object) [ + 'page' => $pagesArray[$fileName], + 'subpages' => $iterator($subpages), + ]; + } + } + + return $result; + }; + + return $iterator($config['static-pages']); + } + + /** + * Returns the parent name of the specified page. + * @param \Cms\Classes\Page $page Specifies a page object. + * @param string Returns the parent page name. + */ + public function getPageParent($page) + { + $pagesConfig = $this->getPagesConfig(); + $requestedFileName = $page->getBaseFileName(); + + $parent = null; + + $iterator = function($configPages) use (&$iterator, &$parent, $requestedFileName) { + foreach ($configPages as $fileName => $subpages) { + if ($fileName == $requestedFileName) { + return true; + } + + if ($iterator($subpages) == true && is_null($parent)) { + + $parent = $fileName; + + return true; + } + } + }; + + $iterator($pagesConfig['static-pages']); + + return $parent; + } + + /** + * Returns a part of the page hierarchy starting from the specified page. + * @param \Cms\Classes\Page $page Specifies a page object. + * @param array Returns a nested array of page names. + */ + public function getPageSubTree($page) + { + $pagesConfig = $this->getPagesConfig(); + $requestedFileName = $page->getBaseFileName(); + + $subTree = []; + + $iterator = function($configPages) use (&$iterator, &$subTree, $requestedFileName) { + if (is_array($configPages)) { + foreach ($configPages as $fileName => $subpages) { + if ($fileName == $requestedFileName) { + $subTree = $subpages; + + return true; + } + + if ($iterator($subpages) === true) { + return true; + } + } + } + }; + + $iterator($pagesConfig['static-pages']); + + return $subTree; + } + + /** + * Appends page to the page hierarchy. + * The page can be added to the end of the hierarchy or as a subpage to any existing page. + */ + public function appendPage($page) + { + $parent = $page->parentFileName; + + $originalData = $this->getPagesConfig(); + $structure = $originalData['static-pages']; + + if (!strlen($parent)) { + $structure[$page->getBaseFileName()] = []; + } + else { + $iterator = function(&$configPages) use (&$iterator, $parent, $page) { + foreach ($configPages as $fileName => &$subpages) { + if ($fileName == $parent) { + $subpages[$page->getBaseFileName()] = []; + + return true; + } + + if ($iterator($subpages) == true) + return true; + } + }; + + $iterator($structure); + } + + $this->updateStructure($structure); + } + + /** + * Removes a part of the page hierarchy starting from the specified page. + * @param \Cms\Classes\Page $page Specifies a page object. + */ + public function removeSubtree($page) + { + $pagesConfig = $this->getPagesConfig(); + $requestedFileName = $page->getBaseFileName(); + + $tree = []; + + $iterator = function($configPages) use (&$iterator, &$pages, $requestedFileName) { + $result = []; + + foreach ($configPages as $fileName => $subpages) { + if ($requestedFileName != $fileName) { + $result[$fileName] = $iterator($subpages); + } + } + + return $result; + }; + + $updatedStructure = $iterator($pagesConfig['static-pages']); + $this->updateStructure($updatedStructure); + } + + /** + * Returns the parsed meta/static-pages.yaml file contents. + * @return mixed + */ + protected function getPagesConfig() + { + if (self::$configCache !== false) { + return self::$configCache; + } + + $config = Meta::loadCached($this->theme, 'static-pages.yaml'); + + if (!$config) { + $config = new Meta(); + $config->fileName = 'static-pages.yaml'; + $config['static-pages'] = []; + $config->save(); + } + + if (!isset($config->attributes['static-pages'])) { + $config['static-pages'] = []; + } + + return self::$configCache = $config; + } + + /** + * Updates the page hierarchy structure in the theme's meta/static-pages.yaml file. + * @param array $structure A nested associative array representing the page structure + */ + public function updateStructure($structure) + { + $config = $this->getPagesConfig(); + $config['static-pages'] = $structure; + $config->save(); + } +} diff --git a/plugins/rainlab/pages/classes/Router.php b/plugins/rainlab/pages/classes/Router.php new file mode 100644 index 0000000..c9cbd13 --- /dev/null +++ b/plugins/rainlab/pages/classes/Router.php @@ -0,0 +1,182 @@ +theme = $theme; + } + + /** + * Finds a static page by its URL. + * @param string $url The requested URL string. + * @return \RainLab\Pages\Classes\Page Returns \RainLab\Pages\Classes\Page object or null if the page cannot be found. + */ + public function findByUrl($url) + { + $url = Str::lower(RouterHelper::normalizeUrl($url)); + + if (array_key_exists($url, self::$cache)) { + return self::$cache[$url]; + } + + $urlMap = $this->getUrlMap(); + $urlMap = array_key_exists('urls', $urlMap) ? $urlMap['urls'] : []; + + if (!array_key_exists($url, $urlMap)) { + return null; + } + + $fileName = $urlMap[$url]; + + if (($page = Page::loadCached($this->theme, $fileName)) === null) { + /* + * If the page was not found on the disk, clear the URL cache + * and try again. + */ + $this->clearCache(); + + return self::$cache[$url] = Page::loadCached($this->theme, $fileName); + } + + return self::$cache[$url] = $page; + } + + /** + * Autoloads the URL map only allowing a single execution. + * @return array Returns the URL map. + */ + protected function getUrlMap() + { + if (!count(self::$urlMap)) { + $this->loadUrlMap(); + } + + return self::$urlMap; + } + + /** + * Loads the URL map - a list of page file names and corresponding URL patterns. + * The URL map can is cached. The clearUrlMap() method resets the cache. By default + * the map is updated every time when a page is saved in the back-end, or + * when the interval defined with the cms.urlCacheTtl expires. + * @return boolean Returns true if the URL map was loaded from the cache. Otherwise returns false. + */ + protected function loadUrlMap() + { + $key = $this->getCacheKey('static-page-url-map'); + + $cacheable = Config::get('cms.enableRoutesCache', Config::get('cms.enable_route_cache', false)); + $cached = $cacheable ? Cache::get($key, false) : false; + + if (!$cached || ($unserialized = @unserialize($cached)) === false) { + /* + * The item doesn't exist in the cache, create the map + */ + $pageList = new PageList($this->theme); + + $pages = $pageList->listPages(); + $map = [ + 'urls' => [], + 'files' => [], + 'titles' => [] + ]; + foreach ($pages as $page) { + if (!$page) { + continue; + } + + $url = $page->getViewBag()->property('url'); + if (!$url) { + continue; + } + + $url = Str::lower(RouterHelper::normalizeUrl($url)); + $file = $page->getBaseFileName(); + + $map['urls'][$url] = $file; + $map['files'][$file] = $url; + $map['titles'][$file] = $page->getViewBag()->property('title'); + } + + self::$urlMap = $map; + + if ($cacheable) { + $comboConfig = Config::get('cms.urlCacheTtl', Config::get('cms.url_cache_ttl', 10)); + $expiresAt = now()->addMinutes($comboConfig); + Cache::put($key, serialize($map), $expiresAt); + } + + return false; + } + + self::$urlMap = $unserialized; + + return true; + } + + /** + * Returns the caching URL key depending on the theme. + * @param string $keyName Specifies the base key name. + * @return string Returns the theme-specific key name. + */ + protected function getCacheKey($keyName) + { + $key = crc32($this->theme->getPath()).$keyName; + /** + * @event pages.router.getCacheKey + * Enables modifying the key used to reference cached RainLab.Pages routes + * + * Example usage: + * + * Event::listen('pages.router.getCacheKey', function (&$key) { + * $key = $key . '-' . App::getLocale(); + * }); + * + */ + Event::fire('pages.router.getCacheKey', [&$key]); + return $key; + } + + /** + * Clears the router cache. + */ + public function clearCache() + { + Cache::forget($this->getCacheKey('static-page-url-map')); + } +} diff --git a/plugins/rainlab/pages/classes/Snippet.php b/plugins/rainlab/pages/classes/Snippet.php new file mode 100644 index 0000000..9b89b0d --- /dev/null +++ b/plugins/rainlab/pages/classes/Snippet.php @@ -0,0 +1,687 @@ +getViewBag(); + + $this->code = $viewBag->property('snippetCode'); + $this->description = $partial->description; + $this->name = $viewBag->property('snippetName'); + $this->properties = $viewBag->property('snippetProperties', []); + } + + /** + * Initializes the snippet from a CMS component information. + * @param string $componentClass Specifies the component class. + * @param string $componentCode Specifies the component code. + */ + public function initFromComponentInfo($componentClass, $componentCode) + { + $this->code = $componentCode; + $this->componentClass = $componentClass; + } + + /** + * Returns the snippet name. + * This method should not be used in the front-end request handling. + * @return string + */ + public function getName() + { + if ($this->name !== null) { + return $this->name; + } + + if ($this->componentClass === null) { + return null; + } + + $component = $this->getComponent(); + + return $this->name = ComponentHelpers::getComponentName($component); + } + + /** + * Returns the snippet description. + * This method should not be used in the front-end request handling. + * @return string + */ + public function getDescription() + { + if ($this->description !== null) { + return $this->description; + } + + if ($this->componentClass === null) { + return null; + } + + $component = $this->getComponent(); + + return $this->description = ComponentHelpers::getComponentDescription($component); + } + + /** + * Returns the snippet component class name. + * If the snippet is a partial snippet, returns NULL. + * @return string Returns the snippet component class name + */ + public function getComponentClass() + { + return $this->componentClass; + } + + /** + * Returns the snippet property list as array, in format compatible with Inspector. + */ + public function getProperties() + { + if (!$this->componentClass) { + return self::parseIniProperties($this->properties); + } + else { + return ComponentHelpers::getComponentsPropertyConfig($this->getComponent(), false, true); + } + } + + /** + * Returns a list of component definitions declared on the page. + * @param string $pageName Specifies the static page file name (the name of the corresponding content block file). + * @param \Cms\Classes\Theme $theme Specifies a parent theme. + * @return array Returns an array of component definitions + */ + public static function listPageComponents($pageName, $theme, $markup) + { + $map = self::extractSnippetsFromMarkupCached($theme, $pageName, $markup); + + $result = []; + + foreach ($map as $snippetDeclaration => $snippetInfo) { + if (!isset($snippetInfo['component'])) { + continue; + } + + $result[] = [ + 'class' => $snippetInfo['component'], + 'alias' => $snippetInfo['code'], + 'properties' => $snippetInfo['properties'] + ]; + } + + return $result; + } + + /** + * Extends the partial form with Snippet fields. + */ + public static function extendPartialForm($formWidget) + { + /* + * Snippet code field + */ + + $fieldConfig = [ + 'tab' => 'rainlab.pages::lang.snippet.partialtab', + 'type' => 'text', + 'label' => 'rainlab.pages::lang.snippet.code', + 'comment' => 'rainlab.pages::lang.snippet.code_comment', + 'span' => 'left' + ]; + + $formWidget->tabs['fields']['viewBag[snippetCode]'] = $fieldConfig; + + /* + * Snippet description field + */ + + $fieldConfig = [ + 'tab' => 'rainlab.pages::lang.snippet.partialtab', + 'type' => 'text', + 'label' => 'rainlab.pages::lang.snippet.name', + 'comment' => 'rainlab.pages::lang.snippet.name_comment', + 'span' => 'right' + ]; + + $formWidget->tabs['fields']['viewBag[snippetName]'] = $fieldConfig; + + /* + * Snippet properties field + */ + + $fieldConfig = [ + 'tab' => 'rainlab.pages::lang.snippet.partialtab', + 'type' => 'datatable', + 'height' => '150', + 'dynamicHeight' => true, + 'columns' => [ + 'title' => [ + 'title' => 'rainlab.pages::lang.snippet.column_property', + 'validation' => [ + 'required' => [ + 'message' => 'Please provide the property title', + 'requiredWith' => 'property' + ] + ] + ], + 'property' => [ + 'title' => 'rainlab.pages::lang.snippet.column_code', + 'validation' => [ + 'required' => [ + 'message' => 'Please provide the property code', + 'requiredWith' => 'title' + ], + 'regex' => [ + 'pattern' => '^[a-z][a-z0-9]*$', + 'modifiers' => 'i', + 'message' => Lang::get('rainlab.pages::lang.snippet.property_format_error') + ] + ] + ], + 'type' => [ + 'title' => 'rainlab.pages::lang.snippet.column_type', + 'type' => 'dropdown', + 'options' => [ + 'string' => 'rainlab.pages::lang.snippet.column_type_string', + 'checkbox' => 'rainlab.pages::lang.snippet.column_type_checkbox', + 'dropdown' => 'rainlab.pages::lang.snippet.column_type_dropdown' + ], + 'validation' => [ + 'required' => [ + 'requiredWith' => 'title' + ] + ] + ], + 'default' => [ + 'title' => 'rainlab.pages::lang.snippet.column_default' + ], + 'options' => [ + 'title' => 'rainlab.pages::lang.snippet.column_options' + ] + ] + ]; + + $formWidget->tabs['fields']['viewBag[snippetProperties]'] = $fieldConfig; + } + + public static function extendEditorPartialToolbar($dataHolder) + { + $dataHolder->buttons[] = [ + 'button' => 'rainlab.pages::lang.snippet.partialtab', + 'icon' => 'octo-icon-code-snippet', + 'popupTitle' => 'rainlab.pages::lang.snippet.settings_popup_title', + 'useViewBag' => true, + 'properties' => [ + [ + 'property' => 'snippetCode', + 'title' => 'rainlab.pages::lang.snippet.code', + 'description' => 'rainlab.pages::lang.snippet.code_comment', + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => 'rainlab.pages::lang.snippet.code_required' + ] + ] + ], + [ + 'property' => 'snippetName', + 'title' => 'rainlab.pages::lang.snippet.name', + 'description' => 'rainlab.pages::lang.snippet.name_comment', + 'type' => 'string', + 'validation' => [ + 'required' => [ + 'message' => 'rainlab.pages::lang.snippet.name_required' + ] + ] + ], + [ + 'property' => 'snippetProperties', + 'title' => '', + 'type' => 'table', + 'tab' => 'rainlab.pages::lang.snippet.properties', + 'columns' => [ + [ + 'column' => 'title', + 'type' => 'string', + 'title' => 'rainlab.pages::lang.snippet.column_property', + 'validation' => [ + 'required' => [ + 'message' => 'rainlab.pages::lang.snippet.title_required' + ] + ] + ], + [ + 'column' => 'property', + 'type' => 'string', + 'title' => 'rainlab.pages::lang.snippet.column_code', + 'validation' => [ + 'required' => [ + 'message' => 'rainlab.pages::lang.snippet.property_required' + ], + 'regex' => [ + 'pattern' => '^[a-z][a-z0-9]*$', + 'modifiers' => 'i', + 'message' => 'rainlab.pages::lang.snippet.property_format_error' + ] + ] + ], + [ + 'column' => 'type', + 'title' => 'rainlab.pages::lang.snippet.column_type', + 'type' => 'dropdown', + 'placeholder' => 'rainlab.pages::lang.snippet.column_type_placeholder', + 'options' => [ + 'string' => 'rainlab.pages::lang.snippet.column_type_string', + 'checkbox' => 'rainlab.pages::lang.snippet.column_type_checkbox', + 'dropdown' => 'rainlab.pages::lang.snippet.column_type_dropdown' + ], + 'validation' => [ + 'required' => [ + 'message' => 'rainlab.pages::lang.snippet.type_required' + ] + ] + ], + [ + 'column' => 'default', + 'type' => 'string', + 'title' => 'rainlab.pages::lang.snippet.column_default' + ], + [ + 'column' => 'options', + 'type' => 'string', + 'title' => 'rainlab.pages::lang.snippet.column_options' + ] + ] + ] + ] + ]; + } + + /** + * Returns a component corresponding to the snippet. + * This method should not be used in the front-end request handling code. + * @return \Cms\Classes\ComponentBase + */ + protected function getComponent() + { + if ($this->componentClass === null) { + return null; + } + + if ($this->componentObj !== null) { + return $this->componentObj; + } + + $componentClass = $this->componentClass; + + return $this->componentObj = new $componentClass(); + } + + // + // Parsing + // + + /** + * Parses the static page markup and renders snippets defined on the page. + * @param string $pageName Specifies the static page file name (the name of the corresponding content block file). + * @param \Cms\Classes\Theme $theme Specifies a parent theme. + * @param string $markup Specifies the markup string to process. + * @return string Returns the processed string. + */ + public static function processPageMarkup($pageName, $theme, $markup) + { + $map = self::extractSnippetsFromMarkupCached($theme, $pageName, $markup); + + $controller = CmsController::getController(); + $partialSnippetMap = SnippetManager::instance()->getPartialSnippetMap($theme); + + foreach ($map as $snippetDeclaration => $snippetInfo) { + $snippetCode = $snippetInfo['code']; + + if (!isset($snippetInfo['component'])) { + if (!array_key_exists($snippetCode, $partialSnippetMap)) { + throw new ApplicationException(sprintf('Partial for the snippet %s is not found', $snippetCode)); + } + + $partialName = $partialSnippetMap[$snippetCode]; + $generatedMarkup = $controller->renderPartial($partialName, $snippetInfo['properties']); + } + else { + $generatedMarkup = $controller->renderComponent($snippetCode); + } + + $pattern = preg_quote($snippetDeclaration); + $markup = mb_ereg_replace($pattern, $generatedMarkup, $markup); + } + + return $markup; + } + + public static function processTemplateSettingsArray($settingsArray) + { + if ( + !isset($settingsArray['viewBag']['snippetProperties']['TableData']) && + !isset($settingsArray['viewBag']['snippetProperties']) // CMS Editor + ) { + return $settingsArray; + } + + $properties = []; + + if (isset($settingsArray['viewBag']['snippetProperties']['TableData'])) { + $rows = $settingsArray['viewBag']['snippetProperties']['TableData']; + } + else { + $rows = $settingsArray['viewBag']['snippetProperties']; + } + + foreach ($rows as $row) { + $property = array_get($row, 'property'); + $settings = array_only($row, ['title', 'type', 'default', 'options']); + + if (isset($settings['options'])) { + $settings['options'] = self::dropDownOptionsToArray($settings['options']); + } + + $properties[$property] = $settings; + } + + $settingsArray['viewBag']['snippetProperties'] = []; + + foreach ($properties as $name => $value) { + $settingsArray['viewBag']['snippetProperties'][$name] = $value; + } + + return $settingsArray; + } + + public static function processTemplateSettings($template, $context = null) + { + if (!isset($template->viewBag['snippetProperties'])) { + return; + } + + $parsedProperties = self::parseIniProperties($template->viewBag['snippetProperties']); + + foreach ($parsedProperties as $index => &$property) { + if ($context !== 'editor') { + $property['id'] = $index; + } + + if (isset($property['options']) && is_array($property['options'])) { + $property['options'] = self::dropDownOptionsToString($property['options']); + } + } + + $template->viewBag['snippetProperties'] = $parsedProperties; + + if ($context == 'editor') { + $template->settings['components']['viewBag'] = $template->viewBag; + } + } + + /** + * Apples default property values and fixes property names. + * + * As snippet properties are defined with data attributes, they are lower case, whereas + * real property names are case sensitive. This method finds original property names defined + * in snippet classes or partials and replaces property names defined in the static page markup. + */ + protected static function preprocessPropertyValues($theme, $snippetCode, $componentClass, $properties) + { + $snippet = SnippetManager::instance()->findByCodeOrComponent($theme, $snippetCode, $componentClass, true); + if (!$snippet) { + throw new ApplicationException(Lang::get('rainlab.pages::lang.snippet.not_found', ['code' => $snippetCode])); + } + + $properties = array_change_key_case($properties); + $snippetProperties = $snippet->getProperties(); + + foreach ($snippetProperties as $propertyInfo) { + $propertyCode = $propertyInfo['property']; + $lowercaseCode = strtolower($propertyCode); + + if (!array_key_exists($lowercaseCode, $properties)) { + if (array_key_exists('default', $propertyInfo)) { + $properties[$propertyCode] = $propertyInfo['default']; + } + } + else { + $markupPropertyInfo = $properties[$lowercaseCode]; + unset($properties[$lowercaseCode]); + $properties[$propertyCode] = $markupPropertyInfo; + } + } + + return $properties; + } + + /** + * Converts a keyed object to an array, converting the index to the "property" value. + * @return array + */ + protected static function parseIniProperties($properties) + { + foreach ($properties as $index => $value) { + $properties[$index]['property'] = $index; + } + + return array_values($properties); + } + + protected static function dropDownOptionsToArray($optionsString) + { + $options = explode('|', $optionsString); + + $result = []; + foreach ($options as $index => $optionStr) { + $parts = explode(':', $optionStr, 2); + + if (count($parts) > 1 ) { + $key = trim($parts[0]); + + if (strlen($key)) { + if (!preg_match('/^[0-9a-z-_]+$/i', $key)) { + throw new ValidationException(['snippetProperties' => Lang::get('rainlab.pages::lang.snippet.invalid_option_key', ['key'=>$key])]); + } + + $result[$key] = trim($parts[1]); + } + else { + $result[$index] = trim($optionStr); + } + } + else { + $result[$index] = trim($optionStr); + } + } + + return $result; + } + + protected static function dropDownOptionsToString($optionsArray) + { + $result = []; + $isAssoc = (bool) count(array_filter(array_keys($optionsArray), 'is_string')); + + foreach ($optionsArray as $optionIndex => $optionValue) { + $result[] = $isAssoc + ? $optionIndex.':'.$optionValue + : $optionValue; + } + + return implode(' | ', $result); + } + + protected static function extractSnippetsFromMarkup($markup, $theme) + { + $map = []; + $matches = []; + + if (preg_match_all('/\]+\>.*\<\/figure\>/i', $markup, $matches)) { + foreach ($matches[0] as $snippetDeclaration) { + $nameMatch = []; + + if (!preg_match('/data\-snippet\s*=\s*"([^"]+)"/', $snippetDeclaration, $nameMatch)) { + continue; + } + + $snippetCode = $nameMatch[1]; + + $properties = []; + + $propertyMatches = []; + if (preg_match_all('/data\-property-(?[^=]+)\s*=\s*\"(?[^\"]+)\"/i', $snippetDeclaration, $propertyMatches)) { + foreach ($propertyMatches['property'] as $index => $propertyName) { + $properties[$propertyName] = $propertyMatches['value'][$index]; + } + } + + $componentMatch = []; + $componentClass = null; + + if (preg_match('/data\-component\s*=\s*"([^"]+)"/', $snippetDeclaration, $componentMatch)) { + $componentClass = $componentMatch[1]; + } + + // Apply default values for properties not defined in the markup + // and normalize property code names. + $properties = self::preprocessPropertyValues($theme, $snippetCode, $componentClass, $properties); + + $map[$snippetDeclaration] = [ + 'code' => $snippetCode, + 'component' => $componentClass, + 'properties' => $properties + ]; + } + } + + return $map; + } + + protected static function extractSnippetsFromMarkupCached($theme, $pageName, $markup) + { + if (array_key_exists($pageName, self::$pageSnippetMap)) { + return self::$pageSnippetMap[$pageName]; + } + + $key = self::getMapCacheKey($theme); + + $map = null; + $cached = Cache::get($key, false); + + if ($cached !== false && ($cached = @unserialize($cached)) !== false) { + if (array_key_exists($pageName, $cached)) { + $map = $cached[$pageName]; + } + } + + if (!is_array($map)) { + $map = self::extractSnippetsFromMarkup($markup, $theme); + + if (!is_array($cached)) { + $cached = []; + } + + $cached[$pageName] = $map; + $comboConfig = Config::get('cms.parsedPageCacheTTL', Config::get('cms.template_cache_ttl', 10)); + $expiresAt = now()->addMinutes($comboConfig); + Cache::put($key, serialize($cached), $expiresAt); + } + + self::$pageSnippetMap[$pageName] = $map; + + return $map; + } + + /** + * Returns a cache key for this record. + */ + protected static function getMapCacheKey($theme) + { + $key = crc32($theme->getPath()).'snippet-map'; + /** + * @event pages.snippet.getMapCacheKey + * Enables modifying the key used to reference cached RainLab.Pages snippet maps + * + * Example usage: + * + * Event::listen('pages.snippet.getMapCacheKey', function (&$key) { + * $key = $key . '-' . App::getLocale(); + * }); + * + */ + Event::fire('pages.snippet.getMapCacheKey', [&$key]); + return $key; + } + + /** + * Clears the snippet map item cache + * @param \Cms\Classes\Theme $theme Specifies the current theme. + */ + public static function clearMapCache($theme) + { + Cache::forget(self::getMapCacheKey($theme)); + } +} diff --git a/plugins/rainlab/pages/classes/SnippetManager.php b/plugins/rainlab/pages/classes/SnippetManager.php new file mode 100644 index 0000000..1d9af0b --- /dev/null +++ b/plugins/rainlab/pages/classes/SnippetManager.php @@ -0,0 +1,278 @@ +snippets !== null) { + return $this->snippets; + } + + $themeSnippets = $this->listThemeSnippets($theme); + $componentSnippets = $this->listComponentSnippets(); + + $this->snippets = array_merge($themeSnippets, $componentSnippets); + + /* + * @event pages.snippets.listSnippets + * Gives the ability to manage the snippet list dynamically. + * + * Example usage to add a snippet to the list: + * + * Event::listen('pages.snippets.listSnippets', function($manager) { + * $snippet = new \RainLab\Pages\Classes\Snippet(); + * $snippet->initFromComponentInfo('\Example\Plugin\Components\ComponentClass', 'snippetCode'); + * $manager->addSnippet($snippet); + * }); + * + * Example usage to remove a snippet from the list: + * + * Event::listen('pages.snippets.listSnippets', function($manager) { + * $manager->removeSnippet('snippetCode'); + * }); + */ + Event::fire('pages.snippets.listSnippets', [$this]); + + return $this->snippets; + } + + /** + * Add snippet to the list of snippets + * + * @param Snippet $snippet + * @return void + */ + public function addSnippet(Snippet $snippet) + { + $this->snippets[] = $snippet; + } + + /** + * Remove a snippet with the given code from the list of snippets + * + * @param string $snippetCode + * @return void + */ + public function removeSnippet(string $snippetCode) + { + $this->snippets = array_filter($this->snippets, function ($snippet) use ($snippetCode) { + return $snippet->code !== $snippetCode; + }); + } + + /** + * Finds a snippet by its code. + * This method is used internally by the system. + * @param \Cms\Classes\Theme $theme Specifies a parent theme. + * @param string $code Specifies the snippet code. + * @param string $$componentClass Specifies the snippet component class, if available. + * @param boolean $allowCaching Specifies whether caching is allowed for the call. + * @return array Returns an array of Snippet objects. + */ + public function findByCodeOrComponent($theme, $code, $componentClass, $allowCaching = false) + { + if (!$allowCaching) { + // If caching is not allowed, list all available snippets, + // find the snippet in the list and return it. + $snippets = $this->listSnippets($theme); + + foreach ($snippets as $snippet) { + if ($componentClass && $snippet->getComponentClass() == $componentClass) { + return $snippet; + } + + if ($snippet->code == $code) { + return $snippet; + } + } + + return null; + } + + // If caching is allowed, and the requested snippet is a partial snippet, + // try to load the partial name from the cache and initialize the snippet + // from the partial. + + if (!strlen($componentClass)) { + $map = $this->getPartialSnippetMap($theme); + + if (!array_key_exists($code, $map)) { + return null; + } + + $partialName = $map[$code]; + $partial = Partial::loadCached($theme, $partialName); + + if (!$partial) { + return null; + } + + $snippet = new Snippet; + $snippet->initFromPartial($partial); + + return $snippet; + } + else { + // If the snippet is a component snippet, initialize it + // from the component + + if (!class_exists($componentClass)) { + throw new SystemException(sprintf('The snippet component class %s is not found.', $componentClass)); + } + + $snippet = new Snippet; + $snippet->initFromComponentInfo($componentClass, $code); + + return $snippet; + } + } + + /** + * Clears front-end run-time cache. + * @param \Cms\Classes\Theme $theme Specifies a parent theme. + */ + public static function clearCache($theme) + { + Cache::forget(self::getPartialMapCacheKey($theme)); + + Snippet::clearMapCache($theme); + } + + /** + * Returns a cache key for this record. + */ + protected static function getPartialMapCacheKey($theme) + { + $key = crc32($theme->getPath()).'snippet-partial-map'; + /** + * @event pages.snippet.getPartialMapCacheKey + * Enables modifying the key used to reference cached RainLab.Pages partial maps + * + * Example usage: + * + * Event::listen('pages.snippet.getPartialMapCacheKey', function (&$key) { + * $key = $key . '-' . App::getLocale(); + * }); + * + */ + Event::fire('pages.snippet.getPartialMapCacheKey', [&$key]); + return $key; + } + + /** + * Returns a list of partial-based snippets and corresponding partial names. + * @param \Cms\Classes\Theme $theme Specifies a parent theme. + * @return Returns an associative array with the snippet code in keys and partial file names in values. + */ + public function getPartialSnippetMap($theme) + { + $key = self::getPartialMapCacheKey($theme); + + $result = []; + $cached = Cache::get($key, false); + + if ($cached !== false && ($cached = @unserialize($cached)) !== false) { + return $cached; + } + + $partials = Partial::listInTheme($theme); + + foreach ($partials as $partial) { + $viewBag = $partial->getViewBag(); + + $snippetCode = $viewBag->property('snippetCode'); + if (!strlen($snippetCode)) { + continue; + } + + $result[$snippetCode] = $partial->getFileName(); + } + + $comboConfig = Config::get('cms.parsedPageCacheTTL', Config::get('cms.template_cache_ttl', 10)); + $expiresAt = now()->addMinutes($comboConfig); + Cache::put($key, serialize($result), $expiresAt); + + return $result; + } + + /** + * Returns a list of snippets in the specified theme. + * @param \Cms\Classes\Theme $theme Specifies a parent theme. + * @return array Returns an array of Snippet objects. + */ + protected function listThemeSnippets($theme) + { + $result = []; + + $partials = Partial::listInTheme($theme, true); + + foreach ($partials as $partial) { + $viewBag = $partial->getViewBag(); + + if (strlen($viewBag->property('snippetCode'))) { + $snippet = new Snippet; + $snippet->initFromPartial($partial); + $result[] = $snippet; + } + } + + return $result; + } + + /** + * Returns a list of snippets created from components. + * @return array Returns an array of Snippet objects. + */ + protected function listComponentSnippets() + { + $result = []; + + $pluginManager = PluginManager::instance(); + $plugins = $pluginManager->getPlugins(); + + foreach ($plugins as $id => $plugin) { + if (!method_exists($plugin, 'registerPageSnippets')) { + continue; + } + + $snippets = $plugin->registerPageSnippets(); + if (!is_array($snippets)) { + continue; + } + + foreach ($snippets as $componentClass => $componentCode) { + // TODO: register snippet components later, during + // the page life cycle. + $snippet = new Snippet; + $snippet->initFromComponentInfo($componentClass, $componentCode); + $result[] = $snippet; + } + } + + return $result; + } +} diff --git a/plugins/rainlab/pages/classes/content/fields.yaml b/plugins/rainlab/pages/classes/content/fields.yaml new file mode 100644 index 0000000..19fe7a7 --- /dev/null +++ b/plugins/rainlab/pages/classes/content/fields.yaml @@ -0,0 +1,38 @@ +# =================================== +# Field Definitions +# =================================== + +fields: + fileName: + label: cms::lang.editor.filename + attributes: + default-focus: 1 + + toolbar: + type: partial + path: content_toolbar + cssClass: collapse-visible + + components: RainLab\Pages\FormWidgets\Components + +secondaryTabs: + stretch: true + fields: + markup: + tab: cms::lang.editor.content + stretch: true + type: codeeditor + language: html + theme: chrome + showGutter: false + highlightActiveLine: false + fontSize: 13 + cssClass: pagesTextEditor + margin: 20 + + markup_html: + tab: cms::lang.editor.content + stretch: true + type: richeditor + size: huge + valueFrom: markup diff --git a/plugins/rainlab/pages/classes/menu/fields.yaml b/plugins/rainlab/pages/classes/menu/fields.yaml new file mode 100644 index 0000000..89afe68 --- /dev/null +++ b/plugins/rainlab/pages/classes/menu/fields.yaml @@ -0,0 +1,34 @@ +# =================================== +# Field Definitions +# =================================== + +fields: + name: + span: left + label: rainlab.pages::lang.menu.name + placeholder: rainlab.pages::lang.menu.new_name + attributes: + default-focus: 1 + + code: + span: right + placeholder: rainlab.pages::lang.menu.new_code + label: rainlab.pages::lang.menu.code + preset: + field: name + type: file + + toolbar: + type: partial + path: menu_toolbar + cssClass: collapse-visible + +tabs: + stretch: true + cssClass: master-area + paneCssClass: pane-compact + fields: + items: + stretch: true + tab: rainlab.pages::lang.menu.items + type: RainLab\Pages\FormWidgets\MenuItems diff --git a/plugins/rainlab/pages/classes/menuitem/fields.yaml b/plugins/rainlab/pages/classes/menuitem/fields.yaml new file mode 100644 index 0000000..e4fa528 --- /dev/null +++ b/plugins/rainlab/pages/classes/menuitem/fields.yaml @@ -0,0 +1,69 @@ +# =================================== +# Field Definitions +# =================================== + +fields: + + search: + type: Rainlab\Pages\FormWidgets\MenuItemSearch + + title: + span: left + label: rainlab.pages::lang.menuitem.title + + type: + span: right + label: rainlab.pages::lang.menuitem.type + type: dropdown + + url: + label: rainlab.pages::lang.menuitem.url + + reference: + label: rainlab.pages::lang.menuitem.reference + type: dropdown + cssClass: input-sidebar-control + + cmsPage: + label: rainlab.pages::lang.menuitem.cms_page + comment: rainlab.pages::lang.menuitem.cms_page_comment + type: dropdown + cssClass: input-sidebar-control + + nesting: + label: rainlab.pages::lang.menuitem.allow_nested_items + comment: rainlab.pages::lang.menuitem.allow_nested_items_comment + type: checkbox + default: true + + replace: + label: rainlab.pages::lang.menuitem.replace + comment: rainlab.pages::lang.menuitem.replace_comment + type: checkbox + default: true + +tabs: + fields: + viewBag[isHidden]: + label: rainlab.pages::lang.menuitem.hidden + comment: rainlab.pages::lang.menuitem.hidden_comment + type: checkbox + tab: rainlab.pages::lang.menuitem.display_tab + + code: + label: rainlab.pages::lang.menuitem.code + comment: rainlab.pages::lang.menuitem.code_comment + tab: rainlab.pages::lang.menuitem.attributes_tab + span: auto + + viewBag[cssClass]: + label: rainlab.pages::lang.menuitem.css_class + comment: rainlab.pages::lang.menuitem.css_class_comment + tab: rainlab.pages::lang.menuitem.attributes_tab + span: auto + + viewBag[isExternal]: + label: rainlab.pages::lang.menuitem.external_link + comment: rainlab.pages::lang.menuitem.external_link_comment + type: checkbox + tab: rainlab.pages::lang.menuitem.attributes_tab diff --git a/plugins/rainlab/pages/classes/page/fields.yaml b/plugins/rainlab/pages/classes/page/fields.yaml new file mode 100644 index 0000000..9a2350e --- /dev/null +++ b/plugins/rainlab/pages/classes/page/fields.yaml @@ -0,0 +1,68 @@ +# =================================== +# Field Definitions +# =================================== + +fields: + viewBag[title]: + span: left + label: rainlab.pages::lang.editor.title + placeholder: rainlab.pages::lang.editor.new_title + attributes: + default-focus: 1 + + viewBag[url]: + span: right + placeholder: / + label: rainlab.pages::lang.editor.url + preset: + field: viewBag[title] + type: url + prefixInput: input[data-parent-url] + + toolbar: + type: partial + path: page_toolbar + cssClass: collapse-visible + +tabs: + cssClass: master-area + fields: + viewBag[layout]: + tab: cms::lang.editor.settings + label: rainlab.pages::lang.page.layout + type: dropdown + options: getLayoutOptions + + viewBag[is_hidden]: + tab: cms::lang.editor.settings + span: left + label: rainlab.pages::lang.editor.hidden + type: checkbox + comment: rainlab.pages::lang.editor.hidden_comment + + viewBag[navigation_hidden]: + tab: cms::lang.editor.settings + span: right + label: rainlab.pages::lang.editor.navigation_hidden + type: checkbox + comment: rainlab.pages::lang.editor.navigation_hidden_comment + + viewBag[meta_title]: + tab: cms::lang.editor.meta + label: cms::lang.editor.meta_title + + viewBag[meta_description]: + tab: cms::lang.editor.meta + label: cms::lang.editor.meta_description + type: textarea + size: tiny + +secondaryTabs: + stretch: true + fields: + markup: + tab: rainlab.pages::lang.editor.content + type: richeditor + legacyMode: true + stretch: true + size: huge diff --git a/plugins/rainlab/pages/components/ChildPages.php b/plugins/rainlab/pages/components/ChildPages.php new file mode 100644 index 0000000..7efba11 --- /dev/null +++ b/plugins/rainlab/pages/components/ChildPages.php @@ -0,0 +1,60 @@ + '', + * 'title' => '', + * 'page' => \RainLab\Pages\Classes\Page, + * 'viewBag' => array, + * 'is_hidden' => bool, + * 'navigation_hidden' => bool, + * ] + */ + public $pages = []; + + public function componentDetails() + { + return [ + 'name' => 'rainlab.pages::lang.component.child_pages_name', + 'description' => 'rainlab.pages::lang.component.child_pages_description' + ]; + } + + public function onRun() + { + // Check if the staticPage component is attached to the rendering template + $this->staticPageComponent = $this->findComponentByName('staticPage'); + if ($this->staticPageComponent->pageObject) { + $this->childPages = $this->staticPageComponent->pageObject->getChildren(); + + if ($this->childPages) { + foreach ($this->childPages as $childPage) { + $viewBag = $childPage->viewBag; + $this->pages = array_merge($this->pages, [[ + 'url' => @$viewBag['url'], + 'title' => @$viewBag['title'], + 'page' => $childPage, + 'viewBag' => $viewBag, + 'is_hidden' => @$viewBag['is_hidden'], + 'navigation_hidden' => @$viewBag['navigation_hidden'], + ]]); + } + } + } + } +} diff --git a/plugins/rainlab/pages/components/StaticBreadcrumbs.php b/plugins/rainlab/pages/components/StaticBreadcrumbs.php new file mode 100644 index 0000000..a1aa822 --- /dev/null +++ b/plugins/rainlab/pages/components/StaticBreadcrumbs.php @@ -0,0 +1,77 @@ + 'rainlab.pages::lang.component.static_breadcrumbs_name', + 'description' => 'rainlab.pages::lang.component.static_breadcrumbs_description' + ]; + } + + public function onRun() + { + $url = $this->getRouter()->getUrl(); + + if (!strlen($url)) { + $url = '/'; + } + + $theme = Theme::getActiveTheme(); + $router = new Router($theme); + $page = $router->findByUrl($url); + + if ($page) { + $tree = StaticPageClass::buildMenuTree($theme); + + $code = $startCode = $page->getBaseFileName(); + $breadcrumbs = []; + + while ($code) { + if (!isset($tree[$code])) { + break; + } + + $pageInfo = $tree[$code]; + + if ($pageInfo['navigation_hidden']) { + $code = $pageInfo['parent']; + continue; + } + + $reference = new MenuItemReference(); + $reference->title = $pageInfo['title']; + $reference->url = StaticPageClass::url($code); + $reference->isActive = $code == $startCode; + + $breadcrumbs[] = $reference; + + $code = $pageInfo['parent']; + } + + $breadcrumbs = array_reverse($breadcrumbs); + + $this->breadcrumbs = $this->page['breadcrumbs'] = $breadcrumbs; + } + } +} diff --git a/plugins/rainlab/pages/components/StaticMenu.php b/plugins/rainlab/pages/components/StaticMenu.php new file mode 100644 index 0000000..77d3aff --- /dev/null +++ b/plugins/rainlab/pages/components/StaticMenu.php @@ -0,0 +1,121 @@ + 'rainlab.pages::lang.component.static_menu_name', + 'description' => 'rainlab.pages::lang.component.static_menu_description' + ]; + } + + public function defineProperties() + { + return [ + 'code' => [ + 'title' => 'rainlab.pages::lang.component.static_menu_code_name', + 'description' => 'rainlab.pages::lang.component.static_menu_code_description', + 'type' => 'dropdown' + ] + ]; + } + + public function getCodeOptions() + { + $result = []; + + $theme = Theme::getEditTheme(); + $menus = PagesMenu::listInTheme($theme, true); + + foreach ($menus as $menu) { + $result[$menu->code] = $menu->name; + } + + return $result; + } + + public function onRun() + { + $this->page['menuItems'] = $this->menuItems(); + } + + public function menuItems() + { + if ($this->menuItems !== null) { + return $this->menuItems; + } + + if (!strlen($this->property('code'))) { + return; + } + + $theme = Theme::getActiveTheme(); + $menu = PagesMenu::loadCached($theme, $this->property('code')); + + if ($menu) { + $this->menuItems = $menu->generateReferences($this->page); + $this->menuName = $menu->name; + } + + return $this->menuItems; + } + + /** + * Counts the total menu items, including children. + */ + public function totalItems() + { + $countAll = function($items) use (&$countAll) { + $count = count($items); + + foreach ($items as $item) { + if (!isset($item->items)) { + continue; + } + + $count += $countAll($item->items); + } + + return $count; + }; + + return $countAll($this->menuItems()); + } + + /** + * Resets the menu code and rebuilds the menu. + * @param string $code + * @return array + */ + public function resetMenu($code) + { + $this->setProperty('code', $code); + $this->menuItems = null; + + return $this->page['menuItems'] = $this->menuItems(); + } +} diff --git a/plugins/rainlab/pages/components/StaticPage.php b/plugins/rainlab/pages/components/StaticPage.php new file mode 100644 index 0000000..c8c2c40 --- /dev/null +++ b/plugins/rainlab/pages/components/StaticPage.php @@ -0,0 +1,196 @@ + 'rainlab.pages::lang.component.static_page_name', + 'description' => 'rainlab.pages::lang.component.static_page_description' + ]; + } + + public function defineProperties() + { + return [ + 'useContent' => [ + 'title' => 'rainlab.pages::lang.component.static_page_use_content_name', + 'description' => 'rainlab.pages::lang.component.static_page_use_content_description', + 'default' => 1, + 'type' => 'checkbox', + 'showExternalParam' => false + ], + 'default' => [ + 'title' => 'rainlab.pages::lang.component.static_page_default_name', + 'description' => 'rainlab.pages::lang.component.static_page_default_description', + 'default' => 0, + 'type' => 'checkbox', + 'showExternalParam' => false + ], + 'childLayout' => [ + 'title' => 'rainlab.pages::lang.component.static_page_child_layout_name', + 'description' => 'rainlab.pages::lang.component.static_page_child_layout_description', + 'type' => 'string', + 'showExternalParam' => false + ] + ]; + } + + public function onRun() + { + $url = $this->getRouter()->getUrl(); + + if (!strlen($url)) { + $url = '/'; + } + + if ($this->isMaintenanceModeEnabled()) { + return; + } + + $router = new Router(Theme::getActiveTheme()); + $this->pageObject = $this->page['page'] = $router->findByUrl($url); + + if ($this->pageObject) { + $this->title = $this->page['title'] = array_get($this->pageObject->viewBag, 'title'); + $this->extraData = $this->page['extraData'] = $this->defineExtraData(); + } + } + + public function page() + { + return $this->pageObject; + } + + public function parent() + { + return $this->pageObject ? $this->pageObject->getParent() : null; + } + + public function children() + { + return $this->pageObject ? $this->pageObject->getChildren() : null; + } + + public function content() + { + // Evaluate the content property only when it's requested in the + // render time. Calling the page's getProcessedMarkup() method in the + // onRun() handler is too early as it triggers rendering component-based + // snippets defined on the static page too early in the page life cycle. -ab + + if ($this->contentCached !== false) { + return $this->contentCached; + } + + if ($this->pageObject) { + return $this->contentCached = $this->pageObject->getProcessedMarkup(); + } + + $this->contentCached = ''; + } + + /** + * Find foreign view bag values and add them to + * the component and page vars. + */ + protected function defineExtraData() + { + $standardProperties = [ + 'title', + 'url', + 'layout', + 'is_hidden', + 'navigation_hidden', + 'meta_title', + 'meta_description' + ]; + + $extraData = array_diff_key( + $this->pageObject->viewBag, + array_flip($standardProperties) + ); + + foreach ($extraData as $key => $value) { + $this->page[$key] = $value; + } + + return $extraData; + } + + /** + * isMaintenanceModeEnabled will check if maintenance mode is currently enabled. + * Static page logic should be disabled when this occurs. + */ + protected function isMaintenanceModeEnabled(): bool + { + // Logic for October CMS v2.0 + if (method_exists(MaintenanceSetting::class, 'isEnabled')) { + return MaintenanceSetting::isEnabled(); + } + + // Logic for October CMS v1.0 + return MaintenanceSetting::isConfigured() && + MaintenanceSetting::get('is_enabled', false) && + !\BackendAuth::getUser(); + } + + /** + * Implements the getter functionality. + * @param string $name + * @return void + */ + public function __get($name) + { + if (array_key_exists($name, $this->extraData)) { + return $this->extraData[$name]; + } + + return null; + } + + /** + * Determine if an attribute exists on the object. + * @param string $key + * @return void + */ + public function __isset($key) + { + if (array_key_exists($key, $this->extraData)) { + return true; + } + + return false; + } +} diff --git a/plugins/rainlab/pages/components/childpages/default.htm b/plugins/rainlab/pages/components/childpages/default.htm new file mode 100644 index 0000000..3e6a01f --- /dev/null +++ b/plugins/rainlab/pages/components/childpages/default.htm @@ -0,0 +1,9 @@ +{% if __SELF__.pages is not empty %} + +{% endif %} diff --git a/plugins/rainlab/pages/components/staticbreadcrumbs/default.htm b/plugins/rainlab/pages/components/staticbreadcrumbs/default.htm new file mode 100644 index 0000000..a1a9184 --- /dev/null +++ b/plugins/rainlab/pages/components/staticbreadcrumbs/default.htm @@ -0,0 +1,9 @@ +{% if breadcrumbs %} + +{% endif %} diff --git a/plugins/rainlab/pages/components/staticmenu/default.htm b/plugins/rainlab/pages/components/staticmenu/default.htm new file mode 100644 index 0000000..5ca78a2 --- /dev/null +++ b/plugins/rainlab/pages/components/staticmenu/default.htm @@ -0,0 +1,5 @@ +{% if __SELF__.menuItems %} +
      + {% partial __SELF__ ~ "::items" items=__SELF__.menuItems %} +
    +{% endif %} diff --git a/plugins/rainlab/pages/components/staticmenu/items.htm b/plugins/rainlab/pages/components/staticmenu/items.htm new file mode 100644 index 0000000..2ac1060 --- /dev/null +++ b/plugins/rainlab/pages/components/staticmenu/items.htm @@ -0,0 +1,17 @@ +{% for item in items %} + {% if not item.viewBag.isHidden %} + + {% endif %} +{% endfor %} diff --git a/plugins/rainlab/pages/components/staticpage/default.htm b/plugins/rainlab/pages/components/staticpage/default.htm new file mode 100644 index 0000000..53cfbbc --- /dev/null +++ b/plugins/rainlab/pages/components/staticpage/default.htm @@ -0,0 +1 @@ +{{ __SELF__.content|raw }} \ No newline at end of file diff --git a/plugins/rainlab/pages/composer.json b/plugins/rainlab/pages/composer.json new file mode 100644 index 0000000..a7fc74d --- /dev/null +++ b/plugins/rainlab/pages/composer.json @@ -0,0 +1,25 @@ +{ + "name": "rainlab/pages-plugin", + "type": "october-plugin", + "description": "Pages plugin for October CMS", + "homepage": "https://octobercms.com/plugin/rainlab-pages", + "keywords": ["october", "octobercms", "pages"], + "license": "MIT", + "authors": [ + { + "name": "Alexey Bobkov", + "email": "aleksey.bobkov@gmail.com", + "role": "Co-founder" + }, + { + "name": "Samuel Georges", + "email": "daftspunky@gmail.com", + "role": "Co-founder" + } + ], + "require": { + "php": ">=5.5.9", + "composer/installers": "~1.0" + }, + "minimum-stability": "dev" +} diff --git a/plugins/rainlab/pages/controllers/Index.php b/plugins/rainlab/pages/controllers/Index.php new file mode 100644 index 0000000..1e3dc99 --- /dev/null +++ b/plugins/rainlab/pages/controllers/Index.php @@ -0,0 +1,1027 @@ +theme = Theme::getEditTheme())) { + throw new ApplicationException(Lang::get('cms::lang.theme.edit.not_found')); + } + + if ($this->user) { + if ($this->user->hasAccess('rainlab.pages.manage_pages')) { + new PageList($this, 'pageList'); + $this->vars['activeWidgets'][] = 'pageList'; + } + + if ($this->user->hasAccess('rainlab.pages.manage_menus')) { + new MenuList($this, 'menuList'); + $this->vars['activeWidgets'][] = 'menuList'; + } + + if ($this->user->hasAccess('rainlab.pages.manage_content')) { + new TemplateList($this, 'contentList', function() { + return $this->getContentTemplateList(); + }); + $this->vars['activeWidgets'][] = 'contentList'; + } + + if ($this->user->hasAccess('rainlab.pages.access_snippets')) { + new SnippetList($this, 'snippetList'); + $this->vars['activeWidgets'][] = 'snippetList'; + } + } + } + catch (Exception $ex) { + $this->handleError($ex); + } + + $context = [ + 'pageList' => 'pages', + 'menuList' => 'menus', + 'contentList' => 'content', + 'snippetList' => 'snippets', + ]; + + BackendMenu::setContext('RainLab.Pages', 'pages', @$context[$this->vars['activeWidgets'][0]]); + } + + // + // Pages, menus and text blocks + // + + public function index() + { + $this->addJs('/plugins/rainlab/pages/assets/js/october.treeview.js', 'RainLab.Pages'); + $this->addJs('/plugins/rainlab/pages/assets/js/pages-page.js', 'RainLab.Pages'); + $this->addJs('/plugins/rainlab/pages/assets/js/pages-snippets.js', 'RainLab.Pages'); + $this->addCss('/plugins/rainlab/pages/assets/css/pages.css', 'RainLab.Pages'); + $this->addCss('/plugins/rainlab/pages/assets/css/treeview.css', 'RainLab.Pages'); + + // Preload the code editor class as it could be needed + // before it loads dynamically. + $this->addJs('/modules/backend/formwidgets/codeeditor/assets/js/build-min.js', 'core'); + + $this->bodyClass = 'compact-container sidenav-responsive'; + $this->pageTitle = 'rainlab.pages::lang.plugin.name'; + $this->pageTitleTemplate = Lang::get('rainlab.pages::lang.page.template_title'); + + if (Request::ajax() && Request::input('formWidgetAlias')) { + $this->bindFormWidgetToController(); + } + } + + /** + * index_onOpen + */ + public function index_onOpen() + { + $this->validateRequestTheme(); + + $type = Request::input('type'); + $object = $this->loadObject($type, Request::input('path')); + + /* + * Extensibility + */ + Event::fire('pages.object.load', [$this, $object, $type]); + $this->fireEvent('object.load', [$object, $type]); + + return $this->pushObjectForm($type, $object); + } + + /** + * onSave + */ + public function onSave() + { + $this->validateRequestTheme(); + $type = Request::input('objectType'); + + $object = $this->fillObjectFromPost($type); + $object->save(); + + /* + * Extensibility + */ + Event::fire('pages.object.save', [$this, $object, $type]); + $this->fireEvent('object.save', [$object, $type]); + + $result = $this->getUpdateResponse($object, $type); + + $successMessages = [ + 'page' => 'rainlab.pages::lang.page.saved', + 'menu' => 'rainlab.pages::lang.menu.saved', + 'content' => 'rainlab.pages::lang.content.saved', + ]; + + $successMessage = isset($successMessages[$type]) + ? $successMessages[$type] + : $successMessages['page']; + + Flash::success(Lang::get($successMessage)); + + return $result; + } + + public function onCreateObject() + { + $this->validateRequestTheme(); + + $type = Request::input('type'); + $object = $this->createObject($type); + $parent = Request::input('parent'); + $parentPage = null; + + if ($type == 'page') { + if (strlen($parent)) { + $parentPage = StaticPage::load($this->theme, $parent); + } + + $object->setDefaultLayout($parentPage); + } + + $widget = $this->makeObjectFormWidget($type, $object); + $this->vars['objectPath'] = ''; + $this->vars['canCommit'] = $this->canCommitObject($object); + $this->vars['canReset'] = $this->canResetObject($object); + + $result = [ + 'tabTitle' => $this->getTabTitle($type, $object), + 'tab' => $this->makePartial('form_page', [ + 'form' => $widget, + 'objectType' => $type, + 'objectTheme' => $this->theme->getDirName(), + 'objectMtime' => null, + 'objectParent' => $parent, + 'parentPage' => $parentPage + ]) + ]; + + return $result; + } + + public function onDelete() + { + $this->validateRequestTheme(); + + $type = Request::input('objectType'); + + $deletedObjects = $this->loadObject($type, trim(Request::input('objectPath')))->delete(); + + $result = [ + 'deletedObjects' => $deletedObjects, + 'theme' => $this->theme->getDirName() + ]; + + return $result; + } + + public function onDeleteObjects() + { + $this->validateRequestTheme(); + + $type = Request::input('type'); + $objects = Request::input('object'); + + if (!$objects) { + $objects = Request::input('template'); + } + + $error = null; + $deleted = []; + + try { + foreach ($objects as $path => $selected) { + if (!$selected) { + continue; + } + $object = $this->loadObject($type, $path, true); + if (!$object) { + continue; + } + + $deletedObjects = $object->delete(); + if (is_array($deletedObjects)) { + $deleted = array_merge($deleted, $deletedObjects); + } + else { + $deleted[] = $path; + } + } + } + catch (Exception $ex) { + $error = $ex->getMessage(); + } + + return [ + 'deleted' => $deleted, + 'error' => $error, + 'theme' => Request::input('theme') + ]; + } + + public function onOpenConcurrencyResolveForm() + { + return $this->makePartial('concurrency_resolve_form'); + } + + public function onGetMenuItemTypeInfo() + { + $type = Request::input('type'); + + return [ + 'menuItemTypeInfo' => MenuItem::getTypeInfo($type) + ]; + } + + public function onUpdatePageLayout() + { + $this->validateRequestTheme(); + + $type = Request::input('objectType'); + + $object = $this->fillObjectFromPost($type); + + return $this->pushObjectForm($type, $object, Request::input('formWidgetAlias')); + } + + public function onGetInspectorConfiguration() + { + $configuration = []; + + $snippetCode = Request::input('snippet'); + $componentClass = Request::input('component'); + + if (strlen($snippetCode)) { + $snippet = SnippetManager::instance()->findByCodeOrComponent($this->theme, $snippetCode, $componentClass); + if (!$snippet) { + throw new ApplicationException(trans('rainlab.pages::lang.snippet.not_found', ['code' => $snippetCode])); + } + + $configuration = $snippet->getProperties(); + } + + return [ + 'configuration' => [ + 'properties' => $configuration, + 'title' => $snippet->getName(), + 'description' => $snippet->getDescription() + ] + ]; + } + + public function onGetSnippetNames() + { + $codes = array_unique(Request::input('codes')); + $result = []; + + foreach ($codes as $snippetCode) { + $parts = explode('|', $snippetCode); + $componentClass = null; + + if (count($parts) > 1) { + $snippetCode = $parts[0]; + $componentClass = $parts[1]; + } + + $snippet = SnippetManager::instance()->findByCodeOrComponent($this->theme, $snippetCode, $componentClass); + + if (!$snippet) { + $result[$snippetCode] = trans('rainlab.pages::lang.snippet.not_found', ['code' => $snippetCode]); + } + else { + $result[$snippetCode] =$snippet->getName(); + } + } + + return [ + 'names' => $result + ]; + } + + public function onMenuItemReferenceSearch() + { + $alias = Request::input('alias'); + + $widget = $this->makeFormWidget( + 'Rainlab\Pages\FormWidgets\MenuItemSearch', + [], + ['alias' => $alias] + ); + + return $widget->onSearch(); + } + + /** + * Commits the DB changes of a object to the filesystem + * + * @return array $response + */ + public function onCommit() + { + $this->validateRequestTheme(); + $type = Request::input('objectType'); + $object = $this->loadObject($type, trim(Request::input('objectPath'))); + + if ($this->canCommitObject($object)) { + if (class_exists('System')) { + // v1.2 + $datasource = $this->getThemeDatasource(); + $datasource->updateModelAtIndex(1, $object); + $datasource->forceDeleteModelAtIndex(0, $object); + } + else { + // v1.1 + $datasource = $this->getThemeDatasource(); + $datasource->pushToSource($object, 'filesystem'); + $datasource->removeFromSource($object, 'database'); + } + + Flash::success(Lang::get('cms::lang.editor.commit_success', ['type' => $type])); + } + + return array_merge($this->getUpdateResponse($object, $type), ['forceReload' => true]); + } + + /** + * Resets a object to the version on the filesystem + * + * @return array $response + */ + public function onReset() + { + $this->validateRequestTheme(); + $type = Request::input('objectType'); + $object = $this->loadObject($type, trim(Request::input('objectPath'))); + + if ($this->canResetObject($object)) { + if (class_exists('System')) { + // v1.2 + $datasource = $this->getThemeDatasource(); + $datasource->forceDeleteModelAtIndex(0, $object); + } + else { + // v1.1 + $datasource = $this->getThemeDatasource(); + $datasource->removeFromSource($object, 'database'); + } + + Flash::success(Lang::get('cms::lang.editor.reset_success', ['type' => $type])); + } + + return array_merge($this->getUpdateResponse($object, $type), ['forceReload' => true]); + } + + // + // Methods for internal use + // + + /** + * Get the response to return in an AJAX request that updates an object + * + * @param CmsObject $object The object that has been affected + * @param string $type The type of object being affected + * @return array $result; + */ + protected function getUpdateResponse(CmsObject $object, string $type) + { + $result = [ + 'objectPath' => $type != 'content' ? $object->getBaseFileName() : $object->fileName, + 'objectMtime' => $object->mtime, + 'tabTitle' => $this->getTabTitle($type, $object) + ]; + + if ($type == 'page') { + $result['pageUrl'] = $this->getPreviewPageUrl($object); + PagesPlugin::clearCache(); + } + + $result['canCommit'] = $this->canCommitObject($object); + $result['canReset'] = $this->canResetObject($object); + + return $result; + } + + /** + * Get the active theme's datasource + */ + protected function getThemeDatasource() + { + return $this->theme->getDatasource(); + } + + /** + * Check to see if the provided object can be committed + * Only available in debug mode, the DB layer must be enabled, and the object must exist in the database + * + * @param CmsObject $object + * @return boolean + */ + protected function canCommitObject(CmsObject $object) + { + $result = false; + + if (class_exists('System')) { + // v1.2 + if ( + Config::get('app.debug', false) && + $this->theme->secondLayerEnabled() && + $this->getThemeDatasource()->hasModelAtIndex(1, $object) + ) { + $result = true; + } + } + else { + // v1.1 + if (Config::get('app.debug', false) && + Theme::databaseLayerEnabled() && + $this->getThemeDatasource()->sourceHasModel('database', $object) + ) { + $result = true; + } + } + + return $result; + } + + /** + * Check to see if the provided object can be reset + * Only available when the DB layer is enabled and the object exists in both the DB & Filesystem + * + * @param CmsObject $object + * @return boolean + */ + protected function canResetObject(CmsObject $object) + { + $result = false; + + if (class_exists('System')) { + // v1.2 + if ($this->theme->secondLayerEnabled()) { + $datasource = $this->getThemeDatasource(); + $result = $datasource->hasModelAtIndex(0, $object) && + $datasource->hasModelAtIndex(1, $object); + } + } + else { + // v1.1 + if (Theme::databaseLayerEnabled()) { + $datasource = $this->getThemeDatasource(); + $result = $datasource->sourceHasModel('database', $object) && $datasource->sourceHasModel('filesystem', $object); + } + } + + return $result; + } + + /** + * validateRequestTheme + */ + protected function validateRequestTheme() + { + if ($this->theme->getDirName() != Request::input('theme')) { + throw new ApplicationException(trans('cms::lang.theme.edit.not_match')); + } + } + + /** + * loadObject + */ + protected function loadObject($type, $path, $ignoreNotFound = false) + { + $class = $this->resolveTypeClassName($type); + + if (!($object = call_user_func(array($class, 'load'), $this->theme, $path))) { + if (!$ignoreNotFound) { + throw new ApplicationException(trans('rainlab.pages::lang.object.not_found')); + } + + return null; + } + + return $object; + } + + protected function createObject($type) + { + $class = $this->resolveTypeClassName($type); + + if (!($object = $class::inTheme($this->theme))) { + throw new ApplicationException(trans('rainlab.pages::lang.object.not_found')); + } + + return $object; + } + + protected function resolveTypeClassName($type) + { + $types = [ + 'page' => \RainLab\Pages\Classes\Page::class, + 'menu' => \RainLab\Pages\Classes\Menu::class, + 'content' => \RainLab\Pages\Classes\Content::class + ]; + + if (!array_key_exists($type, $types)) { + throw new ApplicationException(Lang::get('rainlab.pages::lang.object.invalid_type') . ' - type - ' . $type); + } + + $allowed = false; + if ($type === 'content') { + $allowed = $this->user->hasAccess('rainlab.pages.manage_content'); + } + else { + $allowed = $this->user->hasAccess("rainlab.pages.manage_{$type}s"); + } + + if (!$allowed) { + throw new ApplicationException(Lang::get('rainlab.pages::lang.object.unauthorized_type', ['type' => $type])); + } + + return $types[$type]; + } + + protected function makeObjectFormWidget($type, $object, $alias = null) + { + $formConfigs = [ + 'page' => '~/plugins/rainlab/pages/classes/page/fields.yaml', + 'menu' => '~/plugins/rainlab/pages/classes/menu/fields.yaml', + 'content' => '~/plugins/rainlab/pages/classes/content/fields.yaml' + ]; + + if (!array_key_exists($type, $formConfigs)) { + throw new ApplicationException(Lang::get('rainlab.pages::lang.object.not_found')); + } + + $widgetConfig = $this->makeConfig($formConfigs[$type]); + $widgetConfig->model = $object; + $widgetConfig->alias = $alias ?: 'form' . studly_case($type) . md5($object->exists ? $object->getFileName() : uniqid()); + $widgetConfig->context = !$object->exists ? 'create' : 'update'; + + $widget = $this->makeWidget('Backend\Widgets\Form', $widgetConfig); + + if ($type == 'page') { + $widget->bindEvent('form.extendFieldsBefore', function() use ($widget, $object) { + $this->checkContentField($widget, $object); + $this->addPagePlaceholders($widget, $object); + $this->addPageSyntaxFields($widget, $object); + }); + } + + return $widget; + } + + protected function checkContentField($formWidget, $page) + { + if (!($layout = $page->getLayoutObject())) { + return; + } + + $component = $layout->getComponent('staticPage'); + + if (!$component) { + return; + } + + if (!$component->property('useContent', true)) { + unset($formWidget->secondaryTabs['fields']['markup']); + } + } + + /** + * modLegacyModeFields will ensure specific field types use legacy mode + */ + protected function modLegacyModeFields($fields) + { + foreach ($fields as &$fieldConfig) { + if (in_array($fieldConfig['type'], ['richeditor', 'codeeditor'])) { + $fieldConfig['legacyMode'] = true; + } + } + + return $fields; + } + + /** + * addPageSyntaxFields adds syntax defined fields to the form + */ + protected function addPageSyntaxFields($formWidget, $page) + { + $fields = $page->listLayoutSyntaxFields(); + $fields = $this->modLegacyModeFields($fields); + + foreach ($fields as $fieldCode => $fieldConfig) { + if ($fieldConfig['type'] === 'fileupload') { + continue; + } + + if (in_array($fieldConfig['type'], ['repeater', 'nestedform'])) { + if (empty($fieldConfig['form']) || !is_string($fieldConfig['form'])) { + $repeaterFields = array_get($fieldConfig, 'fields', []); + $repeaterFields = $this->modLegacyModeFields($repeaterFields); + $fieldConfig['form']['fields'] = $repeaterFields; + unset($fieldConfig['fields']); + } + } + + /* + * Custom fields placement + */ + $placement = !empty($fieldConfig['placement']) ? $fieldConfig['placement'] : null; + + switch ($placement) { + case 'primary': + $formWidget->tabs['fields']['viewBag[' . $fieldCode . ']'] = $fieldConfig; + break; + + default: + $fieldConfig['cssClass'] = 'secondary-tab ' . array_get($fieldConfig, 'cssClass', ''); + $formWidget->secondaryTabs['fields']['viewBag[' . $fieldCode . ']'] = $fieldConfig; + break; + } + + /* + * Translation support + */ + $translatableTypes = ['text', 'textarea', 'richeditor', 'repeater', 'markdown', 'mediafinder', 'nestedform']; + if (in_array($fieldConfig['type'], $translatableTypes) && array_get($fieldConfig, 'translatable', true)) { + $page->translatable[] = 'viewBag['.$fieldCode.']'; + } + } + } + + protected function addPagePlaceholders($formWidget, $page) + { + $placeholders = $page->listLayoutPlaceholders(); + + foreach ($placeholders as $placeholderCode => $info) { + if ($info['ignore']) { + continue; + } + + $placeholderTitle = $info['title']; + $fieldConfig = [ + 'tab' => $placeholderTitle, + 'stretch' => '1', + 'size' => 'huge', + 'legacyMode' => true + ]; + + if ($info['type'] != 'text') { + $fieldConfig['type'] = 'richeditor'; + } + else { + $fieldConfig['type'] = 'codeeditor'; + $fieldConfig['language'] = 'text'; + $fieldConfig['theme'] = 'chrome'; + $fieldConfig['showGutter'] = false; + $fieldConfig['highlightActiveLine'] = false; + $fieldConfig['cssClass'] = 'pagesTextEditor'; + $fieldConfig['showInvisibles'] = false; + $fieldConfig['fontSize'] = 13; + $fieldConfig['margin'] = '20'; + } + + $formWidget->secondaryTabs['fields']['placeholders['.$placeholderCode.']'] = $fieldConfig; + + /* + * Translation support + */ + $page->translatable[] = 'placeholders['.$placeholderCode.']'; + } + } + + protected function getTabTitle($type, $object) + { + if ($type == 'page') { + $viewBag = $object->getViewBag(); + $result = $viewBag ? $viewBag->property('title') : false; + if (!$result) { + $result = trans('rainlab.pages::lang.page.new'); + } + + return $result; + } + elseif ($type == 'menu') { + $result = $object->name; + if (!strlen($result)) { + $result = trans('rainlab.pages::lang.menu.new'); + } + + return $result; + } + elseif ($type == 'content') { + $result = in_array($type, ['asset', 'content']) + ? $object->getFileName() + : $object->getBaseFileName(); + + if (!$result) { + $result = trans('cms::lang.'.$type.'.new'); + } + + return $result; + } + + return $object->getFileName(); + } + + /** + * fillObjectFromPost + */ + protected function fillObjectFromPost($type) + { + $objectPath = trim(Request::input('objectPath')); + $object = $objectPath ? $this->loadObject($type, $objectPath) : $this->createObject($type); + + // Set page layout super early because it cascades to other elements + if ($type === 'page' && ($layout = post('viewBag[layout]'))) { + $object->getViewBag()->setProperty('layout', $layout); + } + + $formWidget = $this->makeObjectFormWidget($type, $object, Request::input('formWidgetAlias')); + + $saveData = $formWidget->getSaveData(); + $postData = post(); + $objectData = []; + + if ($viewBag = array_get($saveData, 'viewBag')) { + $objectData['settings'] = ['viewBag' => $viewBag]; + } + + $fields = ['markup', 'code', 'fileName', 'content', 'itemData', 'name']; + + if ($type != 'menu' && $type != 'content') { + $object->parentFileName = Request::input('parentFileName'); + } + + foreach ($fields as $field) { + if (array_key_exists($field, $saveData)) { + $objectData[$field] = $saveData[$field]; + } + elseif (array_key_exists($field, $postData)) { + $objectData[$field] = $postData[$field]; + } + } + + if ($type == 'page') { + $placeholders = array_get($saveData, 'placeholders'); + + $comboConfig = Config::get('cms.convertLineEndings', Config::get('system.convert_line_endings', false)); + if (is_array($placeholders) && $comboConfig === true) { + $placeholders = array_map([$this, 'convertLineEndings'], $placeholders); + } + + $objectData['placeholders'] = $placeholders; + } + + if ($type == 'content') { + $fileName = $objectData['fileName']; + + if (dirname($fileName) == 'static-pages') { + throw new ApplicationException(trans('rainlab.pages::lang.content.cant_save_to_dir')); + } + + $extension = pathinfo($fileName, PATHINFO_EXTENSION); + + if ($extension === 'htm' || $extension === 'html' || !strlen($extension)) { + $objectData['markup'] = array_get($saveData, 'markup_html'); + } + } + + if ($type == 'menu') { + // If no item data is sent through POST, this means the menu is empty + if (!isset($objectData['itemData'])) { + $objectData['itemData'] = []; + } else { + $objectData['itemData'] = json_decode($objectData['itemData'], true); + if (json_last_error() !== JSON_ERROR_NONE || !is_array($objectData['itemData'])) { + $objectData['itemData'] = []; + } + } + } + + $comboConfig = Config::get('cms.convertLineEndings', Config::get('system.convert_line_endings', false)); + if (!empty($objectData['markup']) && $comboConfig === true) { + $objectData['markup'] = $this->convertLineEndings($objectData['markup']); + } + + /* + * Extensibility + */ + Event::fire('pages.object.fillObject', [$this, $object, &$objectData, $type]); + $this->fireEvent('object.fillObject', [$object, &$objectData, $type]); + + if (!Request::input('objectForceSave') && $object->mtime) { + if (Request::input('objectMtime') != $object->mtime) { + throw new ApplicationException('mtime-mismatch'); + } + } + + $object->fill($objectData); + + /* + * Rehydrate the object viewBag array property where values are sourced. + */ + if ($object instanceof CmsCompoundObject && is_array($viewBag)) { + $object->viewBag = $viewBag + $object->viewBag; + } + + return $object; + } + + /** + * pushObjectForm + */ + protected function pushObjectForm($type, $object, $alias = null) + { + $widget = $this->makeObjectFormWidget($type, $object, $alias); + + $this->vars['canCommit'] = $this->canCommitObject($object); + $this->vars['canReset'] = $this->canResetObject($object); + $this->vars['objectPath'] = Request::input('path'); + $this->vars['lastModified'] = DateTime::makeCarbon($object->mtime); + + if ($type == 'page') { + $this->vars['pageUrl'] = $this->getPreviewPageUrl($object); + } + + return [ + 'tabTitle' => $this->getTabTitle($type, $object), + 'tab' => $this->makePartial('form_page', [ + 'form' => $widget, + 'objectType' => $type, + 'objectTheme' => $this->theme->getDirName(), + 'objectMtime' => $object->mtime, + 'objectParent' => Request::input('parentFileName') + ]) + ]; + } + + /** + * getPreviewPageUrl + */ + protected function getPreviewPageUrl($object) + { + $pageUrl = $object->getViewBag()->property('url'); + + // Support for October CMS 3.0 and below + if (!class_exists('Site')) { + return Url::to($pageUrl); + } + + /** + * Hook the site picker to determine preview + * @see \Cms\Components\SitePicker + */ + $eventPattern = Event::fire('cms.sitePicker.overridePattern', [ + $object, + $pageUrl, + Site::getEditSite(), + Site::getEditSite() + ], true); + + if ($eventPattern) { + $pageUrl = $eventPattern; + } + + return Cms::fullUrl($pageUrl); + } + + /** + * bindFormWidgetToController + */ + protected function bindFormWidgetToController() + { + $alias = Request::input('formWidgetAlias'); + $type = Request::input('objectType'); + $objectPath = trim(Request::input('objectPath')); + + if (!$objectPath) { + $object = $this->createObject($type); + } + else { + $object = $this->loadObject($type, $objectPath); + } + + // Set page layout super early because it cascades to other elements + if ($type === 'page' && ($layout = post('viewBag[layout]'))) { + $object->getViewBag()->setProperty('layout', $layout); + } + + $widget = $this->makeObjectFormWidget($type, $object, $alias); + $widget->bindToController(); + } + + /** + * Replaces Windows style (/r/n) line endings with unix style (/n) + * line endings. + * @param string $markup The markup to convert to unix style endings + * @return string + */ + protected function convertLineEndings($markup) + { + $markup = str_replace("\r\n", "\n", $markup); + $markup = str_replace("\r", "\n", $markup); + + return $markup; + } + + /** + * Returns a list of content files + * @return \October\Rain\Database\Collection + */ + protected function getContentTemplateList() + { + $templates = Content::listInTheme($this->theme, true); + + /** + * @event pages.content.templateList + * Provides opportunity to filter the items returned to the ContentList widget used by the RainLab.Pages plugin in the backend. + * + * >**NOTE**: Recommended to just use cms.object.listInTheme instead + * + * Parameter provided is `$templates` (a collection of the Content CmsObjects being returned). + * > Note: The `$templates` parameter provided is an object reference to a CmsObjectCollection, to make changes you must use object modifying methods. + * + * Example usage (only shows allowed content files): + * + * \Event::listen('pages.content.templateList', function ($templates) { + * foreach ($templates as $index = $content) { + * if (!in_array($content->fileName, $allowedContent)) { + * $templates->forget($index); + * } + * } + * }); + * + * Or: + * + * \RainLab\Pages\Controller\Index::extend(function ($controller) { + * $controller->bindEvent('content.templateList', function ($templates) { + * foreach ($templates as $index = $content) { + * if (!in_array($content->fileName, $allowedContent)) { + * $templates->forget($index); + * } + * } + * }); + * }); + * } + */ + if ( + ($event = $this->fireEvent('content.templateList', [$templates], true)) || + ($event = Event::fire('pages.content.templateList', [$this, $templates], true)) + ) { + return $event; + } + + return $templates; + } +} diff --git a/plugins/rainlab/pages/controllers/index/_concurrency_resolve_form.htm b/plugins/rainlab/pages/controllers/index/_concurrency_resolve_form.htm new file mode 100644 index 0000000..5e3d7be --- /dev/null +++ b/plugins/rainlab/pages/controllers/index/_concurrency_resolve_form.htm @@ -0,0 +1,29 @@ +'return false']) ?> + + + + \ No newline at end of file diff --git a/plugins/rainlab/pages/controllers/index/_content_toolbar.htm b/plugins/rainlab/pages/controllers/index/_content_toolbar.htm new file mode 100644 index 0000000..a77f306 --- /dev/null +++ b/plugins/rainlab/pages/controllers/index/_content_toolbar.htm @@ -0,0 +1,48 @@ +
    + + + + + + + + + + + + + + +
    diff --git a/plugins/rainlab/pages/controllers/index/_form_page.htm b/plugins/rainlab/pages/controllers/index/_form_page.htm new file mode 100644 index 0000000..1ee8c7c --- /dev/null +++ b/plugins/rainlab/pages/controllers/index/_form_page.htm @@ -0,0 +1,25 @@ + 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => e(trans('backend::lang.form.confirm_tab_close')), + 'data-object-type' => e($objectType) +]) ?> + render() ?> + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/rainlab/pages/controllers/index/_menu_toolbar.htm b/plugins/rainlab/pages/controllers/index/_menu_toolbar.htm new file mode 100644 index 0000000..8faf463 --- /dev/null +++ b/plugins/rainlab/pages/controllers/index/_menu_toolbar.htm @@ -0,0 +1,48 @@ +
    + + + + + + + + + + + + + + +
    diff --git a/plugins/rainlab/pages/controllers/index/_page_toolbar.htm b/plugins/rainlab/pages/controllers/index/_page_toolbar.htm new file mode 100644 index 0000000..028bb08 --- /dev/null +++ b/plugins/rainlab/pages/controllers/index/_page_toolbar.htm @@ -0,0 +1,58 @@ +
    + + + + + + + + + + + + + + + + + + + +
    diff --git a/plugins/rainlab/pages/controllers/index/_sidepanel.htm b/plugins/rainlab/pages/controllers/index/_sidepanel.htm new file mode 100644 index 0000000..183a839 --- /dev/null +++ b/plugins/rainlab/pages/controllers/index/_sidepanel.htm @@ -0,0 +1,29 @@ +
    +
    +
    + +
    + widget->pageList->render() ?> +
    + + + +
    + widget->menuList->render() ?> +
    + + + +
    + widget->contentList->render() ?> +
    + + + +
    + widget->snippetList->render() ?> +
    + +
    +
    +
    diff --git a/plugins/rainlab/pages/controllers/index/config_content_list.yaml b/plugins/rainlab/pages/controllers/index/config_content_list.yaml new file mode 100644 index 0000000..511203b --- /dev/null +++ b/plugins/rainlab/pages/controllers/index/config_content_list.yaml @@ -0,0 +1,11 @@ +# =================================== +# Configures the layout list widget +# =================================== + +titleProperty: 'nice_title' +noRecordsMessage: 'cms::lang.content.no_list_records' +deleteConfirmation: 'cms::lang.content.delete_confirm_multiple' +itemType: content +controlClass: filelist-hero content +ignoreDirectories: + - static-pages* diff --git a/plugins/rainlab/pages/controllers/index/index.htm b/plugins/rainlab/pages/controllers/index/index.htm new file mode 100644 index 0000000..e9279db --- /dev/null +++ b/plugins/rainlab/pages/controllers/index/index.htm @@ -0,0 +1,32 @@ + + fatalError): ?> + makePartial('sidepanel') ?> + + + + + fatalError): ?> +
    + +
    +
    + +
    +
    +
    +
    + +
    + + +

    fatalError)) ?>

    + + diff --git a/plugins/rainlab/pages/docs/component-childpages.md b/plugins/rainlab/pages/docs/component-childpages.md new file mode 100644 index 0000000..55268c1 --- /dev/null +++ b/plugins/rainlab/pages/docs/component-childpages.md @@ -0,0 +1,35 @@ +# Component: Child Pages (childPages) + +## Purpose +Outputs a list of child pages of the current page + +## Default output + +The default component partial outputs a simple nested unordered list: + +```html + +``` + +You might want to render the list with your own code. The `childPages.pages` variable is an array of arrays representing the child pages. Each of the arrays has the following items: + +Property | Type | Description +-------- | ---- | ----------- +`url` | `string` | The relative URL for the page (use `{{ url | app }}` to get the absolute URL) +`title` | `string` | Page title +`page` | `RainLab\Pages\Classes\Page` | The page object itself +`viewBag` | `array` | Contains all the extra data used by the page +`is_hidden` | `bool` | Whether the page is hidden (only accessible to backend users) +`navigation_hidden` | `bool` | Whether the page is hidden in automaticaly generated contexts (i.e menu) + +## Example of custom markup for component + +```html +{% for page in childPages.pages %} +
  • {{ page.title }}
  • +{% endfor %} +``` \ No newline at end of file diff --git a/plugins/rainlab/pages/docs/component-staticbreadcrumbs.md b/plugins/rainlab/pages/docs/component-staticbreadcrumbs.md new file mode 100644 index 0000000..27db415 --- /dev/null +++ b/plugins/rainlab/pages/docs/component-staticbreadcrumbs.md @@ -0,0 +1,44 @@ +# Component: Static Menu (staticMenu) + +## Purpose +Outputs a breadcrumb navigation for the current static page + +## Page variables + +Variable | Type | Description +-------- | ---- | ----------- +`breadcrumbs` | `array` | Array of `RainLab\Pages\Classes\MenuItemReference` objects representing the defined menu + +## Default output + +The default component partial outputs a simple unordered list for breadcrumbs: + +```twig +{% if breadcrumbs %} + +{% endif %} +``` + +You might want to render the breadcrumbs with your own code. The `breadcrumbs` variable is an array of the `RainLab\Pages\Classes\MenuItemReference` objects. Each object has the following properties: + +Property | Type | Description +-------- | ---- | ----------- +`title` | `string` | Menu item title +`url` | `string` | Absolute menu item URL +`isActive` | `bool` | Indicates whether the item corresponds to a page currently being viewed +`isChildActive` | `bool` | Indicates whether the item contains an active subitem. +`items` | `array` | The menu item subitems, if any. If there are no subitems, the array is empty + +## Example of custom markup for component + +```html +{% for item in staticBreadCrumbs.breadcrumbs %} +
  • {{ item.title }}
  • +{% endfor %} +``` \ No newline at end of file diff --git a/plugins/rainlab/pages/docs/component-staticmenu.md b/plugins/rainlab/pages/docs/component-staticmenu.md new file mode 100644 index 0000000..d7d2360 --- /dev/null +++ b/plugins/rainlab/pages/docs/component-staticmenu.md @@ -0,0 +1,65 @@ +# Component: Static Menu (staticMenu) + +## Purpose +Outputs a single menu + +## Available properties: + +Property | Inspector Name | Description +-------- | -------------- | ----------- +`code` | Menu | The code (identifier) for the menu that should be displayed by the component + +## Page variables + +Variable | Type | Description +-------- | ---- | ----------- +`menuItems` | `array` | Array of `RainLab\Pages\Classes\MenuItemReference` objects representing the defined menu + +## Default output + +The default component partial outputs a simple nested unordered list for menus: + +```html + +``` + +You might want to render the menus with your own code. The `menuItems` variable is an array of the `RainLab\Pages\Classes\MenuItemReference` objects. Each object has the following properties: + +Property | Type | Description +-------- | ---- | ----------- +`title` | `string` | Menu item title +`url` | `string` | Absolute menu item URL +`isActive` | `bool` | Indicates whether the item corresponds to a page currently being viewed +`isChildActive` | `bool` | Indicates whether the item contains an active subitem. +`items` | `array` | The menu item subitems, if any. If there are no subitems, the array is empty + +## Example of custom markup for component + +```html +{% for item in staticMenu.menuItems %} +
  • {{ item.title }}
  • +{% endfor %} +``` + +## Setting the active menu item explicitly + +In some cases you might want to mark a specific menu item as active explicitly. You can do that in the page's [`onInit()`](https://octobercms.com/docs/cms/pages#dynamic-pages) function with assigning the `activeMenuItem` page variable a value matching the menu item code you want to make active. Menu item codes are managed in the Edit Menu Item popup. + +```php +function onInit() +{ + $this['activeMenuItem'] = 'blog'; +} +``` \ No newline at end of file diff --git a/plugins/rainlab/pages/docs/component-staticpage.md b/plugins/rainlab/pages/docs/component-staticpage.md new file mode 100644 index 0000000..5c42831 --- /dev/null +++ b/plugins/rainlab/pages/docs/component-staticpage.md @@ -0,0 +1,39 @@ +# Component: Static Page (staticPage) + +## Purpose +Enables Static Pages to use the layout that includes this component. + +## Available properties + +Property | Inspector Name | Description +-------- | -------------- | ----------- +`useContent` | Use page content field | If false, the content section will not appear when editing the static page. Page content will be determined solely through placeholders and variables. +`default` | Default layout | If true, defines this layout (the layout this component is included on) as the default for new pages +`childLayout` | Subpage layout | The layout to use as the default for any new subpages created from pages that use this layout + +## Page variables + +Variable | Type | Description +-------- | ---- | ----------- +`page` | `RainLab\Pages\Classes\Page` | Reference to the current static page object +`title` | `string` | The title of the current static page +`extraData` | `array` | Any extra data defined in the page object (i.e. placeholders & variables defined in the layout) + +## Default output + +The default component partial outputs the rendered contents of the current Static Page. However, it's recommended to just use `{% page %}` to render the contents of the page instead to match up with how CMS pages are rendered. + +## Default page layout + +If adding a new subpage, the parent page's layout is checked for a `childLayout` property, and the new subpage's layout will default to that property value. Otherwise, the theme layouts will be searched for the `default` component property and that layout will be selected by default. + +Example: +``` +# /themes/mytheme/layouts/layout1.htm +[staticPage] +default = true +childLayout = "child" + +# /themes/mytheme/layouts/child.htm +[staticPage] +``` \ No newline at end of file diff --git a/plugins/rainlab/pages/docs/documentation.md b/plugins/rainlab/pages/docs/documentation.md new file mode 100644 index 0000000..c6f83d3 --- /dev/null +++ b/plugins/rainlab/pages/docs/documentation.md @@ -0,0 +1,479 @@ +The plugin currently includes three components: Static Page, Static Menu and Static Breadcrumbs. + +### Integrating the Static Pages plugin + +In the simplest case you could create a [layout](https://octobercms.com/docs/cms/layouts) in the CMS area and include the plugin's components to its body. The next example layout outputs a menu, breadcrumbs and a static page: + + + + {{ this.page.title }} + + + {% component 'staticMenu' %} + {% component 'staticBreadcrumbs' %} + {% page %} + + + +![image](https://raw.githubusercontent.com/rainlab/pages-plugin/master/docs/images/static-layout.png) {.img-responsive .frame} + +##### Static pages + +Include the Static Page [component](http://octobercms.com/docs/cms/components) to the layout. The Static Page component has two public properties: + +* `title` - specifies the static page title. +* `content` - the static page content. + +##### Static menus + +Add the staticMenu component to the static page layout to output a menu. The static menu component has the `code` property that should refer a code of a static menu the component should display. In the Inspector the `code` field is displayed as Menu. + +The static menu component injects the `menuItems` page variable. The default component partial outputs a simple nested unordered list for menus: + + + +You might want to render the menus with your own code. The `menuItems` variable is an array of the `RainLab\Pages\Classes\MenuItemReference` objects. Each object has the following properties: + +* `title` - specifies the menu item title. +* `url` - specifies the absolute menu item URL. +* `isActive` - indicates whether the item corresponds to a page currently being viewed. +* `isChildActive` - indicates whether the item contains an active subitem. +* `items` - an array of the menu item subitems, if any. If there are no subitems, the array is empty + +The static menu component also has the `menuItems` property that you can access in the Twig code using the component's alias, for example: + + {% for item in staticMenu.menuItems %} +
  • {{ item.title }}
  • + {% endfor %} + +##### Breadcrumbs + +The staticBreadcrumbs component outputs breadcrumbs for static pages. This component doesn't have any properties. The default component partial outputs a simple unordered list for the breadcrumbs: + + + +The component injects the `breadcrumbs` page variable that contains an array of the `MenuItemReference` objects described above. + +##### Setting the active menu item explicitly + +In some cases you might want to mark a specific menu item as active explicitly. You can do that in the page's [`onInit()`](http://octobercms.com/docs/cms/pages#dynamic-pages) function with assigning the `activeMenuItem` page variable a value matching the menu item code you want to make active. Menu item codes are managed in the Edit Menu Item popup. + +```php +function onInit() +{ + $this['activeMenuItem'] = 'blog'; +} +``` + +##### Linking to static pages + +When a static page is first created it will be assigned a file name based on the URL. For example, a page with the URL **/chairs** will create a content file called **static-pages/chairs.htm** in the theme. This file will not change even if the URL is changed at a later time. + +To create a link to a static page, use the `|staticPage` filter: + +```twig +Go to Chairs +``` + +This filter translates to PHP code as: + +```php +echo RainLab\Pages\Classes\Page::url('chairs'); +``` + +If you want to link to the static page by its URL, simply use the `|app` filter: + +```twig +Go to Chairs +``` + +Linking to the current page, if the component name is called `staticPage`: + +```twig +​{{ staticPage.page.baseFileName|staticPage }} +``` + +##### Manually displaying a static menu + +When a static menu is first created it will be assigned a file name based on the menu name (menu code can also be manually defined). For example, a menu with the name **Primary Nav** will create a meta file called **menus/primary-nav.yaml** in the theme. This file will not change even if the menu name is changed at a later time. + +To render a static menu based on a menu code from the `staticmenupicker` dropdown form widget: + +You can either define the code property on the staticMenu component. + +```twig +{% component 'staticMenu' code=this.theme.primary_menu %} +``` + +Or, use the resetMenu method on the staticMenu component, so we can manually control the menu output without having to create a staticMenu partial override. + +```twig +{% set menuItems = staticMenu.resetMenu(this.theme.primary_menu) %} + + +``` + +##### Backend forms + +If you need to select from a list of static pages in your own backend forms, you can use the `staticpagepicker` widget: + + fields: + field_name: + label: Static Page + type: staticpagepicker + +The field's assigned value will be the static page's file name, which can be used to link to the page as described above. + +If you need to select from a list of static menus in your own backend forms, you can use the `staticmenupicker` widget: + + fields: + field_name: + label: Static Menu + type: staticmenupicker + +The field's assigned value will be the static menu's code, which can be used to link to the menu as described above. + +### Placeholders + +[Placeholders](https://octobercms.com/docs/cms/layouts#placeholders) defined in the layout are automatically detected by the Static Pages plugin. The Edit Static Page form displays a tab for each placeholder defined in the layout used by the page. Placeholders are defined in the layout in the usual way: + + {% placeholder ordering %} + +The `placeholder` tag accepts some optional attributes: + +- `title`: manages the tab title in the Static Page editor. +- `type`: manages the placeholder type. The following values are supported - **text**, **html** and **hidden**. + +The content of text placeholders is escaped before it's displayed. Text placeholders are edited with a regular (non-WYSIWYG) text editor. The title and type attributes should be defined after the placeholder code: + + {% placeholder ordering title="Ordering information" type="text" %} + +They should also appear after the `default` attribute, if it's presented. + + {% placeholder ordering default title="Ordering information" type="text" %} + There is no ordering information for this product. + {% endplaceholder %} + +To prevent a placeholder from appearing in the editor set the `type` attribute to **hidden**. + + {% placeholder systemInfo type="hidden" %} + +### Creating new menu item types + +Plugins can extend the Static Pages plugin with new menu item types. Please refer to the [Blog plugin](https://octobercms.com/plugin/rainlab-blog) for the integration example. New item types are registered with the API events triggered by the Static Pages plugin. The event handlers should be defined in the `boot()` method of the [plugin registration file](https://octobercms.com/docs/plugin/registration#registration-file). There are three events that should be handled in the plugin. + +* `pages.menuitem.listType` event handler should return a list of new menu item types supported by the plugin. +* `pages.menuitem.getTypeInfo` event handler returns detailed information about a menu item type. +* `pages.menuitem.resolveItem` event handler "resolves" a menu item information and returns the actual item URL, title, an indicator whether the item is currently active, and subitems, if any. + +The next example shows an event handler registration code for the Blog plugin. The Blog plugin registers two item types. As you can see, the Blog plugin uses the Category class to handle the events. That's a recommended approach. + + public function boot() + { + Event::listen('pages.menuitem.listTypes', function() { + return [ + 'blog-category'=>'Blog category', + 'all-blog-categories'=>'All blog categories', + ]; + }); + + Event::listen('pages.menuitem.getTypeInfo', function($type) { + if ($type == 'blog-category' || $type == 'all-blog-categories') { + return Category::getMenuTypeInfo($type); + } + }); + + Event::listen('pages.menuitem.resolveItem', function($type, $item, $url, $theme) { + if ($type == 'blog-category' || $type == 'all-blog-categories') { + return Category::resolveMenuItem($item, $url, $theme); + } + }); + } + +##### Registering new menu item types + +New menu item types are registered with the `pages.menuitem.listTypes` event handlers. The handler should return an associative array with the type codes in indexes and type names in values. It's highly recommended to use the plugin name in the type codes, to avoid conflicts with other menu item type providers. Example: + + [ + `my-plugin-item-type` => 'My plugin menu item type' + ] + +##### Returning information about an item type + +Plugins should provide detailed information about the supported menu item types with the `pages.menuitem.getTypeInfo` event handlers. The handler gets a single parameter - the menu item type code (one of the codes you registered with the `pages.menuitem.listTypes` handler). The handler code must check whether the requested item type code belongs to the plugin. The handler should return an associative array in the following format: + + Array ( + [dynamicItems] => 0, + [nesting] => 0, + [references] => Array ( + [11] => News, + [12] => Tutorials, + [33] => Philosophy + ) + [cmsPages] => Array ( + [0] => Cms\Classes\Page object, + [1] => Cms\Classes\Page object + ) + ) + +All elements of the array are optional and depend on the menu item type. The default values for `dynamicItems` and `nesting` are `false` and these keys can be omitted. + +###### dynamicItems element + +The `dynamicItems` element is a Boolean value indicating whether the item type could generate new menu items. Optional, false if omitted. Examples of menu item types that generate new menu items: **All blog categories**, **Static page**. Examples of item types that don't generate new menu items: **URL**, **Blog category**. + +###### nesting element + +The `nesting` element is a Boolean value indicating whether the item type supports nested items. Optional, `false` if omitted. Examples of item types that support nesting: **Static page**, **All static pages**. Examples of item types that don't support nesting: **Blog category**, **URL**. + +###### references element + +The `references` element is a list objects the menu item could refer to. For example, the **Blog category** menu item type returns a list of the blog categories. Some object supports nesting, for example static pages. Other objects don't support nesting, for example the blog categories. The format of the `references` value depends on whether the references have subitems or not. The format for references that don't support subitems is + + ['item-key' => 'Item title'] + +The format for references with subitems is + + ['item-key' => ['title'=>'Item title', 'items'=>[...]]] + +The reference keys should reflect the object identifier they represent. For blog categories keys match the category identifiers. A plugin should be able to load an object by its key in the `pages.menuitem.resolveItem` event handler. The references element is optional, it is required only if a menu item type supports the Reference drop-down, or, in other words, if the user should be able to select an object the menu item refers to. + +###### cmsPages element + +The `cmsPages` is a list of CMS pages that can display objects supported by the menu item type. For example, for the **Blog category** item type the page list contains pages that host the `blogPosts` component. That component can display a blog category contents. The `cmsPages` element should be an array of the `Cms\Classes\Page` objects. The next code snippet shows how to return a list of pages hosting a specific component. + + use Cms\Classes\Page as CmsPage; + use Cms\Classes\Theme; + + ... + + $result = []; + ... + $theme = Theme::getActiveTheme(); + $pages = CmsPage::listInTheme($theme, true); + + $cmsPages = []; + foreach ($pages as $page) { + if (!$page->hasComponent('blogPosts')) { + continue; + } + + $cmsPages[] = $page; + } + + $result['cmsPages'] = $cmsPages; + ... + return $result; + +##### Resolving menu items + +When the Static Pages plugin generates a menu on the front-end, every menu item should **resolved** by the plugin that supplies the menu item type. The process of resolving involves generating the real item URL, determining whether the menu item is active, and generating the subitems (if required). Plugins should register the `pages.menuitem.resolveItem` event handler in order to resolve menu items. The event handler takes four arguments: + +* `$type` - the item type name. Plugins must only handle item types they provide and ignore other types. +* `$item` - the menu item object (RainLab\Pages\Classes\MenuItem). The menu item object represents the menu item configuration provided by the user. The object has the following properties: `title`, `type`, `reference`, `cmsPage`, `nesting`. +* `$url` - specifies the current absolute URL, in lower case. Always use the `Url::to()` helper to generate menu item links and compare them with the current URL. +* `$theme` - the current theme object (`Cms\Classes\Theme`). + +The event handler should return an array. The array keys depend on whether the menu item contains subitems or not. Expected result format: + + Array ( + [url] => https://example.com/blog/category/another-category + [isActive] => 1, + [items] => Array ( + [0] => Array ( + [title] => Another category + [url] => https://example.com/blog/category/another-category + [isActive] => 1 + ) + + [1] => Array ( + [title] => News + [url] => https://example.com/blog/category/news + [isActive] => 0 + ) + ) + ) + +The `url` and `isActive` elements are required for menu items that point to a specific page, but it's not always the case. For example, the **All blog categories** menu item type doesn't have a specific page to point to. It generates multiple menu items. In this case the items should be listed in the `items` element. The `items` element should only be provided if the menu item's `nesting` property is `true`. + +As the resolving process occurs every time when the front-end page is rendered, it's a good idea to cache all the information required for resolving menu items, if that's possible. + +If your item type requires a CMS page to resolve item URLs, you might need to return the selected page's URL, and sometimes pass parameters to the page through the URL. The next code example shows how to load a blog category CMS page referred by a menu item and how to generate an URL to this page. The blog category page has the `blogPosts` component that can load the requested category slug from the URL. We assume that the URL parameter is called 'slug', although it can be edited manually. We skip the part that loads the real parameter name for the simplicity. Please refer to the [Blog plugin](https://octobercms.com/plugin/rainlab-blog) for the reference. + + use Cms\Classes\Page as CmsPage; + use October\Rain\Router\Helper as RouterHelper; + use Str; + use Url; + + ... + + $page = CmsPage::loadCached($theme, $item->cmsPage); + + // Always check if the page can be resolved + if (!$page) { + return; + } + + // Generate the URL + $url = CmsPage::url($page->getBaseFileName(), ['slug' => $category->slug]); + + $url = Url::to(Str::lower(RouterHelper::normalizeUrl($url))); + +To determine whether an item is active just compare it with the `$url` argument of the event handler. + +#### Overriding generated references + +In order to override generated references you can listen to `pages.menu.referencesGenerated` event that fires right before injecting to page object. For example you can filter the unwanted menu entries. + +#### Snippets + +Snippets are elements that can be added by non-technical user to a Static Page, in the rich text editor. They allow to inject complex (and interactive) areas to pages. There are many possible applications and examples of using Snippets: + +* Google Maps snippet - outputs a map centered on specific coordinates with predefined zoom factor. That snippet would be great for static pages that explain directions. +* Universal commenting system - allows visitors to post comments to any static page. +* Third-party integrations - for example with Yelp or TripAdvisor for displaying extra information on a static page. + +Snippets are displayed in the sidebar list on the Static Pages and can be added into a rich editor with a mouse click. Snippets are configurable and have properties that users can manage with the Inspector. + +Snippets can be created from partials or programmatically in plugins. Conceptually snippets are similar to CMS components (and technically, components can act as snippets). + +###### Snippets created from partials + +Partial-based snippets provide simpler functionality and usually are just containers for HTML markup (or markup generated with Twig in a snippet). + +To create snippet from a partial just enter the snippet code and snippet name in the partial form. + +![image](https://raw.githubusercontent.com/rainlab/pages-plugin/master/docs/images/snippets-partial.png) + +The snippet properties are optional and can be defined with the grid control on the partial settings form. The table has the following columns: + +* Property title - specifies the property title. The property title will be visible to the end user in the snippet inspector popup window. +* Property code - specifies the property code. The property code is used for accessing the property values in the partial markup. See the example below. The property code should start with a Latin letter and can contain Latin letters and digits. +* Type - the property type. Available types are String, Dropdown and Checkbox. +* Default - the default property value. For Checkbox properties use 0 and 1 values. +* Options - the option list for the drop-down properties. The option list should have the following format: `key:Value | key2:Value`. The keys represent the internal option value, and values represent the string that users see in the drop-down list. The pipe character separates individual options. Example: `us:US | ca:Canada`. The key is optional, if it's omitted (`US | Canada`), the internal option value will be zero-based integer (0, 1, ...). It's recommended to always use explicit option keys. The keys can contain only Latin letters, digits and characters - and _. + +Any property defined in the property list can be accessed within the partial markdown as a usual variable, for example: + + The country name is {{ country }} + +In addition, properties can be passed to the partial components using an [external property value](http://octobercms.com/docs/cms/components#external-property-values). + +###### Snippets created from components + +Any component can be registered as a snippet and be used in Static Pages. To register a snippet, add the `registerPageSnippets()` method to your plugin class in the [registration file](https://octobercms.com/docs/plugin/registration#registration-file). The API for registering a snippet is similar to the one for [registering components](https://octobercms.com/docs/plugin/registration#component-registration) - the method should return an array with class names in keys and aliases in values: + + public function registerPageSnippets() + { + return [ + '\RainLab\Weather\Components\Weather' => 'weather' + ]; + } + +A same component can be registered with registerPageSnippets() and registerComponents() and used in CMS pages and Static Pages. + +###### Extending the list of snippets + +If you want to dynamically extend the list of the snippets you can bind to the `pages.snippets.listSnippets` event. + +An example usage to add a snippet to the list: + + Event::listen('pages.snippets.listSnippets', function($manager) { + $snippet = new \RainLab\Pages\Classes\Snippet(); + $snippet->initFromComponentInfo('\Example\Plugin\Components\ComponentClass', 'snippetCode'); + $manager->addSnippet($snippet); + }); + +An example usage to remove a snippet from the list: + + Event::listen('pages.snippets.listSnippets', function($manager) { + $manager->removeSnippet('snippetCode'); + }); + +##### Custom page fields + +There is a special syntax you can use inside your layout to add custom fields to the page editor form, called *Syntax Fields*. For example, if you add the following markup to a Layout that uses Static Pages: + + {variable name="tagline" label="Tagline" tab="Header" type="text"}{/variable} + {variable name="banner" label="Banner" tab="Header" type="mediafinder" mode="image"}{/variable} + {variable name="color" label="Color" tab="Header" type="dropdown" + options="blue:Blue | orange:Orange | red:Red" + }{/variable} + +These act just like regular form field definitions. Accessing the variables inside the markup is just as easy: + +

    {{ tagline }}

    + + +All custom fields are placed in the Secondary tabs container (next to Content field). If you need to place them in the Primary tabs container, use *placement="primary"* attribute. + + {variable name="tagline" label="Tagline" tab="Header" type="text" placement="primary"}{/variable} + +Alternatively you may use the field type as the tag name, here we use the `{text}` tag to directly render the `tagline` variable: + +

    {text name="tagline" label="Tagline"}Our wonderful website{/text}

    + +You may also use the `{repeater}` tag for repeating content: + + {repeater name="content_sections" prompt="Add another content section"} +

    + {text name="content_header" label="Content section" placeholder="Type in a heading and enter some content for it below"}{/text} +

    +
    + {richeditor name="content_body" size="large"}{/richeditor} +
    + {/repeater} + +For more details on syntax fields, see the [Parser section](https://octobercms.com/docs/services/parser#dynamic-syntax-parser) of the October documentation. + +##### Custom menu item form fields + +Just like CMS objects have the view bag component to store arbitrary values, you may use the `viewBag` property of the `MenuItem` class to store custom data values and add corresponding form fields. + + Event::listen('backend.form.extendFields', function ($widget) { + if ( + !$widget->getController() instanceof \RainLab\Pages\Controllers\Index || + !$widget->model instanceof \RainLab\Pages\Classes\MenuItem + ) { + return; + } + + $widget->addTabFields([ + 'viewBag[featured]' => [ + 'tab' => 'Display', + 'label' => 'Featured', + 'comment' => 'Mark this menu item as featured', + 'type' => 'checkbox' + ] + ]); + }); + +This value can then be accessed in Twig using the `{{ item.viewBag }}` property on the menu item. For example: + + {% for item in items %} +
  • + + {{ item.title }} + +
  • + {% endfor %} + diff --git a/plugins/rainlab/pages/docs/images/menu-item.png b/plugins/rainlab/pages/docs/images/menu-item.png new file mode 100644 index 0000000..fc207e2 Binary files /dev/null and b/plugins/rainlab/pages/docs/images/menu-item.png differ diff --git a/plugins/rainlab/pages/docs/images/menu-management.png b/plugins/rainlab/pages/docs/images/menu-management.png new file mode 100644 index 0000000..76e8a8b Binary files /dev/null and b/plugins/rainlab/pages/docs/images/menu-management.png differ diff --git a/plugins/rainlab/pages/docs/images/snippets-backend.png b/plugins/rainlab/pages/docs/images/snippets-backend.png new file mode 100644 index 0000000..2e415fc Binary files /dev/null and b/plugins/rainlab/pages/docs/images/snippets-backend.png differ diff --git a/plugins/rainlab/pages/docs/images/snippets-frontend.png b/plugins/rainlab/pages/docs/images/snippets-frontend.png new file mode 100644 index 0000000..4e27130 Binary files /dev/null and b/plugins/rainlab/pages/docs/images/snippets-frontend.png differ diff --git a/plugins/rainlab/pages/docs/images/snippets-partial.png b/plugins/rainlab/pages/docs/images/snippets-partial.png new file mode 100644 index 0000000..999353a Binary files /dev/null and b/plugins/rainlab/pages/docs/images/snippets-partial.png differ diff --git a/plugins/rainlab/pages/docs/images/static-layout.png b/plugins/rainlab/pages/docs/images/static-layout.png new file mode 100644 index 0000000..dde2baa Binary files /dev/null and b/plugins/rainlab/pages/docs/images/static-layout.png differ diff --git a/plugins/rainlab/pages/docs/images/static-page.png b/plugins/rainlab/pages/docs/images/static-page.png new file mode 100644 index 0000000..782a352 Binary files /dev/null and b/plugins/rainlab/pages/docs/images/static-page.png differ diff --git a/plugins/rainlab/pages/formwidgets/Components.php b/plugins/rainlab/pages/formwidgets/Components.php new file mode 100644 index 0000000..5f6421d --- /dev/null +++ b/plugins/rainlab/pages/formwidgets/Components.php @@ -0,0 +1,92 @@ +listComponents(); + + return $this->makePartial('formcomponents', ['components' => $components]); + } + + /** + * listComponents + */ + protected function listComponents() + { + $result = []; + + if (!isset($this->model->settings['components'])) { + return $result; + } + + $manager = ComponentManager::instance(); + $manager->listComponents(); + + foreach ($this->model->settings['components'] as $name => $properties) { + list($name, $alias) = strpos($name, ' ') ? explode(' ', $name) : [$name, $name]; + + try { + $componentObj = $manager->makeComponent($name, null, $properties); + $componentObj->alias = $alias; + $componentObj->pluginIcon = $manager->findComponentOwnerDetails($componentObj)['icon'] ?? 'icon-puzzle-piece'; + } + catch (Exception $ex) { + $componentObj = new UnknownComponent(null, $properties, $ex->getMessage()); + $componentObj->alias = $alias; + $componentObj->pluginIcon = 'icon-bug'; + } + + $result[] = $componentObj; + } + + return $result; + } + + /** + * getComponentName + */ + protected function getComponentName($component) + { + return ComponentHelpers::getComponentName($component); + } + + /** + * getComponentDescription + */ + protected function getComponentDescription($component) + { + return ComponentHelpers::getComponentDescription($component); + } + + /** + * getComponentsPropertyConfig + */ + protected function getComponentsPropertyConfig($component) + { + return ComponentHelpers::getComponentsPropertyConfig($component); + } + + /** + * getComponentPropertyValues + */ + protected function getComponentPropertyValues($component) + { + return ComponentHelpers::getComponentPropertyValues($component); + } +} diff --git a/plugins/rainlab/pages/formwidgets/MenuItemSearch.php b/plugins/rainlab/pages/formwidgets/MenuItemSearch.php new file mode 100644 index 0000000..d1bf49d --- /dev/null +++ b/plugins/rainlab/pages/formwidgets/MenuItemSearch.php @@ -0,0 +1,105 @@ +makePartial('body'); + } + + /* + * Event handlers + */ + public function onSearch() + { + $this->setSearchTerm(Input::get('term')); + + return $this->getData(); + } + + /* + * Methods for internal use + */ + protected function getData() + { + return [ + 'results' => $this->getMatches() + ]; + } + + protected function getMatches() + { + $searchTerm = Str::lower($this->getSearchTerm()); + if (!strlen($searchTerm)) { + return []; + } + + $words = explode(' ', $searchTerm); + + $iterator = function ($type, $references) use (&$iterator, $words) { + $typeMatches = []; + + foreach ($references as $key => $referenceInfo) { + $title = (is_array($referenceInfo)) + ? $referenceInfo['title'] + : $referenceInfo; + + if ($this->textMatchesSearch($words, $title)) { + $typeMatches[] = [ + 'id' => "$type::$key", + 'text' => $title + ]; + } + + if (isset($referenceInfo['items']) && count($referenceInfo['items'])) { + $typeMatches = array_merge($typeMatches, $iterator($type, $referenceInfo['items'])); + } + } + + return $typeMatches; + }; + + $types = []; + $item = new MenuItem(); + foreach ($item->getTypeOptions() as $type => $typeTitle) { + $typeInfo = MenuItem::getTypeInfo($type); + if (empty($typeInfo['references'])) { + continue; + } + + $typeMatches = $iterator($type, $typeInfo['references']); + + if (!empty($typeMatches)) { + $types[] = [ + 'text' => trans($typeTitle), + 'children' => $typeMatches + ]; + } + } + + return $types; + } +} diff --git a/plugins/rainlab/pages/formwidgets/MenuItems.php b/plugins/rainlab/pages/formwidgets/MenuItems.php new file mode 100644 index 0000000..58958cb --- /dev/null +++ b/plugins/rainlab/pages/formwidgets/MenuItems.php @@ -0,0 +1,187 @@ +prepareVars(); + + return $this->makePartial('menuitems'); + } + + /** + * Prepares the list data + */ + public function prepareVars() + { + $menuItem = new MenuItem; + + $this->vars['itemProperties'] = json_encode($menuItem->fillable); + $this->vars['items'] = $this->model->items; + + $emptyItem = new MenuItem; + $emptyItem->title = trans($this->newItemTitle); + $emptyItem->type = 'url'; + $emptyItem->url = '/'; + + $this->vars['emptyItem'] = $emptyItem; + + $widgetConfig = $this->makeConfig('~/plugins/rainlab/pages/classes/menuitem/fields.yaml'); + $widgetConfig->model = $menuItem; + $widgetConfig->alias = $this->alias.'MenuItem'; + + $this->vars['itemFormWidget'] = $this->makeWidget('Backend\Widgets\Form', $widgetConfig); + } + + /** + * {@inheritDoc} + */ + protected function loadAssets() + { + $this->addJs('js/menu-items-editor.js', 'RainLab.Pages'); + } + + /** + * {@inheritDoc} + */ + public function getSaveValue($value) + { + return strlen($value) ? $value : null; + } + + // + // Methods for the internal use + // + + /** + * Returns the item reference description. + * @param \RainLab\Pages\Classes\MenuItem $item Specifies the menu item + * @return string + */ + protected function getReferenceDescription($item) + { + if ($this->typeListCache === false) { + $this->typeListCache = $item->getTypeOptions(); + } + + if (!isset($this->typeInfoCache[$item->type])) { + $this->typeInfoCache[$item->type] = MenuItem::getTypeInfo($item->type); + } + + if (isset($this->typeInfoCache[$item->type])) { + $result = trans($this->typeListCache[$item->type]); + + if ($item->type !== 'url') { + if (isset($this->typeInfoCache[$item->type]['references'])) { + $result .= ': '.$this->findReferenceName($item->reference, $this->typeInfoCache[$item->type]['references']); + } + } + else { + $result .= ': '.$item->url; + } + + } + else { + $result = trans('rainlab.pages::lang.menuitem.unknown_type'); + } + + return $result; + } + + protected function findReferenceName($search, $typeOptionList) + { + $iterator = function($optionList, $path) use ($search, &$iterator) { + foreach ($optionList as $reference => $info) { + if ($reference == $search) { + $result = $this->getMenuItemTitle($info); + + return strlen($path) ? $path.' / ' .$result : $result; + } + + if (is_array($info) && isset($info['items'])) { + $result = $iterator($info['items'], $path.' / '.$this->getMenuItemTitle($info)); + + if (strlen($result)) { + return strlen($path) ? $path.' / '.$result : $result; + } + } + } + }; + + $result = $iterator($typeOptionList, null); + if (!strlen($result)) { + $result = trans('rainlab.pages::lang.menuitem.unnamed'); + } + + $result = preg_replace('|^\s+\/|', '', $result); + + return $result; + } + + protected function getMenuItemTitle($itemInfo) + { + if (is_array($itemInfo)) { + if (!array_key_exists('title', $itemInfo) || !strlen($itemInfo['title'])) { + return trans('rainlab.pages::lang.menuitem.unnamed'); + } + + return $itemInfo['title']; + } + + return strlen($itemInfo) ? $itemInfo : trans('rainlab.pages::lang.menuitem.unnamed'); + } + + public function makeEditorTemplate() + { + $regEx = '##is'; + $partial = $this->makePartial('editorTemplate'); + + preg_match_all($regEx, $partial, $matches); + + $scripts = implode('', $matches[0]); + $template = preg_replace($regEx, '', $partial); + + return [$template, $scripts]; + } +} diff --git a/plugins/rainlab/pages/formwidgets/MenuPicker.php b/plugins/rainlab/pages/formwidgets/MenuPicker.php new file mode 100644 index 0000000..5ba38f4 --- /dev/null +++ b/plugins/rainlab/pages/formwidgets/MenuPicker.php @@ -0,0 +1,49 @@ +prepareVars(); + + return $this->makePartial('~/modules/backend/widgets/form/partials/_field_dropdown.htm'); + } + + /** + * Prepares the view data + */ + public function prepareVars() + { + $this->vars['field'] = $this->makeFormField(); + } + + protected function makeFormField(): FormField + { + $field = clone $this->formField; + $field->type = 'dropdown'; + $field->options = $this->getOptions(); + + return $field; + } + + protected function getOptions(): array + { + return Menu::listInTheme(Theme::getEditTheme(), true) + ->mapWithKeys(function ($menu) { + return [ + $menu->code => $menu->name, + ]; + })->toArray(); + } +} diff --git a/plugins/rainlab/pages/formwidgets/PagePicker.php b/plugins/rainlab/pages/formwidgets/PagePicker.php new file mode 100644 index 0000000..c6c5f30 --- /dev/null +++ b/plugins/rainlab/pages/formwidgets/PagePicker.php @@ -0,0 +1,64 @@ +prepareVars(); + return $this->makePartial('~/modules/backend/widgets/form/partials/_field_dropdown.htm'); + } + + /** + * Prepares the view data + */ + public function prepareVars() + { + $this->vars['field'] = $this->makeFormField(); + } + + /** + * @return \Backend\Classes\FormField + */ + protected function makeFormField() + { + $field = clone $this->formField; + $field->type = 'dropdown'; + + $tree = Page::buildMenuTree(Theme::getEditTheme()); + $indent = $field->getConfig('indent', $this->indent); + + // Flatten page tree for dropdown options + $options = []; + $iterator = function($items, $depth=0) use(&$iterator, &$tree, &$options, $indent) { + + foreach ($items as $code) { + $itemData = $tree[$code]; + $options[$code] = str_repeat($indent, $depth) . $itemData['title']; + if (!empty($itemData['items'])) { + $iterator($itemData['items'], $depth+1); + } + } + + return $options; + }; + + $field->options = $iterator($tree['--root-pages--']); + + return $field; + } +} \ No newline at end of file diff --git a/plugins/rainlab/pages/formwidgets/components/partials/_component.htm b/plugins/rainlab/pages/formwidgets/components/partials/_component.htm new file mode 100644 index 0000000..0707d8b --- /dev/null +++ b/plugins/rainlab/pages/formwidgets/components/partials/_component.htm @@ -0,0 +1,17 @@ +
    +
    inspectorEnabled): ?>data-inspectable + data-inspector-title="getComponentName($component)) ?>" + data-inspector-description="getComponentDescription($component)) ?>" + data-inspector-config="getComponentsPropertyConfig($component)) ?>" + data-inspector-class=""> + + + alias) ?> + + + + × +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/pages/formwidgets/components/partials/_formcomponents.htm b/plugins/rainlab/pages/formwidgets/components/partials/_formcomponents.htm new file mode 100644 index 0000000..0f22cbb --- /dev/null +++ b/plugins/rainlab/pages/formwidgets/components/partials/_formcomponents.htm @@ -0,0 +1,17 @@ +
    + + isHidden): ?> + makePartial('component', ['component' => $component]) ?> + + + +
    +
    + + isHidden): ?> + makePartial('component', ['component' => $component]) ?> + + +
    +
    +
    diff --git a/plugins/rainlab/pages/formwidgets/menuitems/assets/js/menu-items-editor.js b/plugins/rainlab/pages/formwidgets/menuitems/assets/js/menu-items-editor.js new file mode 100644 index 0000000..6252ab7 --- /dev/null +++ b/plugins/rainlab/pages/formwidgets/menuitems/assets/js/menu-items-editor.js @@ -0,0 +1,651 @@ +/* + * The menu item editor. Provides tools for managing the + * menu items. + */ ++function ($) { "use strict"; + var MenuItemsEditor = function (el, options) { + this.$el = $(el) + this.options = options + + this.init() + } + + MenuItemsEditor.prototype.init = function() { + var self = this + + this.alias = this.$el.data('alias') + this.$treeView = this.$el.find('div[data-control="treeview"]') + + this.typeInfo = {} + + // Menu items is clicked + this.$el.on('open.oc.treeview', function(e) { + return self.onItemClick(e.relatedTarget) + }) + + // Submenu item is clicked in the master tabs + this.$el.on('submenu.oc.treeview', $.proxy(this.onSubmenuItemClick, this)) + + this.$el.on('click', 'a[data-control="add-item"]', function(e) { + self.onCreateItem(e.target) + return false + }) + } + + /* + * Triggered when a submenu item is clicked in the menu editor. + */ + MenuItemsEditor.prototype.onSubmenuItemClick = function(e) { + if ($(e.relatedTarget).data('control') == 'delete-menu-item') + this.onDeleteMenuItem(e.relatedTarget) + + if ($(e.relatedTarget).data('control') == 'create-item') + this.onCreateItem(e.relatedTarget) + + return false + } + + /* + * Removes a menu item + */ + MenuItemsEditor.prototype.onDeleteMenuItem = function(link) { + if (!confirm('Do you really want to delete the menu item? This will also delete the subitems, if any.')) + return + + $(link).trigger('change') + $(link).closest('li[data-menu-item]').remove() + + $(window).trigger('oc.updateUi') + + this.$treeView.treeView('update') + this.$treeView.treeView('fixSubItems') + } + + /* + * Opens the menu item editor + */ + MenuItemsEditor.prototype.onItemClick = function(item, newItemMode) { + var $item = $(item), + $container = $('> div', $item), + self = this + + $container.one('show.oc.popup', function(e) { + self.triggerRenderEvent(); + + self.$popupContainer = $(e.relatedTarget); + self.$itemDataContainer = $container.closest('li') + + $('input[type=checkbox]', self.$popupContainer).removeAttr('checked') + + self.loadProperties(self.$popupContainer, self.$itemDataContainer.data('menu-item')) + self.$popupForm = self.$popupContainer.find('form') + self.itemSaved = false + + var $titleField = $('input[name=title]', self.$popupContainer).focus().select() + var $typeField = $('select[name=type]', self.$popupContainer).change(function(){ + self.loadTypeInfo(false, true) + }) + + $('select[name=reference]', self.$popupContainer).change(function() { + var selectedTitle = $(this).find('option:selected').text(); + // If the saved title is the default new item title, use reference title, + // removing CMS page [base file name] suffix + if (selectedTitle && self.properties.title === self.$popupForm.attr('data-new-item-title')) { + var title = $.trim(selectedTitle.replace(/\s*\[.*\]$/, '')) + $titleField.val(title) + + // Support for RainLab.Translate + var defaultLocale = $('[data-control="multilingual"]').data('default-locale') + if (defaultLocale) { + $('[name="RLTranslate['+defaultLocale+'][title]"]', self.$popupContainer).val(title) + } + } + }) + + self.$popupContainer.on('keydown', function(e) { + if (e.which == 13) + self.applyMenuItem() + }) + + $('button[data-control="apply-btn"]', self.$popupContainer).click($.proxy(self.applyMenuItem, self)) + + var $updateTypeOptionsBtn = $('') + $('div[data-field-name=reference]').addClass('input-sidebar-control').append($updateTypeOptionsBtn) + + $updateTypeOptionsBtn.click(function(){ + self.loadTypeInfo(true) + + return false + }) + + $updateTypeOptionsBtn.keydown(function(ev){ + if (ev.which == 13 || ev.which == 32) { + self.loadTypeInfo(true) + return false + } + }) + + self.$popupContainer.on('change', 'select[name="referenceSearch"]', function() { + var $select = $(this), + val = $select.val(), + parts + + if (!val) return + + // type::reference ID + parts = val.split('::', 2) + + self.referenceSearchOverride = parts[1]; + + $select.empty().trigger('change.select2'); + + $typeField + .val(parts[0]) + .triggerHandler('change') + }) + + var $updateCmsPagesBtn = $updateTypeOptionsBtn.clone(true) + $('div[data-field-name=cmsPage]').addClass('input-sidebar-control').append($updateCmsPagesBtn) + + self.loadTypeInfo() + }) + + $container.one('hide.oc.popup', function(e) { + if (!self.itemSaved && newItemMode) + $item.remove() + + self.$treeView.treeView('update') + self.$treeView.treeView('fixSubItems') + + $container.removeClass('popover-highlight') + }) + + $container.popup({ + content: $('script[data-editor-template]', this.$el).html() + }) + + /* + * Highlight modal target + */ + $container.addClass('popover-highlight') + $container.blur() + + return false + } + + MenuItemsEditor.prototype.loadProperties = function($popupContainer, properties) { + this.properties = properties + + var setPropertyOnElement = function($input, val) { + if ($input.prop('type') == 'checkbox') { + var checked = !(val == '0' || val == 'false' || val == 0 || val == undefined || val == null) + checked ? $input.prop('checked', 'checked') : $input.removeAttr('checked') + } + else if ($input.prop('type') == 'radio') { + $input.filter('[value="'+val+'"]').prop('checked', true) + } + else { + $input.val(val) + $input.change() + } + } + + var defaultLocale = $('[data-control="multilingual"]', $popupContainer).data('default-locale') + $.each(properties, function(property, val) { + if (property == 'viewBag') { + $.each(val, function(vbProperty, vbVal) { + var $input = $('[name="viewBag['+vbProperty+']"]', $popupContainer).not('[type=hidden]') + setPropertyOnElement($input, vbVal) + // Ensure that locale specific data is made available in the RainLab.Translate data holders + if (vbProperty === 'locale') { + $.each(vbVal, function(locale, fields) { + $.each(fields, function(fieldName, fieldValue) { + var $locker = $('[name="RLTranslate['+locale+']['+fieldName+']"]', $popupContainer) + if ($locker) { + $locker.val(fieldValue) + } + }) + }) + } + }) + + /** + * Mediafinder support + */ + var mediafinderElements = $('[data-control="mediafinder"]', $popupContainer); + var storageMediaPath = $('[data-storage-media-path]').data('storage-media-path'); + + $.each(mediafinderElements, function() { + var input = $(this).find('input'), + propertyName = input.attr('name'), + propertyNameSimple; + + if (propertyName && propertyName.length) { + propertyNameSimple = propertyName.substr(8).slice(0, -1); + } + + var propertyValue = ''; + + $.each(val, function(vbProperty, vbVal) { + if (vbProperty == propertyNameSimple) { + propertyValue = vbVal; + } + }); + + if (propertyValue != '') { + // v2 media finder + var dataLocker = $('[data-data-locker]', this); + if (dataLocker.length) { + var items = [{ + path: propertyValue, + publicUrl: storageMediaPath + propertyValue, + thumbUrl: storageMediaPath + propertyValue, + title: propertyValue.substring(1) + }]; + + var mediafinder = $(this).data('oc.mediaFinder'); + mediafinder.addItems(items); + mediafinder.setValue(); + mediafinder.evalIsPopulated(); + } + // v1 media finder + else { + $(this).toggleClass('is-populated'); + input.attr('value', propertyValue); + + var image = $('[data-find-image]', this); + if (image.length) { + image.attr('src', storageMediaPath + propertyValue); + } + + var file = $('[data-find-file-name]', this); + if (file.length) { + file.text(propertyValue.substring(1)); + } + } + } + }); + + } + else { + var $input = $('[name="'+property+'"]', $popupContainer).not('[type=hidden]') + setPropertyOnElement($input, val) + // If the RainLab.Translate default locale data locker fields are available make sure that they are properly populated + var $defaultLocaleField = $('[name="RLTranslate['+defaultLocale+']['+property+']"]', self.$popupContainer) + if ($defaultLocaleField) { + $defaultLocaleField.val($input.val()); + } + } + }) + } + + MenuItemsEditor.prototype.loadTypeInfo = function(force, focusList) { + var type = $('select[name=type]', this.$popupContainer).val() + + var self = this + + if (!force && this.typeInfo[type] !== undefined) { + self.applyTypeInfo(this.typeInfo[type], type, focusList) + return + } + + $.oc.stripeLoadIndicator.show() + this.$popupForm.request('onGetMenuItemTypeInfo') + .always(function(){ + $.oc.stripeLoadIndicator.hide() + }) + .done(function(data){ + self.typeInfo[type] = data.menuItemTypeInfo + self.applyTypeInfo(data.menuItemTypeInfo, type, focusList) + }) + } + + MenuItemsEditor.prototype.applyTypeInfo = function(typeInfo, type, focusList) { + var $referenceFormGroup = $('div[data-field-name="reference"]', this.$popupContainer), + $optionSelector = $('select', $referenceFormGroup), + $nestingFormGroup = $('div[data-field-name="nesting"]', this.$popupContainer), + $urlFormGroup = $('div[data-field-name="url"]', this.$popupContainer), + $replaceFormGroup = $('div[data-field-name="replace"]', this.$popupContainer), + $cmsPageFormGroup = $('div[data-field-name="cmsPage"]', this.$popupContainer), + $cmsPageSelector = $('select', $cmsPageFormGroup), + prevSelectedReference = $optionSelector.val(), + prevSelectedPage = $cmsPageSelector.val() + + // Search selection + if (this.referenceSearchOverride) { + prevSelectedReference = this.referenceSearchOverride; + this.referenceSearchOverride = null; + } + + if (typeInfo.references) { + $optionSelector.find('option').remove() + $referenceFormGroup.show() + + var iterator = function(options, level, path) { + $.each(options, function(code) { + var $option = $('').attr('value', code), + offset = Array(level*4).join(' '), + isObject = $.type(this) == 'object' + + $option.text(isObject ? this.title : this) + + var optionPath = path.length > 0 + ? (path + ' / ' + $option.text()) + : $option.text() + + $option.data('path', optionPath) + + $option.html(offset + $option.html()) + + $optionSelector.append($option) + + if (isObject) + iterator(this.items, level+1, optionPath) + }) + } + + iterator(typeInfo.references, 0, '') + + $optionSelector + .val(prevSelectedReference ? prevSelectedReference : this.properties.reference) + .triggerHandler('change') + } + else { + $referenceFormGroup.hide() + } + + if (typeInfo.cmsPages) { + $cmsPageSelector.find('option').remove() + $cmsPageFormGroup.show() + + $.each(typeInfo.cmsPages, function(code) { + var $option = $('').attr('value', code) + + $option.text(this).val(code) + $cmsPageSelector.append($option) + }) + + $cmsPageSelector + .val(prevSelectedPage ? prevSelectedPage : this.properties.cmsPage) + .triggerHandler('change') + } + else { + $cmsPageFormGroup.hide() + } + + $nestingFormGroup.toggle(typeInfo.nesting !== undefined && typeInfo.nesting) + $urlFormGroup.toggle(type == 'url') + $replaceFormGroup.toggle(typeInfo.dynamicItems !== undefined && typeInfo.dynamicItems) + + this.triggerRenderEvent(); + + if (focusList) { + var focusElements = [ + $referenceFormGroup, + $cmsPageFormGroup, + $('div.custom-checkbox', $nestingFormGroup), + $('div.custom-checkbox', $replaceFormGroup), + $('input', $urlFormGroup) + ] + + $.each(focusElements, function(){ + if (this.is(':visible')) { + var $self = this + + window.setTimeout(function() { + if ($self.hasClass('dropdown-field')) + $('select', $self).select2('focus', 100) + else $self.focus() + }) + + return false; + } + }) + } + } + + MenuItemsEditor.prototype.applyMenuItem = function() { + var self = this, + data = {}, + propertyNames = this.$el.data('item-properties'), + basicProperties = { + 'title': 1, + 'type': 1, + 'code': 1 + }, + typeInfoPropertyMap = { + reference: 'references', + replace: 'dynamicItems', + cmsPage: 'cmsPages' + }, + typeInfo = {}, + validationErrorFound = false + + // Ensure that locale specific data is made available in the RainLab.Translate data holders + $('[name^="viewBag[locale]"]', self.$popupContainer).each(function() { + var locale = $(this).data('locale') + var fieldName = $(this).data('field-name') + var $localeField = $('[name="RLTranslate['+locale+']['+fieldName+']"]', self.$popupContainer) + $(this).val($localeField.val()) + }); + + var defaultLocale = $('[data-control="multilingual"]').data('default-locale') + + $.each(propertyNames, function() { + var propertyName = this, + $input = $('[name="'+propertyName+'"]', self.$popupContainer).not('[type=hidden]') + + // If the RainLab.Translate default locale data locker fields are available make sure the regular inputs are properly populated + if (defaultLocale) { + var $defaultLocaleField = $('[name="RLTranslate['+defaultLocale+']['+propertyName+']"]', self.$popupContainer) + if ($defaultLocaleField && $defaultLocaleField.val()) { + $input.val($defaultLocaleField.val()) + } + } + + if ($input.prop('type') !== 'checkbox') { + data[propertyName] = $.trim($input.val()) + + if (propertyName == 'type') + typeInfo = self.typeInfo[data.type] + + if (data[propertyName].length == 0) { + var typeInfoProperty = typeInfoPropertyMap[propertyName] !== undefined ? typeInfoPropertyMap[propertyName] : propertyName + + if (typeInfo[typeInfoProperty] !== undefined) { + + $.oc.flashMsg({ + class: 'error', + text: self.$popupForm.attr('data-message-'+propertyName+'-required') + }) + + if ($input.prop("tagName") == 'SELECT') + $input.select2('focus') + else + $input.focus() + + validationErrorFound = true + + return false + } + } + } + else { + data[propertyName] = $input.prop('checked') ? 1 : 0 + } + }) + + if (validationErrorFound) + return + + if (data.type !== 'url') { + delete data['url'] + + $.each(data, function(property) { + if (property == 'type') + return + + var typeInfoProperty = typeInfoPropertyMap[property] !== undefined ? typeInfoPropertyMap[property] : property + if ((typeInfo[typeInfoProperty] === undefined || typeInfo[typeInfoProperty] === false) + && basicProperties[property] === undefined) + delete data[property] + }) + } + else { + $.each(propertyNames, function(){ + if (this != 'url' && basicProperties[this] === undefined) + delete data[this] + }) + } + + if ($.trim(data.title).length == 0) { + $.oc.flashMsg({ + class: 'error', + text: self.$popupForm.data('messageTitleRequired') + }) + + $('[name=title]', self.$popupContainer).focus() + + return + } + + if (data.type == 'url' && $.trim(data.url).length == 0) { + $.oc.flashMsg({ + class: 'error', + text: self.$popupForm.data('messageUrlRequired') + }) + + $('[name=url]', self.$popupContainer).focus() + + return + } + + $('> div span.title', self.$itemDataContainer).text(data.title) + + var referenceDescription = $.trim($('select[name=type] option:selected', self.$popupContainer).text()) + + if (data.type == 'url') { + referenceDescription += ': ' + $('input[name=url]', self.$popupContainer).val() + } + else if (typeInfo.references) { + referenceDescription += ': ' + $.trim($('select[name=reference] option:selected', self.$popupContainer).data('path')) + } + + $('> div span.comment', self.$itemDataContainer).text(referenceDescription) + + this.attachViewBagData(data) + + this.$itemDataContainer.data('menu-item', data) + this.itemSaved = true + this.$popupContainer.trigger('close.oc.popup') + this.$el.trigger('change') + } + + MenuItemsEditor.prototype.attachViewBagData = function(data) { + var fields = this.$popupForm.serializeArray(), + fieldName, + fieldValue + + $.each(fields, function(index, field) { + fieldName = field.name + fieldValue = field.value + + if (fieldName.indexOf('viewBag[') != 0) { + return true // Continue + } + + /* + * Break field name in to elements + */ + var elements = [], + searchResult, + expression = /([^\]\[]+)/g + + while ((searchResult = expression.exec(fieldName))) { + elements.push(searchResult[0]) + } + + /* + * Attach elements to data with value + */ + var currentData = data, + elementsNum = elements.length, + lastIndex = elementsNum - 1, + currentProperty + + for (var i = 0; i < elementsNum; ++i) { + currentProperty = elements[i] + + if (i === lastIndex) { + currentData[currentProperty] = fieldValue + } + else if (currentData[currentProperty] === undefined) { + currentData[currentProperty] = {} + } + + currentData = currentData[currentProperty] + } + }) + } + + MenuItemsEditor.prototype.onCreateItem = function(target) { + var parentList = $(target).closest('li[data-menu-item]').find(' > ol'), + item = $($('script[data-item-template]', this.$el).html()) + + if (!parentList.length) + parentList = $(target).closest('div[data-control=treeview]').find(' > ol') + + parentList.append(item) + this.$treeView.treeView('update') + $(window).trigger('oc.updateUi') + + this.onItemClick(item, true) + } + + MenuItemsEditor.prototype.triggerRenderEvent = function() { + // Vanilla AJAX Framework (v3) + if (window.oc && oc.Events) { + oc.Events.dispatch('render'); + } + // Classic AJAX Framework (v1,2) + else { + $(document).trigger('render'); + } + } + + MenuItemsEditor.DEFAULTS = { + } + + // MENUITEMSEDITOR PLUGIN DEFINITION + // ============================ + + var old = $.fn.menuItemsEditor + + $.fn.menuItemsEditor = function (option) { + var args = Array.prototype.slice.call(arguments, 1) + return this.each(function () { + var $this = $(this) + var data = $this.data('oc.menuitemseditor') + var options = $.extend({}, MenuItemsEditor.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.menuitemseditor', (data = new MenuItemsEditor(this, options))) + else if (typeof option == 'string') data[option].apply(data, args) + }) + } + + $.fn.menuItemsEditor.Constructor = MenuItemsEditor + + // MENUITEMSEDITOR NO CONFLICT + // ================= + + $.fn.menuItemsEditor.noConflict = function () { + $.fn.menuItemsEditor = old + return this + } + + // MENUITEMSEDITOR DATA-API + // =============== + + $(document).on('render', function() { + $('[data-control="menu-item-editor"]').menuItemsEditor() + }); +}(window.jQuery); diff --git a/plugins/rainlab/pages/formwidgets/menuitems/partials/_editortemplate.htm b/plugins/rainlab/pages/formwidgets/menuitems/partials/_editortemplate.htm new file mode 100644 index 0000000..fc49f10 --- /dev/null +++ b/plugins/rainlab/pages/formwidgets/menuitems/partials/_editortemplate.htm @@ -0,0 +1,29 @@ + + + \ No newline at end of file diff --git a/plugins/rainlab/pages/formwidgets/menuitems/partials/_item.htm b/plugins/rainlab/pages/formwidgets/menuitems/partials/_item.htm new file mode 100644 index 0000000..2c320a8 --- /dev/null +++ b/plugins/rainlab/pages/formwidgets/menuitems/partials/_item.htm @@ -0,0 +1,38 @@ + +
  • + + +
      + items): ?> + makePartial('itemlist', ['items' => $subItems]) ?> + +
    +
  • \ No newline at end of file diff --git a/plugins/rainlab/pages/formwidgets/menuitems/partials/_itemlist.htm b/plugins/rainlab/pages/formwidgets/menuitems/partials/_itemlist.htm new file mode 100644 index 0000000..8a061b8 --- /dev/null +++ b/plugins/rainlab/pages/formwidgets/menuitems/partials/_itemlist.htm @@ -0,0 +1,5 @@ + + + makePartial('item', ['item' => $item]) ?> + + \ No newline at end of file diff --git a/plugins/rainlab/pages/formwidgets/menuitems/partials/_items.htm b/plugins/rainlab/pages/formwidgets/menuitems/partials/_items.htm new file mode 100644 index 0000000..8f1d805 --- /dev/null +++ b/plugins/rainlab/pages/formwidgets/menuitems/partials/_items.htm @@ -0,0 +1,11 @@ +
      + makePartial('itemlist', ['items' => $items]) ?> +
    + + + + \ No newline at end of file diff --git a/plugins/rainlab/pages/formwidgets/menuitems/partials/_menuitems.htm b/plugins/rainlab/pages/formwidgets/menuitems/partials/_menuitems.htm new file mode 100644 index 0000000..e9b5c7b --- /dev/null +++ b/plugins/rainlab/pages/formwidgets/menuitems/partials/_menuitems.htm @@ -0,0 +1,36 @@ +makeEditorTemplate(); +?> +
    +
    +
    + makePartial('items', ['items' => $items]) ?> +
    +
    + + + + + + +
    diff --git a/plugins/rainlab/pages/formwidgets/menuitemsearch/partials/_body.htm b/plugins/rainlab/pages/formwidgets/menuitemsearch/partials/_body.htm new file mode 100644 index 0000000..a42399d --- /dev/null +++ b/plugins/rainlab/pages/formwidgets/menuitemsearch/partials/_body.htm @@ -0,0 +1,10 @@ + diff --git a/plugins/rainlab/pages/lang/cs/lang.php b/plugins/rainlab/pages/lang/cs/lang.php new file mode 100644 index 0000000..0123f42 --- /dev/null +++ b/plugins/rainlab/pages/lang/cs/lang.php @@ -0,0 +1,125 @@ + [ + 'name' => 'Stránky', + 'description' => 'Funkce pro správu stránek a menu.', + ], + 'page' => [ + 'menu_label' => 'Stránky', + 'template_title' => '%s Stránky', + 'delete_confirmation' => 'Opravdu chcete odstranit vybrané stránky? Budou odstraněny i případné podstránky.', + 'no_records' => 'Stránky nenalezeny', + 'delete_confirm_single' => 'Opravu chcete odstranit tuto stránku? Budou odstraněny i případné podstránky.', + 'new' => 'Nová stránka', + 'add_subpage' => 'Přidat podstránku', + 'invalid_url' => 'Neplatný formát URL. URL by mělo začínat lomítkem a může obsahovat čísla, písmena a znaky: _-/', + 'url_not_unique' => 'Toto URL je používáno jinou stránkou.', + 'layout' => 'Layouty', + 'layouts_not_found' => 'Layouts nenalezeny', + 'saved' => 'Stránka byla úspěšně uložena.', + 'tab' => 'Stránky', + 'manage_pages' => 'Spravovat stránky', + 'manage_menus' => 'Spravovat menu', + 'access_snippets' => 'Používat snippety', + 'manage_content' => 'Spravovat obsah' + ], + 'menu' => [ + 'menu_label' => 'Menu', + 'delete_confirmation' => 'Opravdu chcete odstranit vybraná menu?', + 'no_records' => 'Položky nenalezeny', + 'new' => 'Nové menu', + 'new_name' => 'Nové menu', + 'new_code' => 'nove-menu', + 'delete_confirm_single' => 'Opravdu chcete odstranit toto menu?', + 'saved' => 'Menu bylo úspěšně uloženo.', + 'name' => 'Název', + 'code' => 'Kód', + 'items' => 'Položky menu', + 'add_subitem' => 'Přidat položku', + 'code_required' => 'Pole kód je povinné.', + 'invalid_code' => 'Pole kód obsahuje neplatné znaky. Může obsahovat pouze číslice, písmena a znaky: _-' + ], + 'menuitem' => [ + 'title' => 'Titulek', + 'editor_title' => 'Upravit položku menu', + 'type' => 'Typ', + 'allow_nested_items' => 'Povolit vnořené položky', + 'allow_nested_items_comment' => 'Vnořené položky mohou být automaticky vygenerovány statickými stránkami nebo jinými typy stránek.', + 'url' => 'URL', + 'reference' => 'Odkaz', + 'search_placeholder' => 'Prohledat odkazy...', + 'title_required' => 'Titulek je povinný', + 'unknown_type' => 'Neznámý typ položky', + 'unnamed' => 'Nepojmenovaný typ položky', + 'add_item' => 'Přidat položku', + 'new_item' => 'Nová položka menu', + 'replace' => 'Nahradit tuto položku jejími vygenerovanými vnořenými položkami', + 'replace_comment' => 'Toto pole zaškrtněte, pokud si přejete vnořené položky posunout na stejnou úroveň jako má tato položka. Samotná položka zůstane skryta.', + 'cms_page' => 'CMS stránka', + 'cms_page_comment' => 'Vyberte stránku, která se otevře při kliknutí na tuto položku v menu.', + 'reference_required' => 'Odkaz je povinný.', + 'url_required' => 'URL je povinné', + 'cms_page_required' => 'Prosím vyberte CMS stránku', + 'display_tab' => 'Zobrazení', + 'hidden' => 'Skrytá', + 'hidden_comment' => 'Skrýt tuto položku menu pro celý front-end.', + 'attributes_tab' => 'Vlastnosti', + 'code' => 'Kód', + 'code_comment' => 'Zadejte kód položky menu pokud k ní chcete přistupovat přes API.', + 'css_class' => 'CSS třída', + 'css_class_comment' => 'Vložte název CSS třídy k zajištění specifického vzhledu této položky menu.', + 'external_link' => 'Externí odkaz', + 'external_link_comment' => 'Otevřít odkaz této položky v novém okně.', + 'static_page' => 'Statická stránka', + 'all_static_pages' => 'Všechny statické stránky' + ], + 'content' => [ + 'menu_label' => 'Obsah', + 'cant_save_to_dir' => 'Ukládat obsah do složky statických stránek není povoleno.' + ], + 'sidebar' => [ + 'add' => 'Přidat', + 'search' => 'Hledat...' + ], + 'object' => [ + 'invalid_type' => 'Neznámý typ objektu', + 'not_found' => 'Požadovaný objekt nebyl nalezen.' + ], + 'editor' => [ + 'title' => 'Titulek', + 'new_title' => 'Nový titulek stránky', + 'content' => 'Obsah', + 'url' => 'URL', + 'filename' => 'Název souboru', + 'layout' => 'Layout', + 'description' => 'Popis', + 'preview' => 'Náhled', + 'enter_fullscreen' => 'Vstoupit do režimu celé obrazovky', + 'exit_fullscreen' => 'Opustit režim celé obrazovky', + 'hidden' => 'Skrytá', + 'hidden_comment' => 'Skryté stránky jsou dostupné pouze přihlášeným administrátorům.', + 'navigation_hidden' => 'Skrýt v menu', + 'navigation_hidden_comment' => 'Zaškrtněte toto pole, pokud chcete stránku skrýt z automaticky vygenerovaných menu a drobečkové navigace.', + ], + 'snippet' => [ + 'partialtab' => 'Snippet', + 'code' => 'Kód snippetu', + 'code_comment' => 'Zadejte kód, aby tato dílčí šablona byla dostupná jako snippet v pluginu statických stránek.', + 'name' => 'Název', + 'name_comment' => 'Tento název bude zobrazen v seznamu snippetů v bočním menu pluginu statických stránek a přímo na stránce, když bude snippet přidán.', + 'no_records' => 'Snippety nenalezeny', + 'menu_label' => 'Snippety', + 'column_property' => 'Název vlastnosti', + 'column_type' => 'Vlastnosti', + 'column_code' => 'Kód', + 'column_default' => 'Výchozí', + 'column_options' => 'Možnosti', + 'column_type_string' => 'Řetězec', + 'column_type_checkbox' => 'Zaškrtávací políčko', + 'column_type_dropdown' => 'Seznam', + 'not_found' => 'Snippet s kódem :code nebyl nalezen v rámci tématu.', + 'property_format_error' => 'Kód vlastnosti by měl začínat písmenem a může obsahovat pouze písmena nebo číslice.', + 'invalid_option_key' => 'Neplatný klíč položky seznamu: %s. Klíč položky seznamu může obsahovat pouze písmena, číslice a znaky: _-' + ] +]; diff --git a/plugins/rainlab/pages/lang/de/lang.php b/plugins/rainlab/pages/lang/de/lang.php new file mode 100644 index 0000000..3a99b35 --- /dev/null +++ b/plugins/rainlab/pages/lang/de/lang.php @@ -0,0 +1,114 @@ + [ + 'name' => 'Seiten', + 'description' => 'Pages & menus features.', + ], + 'page' => [ + 'menu_label' => 'Seiten', + 'template_title' => '%s Seiten', + 'delete_confirmation' => 'Möchten Sie die ausgewählten Seiten wirklich löschen? Dadurch werden auch mögliche Unterseiten gelöscht.', + 'no_records' => 'Keine Seiten gefunden', + 'delete_confirm_single' => 'Möchten Sie die ausgewählte Seite wirklich löschen? Dadurch werden auch mögliche Unterseiten gelöscht.', + 'new' => 'Neue Seite', + 'add_subpage' => 'Neue Unterseite', + 'invalid_url' => 'Ungültiges URL Format. Die URL sollte mit einem Schrägstrich (Slash) starten und darf Ziffern, Buchstaben und folgenden Symbole enthalten: _-/.', + 'url_not_unique' => 'Die URL wird schon von einer anderen Seite benutzt.', + 'layout' => 'Layout', + 'layouts_not_found' => 'Keine Layouts gefunden', + 'saved' => 'Die Seite wurde erfolgreich gespeichert.', + 'manage_pages' => 'Verwalte statische Seiten', + 'manage_menus' => 'Verwalte statische Menüs', + 'access_snippets' => 'Verwalte Snippets', + 'manage_content' => 'Verwalte den Inhalt' + ], + 'menu' => [ + 'menu_label' => 'Menüs', + 'delete_confirmation' => 'Möchten Sie die ausgewählten Menüs wirklich löschen?', + 'no_records' => 'Keine Menüs gefunden', + 'new' => 'Neues Menü', + 'new_name' => 'Menüname', + 'new_code' => 'menuename', + 'delete_confirm_single' => 'Möchten Sie das ausgewählte Menü wirklich löschen?', + 'saved' => 'Das Menü wurde erfolgreich gespeichert.', + 'name' => 'Name', + 'code' => 'Code', + 'items' => 'Menüpunkte', + 'add_subitem' => 'Neuer Menüpunkt', + 'no_records' => 'Keine Menüpunkte gefunden', + 'code_required' => 'Ein Code ist erforderlich', + 'invalid_code' => 'Ungültiges Code Format. Der Code darf Ziffern, Buchstaben und folgenden Symbole enthalten: _-/' + ], + 'menuitem' => [ + 'title' => 'Titel', + 'editor_title' => 'Menüpunkt bearbeiten', + 'type' => 'Typ', + 'allow_nested_items' => 'Erlaube verschachtelte Menüpunkte', + 'allow_nested_items_comment' => 'Verschachtelte Menüpunkte können dynamisch durch statische Seiten und einigen anderen Menüpunkt-Typen erzeugt werden.', + 'url' => 'URL', + 'reference' => 'Referenz', + 'title_required' => 'Ein Titel ist erforderlich', + 'unknown_type' => 'Unbekannter Menüpunkt-Typ', + 'unnamed' => 'Unbekannter Menüpunkt', + 'add_item' => 'Neuer Menüpunkt', + 'new_item' => 'Neuer Menüpunkt', + 'replace' => 'Ersetze diesen Menüpunkt mit seinen Unterpunkten', + 'replace_comment' => 'Verwenden Sie diese Option, um erzeugte Menüpunkte auf die gleiche Ebene von diesem zu bringen. Dieser Menüpunkt selbst wird ausgeblendet.', + 'cms_page' => 'CMS Seite', + 'cms_page_comment' => 'Wählen Sie eine Seite die geöffnet werden soll, wenn dieser Menüpunkt angeklickt wird.', + 'reference_required' => 'Eine Menüpunkt-Referenz ist erforderlich', + 'url_required' => 'Eine URL ist erforderlich', + 'cms_page_required' => 'Bitten wählen Sie eine CMS Seite', + 'code' => 'Code', + 'code_comment' => 'Geben Sie einen Menüpunkt-Code ein, wenn Sie diesen mit der API ansprechen möchten.' + ], + 'content' => [ + 'menu_label' => 'Inhalte', + 'cant_save_to_dir' => 'Das Speichern von Inhaltsdateien in den Statische-Seiten Ordner ist nicht erlaubt.' + ], + 'sidebar' => [ + 'add' => 'Neu', + 'search' => 'Suche...' + ], + 'object' => [ + 'invalid_type' => 'Unbekannter Objekttyp', + 'not_found' => 'Das angeforderte Objekt wurde nicht gefunden.' + ], + 'editor' => [ + 'title' => 'Titel', + 'new_title' => 'Titel für die neue Seite', + 'content' => 'Inhalt', + 'url' => 'URL', + 'filename' => 'Dateiname', + 'layout' => 'Layout', + 'description' => 'Beschreibung', + 'preview' => 'Vorschau', + 'enter_fullscreen' => 'Vollbildmodus einschalten', + 'exit_fullscreen' => 'Vollbildmodus verlassen', + 'hidden' => 'Verstecken', + 'hidden_comment' => 'Versteckte Seiten sind nur für eingeloggte administrations Benutzer zugänglich.', + 'navigation_hidden' => 'In der Navigation verstecken', + 'navigation_hidden_comment' => 'Setzen Sie diese Option, um diese Seite von automatisch generierten Menüs und Breadcrumbs zu verstecken.', + ], + 'snippet' => [ + 'partialtab' => 'Snippet', + 'code' => 'Snippet code', + 'code_comment' => 'Geben Sie einen Code ein, um dieses Partial als ein Snippet für das Statische-Seiten Plugin freizugeben.', + 'name' => 'Name', + 'name_comment' => 'Der Name wird in der Snippet-Liste in der Seitenleiste der Statische-Seiten angezeigt. Außerdem auf einer Seite wenn ein Snippet angelegt wird.', + 'no_records' => 'Keine Snippets gefunden', + 'menu_label' => 'Snippets', + 'column_property' => 'Titel für die Eigenschaft', + 'column_type' => 'Typ', + 'column_code' => 'Code', + 'column_default' => 'Standard', + 'column_options' => 'Optionen', + 'column_type_string' => 'Zeichenkette', + 'column_type_checkbox' => 'Checkbox', + 'column_type_dropdown' => 'Dropdown', + 'not_found' => 'Das Snippet mit dem angeforderten code :code wurde nicht im Theme gefunden.', + 'property_format_error' => 'Der Code für die Eigenschaft muss mit einem Buchstaben anfangen, und darf nur Buchstaben und Zahlen enthalten', + 'invalid_option_key' => 'Ungültiger Dropdown Optionsschlüssel: %s. Optionsschlüssel dürfen nur Zahlen, Buchstaben und die Zeichen _ und - enthalten' + ] + ]; diff --git a/plugins/rainlab/pages/lang/el/lang.php b/plugins/rainlab/pages/lang/el/lang.php new file mode 100644 index 0000000..724ce88 --- /dev/null +++ b/plugins/rainlab/pages/lang/el/lang.php @@ -0,0 +1,133 @@ + [ + 'name' => 'Σελίδες', + 'description' => 'Σελίδες και Μενού.', + ], + 'page' => [ + 'menu_label' => 'Σελίδες', + 'template_title' => '%s Σελίδες', + 'delete_confirmation' => 'Θέλετε πραγματικά να διαγράψετε τις επιλεγμένες σελίδες; Αυτό θα διαγράψει και τις υποσελίδες, εάν υπάρχουν.', + 'no_records' => 'Δεν βρέθηκαν σελίδες', + 'delete_confirm_single' => 'Θέλετε πραγματικά να διαγράψετε αυτή την σελίδα; Αυτό θα διαγράψει και τις υποσελίδες, εάν υπάρχουν.', + 'new' => 'Νέα σελίδα', + 'add_subpage' => 'Προσθήκη υποσελίδας', + 'invalid_url' => 'Μή έγκυρη μορφή URL. Το URL πρέπει να αρχίζει με το σύμβολο μπροστινής καθέτου και μπορεί να περιέχει αριθμητικά ψηφία, Λατινικούς χαρακτήρες και τα ακόλουθα σύμβολα: _-/.', + 'url_not_unique' => 'Αυτό το URL χρησιμοποιήται ήδη από άλλη σελίδα.', + 'layout' => 'Σχέδιο', + 'layouts_not_found' => 'Δεν βρέθηκαν σχέδια', + 'saved' => 'Η σελίδα αποθηκεύτηκε επιτυχώς.', + 'tab' => 'Σελίδες', + 'manage_pages' => 'Διαχείριση στατικών σελίδων', + 'manage_menus' => 'Διαχείριση στατικών μενού', + 'access_snippets' => 'Πρόσβαση στα αποσπάσματα', + 'manage_content' => 'Διαχείριση στατικού περιεχομένου', + ], + 'menu' => [ + 'menu_label' => 'Μενού', + 'delete_confirmation' => 'Θέλετε πραγματικά να διαγράψετε τα επιλεγμένα μενού;', + 'no_records' => 'Δεν βρέθηκανε μενού', + 'new' => 'Νέο μενού', + 'new_name' => 'Νέο μενού', + 'new_code' => 'new-menu', + 'delete_confirm_single' => 'Θέλετε πραγματικά να διαγράψετε αυτό το μενού;', + 'saved' => 'Αυτό το μενού αποθηκεύτηκε επιτυχώς.', + 'name' => 'Όνομα', + 'code' => 'Κωδικός', + 'items' => 'Στοιχεία μενού', + 'add_subitem' => 'Προσθήκη υποστοιχείου', + 'code_required' => 'Ο Κωδικός είναι απαραίτητος', + 'invalid_code' => 'Μή έγκυρη μορφή Κωδικού. Ο Κωδικός μπορεί να περιέχει αριθμητικά ψηφία, Λατινικούς χαρακτήρες και τα ακόλουθα σύμβολα: _-', + ], + 'menuitem' => [ + 'title' => 'Τίτλος', + 'editor_title' => 'Επεξεργασία στοιχείου μενού', + 'type' => 'Τύπος', + 'allow_nested_items' => 'Να επιτρέπονται ένθετα στοιχεία', + 'allow_nested_items_comment' => 'Τα ένθετα στοιχεία μπορούν να δημιουργηθούν δυναμικά από στατικές σελίδες και κάποιους άλλους τύπους στοιχείων', + 'url' => 'URL', + 'reference' => 'Αναφορά', + 'search_placeholder' => 'Αναζήτηση αναφορών...', + 'title_required' => 'Ο Τίτλος είναι απαραίτητος', + 'unknown_type' => 'Άγνωστος τύπος στοιχείου μενού', + 'unnamed' => 'Στοιχείο μενού χωρίς όνομα', + 'add_item' => 'Προσθήκη Στοιχείου', + 'new_item' => 'Νέο στοιχείο μενού', + 'replace' => 'Αντικατάσταση του στοιχείου με τα παραγμένα υποστοιχεία', + 'replace_comment' => 'Χρησιμοποιήστε αυτό το πλαίσιο για να ωθήσετε τα παραγμένα στοιχεία μενού στο ίδιο επίπεδο με αυτό το στοιχείο. Το ίδιο το στοιχείο θα γίνει κρυφό.', + 'cms_page' => 'Σελίδα CMS', + 'cms_page_comment' => 'Επιλέξτε σελίδα που θα ανοίγει όταν αυτό το μενού πατηθεί.', + 'reference_required' => 'Η αναφορά του στοιχείου μενού είναι απαραίτητη.', + 'url_required' => 'Το URL είναι απαραίτητο', + 'cms_page_required' => 'Παρακαλώ διαλέξτε μία σελίδα CMS', + 'code' => 'Κωδικός', + 'code_comment' => 'Εισάγετε το κωδικό του μενού εάν θέλετε να έχετε πρόσβαση μέσω του API.', + 'static_page' => 'Στατική σελίδα', + 'all_static_pages' => 'Όλες οι Στατικές Σελίδες' + ], + 'content' => [ + 'menu_label' => 'Περιεχόμενο', + 'cant_save_to_dir' => 'Η αποθήκευση των αρχείων περιεχομένου στο φάκελο στατικών σελίδων δεν επιτρέπεται.', + ], + 'sidebar' => [ + 'add' => 'Προσθήκη', + 'search' => 'Αναζήτηση...', + ], + 'object' => [ + 'invalid_type' => 'Άγνωστος τύπος αντικειμένου', + 'not_found' => 'Το ζητούμενο αντικείμενο δεν βρέθηκε.', + ], + 'editor' => [ + 'title' => 'Τίτλος', + 'new_title' => 'Νέος τίτλος σελίδας', + 'content' => 'Περιεχόμενο', + 'url' => 'URL', + 'filename' => 'Όνομα αρχείου', + 'layout' => 'Σχέδιο', + 'description' => 'Περιγραφή', + 'preview' => 'Προεπισκόπηση', + 'enter_fullscreen' => 'Πλήρης οθόνη', + 'exit_fullscreen' => 'Έξοδος πλήρους οθόνης', + 'hidden' => 'Κρυφό', + 'hidden_comment' => 'Κρυφές σελίδες είναι προσβάσιμες μόνο στους συνδεδεμένους χρήστες back-end.', + 'navigation_hidden' => 'Απόκρυψη στην πλοήγηση', + 'navigation_hidden_comment' => 'Επιλέξτε αυτό το πλαίσιο για να κρύψετε αυτή την σελίδα από αυτοματοποιημένα μενού και breadcrumbs.', + ], + 'snippet' => [ + 'partialtab' => 'Αποσπάσματα', + 'code' => 'Κώδικας αποσπάσματος', + 'code_comment' => 'Εισάγετε ένα κώδικα για να κάνεται αυτό το partial διαθέσιμο σαν απόσπασμα στο πρόσθετο Στατικών Σελίδων.', + 'name' => 'Όνομα', + 'name_comment' => 'Το όνομα εμφανίζεται στην λίστα αποσπασμάτων στην πλευρική στήλη Στατικών Σελίδων και σε μία Σελίδα όταν προστίθεται ένα απόσπασμα.', + 'no_records' => 'Δεν βρέθηκαν αποσπάσματα', + 'menu_label' => 'Αποσπάσματα', + 'column_property' => 'Τίτλος ιδιότητας', + 'column_type' => 'Τύπος', + 'column_code' => 'Κωδικός', + 'column_default' => 'Προκαθορισμένο', + 'column_options' => 'Επιλογές', + 'column_type_string' => 'Κείμενο', + 'column_type_checkbox' => 'Πλαίσιο ελέγχου', + 'column_type_dropdown' => 'Πτυσσόμενες επιλογές', + 'not_found' => 'Απόσπασμα με τον ζητούμενο κωδικό :code δεν βρέθηκε στο πρότυπο θέμα.', + 'property_format_error' => 'Οι κωδικοί των ιδιοτήτων πρέπει να ξεκινούν με Λατινικά γράμματα και μπορούν να περιέχουν μόνο Λατινικά γράμματα και αριθμητικά ψηφία', + 'invalid_option_key' => 'Μή έγκυρο κλειδί πτυσσόμενης επιλογής: :key. Τα κλειδιά επιλογών μπορούνα να περιέχουν μόνο αριθμιτικά ψηφία, Λατινικά γράμματα και τους χαρακτήρες _ και -', + ], + 'component' => [ + 'static_page_name' => 'Στατική σελίδα', + 'static_page_description' => 'Παράγει μία στατική σελίδα ενσωματωμένη σε ένα σχέδιο CMS.', + 'static_page_use_content_name' => 'Χρησιμοποιήστε το πεδίο περιεχομένου σελίδας', + 'static_page_use_content_description' => 'Εάν δεν είναι επιλεγμένο, η περιοχή περιεχομένου δεν θα εμφανίζεται όταν επεξεργάζεται η στατική σελίδα. Το περιεχόμενο της σελίδας θα ορίζεται αποκλειστικά μέσω αντικαταστατών και μεταβλητών.', + 'static_page_default_name' => 'Προεπιλεγμένο σχέδιο', + 'static_page_default_description' => 'Ορίζει αυτό το σχέδιο σαν το προεπιλεγμένο για καινούργιες σελίδες', + 'static_page_child_layout_name' => 'Σχέδιο υποσελίδων', + 'static_page_child_layout_description' => 'Το προεπιλεγμένο σχέδιο για καινούργιες υποσελίδες', + 'static_menu_name' => 'Στατικό μενού', + 'static_menu_description' => 'Παράγει ένα μενού σε ένα σχέδιο CMS.', + 'static_menu_code_name' => 'Μενού', + 'static_menu_code_description' => 'Ορίστε ένα κωδικό του μενού που το Δομικό Στοιχείο θα πρέπει να εξάγει.', + 'static_breadcrumbs_name' => 'Στατικά breadcrumbs', + 'static_breadcrumbs_description' => 'Παράγει breadcrumbs για μία στατική σελίδα.', + ] +]; diff --git a/plugins/rainlab/pages/lang/en/lang.php b/plugins/rainlab/pages/lang/en/lang.php new file mode 100644 index 0000000..9cca7b2 --- /dev/null +++ b/plugins/rainlab/pages/lang/en/lang.php @@ -0,0 +1,158 @@ + [ + 'name' => 'Pages', + 'description' => 'Pages & menus features.', + ], + 'page' => [ + 'menu_label' => 'Pages', + 'template_title' => '%s Pages', + 'delete_confirmation' => 'Do you really want to delete selected pages? This will also delete the subpages, if any.', + 'no_records' => 'No pages found', + 'delete_confirm_single' => 'Do you really want delete this page? This will also delete the subpages, if any.', + 'new' => 'New page', + 'add_subpage' => 'Add subpage', + 'invalid_url' => 'Invalid URL format. The URL should start with the forward slash symbol and can contain digits, Latin letters and the following symbols: _-/.', + 'url_not_unique' => 'This URL is already used by another page.', + 'layout' => 'Layout', + 'layouts_not_found' => 'Layouts not found', + 'saved' => 'The page has been successfully saved.', + 'tab' => 'Pages', + 'manage_pages' => 'Manage static pages', + 'manage_menus' => 'Manage static menus', + 'access_snippets' => 'Access snippets', + 'manage_content' => 'Manage static content', + ], + 'menu' => [ + 'menu_label' => 'Menus', + 'delete_confirmation' => 'Do you really want to delete selected menus?', + 'no_records' => 'No menus found', + 'new' => 'New menu', + 'new_name' => 'New menu', + 'new_code' => 'new-menu', + 'delete_confirm_single' => 'Do you really want delete this menu?', + 'saved' => 'The menu has been successfully saved.', + 'name' => 'Name', + 'code' => 'Code', + 'items' => 'Menu items', + 'add_subitem' => 'Add subitem', + 'code_required' => 'The Code is required', + 'invalid_code' => 'Invalid Code format. The Code can contain digits, Latin letters and the following symbols: _-', + ], + 'menuitem' => [ + 'title' => 'Title', + 'editor_title' => 'Edit Menu Item', + 'type' => 'Type', + 'allow_nested_items' => 'Allow nested items', + 'allow_nested_items_comment' => 'Nested items could be generated dynamically by static page and some other item types', + 'url' => 'URL', + 'reference' => 'Reference', + 'search_placeholder' => 'Search all references...', + 'title_required' => 'The Title is required', + 'unknown_type' => 'Unknown menu item type', + 'unnamed' => 'Unnamed menu item', + 'add_item' => 'Add Item', + 'new_item' => 'New menu item', + 'replace' => 'Replace this item with its generated children', + 'replace_comment' => 'Use this checkbox to push generated menu items to the same level with this item. This item itself will be hidden.', + 'cms_page' => 'CMS Page', + 'cms_page_comment' => 'Select a page to open when the menu item is clicked.', + 'reference_required' => 'The menu item reference is required.', + 'url_required' => 'The URL is required', + 'cms_page_required' => 'Please select a CMS page', + 'display_tab' => 'Display', + 'hidden' => 'Hidden', + 'hidden_comment' => 'Hide this menu item from appearing on the front-end.', + 'attributes_tab' => 'Attributes', + 'code' => 'Code', + 'code_comment' => 'Enter the menu item code if you want to access it with the API.', + 'css_class' => 'CSS Class', + 'css_class_comment' => 'Enter a CSS class name to give this menu item a custom appearance.', + 'external_link' => 'External link', + 'external_link_comment' => 'Open links for this menu item in a new window.', + 'static_page' => 'Static Page', + 'all_static_pages' => 'All Static Pages' + ], + 'content' => [ + 'menu_label' => 'Content', + 'saved' => 'The content has been successfully saved.', + 'cant_save_to_dir' => 'Saving content files to the static-pages directory is not allowed.', + ], + 'template' => [ + 'order_by' => 'Order by', + 'no_list_records' => 'No records found', + 'delete_confirm' => 'Delete selected templates?', + ], + 'sidebar' => [ + 'add' => 'Add', + 'search' => 'Search...', + ], + 'object' => [ + 'invalid_type' => 'Unknown object type', + 'unauthorized_type' => 'You are not authorized to manage :type objects', + 'not_found' => 'The requested object was not found.', + ], + 'editor' => [ + 'title' => 'Title', + 'new_title' => 'New page title', + 'content' => 'Content', + 'url' => 'URL', + 'filename' => 'File Name', + 'layout' => 'Layout', + 'description' => 'Description', + 'preview' => 'Preview', + 'enter_fullscreen' => 'Enter fullscreen mode', + 'exit_fullscreen' => 'Exit fullscreen mode', + 'hidden' => 'Hidden', + 'hidden_comment' => 'Hidden pages are accessible only by logged-in back-end users.', + 'navigation_hidden' => 'Hide in navigation', + 'navigation_hidden_comment' => 'Check this box to hide this page from automatically generated menus and breadcrumbs.', + ], + 'snippet' => [ + 'partialtab' => 'Snippet', + 'settings_popup_title' => 'Static Pages Snippet', + 'code' => 'Snippet code', + 'code_comment' => 'Enter a code to make this partial available as a snippet in the Static Pages plugin.', + 'code_required' => 'Please enter tne snippet code', + 'name' => 'Name', + 'name_comment' => 'The name is displayed in the snippet list in the Static Pages sidebar and on a Page when a snippet is added.', + 'name_required' => 'Please enter tne snippet name', + 'no_records' => 'No snippets found', + 'menu_label' => 'Snippets', + 'properties' => 'Snippet properties', + 'column_property' => 'Property Title', + 'title_required' => 'Please provide the property title', + 'type_required' => 'Please select the property type', + 'property_required' => 'Please provide the property name', + 'column_type' => 'Type', + 'column_type_placeholder' => 'Select', + 'column_code' => 'Code', + 'column_default' => 'Default', + 'column_options' => 'Options', + 'column_type_string' => 'String', + 'column_type_checkbox' => 'Checkbox', + 'column_type_dropdown' => 'Dropdown', + 'not_found' => 'Snippet with the requested code :code was not found in the theme.', + 'property_format_error' => 'Property code should start with a Latin letter and can contain only Latin letters and digits', + 'invalid_option_key' => 'Invalid drop-down option key: :key. Option keys can contain only digits, Latin letters and characters _ and -', + ], + 'component' => [ + 'static_page_name' => 'Static page', + 'static_page_description' => 'Outputs a static page in a CMS layout.', + 'static_page_use_content_name' => 'Use page content field', + 'static_page_use_content_description' => 'If unchecked, the content section will not appear when editing the static page. Page content will be determined solely through placeholders and variables.', + 'static_page_default_name' => 'Default layout', + 'static_page_default_description' => 'Defines this layout as the default for new pages', + 'static_page_child_layout_name' => 'Subpage layout', + 'static_page_child_layout_description' => 'The layout to use as the default for any new subpages', + 'static_menu_name' => 'Static menu', + 'static_menu_description' => 'Outputs a menu in a CMS layout.', + 'static_menu_code_name' => 'Menu', + 'static_menu_code_description' => 'Specify a code of the menu the component should output.', + 'static_breadcrumbs_name' => 'Static breadcrumbs', + 'static_breadcrumbs_description' => 'Outputs breadcrumbs for a static page.', + 'child_pages_name' => 'Child pages', + 'child_pages_description' => 'Displays a list of child pages for the current page', + ] +]; diff --git a/plugins/rainlab/pages/lang/es/lang.php b/plugins/rainlab/pages/lang/es/lang.php new file mode 100644 index 0000000..1cf8dcc --- /dev/null +++ b/plugins/rainlab/pages/lang/es/lang.php @@ -0,0 +1,115 @@ + [ + 'name' => 'Páginas', + 'description' => 'Páginas & menus', + ], + 'page' => [ + 'menu_label' => 'Páginas', + 'template_title' => '%s Páginas', + 'delete_confirmation' => 'Estas seguro de querer borrar las páginas seleccionadas? Esto también borrará las sub-páginas que existan.', + 'no_records' => 'No se ha encontrado ninguna página', + 'delete_confirm_single' => 'Estas seguro de querer borrar esta página? Esto también borrará las sub-páginas que existan.', + 'new' => 'Nueva página', + 'add_subpage' => 'Añadir sub-página', + 'invalid_url' => 'Formato de URL no válido. La URL debería comenzar por una barra (\'/\'). Puede contener letras, números, y los siguientes símbolos _ - / ', + 'url_not_unique' => 'Esta URL ya está siendo utilizada por otra página.', + 'layout' => 'Plantilla', + 'layouts_not_found' => 'No se han encontrado plantillas', + 'saved' => 'La página se ha guardado correctamente.', + 'tab' => 'Páginas', + 'manage_pages' => 'Administrar páginas', + 'manage_menus' => 'Administrar menús', + 'access_snippets' => 'Acceder a fragmentos', + 'manage_content' => 'Administrar contenidos' + ], + 'menu' => [ + 'menu_label' => 'Menus', + 'delete_confirmation' => 'Estas seguro de querer borrar los menus seleccionados?', + 'no_records' => 'No se han encontrado menus.', + 'new' => 'Nuevo menu', + 'new_name' => 'Nuevo menu', + 'new_code' => 'nuevo-menu', + 'delete_confirm_single' => 'Estas seguro de querer borrar este menu?', + 'saved' => 'El menú se ha guardado correctamente.', + 'name' => 'Nombre', + 'code' => 'Código', + 'items' => 'Elementos del menu', + 'add_subitem' => 'Añadir sub-elemento', + 'no_records' => 'No se han encontrado elementos.', + 'code_required' => 'El código es obligatorio', + 'invalid_code' => 'El formato del código no es válido. Puede contener letras, números y los siguientes símbolos: _ - ' + ], + 'menuitem' => [ + 'title' => 'Título', + 'editor_title' => 'Editar elemento del menu', + 'type' => 'Tipo', + 'allow_nested_items' => 'Permitir elementos anidados', + 'allow_nested_items_comment' => 'Los elementos anidados se pueden generar automáticamente mediante las páginas y otros tipos de elementos.', + 'url' => 'URL', + 'reference' => 'Referencia', + 'title_required' => 'El título es obligatorio', + 'unknown_type' => 'Este tipo de elemento del menú es desconocido.', + 'unnamed' => 'Elemento del menú sin nombre', + 'add_item' => 'Añadir elemento', + 'new_item' => 'Nuevo elemento', + 'replace' => 'Sustituye este elemento por los sub-elementos que contenga.', + 'replace_comment' => 'Marca esta casilla sustituir este elemento por los sub-elementos que contenga. El elemento proncipal quedará oculto.', + 'cms_page' => 'Página del CMS', + 'cms_page_comment' => 'Selecciona una página a la que enlazar cuando se haga click en este elemento del menu.', + 'reference_required' => 'La referencia al elemento del menú es obligatoria.', + 'url_required' => 'La URL es obligatoria', + 'cms_page_required' => 'Selecciona una página del CMS', + 'code' => 'Código', + 'code_comment' => 'Introduce el código del elemento para acceder mediante la API.' + ], + 'content' => [ + 'menu_label' => 'Contenido', + 'cant_save_to_dir' => 'No está permitido guardar archivos de contenido en el directorio de las páginas.' + ], + 'sidebar' => [ + 'add' => 'Añadir', + 'search' => 'Buscar...' + ], + 'object' => [ + 'invalid_type' => 'Tipo de objeto desconocido', + 'not_found' => 'No se ha encontrado el objeto solicitado.' + ], + 'editor' => [ + 'title' => 'Título', + 'new_title' => 'Título de la nueva página', + 'content' => 'Contenido', + 'url' => 'URL', + 'filename' => 'Nombre de archivo', + 'layout' => 'Plantilla', + 'description' => 'Descripción', + 'preview' => 'Vista previa', + 'enter_fullscreen' => 'Entrar en modo de pantalla completa', + 'exit_fullscreen' => 'Salir del modo de pantalla completa', + 'hidden' => 'Oculto', + 'hidden_comment' => 'Las páginas ocultas solo son visibles para los administradores que hayan iniciado sesión.', + 'navigation_hidden' => 'No mostrar en el menu', + 'navigation_hidden_comment' => 'Marca esta casilla para ocultar esta página en los menus generados automáticamente.', + ], + 'snippet' => [ + 'partialtab' => 'Fragmentos', + 'code' => 'Código del fragmento', + 'code_comment' => 'Introduce un código para hacer que el fragmento esté disponible en el plugin de páginas.', + 'name' => 'Nombre', + 'name_comment' => 'El nombre se muestra en la lista de fragmentos, en el menu lateral del plugin de las páginas, y en cada página en la que se haya utilizado el fragmento.', + 'no_records' => 'No se han encontrado fragmentos', + 'menu_label' => 'Fragmentos', + 'column_property' => 'Título de propiedad', + 'column_type' => 'Tipo', + 'column_code' => 'Código', + 'column_default' => 'Valor Predeterminado', + 'column_options' => 'Opciones', + 'column_type_string' => 'Texto', + 'column_type_checkbox' => 'Casilla', + 'column_type_dropdown' => 'Desplegable', + 'not_found' => 'No se ha encontrado ningún fragmento con el código :code en este tema.', + 'property_format_error' => 'El código de propiedad debería comenzar por una letra. Sólo puede contener letras y números.', + 'invalid_option_key' => 'La clave de opción del desplegable no es válida : %s. Estas claves sólo pueden contener números, letras y los símbolos _ y -' + ] +]; diff --git a/plugins/rainlab/pages/lang/fa/lang.php b/plugins/rainlab/pages/lang/fa/lang.php new file mode 100644 index 0000000..22ed045 --- /dev/null +++ b/plugins/rainlab/pages/lang/fa/lang.php @@ -0,0 +1,131 @@ + [ + 'name' => 'صفحات', + 'description' => 'مدیریت صفحات و فهرست ها', + ], + 'page' => [ + 'menu_label' => 'صفحات', + 'template_title' => 'صفحات %s', + 'delete_confirmation' => 'آیا از حذف صفحات انتخاب شده اطمینان دارید؟ اگر صفحات دارای زیر صفحه باشند آنها نیز حذف خواهند شد.', + 'no_records' => 'صفحه ای یافت نشد', + 'delete_confirm_single' => 'آیا از حذف این صفحه اطمینان دارید؟ اگر این صفحه دارای زیر مجموعه باشد آنها نیز حذف خواهند شد.', + 'new' => 'صفحه ی جدید', + 'add_subpage' => 'افزودن زیر مجموعه', + 'invalid_url' => 'قالب آدرس نا معتبر است. آدرس باید با اسلش شروع شود و میتواند شامل حروف لاتین، حروف فارسی، اعداد و این کاراکتر ها باشد: _-/.', + 'url_not_unique' => 'این آدرس توسط صفحه ی دیگری استفاده شده است.', + 'layout' => 'طرح بندی', + 'layouts_not_found' => 'طرح بندی برای صفحات استاتیک یافت نشد.', + 'saved' => 'صفحه با موفقیت ذخیره شد.', + 'tab' => 'صفحات', + 'manage_pages' => 'مدیریت صفحات استاتیک', + 'manage_menus' => 'مدیریت فهرست های استاتیک', + 'access_snippets' => 'دسترسی به تکه کد ها', + 'manage_content' => 'مدیریت محتوی استاتیک', + ], + 'menu' => [ + 'menu_label' => 'فهرست ها', + 'delete_confirmation' => 'آیا از حذف فهرست انتخاب شده اطمینان دارید؟', + 'no_records' => 'موردی یافت نشد', + 'new' => 'فهرست جدید', + 'new_name' => 'فهرست جدید', + 'new_code' => 'new-menu', + 'delete_confirm_single' => 'آیا از حذف این فهرست اطمینان دارید؟', + 'saved' => 'فهرست با موفقیت ذخیره شد.', + 'name' => 'نام', + 'code' => 'کد', + 'items' => 'موارد فهرست', + 'add_subitem' => 'افزودن زیر فهرست', + 'code_required' => 'وارد کردن کد اجباریست', + 'invalid_code' => 'قالب کد نا معتبر است. کد میتواند شامل اعداد، حروف لاتین و این کاراکتر ها باشد: _-', + ], + 'menuitem' => [ + 'title' => 'عنوان', + 'editor_title' => 'ویرایش فهرست', + 'type' => 'نوع', + 'allow_nested_items' => 'استفاده از موارد تو در تو', + 'allow_nested_items_comment' => 'موارد تو در تو به صورت خودکار توسط صفحات استاتیک و برخی از دیگر موارد ایجاد می شوند', + 'url' => 'آدرس', + 'reference' => 'مرجع', + 'search_placeholder' => 'جستجوی همه موارد...', + 'title_required' => 'وارد کردن عنوان اجباریست', + 'unknown_type' => 'نوع نامشخص فهرست', + 'unnamed' => 'فهرست بدون نام', + 'add_item' => 'افزودن فهرست', + 'new_item' => 'مورد جدید برای فهرست', + 'replace' => 'جایگرینی این مورد با زیر مورد های ایجاد شده', + 'replace_comment' => 'اگر میخواهید زیر فهرست های ایجاد شده هم سطح با این مورد قرار بگیرند این گزینه را فعال نمایید. خود فهرست بصورت خودکار مخفی خواهد شد.', + 'cms_page' => 'صفحه ی مدیریت محتوی', + 'cms_page_comment' => 'صفحه ای را که میخواهید به هنگام انتخاب این فهرست باز شود را انتخاب نمایید.', + 'reference_required' => 'وارد کردن مرجع برای فهرست الزامیست.', + 'url_required' => 'وارد کردن آدرس الزامیست', + 'cms_page_required' => 'لطفا یک صفحه را انتخاب کنید', + 'code' => 'کد', + 'code_comment' => 'اگر میخواهید از طریق کد ها به این مورد از فهرست دسترسی پیدا کنید کد آن را وارد نمایید.', + 'static_page' => 'صفحات استاتیک', + 'all_static_pages' => 'تمام صفحات استاتیک', + ], + 'content' => [ + 'menu_label' => 'محتوی', + 'cant_save_to_dir' => 'مجوز ذخیره ی داده ها در پوشه ی صفحات استاتسک وجود ندارد.', + ], + 'sidebar' => [ + 'add' => 'افزودن', + 'search' => 'جستجو...', + ], + 'object' => [ + 'invalid_type' => 'نوع شیء نا مشخص است', + 'not_found' => 'شیء درخواستی یافت نشد.', + ], + 'editor' => [ + 'title' => 'عنوان', + 'new_title' => 'عنوان صفحه ی جدید', + 'content' => 'محتوی', + 'url' => 'آدرس', + 'filename' => 'نام فایل', + 'layout' => 'طرح بندی', + 'description' => 'توضیحات', + 'preview' => 'پیش نمایش', + 'enter_fullscreen' => 'حالت تمام صفحه', + 'exit_fullscreen' => 'خروج از حالت تمام صفحه', + 'hidden' => 'مخفی', + 'hidden_comment' => 'صفحات مخفی توسط کاربران وارد شده به سایت قابل دسترس می باشند.', + 'navigation_hidden' => 'مخفی کردن در فهرست', + 'navigation_hidden_comment' => 'اگر میخواهید صفحه مورد نظر در فهرست هایی که خودکار ایجاد می شوند و یا نشان گرهای صفحه دیده نشوند این گزینه را انتخاب نمایید.', + ], + 'snippet' => [ + 'partialtab' => 'تکه کد', + 'code' => 'نام یکتای تکه کد', + 'code_comment' => 'نام یکتایی را جهت دسترسی به این بخش در افزونه صفحات استاتیک به عنوان تکه کد وارد نمایید.', + 'name' => 'نام', + 'name_comment' => 'نام نمایش داده شده این تکه کد در لیست', + 'no_records' => 'تکه کدی یافت نشد', + 'menu_label' => 'تکه کدها', + 'column_property' => 'عنوان مشخصه', + 'column_type' => 'نوع', + 'column_code' => 'کد یکتا', + 'column_default' => 'مقدار پیشفرض', + 'column_options' => 'گزینه ها', + 'column_type_string' => 'رشته', + 'column_type_checkbox' => 'جعبه انتخابی', + 'column_type_dropdown' => 'انتخابگر کشویی', + 'not_found' => 'تکه کدی با کد یکتای :code در قالب یافت نشد.', + 'property_format_error' => 'کد مشخصه باید با یک حرف لاتین شروع شده و شامل حروف لاتین و اعداد می تواند باشد.', + 'invalid_option_key' => 'کلید گزینه %s نامعتبر است. کلید گزینه انتخابگر کشویی فقط میتواند شامل اعداد، حروف لاتین وکاراکتر های _ و - باشد.', + ], + 'component' => [ + 'static_page_name' => 'صفحات استاتیک', + 'static_page_description' => 'نمایش یک صفحه استاتیک در طرح بندی.', + 'static_page_use_content_name' => 'استفاده از گرینه ها در محتوی.', + 'static_page_use_content_description' => 'اگر غیر فعال باشد، فیلد ها به هنگام ویرایش صفحات استاتیک در بخش محتوی نمایش داده نخواهند شد. محتوی صفحه با استفاده از متغییر های تعریف شده قابل کنتل می باشند.', + 'static_page_default_name' => 'طرح بندی پیش فرض', + 'static_page_default_description' => 'این طرح بندی به عنوان طرح بندی پیشفرض به هنگام ایجاد صفحه جدید در نظر گرفته شود؟', + 'static_page_child_layout_name' => 'طرح بندی صفحات زیرمجموعه', + 'static_page_child_layout_description' => 'این طرح بندی به عنوان طرح بندی تمام صفحات زیر مجموعه در نظر گرفنه شود؟', + 'static_menu_name' => 'فهرست استاتیک', + 'static_menu_description' => 'نمایش فهرست استاتیک در طرح بندی.', + 'static_menu_code_name' => 'فهرست', + 'static_menu_code_description' => 'کد فهرستی را که میخواهید به نمایش درآید انتخاب نمایید.', + 'static_breadcrumbs_name' => 'نشان گرها', + 'static_breadcrumbs_description' => 'نمایش نشان گرهای صفحه.', + ] +]; diff --git a/plugins/rainlab/pages/lang/fi/lang.php b/plugins/rainlab/pages/lang/fi/lang.php new file mode 100644 index 0000000..f4d2616 --- /dev/null +++ b/plugins/rainlab/pages/lang/fi/lang.php @@ -0,0 +1,153 @@ + [ + 'name' => 'Sivut', + 'description' => 'Sivu- ja valikko-ominaisuudet.', + ], + 'page' => [ + 'menu_label' => 'Sivut', + 'template_title' => '%s Sivut', + 'delete_confirmation' => 'Haluatko varmasti poistaa valitut sivut? Tämä poistaa myös alasivut, jos sellaisia on.', + 'no_records' => 'Sivuja ei löytynyt', + 'delete_confirm_single' => 'Haluatko varmasti poistaa tämän sivun? Tämä poistaa myös alasivut, jos sellaisia on.', + 'new' => 'Uusi sivu', + 'add_subpage' => 'Lisää alasivu', + 'invalid_url' => 'Kelvoton URL formaatti. URL pitäisi alkaa kautta -merkillä ja voi sisältää kokonaislukuja, latinalaisia kirjamia, ja seuraavia merkkejä: _-/.', + 'url_not_unique' => 'Tämä URL on toisen sivun käyttämä.', + 'layout' => 'Ulkoasu', + 'layouts_not_found' => 'Ulkoasuja ei löytynyt', + 'saved' => 'Sivu on tallennettu onnistuneesti.', + 'tab' => 'Sivut', + 'manage_pages' => 'Hallitse staattisia sivuja', + 'manage_menus' => 'Hallitse staattisia valikkoja', + 'access_snippets' => 'Hallitse koodinpätkiä', + 'manage_content' => 'Hallitse staattista sisältöä', + ], + 'menu' => [ + 'menu_label' => 'Valikot', + 'delete_confirmation' => 'Haluatko varmasti poista valitut valikot?', + 'no_records' => 'Vakujjiha ei löytynyt', + 'new' => 'Uusi valikko', + 'new_name' => 'Uusi valikko', + 'new_code' => 'uusi-valikko', + 'delete_confirm_single' => 'Haluatko varmasti poistaa tämän valikon?', + 'saved' => 'Tämä valikko on tallennettu onnistuneesti.', + 'name' => 'Nimi', + 'code' => 'Koodi', + 'items' => 'Valikon kohteet', + 'add_subitem' => 'Lisää alakohde', + 'code_required' => 'Koodi on vaadittu', + 'invalid_code' => 'Koodilla on kelvoton formaatti. Koodi voi sisältää kokonaislukuja, latinalaisia kirjamia, ja seuraavia merkkejä: _-', + ], + 'menuitem' => [ + 'title' => 'Otsikko', + 'editor_title' => 'Muokkaa valikkokohdetta', + 'type' => 'Tyyppi', + 'allow_nested_items' => 'Salli sisäkkäiset kohteet', + 'allow_nested_items_comment' => 'Sisäkkäiset kohteet staattisissa sivuissa ja muissa kohdetyypeissä voidaan generoida dynaamisesti', + 'url' => 'URL', + 'reference' => 'Viite', + 'search_placeholder' => 'Hae kaikista viitteistä...', + 'title_required' => 'Otsikko on vaadittu', + 'unknown_type' => 'Tuntematon valikkokohteen tyyppi', + 'unnamed' => 'Nimeämätön valikkokohde', + 'add_item' => 'Lisää Kohde', + 'new_item' => 'Uusi valikkokohde', + 'replace' => 'Korvaa valikko sen generoimilla alikohteilla', + 'replace_comment' => 'Käytä tätä valintaruutua työntääksesi valikon kohteet samalle tasolle tämän kohteen kanssa. Tämä kohde itsessään on piilotettu.', + 'cms_page' => 'CMS sivu', + 'cms_page_comment' => 'Valitse sivu joka avataan, kun valikkokohtaa napsautetaan.', + 'reference_required' => 'Valikkokohteen viite on vaadittu.', + 'url_required' => 'URL on vaadittu', + 'cms_page_required' => 'Valitse CMS sivu', + 'display_tab' => 'Näkyvyys', + 'hidden' => 'Piilotettu', + 'hidden_comment' => 'Piilota tämän valikon kohde näkyvistä käyttäjän näkymässä.', + 'attributes_tab' => 'Attribuutti', + 'code' => 'Koodi', + 'code_comment' => 'Syötä valikkokohten koodi jos haluat käyttää sitä API:n kanssa.', + 'css_class' => 'CSS-luokka', + 'css_class_comment' => 'Anna tämän valikon kohteelle oma CSS-luokka ulkoasua varten.', + 'external_link' => 'Ulkoinen linkki', + 'external_link_comment' => 'Avaa linkki tämän valikon kohteesta uudessa ikkunassa.', + 'static_page' => 'Staattinen sivu', + 'all_static_pages' => 'Kaikki staattiset sivut' + ], + 'content' => [ + 'menu_label' => 'Sisältö', + 'saved' => 'Sisältö tallennettu onnistuneesti.', + 'cant_save_to_dir' => 'Sisältötiedostojen tallentaminen staatisen-sivujen hakemistoon ei ole sallittua.', + ], + 'sidebar' => [ + 'add' => 'Lisää', + 'search' => 'Hae...', + ], + 'object' => [ + 'invalid_type' => 'Tuntematon kohdetyyppi', + 'unauthorized_type' => 'Sinulla ei ole oikeuksia muokata kohdetta :type', + 'not_found' => 'Pyydettyä kohdetta ei löytynyt.', + ], + 'editor' => [ + 'title' => 'Otsikko', + 'new_title' => 'Uuden sivun otsikko', + 'content' => 'Sisältö', + 'url' => 'URL', + 'filename' => 'Tiedostonimi', + 'layout' => 'Ulkoasu', + 'description' => 'Kuvaus', + 'preview' => 'Esikatsele', + 'enter_fullscreen' => 'Kokoruudun tila', + 'exit_fullscreen' => 'Poistu kokoruudun tilasta', + 'hidden' => 'Piilotettu', + 'hidden_comment' => 'Piilotetut sivut ovat saatavilla ainoastaan hallintaan kirjautuneille.', + 'navigation_hidden' => 'Piilota navigaatiossa', + 'navigation_hidden_comment' => 'Käytä tätä valintaruutua piilottaaksesi tämä sivu automaattisesti generoiduista valikoista ja leivänmuruista.', + ], + 'snippet' => [ + 'partialtab' => 'Osat', + 'settings_popup_title' => 'Staattisten sivujen koodinpätkä', + 'code' => 'Osan koodi', + 'code_comment' => 'Syötä koodi, jotta tämä osio on käytettävissä Staattisten sivujen -lisäosassa.', + 'code_required' => 'Ole hyvä ja lisää koodin pätkä', + 'name' => 'Nimi', + 'name_comment' => 'Nimi näkyy osiolistassa Staattisten sivujen -sivupalkissa ja sivuilla kun osa on lisätty.', + 'name_required' => 'Pätkällä on oltava nimi', + 'no_records' => 'Osia ei löydy', + 'menu_label' => 'Osat', + 'properties' => 'Koodin pätkän ominaisuudet', + 'column_property' => 'Ominaisuuden otsikko', + 'title_required' => 'Ole hyvä ja lisää ominaisuuden otsikko', + 'type_required' => 'Valitse ominaisuuden tyyppi', + 'property_required' => 'Ominaisuuden nimi on pakollinen', + 'column_type' => 'Tyyppi', + 'column_type_placeholder' => 'Valitse', + 'column_code' => 'Koodi', + 'column_default' => 'Oletus', + 'column_options' => 'Vaihtoehdot', + 'column_type_string' => 'Merkkijono', + 'column_type_checkbox' => 'Valintaruutu', + 'column_type_dropdown' => 'Alasvetovalikko', + 'not_found' => 'Osaa pyydetyllä koodilla :code ei löytynyt teemasta.', + 'property_format_error' => 'Ominaisuuden koodin tulisi alkaa latinalaisella kirjaimella ja voi sisältää ainoastaan latinalaisia merkkejä ja kokonaislukuja', + 'invalid_option_key' => 'Kelvoton alasvetovalikon vaihtoehtoavain :key. Vaihtoehtojen avaimet voivat sisältää ainoastaan kokonaislukuja, latinalaisia merkkejä, ja merkkejä _ ja -', + ], + 'component' => [ + 'static_page_name' => 'Staattinen sivu', + 'static_page_description' => 'Näyttää staattisen sivun CMS ulkoasussa.', + 'static_page_use_content_name' => 'Käytä sivun sisältökenttää Use page content field', + 'static_page_use_content_description' => 'Jos valitsematta, sisältö -kohta ei tule näkyviin staattista sivua muokattaessa. Sivun sisältö määritetään vain paikkamerkkien ja muuttujien kautta.', + 'static_page_default_name' => 'Oletusulkoasu', + 'static_page_default_description' => 'Määrittelee tämän ulkoasun oletukseksi uusille sivuille', + 'static_page_child_layout_name' => 'Alasivun ulkoasu', + 'static_page_child_layout_description' => 'Oletusulkoasu kaikille uusille alasivuille', + 'static_menu_name' => 'Staattinen valikko', + 'static_menu_description' => 'Näyttää valikon CMS ulkoasussa.', + 'static_menu_code_name' => 'Valikko', + 'static_menu_code_description' => 'Määritä valikon koodi joka pitäisi näyttää.', + 'static_breadcrumbs_name' => 'Staattinen murupolku', + 'static_breadcrumbs_description' => 'Näyttää murupolun staattisella sivulla.', + 'child_pages_name' => 'Alasivut', + 'child_pages_description' => 'Näyttää listan nykyisen sivun alasivuista', + ] +]; diff --git a/plugins/rainlab/pages/lang/fr/lang.php b/plugins/rainlab/pages/lang/fr/lang.php new file mode 100644 index 0000000..ff50f05 --- /dev/null +++ b/plugins/rainlab/pages/lang/fr/lang.php @@ -0,0 +1,143 @@ + [ + 'name' => 'Pages', + 'description' => 'Fonctionnalités de pages et menus statiques.', + ], + 'page' => [ + 'menu_label' => 'Pages', + 'template_title' => '%s Pages', + 'delete_confirmation' => 'Confirmez-vous la suppression des pages sélectionnées ? Les sous-pages seront également supprimées.', + 'no_records' => 'Aucune page trouvée', + 'delete_confirm_single' => 'Confirmez-vous la suppression de cette page ? Les sous-pages seront également supprimées.', + 'new' => 'Nouvelle page', + 'add_subpage' => 'Ajouter une sous-page', + 'invalid_url' => 'Le format d’URL est invalide. L’URL doit commencer par un / et peut contenir des chiffres, des lettres et les symboles suivants : _-/.', + 'url_not_unique' => 'Cette URL est déjà utilisée par une autre page.', + 'layout' => 'Maquette', + 'layouts_not_found' => 'Aucune maquette trouvée', + 'saved' => 'La page a été sauvegardée avec succès.', + 'tab' => 'Pages', + 'manage_pages' => 'Gérer les pages statiques', + 'manage_menus' => 'Gérer les menus statiques', + 'access_snippets' => 'Accès aux fragments', + 'manage_content' => 'Gérer le contenu statique' + ], + 'menu' => [ + 'menu_label' => 'Menus', + 'delete_confirmation' => 'Confirmez-vous la suppression des menus sélectionnés ?', + 'no_records' => 'Aucun menu trouvé', + 'new' => 'Nouveau menu', + 'new_name' => 'Nouveau menu', + 'new_code' => 'nouveau-menu', + 'delete_confirm_single' => 'Confirmez-vous la suppression de ce menu ?', + 'saved' => 'Le menu a été sauvegardé avec succès.', + 'name' => 'Nom', + 'code' => 'Code', + 'items' => 'Éléments du menu', + 'add_subitem' => 'Ajouter un élément', + 'code_required' => 'Le Code est requis', + 'invalid_code' => 'Le format du Code est invalide. Le Code peut contenir des chiffres, des lettres et les symboles suivants : _-' + ], + 'menuitem' => [ + 'title' => 'Titre', + 'editor_title' => 'Modifier l’élément du menu', + 'type' => 'Type', + 'allow_nested_items' => 'Autoriser les sous-éléments', + 'allow_nested_items_comment' => 'Les sous-éléments peuvent être générés dynamiquement par les pages statiques et certains des autres types d’élément', + 'url' => 'URL', + 'reference' => 'Référence', + 'search_placeholder' => 'Rechercher toutes les références...', + 'title_required' => 'Le Titre est requis', + 'unknown_type' => 'Type d’élément du menu inconnu', + 'unnamed' => 'Élément de menu sans nom', + 'add_item' => 'Ajouter un élément', + 'new_item' => 'Nouvel élément du menu', + 'replace' => 'Remplacer cet élément part ses sous-éléments générés', + 'replace_comment' => 'Utiliser cette case à cocher pour envoyer les sous-éléments générés au même niveau que cet élément. Cet élément sera lui-même masqué.', + 'cms_page' => 'Page CMS', + 'cms_page_comment' => 'Sélectionnez une page à ouvrir lors d’un clic sur cet élément du menu.', + 'reference_required' => 'La référence de l’élément du menu est requis.', + 'url_required' => 'L’URL est requise', + 'cms_page_required' => 'Sélectionnez une page CMS s’il vous plaît', + 'display_tab' => 'Affichage', + 'hidden' => 'Caché', + 'hidden_comment' => "Empêcher ce menu d'apparaître sur le site web.", + 'attributes_tab' => 'Attributs', + 'code' => 'Code', + 'code_comment' => 'Entrez le code de l’élément du menu si vous souhaitez y accéder via l’API.', + 'css_class' => 'Classe CSS', + 'css_class_comment' => 'Entrez un nom de classe CSS pour donner à cet élément de menu une apparence personnalisée.', + 'external_link' => 'Lien externe', + 'external_link_comment' => 'Ouvrir les liens pour ce menu dans une nouvelle fenêtre.', + 'static_page' => 'Page Statique', + 'all_static_pages' => 'Toutes les pages' + ], + 'content' => [ + 'menu_label' => 'Contenu', + 'cant_save_to_dir' => 'L’enregistrement des fichiers de contenu dans le répertoire des pages statiques n’est pas autorisé.' + ], + 'sidebar' => [ + 'add' => 'Ajouter', + 'search' => 'Rechercher...' + ], + 'object' => [ + 'invalid_type' => 'Type d’objet inconnu', + 'not_found' => 'L’objet demandé n’a pas été trouvé.' + ], + 'editor' => [ + 'title' => 'Titre', + 'new_title' => 'Nouveau titre de la page', + 'content' => 'Contenu', + 'url' => 'URL', + 'filename' => 'Nom du fichier', + 'layout' => 'Maquette', + 'description' => 'Description', + 'preview' => 'Aperçu', + 'enter_fullscreen' => 'Activer le mode plein écran', + 'exit_fullscreen' => 'Annuler le mode plein écran', + 'hidden' => 'Caché', + 'hidden_comment' => 'Les pages cachées sont seulement accessibles aux administrateurs connectés.', + 'navigation_hidden' => 'Masquer dans la navigation', + 'navigation_hidden_comment' => 'Cochez cette case pour masquer cette page dans les menus et le fil d’ariane générés automatiquement.', + ], + 'snippet' => [ + 'partialtab' => 'Fragment', + 'code' => 'Code du fragment', + 'code_comment' => 'Entrez un code pour rendre ce contenu partiel disponible en tant que fragment dans le plugin des Pages Statiques.', + 'name' => 'Nom', + 'name_comment' => 'Le nom est affiché dans la liste des fragments dans le menu latéral des Pages Statiques et dans une Page lorsque qu’un fragment y est ajouté.', + 'no_records' => 'Aucun fragment trouvé', + 'menu_label' => 'Fragments', + 'column_property' => 'Nom de la propriété', + 'column_type' => 'Type', + 'column_code' => 'Code', + 'column_default' => 'Valeur par défaut', + 'column_options' => 'Options', + 'column_type_string' => 'Chaîne de caractères', + 'column_type_checkbox' => 'Case à cocher', + 'column_type_dropdown' => 'Menu déroulant', + 'not_found' => 'Le fragment demandé avec le code :code n’a pas été trouvé dans le thème.', + 'property_format_error' => 'Le code de la propriété devrait commencer par une lettre et ne peut contenir que des lettres et des chiffres', + 'invalid_option_key' => 'Clé de l’option de la liste déroulante invalide. Les clés des options ne peuvent contenir que des chiffres, des lettres et les symboles _ et -' + ], + 'component' => [ + 'static_page_name' => 'Page Statique', + 'static_page_description' => 'Affiche une page statique dans une maquette du CMS.', + 'static_page_use_content_name' => 'Affiche la section de contenu', + 'static_page_use_content_description' => 'Si cette case n\'est pas cochée, la section de contenu n\'apparaîtra pas lors de la modification de la page statique. Le contenu de la page sera déterminé uniquement à l\'aide d\'espaces réservés et de variables.', + 'static_page_default_name' => 'Disposition par défault', + 'static_page_default_description' => 'Définit cette mise en page par défault pour les nouvelles pages', + 'static_page_child_layout_name' => 'Mise en page de la sous-page', + 'static_page_child_layout_description' => 'La mise en page à utiliser par défault pour les nouvelles sous-pages', + 'static_menu_name' => 'Menu Statique', + 'static_menu_description' => 'Affiche un menu dans une maquette du CMS.', + 'static_menu_code_name' => 'Menu', + 'static_menu_code_description' => 'Spécifiez le code du menu que le composant devrait afficher.', + 'static_breadcrumbs_name' => 'Breadcrumbs statique', + 'static_breadcrumbs_description' => 'Affiche l\' aide à la navigation dans une page statique.', + 'child_pages_name' => 'Pages enfants', + 'child_pages_description' => 'Affiche une liste de pages enfants pour la page en cours', + ], +]; diff --git a/plugins/rainlab/pages/lang/hu/lang.php b/plugins/rainlab/pages/lang/hu/lang.php new file mode 100644 index 0000000..6c4238c --- /dev/null +++ b/plugins/rainlab/pages/lang/hu/lang.php @@ -0,0 +1,145 @@ + [ + 'name' => 'Oldalak', + 'description' => 'Oldalak, menük, tartalmak és kódrészletek menedzselése.' + ], + 'page' => [ + 'menu_label' => 'Oldalak', + 'template_title' => '%s Oldalak', + 'delete_confirmation' => 'Valóban törölni akarja a kijelölt oldalakat és azok aloldalait?', + 'no_records' => 'Nincs létrehozva oldal', + 'delete_confirm_single' => 'Valóban törölni akarja ezt az oldalt és aloldalait?', + 'new' => 'Új oldal', + 'add_subpage' => 'Aloldal hozzáadása', + 'invalid_url' => 'Érvénytelen a webcím formátuma. Perjellel kell kezdődnie, és számokat, latin betűket, valamint a következő szimbólumokat tartalmazhatja: _-/.', + 'url_not_unique' => 'Egy másik oldal már használja ezt a webcímet.', + 'layout' => 'Elrendezés', + 'layouts_not_found' => 'Nincs létrehozva elrendezés.', + 'saved' => 'Az oldal mentése sikerült.', + 'tab' => 'Oldalak', + 'manage_pages' => 'Oldalak kezelése', + 'manage_menus' => 'Menük kezelése', + 'access_snippets' => 'Kódrészletek kezelése', + 'manage_content' => 'Tartalom kezelése' + ], + 'menu' => [ + 'menu_label' => 'Menük', + 'delete_confirmation' => 'Valóban törölni akarja a kijelölt menüket?', + 'no_records' => 'Nincs létrehozva menü', + 'new' => 'Új menü', + 'new_name' => 'Új menü', + 'new_code' => 'uj-menu', + 'delete_confirm_single' => 'Valóban törölni akarja ezt a menüt?', + 'saved' => 'A menü mentése sikerült.', + 'name' => 'Név', + 'code' => 'Kód', + 'items' => 'Menüpont', + 'add_subitem' => 'Almenü hozzáadása', + 'code_required' => 'A Kód kötelező', + 'invalid_code' => 'Érvénytelen a kód formátuma. Csak számokat, latin betűket és a következő szimbólumokat tartalmazhatja: _-' + ], + 'menuitem' => [ + 'title' => 'Cím', + 'editor_title' => 'Menüpont szerkesztése', + 'type' => 'Típus', + 'allow_nested_items' => 'Beágyazott menüpontok engedélyezése', + 'allow_nested_items_comment' => 'A beágyazott menüpontokat az oldal és néhány más menüpont típus dinamikusan generálhatja', + 'url' => 'Webcím', + 'reference' => 'Hivatkozás', + 'search_placeholder' => 'Keresés...', + 'title_required' => 'A cím megadása kötelező', + 'unknown_type' => 'Ismeretlen menüponttípus', + 'unnamed' => 'Névtelen menüpont', + 'add_item' => 'Menüpont hozzáadása', + 'new_item' => 'Új menüpont', + 'replace' => 'A menüpont kicserélése a generált gyermekeire', + 'replace_comment' => 'Ennek a jelölőnégyzetnek a használatával viheti a generált menüpontokat az ezen menüpont által azonos szintre. Maga ez a menüpont rejtett marad.', + 'cms_page' => 'Oldal', + 'cms_page_comment' => 'Válassza ki a menüre kattintáskor megnyitni kívánt oldalt.', + 'reference_required' => 'A menüpont hivatkozás kitöltése kötelező.', + 'url_required' => 'A webcím megadása kötelező', + 'cms_page_required' => 'Válasszon egy oldalt', + 'display_tab' => 'Megjelenés', + 'hidden' => 'Rejtett', + 'hidden_comment' => 'Nem jelenik meg a felhasználói felületen.', + 'attributes_tab' => 'Tulajdonságok', + 'code' => 'Kód', + 'code_comment' => 'Az API eléréshez szükséges egyedi azonosító.', + 'css_class' => 'CSS osztály', + 'css_class_comment' => 'Egyedi megjelenés esetén szükséges megadni.', + 'external_link' => 'Külső hivatkozás', + 'external_link_comment' => 'A link új ablakban fog megjelenni.', + 'static_page' => 'Oldalak', + 'all_static_pages' => 'Összes oldal' + ], + 'content' => [ + 'menu_label' => 'Tartalom', + 'saved' => 'A tartalom mentése sikerült.', + 'cant_save_to_dir' => 'A fájlok mentése a "static-pages" könyvtárba nem engedélyezett.' + ], + 'sidebar' => [ + 'add' => 'Hozzáadás', + 'search' => 'Keresés...' + ], + 'object' => [ + 'invalid_type' => 'Ismeretlen objektumtípus', + 'unauthorized_type' => 'Nem jogosult a következő objektum(ok) kezelésére: :type', + 'not_found' => 'A kért objektum nem található.' + ], + 'editor' => [ + 'title' => 'Cím', + 'new_title' => 'Új oldal címe', + 'content' => 'Tartalom', + 'url' => 'Webcím', + 'filename' => 'Fájlnév', + 'layout' => 'Elrendezés', + 'description' => 'Leírás', + 'preview' => 'Előnézet', + 'enter_fullscreen' => 'Váltás teljes képernyős módra', + 'exit_fullscreen' => 'Kilépés a teljes képernyős módból', + 'hidden' => 'Rejtett', + 'hidden_comment' => 'A rejtett oldalakhoz csak a bejelentkezett kiszolgáló oldali felhasználók férhetnek hozzá.', + 'navigation_hidden' => 'Elrejtés a navigációban', + 'navigation_hidden_comment' => 'Jelölje be ezt a jelölőnégyzetet ennek a oldalnak az automatikusan generált menükből és útkövetésekből való elrejtéséhez.' + ], + 'snippet' => [ + 'partialtab' => 'Kódrészlet', + 'code' => 'Kódrészlet kódja', + 'code_comment' => 'Adja meg a kódot, hogy a jelenlegi részlap elérhető legyen kódrészletként a Oldalak bővítményben.', + 'name' => 'Név', + 'name_comment' => 'A Kódrészletek listában jelenik meg a Oldalak oldalsó menüjében, valamint a Oldalak aloldalon.', + 'no_records' => 'Nincs létrehozva kódrészlet', + 'menu_label' => 'Kódrészletek', + 'column_property' => 'Cím', + 'column_type' => 'Típus', + 'column_code' => 'kód', + 'column_default' => 'Alapértelmezett', + 'column_options' => 'Lehetőségek', + 'column_type_string' => 'Szöveg', + 'column_type_checkbox' => 'Jelölőnégyzet', + 'column_type_dropdown' => 'Lenyíló lista', + 'not_found' => 'A(z) :code nevű kódrészlet nem található a témában.', + 'property_format_error' => 'A kód latin karakterrel kezdődhet és csak latin karaktereket és számokat tartalmazhat.', + 'invalid_option_key' => 'Érvénytelen formátum: :key. Csak számokat, latin betűket és a következő szimbólumokat tartalmazhatja: _-' + ], + 'component' => [ + 'static_page_name' => 'Statikus oldal', + 'static_page_description' => 'Oldalak megjelenítése.', + 'static_page_use_content_name' => 'Tartalom mező használata', + 'static_page_use_content_description' => 'Ha nem engedélyezi ezt, akkor a tartalmi rész nem fog megjelenni az oldal szerkesztésénél. Az oldal tartalmát kizárólag a változók fogják meghatározni.', + 'static_page_default_name' => 'Alapértelmezett elrendezés', + 'static_page_default_description' => 'Minden új oldal ezt az elrendezést fogja hasznáni alapértelmezettként.', + 'static_page_child_layout_name' => 'Aloldal elrendezés', + 'static_page_child_layout_description' => 'Minden új aloldal ezt az elrendezést fogja használni alapértelmezettként.', + 'static_menu_name' => 'Statikus menü', + 'static_menu_description' => 'Menük megjelenítése.', + 'static_menu_code_name' => 'Menü', + 'static_menu_code_description' => 'Speciális kód a megjelenő menünek.', + 'static_breadcrumbs_name' => 'Statikus kenyérmorzsa', + 'static_breadcrumbs_description' => 'Kenyérmorzsa megjelenítése.', + 'child_pages_name' => 'Aloldalak', + 'child_pages_description' => 'Megjeleníti az aktuális oldal aloldalainak listáját.', + ] +]; diff --git a/plugins/rainlab/pages/lang/it/lang.php b/plugins/rainlab/pages/lang/it/lang.php new file mode 100644 index 0000000..f987877 --- /dev/null +++ b/plugins/rainlab/pages/lang/it/lang.php @@ -0,0 +1,116 @@ + [ + 'name' => 'Pages', + 'description' => 'Funzionalità di pagine & menu.', + ], + 'page' => [ + 'menu_label' => 'Pagine', + 'template_title' => '%s Pagine', + 'delete_confirmation' => 'Vuoi davvero eliminare le pagine selezionate? L\'operazione cancellerà anche le sottopagine, se presenti.', + 'no_records' => 'Nessuna pagina trovata', + 'delete_confirm_single' => 'Vuoi davvero eliminare questa pagina? L\'operazione cancellerà anche le sottopagine, se presenti.', + 'new' => 'Nuova pagina', + 'add_subpage' => 'Aggiungi sottopagina', + 'invalid_url' => 'Formato dell\'URL non valido. L\'URL deve iniziare con una barra e può contenere numeri, lettere latine e i seguenti simboli: _-/.', + 'url_not_unique' => 'L\'URL è già utilizzato da un\'altra pagina.', + 'layout' => 'Layout', + 'layouts_not_found' => 'Layouts non trovato', + 'saved' => 'Pagina salvata con successo.', + 'tab' => 'Pagine', + 'manage_pages' => 'Gestisci pagine', + 'manage_menus' => 'Gestisci menu', + 'access_snippets' => 'Accedi agli snippet', + 'manage_content' => 'Gestisci contenuti' + ], + 'menu' => [ + 'menu_label' => 'Menu', + 'delete_confirmation' => 'Vuoi davvero eliminare i menu selezionati?', + 'no_records' => 'Nessun menu trovato', + 'new' => 'Nuovo menu', + 'new_name' => 'Nuovo menu', + 'new_code' => 'nuovo-menu', + 'delete_confirm_single' => 'Vuoi davvero eliminare questo menu?', + 'saved' => 'Menu salvato con successo.', + 'name' => 'Nome', + 'code' => 'Codice', + 'items' => 'Voci di menu', + 'add_subitem' => 'Aggiungi sottomenu', + 'code_required' => 'Il Codice è obbligatorio', + 'invalid_code' => 'Formato del Codice non valido. Il Codice può contenere numeri, lettere latine e i seguenti simboli: _-' + ], + 'menuitem' => [ + 'title' => 'Titolo', + 'editor_title' => 'Modifica voce di menu', + 'type' => 'Tipo', + 'allow_nested_items' => 'Consenti elementi nidificati', + 'allow_nested_items_comment' => 'Gli elementi nidificati possono essere generati dinamicamente dalle pagine e altre tipologie di elementi', + 'url' => 'URL', + 'reference' => 'Riferimento', + 'title_required' => 'Il Titolo è obbligatorio', + 'unknown_type' => 'Tipologia di menu sconosciuta', + 'unnamed' => 'Voce di menu senza nome', + 'add_item' => 'Aggiungi elemento', + 'new_item' => 'Nuova voce di menu', + 'replace' => 'Sostituisci questo elemento con i figli generati', + 'replace_comment' => 'Usa questa checkbox per inserire le voci di menu generate allo stesso livello di questo elemento. Questa voce verrà nascosta.', + 'cms_page' => 'Pagine CMS', + 'cms_page_comment' => 'Seleziona una pagina del CMS da aprire quando viene selezionata la voce di menu.', + 'reference_required' => 'Il riferimento della voce di menu è obbligatorio.', + 'url_required' => 'L\'URL è obbligatorio', + 'cms_page_required' => 'Seleziona una pagina CMS', + 'code' => 'Codice', + 'code_comment' => 'Inserisci il codice della voce di menu se vuoi accedervi con l\'API.', + 'static_page' => 'Pagine', + 'all_static_pages' => 'Tutte le pagine' + ], + 'content' => [ + 'menu_label' => 'Contenuti', + 'cant_save_to_dir' => 'Salvataggio dei file di contenuto nella directory static-pages non consentito.' + ], + 'sidebar' => [ + 'add' => 'Aggiungi', + 'search' => 'Cerca...' + ], + 'object' => [ + 'invalid_type' => 'Tipo di oggetto sconosciuto', + 'not_found' => 'Oggetto richiesto non trovato.' + ], + 'editor' => [ + 'title' => 'Titolo', + 'new_title' => 'Titolo nuova pagina', + 'content' => 'Contenuto', + 'url' => 'URL', + 'filename' => 'Nome file', + 'layout' => 'Layout', + 'description' => 'Descrizione', + 'preview' => 'Anteprima', + 'enter_fullscreen' => 'Abilita visualizzazione a schermo intero', + 'exit_fullscreen' => 'Esci dalla visualizzazione a schermo intero', + 'hidden' => 'Nascosto', + 'hidden_comment' => 'Le pagine nascoste sono accessibili soltanto dagli utenti che hanno effettuato l\'accesso al pannello di controllo.', + 'navigation_hidden' => 'Nascondi dalla navigazione', + 'navigation_hidden_comment' => 'Seleziona questa checkbox per nascondere questa pagina dai menu e dalle barre di navigazione generate automaticamente.', + ], + 'snippet' => [ + 'partialtab' => 'Snippet', + 'code' => 'Codice Snippet', + 'code_comment' => 'Inserisci un codice per rendere questa vista parziale disponibile come snippet nel plugin Static Pages.', + 'name' => 'Nome', + 'name_comment' => 'Il nome è visualizzato nella lista degli snippet nella barra laterale di Static Pages e su una Pagina quando viene aggiunto lo snippet.', + 'no_records' => 'Nessuno snippet trovato', + 'menu_label' => 'Snippet', + 'column_property' => 'Titolo proprietà', + 'column_type' => 'Tipo', + 'column_code' => 'Codice', + 'column_default' => 'Default', + 'column_options' => 'Opzioni', + 'column_type_string' => 'Testo', + 'column_type_checkbox' => 'Checkbox', + 'column_type_dropdown' => 'Menu a cascata', + 'not_found' => 'Snippet con codice :code non trovato nel tema.', + 'property_format_error' => 'Il codice della proprietà deve iniziare con una lettera latina e può contenere solo lettere latine e numeri', + 'invalid_option_key' => 'Opzione del menu a cascata non valida: %s. Le opzioni possono contenere solo numeri, lettere latine e i caratteri _ e -' + ] +]; diff --git a/plugins/rainlab/pages/lang/lv/lang.php b/plugins/rainlab/pages/lang/lv/lang.php new file mode 100644 index 0000000..350554b --- /dev/null +++ b/plugins/rainlab/pages/lang/lv/lang.php @@ -0,0 +1,120 @@ + [ + 'name' => 'Lapas', + 'description' => 'Lapu un izvēļņu funkcijas.', + ], + 'page' => [ + 'menu_label' => 'Lapas', + 'template_title' => '%s Lapas', + 'delete_confirmation' => 'Vai tu tiešām vēlies dzēst izvēlētās lapas? Šī operācija izdzēsīs arī apakšlapas (ja tādas ir).', + 'no_records' => 'Neviena lapa netika atrasta', + 'delete_confirm_single' => 'Vai tu tiešām vēlies dzēst izvēlēto lapu? Šī operācija izdzēsīs arī apakšlapas (ja tādas ir).', + 'new' => 'Jauna lapa', + 'add_subpage' => 'Pievienot apakšlapu', + 'invalid_url' => 'Nekorekts saites formāts. Saitei vajadzētu sākties ar slīpsvītru un tā var saturēt ciparus, latīnu alfabēta burtus, slīpsvītras un sekojošos sibolus: _-/.', + 'url_not_unique' => 'Šādu saiti izmanto jau kāda cita lapa.', + 'layout' => 'Izkārtojums', + 'layouts_not_found' => 'Izkārtojumi netika atrasti', + 'saved' => 'Lapa tika veiksmīgi saglabāta.', + 'tab' => 'Lapas', + 'manage_pages' => 'Pieeja labot statiskās lapas', + 'manage_menus' => 'Pieeja labot statiskās izvēlnes', + 'access_snippets' => 'Pieeja koda fragmentiem', + 'manage_content' => 'Pieeja labot statisko saturu', + ], + 'menu' => [ + 'menu_label' => 'Izvēlnes', + 'delete_confirmation' => 'Vai tu tiešām vēlies dzēst izvēlētās izvēlnes?', + 'no_records' => 'Izvēlnes netika atrastas', + 'new' => 'Jauna izvēlne', + 'new_name' => 'Jauna izvēlne', + 'new_code' => 'jauna-izvelne', + 'delete_confirm_single' => 'Vai tu tiešām vēlies dzēst šo izvēlni?', + 'saved' => 'Izvēlne tika veiksmīgi saglabāta', + 'name' => 'Vārds', + 'code' => 'Kods', + 'items' => 'Izvēlnes priekšmeti', + 'add_subitem' => 'Pievienot apakšpriekšmetu', + 'code_required' => 'Kods ir obligāts lauks.', + 'invalid_code' => 'Nepreaizs koda formāts. Kods var saturēt ciparus, latīnu alfabēta burtus un sekojošos simbolus: _-', + ], + 'menuitem' => [ + 'title' => 'Nosaukums', + 'editor_title' => 'Labot izvēlnes priekšmetu', + 'type' => 'Tips', + 'allow_nested_items' => 'Atļaut iegultos priekšmetus', + 'allow_nested_items_comment' => 'Iegultie priekšmeti var tikt dinamiski ģenerēti', + 'url' => 'Saite', + 'reference' => 'Atsauce', + 'title_required' => 'Nosaukuma lauks ir obligāts', + 'unknown_type' => 'Nezināms izvēlnes tips', + 'unnamed' => 'Izvēlnes priekšmets bez nosaukums', + 'add_item' => 'Pievienot Priekšmetu', + 'new_item' => 'Jauns izvēlnes priekšmets', + 'replace' => 'Aizvietot šo priekšmetu ar tā ģenerētajiem bērniem', + 'cms_page' => 'CMS lapa', + 'cms_page_comment' => 'Izvēlies lapu, kas atvērsies, kad tiks noklikšķiāts uz šī izvēlnes priekšmeta.', + 'reference_required' => 'Izvēlnes priekšmeta atsauce ir obligāts lauks.', + 'url_required' => 'Saite ir obligāti jāievada', + 'cms_page_required' => 'Lūdzu, izvēlies CMS lapu', + 'code' => 'Kods', + 'code_comment' => 'Ievadi izvēlnes priekšmeta kodu, ja tam vēlies piekļūt izmantojot API.', + 'static_page' => 'Statiska lapa', + 'all_static_pages' => 'Visas statiskās lapas' + ], + 'content' => [ + 'menu_label' => 'Saturs', + 'cant_save_to_dir' => 'Satura failu saglabāšana statisko lapu direktorijā nav atļauta.S', + ], + 'sidebar' => [ + 'add' => 'Pievienot', + 'search' => 'Meklēt...', + ], + 'object' => [ + 'invalid_type' => 'Nezināms objekta tips', + 'not_found' => 'Pieprasītais objekts netika atrasts.', + ], + 'editor' => [ + 'title' => 'Nosaukums', + 'new_title' => 'Jaunās lapas nosaukums', + 'content' => 'Saturs', + 'url' => 'Saite', + 'filename' => 'Faila nosaukums', + 'layout' => 'Izkārtojums', + 'description' => 'Skaidrojums', + 'preview' => 'Priekšskats', + 'enter_fullscreen' => 'Atvērt pilnekrāna režīmu', + 'exit_fullscreen' => 'Aizvērt pilnekrāna režīmu', + 'hidden' => 'Paslēpts', + 'hidden_comment' => 'Paslēptās lapas varēs redzēt tikai ielogojušies back-end lietotāji.', + 'navigation_hidden' => 'Paslēpt navigācijā', + 'navigation_hidden_comment' => 'Atķeksē šo kasti, lai automātiski ģenerētu izvēlnes un breadcrumbus.', + ], + 'snippet' => [ + 'partialtab' => 'Koda fragmenti', + 'code' => 'Koda fragmenta kods', + 'code_comment' => 'Ievadi kodu, lai padarītu šo partialu par koda fragmentu.', + 'name' => 'Nosaukums', + 'name_comment' => 'Nosaukums tiks rādīts koda fragmentu sarakstā.', + 'no_records' => 'Koda fragmenti netika atrasti', + 'menu_label' => 'Koda fragmenti', + 'column_property' => 'Nosaukums', + 'column_type' => 'Tips', + 'column_code' => 'Kods', + 'column_default' => 'Noklusējuma vērtība', + 'column_options' => 'Opcijas', + 'column_type_string' => 'Teksts', + 'column_type_checkbox' => 'Checkboksis', + 'column_type_dropdown' => 'Dropdowns', + 'not_found' => 'Koda fragments ar pieprasīto kodu :code netika atrasts tēmā.', + 'property_format_error' => 'Kodam vajadzētu sākties ar latīņu alfabēta burtu un tas var saturēt latīņu alfabēta burtus un ciparus', + 'invalid_option_key' => 'Nekorekta dropdowna vērtība: :key.', + ], + 'component' => [ + 'static_page_description' => 'Izvada statisku lapu CMS iegultnē.', + 'static_menu_description' => 'Izvada izvēlni CMS iegultnē.', + 'static_menu_menu_code' => 'Specificē komponentes kodu, ko izvadīt', + 'static_breadcrumbs_description' => 'Izvada breadcrumbus CMS iegultnē.', + ], +]; diff --git a/plugins/rainlab/pages/lang/nb-no/lang.php b/plugins/rainlab/pages/lang/nb-no/lang.php new file mode 100644 index 0000000..797db80 --- /dev/null +++ b/plugins/rainlab/pages/lang/nb-no/lang.php @@ -0,0 +1,114 @@ + [ + 'name' => 'Sider', + 'description' => 'Side- og menyfunksjoner.', + ], + 'page' => [ + 'menu_label' => 'Sider', + 'template_title' => '%s Sider', + 'delete_confirmation' => 'Vil du virkelig slette de valgte sidene? Hvis siden har undersider, blir de også slettet.', + 'no_records' => 'Ingen sider funnet', + 'delete_confirm_single' => 'Vil du virkelig slette denne siden? Hvis siden har undersider, blir de også slettet.', + 'new' => 'Ny side', + 'add_subpage' => 'Ny underside', + 'invalid_url' => 'Ugyldig URL-format. URL-en skal starte med en skråstrek og kan bare inneholde tall, latinske bokstaver og følgende symboler: _-/.', + 'url_not_unique' => 'URL-en er allerede i bruk av en annen side.', + 'layout' => 'Layout', + 'layouts_not_found' => 'Ingen layouts funnet', + 'saved' => 'Siden har blitt lagret.', + 'manage_pages' => 'Administrer statiske sider', + 'manage_menus' => 'Administrer statiske menyer', + 'access_snippets' => 'Tilgang til snippets', + 'manage_content' => 'Administrer statisk innhold' + ], + 'menu' => [ + 'menu_label' => 'Menyer', + 'delete_confirmation' => 'Vil du virkelig slette valgte menyer?', + 'no_records' => 'Ingen menyer funnet', + 'new' => 'Ny meny', + 'new_name' => 'Ny meny', + 'new_code' => 'new-menu', + 'delete_confirm_single' => 'Vil du virkelig slette denne menyen?', + 'saved' => 'Menyen har blitt lagret.', + 'name' => 'Navn', + 'code' => 'Kode', + 'items' => 'Elementer', + 'add_subitem' => 'Nytt underelement', + 'no_records' => 'Ingen elementer funnet', + 'code_required' => 'En kode kreves.', + 'invalid_code' => 'Ugyldig kode-format. Koden kan inneholde tall, latinske bokstaver og følgende symboler: _-' + ], + 'menuitem' => [ + 'title' => 'Tittel', + 'editor_title' => 'Endre element', + 'type' => 'Type', + 'allow_nested_items' => 'Tillat underelementer', + 'allow_nested_items_comment' => 'Underelementer kan bli generert dynamisk av statiske sider og andre elementtyper', + 'url' => 'URL', + 'reference' => 'Referanse', + 'title_required' => 'Tittel kreves.', + 'unknown_type' => 'Ukjent elementtype', + 'unnamed' => 'Navnløs elementtype', + 'add_item' => 'Legg til element', + 'new_item' => 'Nytt element', + 'replace' => 'Erstatt dette elementet med sine underelementer', + 'replace_comment' => 'Huk av denne boksen for å skjule dette elementet. Underelementer blir fremdeles synlige.', + 'cms_page' => 'CMS-side', + 'cms_page_comment' => 'Velg hvilken side som skal åpnes når man trykker på linken.', + 'reference_required' => 'En referanse kreves.', + 'url_required' => 'En URL kreves.', + 'cms_page_required' => 'Vennligst velg en CMS-side', + 'code' => 'Kode', + 'code_comment' => 'Velg en elementkode hvis du trenger tilgang via API-en. (valgfritt)' + ], + 'content' => [ + 'menu_label' => 'Innhold', + 'cant_save_to_dir' => 'Å lagre innhold til files i static-pages-mappen er ikke tillatt.' + ], + 'sidebar' => [ + 'add' => 'Legg til', + 'search' => 'Søk...' + ], + 'object' => [ + 'invalid_type' => 'Ukjent objekttype', + 'not_found' => 'Det forespurte objektet ble ikke funnet.' + ], + 'editor' => [ + 'title' => 'Tittel', + 'new_title' => 'Tittel på siden', + 'content' => 'Innhold', + 'url' => 'URL', + 'filename' => 'Filnavn', + 'layout' => 'Layout', + 'description' => 'Beskrivelse', + 'preview' => 'Forhåndsvis', + 'enter_fullscreen' => 'Fullskjermmodus', + 'exit_fullscreen' => 'Avslutt fullskjermmodus', + 'hidden' => 'Skjult', + 'hidden_comment' => 'Kun backend-brukere har tilgang til skjulte sider.', + 'navigation_hidden' => 'Gjem i menyer', + 'navigation_hidden_comment' => 'Huk av denne boksen for å skjule denne siden i genererte menyer', + ], + 'snippet' => [ + 'partialtab' => 'Snippet', + 'code' => 'Snippet-kode', + 'code_comment' => 'Fyll inn en kode for å gjøre denne tilgjengelig som en snippet i Static Pages.', + 'name' => 'Navn', + 'name_comment' => 'Navnet som blir presentert i snippetlisten i Static Pages-menyen og når snippeten er lagt inn på en side.', + 'no_records' => 'Ingen snippets funnet', + 'menu_label' => 'Snippets', + 'column_property' => 'Egenskap', + 'column_type' => 'Type', + 'column_code' => 'Kode', + 'column_default' => 'Standard', + 'column_options' => 'Alternativer', + 'column_type_string' => 'String', + 'column_type_checkbox' => 'Checkbox', + 'column_type_dropdown' => 'Dropdown', + 'not_found' => 'En snippet med koden :code ble ikke funnet.', + 'property_format_error' => 'Egenskapkoden skal starte med en latinsk bokstav og kan kun inneholde bokstver og tall.', + 'invalid_option_key' => 'Ugyldig dropdown-alternativ kode: %s. Alternativkoder kan bare inneholde tall, latinske bokstaver, _ og -' + ] +]; diff --git a/plugins/rainlab/pages/lang/nl/lang.php b/plugins/rainlab/pages/lang/nl/lang.php new file mode 100644 index 0000000..13ea5c0 --- /dev/null +++ b/plugins/rainlab/pages/lang/nl/lang.php @@ -0,0 +1,116 @@ + [ + 'name' => 'Pagina\'s', + 'description' => 'Pagina & menu functionaliteit.', + ], + 'page' => [ + 'menu_label' => 'Pagina\'s', + 'template_title' => '%s Pagina\'s', + 'delete_confirmation' => 'Weet u zeker dat u de geselecteerde pagina\'s wilt verwijderen? Ook eventuele subpagina\'s zullen hierdoor verwijderd worden.', + 'no_records' => 'Geen pagina\'s gevonden', + 'delete_confirm_single' => 'Weet u zeker dat u deze pagina wilt verwijderen? Ook eventuele subpagina\'s zullen hierdoor verwijderd worden.', + 'new' => 'Nieuwe pagina', + 'add_subpage' => 'Subpagina toevoegen', + 'invalid_url' => 'Ongeldige URL-structuur. De URL moet beginnen met een slash en kan enkel cijfers, Latijnse letters en deze symbolen bevatten: _-/.', + 'url_not_unique' => 'Deze URL wordt al gebruikt door een andere pagina.', + 'layout' => 'Layout', + 'layouts_not_found' => 'Geen layouts gevonden', + 'saved' => 'De pagina is succesvol opgeslagen.', + 'tab' => 'Pagina\'s', + 'manage_pages' => 'Beheer statische pagina\'s', + 'manage_menus' => 'Beheer statische menu\'s', + 'access_snippets' => 'Toegang tot blokken', + 'manage_content' => 'Beheer statische inhoud', + ], + 'menu' => [ + 'menu_label' => 'Menu\'s', + 'delete_confirmation' => 'Weet u zeker dat u de geselecteerde menu\'s wilt verwijderen?', + 'no_records' => 'Geen menu\'s gevonden', + 'new' => 'Nieuw menu', + 'new_name' => 'Nieuw menu', + 'new_code' => 'nieuw-menu', + 'delete_confirm_single' => 'Weet u zeker dat u dit menu wilt verwijderen?', + 'saved' => 'Het menu is opgeslagen.', + 'name' => 'Naam', + 'code' => 'Code', + 'items' => 'Menu items', + 'add_subitem' => 'Subitem toevoegen', + 'code_required' => 'Code is verplicht', + 'invalid_code' => 'Ongeldige code-structuur. De Code kan enkel cijfers, Latijnse letters en deze symbolen bevatten: _-', + ], + 'menuitem' => [ + 'title' => 'Titel', + 'editor_title' => 'Bewerk Menu Item', + 'type' => 'Type', + 'allow_nested_items' => 'Accepteer geneste items', + 'allow_nested_items_comment' => 'Geneste items worden dynamisch gegenereerd door statische pagina\'s en sommige andere types.', + 'url' => 'URL', + 'reference' => 'Referentie', + 'title_required' => 'Titel is verplicht', + 'unknown_type' => 'Onbekend menu item type', + 'unnamed' => 'Onbenoemd menu item', + 'add_item' => 'Item toevoegen', + 'new_item' => 'Nieuw menu item', + 'replace' => 'Vervang dit item door de gegenereerde subitems', + 'replace_comment' => 'Wanneer u deze optie aanvinkt, zullen de gegenereerd menu items worden getoond op het niveau van dit item. Dit item zelf zal verborgen blijven.', + 'cms_page' => 'CMS Pagina', + 'cms_page_comment' => 'Selecteer een pagina om te openen wanneer op het menu item geklikt wordt.', + 'reference_required' => 'Een referentie is verplicht.', + 'url_required' => 'Een URL is verplicht', + 'cms_page_required' => 'Gelieve een CMS Pagina te selecteren', + 'code' => 'Code', + 'code_comment' => 'Geef de menu item code op indien u deze wilt benaderen via de API.', + 'static_page' => 'Statische pagina', + 'all_static_pages' => 'Alle statische pagina\'s' + ], + 'content' => [ + 'menu_label' => 'Inhoud', + 'cant_save_to_dir' => 'Het is niet toegelaten bestanden met inhoud op te slaan in de static-pages map.', + ], + 'sidebar' => [ + 'add' => 'Toevoegen', + 'search' => 'Zoeken...', + ], + 'object' => [ + 'invalid_type' => 'Onbekend object type', + 'not_found' => 'Het gevraagde object is niet gevonden.', + ], + 'editor' => [ + 'title' => 'Titel', + 'new_title' => 'Nieuwe pagina titel', + 'content' => 'Inhoud', + 'url' => 'URL', + 'filename' => 'Bestandsnaam', + 'layout' => 'Layout', + 'description' => 'Beschrijving', + 'preview' => 'Voorbeeld', + 'enter_fullscreen' => 'Volledig scherm openen', + 'exit_fullscreen' => 'Volledig scherm afsluiten', + 'hidden' => 'Verborgen', + 'hidden_comment' => 'Verborgen pagina\'s zijn alleen toegankelijk voor ingelogde gebruikers.', + 'navigation_hidden' => 'Verbergen in de navigatie', + 'navigation_hidden_comment' => 'Indien aangevinkt, zal deze pagina niet weergegeven worden in automatisch gegenereerde menu\'s en kruimelpaden (breadcrumbs).', + ], + 'snippet' => [ + 'partialtab' => 'Blokken', + 'code' => 'Blok code', + 'code_comment' => 'Voer een code in om dit fragment beschikbaar the maken in de Static Pages plugin.', + 'name' => 'Naam', + 'name_comment' => 'De naam wordt weergegeven in de blokkenlijst in de zijbalk en op de pagina waar dit blok wordt toegevoegd.', + 'no_records' => 'Geen blokken gevonden', + 'menu_label' => 'Blokken', + 'column_property' => 'Eigenschap naam', + 'column_type' => 'Type', + 'column_code' => 'Code', + 'column_default' => 'Standaardwaarde', + 'column_options' => 'Opties', + 'column_type_string' => 'Tekst', + 'column_type_checkbox' => 'Selectieveld', + 'column_type_dropdown' => 'Selectielijst', + 'not_found' => 'Blok met de gevraagde code :code is niet gevonden in het thema.', + 'property_format_error' => 'De naam van de eigenschap moet beginnen met een letter en kan alleen letters en cijfers bevatten.', + 'invalid_option_key' => 'Ongeldige selectlijst waarde: %s. Deze waarden mogen alleen cijfers, letters of de karakters _- bevatten.', + ], +]; diff --git a/plugins/rainlab/pages/lang/pl/lang.php b/plugins/rainlab/pages/lang/pl/lang.php new file mode 100644 index 0000000..b10c968 --- /dev/null +++ b/plugins/rainlab/pages/lang/pl/lang.php @@ -0,0 +1,142 @@ + [ + 'name' => 'Strony', + 'description' => 'Strony statyczne oraz menu.', + ], + 'page' => [ + 'menu_label' => 'Strony', + 'template_title' => '%s Strony', + 'delete_confirmation' => 'Czy na pewno chcesz usunąć wybrane strony? Podstrony również zostaną usnięte.', + 'no_records' => 'Nie znaleziono stron', + 'delete_confirm_single' => 'Czy na pewno chcesz usunąć stronę? Podstrony również zostaną usnięte.', + 'new' => 'Nowa strona', + 'add_subpage' => 'Dodaj podstronę', + 'invalid_url' => 'Niewprawidłowy format URL lub niedozwolone znaki.', + 'url_not_unique' => 'Podany URL istnieje już w bazie.', + 'layout' => 'Układ', + 'layouts_not_found' => 'Brak układów', + 'saved' => 'Strona została zapisana poprawnie.', + 'tab' => 'Strony', + 'manage_pages' => 'Zarządzaj stronami statycznymi', + 'manage_menus' => 'Zarządzaj menu statycznymi', + 'access_snippets' => 'Fragmenty', + 'manage_content' => 'Zarządzaj treścią statyczną', + ], + 'menu' => [ + 'menu_label' => 'Menu', + 'delete_confirmation' => 'Czy na pewno chcesz usunąć wybrane menu?', + 'no_records' => 'Nie znaleziono menu', + 'new' => 'Nowe menu', + 'new_name' => 'Nowe menu', + 'new_code' => 'nowe-menu', + 'delete_confirm_single' => 'Czy na pewno chcesz usunąć wybrane menu?', + 'saved' => 'Menu zostało zapisane poprawnie.', + 'name' => 'Nazwa', + 'code' => 'Kod systemowy', + 'items' => 'Elementy menu', + 'add_subitem' => 'Dodaj element', + 'code_required' => 'Kod systemowy jest wymagany', + 'invalid_code' => 'Nieprawidłowy kod systemowy. Nie może zawierać znaków specjalnych', + ], + 'menuitem' => [ + 'title' => 'Tytuł', + 'editor_title' => 'Edytuj element', + 'type' => 'Typ', + 'allow_nested_items' => 'Pozwól na zagnieżdżanie elementów', + 'allow_nested_items_comment' => 'Zagnieżdżone elementy mogą być utworzone dynamicznie np ze stron statycznych', + 'url' => 'URL', + 'reference' => 'Referencja', + 'search_placeholder' => 'Przeszukaj wszystkie referencje...', + 'title_required' => 'Tytuł jest wymagany', + 'unknown_type' => 'Nieznany typ elementu', + 'unnamed' => 'Brak nazwy typu elementu', + 'add_item' => 'Dodaj Element', + 'new_item' => 'Nowy element menu', + 'replace' => 'Zamień element na elementy wenątrz tego elementu', + 'replace_comment' => 'Użyj tej opcji aby elementy znajdujące sie w tym elemencie były wygenerowane na poziomie tego elementu a sam element zostanie ukryty.', + 'cms_page' => 'Strona CMS', + 'cms_page_comment' => 'Wybierz stronę z cms do której ma kierować', + 'reference_required' => 'Referencja jest wymagana', + 'url_required' => 'URL jest wymagany', + 'cms_page_required' => 'Wybierz stronę z CMS', + 'display_tab' => 'Wyświetlanie', + 'hidden' => 'Ukryj', + 'hidden_comment' => 'Ukryj ten element menu na stronie', + 'attributes_tab' => 'Atrybuty', + 'code' => 'Kod systemowy', + 'code_comment' => 'Wprowadź kod systemowy aby móc go używać w API.', + 'css_class' => 'Klasa CSS', + 'css_class_comment' => 'Wprowadź klasę CSS, aby nadać temu elementowi niestandardowy wygląd', + 'external_link' => 'Zewnętrzny link', + 'external_link_comment' => 'Adres linku zostanie otworzony w nowym oknie', + 'static_page' => 'Strona statyczna', + 'all_static_pages' => 'Wszystkie strony statyczne', + ], + 'content' => [ + 'menu_label' => 'Treść', + 'cant_save_to_dir' => 'Zapis treści jest niemożliwy. Sprawdź dostęp do folderu treści statycznych.', + ], + 'sidebar' => [ + 'add' => 'Dodaj', + 'search' => 'Szukaj...', + ], + 'object' => [ + 'invalid_type' => 'Nieznany typ obiektu', + 'not_found' => 'Nie znaleziono objektu.', + ], + 'editor' => [ + 'title' => 'Tytuł', + 'new_title' => 'Nowy tytuł strony', + 'content' => 'Treść', + 'url' => 'URL', + 'filename' => 'Nazwa pliku', + 'layout' => 'Układ', + 'description' => 'Opis', + 'preview' => 'Podgląd', + 'enter_fullscreen' => 'Pełny ekran', + 'exit_fullscreen' => 'Zamknij pełny ekran', + 'hidden' => 'Ukryta', + 'hidden_comment' => 'Ukryte strony są dostępne tylko dla zalogowanych administratorów.', + 'navigation_hidden' => 'Ukryj stronę w nawigacji', + 'navigation_hidden_comment' => 'Zaznacz aby usunąć strone z automatycznego generowania menu oraz ścieżek (breadcrumbs).', + ], + 'snippet' => [ + 'partialtab' => 'Fragment', + 'code' => 'Kod systemowy', + 'code_comment' => 'Dodaj kod systemowy aby ten fragment był dostępny do użycia w treści stron statycznych.', + 'name' => 'Nazwa', + 'name_comment' => 'Nazwa będzie się wyświetlać w menu obok stron statycznych.', + 'no_records' => 'Nie znaleziono', + 'menu_label' => 'Fragmenty', + 'column_property' => 'Nazwa parametru', + 'column_type' => 'Typ', + 'column_code' => 'Kod systemowy', + 'column_default' => 'Domyślny', + 'column_options' => 'Opcje', + 'column_type_string' => 'Tekst', + 'column_type_checkbox' => 'Checkbox', + 'column_type_dropdown' => 'Lista rozwijana', + 'not_found' => 'Fragment o podanym kodzie systemowym :code nie został znaleziony.', + 'property_format_error' => 'Nazwa parametru musi się zaczynać od litery i może zawierać tylko litery oraz liczby', + 'invalid_option_key' => 'Nieprawidłowa opcja: :key. Opcja wyboru może zawierać tylko litery, cyfry, myślnik i podkreślnik', + ], + 'component' => [ + 'static_page_name' => 'Strona statyczna', + 'static_page_description' => 'Dodaje zawartość statycznej strony.', + 'static_page_use_content_name' => 'Użyj pola zawartości strony', + 'static_page_use_content_description' => 'Jeżeli odznaczone, sekcja treści nie pojawi się podczas edycji strony statycznej. Zawartość strony będzie ustalana wyłącznie na podstawie symboli zastępczych i zmiennych', + 'static_page_default_name' => 'Domyślny układ', + 'static_page_default_description' => 'Definiuje ten układ jako domyślny dla nowych stron', + 'static_page_child_layout_name' => 'Układ podstrony', + 'static_page_child_layout_description' => 'Układ, który będzie używany jako domyślny dla każdej nowej podstrony', + 'static_menu_name' => 'Menu', + 'static_menu_description' => 'Dodaje menu do strony.', + 'static_menu_code_name' => 'Menu', + 'static_menu_code_description' => 'Podaj kod systemowy menu, które ma zostać wyświetlone.', + 'static_breadcrumbs_name' => 'Okruszki (Breadcrumbs)', + 'static_breadcrumbs_description' => 'Zwraca ścieżkę stron statycznych.', + 'child_pages_name' => 'Strony podrzędne', + 'child_pages_description' => 'Wyświetla listę stron podrzędnych dla aktualnej strony', + 'static_menu_menu_code' => 'Podaj kod systemowy menu', + ], +]; \ No newline at end of file diff --git a/plugins/rainlab/pages/lang/pt-br/lang.php b/plugins/rainlab/pages/lang/pt-br/lang.php new file mode 100644 index 0000000..03b20d1 --- /dev/null +++ b/plugins/rainlab/pages/lang/pt-br/lang.php @@ -0,0 +1,115 @@ + [ + 'name' => 'Páginas', + 'description' => 'Gerenciar páginas e menus.', + ], + 'page' => [ + 'menu_label' => 'Páginas', + 'template_title' => '%s Páginas', + 'delete_confirmation' => 'Tem certeza que deseja excluir as páginas selecionadas? Todas as subpáginas também serão excluídas.', + 'no_records' => 'Nenhuma página encontrada', + 'delete_confirm_single' => 'Tem certeza que deseja excluir a página selecionada? Todas as subpáginas também serão excluídas.', + 'new' => 'Nova página', + 'add_subpage' => 'Adicionar subpágina', + 'invalid_url' => 'Formato inválido de URL. A URL deve iniciar com o símbolo / e pode conter apenas dígitos, letras latinas e os seguintes símbolos: _-/.', + 'url_not_unique' => 'Esta URL já está sendo utilizada por outra página.', + 'layout' => 'Layout', + 'layouts_not_found' => 'Nenhum layout encontrado', + 'saved' => 'Página salva com sucesso.', + 'tab' => 'Páginas', + 'manage_pages' => 'Gerenciar páginas estáticas', + 'manage_menus' => 'Gerenciar menus estáticos', + 'access_snippets' => 'Acessar fragmentos', + 'manage_content' => 'Gerenciar conteúdos estáticos' + ], + 'menu' => [ + 'menu_label' => 'Menus', + 'delete_confirmation' => 'Tem certeza que deseja excluir os menus selecionados?', + 'no_records' => 'Nenhum menu encontrado', + 'new' => 'Novo menu', + 'new_name' => 'Novo menu', + 'new_code' => 'novo-menu', + 'delete_confirm_single' => 'Tem certeza que deseja excluir este menu?', + 'saved' => 'Menu salvo com sucesso.', + 'name' => 'Nome', + 'code' => 'Código', + 'items' => 'Itens do menu', + 'add_subitem' => 'Adicionar subitem', + 'no_records' => 'Nenhum item encontrado', + 'code_required' => 'O código é necessário', + 'invalid_code' => 'Formato inválido de código. O código pode conter dígitos, letras latinas e os seguintes símbolos: _-' + ], + 'menuitem' => [ + 'title' => 'Título', + 'editor_title' => 'Editar item', + 'type' => 'Tipo', + 'allow_nested_items' => 'Permitir itens aninhados', + 'allow_nested_items_comment' => 'Itens aninhados podem ser gerados dinamicamente por páginas estáticas e outros tipos de itens', + 'url' => 'URL', + 'reference' => 'Referência', + 'title_required' => 'O título é necessário', + 'unknown_type' => 'Tipo de item desconhecido', + 'unnamed' => 'Item de menu sem nome', + 'add_item' => 'Adicionar item', + 'new_item' => 'Novo item', + 'replace' => 'Substituir este item com seus filhos gerados', + 'replace_comment' => 'Use esta opção para empurrar os itens de menu gerados para o mesmo nível que este item. Este item em si será ocultado.', + 'cms_page' => 'Página CMS', + 'cms_page_comment' => 'Selecione uma página para abrir quando o item for clicado.', + 'reference_required' => 'A referência do item é necessária.', + 'url_required' => 'A URL é necessária', + 'cms_page_required' => 'Por favor, selecione uma página CMS', + 'code' => 'Código', + 'code_comment' => 'Entre com o código do item se deseja acessar com a API.' + ], + 'content' => [ + 'menu_label' => 'Conteúdo', + 'cant_save_to_dir' => 'Não é permitido salvar arquivos de conteúdo no diretório de páginas estáticas.' + ], + 'sidebar' => [ + 'add' => 'Adicionar', + 'search' => 'Buscar...' + ], + 'object' => [ + 'invalid_type' => 'Tipo de objeto desconhecido', + 'not_found' => 'O objeto requisitado não foi encontrado.' + ], + 'editor' => [ + 'title' => 'Título', + 'new_title' => 'Título da nova página', + 'content' => 'Conteúdo', + 'url' => 'URL', + 'filename' => 'Nome do arquivo', + 'layout' => 'Layout', + 'description' => 'Descrição', + 'preview' => 'Visualizar', + 'enter_fullscreen' => 'Entrar no modo tela cheia', + 'exit_fullscreen' => 'Sair do modo tela cheia', + 'hidden' => 'Ocultar', + 'hidden_comment' => 'Páginas ocultas são acessíveis apenas para administradores.', + 'navigation_hidden' => 'Ocultar na navegação', + 'navigation_hidden_comment' => 'Marque esta opção para ocultar esta página de menus gerados automaticamente e itens de hierarquia de navegação.', + ], + 'snippet' => [ + 'partialtab' => 'Fragmentos', + 'code' => 'Código do fragmento', + 'code_comment' => 'Entre com o código para disponibilizar este bloco como um fragmento nas páginas estáticas.', + 'name' => 'Nome', + 'name_comment' => 'O nome é exibido na lista de fragmentos no menu lateral na área de páginas estáticas e nas páginas em que o fragmento é adicionado.', + 'no_records' => 'Nenhum fragmento encontrado', + 'menu_label' => 'Fragmentos', + 'column_property' => 'Título da propriedade', + 'column_type' => 'Tipo', + 'column_code' => 'Código', + 'column_default' => 'Padrão', + 'column_options' => 'Opções', + 'column_type_string' => 'Texto', + 'column_type_checkbox' => 'Caixa de seleção', + 'column_type_dropdown' => 'Caixa de seleção suspensa', + 'not_found' => 'Fragmento com o código :code não foi encontrado.', + 'property_format_error' => 'Código da propriedade deve iniciar com uma letra latina e pode conter apenas letras latinas e dígitos', + 'invalid_option_key' => 'Chave de opção inválida: %s. Chaves de opção podem conter apenas dígitos, letras latinas e os caracteres _ e -' + ] +]; diff --git a/plugins/rainlab/pages/lang/ru/lang.php b/plugins/rainlab/pages/lang/ru/lang.php new file mode 100644 index 0000000..e3e9871 --- /dev/null +++ b/plugins/rainlab/pages/lang/ru/lang.php @@ -0,0 +1,118 @@ + [ + 'name' => 'Страницы', + 'description' => 'Страницы и меню.', + ], + 'page' => [ + 'menu_label' => 'Страницы', + 'template_title' => '%s Страницы', + 'delete_confirmation' => 'Вы действительно хотите удалить выбранные страницы? Это также удалит имеющиеся подстраницы.', + 'no_records' => 'Страниц не найдено', + 'delete_confirm_single' => 'Вы действительно хотите удалить эту страницу? Это также удалит имеющиеся подстраницы.', + 'new' => 'Новая страница', + 'add_subpage' => 'Добавить подстраницу', + 'invalid_url' => 'Некорректный формат URL. URL должен начинаться с прямого слеша и может содержать цифры, латинские буквы и следующие символы: _-/.', + 'url_not_unique' => 'Это URL уже используется другой страницей.', + 'layout' => 'Шаблон', + 'layouts_not_found' => 'Шаблоны не найдены', + 'saved' => 'Страница была успешно сохранена.', + 'tab' => 'Страницы', + 'manage_pages' => 'Управление страницами', + 'manage_menus' => 'Управление меню', + 'access_snippets' => 'Доступ к сниппетами', + 'manage_content' => 'Управление содержимым', + ], + 'menu' => [ + 'menu_label' => 'Меню', + 'delete_confirmation' => 'Вы действительно хотите удалить выбранные пункты меню?', + 'no_records' => 'Меню не найдены', + 'new' => 'Новое меню', + 'new_name' => 'Новое меню', + 'new_code' => 'novoe-menyu', + 'delete_confirm_single' => 'Вы действительно хотите удалить это меню?', + 'saved' => 'Меню было успешно сохранено.', + 'name' => 'Имя', + 'code' => 'Код', + 'items' => 'Пункты меню', + 'add_subitem' => 'Добавить подменю', + 'code_required' => 'Поле Код обязательно', + 'invalid_code' => 'Некорректный формат Кода. Код может содержать цифры, латинские буквы и следующие символы: _-/', + ], + 'menuitem' => [ + 'title' => 'Название', + 'editor_title' => 'Редактировать пункт меню', + 'type' => 'Тип', + 'allow_nested_items' => 'Разрешить вложенные', + 'allow_nested_items_comment' => 'Вложенные пункты могут быть динамически сгенерированы статической страницей или другими типами элементов', + 'url' => 'URL', + 'reference' => 'Ссылка', + 'title_required' => 'Название обязательно', + 'unknown_type' => 'Неизвестный тип меню', + 'unnamed' => 'Безымянный пункт', + 'add_item' => 'Добавить пункт (i)', + 'new_item' => 'Новый пункт', + 'replace' => 'Заменять этот пункт его сгенерированными потомками', + 'replace_comment' => 'Отметьте для переноса генерируемых пунктов меню на один уровень с этим пунктом. Сам этот пункт будет скрыт.', + 'cms_page' => 'Страницы CMS', + 'cms_page_comment' => 'Выберите открываемую по клику страницу.', + 'reference_required' => 'Необходима ссылка для пункта меню.', + 'url_required' => 'Необходим URL', + 'cms_page_required' => 'Пожалуйста, выберите страницу CMS', + 'code' => 'Код', + 'code_comment' => 'Введите код пункта меню, если хотите иметь к нему доступ через API.', + ], + 'content' => [ + 'menu_label' => 'Содержимое', + 'cant_save_to_dir' => 'Сохранение файлов содержимого в директорию static-pages запрещено.', + ], + 'sidebar' => [ + 'add' => 'Добавить', + 'search' => 'Поиск...', + ], + 'object' => [ + 'invalid_type' => 'Неизвестный тип объекта', + 'not_found' => 'Запрашиваемый объект не найден.', + ], + 'editor' => [ + 'title' => 'Название', + 'new_title' => 'Название новой страницы', + 'content' => 'Содержимое', + 'url' => 'URL', + 'filename' => 'Имя Файла', + 'layout' => 'Шаблон', + 'description' => 'Описание', + 'preview' => 'Предпросмотр', + 'enter_fullscreen' => 'Войти в полноэкранный режим', + 'exit_fullscreen' => 'Выйти из полноэкранного режима', + 'hidden' => 'Скрытый', + 'hidden_comment' => 'Скрытые страницы доступны только вошедшим администраторам.', + 'navigation_hidden' => 'Спрятать в навигации', + 'navigation_hidden_comment' => 'Отметьте, чтобы скрыть эту страницу в генерируемых меню и хлебных крошках.', + ], + 'snippet' => [ + 'partialtab' => 'Сниппеты', + 'code' => 'Код сниппета', + 'code_comment' => 'Введите код, чтобы сделать этот фрагмент доступным как сниппет в расширении Страницы.', + 'name' => 'Имя', + 'name_comment' => 'Имя отображается в списке сниппетов расширения Страницы и на странице, когда сниппет добавлен.', + 'no_records' => 'Сниппеты не найдены', + 'menu_label' => 'Сниппеты', + 'column_property' => 'Название свойства', + 'column_type' => 'Тип', + 'column_code' => 'Код', + 'column_default' => 'По умолчанию', + 'column_options' => 'Опции', + 'column_type_string' => 'Строка', + 'column_type_checkbox' => 'Чекбокс', + 'column_type_dropdown' => 'Выпадающий список', + 'not_found' => 'Сниппет с запрошенным кодом %s не найден в теме.', + 'property_format_error' => 'Код свойства должен начинаться с латинской буквы и может содержать только латинские буквы и цифры', + 'invalid_option_key' => 'Некорректный ключ выпадающего списка: %s. Ключ может содержать только цифры, латинские буквы и символы _ и -', + ], + 'component' => [ + 'static_page_description' => 'Выводит страницу в CMS шаблоне.', + 'static_menu_description' => 'Выводит меню в CMS шаблоне.', + 'static_menu_menu_code' => 'Укажите код меню, которое должно быть показано', + 'static_breadcrumbs_description' => 'Выводит хлебные крошки для страницы.', + ], +]; diff --git a/plugins/rainlab/pages/lang/sk/lang.php b/plugins/rainlab/pages/lang/sk/lang.php new file mode 100644 index 0000000..8bfeb2a --- /dev/null +++ b/plugins/rainlab/pages/lang/sk/lang.php @@ -0,0 +1,141 @@ + [ + 'name' => 'Stránky', + 'description' => 'Funkcie pre správu stránok a menu.', + ], + 'page' => [ + 'menu_label' => 'Stránky', + 'template_title' => '%s Stránky', + 'delete_confirmation' => 'Naozaj chcete odstrániť vybrané stránky? Ak existujú nejaké podstránky, budú taktiež odstránené.', + 'no_records' => 'Neboli nájdené žiadne stránky', + 'delete_confirm_single' => 'Naozaj chcete odstrániť túto stránku? Ak existujú nejaké podstránky, budú taktiež odstránené.', + 'new' => 'Nová stránka', + 'add_subpage' => 'Pridať podstránku', + 'invalid_url' => 'Neplatný formát URL adresy. URL by mala začínať symbolom lomítka a môže obsahovať číslice, latinské písmená a nasledujúce znaky: _- /.', + 'url_not_unique' => 'Túto URL adresu už používa iná stránka.', + 'layout' => 'Layout', + 'layouts_not_found' => 'Žiadne layouty neboli nájdené', + 'saved' => 'Stránka bola úspešne uložená.', + 'tab' => 'Stránky', + 'manage_pages' => 'Správa stránok', + 'manage_menus' => 'Správa menu', + 'access_snippets' => 'Správa snippetov', + 'manage_content' => 'Správa obsahu', + ], + 'menu' => [ + 'menu_label' => 'Menu', + 'delete_confirmation' => 'Naozaj chcete odstrániť vybrané menu?', + 'no_records' => 'Neboli nájdené žiadne položky', + 'new' => 'Nové menu', + 'new_name' => 'Nové menu', + 'new_code' => 'nove-menu', + 'delete_confirm_single' => 'Naozaj chcete odstrániť toto menu?', + 'saved' => 'Menu bolo úspešne uložené', + 'name' => 'Názov', + 'code' => 'Kód', + 'items' => 'Položky menu', + 'add_subitem' => 'Pridať vnorenú položku', + 'code_required' => 'Pole kód je povinné.', + 'invalid_code' => 'Neplatný formát kódu. Kód môže obsahovať číslice, latinské písmená a nasledujúce znaky: _-', + ], + 'menuitem' => [ + 'title' => 'Názov', + 'editor_title' => 'Upraviť položku menu', + 'type' => 'Typ', + 'allow_nested_items' => 'Povoliť vnorené položky', + 'allow_nested_items_comment' => 'Vnorené položky môžu byť automaticky generované statickou stránkou alebo niektorými ďalšími typmi položiek', + 'url' => 'URL adresa', + 'reference' => 'Odkaz', + 'search_placeholder' => 'Prehľadať všetky odkazy...', + 'title_required' => 'Názov je povinný', + 'unknown_type' => 'Neznámy typ položky menu', + 'unnamed' => 'Nepomenovaná položka menu', + 'add_item' => 'Pridať Položku', + 'new_item' => 'Nová položka menu', + 'replace' => 'Nahradiť túto položku jej generovanými vnorenými položkami', + 'replace_comment' => 'Zaškrtnite toto pole pokiaľ si prajete vnorené položky menu posunúť na rovnakú úroveň akú má táto položka. Samotná položka zostane skrytá.', + 'cms_page' => 'CMS stránka', + 'cms_page_comment' => 'Vyberte stránku, ktorá sa má otvoriť po kliknutí na položku v menu.', + 'reference_required' => 'Odkaz na položku menu je povinný.', + 'url_required' => 'Adresa URL je povinná', + 'cms_page_required' => 'Prosím vyberte CMS stránku', + 'display_tab' => 'Zobrazenie', + 'hidden' => 'Skrytá', + 'hidden_comment' => 'Skryť túto položku menu pre celú webovú stránku.', + 'attributes_tab' => 'Vlastnosti', + 'code' => 'Kód', + 'code_comment' => 'Zadajte kód položky menu ak k nej chcete pristupovať prostredníctvom API.', + 'css_class' => 'CSS trieda', + 'css_class_comment' => 'Zadajte názov CSS triedy, ktorá sa ma aplikovať pre túto položku menu.', + 'external_link' => 'Externý odkaz', + 'external_link_comment' => 'Otvoriť odkaz tejto položky menu v novom okne.', + 'static_page' => 'Statická stránka', + 'all_static_pages' => 'Všetky statické stránky' + ], + 'content' => [ + 'menu_label' => 'Obsah', + 'cant_save_to_dir' => 'Ukladanie súborov s obsahom do adresára statických stránok nie je povolené.', + ], + 'sidebar' => [ + 'add' => 'Pridať', + 'search' => 'Hľadať...', + ], + 'object' => [ + 'invalid_type' => 'Neznámy typ objektu', + 'not_found' => 'Požadovaný objekt nebol nájdený.', + ], + 'editor' => [ + 'title' => 'Názov', + 'new_title' => 'Názov novej stránky', + 'content' => 'Obsah', + 'url' => 'URL adresa', + 'filename' => 'Názov súboru', + 'layout' => 'Layout', + 'description' => 'Popis', + 'preview' => 'Náhľad', + 'enter_fullscreen' => 'Zapnúť režim celej obrazovky', + 'exit_fullscreen' => 'Vypnúť režim celej obrazovky', + 'hidden' => 'Skrytá', + 'hidden_comment' => 'Skryté stránky sú prístupné iba prihláseným používateľom.', + 'navigation_hidden' => 'Skryť v menu', + 'navigation_hidden_comment' => 'Začiarknutím tohto poľa skryjete túto stránku z automaticky generovaných menu a navigačnej cesty.', + ], + 'snippet' => [ + 'partialtab' => 'Snippet', + 'code' => 'Kód snippetu', + 'code_comment' => 'Zadajte kód, aby táto čiastková šablóna bola dostupná ako snippet v plugine statických stránok.', + 'name' => 'Názov', + 'name_comment' => 'Tento názov sa zobrazí v zozname snippetov v bočnom menu pluginu statických stránok a priamo na stránke, keď bude snippet pridaný.', + 'no_records' => 'Neboli nájdené žiadne snippety', + 'menu_label' => 'Snippety', + 'column_property' => 'Názov vlastnosti', + 'column_type' => 'Typ', + 'column_code' => 'Kód', + 'column_default' => 'Predvolená hodnota', + 'column_options' => 'Možnosti', + 'column_type_string' => 'Reťazec', + 'column_type_checkbox' => 'Zaškrtávacie pole', + 'column_type_dropdown' => 'Rozbaľovací zoznam', + 'not_found' => 'Snippet s požadovaným kódom :code nebol nájdený v téme.', + 'property_format_error' => 'Kód vlastnosti by mal začínať latinským písmenom a môže obsahovať len latinské písmená a číslice', + 'invalid_option_key' => 'Neplatný kľúč položky rozbaľovacieho zoznamu: :key. Kľúč položky rozbaľovacieho zoznamu môže obsahovať iba písmená, číslice a znaky: _-', + ], + 'component' => [ + 'static_page_name' => 'Statická stránka', + 'static_page_description' => 'Zobrazí obsah statickej stránky', + 'static_page_use_content_name' => 'Použiť pole obsah stránky', + 'static_page_use_content_description' => 'Ak nie je začiarknuté, sekcia obsahu sa nezobrazí pri úprave statickej stránky. Obsah stránky bude určený výhradne prostredníctvom zástupcov a premenných.', + 'static_page_default_name' => 'Predvolený layout', + 'static_page_default_description' => 'Nastaví tento layout ako predvolený pre nové stránky', + 'static_page_child_layout_name' => 'Layout podstránky', + 'static_page_child_layout_description' => 'Layout ktorý sa má použiť ako predvolený pre všetky nové podstránky', + 'static_menu_name' => 'Statické menu', + 'static_menu_description' => 'Zobrazí menu na stránke', + 'static_menu_code_name' => 'Menu', + 'static_menu_code_description' => 'Zadajte kód menu, ktoré má komponent zobraziť.', + 'static_breadcrumbs_name' => 'Statická navigačná cesta', + 'static_breadcrumbs_description' => 'Zobrazí navigačnú cestu na stránke.', + ] +]; diff --git a/plugins/rainlab/pages/lang/sl/lang.php b/plugins/rainlab/pages/lang/sl/lang.php new file mode 100644 index 0000000..d15cc0e --- /dev/null +++ b/plugins/rainlab/pages/lang/sl/lang.php @@ -0,0 +1,145 @@ + [ + 'name' => 'Strani', + 'description' => 'Ustvarjanje strani in menijev.', + ], + 'page' => [ + 'menu_label' => 'Strani', + 'template_title' => '%s strani', + 'delete_confirmation' => 'Ali ste prepričani, da želite izbrisati izbrane strani? S tem boste izbrisali tudi njihove podstrani, če obstajajo.', + 'no_records' => 'Ni najdenih strani.', + 'delete_confirm_single' => 'Ali ste prepričani, da želite izbrisati to stran? S tem boste izbrisali tudi njene podstrani, če obstajajo.', + 'new' => 'Nova stran', + 'add_subpage' => 'Dodaj podstran', + 'invalid_url' => 'Neveljavna oblika URL formata. URL se mora začeti z znakom za desno poševnico in lahko vsebuje številke, latinične črke in naslednje znake: _-/.', + 'url_not_unique' => 'To URL povezavo uporablja že ena od drugih strani.', + 'layout' => 'Postavitev', + 'layouts_not_found' => 'Ni najdenih postavitev.', + 'saved' => 'Stran je bila uspešno shranjena.', + 'tab' => 'Strani', + 'manage_pages' => 'Upravljanje statičnih strani', + 'manage_menus' => 'Upravljanje statičnih menijev', + 'access_snippets' => 'Dostop do gradnikov', + 'manage_content' => 'Upravljanje statičnih vsebin', + ], + 'menu' => [ + 'menu_label' => 'Meniji', + 'delete_confirmation' => 'Ali ste prepričani, da želite izbrisati izbrane menije?', + 'no_records' => 'Ni najdenih menijev.', + 'new' => 'Nov meni', + 'new_name' => 'Nov meni', + 'new_code' => 'nov-meni', + 'delete_confirm_single' => 'Ali ste prepričani, da želite izbrisati ta meni?', + 'saved' => 'Meni je uspešno shranjen.', + 'name' => 'Ime', + 'code' => 'Koda', + 'items' => 'Elementi menija', + 'add_subitem' => 'Dodaj pod-element', + 'code_required' => 'Koda je obvezna.', + 'invalid_code' => 'Neveljaven format kode. Koda lahko vsebuje številke, latinične črke in naslednje znake: _-', + ], + 'menuitem' => [ + 'title' => 'Naslov', + 'editor_title' => 'Element menija', + 'type' => 'Vrsta', + 'allow_nested_items' => 'Dovoli gnezdene elemente', + 'allow_nested_items_comment' => 'Gnezdene elemente lahko dinamično ustvarijo statične strani in nekatere druge vrste elementov.', + 'url' => 'URL', + 'reference' => 'Referenca', + 'search_placeholder' => 'Išči po vseh referencah...', + 'title_required' => 'Naslov je obvezen', + 'unknown_type' => 'Neznana vrsta elementa menija.', + 'unnamed' => 'Neimenovan element menija.', + 'add_item' => 'Dodaj element', + 'new_item' => 'Nov element menija', + 'replace' => 'Zamenjaj ta element z njegovimi pod-elementi', + 'replace_comment' => 'Z uporabo tega kvadratka lahko potisnete ustvarjene elemente menija na njegov nivo, ob tem pa bo le-ta element postal skrit.', + 'cms_page' => 'CMS stran', + 'cms_page_comment' => 'Izberite stran, ki naj se odpre ob kliku na element menija.', + 'reference_required' => 'Referenca elementa menija je obvezna.', + 'url_required' => 'Povezava URL je obvezna.', + 'cms_page_required' => 'Prosimo, izberite CMS stran.', + 'display_tab' => 'Prikaz', + 'hidden' => 'Skrito', + 'hidden_comment' => 'Element menija na spletni strani naj ne bo prikazan.', + 'attributes_tab' => 'Atributi', + 'code' => 'Koda', + 'code_comment' => 'Vnesite kodo za element menija, če želite do njega omogočiti API dostop.', + 'css_class' => 'CSS razred', + 'css_class_comment' => 'Vnesite ime CSS razreda, če želite elementu omogočiti videz po meri.', + 'external_link' => 'Zunanja povezava', + 'external_link_comment' => 'Povezava za ta element menija naj se odpre v novem oknu.', + 'static_page' => 'Statična stran', + 'all_static_pages' => 'Vse statične strani', + ], + 'content' => [ + 'menu_label' => 'Vsebine', + 'saved' => 'Vsebina je bila uspešno shranjena.', + 'cant_save_to_dir' => 'Shranjevanje datotek z vsebino v mapo statičnih strani ni dovoljeno.', + ], + 'sidebar' => [ + 'add' => 'Dodaj', + 'search' => 'Išči...', + ], + 'object' => [ + 'invalid_type' => 'Neznana vrsta objekta', + 'unauthorized_type' => 'Nimate pooblastil za upravljanje :type objektov.', + 'not_found' => 'Zahtevanega objekta ni mogoče najti.', + ], + 'editor' => [ + 'title' => 'Naslov', + 'new_title' => 'Nov naslov strani', + 'content' => 'Vsebina', + 'url' => 'URL', + 'filename' => 'Ime datoteke', + 'layout' => 'Postavitev', + 'description' => 'Opis', + 'preview' => 'Predogled', + 'enter_fullscreen' => 'Celozaslonski način', + 'exit_fullscreen' => 'Zapri celozaslonski način', + 'hidden' => 'Skrita stran', + 'hidden_comment' => 'Skrite strani so dostopne le prijavljenim administratorjem.', + 'navigation_hidden' => 'Skrita v navigaciji', + 'navigation_hidden_comment' => 'Skrite strani v navigaciji se v menijih in povezavah ne prikažejo.', + ], + 'snippet' => [ + 'partialtab' => 'Gradniki', + 'code' => 'Koda gradnika', + 'code_comment' => 'Vnesite kodo, s katero bo ta predloga na voljo kot gradnik v vtičniku za statične strani.', + 'name' => 'Ime', + 'name_comment' => 'Ime se prikaže na seznamu gradnikov, na stranskem meniju statičnih strani in na vsebini strani, na katero je dodan gradnik.', + 'no_records' => 'Ni najdenih gradnikov.', + 'menu_label' => 'Gradniki', + 'column_property' => 'Naslov lastnosti', + 'column_type' => 'Tip', + 'column_code' => 'Koda', + 'column_default' => 'Privzeto', + 'column_options' => 'Možnosti', + 'column_type_string' => 'Niz znakov', + 'column_type_checkbox' => 'Potrditveno polje', + 'column_type_dropdown' => 'Spustni meni', + 'not_found' => 'Gradnika s kodo :code v trenutni temi ni mogoče najti.', + 'property_format_error' => 'Koda lastnosti se mora začeti z latinično črko in lahko vsebuje samo latinične črke in številke.', + 'invalid_option_key' => 'Neveljaven ključ elementa spustnega seznama: :key. Ključi lahko vsebujejo le številke, latinične črke in znaka _ ter -.', + ], + 'component' => [ + 'static_page_name' => 'Statična stran', + 'static_page_description' => 'Ustvari statično stran na CMS postavitvi.', + 'static_page_use_content_name' => 'Uporabi polje z vsebino strani', + 'static_page_use_content_description' => 'Če ni označeno, se razdelek z vsebino pri urejanju statične strani ne bo prikazal. Vsebina strani bo določena izključno prek vsebinskih okvirov in spremenljivk.', + 'static_page_default_name' => 'Privzeta postavitev', + 'static_page_default_description' => 'To postavitev definira kot privzeto za nove strani.', + 'static_page_child_layout_name' => 'Postavitev podstrani', + 'static_page_child_layout_description' => 'To postavitev definira kot privzeto za vse nove podstrani.', + 'static_menu_name' => 'Statični meni', + 'static_menu_description' => 'Ustvari meni na CMS postavitvi.', + 'static_menu_code_name' => 'Meni', + 'static_menu_code_description' => 'Določite kodo menija, ki ga mora sestaviti komponenta.', + 'static_breadcrumbs_name' => 'Statične povezave', + 'static_breadcrumbs_description' => 'Ustvari povezave za statično stran.', + 'child_pages_name' => 'Podstrani', + 'child_pages_description' => 'Prikaže seznam podstrani za trenutno stran.', + ], +]; diff --git a/plugins/rainlab/pages/lang/sv/lang.php b/plugins/rainlab/pages/lang/sv/lang.php new file mode 100644 index 0000000..8e09e33 --- /dev/null +++ b/plugins/rainlab/pages/lang/sv/lang.php @@ -0,0 +1,115 @@ + [ + 'name' => 'Sidor', + 'description' => 'Sidor & menyer.', + ], + 'page' => [ + 'menu_label' => 'Sidor', + 'template_title' => '%s Sidor', + 'delete_confirmation' => 'Vill du verkligen ta bort de valda sidorna? Detta kommer också ta bort undersidorna, ifall det finns några.', + 'no_records' => 'Inga sidor hittades', + 'delete_confirm_single' => 'Vill du verkligen ta bort den valda sidan? Detta kommer också ta bort sidans undersidor, ifall det finns några.', + 'new' => 'Ny sida', + 'add_subpage' => 'Lägg till undersida', + 'invalid_url' => 'Ogiltigt format på URL. URL:en ska börja med slash och kan innehålla siffror, latinska bokstäver och följande symboler: _-/', + 'url_not_unique' => 'Denna URL används redan av en annan sida.', + 'layout' => 'Layout', + 'layouts_not_found' => 'Layouter kan inte hittas', + 'saved' => 'Sidan har sparats.', + 'tab' => 'Sidor', + 'manage_pages' => 'Hantera statiska sidor', + 'manage_menus' => 'Hantera statiska menyer', + 'access_snippets' => 'Hantera stumpar', + 'manage_content' => 'Hantera statiskt innehåll' + ], + 'menu' => [ + 'menu_label' => 'Menyer', + 'delete_confirmation' => 'Vill du verkligen ta bort valda de menyerna?', + 'no_records' => 'Inga menyer kunde finnas', + 'new' => 'Ny meny', + 'new_name' => 'Ny meny', + 'new_code' => 'ny-meny', + 'delete_confirm_single' => 'Vill du verkligen ta bort denna menyn?', + 'saved' => 'Menyn har sparats.', + 'name' => 'Namn', + 'code' => 'Kod', + 'items' => 'Menyföremål', + 'add_subitem' => 'Lägg till underföremål', + 'no_records' => 'Inga föremål kunde finnas', + 'code_required' => 'Koden är obligatorisk', + 'invalid_code' => 'Ogiltigt kodformat. Koden kan innehålla siffror, latinska bokstäver och följande symboler: _-' + ], + 'menuitem' => [ + 'title' => 'Rubrik', + 'editor_title' => 'Redigera menyföremål', + 'type' => 'Typ', + 'allow_nested_items' => 'Tillåt underliggande föremål', + 'allow_nested_items_comment' => 'Underliggande föremål kan skapas dynamiskt av en etatisk sida och några andra föremålstyper', + 'url' => 'URL', + 'reference' => 'Referens', + 'title_required' => 'Rubriken är obligatorisk', + 'unknown_type' => 'Okänd menyföremålstyp', + 'unnamed' => 'Namnlöst menyföremål', + 'add_item' => 'Lägg till föremål', + 'new_item' => 'Nytt menyföremål', + 'replace' => 'Ersätt detta föremål med dens skapade underföremål', + 'replace_comment' => 'Använd denna kryssruta för att föra skapade menyföremål till samma nivå som detta föremålet. Detta föremålet kommer att gömmas.', + 'cms_page' => 'CMS-sida', + 'cms_page_comment' => 'Välj en sida som ska öppnas när menyföremålet klickas.', + 'reference_required' => 'Menyföremålets referens är obligatorisk.', + 'url_required' => 'URL:en är obligatorisk', + 'cms_page_required' => 'Vänligen välj en CMS-sida', + 'code' => 'Kod', + 'code_comment' => 'Fyll i menyföremålets kod om du vill få tillgång till det i API:t.' + ], + 'content' => [ + 'menu_label' => 'Innehåll', + 'cant_save_to_dir' => 'Att sparar innehållsfiler till mappen för statiska sidor är inte tillåtet.' + ], + 'sidebar' => [ + 'add' => 'Lägg till', + 'search' => 'Sök...' + ], + 'object' => [ + 'invalid_type' => 'Ogiltig objekttyp', + 'not_found' => 'Det begärda objektet kunde inte finnas.' + ], + 'editor' => [ + 'title' => 'Rubrik', + 'new_title' => 'Ny sidrubrik', + 'content' => 'Innehåll', + 'url' => 'URL', + 'filename' => 'Filnamn', + 'layout' => 'Layout', + 'description' => 'Beskrivning', + 'preview' => 'Förhandsgranska', + 'enter_fullscreen' => 'Gå in i fullskärmsläge', + 'exit_fullscreen' => 'Gå ut ur fullskärmsläge', + 'hidden' => 'Gömd', + 'hidden_comment' => 'Gömda sidor är bara tillgängliga för inloggande back-endanvändare.', + 'navigation_hidden' => 'Göm i navigation', + 'navigation_hidden_comment' => 'Fyll i denna rutan för att gömma sidan från automatiskt skapade menyer och sökvägar.', + ], + 'snippet' => [ + 'partialtab' => 'Stump', + 'code' => 'Stumpkod', + 'code_comment' => 'Skriv in en kod som gör att denna sidurklipp är tillgänglig som en stump i tillägget för statiska sidor.', + 'name' => 'Namn', + 'name_comment' => 'Namnet visas i listan med stumpar i sidopanelen och på en sida när stumpen är tillagd.', + 'no_records' => 'Inga stumpar hittades', + 'menu_label' => 'Stumpar', + 'column_property' => 'Egenskapsrubrik', + 'column_type' => 'Typ', + 'column_code' => 'Kod', + 'column_default' => 'Standard', + 'column_options' => 'Alternativ', + 'column_type_string' => 'Sträng', + 'column_type_checkbox' => 'Kryssruta', + 'column_type_dropdown' => 'Rullgardinsmeny', + 'not_found' => 'En stump med den begärda koden :code kunde inte hittas i temat.', + 'property_format_error' => 'Egenskapskoden ska börja med en latisk bokstav kan bara innehålla latinska bokstäver samt siffror', + 'invalid_option_key' => 'Nyckeln: %s, i Rullgardinsmenyn är ogiltig. Alternativnycklarna kan bara innehålla siffror, latinska bokstäver och karaktärerna _ samt -' + ] +]; diff --git a/plugins/rainlab/pages/lang/tr/lang.php b/plugins/rainlab/pages/lang/tr/lang.php new file mode 100644 index 0000000..6f0be12 --- /dev/null +++ b/plugins/rainlab/pages/lang/tr/lang.php @@ -0,0 +1,141 @@ + [ + 'name' => 'Sayfalar', + 'description' => 'Sayfalar & menüler modülü.', + ], + 'page' => [ + 'menu_label' => 'Sayfalar', + 'template_title' => '%s Sayfalar', + 'delete_confirmation' => 'Seçili sayfaları silmek istiyor musunuz? Alt sayfalar da silinecektir.', + 'no_records' => 'Sayfa bulunamadı', + 'delete_confirm_single' => 'Bu sayfayı silmek istiyor musunuz? Alt sayfalar da silinecektir', + 'new' => 'Yeni sayfa', + 'add_subpage' => 'Altsayfa ekle', + 'invalid_url' => 'Geçersiz URL formatı. URL eğik çizgi sembolü ile başlamalıdır ve rakam, latin harfleri ve bu sembolleri: _-/. içerebilir.', + 'url_not_unique' => 'Bu URL başka bir sayfa tarafından kullanılıyor', + 'layout' => 'Şablon', + 'layouts_not_found' => 'Şablon bulunamadı', + 'saved' => 'Sayfa başarıyla kaydedildi.', + 'tab' => 'Sayfalar', + 'manage_pages' => 'Sayfaları yönetebilsin', + 'manage_menus' => 'Menüleri yönetebilsin', + 'access_snippets' => 'Snippetleri yönetebilsin', + 'manage_content' => 'Sabit içerikleri yönetebilsin', + ], + 'menu' => [ + 'menu_label' => 'Menüler', + 'delete_confirmation' => 'Seçili menüleri silmek istiyor musunuz?', + 'no_records' => 'Menü bulunamadı', + 'new' => 'Yeni Menü', + 'new_name' => 'Yeni menü', + 'new_code' => 'yeni-menu', + 'delete_confirm_single' => 'Bu menüyü silmek istiyor musunuz?', + 'saved' => 'Menü başarıyla kaydedildi.', + 'name' => 'İsim', + 'code' => 'Kod', + 'items' => 'Menü Ögeleri', + 'add_subitem' => 'Altöge ekle', + 'code_required' => 'Kod gerekli', + 'invalid_code' => 'Geçersiz KOD formatı. Kod yalnızca rakam, Latin harfleri ve bu sembolleri: _- içerebilir.', + ], + 'menuitem' => [ + 'title' => 'Başlık', + 'editor_title' => 'Menü Ögesini Düzenle', + 'type' => 'Tür', + 'allow_nested_items' => 'İçiçe ögelere izin ver', + 'allow_nested_items_comment' => 'İç içe öğeler statik sayfa ve bazı diğer öğe türlerine göre dinamik olarak üretilen olabilir', + 'url' => 'URL', + 'reference' => 'Referans', + 'search_placeholder' => 'Referansları ara...', + 'title_required' => 'Başlık gerekli', + 'unknown_type' => 'Geçersiz menü ögesi türü', + 'unnamed' => 'İsimsiz menü ögesi', + 'add_item' => 'Öge Ekle', + 'new_item' => 'Yeni menü ögesi', + 'replace' => 'Bu ögeyi oluşturulan çocuklarıyla değiştir', + 'replace_comment' => 'Use this checkbox to push generated menu items to the same level with this item. This item itself will be hidden.', + 'cms_page' => 'CMS Sayfası', + 'cms_page_comment' => 'Menü ögesine tıklandığında açılacak sayfayı seçin', + 'reference_required' => 'Menü ögesi referansı gereklidir.', + 'url_required' => 'URL gereklidir', + 'cms_page_required' => 'Lütfen bir CMS sayfası seçin', + 'display_tab' => 'Görünüm', + 'hidden' => 'Gizli', + 'hidden_comment' => 'Bu menüyü önyüzde gizle.', + 'attributes_tab' => 'Öznitellikler', + 'code' => 'Kod', + 'code_comment' => 'API ile giriş yapabilmek için menü ögesi kodunu girin.', + 'css_class' => 'CSS Class', + 'css_class_comment' => 'Bu menüye özel bir görünüm vermek için bir CSS sınıfı adı girin.', + 'external_link' => 'Dış link', + 'external_link_comment' => 'Bu menü için bağlantıları yeni sekmede aç.', + 'static_page' => 'Sayfa', + 'all_static_pages' => 'Tüm sayfalar', + ], + 'content' => [ + 'menu_label' => 'İçerik', + 'cant_save_to_dir' => 'Statik sayfalar dizinine içerik dosyalarını kaydetme izni verilmez.', + ], + 'sidebar' => [ + 'add' => 'Ekle', + 'search' => 'Ara...', + ], + 'object' => [ + 'invalid_type' => 'Bilineyen nesne türü', + 'not_found' => 'İstenen nesne bulunamadı', + ], + 'editor' => [ + 'title' => 'Başlık', + 'new_title' => 'Yeni sayfa başlığı', + 'content' => 'İçerik', + 'url' => 'URL', + 'filename' => 'Dosya Adı', + 'layout' => 'Layout', + 'description' => 'Tanımlama', + 'preview' => 'Önizleme', + 'enter_fullscreen' => 'Tam Ekran moduna geç', + 'exit_fullscreen' => 'Tam Ekran modundan çık', + 'hidden' => 'Gizli', + 'hidden_comment' => 'Gizli sayfalar yalnızca yönetim paneline giriş yapmış kullanıcılar tarafından görüntülenebilir.', + 'navigation_hidden' => 'Menüde Gizle', + 'navigation_hidden_comment' => 'Otomatik olarak oluşturulan menüler ve kırıntıları gizlemek için bu kutuyu işaretleyin.', + ], + 'snippet' => [ + 'partialtab' => 'Snippet', + 'code' => 'Snippet kodu', + 'code_comment' => 'Sayfalar eklentisinde snippet olarak kullanabilmek için bir kod tanımlayın.', + 'name' => 'İsim', + 'name_comment' => 'Sol snippet listesinde görüntülenecek ismi girin.', + 'no_records' => 'Snippet bulunamadı', + 'menu_label' => 'Snippetlar', + 'column_property' => 'Property başlığı', + 'column_type' => 'Tip', + 'column_code' => 'Kod', + 'column_default' => 'Ön tanımlı (default)', + 'column_options' => 'Seçenekler (options)', + 'column_type_string' => 'Metin (string)', + 'column_type_checkbox' => 'Seçmeli (checkbox)', + 'column_type_dropdown' => 'Açılır liste (dropdown)', + 'not_found' => 'Tema için :code kodu ile istenilen snippet bulunamadı.', + 'property_format_error' => 'Kod sadece latin karakterle başlamalı ve latin karakter veya sayı içermelidir', + 'invalid_option_key' => 'Seçenek key i geçersiz: :key. Seçenek keyleri sadece sayı, Latin harfler ve karakter _ ve - içerebilir', + ], + 'component' => [ + 'static_page_name' => 'Sabit sayfa', + 'static_page_description' => 'CMS bölümüne sabit sayfa içeriği ekler.', + 'static_page_use_content_name' => 'Sayfa içeriği alanını kullan', + 'static_page_use_content_description' => 'Seçilmezse, statik sayfa düzenlenirken içerik bölümü görünmez. Sayfa içeriği yalnızca placeholderlar ve değişkenler aracılığıyla belirlenir.', + 'static_page_default_name' => 'Varsayılan şablon', + 'static_page_default_description' => 'Bu şablonu yeni sayfalar için varsayılan olarak tanımlar.', + 'static_page_child_layout_name' => 'Alt sayfa şablobu', + 'static_page_child_layout_description' => 'Yeni alt sayfalar için varsayılan olarak kullanılacak şablon', + 'static_menu_name' => 'Statik (sabit) menü', + 'static_menu_description' => 'CMS bölümüne sabit menü içeriği ekler.', + 'static_menu_code_name' => 'Menü', + 'static_menu_code_description' => 'Component in göstereceği menünün kodunu belirtin.', + 'static_breadcrumbs_name' => 'Sabit breadcrumbs', + 'static_breadcrumbs_description' => 'Sabit sayfaya breadcrumbs ekler.', + ], +]; diff --git a/plugins/rainlab/pages/lang/uk/lang.php b/plugins/rainlab/pages/lang/uk/lang.php new file mode 100644 index 0000000..3434229 --- /dev/null +++ b/plugins/rainlab/pages/lang/uk/lang.php @@ -0,0 +1,118 @@ + [ + 'name' => 'Сторінки', + 'description' => 'Сторінки і меню.', + ], + 'page' => [ + 'menu_label' => 'Сторінки', + 'template_title' => '%s Сторінки', + 'delete_confirmation' => 'Ви дійсно хочете видалити вибрані сторінки? Це також видалить наявні підсторінки.', + 'no_records' => 'Сторінок не знайдено', + 'delete_confirm_single' => 'Ви дійсно хочете видалити цю сторінку? Це також видалить наявні підсторінки.', + 'new' => 'Нова сторінка', + 'add_subpage' => 'Додати підсторінку', + 'invalid_url' => 'Некоректний формат URL. URL повинен починатися з прямого слеша і може містити цифри, латинські літери і такі символи: _-/.', + 'url_not_unique' => 'Цей URL вже використовується іншою сторінкою.', + 'layout' => 'Шаблон', + 'layouts_not_found' => 'Шаблони не знайдені', + 'saved' => 'Сторінка була успішно збережена.', + 'tab' => 'Сторінки', + 'manage_pages' => 'Управління сторінками', + 'manage_menus' => 'Управління меню', + 'access_snippets' => 'Доступ до сніппетів', + 'manage_content' => 'Управління змістом', + ], + 'menu' => [ + 'menu_label' => 'Меню', + 'delete_confirmation' => 'Ви дійсно хочете видалити вибрані пункти меню?', + 'no_records' => 'Меню не знайдені', + 'new' => 'Нове меню', + 'new_name' => 'Новое меню', + 'new_code' => 'nove-menu', + 'delete_confirm_single' => 'Ви дійсно хочете видалити це меню?', + 'saved' => 'Меню було успішно збережено.', + 'name' => "Ім`я", + 'code' => 'Код', + 'items' => 'Пункти меню', + 'add_subitem' => 'Додати підменю', + 'code_required' => "Поле Код обов'язкове", + 'invalid_code' => 'Некоректний формат Коду. Код може містити цифри, латинські літери і такі символи: _-/', + ], + 'menuitem' => [ + 'title' => 'Назва', + 'editor_title' => 'Редагувати пункт меню', + 'type' => 'Тип', + 'allow_nested_items' => 'Дозволити вкладені', + 'allow_nested_items_comment' => 'Вкладені пункти можуть бути динамічно згенеровані статичною сторінкою або іншими типами елементів', + 'url' => 'URL', + 'reference' => 'Посилання', + 'title_required' => "Назва обов'язково", + 'unknown_type' => 'Невідомий тип меню', + 'unnamed' => 'Безіменний пункт', + 'add_item' => 'Додати пункт ( i )', + 'new_item' => 'Новий пункт', + 'replace' => 'Замінювати цей пункт його згенеруванними нащадками', + 'replace_comment' => 'Відмітьте для перенесення згенерованних пунктів меню на один рівень з цим пунктом. Сам цей пункт буде приховано.', + 'cms_page' => 'Сторінки CMS', + 'cms_page_comment' => 'Оберіть відкриваючу при натисканні сторінку.', + 'reference_required' => 'Необхідне посилання для пункту меню.', + 'url_required' => 'Необхідний URL', + 'cms_page_required' => 'Будь ласка, виберіть сторінку CMS', + 'code' => 'Код', + 'code_comment' => 'Введіть код пункту меню, якщо хочете мати до нього доступ через API.', + ], + 'content' => [ + 'menu_label' => 'Зміст', + 'cant_save_to_dir' => 'Збереження файлів змісту в директорію static-pages заборонено.', + ], + 'sidebar' => [ + 'Add' => 'Додати', + 'search' => 'Пошук...', + ], + 'object' => [ + 'invalid_type' => "Невідомий тип об'єкту", + 'not_found' => "Запитуваний об'єкт не знайдено.", + ], + 'editor' => [ + 'title' => 'Назва', + 'new_title' => 'Назва нової сторінки', + 'content' => 'Зміст', + 'url' => 'URL', + 'filename' => "Ім'я файлу", + 'layout' => 'Шаблон', + 'description' => 'Опис', + 'preview' => 'Попередній огляд', + 'enter_fullscreen' => 'Увійти в повноекранний режим', + 'exit_fullscreen' => 'Вийти з повноекранного режиму', + 'hidden' => 'Прихований', + 'hidden_comment' => 'Приховані сторінки доступні тільки увійшовшим адміністраторам.', + 'navigation_hidden' => 'Сховати в навігації', + 'navigation_hidden_comment' => 'Відмітьте, щоб приховати цю сторінку в генеруючих меню і хлібних крихтах.', + ], + 'snippet' => [ + 'partialtab' => 'Сніппети', + 'code' => 'Код сніппета', + 'code_comment' => 'Введіть код, щоб зробити цей фрагмент доступним як сніппет в розширенні Сторінки.', + 'name' => "Ім'я", + 'name_comment' => "Ім'я відображається в списку фрагментів розширення Сторінки і на сторінці, коли сніппет доданий.", + 'no_records' => 'Сніппети не знайдені', + 'menu_label' => 'Сніппети', + 'column_property' => 'Назва властивості', + 'column_type' => 'Тип', + 'column_code' => 'Код', + 'column_default' => 'За замовчуванням', + 'column_options' => 'Опції', + 'column_type_string' => 'Рядок', + 'column_type_checkbox' => 'Чекбокс', + 'column_type_dropdown' => 'Список, що випадає', + 'not_found' => 'Сніппет з запитаним кодом %s не знайдений в темі.', + 'property_format_error' => 'Код властивості повинен починатися з літери та може містити тільки латинські букви і цифри', + 'invalid_option_key' => 'Неправильний ключ списку: %s. Ключ може містити тільки цифри, латинські літери і символи _ і -', + ], + 'component' => [ + 'static_page_description' => 'Виводити сторінку в CMS шаблоні.', + 'static_menu_description' => 'Виводити меню в CMS шаблоні.', + 'static_menu_menu_code' => 'Вкажіть код меню, яке повинно бути показано', + 'static_breadcrumbs_description' => 'Виводити хлібні крихти для сторінки.', + ], +]; diff --git a/plugins/rainlab/pages/lang/zh-cn/lang.php b/plugins/rainlab/pages/lang/zh-cn/lang.php new file mode 100644 index 0000000..0caa473 --- /dev/null +++ b/plugins/rainlab/pages/lang/zh-cn/lang.php @@ -0,0 +1,132 @@ + [ + 'name' => '页面', + 'description' => '页面和菜单功能拓展', + ], + 'page' => [ + 'menu_label' => '页面', + 'template_title' => '%s 页面', + 'delete_confirmation' => '你真的要删除所选页面吗? 如果有子页面,也将被删除。', + 'no_records' => '找不到页面', + 'delete_confirm_single' => '你真的要删除这个页面吗? 如果有子页面,也将被删除。', + 'new' => '新建', + 'add_subpage' => '插入子页面', + 'invalid_url' => 'URL 格式无效,应以 \'/\' 开头,可以包含数字,字母和以下符号:_-/', + 'url_not_unique' => 'URL 已存在', + 'layout' => '布局', + 'layouts_not_found' => '找不到布局文件', + 'saved' => '保存成功!', + 'tab' => '页面', + 'manage_pages' => '管理静态页面', + 'manage_menus' => '管理静态菜单', + 'access_snippets' => '代码片段', + 'manage_content' => '管理静态内容', + ], + 'menu' => [ + 'menu_label' => '菜单', + 'delete_confirmation' => '你真的要删除所选菜单吗?', + 'no_records' => '找不到菜单', + 'new' => '新建', + 'new_name' => '未命名的菜单', + 'new_code' => 'new-menu', + 'delete_confirm_single' => '你真的要删除这个菜单吗?', + 'saved' => '保存成功!', + 'name' => '名称', + 'code' => '编码', + 'items' => '菜单项', + 'add_subitem' => '插入子项', + 'code_required' => '编码是必要的!', + 'invalid_code' => '编码格式无效,该编码可以包含数字,字母和以下符号:_-', + ], + 'menuitem' => [ + 'title' => '标题', + 'editor_title' => '编辑菜单项', + 'type' => '类型', + 'allow_nested_items' => '允许嵌套', + 'allow_nested_items_comment' => '嵌套项目可以通过静态页面和其他一些项目类型动态生成', + 'url' => 'URL', + 'reference' => '参考', + 'search_placeholder' => '搜索所有参考...', + 'title_required' => '标题是必需的', + 'unknown_type' => '未知的菜单项类型', + 'unnamed' => '未命名的菜单项', + 'add_item' => '掺入菜单项I', + 'new_item' => '新菜单项', + 'replace' => '将此项目替换为生成的子项', + 'replace_comment' => '使用此复选框产生的菜单项推到与本项目同一层级。 该项目本身将被隐藏。', + 'cms_page' => 'CMS 页面', + 'cms_page_comment' => '当单击菜单项时,选择要打开的页面。', + 'reference_required' => '菜单项参考 是必需的。', + 'url_required' => 'URL 是必需的。', + 'cms_page_required' => '请选择 CMS 页面', + 'code' => '编码', + 'code_comment' => '如果要使用 API 访问菜单项代码,请输入。', + 'static_page' => '静态页面', + 'all_static_pages' => '所有静态页' + ], + 'content' => [ + 'menu_label' => '内容', + 'cant_save_to_dir' => '将内容文件保存到 \'static-pages\' 目录是不允许的。', + ], + 'sidebar' => [ + 'add' => '插入', + 'search' => '检索...', + ], + 'object' => [ + 'invalid_type' => '未知的对象类型', + 'not_found' => '找不到请求的对象。', + ], + 'editor' => [ + 'title' => '标题', + 'new_title' => '未命名', + 'content' => '内容', + 'url' => 'URL', + 'filename' => '文件名', + 'layout' => '布局', + 'description' => '描述', + 'preview' => '预览', + 'enter_fullscreen' => '全屏编辑', + 'exit_fullscreen' => '退出全屏', + 'hidden' => '隐藏', + 'hidden_comment' => '隐藏的页面只能由登录的后台用户访问。', + 'navigation_hidden' => '在导航中隐藏', + 'navigation_hidden_comment' => '选中此框可将该页面在自动生成的菜单和面包屑导航中隐藏起来。', + ], + 'snippet' => [ + 'partialtab' => 'Snippet', + 'code' => 'Snippet code', + 'code_comment' => '输入一个代码,使其部分可用作“静态页面”插件中的代码段。', + 'name' => '名称', + 'name_comment' => '该名称显示在“静态页面”侧边栏的代码段列表中,并在添加代码段时显示在该页面上。', + 'no_records' => '找不到代码片段', + 'menu_label' => '代码片段', + 'column_property' => '性质', + 'column_type' => '类型', + 'column_code' => '编码', + 'column_default' => '默认', + 'column_options' => '选项', + 'column_type_string' => '字符串', + 'column_type_checkbox' => '检查框', + 'column_type_dropdown' => '下拉框', + 'not_found' => '代码段与请求的 code:code 没有在主题中找到。', + 'property_format_error' => '属性代码应以字母开头,只能包含字母和数字', + 'invalid_option_key' => '无效的下拉选项 key: :key。 选项键只能包含数字,字母和字符 _ 和 -', + ], + 'component' => [ + 'static_page_name' => '静态页', + 'static_page_description' => '在 CMS 布局中输出静态页。', + 'static_page_use_content_name' => '使用页面内容字段', + 'static_page_use_content_description' => '如果未选中,编辑静态页面时内容部分将不会出现。 页面内容将仅通过占位符和变量来确定。', + 'static_page_default_name' => '默认布局', + 'static_page_default_description' => '将此布局定义为新页面的默认设置', + 'static_page_child_layout_name' => '子页面布局', + 'static_page_child_layout_description' => '该布局用作任何新子页面的默认布局', + 'static_menu_name' => '静态菜单', + 'static_menu_description' => '输出 CMS 布局中的菜单。', + 'static_menu_code_name' => '菜单', + 'static_menu_code_description' => '指定组件应输出的菜单代码。', + 'static_breadcrumbs_name' => '静态面包屑导航', + 'static_breadcrumbs_description' => '输出静态页面的面包屑导航。', + ] +]; diff --git a/plugins/rainlab/pages/rainlab-pages.mix.js b/plugins/rainlab/pages/rainlab-pages.mix.js new file mode 100644 index 0000000..6d1227d --- /dev/null +++ b/plugins/rainlab/pages/rainlab-pages.mix.js @@ -0,0 +1,15 @@ +/* + |-------------------------------------------------------------------------- + | Mix Asset Management + |-------------------------------------------------------------------------- + | + | Mix provides a clean, fluent API for defining some Webpack build steps + | for your theme assets. By default, we are compiling the CSS + | file for the application as well as bundling up all the JS files. + | + */ + +module.exports = (mix) => { + mix.less('plugins/rainlab/pages/assets/less/pages.less', 'plugins/rainlab/pages/assets/css/'); + mix.less('plugins/rainlab/pages/assets/less/treeview.less', 'plugins/rainlab/pages/assets/css/'); +} diff --git a/plugins/rainlab/pages/updates/snippets_rename_viewbag_properties.php b/plugins/rainlab/pages/updates/snippets_rename_viewbag_properties.php new file mode 100644 index 0000000..cdca387 --- /dev/null +++ b/plugins/rainlab/pages/updates/snippets_rename_viewbag_properties.php @@ -0,0 +1,34 @@ +all(); + foreach ($partials as $partial) { + try { + $path = $partial->getFilePath(); + $contents = File::get($path); + if (strpos($contents, 'staticPageSnippetCode') === false) continue; + $contents = str_replace('staticPageSnippetName', 'snippetName', $contents); + $contents = str_replace('staticPageSnippetCode', 'snippetCode', $contents); + $contents = str_replace('staticPageSnippetProperties', 'snippetProperties', $contents); + File::put($path, $contents); + } + catch (\Exception $ex) { continue; } + } + } + } + + public function down() + { + } +} diff --git a/plugins/rainlab/pages/updates/version.yaml b/plugins/rainlab/pages/updates/version.yaml new file mode 100644 index 0000000..389493b --- /dev/null +++ b/plugins/rainlab/pages/updates/version.yaml @@ -0,0 +1,75 @@ +v1.0.1: Implemented the static pages management and the Static Page component. +v1.0.2: Fixed the page preview URL. +v1.0.3: Implemented menus. +v1.0.4: Implemented the content block management and placeholder support. +v1.0.5: Added support for the Sitemap plugin. +v1.0.6: Minor updates to the internal API. +v1.0.7: Added the Snippets feature. +v1.0.8: Minor improvements to the code. +v1.0.9: Fixes issue where Snippet tab is missing from the Partials form. +v1.0.10: Add translations for various locales. +v1.0.11: Fixes issue where placeholders tabs were missing from Page form. +v1.0.12: Implement Media Manager support. +v1.1.0: + - Adds meta title and description to pages. Adds |staticPage filter. + - snippets_rename_viewbag_properties.php +v1.1.1: Add support for Syntax Fields. +v1.1.2: Static Breadcrumbs component now respects the hide from navigation setting. +v1.1.3: Minor back-end styling fix. +v1.1.4: Minor fix to the StaticPage component API. +v1.1.5: Fixes bug when using syntax fields. +v1.1.6: Minor styling fix to the back-end UI. +v1.1.7: Improved menu item form to include CSS class, open in a new window and hidden flag. +v1.1.8: Improved the output of snippet partials when saved. +v1.1.9: Minor update to snippet inspector internal API. +v1.1.10: Fixes a bug where selecting a layout causes permanent unsaved changes. +v1.1.11: Add support for repeater syntax field. +v1.2.0: Added support for translations, UI updates. +v1.2.1: Use nice titles when listing the content files. +v1.2.2: Minor styling update. +v1.2.3: Snippets can now be moved by dragging them. +v1.2.4: Fixes a bug where the cursor is misplaced when editing text files. +v1.2.5: Fixes a bug where the parent page is lost upon changing a page layout. +v1.2.6: Shared view variables are now passed to static pages. +v1.2.7: Fixes issue with duplicating properties when adding multiple snippets on the same page. +v1.2.8: Fixes a bug where creating a content block without extension doesn't save the contents to file. +v1.2.9: Add conditional support for translating page URLs. +v1.2.10: Streamline generation of URLs to use the new Cms::url helper. +v1.2.11: Implements repeater usage with translate plugin. +v1.2.12: Fixes minor issue when using snippets and switching the application locale. +v1.2.13: Fixes bug when AJAX is used on a page that does not yet exist. +v1.2.14: Add theme logging support for changes made to menus. +v1.2.15: Back-end navigation sort order updated. +v1.2.16: Fixes a bug when saving a template that has been modified outside of the CMS (mtime mismatch). +v1.2.17: Changes locations of custom fields to secondary tabs instead of the primary Settings area. New menu search ability on adding menu items +v1.2.18: Fixes cache-invalidation issues when RainLab.Translate is not installed. Added Greek & Simplified Chinese translations. Removed deprecated calls. Allowed saving HTML in snippet properties. Added support for the MediaFinder in menu items. +v1.2.19: Catch exception with corrupted menu file. +v1.2.20: StaticMenu component now exposes menuName property; added pages.menu.referencesGenerated event. +v1.2.21: Fixes a bug where last Static Menu item cannot be deleted. Improved Persian, Slovak and Turkish translations. +v1.3.0: Added support for using Database-driven Themes when enabled in the CMS configuration. +v1.3.1: Added ChildPages Component, prevent hidden pages from being returned via menu item resolver. +v1.3.2: Fixes error when creating a subpage whose parent has no layout set. +v1.3.3: Improves user experience for users with only partial access through permissions +v1.3.4: Fix error where large menus were being truncated due to the PHP "max_input_vars" configuration value. Improved Slovenian translation. +v1.3.5: Minor fix to bust the browser cache for JS assets. Prevent duplicate property fields in snippet inspector. +v1.3.6: ChildPages component now displays localized page titles from Translate plugin. +v1.3.7: Adds MenuPicker formwidget. Adds future support for v2.0 of October CMS. +v1.4.0: Fixes bug when adding menu items in October CMS v2.0. +v1.4.1: Fixes support for configuration values. +v1.4.3: Fixes page deletion is newer platform builds. +v1.4.4: Disable touch device detection +v1.4.5: Minor styling improvements +v1.4.6: Minor styling improvements +v1.4.7: Minor layout fix in the Page editor +v1.4.8: Fixes rich editor usage inside repeaters. Adds getProcessedMarkup event. +v1.4.9: Fixes a lifecycle issue when switching the page layout. +v1.4.10: Fixes maintenance mode when using static pages. +v1.4.11: Adds type hidden to content placeholders. +v1.4.12: Improve support with October v2.2 +v1.5.0: Improve support with October v3.0 +v1.5.4: Compatibility updates +v1.5.5: Fixes media finder added to menu in October v2 +v1.5.6: Fixes concurrency save form in October v3 +v1.5.7: Adds page finder support for October v3.2 +v1.5.8: Fixes resolving links used in static pages +v1.5.9: Fixes fancy layout with nested forms diff --git a/plugins/rainlab/pages/widgets/MenuList.php b/plugins/rainlab/pages/widgets/MenuList.php new file mode 100644 index 0000000..ccef3ef --- /dev/null +++ b/plugins/rainlab/pages/widgets/MenuList.php @@ -0,0 +1,122 @@ +alias = $alias; + $this->theme = Theme::getEditTheme(); + $this->dataIdPrefix = 'page-'.$this->theme->getDirName(); + + parent::__construct($controller, []); + $this->bindToController(); + } + + /** + * Renders the widget. + * @return string + */ + public function render() + { + return $this->makePartial('body', [ + 'data' => $this->getData() + ]); + } + + // + // Event handlers + // + + public function onUpdate() + { + $this->extendSelection(); + + return $this->updateList(); + } + + public function onSearch() + { + $this->setSearchTerm(Input::get('search')); + $this->extendSelection(); + + return $this->updateList(); + } + + // + // Methods for the internal use + // + + protected function getData() + { + $menus = Menu::listInTheme($this->theme, true); + + $searchTerm = Str::lower($this->getSearchTerm()); + + if (strlen($searchTerm)) { + $words = explode(' ', $searchTerm); + $filteredMenus = []; + + foreach ($menus as $menu) { + if ($this->textMatchesSearch($words, $menu->name.' '.$menu->fileName)) { + $filteredMenus[] = $menu; + } + } + + $menus = $filteredMenus; + } + + return $menus; + } + + protected function updateList() + { + $vars = ['items' => $this->getData()]; + return ['#'.$this->getId('menu-list') => $this->makePartial('items', $vars)]; + } + + protected function getThemeSessionKey($prefix) + { + return $prefix . $this->theme->getDirName(); + } + + protected function getSession($key = null, $default = null) + { + $key = strlen($key) ? $this->getThemeSessionKey($key) : $key; + + return parent::getSession($key, $default); + } + + protected function putSession($key, $value) + { + return parent::putSession($this->getThemeSessionKey($key), $value); + } +} diff --git a/plugins/rainlab/pages/widgets/PageList.php b/plugins/rainlab/pages/widgets/PageList.php new file mode 100644 index 0000000..2ae2c41 --- /dev/null +++ b/plugins/rainlab/pages/widgets/PageList.php @@ -0,0 +1,165 @@ +alias = $alias; + $this->theme = Theme::getEditTheme(); + $this->dataIdPrefix = 'page-'.$this->theme->getDirName(); + + parent::__construct($controller, []); + $this->bindToController(); + } + + /** + * Renders the widget. + * @return string + */ + public function render() + { + return $this->makePartial('body', [ + 'data' => $this->getData() + ]); + } + + /* + * Event handlers + */ + + public function onReorder() + { + $structure = json_decode(Input::get('structure'), true); + if (!$structure) { + throw new SystemException('Invalid structure data posted.'); + } + + $pageList = new StaticPageList($this->theme); + $pageList->updateStructure($structure); + } + + public function onUpdate() + { + $this->extendSelection(); + + return $this->updateList(); + } + + public function onSearch() + { + $this->setSearchTerm(Input::get('search')); + $this->extendSelection(); + + return $this->updateList(); + } + + /* + * Methods for internal use + */ + + protected function getData() + { + $pageList = new StaticPageList($this->theme); + $pages = $pageList->getPageTree(true); + + $searchTerm = Str::lower($this->getSearchTerm()); + + if (strlen($searchTerm)) { + $words = explode(' ', $searchTerm); + + $iterator = function($pages) use (&$iterator, $words) { + $result = []; + + foreach ($pages as $page) { + if ($this->textMatchesSearch($words, $this->subtreeToText($page))) { + $result[] = (object) [ + 'page' => $page->page, + 'subpages' => $iterator($page->subpages) + ]; + } + } + + return $result; + }; + + $pages = $iterator($pages); + } + + return $pages; + } + + protected function getThemeSessionKey($prefix) + { + return $prefix.$this->theme->getDirName(); + } + + protected function updateList() + { + return ['#'.$this->getId('page-list') => $this->makePartial('items', ['items' => $this->getData()])]; + } + + protected function subtreeToText($page) + { + $result = $this->pageToText($page->page); + + $iterator = function($pages) use (&$iterator, &$result) { + foreach ($pages as $page) { + $result .= ' '.$this->pageToText($page->page); + $iterator($page->subpages); + } + }; + + $iterator($page->subpages); + + return $result; + } + + protected function pageToText($page) + { + $viewBag = $page->getViewBag(); + + return $page->getViewBag()->property('title').' '.$page->getViewBag()->property('url'); + } + + protected function getSession($key = null, $default = null) + { + $key = strlen($key) ? $this->getThemeSessionKey($key) : $key; + + return parent::getSession($key, $default); + } + + protected function putSession($key, $value) + { + return parent::putSession($this->getThemeSessionKey($key), $value); + } +} diff --git a/plugins/rainlab/pages/widgets/SnippetList.php b/plugins/rainlab/pages/widgets/SnippetList.php new file mode 100644 index 0000000..e4045de --- /dev/null +++ b/plugins/rainlab/pages/widgets/SnippetList.php @@ -0,0 +1,109 @@ +alias = $alias; + $this->theme = Theme::getEditTheme(); + $this->dataIdPrefix = 'snippet-'.$this->theme->getDirName(); + + parent::__construct($controller, []); + $this->bindToController(); + } + + /** + * Renders the widget. + * @return string + */ + public function render() + { + return $this->makePartial('body', [ + 'data' => $this->getData() + ]); + } + + /* + * Event handlers + */ + + public function onSearch() + { + $this->setSearchTerm(Input::get('search')); + + return $this->updateList(); + } + + /* + * Methods for the internal use + */ + + protected function getData() + { + $manager = SnippetManager::instance(); + $snippets = $manager->listSnippets($this->theme); + + $searchTerm = Str::lower($this->getSearchTerm()); + + if (strlen($searchTerm)) { + $words = explode(' ', $searchTerm); + $filteredSnippets = []; + + foreach ($snippets as $snippet) { + if ($this->textMatchesSearch($words, $snippet->getName().' '.$snippet->code.' '.$snippet->getDescription())) { + $filteredSnippets[] = $snippet; + } + } + + $snippets = $filteredSnippets; + } + + usort($snippets, function($a, $b) { + return strcmp($a->getName(), $b->getName()); + }); + + return $snippets; + } + + protected function updateList() + { + return ['#'.$this->getId('snippet-list') => $this->makePartial('items', ['items' => $this->getData()])]; + } + + protected function getThemeSessionKey($prefix) + { + return $prefix.$this->theme->getDirName(); + } + + protected function getSession($key = null, $default = null) + { + $key = strlen($key) ? $this->getThemeSessionKey($key) : $key; + + return parent::getSession($key, $default); + } + + protected function putSession($key, $value) + { + return parent::putSession($this->getThemeSessionKey($key), $value); + } +} diff --git a/plugins/rainlab/pages/widgets/TemplateList.php b/plugins/rainlab/pages/widgets/TemplateList.php new file mode 100644 index 0000000..3e53ca3 --- /dev/null +++ b/plugins/rainlab/pages/widgets/TemplateList.php @@ -0,0 +1,415 @@ +'URL'] + */ + public $descriptionProperties = []; + + /** + * @var string object property to use as a description. + */ + public $descriptionProperty; + + /** + * @var string Message to display when there are no records in the list. + */ + public $noRecordsMessage = 'rainlab.pages::lang.template.no_list_records'; + + /** + * @var string Message to display when the Delete button is clicked. + */ + public $deleteConfirmation = 'rainlab.pages::lang.template.delete_confirm'; + + /** + * @var string Specifies the item type. + */ + public $itemType; + + /** + * @var string Extra CSS class name to apply to the control. + */ + public $controlClass; + + /** + * @var array A list of file name patterns to suppress / hide. + */ + public $ignoreDirectories = []; + + /** + * @var array Defines sorting properties. + * The sorting feature is disabled if there are no sorting properties defined. + */ + public $sortingProperties = []; + + /* + * Public methods + */ + + public function __construct($controller, $alias, callable $dataSource) + { + $this->alias = $alias; + $this->dataSource = $dataSource; + $this->theme = Theme::getEditTheme(); + $this->selectionInputName = 'template'; + $this->collapseSessionKey = $this->getThemeSessionKey('groups'); + + parent::__construct($controller, []); + + if (!Request::isXmlHttpRequest()) { + $this->resetSelection(); + } + + $configFile = 'config_' . snake_case($alias) .'.yaml'; + $config = $this->makeConfig($configFile); + + foreach ($config as $field => $value) { + if (property_exists($this, $field)) { + $this->$field = $value; + } + } + + $this->bindToController(); + } + + /** + * Renders the widget. + * @return string + */ + public function render() + { + $toolbarClass = Str::contains($this->controlClass, 'hero') ? 'separator' : null; + + $this->vars['toolbarClass'] = $toolbarClass; + + return $this->makePartial('body', [ + 'data' => $this->getData() + ]); + } + + /* + * Event handlers + */ + + public function onSearch() + { + $this->setSearchTerm(Input::get('search')); + $this->extendSelection(); + + return $this->updateList(); + } + + public function onUpdate() + { + $this->extendSelection(); + + return $this->updateList(); + } + + public function onApplySorting() + { + $this->setSortingProperty(Input::get('sortProperty')); + + $result = $this->updateList(); + $result['#'.$this->getId('sorting-options')] = $this->makePartial('sorting-options'); + + return $result; + } + + // + // Methods for the internal use + // + + protected function getData() + { + /* + * Load the data + */ + $items = call_user_func($this->dataSource); + + if ($items instanceof \October\Rain\Support\Collection) { + $items = $items->all(); + } + + $items = $this->removeIgnoredDirectories($items); + + $items = array_map([$this, 'normalizeItem'], $items); + + $this->sortItems($items); + + /* + * Apply the search + */ + $filteredItems = []; + $searchTerm = Str::lower($this->getSearchTerm()); + + if (strlen($searchTerm)) { + /* + * Exact + */ + foreach ($items as $index => $item) { + if ($this->itemContainsWord($searchTerm, $item, true)) { + $filteredItems[] = $item; + unset($items[$index]); + } + } + + /* + * Fuzzy + */ + $words = explode(' ', $searchTerm); + foreach ($items as $item) { + if ($this->itemMatchesSearch($words, $item)) { + $filteredItems[] = $item; + } + } + } + else { + $filteredItems = $items; + } + + /* + * Group the items + */ + $result = []; + $foundGroups = []; + foreach ($filteredItems as $itemData) { + $pos = strpos($itemData->fileName, '/'); + + if ($pos !== false) { + $group = substr($itemData->fileName, 0, $pos); + if (!array_key_exists($group, $foundGroups)) { + $newGroup = (object)[ + 'title' => $group, + 'items' => [] + ]; + + $foundGroups[$group] = $newGroup; + } + + $foundGroups[$group]->items[] = $itemData; + } + else { + $result[] = $itemData; + } + } + + // Sort folders by name regardless of the + // selected sorting options. + ksort($foundGroups); + + foreach ($foundGroups as $group) { + $result[] = $group; + } + + return $result; + } + + protected function sortItems(&$items) + { + $sortingProperty = $this->getSortingProperty(); + + usort($items, function ($a, $b) use ($sortingProperty) { + return strcmp($a->$sortingProperty, $b->$sortingProperty); + }); + } + + protected function removeIgnoredDirectories($items) + { + if (!$this->ignoreDirectories) { + return $items; + } + + $ignoreCache = []; + + $items = array_filter($items, function ($item) use (&$ignoreCache) { + $fileName = $item->getBaseFileName(); + $dirName = dirname($fileName); + + if (isset($ignoreCache[$dirName])) { + return false; + } + + foreach ($this->ignoreDirectories as $ignoreDir) { + if (File::fileNameMatch($dirName, $ignoreDir)) { + $ignoreCache[$dirName] = true; + return false; + } + } + + return true; + }); + + return $items; + } + + protected function normalizeItem($item) + { + $description = null; + if ($descriptionProperty = $this->descriptionProperty) { + $description = $item->$descriptionProperty; + } + + $descriptions = []; + foreach ($this->descriptionProperties as $property => $title) { + if ($item->$property) { + $descriptions[$title] = $item->$property; + } + } + + $result = [ + 'title' => $this->getItemTitle($item), + 'fileName' => $item->getFileName(), + 'description' => $description, + 'descriptions' => $descriptions, + 'dragValue' => $this->getItemDragValue($item) + ]; + + foreach ($this->sortingProperties as $property => $name) { + $result[$property] = $item->$property; + } + + return (object) $result; + } + + protected function getItemDragValue($item) + { + if ($item instanceof \Cms\Classes\Partial) { + return "{% partial '".$item->getBaseFileName()."' %}"; + } + + if ($item instanceof \Cms\Classes\Content) { + return "{% content '".$item->getBaseFileName()."' %}"; + } + + if ($item instanceof \Cms\Classes\Page) { + return "{{ '".$item->getBaseFileName()."'|page }}"; + } + + return ''; + } + + protected function getItemTitle($item) + { + $titleProperty = $this->titleProperty; + + if ($titleProperty) { + return $item->$titleProperty ?: basename($item->getFileName()); + } + + return basename($item->getFileName()); + } + + protected function setSearchTerm($term) + { + $this->searchTerm = trim($term); + $this->putSession('search', $this->searchTerm); + } + + protected function getSearchTerm() + { + return $this->searchTerm !== false ? $this->searchTerm : $this->getSession('search'); + } + + protected function updateList() + { + return [ + '#'.$this->getId('template-list') => $this->makePartial('items', ['items' => $this->getData()]) + ]; + } + + protected function itemMatchesSearch($words, $item) + { + foreach ($words as $word) { + $word = trim($word); + if (!strlen($word)) { + continue; + } + + if (!$this->itemContainsWord($word, $item)) { + return false; + } + } + + return true; + } + + protected function itemContainsWord($word, $item, $exact = false) + { + $operator = $exact ? 'is' : 'contains'; + + if (strlen($item->title) && Str::$operator(Str::lower($item->title), $word)) { + return true; + } + + if (Str::$operator(Str::lower($item->fileName), $word)) { + return true; + } + + if (Str::$operator(Str::lower($item->description), $word) && strlen($item->description)) { + return true; + } + + foreach ($item->descriptions as $value) { + if (Str::$operator(Str::lower($value), $word) && strlen($value)) { + return true; + } + } + + return false; + } + + protected function getThemeSessionKey($prefix) + { + return $prefix.$this->theme->getDirName(); + } + + protected function getSortingProperty() + { + $property = $this->getSession($this->getThemeSessionKey('sorting_property'), self::SORTING_FILENAME); + + if (!array_key_exists($property, $this->sortingProperties)) { + return self::SORTING_FILENAME; + } + + return $property; + } + + protected function setSortingProperty($property) + { + $this->putSession($this->getThemeSessionKey('sorting_property'), $property); + } +} diff --git a/plugins/rainlab/pages/widgets/menulist/partials/_body.htm b/plugins/rainlab/pages/widgets/menulist/partials/_body.htm new file mode 100644 index 0000000..da0e696 --- /dev/null +++ b/plugins/rainlab/pages/widgets/menulist/partials/_body.htm @@ -0,0 +1,10 @@ + +makePartial('toolbar') ?> + +
    +
    +
    + makePartial('menus', ['data' => $data]) ?> +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/pages/widgets/menulist/partials/_items.htm b/plugins/rainlab/pages/widgets/menulist/partials/_items.htm new file mode 100644 index 0000000..94696c3 --- /dev/null +++ b/plugins/rainlab/pages/widgets/menulist/partials/_items.htm @@ -0,0 +1,39 @@ + +
      + + getBaseFileName(); + $dataId = 'menu-'.$this->theme->getDirName().'-'.$fileName; + $cbId = 'cb'.md5($item->getBaseFileName()); + ?> +
    • + + name) ?> + + code) ?> + + + + + + +
      + isItemSelected($dataId) ? 'checked' : null ?> + data-request="getEventHandler('onSelect') ?>" + value="1" /> + +
      +
    • + +
    + +

    noRecordsMessage)) ?>

    + + + + + diff --git a/plugins/rainlab/pages/widgets/menulist/partials/_menus.htm b/plugins/rainlab/pages/widgets/menulist/partials/_menus.htm new file mode 100644 index 0000000..c5f03ac --- /dev/null +++ b/plugins/rainlab/pages/widgets/menulist/partials/_menus.htm @@ -0,0 +1,10 @@ +
    +
    + +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/pages/widgets/menulist/partials/_toolbar.htm b/plugins/rainlab/pages/widgets/menulist/partials/_toolbar.htm new file mode 100644 index 0000000..3fe3fa6 --- /dev/null +++ b/plugins/rainlab/pages/widgets/menulist/partials/_toolbar.htm @@ -0,0 +1,37 @@ +
    +
    + + +
    +
    + + +
    +
    + + +
    + +
    + +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/pages/widgets/pagelist/partials/_body.htm b/plugins/rainlab/pages/widgets/pagelist/partials/_body.htm new file mode 100644 index 0000000..cf5e883 --- /dev/null +++ b/plugins/rainlab/pages/widgets/pagelist/partials/_body.htm @@ -0,0 +1,10 @@ + +makePartial('toolbar') ?> + +
    +
    +
    + makePartial('pages', ['data' => $data]) ?> +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/pages/widgets/pagelist/partials/_items.htm b/plugins/rainlab/pages/widgets/pagelist/partials/_items.htm new file mode 100644 index 0000000..61b0791 --- /dev/null +++ b/plugins/rainlab/pages/widgets/pagelist/partials/_items.htm @@ -0,0 +1,9 @@ + +
      + makePartial('treebranch', ['items' => $items]) ?> +
    + +

    noRecordsMessage) ?>

    + + + \ No newline at end of file diff --git a/plugins/rainlab/pages/widgets/pagelist/partials/_pages.htm b/plugins/rainlab/pages/widgets/pagelist/partials/_pages.htm new file mode 100644 index 0000000..4748886 --- /dev/null +++ b/plugins/rainlab/pages/widgets/pagelist/partials/_pages.htm @@ -0,0 +1,12 @@ +
    +
    +
    + makePartial('items', ['items' => $data]) ?> +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/pages/widgets/pagelist/partials/_toolbar.htm b/plugins/rainlab/pages/widgets/pagelist/partials/_toolbar.htm new file mode 100644 index 0000000..fa2dd82 --- /dev/null +++ b/plugins/rainlab/pages/widgets/pagelist/partials/_toolbar.htm @@ -0,0 +1,37 @@ +
    +
    + + +
    +
    + + +
    +
    + + +
    + +
    + +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/pages/widgets/pagelist/partials/_treebranch.htm b/plugins/rainlab/pages/widgets/pagelist/partials/_treebranch.htm new file mode 100644 index 0000000..607c4a6 --- /dev/null +++ b/plugins/rainlab/pages/widgets/pagelist/partials/_treebranch.htm @@ -0,0 +1,55 @@ + + page->getBaseFileName(); + $groupStatus = $this->getCollapseStatus($fileName); + $dataId = $this->dataIdPrefix.'-'.$fileName; + $searchMode = strlen($this->getSearchTerm()) > 0; + $cbId = 'cb'.md5($fileName); + ?> +
  • data-no-drag-mode + data-id="" + > +
    + + page->getViewBag()->property('title')) ?> + page->getViewBag()->property('url')) ?> + + + +
    + isItemSelected($fileName) ? 'checked' : null ?> + data-request="getEventHandler('onSelect') ?>" + value="1"> + +
    + + +
    + +
      + subpages): ?> + makePartial('treebranch', ['items' => $subpages]) ?> + +
    +
  • + diff --git a/plugins/rainlab/pages/widgets/snippetlist/partials/_body.htm b/plugins/rainlab/pages/widgets/snippetlist/partials/_body.htm new file mode 100644 index 0000000..807c293 --- /dev/null +++ b/plugins/rainlab/pages/widgets/snippetlist/partials/_body.htm @@ -0,0 +1,8 @@ +makePartial('toolbar') ?> +
    +
    +
    + makePartial('snippets', ['data'=>$data]) ?> +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/pages/widgets/snippetlist/partials/_items.htm b/plugins/rainlab/pages/widgets/snippetlist/partials/_items.htm new file mode 100644 index 0000000..b0c85ee --- /dev/null +++ b/plugins/rainlab/pages/widgets/snippetlist/partials/_items.htm @@ -0,0 +1,28 @@ + + + +

    noRecordsMessage)) ?>

    + + + \ No newline at end of file diff --git a/plugins/rainlab/pages/widgets/snippetlist/partials/_snippets.htm b/plugins/rainlab/pages/widgets/snippetlist/partials/_snippets.htm new file mode 100644 index 0000000..bd8989c --- /dev/null +++ b/plugins/rainlab/pages/widgets/snippetlist/partials/_snippets.htm @@ -0,0 +1,10 @@ +
    +
    +
    + makePartial('items', ['items'=>$data]) ?> +
    +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/pages/widgets/snippetlist/partials/_toolbar.htm b/plugins/rainlab/pages/widgets/snippetlist/partials/_toolbar.htm new file mode 100644 index 0000000..84094f4 --- /dev/null +++ b/plugins/rainlab/pages/widgets/snippetlist/partials/_toolbar.htm @@ -0,0 +1,20 @@ +
    +
    + + +
    + +
    + +
    +
    \ No newline at end of file diff --git a/plugins/rainlab/pages/widgets/templatelist/partials/_body.htm b/plugins/rainlab/pages/widgets/templatelist/partials/_body.htm new file mode 100644 index 0000000..a4273cb --- /dev/null +++ b/plugins/rainlab/pages/widgets/templatelist/partials/_body.htm @@ -0,0 +1,8 @@ +makePartial('toolbar') ?> +
    +
    +
    + makePartial('templates', ['data' => $data]) ?> +
    +
    +
    diff --git a/plugins/rainlab/pages/widgets/templatelist/partials/_items.htm b/plugins/rainlab/pages/widgets/templatelist/partials/_items.htm new file mode 100644 index 0000000..d330ca3 --- /dev/null +++ b/plugins/rainlab/pages/widgets/templatelist/partials/_items.htm @@ -0,0 +1,59 @@ + + + +

    noRecordsMessage)) ?>

    + + + + + diff --git a/plugins/rainlab/pages/widgets/templatelist/partials/_sorting-options.htm b/plugins/rainlab/pages/widgets/templatelist/partials/_sorting-options.htm new file mode 100644 index 0000000..4aacc07 --- /dev/null +++ b/plugins/rainlab/pages/widgets/templatelist/partials/_sorting-options.htm @@ -0,0 +1,7 @@ +sortingProperties as $propertyName=>$propertyTitle): ?> +
  • getSortingProperty() == $propertyName): ?>class="active"> + + + +
  • + diff --git a/plugins/rainlab/pages/widgets/templatelist/partials/_templates.htm b/plugins/rainlab/pages/widgets/templatelist/partials/_templates.htm new file mode 100644 index 0000000..e1f0b86 --- /dev/null +++ b/plugins/rainlab/pages/widgets/templatelist/partials/_templates.htm @@ -0,0 +1,11 @@ +
    +
    +
    + makePartial('items', ['items' => $data]) ?> +
    +
    +
    diff --git a/plugins/rainlab/pages/widgets/templatelist/partials/_toolbar.htm b/plugins/rainlab/pages/widgets/templatelist/partials/_toolbar.htm new file mode 100644 index 0000000..c3ed60f --- /dev/null +++ b/plugins/rainlab/pages/widgets/templatelist/partials/_toolbar.htm @@ -0,0 +1,51 @@ +
    +
    + + +
    +
    + + + sortingProperties): ?> + + + + +
    +
    + + +
    + +
    + +
    +
    diff --git a/plugins/rainlab/translate/.gitignore b/plugins/rainlab/translate/.gitignore new file mode 100644 index 0000000..4b53aba --- /dev/null +++ b/plugins/rainlab/translate/.gitignore @@ -0,0 +1,4 @@ +/vendor +composer.lock +.DS_Store +.phpunit.result.cache diff --git a/plugins/rainlab/translate/LICENCE.md b/plugins/rainlab/translate/LICENCE.md new file mode 100644 index 0000000..e49b459 --- /dev/null +++ b/plugins/rainlab/translate/LICENCE.md @@ -0,0 +1,21 @@ +# MIT license + +Copyright (c) 2014-2022 Responsiv Pty Ltd, October 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/plugins/rainlab/translate/Plugin.php b/plugins/rainlab/translate/Plugin.php new file mode 100644 index 0000000..ec57883 --- /dev/null +++ b/plugins/rainlab/translate/Plugin.php @@ -0,0 +1,381 @@ + 'rainlab.translate::lang.plugin.name', + 'description' => 'rainlab.translate::lang.plugin.description', + 'author' => 'Alexey Bobkov, Samuel Georges', + 'icon' => 'icon-language', + 'homepage' => 'https://github.com/rainlab/translate-plugin' + ]; + } + + /** + * register the plugin + */ + public function register() + { + // Load localized version of mail templates (akin to localized CMS content files) + Event::listen('mailer.beforeAddContent', function ($mailer, $message, $view, $data, $raw, $plain) { + return EventRegistry::instance()->findLocalizedMailViewContent($mailer, $message, $view, $data, $raw, $plain); + }, 1); + + // Defer event with low priority to let others contribute before this registers. + Event::listen('backend.form.extendFieldsBefore', function($widget) { + EventRegistry::instance()->registerFormFieldReplacements($widget); + }, -1); + + // Handle translated page URLs + Page::extend(function($model) { + if (!$model->propertyExists('translatable')) { + $model->addDynamicProperty('translatable', []); + } + $model->translatable = array_merge($model->translatable, ['title', 'description', 'meta_title', 'meta_description']); + if (!$model->isClassExtendedWith(\RainLab\Translate\Behaviors\TranslatablePageUrl::class)) { + $model->extendClassWith(\RainLab\Translate\Behaviors\TranslatablePageUrl::class); + } + if (!$model->isClassExtendedWith(\RainLab\Translate\Behaviors\TranslatablePage::class)) { + $model->extendClassWith(\RainLab\Translate\Behaviors\TranslatablePage::class); + } + }); + + // Extension logic for October CMS v1.0 + if (!class_exists('System')) { + $this->extendLegacyPlatform(); + } + // Extension logic for October CMS v2.0 + else { + Event::listen('cms.theme.createThemeDataModel', function($attributes) { + return new \RainLab\Translate\Models\MLThemeData($attributes); + }); + + Event::listen('cms.template.getTemplateToolbarSettingsButtons', function($extension, $dataHolder) { + if ($dataHolder->templateType === 'page') { + EventRegistry::instance()->extendEditorPageToolbar($dataHolder); + } + }); + } + + // Register console commands + $this->registerConsoleCommand('translate.scan', \Rainlab\Translate\Console\ScanCommand::class); + + // Register asset bundles + $this->registerAssetBundles(); + } + + /** + * extendLegacyPlatform will add the legacy features expected in v1.0 + */ + protected function extendLegacyPlatform() + { + // Adds translation support to file models + File::extend(function ($model) { + if (!$model->propertyExists('translatable')) { + $model->addDynamicProperty('translatable', []); + } + $model->translatable = array_merge($model->translatable, ['title', 'description']); + if (!$model->isClassExtendedWith(\October\Rain\Database\Behaviors\Purgeable::class)) { + $model->extendClassWith(\October\Rain\Database\Behaviors\Purgeable::class); + } + if (!$model->isClassExtendedWith(\RainLab\Translate\Behaviors\TranslatableModel::class)) { + $model->extendClassWith(\RainLab\Translate\Behaviors\TranslatableModel::class); + } + }); + + // Adds translation support to theme settings + ThemeData::extend(static function ($model) { + if (!$model->propertyExists('translatable')) { + $model->addDynamicProperty('translatable', []); + } + + if (!$model->isClassExtendedWith(\October\Rain\Database\Behaviors\Purgeable::class)) { + $model->extendClassWith(\October\Rain\Database\Behaviors\Purgeable::class); + } + if (!$model->isClassExtendedWith(\RainLab\Translate\Behaviors\TranslatableModel::class)) { + $model->extendClassWith(\RainLab\Translate\Behaviors\TranslatableModel::class); + } + + $model->bindEvent('model.afterFetch', static function() use ($model) { + foreach ($model->getFormFields() as $id => $field) { + if (!empty($field['translatable'])) { + $model->translatable[] = $id; + } + } + }); + }); + } + + /** + * boot the plugin + */ + public function boot() + { + // Set the page context for translation caching with high priority. + Event::listen('cms.page.init', function($controller, $page) { + EventRegistry::instance()->setMessageContext($page); + }, 100); + + // Populate MenuItem properties with localized values if available + Event::listen('pages.menu.referencesGenerated', function (&$items) { + $locale = App::getLocale(); + $iterator = function ($menuItems) use (&$iterator, $locale) { + $result = []; + foreach ($menuItems as $item) { + $localeFields = array_get($item->viewBag, "locale.$locale", []); + foreach ($localeFields as $fieldName => $fieldValue) { + if ($fieldValue) { + $item->$fieldName = $fieldValue; + } + } + if ($item->items) { + $item->items = $iterator($item->items); + } + $result[] = $item; + } + return $result; + }; + $items = $iterator($items); + }); + + // Import messages defined by the theme + Event::listen('cms.theme.setActiveTheme', function($code) { + EventRegistry::instance()->importMessagesFromTheme($code); + }); + + // Adds language suffixes to content files. + Event::listen('cms.page.beforeRenderContent', function($controller, $fileName) { + return EventRegistry::instance() + ->findTranslatedContentFile($controller, $fileName) + ; + }); + + // Prune localized content files from template list + Event::listen('pages.content.templateList', function($widget, $templates) { + return EventRegistry::instance() + ->pruneTranslatedContentTemplates($templates) + ; + }); + + // Look at session for locale using middleware + \Cms\Classes\CmsController::extend(function($controller) { + $controller->middleware(\RainLab\Translate\Classes\LocaleMiddleware::class); + }); + + // Append current locale to static page's cache keys + $modifyKey = function (&$key) { + $key = $key . '-' . Lang::getLocale(); + }; + Event::listen('pages.router.getCacheKey', $modifyKey); + Event::listen('pages.page.getMenuCacheKey', $modifyKey); + Event::listen('pages.snippet.getMapCacheKey', $modifyKey); + Event::listen('pages.snippet.getPartialMapCacheKey', $modifyKey); + + if (class_exists('\RainLab\Pages\Classes\SnippetManager')) { + $handler = function ($controller, $template, $type) { + if (!$template->methodExists('getDirtyLocales')) { + return; + } + + // Get the locales that have changed + $dirtyLocales = $template->getDirtyLocales(); + + if (!empty($dirtyLocales)) { + $currentLocale = Lang::getLocale(); + + foreach ($dirtyLocales as $locale) { + if (!$template->isTranslateDirty(null, $locale)) { + continue; + } + + // Clear the RainLab.Pages caches for each dirty locale + App::setLocale($locale); + \RainLab\Pages\Plugin::clearCache(); + } + + // Restore the original locale for this request + App::setLocale($currentLocale); + } + }; + + Event::listen('cms.template.save', $handler); + Event::listen('pages.object.save', $handler); + } + } + + /** + * registerComponents + */ + public function registerComponents() + { + return [ + \RainLab\Translate\Components\LocalePicker::class => 'localePicker', + \RainLab\Translate\Components\AlternateHrefLangElements::class => 'alternateHrefLangElements' + ]; + } + + /** + * registerPermissions + */ + public function registerPermissions() + { + return [ + 'rainlab.translate.manage_locales' => [ + 'tab' => 'rainlab.translate::lang.plugin.tab', + 'label' => 'rainlab.translate::lang.plugin.manage_locales' + ], + 'rainlab.translate.manage_messages' => [ + 'tab' => 'rainlab.translate::lang.plugin.tab', + 'label' => 'rainlab.translate::lang.plugin.manage_messages' + ] + ]; + } + + /** + * registerSettings + */ + public function registerSettings() + { + return [ + 'locales' => [ + 'label' => 'rainlab.translate::lang.locale.title', + 'description' => 'rainlab.translate::lang.plugin.description', + 'icon' => 'icon-language', + 'url' => Backend::url('rainlab/translate/locales'), + 'order' => 550, + 'category' => 'rainlab.translate::lang.plugin.name', + 'permissions' => ['rainlab.translate.manage_locales'], + 'keywords' => 'translate', + ], + 'messages' => [ + 'label' => 'rainlab.translate::lang.messages.title', + 'description' => 'rainlab.translate::lang.messages.description', + 'icon' => 'icon-list-alt', + 'url' => Backend::url('rainlab/translate/messages'), + 'order' => 551, + 'category' => 'rainlab.translate::lang.plugin.name', + 'permissions' => ['rainlab.translate.manage_messages'], + 'keywords' => 'translate', + ] + ]; + } + + /** + * registerMarkupTags for Twig + * @return array + */ + public function registerMarkupTags() + { + return [ + 'filters' => [ + '_' => [$this, 'translateString'], + '__' => [$this, 'translatePlural'], + 'transRaw' => [$this, 'translateRawString'], + 'transRawPlural' => [$this, 'translateRawPlural'], + 'localeUrl' => [$this, 'localeUrl'], + ] + ]; + } + + /** + * registerFormWidgets for multi-lingual + */ + public function registerFormWidgets() + { + $mediaFinderClass = class_exists('System') + ? \RainLab\Translate\FormWidgets\MLMediaFinderv2::class + : \RainLab\Translate\FormWidgets\MLMediaFinder::class; + + return [ + \RainLab\Translate\FormWidgets\MLText::class => 'mltext', + \RainLab\Translate\FormWidgets\MLTextarea::class => 'mltextarea', + \RainLab\Translate\FormWidgets\MLRichEditor::class => 'mlricheditor', + \RainLab\Translate\FormWidgets\MLMarkdownEditor::class => 'mlmarkdowneditor', + \RainLab\Translate\FormWidgets\MLRepeater::class => 'mlrepeater', + \RainLab\Translate\FormWidgets\MLNestedForm::class => 'mlnestedform', + $mediaFinderClass => 'mlmediafinder', + ]; + } + + /** + * registerAssetBundles for compilation + */ + protected function registerAssetBundles() + { + CombineAssets::registerCallback(function ($combiner) { + $combiner->registerBundle('$/rainlab/translate/assets/less/messages.less'); + $combiner->registerBundle('$/rainlab/translate/assets/less/multilingual.less'); + }); + } + + /** + * localeUrl builds a localized URL + */ + public function localeUrl($url, $locale) + { + $translator = Translator::instance(); + + $parts = parse_url($url); + + $path = array_get($parts, 'path'); + + return http_build_url($parts, [ + 'path' => '/' . $translator->getPathInLocale($path, $locale) + ]); + } + + /** + * translateString + */ + public function translateString($string, $params = [], $locale = null) + { + return Message::trans($string, $params, $locale); + } + + /** + * translatePlural + */ + public function translatePlural($string, $count = 0, $params = [], $locale = null) + { + return Lang::choice(Message::trans($string, $params, $locale), $count, $params); + } + + /** + * translateRawString + */ + public function translateRawString($string, $params = [], $locale = null) + { + return Message::transRaw($string, $params, $locale); + } + + /** + * translateRawPlural + */ + public function translateRawPlural($string, $count = 0, $params = [], $locale = null) + { + return Lang::choice(Message::transRaw($string, $params, $locale), $count, $params); + } +} diff --git a/plugins/rainlab/translate/README.md b/plugins/rainlab/translate/README.md new file mode 100644 index 0000000..6522717 --- /dev/null +++ b/plugins/rainlab/translate/README.md @@ -0,0 +1,394 @@ +# Translation plugin + +Enables multi-lingual sites. + +## Selecting a language + +Different languages can be set up in the back-end area, with a single default language selected. This activates the use of the language on the front-end and in the back-end UI. + +A visitor can select a language by prefixing the language code to the URL, this is then stored in the user's session as their chosen language. For example: + +* `http://website/ru/` will display the site in Russian +* `http://website/fr/` will display the site in French +* `http://website/` will display the site in the default language or the user's chosen language. + +## Language Picker Component + +A visitor can select their chosen language using the `LocalePicker` component. This component will display a simple dropdown that changes the page language depending on the selection. + + title = "Home" + url = "/" + + [localePicker] + == + +

    {{ 'Please select your language:'|_ }}

    + {% component 'localePicker' %} + +If translated, the text above will appear as whatever language is selected by the user. The dropdown is very basic and is intended to be restyled. A simpler example might be: + + [...] + == + +

    + Switch language to: + English, + Russian +

    + +## Message translation + +Message or string translation is the conversion of adhoc strings used throughout the site. A message can be translated with parameters. + + {{ 'site.name'|_ }} + + {{ 'Welcome to our website!'|_ }} + + {{ 'Hello :name!'|_({ name: 'Friend' }) }} + +A message can also be translated for a choice usage. + + {{ 'There are no apples|There are :number applies!'|__(2, { number: 'two' }) }} + +Or you set a locale manually by passing a second argument. + + {{ 'this is always english'|_({}, 'en') }} + +Themes can provide default values for these messages by defining a `translate` key in the `theme.yaml` file, located in the theme directory. + + name: My Theme + # [...] + + translate: + en: + site.name: 'My Website' + nav.home: 'Home' + nav.video: 'Video' + title.home: 'Welcome Home' + title.video: 'Screencast Video' + +You may also define the translations in a separate file, where the path is relative to the theme. The following definition will source the default messages from the file **config/lang.yaml** inside the theme. + + name: My Theme + # [...] + + translate: config/lang.yaml + +This is an example of **config/lang.yaml** file with two languages: + + en: + site.name: 'My Website' + nav.home: 'Home' + nav.video: 'Video' + title.home: 'Welcome Home' + hr: + site.name: 'Moje web stranice' + nav.home: 'Početna' + nav.video: 'Video' + title.home: 'Dobrodošli' + +You may also define the translations in a separate file per locale, where the path is relative to the theme. The following definition will source the default messages from the file **config/lang-en.yaml** inside the theme for the english locale and from the file **config/lang-fr.yaml** for the french locale. + + name: My Theme + # [...] + + translate: + en: config/lang-en.yaml + fr: config/lang-fr.yaml + +This is an example for the **config/lang-en.yaml** file: + + site.name: 'My Website' + nav.home: 'Home' + nav.video: 'Video' + title.home: 'Welcome Home' + +In order to make these default values reflected to your frontend site, go to **Settings -> Translate messages** in the backend and hit **Scan for messages**. They will also be loaded automatically when the theme is activated. + +The same operation can be performed with the `translate:scan` artisan command. It may be worth including it in a deployment script to automatically fetch updated messages: + + php artisan translate:scan + +Add the `--purge` option to clear old messages first: + + php artisan translate:scan --purge + +## Content & mail template translation + +This plugin activates a feature in the CMS that allows content & mail template files to use language suffixes, for example: + +* **welcome.htm** will contain the content or mail template in the default language. +* **welcome-ru.htm** will contain the content or mail template in Russian. +* **welcome-fr.htm** will contain the content or mail template in French. + +## Model translation + +Models can have their attributes translated by using the `RainLab.Translate.Behaviors.TranslatableModel` behavior and specifying which attributes to translate in the class. + + class User + { + public $implement = ['RainLab.Translate.Behaviors.TranslatableModel']; + + public $translatable = ['name']; + } + +The attribute will then contain the default language value and other language code values can be created by using the `translateContext()` method. + + $user = User::first(); + + // Outputs the name in the default language + echo $user->name; + + $user->translateContext('fr'); + + // Outputs the name in French + echo $user->name; + +You may use the same process for setting values. + + $user = User::first(); + + // Sets the name in the default language + $user->name = 'English'; + + $user->translateContext('fr'); + + // Sets the name in French + $user->name = 'Anglais'; + +The `lang()` method is a shorthand version of `translateContext()` and is also chainable. + + // Outputs the name in French + echo $user->lang('fr')->name; + +This can be useful inside a Twig template. + + {{ user.lang('fr').name }} + +There are ways to get and set attributes without changing the context. + + // Gets a single translated attribute for a language + $user->getAttributeTranslated('name', 'fr'); + + // Sets a single translated attribute for a language + $user->setAttributeTranslated('name', 'Jean-Claude', 'fr'); + +## Theme data translation + +It is also possible to translate theme customisation options. Just mark your form fields with `translatable` property and the plugin will take care about everything else: + + tabs: + fields: + website_name: + tab: Info + label: Website Name + type: text + default: Your website name + translatable: true + +## Fallback attribute values + +By default, untranslated attributes will fall back to the default locale. This behavior can be disabled by calling the `noFallbackLocale` method. + + $user = User::first(); + + $user->noFallbackLocale()->lang('fr'); + + // Returns NULL if there is no French translation + $user->name; + +## Indexed attributes + +Translatable model attributes can also be declared as an index by passing the `$transatable` attribute value as an array. The first value is the attribute name, the other values represent options, in this case setting the option `index` to `true`. + + public $translatable = [ + 'name', + ['slug', 'index' => true] + ]; + +Once an attribute is indexed, you may use the `transWhere` method to apply a basic query to the model. + + Post::transWhere('slug', 'hello-world')->first(); + +The `transWhere` method accepts a third argument to explicitly pass a locale value, otherwise it will be detected from the environment. + + Post::transWhere('slug', 'hello-world', 'en')->first(); + +## URL translation + +Pages in the CMS support translating the URL property. Assuming you have 3 languages set up: + +- en: English +- fr: French +- ru: Russian + +There is a page with the following content: + + url = "/contact" + + [viewBag] + localeUrl[ru] = "/контакт" + == +

    Page content

    + +The word "Contact" in French is the same so a translated URL is not given, or needed. If the page has no URL override specified, then the default URL will be used. Pages will not be duplicated for a given language. + +- /fr/contact - Page in French +- /en/contact - Page in English +- /ru/контакт - Page in Russian +- /ru/contact - 404 + +## URL parameter translation + +It's possible to translate URL parameters by listening to the `translate.localePicker.translateParams` event, which is fired when switching languages. + + Event::listen('translate.localePicker.translateParams', function($page, $params, $oldLocale, $newLocale) { + if ($page->baseFileName == 'your-page-filename') { + return YourModel::translateParams($params, $oldLocale, $newLocale); + } + }); + +In YourModel, one possible implementation might look like this: + + public static function translateParams($params, $oldLocale, $newLocale) { + $newParams = $params; + foreach ($params as $paramName => $paramValue) { + $records = self::transWhere($paramName, $paramValue, $oldLocale)->first(); + if ($records) { + $records->translateContext($newLocale); + $newParams[$paramName] = $records->$paramName; + } + } + return $newParams; + } + +## Query string translation + +It's possible to translate query string parameters by listening to the `translate.localePicker.translateQuery` event, which is fired when switching languages. + + Event::listen('translate.localePicker.translateQuery', function($page, $params, $oldLocale, $newLocale) { + if ($page->baseFileName == 'your-page-filename') { + return YourModel::translateParams($params, $oldLocale, $newLocale); + } + }); + +For a possible implementation of the `YourModel::translateParams` method look at the example under `URL parameter translation` from above. + +## Extend theme scan + + Event::listen('rainlab.translate.themeScanner.afterScan', function (ThemeScanner $scanner) { + ... + }); + +## Settings model translation + +It's possible to translate your settings model like any other model. To retrieve translated values use: + + Settings::instance()->getAttributeTranslated('your_attribute_name'); + +## Conditionally extending plugins + +#### Models + +It is possible to conditionally extend a plugin's models to support translation by placing an `@` symbol before the behavior definition. This is a soft implement will only use `TranslatableModel` if the Translate plugin is installed, otherwise it will not cause any errors. + + /** + * Blog Post Model + */ + class Post extends Model + { + + [...] + + /** + * Softly implement the TranslatableModel behavior. + */ + public $implement = ['@RainLab.Translate.Behaviors.TranslatableModel']; + + /** + * @var array Attributes that support translation, if available. + */ + public $translatable = ['title']; + + [...] + + } + +The back-end forms will automatically detect the presence of translatable fields and replace their controls for multilingual equivalents. + +#### Messages + +Since the Twig filter will not be available all the time, we can pipe them to the native Laravel translation methods instead. This ensures translated messages will always work on the front end. + + /** + * Register new Twig variables + * @return array + */ + public function registerMarkupTags() + { + // Check the translate plugin is installed + if (!class_exists('RainLab\Translate\Behaviors\TranslatableModel')) + return; + + return [ + 'filters' => [ + '_' => ['Lang', 'get'], + '__' => ['Lang', 'choice'], + ] + ]; + } + +# User Interface + +#### Switching locales + +Users can switch between locales by clicking on the locale indicator on the right hand side of the Multi-language input. By holding the CMD / CTRL key all Multi-language Input fields will switch to the selected locale. + +## Integration without jQuery and October Framework files + +It is possible to use the front-end language switcher without using jQuery or the OctoberCMS AJAX Framework by making the AJAX API request yourself manually. The following is an example of how to do that. + + document.querySelector('#languageSelect').addEventListener('change', function () { + const details = { + _session_key: document.querySelector('input[name="_session_key"]').value, + _token: document.querySelector('input[name="_token"]').value, + locale: this.value + } + + let formBody = [] + + for (var property in details) { + let encodedKey = encodeURIComponent(property) + let encodedValue = encodeURIComponent(details[property]) + formBody.push(encodedKey + '=' + encodedValue) + } + + formBody = formBody.join('&') + + fetch(location.href + '/', { + method: 'POST', + body: formBody, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'X-OCTOBER-REQUEST-HANDLER': 'onSwitchLocale', + 'X-OCTOBER-REQUEST-PARTIALS': '', + 'X-Requested-With': 'XMLHttpRequest' + } + }) + .then(res => res.json()) + .then(res => window.location.replace(res.X_OCTOBER_REDIRECT)) + .catch(err => console.log(err)) + }) + +The HTML: + + {{ form_open() }} + + {{ form_close() }} diff --git a/plugins/rainlab/translate/assets/css/messages.css b/plugins/rainlab/translate/assets/css/messages.css new file mode 100644 index 0000000..13b13fa --- /dev/null +++ b/plugins/rainlab/translate/assets/css/messages.css @@ -0,0 +1,17 @@ +#messagesContainer{padding-top:20px} +.translate-messages{position:relative;margin-top:-20px} +.translate-messages .dropdown-button-placeholder{display:block;width:1px;height:20px} +.translate-messages .dropdown-to, +.translate-messages .dropdown-from{position:absolute;top:57px} +.translate-messages .dropdown-to{left:50%} +.translate-messages .dropdown-from{left:0} +.translate-messages .no-other-languages{text-align:center;padding:5px} +.translate-messages .header-language, +.translate-messages .header-swap-languages, +.translate-messages .header-hide-translated{line-height:27px} +.translate-messages .header-language{float:left;cursor:pointer} +.translate-messages .header-language span.is-default{text-transform:none} +.translate-messages .header-swap-languages{margin-right:10px;float:right;font-size:16px;cursor:pointer} +.translate-messages .header-hide-translated{float:right;text-align:right} +.translate-messages .header-hide-translated label{font-weight:normal;margin-bottom:0;margin-right:10px;font-size:12px;white-space:normal} +.translate-messages .header-hide-translated label:before{top:5px;left:0} \ No newline at end of file diff --git a/plugins/rainlab/translate/assets/css/multilingual-v1.css b/plugins/rainlab/translate/assets/css/multilingual-v1.css new file mode 100644 index 0000000..aa2ed8b --- /dev/null +++ b/plugins/rainlab/translate/assets/css/multilingual-v1.css @@ -0,0 +1,13 @@ +/* + * Legacy styles for October v1.0 + */ + +/* Fancy layout */ + +.fancy-layout .form-tabless-fields .field-multilingual .ml-btn { + color: rgba(255,255,255,0.8); +} + +.fancy-layout .form-tabless-fields .field-multilingual .ml-btn:hover { + color: #fff; +} diff --git a/plugins/rainlab/translate/assets/css/multilingual.css b/plugins/rainlab/translate/assets/css/multilingual.css new file mode 100644 index 0000000..278a925 --- /dev/null +++ b/plugins/rainlab/translate/assets/css/multilingual.css @@ -0,0 +1,23 @@ +.field-multilingual{position:relative} +.field-multilingual .ml-btn{background:transparent;position:absolute;color:#7b7b7b;text-transform:uppercase;font-size:11px;letter-spacing:1px;width:44px;padding-right:0;-webkit-box-shadow:none;box-shadow:none;text-shadow:none;z-index:2} +.field-multilingual .ml-btn:hover{color:#555} +.field-multilingual.field-multilingual-text .form-control{padding-right:44px} +.field-multilingual.field-multilingual-text .ml-btn{right:4px;top:50%;margin-top:-22px;height:44px} +.field-multilingual.field-multilingual-textarea textarea{padding-right:30px} +.field-multilingual.field-multilingual-textarea .ml-btn{right:25px;top:5px;width:24px;text-align:right;padding-left:4px} +.field-multilingual.field-multilingual-textarea .ml-dropdown-menu{top:39px;right:1px} +.field-multilingual.field-multilingual-richeditor .ml-btn{top:43px;right:25px;text-align:right} +.field-multilingual.field-multilingual-richeditor .ml-dropdown-menu{top:74px;right:12px} +.field-multilingual.field-multilingual-markdowneditor .ml-btn{top:43px;right:25px;text-align:right} +.field-multilingual.field-multilingual-markdowneditor .ml-dropdown-menu{top:74px;right:12px} +.field-multilingual.field-multilingual-repeater .ml-btn{top:-27px;right:11px;text-align:right} +.field-multilingual.field-multilingual-repeater .ml-dropdown-menu{top:0;right:0} +.field-multilingual.field-multilingual-repeater.is-empty{padding-top:5px} +.field-multilingual.field-multilingual-repeater.is-empty .ml-btn{top:-10px;right:5px;text-align:right} +.field-multilingual.field-multilingual-repeater.is-empty .ml-dropdown-menu{top:15px;right:-7px} +.field-multilingual.field-multilingual-nestedform .ml-btn{top:-3px;right:11px;text-align:right} +.field-multilingual.field-multilingual-nestedform .ml-dropdown-menu{top:24px;right:-2px} +.field-multilingual.field-multilingual-nestedform.is-paneled .ml-btn{top:7px;right:15px} +.field-multilingual.field-multilingual-nestedform.is-paneled .ml-dropdown-menu{top:34px;right:2px} +.fancy-layout .field-multilingual-text input.form-control{padding-right:44px} +.help-block.before-field + .field-multilingual.field-multilingual-textarea .ml-btn{top:-41px} diff --git a/plugins/rainlab/translate/assets/js/locales.js b/plugins/rainlab/translate/assets/js/locales.js new file mode 100644 index 0000000..10e652a --- /dev/null +++ b/plugins/rainlab/translate/assets/js/locales.js @@ -0,0 +1,28 @@ +/* + * Scripts for the Locales controller. + */ ++function ($) { "use strict"; + + var TranslateLocales = function() { + + this.clickRecord = function(recordId) { + var newPopup = $('') + + newPopup.popup({ + handler: 'onUpdateForm', + extraData: { + 'record_id': recordId, + } + }) + } + + this.createRecord = function() { + var newPopup = $('') + newPopup.popup({ handler: 'onCreateForm' }) + } + + } + + $.translateLocales = new TranslateLocales; + +}(window.jQuery); \ No newline at end of file diff --git a/plugins/rainlab/translate/assets/js/messages.js b/plugins/rainlab/translate/assets/js/messages.js new file mode 100644 index 0000000..84fd27e --- /dev/null +++ b/plugins/rainlab/translate/assets/js/messages.js @@ -0,0 +1,173 @@ +/* + * Scripts for the Messages controller. + */ ++function ($) { "use strict"; + + var TranslateMessages = function() { + var self = this + + this.$form = null + + /* + * Table toolbar + */ + this.tableToolbar = null + + /* + * Input with the "from" locale value + */ + this.fromInput = null + + /* + * Template for the "from" header (title) + */ + this.fromHeader = null + + /* + * Input with the "to" locale value + */ + this.toInput = null + + /* + * Template for the "to" header (title) + */ + this.toHeader = null + + /* + * Template for the "found" header (title) + */ + this.foundHeader = null + + /* + * The table widget element + */ + this.tableElement = null + + /* + * Hide translated strings (show only from the empty data set) + */ + this.hideTranslated = false + + /* + * Data sets, complete and untranslated (empty) + */ + this.emptyDataSet = null + this.dataSet = null + + $(document).on('change', '#hideTranslated', function(){ + self.toggleTranslated($(this).is(':checked')) + self.refreshTable() + }); + + $(document).on('keyup', '.control-table input.string-input', function(ev) { + self.onApplyValue(ev) + }); + + this.toggleTranslated = function(isHide) { + this.hideTranslated = isHide + this.setTitleContents() + } + + this.setToolbarContents = function(tableToolbar) { + if (tableToolbar) this.tableToolbar = $(tableToolbar) + if (!this.tableElement) return + + var $toolbar = $('.toolbar', this.tableElement) + if ($toolbar.hasClass('message-buttons-added')) { + return + } + + if (!this.tableToolbar.length) { + return; + } + + $toolbar.addClass('message-buttons-added') + $toolbar.prepend(Mustache.render(this.tableToolbar.html())) + } + + this.setTitleContents = function(fromEl, toEl, foundEl) { + if (fromEl) this.fromHeader = $(fromEl) + if (toEl) this.toHeader = $(toEl) + if (foundEl) this.foundHeader = $(foundEl) + if (!this.tableElement) return + + if (!this.toHeader.length) { + return; + } + + var $headers = $('table.headers th', this.tableElement) + $headers.eq(0).html(this.fromHeader.html()) + $headers.eq(1).html(Mustache.render(this.toHeader.html(), { hideTranslated: this.hideTranslated } )) + $headers.eq(2).html(this.foundHeader.html()) + } + + this.setTableElement = function(el) { + this.tableElement = $(el) + this.$form = $('#messagesForm') + this.fromInput = this.$form.find('input[name=locale_from]') + this.toInput = this.$form.find('input[name=locale_to]') + + this.tableElement.one('oc.tableUpdateData', $.proxy(this.updateTableData, this)) + } + + this.onApplyValue = function(ev) { + if (ev.keyCode == 13) { + var $table = $(ev.currentTarget).closest('[data-control=table]') + + if (!$table.length) { + return + } + + var tableObj = $table.data('oc.table') + if (tableObj) { + tableObj.setCellValue($(ev.currentTarget).closest('td').get(0), ev.currentTarget.value) + tableObj.commitEditedRow() + } + } + } + + this.updateTableData = function(event, records) { + if (this.hideTranslated && !records.length) { + self.toggleTranslated($(this).is(':checked')) + self.refreshTable() + } + } + + this.toggleDropdown = function(el) { + setTimeout(function(){ $(el).dropdown('toggle') }, 1) + return false + } + + this.setLanguage = function(type, code) { + if (type == 'to') + this.toInput.val(code) + else if (type == 'from') + this.fromInput.val(code) + + this.refreshGrid() + return false + } + + this.swapLanguages = function() { + var from = this.fromInput.val(), + to = this.toInput.val() + + this.toggleTranslated(false) + this.fromInput.val(to) + this.toInput.val(from) + this.refreshGrid() + } + + this.refreshGrid = function() { + this.$form.request('onRefresh') + } + + this.refreshTable = function() { + this.tableElement.table('updateDataTable') + } + + } + + $.translateMessages = new TranslateMessages; + +}(window.jQuery); diff --git a/plugins/rainlab/translate/assets/js/multilingual.js b/plugins/rainlab/translate/assets/js/multilingual.js new file mode 100644 index 0000000..2fd6bc3 --- /dev/null +++ b/plugins/rainlab/translate/assets/js/multilingual.js @@ -0,0 +1,145 @@ +/* + * Multi lingual control plugin + * + * Data attributes: + * - data-control="multilingual" - enables the plugin on an element + * - data-default-locale="en" - default locale code + * - data-placeholder-field="#placeholderField" - an element that contains the placeholder value + * + * JavaScript API: + * $('a#someElement').multiLingual({ option: 'value' }) + * + * Dependences: + * - Nil + */ + ++function ($) { "use strict"; + + // MULTILINGUAL CLASS DEFINITION + // ============================ + + var MultiLingual = function(element, options) { + var self = this + this.options = options + this.$el = $(element) + + this.$activeField = null + this.$activeButton = $('[data-active-locale]', this.$el) + this.$dropdown = $('ul.ml-dropdown-menu', this.$el) + this.$placeholder = $(this.options.placeholderField) + + /* + * Init locale + */ + this.activeLocale = this.options.defaultLocale + this.$activeField = this.getLocaleElement(this.activeLocale) + this.$activeButton.text(this.activeLocale) + + this.$dropdown.on('click', '[data-switch-locale]', this.$activeButton, function(event){ + var currentLocale = event.data.text(); + var selectedLocale = $(this).data('switch-locale') + + // only call setLocale() if locale has changed + if (selectedLocale != currentLocale) { + self.setLocale(selectedLocale) + } + + /* + * If Ctrl/Cmd key is pressed, find other instances and switch + */ + if (event.ctrlKey || event.metaKey) { + event.preventDefault(); + $('[data-switch-locale="'+selectedLocale+'"]').click() + } + }) + + this.$placeholder.on('input', function(){ + self.$activeField.val(this.value) + }) + + /* + * Handle oc.inputPreset.beforeUpdate event + */ + $('[data-input-preset]', this.$el).on('oc.inputPreset.beforeUpdate', function(event, src) { + var sourceLocale = src.siblings('.ml-btn[data-active-locale]').text() + var targetLocale = $(this).data('locale-value') + var targetActiveLocale = $(this).siblings('.ml-btn[data-active-locale]').text() + + if (sourceLocale && targetLocale && targetActiveLocale) { + if (targetActiveLocale !== sourceLocale) + self.setLocale(sourceLocale) + $(this).data('update', sourceLocale === targetLocale) + } + }) + } + + MultiLingual.DEFAULTS = { + defaultLocale: 'en', + defaultField: null, + placeholderField: null + } + + MultiLingual.prototype.getLocaleElement = function(locale) { + var el = this.$el.find('[data-locale-value="'+locale+'"]') + return el.length ? el : null + } + + MultiLingual.prototype.getLocaleValue = function(locale) { + var value = this.getLocaleElement(locale) + return value ? value.val() : null + } + + MultiLingual.prototype.setLocaleValue = function(value, locale) { + if (locale) { + this.getLocaleElement(locale).val(value) + } + else { + this.$activeField.val(value) + } + } + + MultiLingual.prototype.setLocale = function(locale) { + this.activeLocale = locale + this.$activeField = this.getLocaleElement(locale) + this.$activeButton.text(locale) + + this.$placeholder.val(this.getLocaleValue(locale)) + this.$el.trigger('setLocale.oc.multilingual', [locale, this.getLocaleValue(locale)]) + } + + // MULTILINGUAL PLUGIN DEFINITION + // ============================ + + var old = $.fn.multiLingual + + $.fn.multiLingual = function (option) { + var args = Array.prototype.slice.call(arguments, 1), result + this.each(function () { + var $this = $(this) + var data = $this.data('oc.multilingual') + var options = $.extend({}, MultiLingual.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.multilingual', (data = new MultiLingual(this, options))) + if (typeof option == 'string') result = data[option].apply(data, args) + if (typeof result != 'undefined') return false + }) + + return result ? result : this + } + + $.fn.multiLingual.Constructor = MultiLingual + + // MULTILINGUAL NO CONFLICT + // ================= + + $.fn.multiLingual.noConflict = function () { + $.fn.multiLingual = old + return this + } + + // MULTILINGUAL DATA-API + // =============== + $(document).render(function () { + $('[data-control="multilingual"]').multiLingual() + }) + +}(window.jQuery); diff --git a/plugins/rainlab/translate/assets/less/messages.less b/plugins/rainlab/translate/assets/less/messages.less new file mode 100644 index 0000000..7a76a04 --- /dev/null +++ b/plugins/rainlab/translate/assets/less/messages.less @@ -0,0 +1,72 @@ +#messagesContainer { + padding-top: 20px; +} + +.translate-messages { + position: relative; + margin-top: -20px; + + .dropdown-button-placeholder { + display:block; + width: 1px; + height: 20px + } + + .dropdown-to, .dropdown-from { + position: absolute; + top: 57px; + } + + .dropdown-to { + left: 50%; + } + + .dropdown-from { + left: 0; + } + + .no-other-languages { + text-align: center; + padding: 5px; + } + + .header-language, + .header-swap-languages, + .header-hide-translated { + line-height: 27px; + } + + .header-language { + float: left; + cursor: pointer; + + span.is-default { + text-transform: none; + } + } + + .header-swap-languages { + margin-right: 10px; + float: right; + font-size: 16px; + cursor: pointer; + } + + .header-hide-translated { + float: right; + text-align: right; + + label { + font-weight: normal; + margin-bottom: 0; + margin-right: 10px; + font-size: 12px; + white-space: normal; + + &:before { + top: 5px; + left: 0; + } + } + } +} diff --git a/plugins/rainlab/translate/assets/less/multilingual.less b/plugins/rainlab/translate/assets/less/multilingual.less new file mode 100644 index 0000000..8024ea5 --- /dev/null +++ b/plugins/rainlab/translate/assets/less/multilingual.less @@ -0,0 +1,148 @@ +@import "../../../../../modules/backend/assets/less/core/boot.less"; + +@multilingual-btn-color: #555555; + +.field-multilingual { + position: relative; + + .ml-btn { + background: transparent; + position: absolute; + color: lighten(@multilingual-btn-color, 15%); + text-transform: uppercase; + font-size: 11px; + letter-spacing: 1px; + width: 44px; + padding-right: 0; + .box-shadow(none); + text-shadow: none; + z-index: 2; + + &:hover { + color: @multilingual-btn-color; + } + } + + &.field-multilingual-text { + .form-control { + padding-right: 44px; + } + .ml-btn { + right: 4px; + top: 50%; + margin-top: -22px; + height: 44px; + } + } + + &.field-multilingual-textarea { + textarea { + // increase padding on the right so that the textarea content does not overlap with the language button + padding-right: 30px; + } + + .ml-btn { + right: 25px; + top: 5px; + width: 24px; + text-align: right; + padding-left: 4px; + } + + .ml-dropdown-menu { + top: 39px; + right: 1px; + } + } + + &.field-multilingual-richeditor { + .ml-btn { + top: 43px; + right: 25px; + text-align: right; + } + + .ml-dropdown-menu { + top: 74px; + right: 12px; + } + } + + &.field-multilingual-markdowneditor { + .ml-btn { + top: 43px; + right: 25px; + text-align: right; + } + + .ml-dropdown-menu { + top: 74px; + right: 12px; + } + } + + &.field-multilingual-repeater { + .ml-btn { + top: -27px; + right: 11px; + text-align: right; + } + + .ml-dropdown-menu { + top: 0; + right: 0; + } + + &.is-empty { + padding-top: 5px; + + .ml-btn { + top: -10px; + right: 5px; + text-align: right; + } + + .ml-dropdown-menu { + top: 15px; + right: -7px; + } + } + } + + &.field-multilingual-nestedform { + .ml-btn { + top: -3px; + right: 11px; + text-align: right; + } + + .ml-dropdown-menu { + top: 24px; + right: -2px; + } + + &.is-paneled { + .ml-btn { + top: 7px; + right: 15px; + } + + .ml-dropdown-menu { + top: 34px; + right: 2px; + } + } + } +} + +.fancy-layout { + .field-multilingual-text input.form-control { + padding-right: 44px; + } +} + +.help-block.before-field + .field-multilingual.field-multilingual-textarea { + .ml-btn { + top: -41px; + } +} diff --git a/plugins/rainlab/translate/behaviors/TranslatableCmsObject.php b/plugins/rainlab/translate/behaviors/TranslatableCmsObject.php new file mode 100644 index 0000000..f327f2a --- /dev/null +++ b/plugins/rainlab/translate/behaviors/TranslatableCmsObject.php @@ -0,0 +1,230 @@ +model->bindEvent('cmsObject.fillViewBagArray', function() { + $this->mergeViewBagAttributes(); + }); + + $this->model->bindEvent('cmsObject.getTwigCacheKey', function($key) { + return $this->overrideTwigCacheKey($key); + }); + + // delete all translation files associated with the default language static page + $this->model->bindEvent('model.afterDelete', function() use ($model) { + foreach (Locale::listEnabled() as $locale => $label) { + if ($locale == $this->translatableDefault) { + continue; + } + if ($obj = $this->getCmsObjectForLocale($locale)) { + $obj->delete(); + } + } + }); + } + + /** + * Merge the viewBag array for the base and translated objects. + * @return void + */ + protected function mergeViewBagAttributes() + { + $locale = $this->translatableContext; + + if (!array_key_exists($locale, $this->translatableAttributes)) { + $this->loadTranslatableData($locale); + } + + if (isset($this->translatableViewBag[$locale])) { + $this->model->viewBag = array_merge( + $this->model->viewBag, + $this->translatableViewBag[$locale] + ); + } + } + + /** + * Translated CMS objects need their own unique cache key in twig. + * @return string|null + */ + protected function overrideTwigCacheKey($key) + { + if (!$locale = $this->translatableContext) { + return null; + } + + return $key . '-' . $locale; + } + + /** + * {@inheritDoc} + */ + public function syncTranslatableAttributes() + { + parent::syncTranslatableAttributes(); + + if ($this->model->isDirty('fileName')) { + $this->syncTranslatableFileNames(); + } + } + + /** + * If the parent model file name is changed, this should + * be reflected in the translated models also. + */ + protected function syncTranslatableFileNames() + { + $knownLocales = array_keys($this->translatableAttributes); + foreach ($knownLocales as $locale) { + if ($locale == $this->translatableDefault) { + continue; + } + + if ($obj = $this->getCmsObjectForLocale($locale)) { + $obj->fileName = $this->model->fileName; + $obj->forceSave(); + } + } + } + + /** + * Saves the translation data in the join table. + * @param string $locale + * @return void + */ + protected function storeTranslatableData($locale = null) + { + if (!$locale) { + $locale = $this->translatableContext; + } + + /* + * Model doesn't exist yet, defer this logic in memory + */ + if (!$this->model->exists) { + $this->model->bindEventOnce('model.afterCreate', function() use ($locale) { + $this->storeTranslatableData($locale); + }); + + return; + } + + $data = $this->translatableAttributes[$locale]; + + if (!$obj = $this->getCmsObjectForLocale($locale)) { + $model = $this->createModel(); + $obj = $model::forLocale($locale, $this->model); + $obj->fileName = $this->model->fileName; + } + + if (!$this->isEmptyDataSet($data)) { + $obj->fill($data); + $obj->forceSave(); + } + } + + /** + * Returns true if all attributes are empty (false when converted to booleans). + * @param array $data + * @return bool + */ + protected function isEmptyDataSet($data) + { + return !array_get($data, 'markup') && + !count(array_filter(array_get($data, 'viewBag', []))) && + !count(array_filter(array_get($data, 'placeholders', []))); + } + + /** + * Loads the translation data from the join table. + * @param string $locale + * @return array + */ + protected function loadTranslatableData($locale = null) + { + if (!$locale) { + $locale = $this->translatableContext; + } + + if (!$this->model->exists) { + return $this->translatableAttributes[$locale] = []; + } + + $obj = $this->getCmsObjectForLocale($locale); + + $result = $obj ? $obj->getAttributes() : []; + + $this->translatableViewBag[$locale] = $obj ? $obj->viewBag : []; + + return $this->translatableOriginals[$locale] = $this->translatableAttributes[$locale] = $result; + } + + protected function getCmsObjectForLocale($locale) + { + if ($locale == $this->translatableDefault) { + return $this->model; + } + + $model = $this->createModel(); + return $model::findLocale($locale, $this->model); + } + + /** + * Internal method, prepare the form model object + * @return Model + */ + protected function createModel() + { + $class = $this->getTranslatableModelClass(); + $model = new $class; + return $model; + } + + /** + * Returns a collection of fields that will be hashed. + * @return array + */ + public function getTranslatableModelClass() + { + if (property_exists($this->model, 'translatableModel')) { + return $this->model->translatableModel; + } + + return 'RainLab\Translate\Classes\MLCmsObject'; + } +} diff --git a/plugins/rainlab/translate/behaviors/TranslatableModel.php b/plugins/rainlab/translate/behaviors/TranslatableModel.php new file mode 100755 index 0000000..21c759f --- /dev/null +++ b/plugins/rainlab/translate/behaviors/TranslatableModel.php @@ -0,0 +1,357 @@ +morphMany['translations'] = [ + 'RainLab\Translate\Models\Attribute', + 'name' => 'model' + ]; + + // October v2.0 + if (class_exists('System')) { + $this->extendFileModels('attachOne'); + $this->extendFileModels('attachMany'); + } + + // Clean up indexes when this model is deleted + $model->bindEvent('model.afterDelete', function() use ($model) { + Db::table('rainlab_translate_attributes') + ->where('model_id', $model->getKey()) + ->where('model_type', get_class($model)) + ->delete(); + + Db::table('rainlab_translate_indexes') + ->where('model_id', $model->getKey()) + ->where('model_type', get_class($model)) + ->delete(); + }); + } + + /** + * extendFileModels will swap the standard File model with MLFile instead + */ + protected function extendFileModels(string $relationGroup) + { + foreach ($this->model->$relationGroup as $relationName => $relationObj) { + $relationClass = is_array($relationObj) ? $relationObj[0] : $relationObj; + if ($relationClass === \System\Models\File::class) { + if (is_array($relationObj)) { + $this->model->$relationGroup[$relationName][0] = \RainLab\Translate\Models\MLFile::class; + } + else { + $this->model->$relationGroup[$relationName] = \RainLab\Translate\Models\MLFile::class; + } + } + } + } + + /** + * scopeTransWhere applies a translatable index to a basic query. This scope will join the + * index table and can be executed neither more than once, nor with scopeTransOrder. + * @param Builder $query + * @param string $index + * @param string $value + * @param string $locale + * @return Builder + */ + public function scopeTransWhere($query, $index, $value, $locale = null, $operator = '=') + { + return $this->transWhereInternal($query, $index, $value, [ + 'locale' => $locale, + 'operator' => $operator + ]); + } + + /** + * scopeTransWhereNoFallback is identical to scopeTransWhere except it will not + * use a fallback query when there are no indexes found. + * @see scopeTransWhere + */ + public function scopeTransWhereNoFallback($query, $index, $value, $locale = null, $operator = '=') + { + // Ignore translatable indexes in default locale context + if(($locale ?: $this->translatableContext) === $this->translatableDefault) { + return $query->where($index, $operator, $value); + } + + return $this->transWhereInternal($query, $index, $value, [ + 'locale' => $locale, + 'operator' => $operator, + 'noFallback' => true + ]); + } + + /** + * transWhereInternal + * @link https://github.com/rainlab/translate-plugin/pull/623 + */ + protected function transWhereInternal($query, $index, $value, $options = []) + { + extract(array_merge([ + 'locale' => null, + 'operator' => '=', + 'noFallback' => false + ], $options)); + + if (!$locale) { + $locale = $this->translatableContext; + } + + // Separate query into two separate queries for improved performance + $translateIndexes = Db::table('rainlab_translate_indexes') + ->where('rainlab_translate_indexes.model_type', '=', $this->getClass()) + ->where('rainlab_translate_indexes.locale', '=', $locale) + ->where('rainlab_translate_indexes.item', $index) + ->where('rainlab_translate_indexes.value', $operator, $value) + ->pluck('model_id') + ; + + if ($translateIndexes->count() || $noFallback) { + $query->whereIn($this->model->getQualifiedKeyName(), $translateIndexes); + } + else { + $query->where($index, $operator, $value); + } + + return $query; + } + + /** + * Applies a sort operation with a translatable index to a basic query. This scope will join the index table. + * @param Builder $query + * @param string $index + * @param string $direction + * @param string $locale + * @return Builder + */ + public function scopeTransOrderBy($query, $index, $direction = 'asc', $locale = null) + { + if (!$locale) { + $locale = $this->translatableContext; + } + $indexTableAlias = 'rainlab_translate_indexes_' . $index . '_' . $locale; + + $query->select( + $this->model->getTable().'.*', + Db::raw('COALESCE(' . $indexTableAlias . '.value, '. $this->model->getTable() .'.'.$index.') AS translate_sorting_key') + ); + + $query->orderBy('translate_sorting_key', $direction); + + $this->joinTranslateIndexesTable($query, $locale, $index, $indexTableAlias); + + return $query; + } + + /** + * Joins the translatable indexes table to a query. + * @param Builder $query + * @param string $locale + * @param string $indexTableAlias + * @return Builder + */ + protected function joinTranslateIndexesTable($query, $locale, $index, $indexTableAlias) + { + $joinTableWithAlias = 'rainlab_translate_indexes as ' . $indexTableAlias; + // check if table with same name and alias is already joined + if (collect($query->getQuery()->joins)->contains('table', $joinTableWithAlias)) { + return $query; + } + + $query->leftJoin($joinTableWithAlias, function($join) use ($locale, $index, $indexTableAlias) { + $join + ->on(Db::raw(DbDongle::cast($this->model->getQualifiedKeyName(), 'TEXT')), '=', $indexTableAlias . '.model_id') + ->where($indexTableAlias . '.model_type', '=', $this->getClass()) + ->where($indexTableAlias . '.item', '=', $index) + ->where($indexTableAlias . '.locale', '=', $locale); + }); + + return $query; + } + + /** + * Saves the translation data in the join table. + * @param string $locale + * @return void + */ + protected function storeTranslatableData($locale = null) + { + if (!$locale) { + $locale = $this->translatableContext; + } + + /* + * Model doesn't exist yet, defer this logic in memory + */ + if (!$this->model->exists) { + $this->model->bindEventOnce('model.afterCreate', function() use ($locale) { + $this->storeTranslatableData($locale); + }); + + return; + } + + /** + * @event model.translate.resolveComputedFields + * Resolve computed fields before saving + * + * Example usage: + * + * Override Model's __construct method + * + * public function __construct(array $attributes = []) + * { + * parent::__construct($attributes); + * + * $this->bindEvent('model.translate.resolveComputedFields', function ($locale) { + * return [ + * 'content_html' => + * self::formatHtml($this->asExtension('TranslatableModel') + * ->getAttributeTranslated('content', $locale)) + * ]; + * }); + * } + * + */ + $computedFields = $this->model->fireEvent('model.translate.resolveComputedFields', [$locale], true); + if (is_array($computedFields)) { + $this->translatableAttributes[$locale] = array_merge($this->translatableAttributes[$locale], $computedFields); + } + + $this->storeTranslatableBasicData($locale); + $this->storeTranslatableIndexData($locale); + } + + /** + * Saves the basic translation data in the join table. + * @param string $locale + * @return void + */ + protected function storeTranslatableBasicData($locale = null) + { + $data = json_encode($this->translatableAttributes[$locale], JSON_UNESCAPED_UNICODE); + + $obj = Db::table('rainlab_translate_attributes') + ->where('locale', $locale) + ->where('model_id', $this->model->getKey()) + ->where('model_type', $this->getClass()); + + if ($obj->count() > 0) { + $obj->update(['attribute_data' => $data]); + } + else { + Db::table('rainlab_translate_attributes')->insert([ + 'locale' => $locale, + 'model_id' => $this->model->getKey(), + 'model_type' => $this->getClass(), + 'attribute_data' => $data + ]); + } + } + + /** + * Saves the indexed translation data in the join table. + * @param string $locale + * @return void + */ + protected function storeTranslatableIndexData($locale = null) + { + $optionedAttributes = $this->getTranslatableAttributesWithOptions(); + if (!count($optionedAttributes)) { + return; + } + + $data = $this->translatableAttributes[$locale]; + + foreach ($optionedAttributes as $attribute => $options) { + if (!array_get($options, 'index', false)) { + continue; + } + + $value = array_get($data, $attribute); + + $obj = Db::table('rainlab_translate_indexes') + ->where('locale', $locale) + ->where('model_id', $this->model->getKey()) + ->where('model_type', $this->getClass()) + ->where('item', $attribute); + + $recordExists = $obj->count() > 0; + + if (!strlen($value)) { + if ($recordExists) { + $obj->delete(); + } + continue; + } + + if ($recordExists) { + $obj->update(['value' => $value]); + } + else { + Db::table('rainlab_translate_indexes')->insert([ + 'locale' => $locale, + 'model_id' => $this->model->getKey(), + 'model_type' => $this->getClass(), + 'item' => $attribute, + 'value' => $value + ]); + } + } + } + + /** + * Loads the translation data from the join table. + * @param string $locale + * @return array + */ + protected function loadTranslatableData($locale = null) + { + if (!$locale) { + $locale = $this->translatableContext; + } + + if (!$this->model->exists) { + return $this->translatableAttributes[$locale] = []; + } + + $obj = $this->model->translations->first(function ($value, $key) use ($locale) { + return $value->attributes['locale'] === $locale; + }); + + $result = $obj ? json_decode($obj->attribute_data, true) : []; + + return $this->translatableOriginals[$locale] = $this->translatableAttributes[$locale] = $result; + } + + /** + * Returns the class name of the model. Takes any + * custom morphMap aliases into account. + * + * @return string + */ + protected function getClass() + { + return $this->model->getMorphClass(); + } +} diff --git a/plugins/rainlab/translate/behaviors/TranslatablePage.php b/plugins/rainlab/translate/behaviors/TranslatablePage.php new file mode 100644 index 0000000..4797e29 --- /dev/null +++ b/plugins/rainlab/translate/behaviors/TranslatablePage.php @@ -0,0 +1,140 @@ +model->bindEvent('model.afterFetch', function() { + $this->translatableOriginals = $this->getModelAttributes(); + + if (!App::runningInBackend()) { + $this->rewriteTranslatablePageAttributes(); + } + }); + } + + public function isTranslatable($key) + { + if ($key === 'translatable' || $this->translatableDefault == $this->translatableContext) { + return false; + } + + return in_array($key, $this->model->translatable); + } + + public function getTranslatableAttributes() + { + $attributes = []; + + foreach ($this->model->translatable as $attr) { + $attributes[] = 'settings['.$attr.']'; + } + + return $attributes; + } + + public function getModelAttributes() + { + $attributes = []; + + foreach ($this->model->translatable as $attr) { + $attributes[$attr] = $this->model[$attr]; + } + + return $attributes; + } + + public function initTranslatableContext() + { + parent::initTranslatableContext(); + $this->translatableOriginals = $this->getModelAttributes(); + } + + public function rewriteTranslatablePageAttributes($locale = null) + { + $locale = $locale ?: $this->translatableContext; + + foreach ($this->model->translatable as $attr) { + $localeAttr = $this->translatableOriginals[$attr]; + + if ($locale != $this->translatableDefault) { + $translated = $this->getAttributeTranslated($attr, $locale); + $localeAttr = ($translated ?: $this->translatableUseFallback) ? $localeAttr : null; + } + + $this->model[$attr] = $localeAttr; + } + } + + public function getAttributeTranslated($key, $locale = null) + { + $locale = $locale ?: $this->translatableContext; + + if (strpbrk($key, '[]') !== false) { + // Retrieve attr name within brackets (i.e. settings[title] yields title) + $key = preg_split("/[\[\]]/", $key)[1]; + } + + $default = ($locale == $this->translatableDefault || $this->translatableUseFallback) + ? array_get($this->translatableOriginals, $key) + : ''; + + $localeAttr = sprintf('viewBag.locale%s.%s', ucfirst($key), $locale); + return array_get($this->model->attributes, $localeAttr, $default); + } + + public function setAttributeTranslated($key, $value, $locale = null) + { + $locale = $locale ?: $this->translatableContext; + + if ($locale == $this->translatableDefault) { + return; + } + + if (strpbrk($key, '[]') !== false) { + // Retrieve attr name within brackets (i.e. settings[title] yields title) + $key = preg_split("/[\[\]]/", $key)[1]; + } + + if ($value == array_get($this->translatableOriginals, $key)) { + return; + } + + $this->saveTranslation($key, $value, $locale); + $this->model->bindEventOnce('model.beforeSave', function() use ($key, $value, $locale) { + $this->saveTranslation($key, $value, $locale); + }); + } + + public function saveTranslation($key, $value, $locale) + { + $localeAttr = sprintf('viewBag.locale%s.%s', ucfirst($key), $locale); + if (!$value) { + array_forget($this->model->attributes, $localeAttr); + } + else { + array_set($this->model->attributes, $localeAttr, $value); + } + } + + // Not needed but parent abstract model requires those + protected function storeTranslatableData($locale = null) {} + protected function loadTranslatableData($locale = null) {} +} diff --git a/plugins/rainlab/translate/behaviors/TranslatablePageUrl.php b/plugins/rainlab/translate/behaviors/TranslatablePageUrl.php new file mode 100644 index 0000000..bbc7147 --- /dev/null +++ b/plugins/rainlab/translate/behaviors/TranslatablePageUrl.php @@ -0,0 +1,173 @@ +model = $model; + + $this->initTranslatableContext(); + + $this->model->bindEvent('model.afterFetch', function() { + $this->translatableDefaultUrl = $this->getModelUrl(); + + if (!App::runningInBackend()) { + $this->rewriteTranslatablePageUrl(); + } + }); + } + + protected function setModelUrl($value) + { + if ($this->model instanceof \RainLab\Pages\Classes\Page) { + array_set($this->model->attributes, 'viewBag.url', $value); + } + else { + $this->model->url = $value; + } + } + + protected function getModelUrl() + { + if ($this->model instanceof \RainLab\Pages\Classes\Page) { + return array_get($this->model->attributes, 'viewBag.url'); + } + else { + return $this->model->url; + } + } + + /** + * Initializes this class, sets the default language code to use. + * @return void + */ + public function initTranslatableContext() + { + $translate = Translator::instance(); + $this->translatableContext = $translate->getLocale(); + $this->translatableDefault = $translate->getDefaultLocale(); + } + + /** + * Checks if a translated URL exists and rewrites it, this method + * should only be called from the context of front-end. + * @return void + */ + public function rewriteTranslatablePageUrl($locale = null) + { + $locale = $locale ?: $this->translatableContext; + $localeUrl = $this->translatableDefaultUrl; + + if ($locale != $this->translatableDefault) { + $localeUrl = $this->getSettingsUrlAttributeTranslated($locale) ?: $localeUrl; + } + + $this->setModelUrl($localeUrl); + } + + /** + * Determines if a locale has a translated URL. + * @return bool + */ + public function hasTranslatablePageUrl($locale = null) + { + $locale = $locale ?: $this->translatableContext; + + return strlen($this->getSettingsUrlAttributeTranslated($locale)) > 0; + } + + /** + * Mutator detected by MLControl + * @return string + */ + public function getSettingsUrlAttributeTranslated($locale) + { + $defaults = ($locale == $this->translatableDefault) ? $this->translatableDefaultUrl : null; + + return array_get($this->model->attributes, 'viewBag.localeUrl.'.$locale, $defaults); + } + + /** + * Mutator detected by MLControl + * @return void + */ + public function setSettingsUrlAttributeTranslated($value, $locale) + { + if ($locale == $this->translatableDefault) { + return; + } + + if ($value == $this->translatableDefaultUrl) { + return; + } + + /* + * The CMS controller will purge attributes just before saving, this + * will ensure the attributes are injected after this logic. + */ + $this->model->bindEventOnce('model.beforeSave', function() use ($value, $locale) { + if (!$value) { + array_forget($this->model->attributes, 'viewBag.localeUrl.'.$locale); + } + else { + array_set($this->model->attributes, 'viewBag.localeUrl.'.$locale, $value); + } + }); + } + + /** + * Mutator detected by MLControl, proxy for Static Pages plugin. + * @return string + */ + public function getViewBagUrlAttributeTranslated($locale) + { + return $this->getSettingsUrlAttributeTranslated($locale); + } + + /** + * Mutator detected by MLControl, proxy for Static Pages plugin. + * @return void + */ + public function setViewBagUrlAttributeTranslated($value, $locale) + { + $this->setSettingsUrlAttributeTranslated($value, $locale); + } +} diff --git a/plugins/rainlab/translate/classes/EventRegistry.php b/plugins/rainlab/translate/classes/EventRegistry.php new file mode 100644 index 0000000..262bf91 --- /dev/null +++ b/plugins/rainlab/translate/classes/EventRegistry.php @@ -0,0 +1,408 @@ +code ?? null; + + $properties = []; + foreach ($locales as $locale => $label) { + if ($locale == $defaultLocale) { + continue; + } + + $properties[] = [ + 'property' => 'localeUrl.'.$locale, + 'title' => 'cms::lang.editor.url', + 'tab' => $label, + 'type' => 'string', + ]; + + $properties[] = [ + 'property' => 'localeTitle.'.$locale, + 'title' => 'cms::lang.editor.title', + 'tab' => $label, + 'type' => 'string', + ]; + + $properties[] = [ + 'property' => 'localeDescription.'.$locale, + 'title' => 'cms::lang.editor.description', + 'tab' => $label, + 'type' => 'text', + ]; + + $properties[] = [ + 'property' => 'localeMeta_title.'.$locale, + 'title' => 'cms::lang.editor.meta_title', + 'tab' => $label, + 'type' => 'string', + ]; + + $properties[] = [ + 'property' => 'localeMeta_description.'.$locale, + 'title' => 'cms::lang.editor.meta_description', + 'tab' => $label, + 'type' => 'text', + ]; + } + + $dataHolder->buttons[] = [ + 'button' => 'rainlab.translate::lang.plugin.name', + 'icon' => 'octo-icon-globe', + 'popupTitle' => 'Translate Page Properties', + 'properties' => $properties + ]; + } + + // + // Utility + // + + /** + * registerFormFieldReplacements + */ + public function registerFormFieldReplacements($widget) + { + // Replace with ML Controls for translatable attributes + $this->registerModelTranslation($widget); + + // Handle URL translations + $this->registerPageUrlTranslation($widget); + + // Handle RainLab.Pages MenuItem translations + if (PluginManager::instance()->exists('RainLab.Pages')) { + $this->registerMenuItemTranslation($widget); + } + } + + /** + * registerMenuItemTranslation for RainLab.Pages MenuItem data + * @param Backend\Widgets\Form $widget + */ + public function registerMenuItemTranslation($widget) + { + if ($widget->model instanceof \RainLab\Pages\Classes\MenuItem) { + $defaultLocale = LocaleModel::getDefault(); + $availableLocales = LocaleModel::listAvailable(); + $fieldsToTranslate = ['title', 'url']; + + // Replace specified fields with multilingual versions + foreach ($fieldsToTranslate as $fieldName) { + $widget->fields[$fieldName]['type'] = 'mltext'; + + foreach ($availableLocales as $code => $locale) { + if (!$defaultLocale || $defaultLocale->code === $code) { + continue; + } + + // Add data locker fields for the different locales under the `viewBag[locale]` property + $widget->fields["viewBag[locale][$code][$fieldName]"] = [ + 'cssClass' => 'hidden', + 'attributes' => [ + 'data-locale' => $code, + 'data-field-name' => $fieldName, + ], + ]; + } + } + } + } + + // + // Translate URLs + // + + /** + * registerPageUrlTranslation + */ + public function registerPageUrlTranslation($widget) + { + if (!$model = $widget->model) { + return; + } + + if ( + $model instanceof Page && + isset($widget->fields['settings[url]']) + ) { + $widget->fields['settings[url]']['type'] = 'mltext'; + } + elseif ( + $model instanceof \RainLab\Pages\Classes\Page && + isset($widget->fields['viewBag[url]']) + ) { + $widget->fields['viewBag[url]']['type'] = 'mltext'; + } + } + + // + // Translatable behavior + // + + /** + * registerModelTranslation automatically replaces form fields for multi-lingual equivalents + */ + public function registerModelTranslation($widget) + { + if ($widget->isNested) { + return; + } + + if (!$model = $widget->model) { + return; + } + + if (!method_exists($model, 'isClassExtendedWith')) { + return; + } + + if ( + !$model->isClassExtendedWith(\RainLab\Translate\Behaviors\TranslatableModel::class) && + !$model->isClassExtendedWith(\RainLab\Translate\Behaviors\TranslatablePage::class) && + !$model->isClassExtendedWith(\RainLab\Translate\Behaviors\TranslatableCmsObject::class) + ) { + return; + } + + if (!$model->hasTranslatableAttributes()) { + return; + } + + if (!empty($widget->fields)) { + $widget->fields = $this->processFormMLFields($widget->fields, $model); + } + + if (!empty($widget->tabs['fields'])) { + $widget->tabs['fields'] = $this->processFormMLFields($widget->tabs['fields'], $model); + } + + if (!empty($widget->secondaryTabs['fields'])) { + $widget->secondaryTabs['fields'] = $this->processFormMLFields($widget->secondaryTabs['fields'], $model); + } + } + + /** + * processFormMLFields function to replace standard fields with multi-lingual equivalents + * @param array $fields + * @param Model $model + * @return array + */ + protected function processFormMLFields($fields, $model) + { + $typesMap = [ + 'text' => 'mltext', + 'textarea' => 'mltextarea', + 'richeditor' => 'mlricheditor', + 'markdown' => 'mlmarkdowneditor', + 'repeater' => 'mlrepeater', + 'nestedform' => 'mlnestedform', + 'mediafinder' => 'mlmediafinder', + ]; + + $translatable = array_flip($model->getTranslatableAttributes()); + + /* + * Special: A custom field "markup_html" is used for Content templates. + */ + if ($model instanceof Content && array_key_exists('markup', $translatable)) { + $translatable['markup_html'] = true; + } + + foreach ($fields as $name => $config) { + if (!array_key_exists($name, $translatable)) { + continue; + } + + $type = array_get($config, 'type', 'text'); + + if (array_key_exists($type, $typesMap)) { + $fields[$name]['type'] = $typesMap[$type]; + } + } + + return $fields; + } + + // + // Theme + // + + /** + * importMessagesFromTheme + */ + public function importMessagesFromTheme($themeCode) + { + try { + (new ThemeScanner)->scanThemeConfigForMessages($themeCode); + } + catch (Exception $ex) {} + } + + // + // CMS objects + // + + /** + * setMessageContext for translation caching. + */ + public function setMessageContext($page) + { + if (!$page) { + return; + } + + $translator = Translator::instance(); + + Message::setContext($translator->getLocale(), $page->url); + } + + /** + * findTranslatedContentFile adds language suffixes to content files. + * @return string|null + */ + public function findTranslatedContentFile($controller, $fileName) + { + if (!strlen(File::extension($fileName))) { + $fileName .= '.htm'; + } + + /* + * Splice the active locale in to the filename + * - content.htm -> content.en.htm + */ + $locale = Translator::instance()->getLocale(); + $fileName = substr_replace($fileName, '.'.$locale, strrpos($fileName, '.'), 0); + if (($content = Content::loadCached($controller->getTheme(), $fileName)) !== null) { + return $content; + } + } + + // + // Static pages + // + + /** + * pruneTranslatedContentTemplates removes localized content files from templates collection + * @param \October\Rain\Database\Collection $templates + * @return \October\Rain\Database\Collection + */ + public function pruneTranslatedContentTemplates($templates) + { + $locales = LocaleModel::listAvailable(); + + $extensions = array_map(function($ext) { + return '.'.$ext; + }, array_keys($locales)); + + return $templates->filter(function($template) use ($extensions) { + return !Str::endsWith($template->getBaseFileName(), $extensions); + }); + } + + /** + * findLocalizedMailViewContent adds language suffixes to mail view files. + * @param \October\Rain\Mail\Mailer $mailer + * @param \Illuminate\Mail\Message $message + * @param string $view + * @param array $data + * @param string $raw + * @param string $plain + * @return bool|void Will return false if the translation process successfully replaced the original message with a translated version to prevent the original version from being processed. + */ + public function findLocalizedMailViewContent($mailer, $message, $view, $data, $raw, $plain) + { + // Raw content cannot be localized at this level + if (!empty($raw)) { + return; + } + + // Get the locale to use for this template + $locale = !empty($data['_current_locale']) ? $data['_current_locale'] : App::getLocale(); + + $factory = $mailer->getViewFactory(); + + if (!empty($view)) { + $view = $this->getLocalizedView($factory, $view, $locale); + } + + if (!empty($plain)) { + $plain = $this->getLocalizedView($factory, $plain, $locale); + } + + $code = $view ?: $plain; + if (empty($code)) { + return null; + } + + $plainOnly = empty($view); + + if (MailManager::instance()->addContentToMailer($message, $code, $data, $plainOnly)) { + // the caller who fired the event is expecting a FALSE response to halt the event + return false; + } + } + + /** + * getLocalizedView searches mail view files based on locale + * @param \October\Rain\Mail\Mailer $mailer + * @param \Illuminate\Mail\Message $message + * @param string $code + * @param string $locale + * @return string|null + */ + public function getLocalizedView($factory, $code, $locale) + { + $locale = strtolower($locale); + + $searchPaths[] = $locale; + + if (str_contains($locale, '-')) { + list($lang) = explode('-', $locale); + $searchPaths[] = $lang; + } + + foreach ($searchPaths as $path) { + $localizedView = sprintf('%s-%s', $code, $path); + + if ($factory->exists($localizedView)) { + return $localizedView; + } + } + return null; + } +} diff --git a/plugins/rainlab/translate/classes/LocaleMiddleware.php b/plugins/rainlab/translate/classes/LocaleMiddleware.php new file mode 100644 index 0000000..20d4f03 --- /dev/null +++ b/plugins/rainlab/translate/classes/LocaleMiddleware.php @@ -0,0 +1,31 @@ +isConfigured(); + + if (!$translator->loadLocaleFromRequest()) { + if (Config::get('rainlab.translate::prefixDefaultLocale')) { + $translator->loadLocaleFromSession(); + } else { + $translator->setLocale($translator->getDefaultLocale()); + } + } + + return $next($request); + } +} diff --git a/plugins/rainlab/translate/classes/MLCmsObject.php b/plugins/rainlab/translate/classes/MLCmsObject.php new file mode 100644 index 0000000..2dce2a0 --- /dev/null +++ b/plugins/rainlab/translate/classes/MLCmsObject.php @@ -0,0 +1,56 @@ +theme); + } + + public static function findLocale($locale, $page) + { + return static::forLocale($locale, $page)->find($page->fileName); + } + + /** + * Returns the directory name corresponding to the object type. + * For pages the directory name is "pages", for layouts - "layouts", etc. + * @return string + */ + public function getObjectTypeDirName() + { + $dirName = static::$parent->getObjectTypeDirName(); + + if (strlen(static::$locale)) { + $dirName .= '-' . static::$locale; + } + + return $dirName; + } +} diff --git a/plugins/rainlab/translate/classes/MLContent.php b/plugins/rainlab/translate/classes/MLContent.php new file mode 100644 index 0000000..0402d8d --- /dev/null +++ b/plugins/rainlab/translate/classes/MLContent.php @@ -0,0 +1,70 @@ +exists) { + return null; + } + + $fileName = $page->getOriginal('fileName') ?: $page->fileName; + + $fileName = static::addLocaleToFileName($fileName, $locale); + + return static::forLocale($locale, $page)->find($fileName); + } + + /** + * Returns the directory name corresponding to the object type. + * Content does not use localized sub directories, but as file suffix instead. + * @return string + */ + public function getObjectTypeDirName() + { + return static::$parent->getObjectTypeDirName(); + } + + /** + * Splice in the locale when setting the file name. + * @param mixed $value + */ + public function setFileNameAttribute($value) + { + $value = static::addLocaleToFileName($value, static::$locale); + + parent::setFileNameAttribute($value); + } + + /** + * Splice the active locale in to the filename + * - content.htm -> content.en.htm + */ + protected static function addLocaleToFileName($fileName, $locale) + { + /* + * Check locale not already present + */ + $parts = explode('.', $fileName); + array_shift($parts); + + foreach ($parts as $part) { + if (trim($part) === $locale) { + return $fileName; + } + } + + return substr_replace($fileName, '.'.$locale, strrpos($fileName, '.'), 0); + } +} diff --git a/plugins/rainlab/translate/classes/MLStaticPage.php b/plugins/rainlab/translate/classes/MLStaticPage.php new file mode 100644 index 0000000..0fba770 --- /dev/null +++ b/plugins/rainlab/translate/classes/MLStaticPage.php @@ -0,0 +1,118 @@ +getPlaceholdersAttribute(); + } + + /** + * Parses the page placeholder {% put %} tags and extracts the placeholder values. + * @return array Returns an associative array of the placeholder names and values. + */ + public function getPlaceholdersAttribute() + { + if (!strlen($this->code)) { + return []; + } + + if ($placeholders = array_get($this->attributes, 'placeholders')) { + return $placeholders; + } + + $bodyNode = $this->getTwigNodeTree($this->code)->getNode('body')->getNode(0); + if ($bodyNode instanceof \Cms\Twig\PutNode) { + $bodyNode = [$bodyNode]; + } + + $result = []; + foreach ($bodyNode as $node) { + if (!$node instanceof \Cms\Twig\PutNode) { + continue; + } + + // October CMS v2.2 and above + if (class_exists('System') && version_compare(\System::VERSION, '2.1') === 1) { + $names = $node->getNode('names'); + $values = $node->getNode('values'); + $isCapture = $node->getAttribute('capture'); + if ($isCapture) { + $name = $names->getNode(0); + $result[$name->getAttribute('name')] = trim($values->getAttribute('data')); + } + } + // Legacy PutNode support + else { + $values = $node->getNode('body'); + $result[$node->getAttribute('name')] = trim($values->getAttribute('data')); + } + } + + $this->attributes['placeholders'] = $result; + + return $result; + } + + /** + * Takes an array of placeholder data (key: code, value: content) and renders + * it as a single string of Twig markup against the "code" attribute. + * @param array $value + * @return void + */ + public function setPlaceholdersAttribute($value) + { + if (!is_array($value)) { + return; + } + + $placeholders = $value; + $result = ''; + + foreach ($placeholders as $code => $content) { + if (!strlen($content)) { + continue; + } + + $result .= '{% put '.$code.' %}'.PHP_EOL; + $result .= $content.PHP_EOL; + $result .= '{% endput %}'.PHP_EOL; + $result .= PHP_EOL; + } + + $this->attributes['code'] = trim($result); + $this->attributes['placeholders'] = $placeholders; + } + + /** + * Disables safe mode check for static pages. + * + * This allows developers to use placeholders in layouts even if safe mode is enabled. + * + * @return void + */ + protected function checkSafeMode() + { + } +} diff --git a/plugins/rainlab/translate/classes/ThemeScanner.php b/plugins/rainlab/translate/classes/ThemeScanner.php new file mode 100644 index 0000000..3ad0929 --- /dev/null +++ b/plugins/rainlab/translate/classes/ThemeScanner.php @@ -0,0 +1,229 @@ +scanForMessages(); + + /** + * @event rainlab.translate.themeScanner.afterScan + * Fires after theme scanning. + * + * Example usage: + * + * Event::listen('rainlab.translate.themeScanner.afterScan', function (ThemeScanner $scanner) { + * // added an extra scan. Add generation files... + * }); + * + */ + Event::fire('rainlab.translate.themeScanner.afterScan', [$obj]); + } + + /** + * Scans theme templates and config for messages. + * @return void + */ + public function scanForMessages() + { + // Set all messages initially as being not found. The scanner later + // sets the entries it finds as found. + Message::query()->update(['found' => false]); + + $this->scanThemeConfigForMessages(); + $this->scanThemeTemplatesForMessages(); + $this->scanMailTemplatesForMessages(); + } + + /** + * Scans the theme configuration for defined messages + * @return void + */ + public function scanThemeConfigForMessages($themeCode = null) + { + if (!$themeCode) { + $theme = Theme::getActiveTheme(); + + if (!$theme) { + return; + } + } + else { + if (!Theme::exists($themeCode)) { + return; + } + + $theme = Theme::load($themeCode); + } + + // October v2.0 + if (class_exists('System') && $theme->hasParentTheme()) { + $parentTheme = $theme->getParentTheme(); + + try { + if (!$this->scanThemeConfigForMessagesInternal($theme)) { + $this->scanThemeConfigForMessagesInternal($parentTheme); + } + } + catch (Exception $ex) { + $this->scanThemeConfigForMessagesInternal($parentTheme); + } + } + else { + $this->scanThemeConfigForMessagesInternal($theme); + } + } + + /** + * scanThemeConfigForMessagesInternal + */ + protected function scanThemeConfigForMessagesInternal(Theme $theme) + { + $config = $theme->getConfigArray('translate'); + + if (!count($config)) { + return false; + } + + $translator = Translator::instance(); + $keys = []; + + foreach ($config as $locale => $messages) { + if (is_string($messages)) { + // $message is a yaml filename, load the yaml file + $messages = $theme->getConfigArray('translate.'.$locale); + } + $keys = array_merge($keys, array_keys($messages)); + } + + Message::importMessages($keys); + + foreach ($config as $locale => $messages) { + if (is_string($messages)) { + // $message is a yaml filename, load the yaml file + $messages = $theme->getConfigArray('translate.'.$locale); + } + Message::importMessageCodes($messages, $locale); + } + } + + /** + * Scans the theme templates for message references. + * @return void + */ + public function scanThemeTemplatesForMessages() + { + $messages = []; + + foreach (Layout::all() as $layout) { + $messages = array_merge($messages, $this->parseContent($layout->markup)); + } + + foreach (Page::all() as $page) { + $messages = array_merge($messages, $this->parseContent($page->markup)); + } + + foreach (Partial::all() as $partial) { + $messages = array_merge($messages, $this->parseContent($partial->markup)); + } + + Message::importMessages($messages); + } + + /** + * Scans the mail templates for message references. + * @return void + */ + public function scanMailTemplatesForMessages() + { + $messages = []; + + foreach (MailTemplate::allTemplates() as $mailTemplate) { + $messages = array_merge($messages, $this->parseContent($mailTemplate->subject)); + $messages = array_merge($messages, $this->parseContent($mailTemplate->content_html)); + } + + Message::importMessages($messages); + } + + /** + * Parse the known language tag types in to messages. + * @param string $content + * @return array + */ + protected function parseContent($content) + { + $messages = []; + $messages = array_merge($messages, $this->processStandardTags($content)); + + return $messages; + } + + /** + * Process standard language filter tag (_|) + * @param string $content + * @return array + */ + protected function processStandardTags($content) + { + $messages = []; + + /* + * Regex used: + * + * {{'AJAX framework'|_}} + * {{\s*'([^'])+'\s*[|]\s*_\s*}} + * + * {{'AJAX framework'|_(variables)}} + * {{\s*'([^'])+'\s*[|]\s*_\s*\([^\)]+\)\s*}} + */ + + $quoteChar = preg_quote("'"); + + preg_match_all('#{{\s*'.$quoteChar.'([^'.$quoteChar.']+)'.$quoteChar.'\s*[|]\s*_\s*(?:[|].+)?}}#', $content, $match); + if (isset($match[1])) { + $messages = array_merge($messages, $match[1]); + } + + preg_match_all('#{{\s*'.$quoteChar.'([^'.$quoteChar.']+)'.$quoteChar.'\s*[|]\s*_\s*\([^\)]+\)\s*}}#', $content, $match); + if (isset($match[1])) { + $messages = array_merge($messages, $match[1]); + } + + $quoteChar = preg_quote('"'); + + preg_match_all('#{{\s*'.$quoteChar.'([^'.$quoteChar.']+)'.$quoteChar.'\s*[|]\s*_\s*(?:[|].+)?}}#', $content, $match); + if (isset($match[1])) { + $messages = array_merge($messages, $match[1]); + } + + preg_match_all('#{{\s*'.$quoteChar.'([^'.$quoteChar.']+)'.$quoteChar.'\s*[|]\s*_\s*\([^\)]+\)\s*}}#', $content, $match); + if (isset($match[1])) { + $messages = array_merge($messages, $match[1]); + } + + return $messages; + } +} diff --git a/plugins/rainlab/translate/classes/TranslatableBehavior.php b/plugins/rainlab/translate/classes/TranslatableBehavior.php new file mode 100644 index 0000000..3ae9e65 --- /dev/null +++ b/plugins/rainlab/translate/classes/TranslatableBehavior.php @@ -0,0 +1,494 @@ +model = $model; + + $this->initTranslatableContext(); + + $this->model->bindEvent('model.beforeGetAttribute', function ($key) use ($model) { + if ($this->isTranslatable($key)) { + $value = $this->getAttributeTranslated($key); + if ($model->hasGetMutator($key)) { + $method = 'get' . Str::studly($key) . 'Attribute'; + $value = $model->{$method}($value); + } + return $value; + } + }); + + $this->model->bindEvent('model.beforeSetAttribute', function ($key, $value) use ($model) { + if ($this->isTranslatable($key)) { + $value = $this->setAttributeTranslated($key, $value); + if ($model->hasSetMutator($key)) { + $method = 'set' . Str::studly($key) . 'Attribute'; + $value = $model->{$method}($value); + } + return $value; + } + }); + + $this->model->bindEvent('model.saveInternal', function() { + $this->syncTranslatableAttributes(); + }); + } + + /** + * Initializes this class, sets the default language code to use. + * @return void + */ + public function initTranslatableContext() + { + $translate = Translator::instance(); + $this->translatableContext = $translate->getLocale(); + $this->translatableDefault = $translate->getDefaultLocale(); + } + + /** + * Checks if an attribute should be translated or not. + * @param string $key + * @return boolean + */ + public function isTranslatable($key) + { + if ($key === 'translatable' || $this->translatableDefault == $this->translatableContext) { + return false; + } + + return in_array($key, $this->model->getTranslatableAttributes()); + } + + /** + * Disables translation fallback locale. + * @return self + */ + public function noFallbackLocale() + { + $this->translatableUseFallback = false; + + return $this->model; + } + + /** + * Enables translation fallback locale. + * @return self + */ + public function withFallbackLocale() + { + $this->translatableUseFallback = true; + + return $this->model; + } + + /** + * Returns a translated attribute value. + * + * The base value must come from 'attributes' on the model otherwise the process + * can possibly loop back to this event, then method triggered by __get() magic. + * + * @param string $key + * @param string $locale + * @return string + */ + public function getAttributeTranslated($key, $locale = null) + { + if ($locale == null) { + $locale = $this->translatableContext; + } + + /* + * Result should not return NULL to successfully hook beforeGetAttribute event + */ + $result = ''; + + /* + * Default locale + */ + if ($locale == $this->translatableDefault) { + $result = $this->getAttributeFromData($this->model->attributes, $key); + } + /* + * Other locale + */ + else { + if (!array_key_exists($locale, $this->translatableAttributes)) { + $this->loadTranslatableData($locale); + } + + if ($this->hasTranslation($key, $locale)) { + $result = $this->getAttributeFromData($this->translatableAttributes[$locale], $key); + } + elseif ($this->translatableUseFallback) { + $result = $this->getAttributeFromData($this->model->attributes, $key); + } + } + + /* + * Handle jsonable attributes, default locale may return the value as a string + */ + if ( + is_string($result) && + method_exists($this->model, 'isJsonable') && + $this->model->isJsonable($key) + ) { + $result = json_decode($result, true); + } + + return $result; + } + + /** + * Returns all translated attribute values. + * @param string $locale + * @return array + */ + public function getTranslateAttributes($locale) + { + if (!array_key_exists($locale, $this->translatableAttributes)) { + $this->loadTranslatableData($locale); + } + + return array_get($this->translatableAttributes, $locale, []); + } + + /** + * Returns whether the attribute is translatable (has a translation) for the given locale. + * @param string $key + * @param string $locale + * @return bool + */ + public function hasTranslation($key, $locale) + { + /* + * If the default locale is passed, the attributes are retreived from the model, + * otherwise fetch the attributes from the $translatableAttributes property + */ + if ($locale == $this->translatableDefault) { + $translatableAttributes = $this->model->attributes; + } + else { + /* + * Ensure that the translatableData has been loaded + * @see https://github.com/rainlab/translate-plugin/issues/302 + */ + if (!isset($this->translatableAttributes[$locale])) { + $this->loadTranslatableData($locale); + } + + $translatableAttributes = $this->translatableAttributes[$locale]; + } + + return !!$this->getAttributeFromData($translatableAttributes, $key); + } + + /** + * Sets a translated attribute value. + * @param string $key Attribute + * @param string $value Value to translate + * @return string Translated value + */ + public function setAttributeTranslated($key, $value, $locale = null) + { + if ($locale == null) { + $locale = $this->translatableContext; + } + + if ($locale == $this->translatableDefault) { + return $this->setAttributeFromData($this->model->attributes, $key, $value); + } + + if (!array_key_exists($locale, $this->translatableAttributes)) { + $this->loadTranslatableData($locale); + } + + return $this->setAttributeFromData($this->translatableAttributes[$locale], $key, $value); + } + + /** + * Restores the default language values on the model and + * stores the translated values in the attributes table. + * @return void + */ + public function syncTranslatableAttributes() + { + /* + * Spin through the known locales, store the translations if necessary + */ + $knownLocales = array_keys($this->translatableAttributes); + foreach ($knownLocales as $locale) { + if (!$this->isTranslateDirty(null, $locale)) { + continue; + } + + $this->storeTranslatableData($locale); + } + + /* + * Saving the default locale, no need to restore anything + */ + if ($this->translatableContext == $this->translatableDefault) { + return; + } + + /* + * Restore translatable values to models originals + */ + $original = $this->model->getOriginal(); + $attributes = $this->model->getAttributes(); + $translatable = $this->model->getTranslatableAttributes(); + $originalValues = array_intersect_key($original, array_flip($translatable)); + $this->model->attributes = array_merge($attributes, $originalValues); + } + + /** + * Changes the active language for this model + * @param string $context + * @return void + */ + public function translateContext($context = null) + { + if ($context === null) { + return $this->translatableContext; + } + + $this->translatableContext = $context; + } + + /** + * Shorthand for translateContext method, and chainable. + * @param string $context + * @return self + */ + public function lang($context = null) + { + $this->translateContext($context); + + return $this->model; + } + + /** + * Checks if this model has transatable attributes. + * @return true + */ + public function hasTranslatableAttributes() + { + return is_array($this->model->translatable) && + count($this->model->translatable) > 0; + } + + /** + * Returns a collection of fields that will be hashed. + * @return array + */ + public function getTranslatableAttributes() + { + $translatable = []; + + if (!is_array($this->model->translatable)) { + return []; + } + + foreach ($this->model->translatable as $attribute) { + $translatable[] = is_array($attribute) ? array_shift($attribute) : $attribute; + } + + return $translatable; + } + + /** + * Returns the defined options for a translatable attribute. + * @return array + */ + public function getTranslatableAttributesWithOptions() + { + $attributes = []; + + foreach ($this->model->translatable as $options) { + if (!is_array($options)) { + continue; + } + + $attributeName = array_shift($options); + + $attributes[$attributeName] = $options; + } + + return $attributes; + } + + /** + * Determine if the model or a given translated attribute has been modified. + * @param string|null $attribute + * @return bool + */ + public function isTranslateDirty($attribute = null, $locale = null) + { + $dirty = $this->getTranslateDirty($locale); + + if (is_null($attribute)) { + return count($dirty) > 0; + } + else { + return array_key_exists($attribute, $dirty); + } + } + + /** + * Get the locales that have changed, if any + * + * @return array + */ + public function getDirtyLocales() + { + $dirtyLocales = []; + $knownLocales = array_keys($this->translatableAttributes); + foreach ($knownLocales as $locale) { + if ($this->isTranslateDirty(null, $locale)) { + $dirtyLocales[] = $locale; + } + } + + return $dirtyLocales; + } + + /** + * Get the original values of the translated attributes. + * @param string|null $locale If `null`, the method will get the original data for all locales. + * @return array|null Returns locale data as an array, or `null` if an invalid locale is specified. + */ + public function getTranslatableOriginals($locale = null) + { + if (!$locale) { + return $this->translatableOriginals; + } else { + return $this->translatableOriginals[$locale] ?? null; + } + } + + /** + * Get the translated attributes that have been changed since last sync. + * @return array + */ + public function getTranslateDirty($locale = null) + { + if (!$locale) { + $locale = $this->translatableContext; + } + + if (!array_key_exists($locale, $this->translatableAttributes)) { + return []; + } + + if (!array_key_exists($locale, $this->translatableOriginals)) { + return $this->translatableAttributes[$locale]; // All dirty + } + + $dirty = []; + + foreach ($this->translatableAttributes[$locale] as $key => $value) { + + if (!array_key_exists($key, $this->translatableOriginals[$locale])) { + $dirty[$key] = $value; + } + elseif ($value != $this->translatableOriginals[$locale][$key]) { + $dirty[$key] = $value; + } + } + + return $dirty; + } + + /** + * Extracts a attribute from a model/array with nesting support. + * @param mixed $data + * @param string $attribute + * @return mixed + */ + protected function getAttributeFromData($data, $attribute) + { + $keyArray = HtmlHelper::nameToArray($attribute); + + return array_get($data, implode('.', $keyArray)); + } + + /** + * Sets an attribute from a model/array with nesting support. + * @param mixed $data + * @param string $attribute + * @return mixed + */ + protected function setAttributeFromData(&$data, $attribute, $value) + { + $keyArray = HtmlHelper::nameToArray($attribute); + + array_set($data, implode('.', $keyArray), $value); + + return $value; + } + + /** + * Saves the translation data for the model. + * @param string $locale + * @return void + */ + abstract protected function storeTranslatableData($locale = null); + + /** + * Loads the translation data from the model. + * @param string $locale + * @return array + */ + abstract protected function loadTranslatableData($locale = null); +} diff --git a/plugins/rainlab/translate/classes/Translator.php b/plugins/rainlab/translate/classes/Translator.php new file mode 100644 index 0000000..de9dd70 --- /dev/null +++ b/plugins/rainlab/translate/classes/Translator.php @@ -0,0 +1,259 @@ +defaultLocale = $this->isConfigured() ? array_get(Locale::getDefault(), 'code', 'en') : 'en'; + $this->activeLocale = $this->defaultLocale; + } + + /** + * Changes the locale in the application and optionally stores it in the session. + * @param string $locale Locale to use + * @param boolean $remember Set to false to not store in the session. + * @return boolean Returns true if the locale exists and is set. + */ + public function setLocale($locale, $remember = true) + { + if (!Locale::isValid($locale)) { + return false; + } + + App::setLocale($locale); + + $this->activeLocale = $locale; + + if ($remember) { + $this->setSessionLocale($locale); + } + + return true; + } + + /** + * Returns the active locale set by this instance. + * @param boolean $fromSession Look in the session. + * @return string + */ + public function getLocale($fromSession = false) + { + if ($fromSession && ($locale = $this->getSessionLocale())) { + return $locale; + } + + return $this->activeLocale; + } + + /** + * Returns the default locale as set by the application. + * @return string + */ + public function getDefaultLocale() + { + return $this->defaultLocale; + } + + /** + * Check if this plugin is installed and the database is available, + * stores the result in the session for efficiency. + * @return boolean + */ + public function isConfigured() + { + if ($this->isConfigured !== null) { + return $this->isConfigured; + } + + if (Session::has(self::SESSION_CONFIGURED)) { + $result = true; + } + elseif (App::hasDatabase() && Schema::hasTable('rainlab_translate_locales')) { + Session::put(self::SESSION_CONFIGURED, true); + $result = true; + } + else { + $result = false; + } + + return $this->isConfigured = $result; + } + + // + // Request handling + // + + /** + * handleLocaleRoute will check if the route contains a translated locale prefix (/en/) + * and return that locale to be registered with the router. + * @return string + */ + public function handleLocaleRoute() + { + if (Config::get('rainlab.translate::disableLocalePrefixRoutes', false)) { + return ''; + } + + if (App::runningInBackend()) { + return ''; + } + + if (!$this->isConfigured()) { + return ''; + } + + if (!$this->loadLocaleFromRequest()) { + return ''; + } + + $locale = $this->getLocale(); + if (!$locale) { + return ''; + } + + return $locale; + } + + /** + * Sets the locale based on the first URI segment. + * @return bool + */ + public function loadLocaleFromRequest() + { + $locale = Request::segment(1); + + if (!Locale::isValid($locale)) { + return false; + } + + $this->setLocale($locale); + return true; + } + + /** + * Returns the current path prefixed with language code. + * + * @param string $locale optional language code, default to the system default language + * @return string + */ + public function getCurrentPathInLocale($locale = null) + { + return $this->getPathInLocale(Request::path(), $locale); + } + + /** + * Returns the path prefixed with language code. + * + * @param string $path Path to rewrite, already translate, with or without locale prefixed + * @param string $locale optional language code, default to the system default language + * @param boolean $prefixDefaultLocale should we prefix the path when the locale = default locale + * @return string + */ + public function getPathInLocale($path, $locale = null, $prefixDefaultLocale = null) + { + $prefixDefaultLocale = (is_null($prefixDefaultLocale)) + ? Config::get('rainlab.translate::prefixDefaultLocale') + : $prefixDefaultLocale; + + $segments = explode('/', $path); + + $segments = array_values(array_filter($segments, function ($v) { + return $v != ''; + })); + + if (is_null($locale) || !Locale::isValid($locale)) { + $locale = $this->defaultLocale; + } + + if (count($segments) == 0 || Locale::isValid($segments[0])) { + $segments[0] = $locale; + } else { + array_unshift($segments, $locale); + } + + // If we don't want te default locale to be prefixed + // and the first segment equals the default locale + if ( + !$prefixDefaultLocale && + isset($segments[0]) && + $segments[0] == $this->defaultLocale + ) { + // Remove the default locale + array_shift($segments); + }; + + return htmlspecialchars(implode('/', $segments), ENT_QUOTES, 'UTF-8'); + } + + // + // Session handling + // + + /** + * Looks at the session storage to find a locale. + * @return bool + */ + public function loadLocaleFromSession() + { + $locale = $this->getSessionLocale(); + + if (!$locale) { + return false; + } + + $this->setLocale($locale); + return true; + } + + protected function getSessionLocale() + { + if (!Session::has(self::SESSION_LOCALE)) { + return null; + } + + return Session::get(self::SESSION_LOCALE); + } + + protected function setSessionLocale($locale) + { + Session::put(self::SESSION_LOCALE, $locale); + } +} diff --git a/plugins/rainlab/translate/components/AlternateHrefLangElements.php b/plugins/rainlab/translate/components/AlternateHrefLangElements.php new file mode 100644 index 0000000..687fd49 --- /dev/null +++ b/plugins/rainlab/translate/components/AlternateHrefLangElements.php @@ -0,0 +1,82 @@ + 'rainlab.translate::lang.alternate_hreflang.component_name', + 'description' => 'rainlab.translate::lang.alternate_hreflang.component_description' + ]; + } + + /** + * locales + */ + public function locales() + { + // Available locales + $locales = collect(LocaleModel::listEnabled()); + + // Transform it to contain the new urls + $locales->transform(function ($item, $key) { + return $this->retrieveLocalizedUrl($key); + }); + + return $locales->toArray(); + } + + /** + * retrieveLocalizedUrl + */ + protected function retrieveLocalizedUrl($locale) + { + $translator = Translator::instance(); + $page = $this->getPage(); + + /* + * Static Page + */ + if (isset($page->apiBag['staticPage'])) { + $staticPage = $page->apiBag['staticPage']; + $staticPage->rewriteTranslatablePageUrl($locale); + $localeUrl = array_get($staticPage->attributes, 'viewBag.url'); + } + /* + * CMS Page + */ + else { + $page->rewriteTranslatablePageUrl($locale); + $params = $this->getRouter()->getParameters(); + + $translatedParams = Event::fire('translate.localePicker.translateParams', [ + $page, + $params, + $this->oldLocale, + $locale + ], true); + + if ($translatedParams) { + $params = $translatedParams; + } + + $router = new RainRouter; + $localeUrl = $router->urlFromPattern($page->url, $params); + } + + return $translator->getPathInLocale($localeUrl, $locale); + } + +} diff --git a/plugins/rainlab/translate/components/LocalePicker.php b/plugins/rainlab/translate/components/LocalePicker.php new file mode 100644 index 0000000..c93b55b --- /dev/null +++ b/plugins/rainlab/translate/components/LocalePicker.php @@ -0,0 +1,226 @@ + 'rainlab.translate::lang.locale_picker.component_name', + 'description' => 'rainlab.translate::lang.locale_picker.component_description', + ]; + } + + public function defineProperties() + { + return [ + 'forceUrl' => [ + 'title' => 'Force URL schema', + 'description' => 'Always prefix the URL with a language code.', + 'default' => 0, + 'type' => 'checkbox' + ], + ]; + } + + public function init() + { + $this->translator = Translator::instance(); + } + + public function onRun() + { + if ($redirect = $this->redirectForceUrl()) { + return $redirect; + } + + $this->page['locales'] = $this->locales = LocaleModel::listEnabled(); + $this->page['activeLocale'] = $this->activeLocale = $this->translator->getLocale(); + $this->page['activeLocaleName'] = $this->activeLocaleName = array_get($this->locales, $this->activeLocale); + } + + public function onSwitchLocale() + { + if (!$locale = post('locale')) { + return; + } + + // Remember the current locale before switching to the requested one + $this->oldLocale = $this->translator->getLocale(); + + $this->translator->setLocale($locale); + + $pageUrl = $this->withPreservedQueryString($this->makeLocaleUrlFromPage($locale), $locale); + if ($this->property('forceUrl')) { + return Redirect::to($this->translator->getPathInLocale($pageUrl, $locale)); + } + + return Redirect::to($pageUrl); + } + + protected function redirectForceUrl() + { + if ( + Request::ajax() || + !$this->property('forceUrl') || + $this->translator->loadLocaleFromRequest() + ) { + return; + } + + $prefixDefaultLocale = Config::get('rainlab.translate::prefixDefaultLocale'); + $locale = $this->translator->getLocale(false) + ?: $this->translator->getDefaultLocale(); + + if ($prefixDefaultLocale) { + return Redirect::to( + $this->withPreservedQueryString( + $this->translator->getCurrentPathInLocale($locale), + $locale + ) + ); + } elseif ( $locale == $this->translator->getDefaultLocale()) { + return; + } else { + $this->translator->setLocale($this->translator->getDefaultLocale()); + return; + } + + } + + /** + * Returns the URL from a page object, including current parameter values. + * @return string + */ + protected function makeLocaleUrlFromPage($locale) + { + $page = $this->getPage(); + + /* + * Static Page + */ + if (isset($page->apiBag['staticPage'])) { + $staticPage = $page->apiBag['staticPage']; + + $staticPage->rewriteTranslatablePageUrl($locale); + + $localeUrl = array_get($staticPage->attributes, 'viewBag.url'); + } + /* + * CMS Page + */ + else { + $page->rewriteTranslatablePageUrl($locale); + + $router = new RainRouter; + + $params = $this->getRouter()->getParameters(); + + /** + * @event translate.localePicker.translateParams + * Enables manipulating the URL parameters + * + * You will have access to the page object, the old and new locale and the URL parameters. + * + * Example usage: + * + * Event::listen('translate.localePicker.translateParams', function($page, $params, $oldLocale, $newLocale) { + * if ($page->baseFileName == 'your-page-filename') { + * return YourModel::translateParams($params, $oldLocale, $newLocale); + * } + * }); + * + */ + $translatedParams = Event::fire('translate.localePicker.translateParams', [ + $page, + $params, + $this->oldLocale, + $locale + ], true); + + if ($translatedParams) { + $params = $translatedParams; + } + + $localeUrl = $router->urlFromPattern($page->url, $params); + } + + return $localeUrl; + } + + /** + * Makes sure to add any existing query string to the redirect url. + * + * @param $pageUrl + * @param $locale + * + * @return string + */ + protected function withPreservedQueryString($pageUrl, $locale) + { + $page = $this->getPage(); + $query = request()->query(); + + /** + * @event translate.localePicker.translateQuery + * Enables manipulating the URL query parameters + * + * You will have access to the page object, the old and new locale and the URL query parameters. + * + * Example usage: + * + * Event::listen('translate.localePicker.translateQuery', function($page, $params, $oldLocale, $newLocale) { + * if ($page->baseFileName == 'your-page-filename') { + * return YourModel::translateParams($params, $oldLocale, $newLocale); + * } + * }); + * + */ + $translatedQuery = Event::fire('translate.localePicker.translateQuery', [ + $page, + $query, + $this->oldLocale, + $locale + ], true); + + $query = http_build_query($translatedQuery ?: $query); + + return $query ? $pageUrl . '?' . $query : $pageUrl; + } +} diff --git a/plugins/rainlab/translate/components/alternatehreflangelements/default.htm b/plugins/rainlab/translate/components/alternatehreflangelements/default.htm new file mode 100644 index 0000000..e7b5fd8 --- /dev/null +++ b/plugins/rainlab/translate/components/alternatehreflangelements/default.htm @@ -0,0 +1,3 @@ +{% for locale, alternateUrl in __SELF__.locales %} + +{% endfor %} diff --git a/plugins/rainlab/translate/components/localepicker/default.htm b/plugins/rainlab/translate/components/localepicker/default.htm new file mode 100644 index 0000000..90c3444 --- /dev/null +++ b/plugins/rainlab/translate/components/localepicker/default.htm @@ -0,0 +1,7 @@ +{{ form_open() }} + +{{ form_close() }} \ No newline at end of file diff --git a/plugins/rainlab/translate/composer.json b/plugins/rainlab/translate/composer.json new file mode 100644 index 0000000..af34178 --- /dev/null +++ b/plugins/rainlab/translate/composer.json @@ -0,0 +1,25 @@ +{ + "name": "rainlab/translate-plugin", + "type": "october-plugin", + "description": "Translate plugin for October CMS", + "homepage": "https://octobercms.com/plugin/rainlab-translate", + "keywords": ["october", "octobercms", "translate"], + "license": "MIT", + "authors": [ + { + "name": "Alexey Bobkov", + "email": "aleksey.bobkov@gmail.com", + "role": "Co-founder" + }, + { + "name": "Samuel Georges", + "email": "daftspunky@gmail.com", + "role": "Co-founder" + } + ], + "require": { + "php": ">=5.5.9", + "composer/installers": "~1.0" + }, + "minimum-stability": "dev" +} diff --git a/plugins/rainlab/translate/config/config.php b/plugins/rainlab/translate/config/config.php new file mode 100644 index 0000000..d9c60fc --- /dev/null +++ b/plugins/rainlab/translate/config/config.php @@ -0,0 +1,49 @@ + env('TRANSLATE_FORCE_LOCALE', null), + + /* + |-------------------------------------------------------------------------- + | Prefix the Default Locale + |-------------------------------------------------------------------------- + | + | Specifies if the default locale be prefixed by the plugin. + | + */ + 'prefixDefaultLocale' => env('TRANSLATE_PREFIX_LOCALE', true), + + /* + |-------------------------------------------------------------------------- + | Cache Timeout in Minutes + |-------------------------------------------------------------------------- + | + | By default all translations are cached for 24 hours (1440 min). + | This setting allows to change that period with given amount of minutes. + | + | For example, 43200 for 30 days or 525600 for one year. + | + */ + 'cacheTimeout' => env('TRANSLATE_CACHE_TIMEOUT', 1440), + + /* + |-------------------------------------------------------------------------- + | Disable Locale Prefix Routes + |-------------------------------------------------------------------------- + | + | Disables the automatically generated locale prefixed routes + | (i.e. /en/original-route) when enabled. + | + */ + 'disableLocalePrefixRoutes' => env('TRANSLATE_DISABLE_PREFIX_ROUTES', false), + +]; diff --git a/plugins/rainlab/translate/console/ScanCommand.php b/plugins/rainlab/translate/console/ScanCommand.php new file mode 100644 index 0000000..4d38604 --- /dev/null +++ b/plugins/rainlab/translate/console/ScanCommand.php @@ -0,0 +1,40 @@ +option('purge')) { + $this->output->writeln('Purging messages...'); + Message::truncate(); + } + + ThemeScanner::scan(); + $this->output->success('Messages scanned successfully.'); + $this->output->note('You may need to run cache:clear for updated messages to take effect.'); + } + + protected function getArguments() + { + return []; + } + + protected function getOptions() + { + return [ + ['purge', 'null', InputOption::VALUE_NONE, 'First purge existing messages.', null], + ]; + } +} diff --git a/plugins/rainlab/translate/controllers/Locales.php b/plugins/rainlab/translate/controllers/Locales.php new file mode 100644 index 0000000..7f3be5d --- /dev/null +++ b/plugins/rainlab/translate/controllers/Locales.php @@ -0,0 +1,92 @@ +addJs('/plugins/rainlab/translate/assets/js/locales.js'); + } + + /** + * {@inheritDoc} + */ + public function listInjectRowClass($record, $definition = null) + { + if (!$record->is_enabled) { + return 'safe disabled'; + } + } + + public function onCreateForm() + { + $this->asExtension('FormController')->create(); + + return $this->makePartial('create_form'); + } + + public function onCreate() + { + LocaleModel::clearCache(); + $this->asExtension('FormController')->create_onSave(); + + return $this->listRefresh(); + } + + public function onUpdateForm() + { + $this->asExtension('FormController')->update(post('record_id')); + $this->vars['recordId'] = post('record_id'); + + return $this->makePartial('update_form'); + } + + public function onUpdate() + { + LocaleModel::clearCache(); + $this->asExtension('FormController')->update_onSave(post('record_id')); + + return $this->listRefresh(); + } + + public function onDelete() + { + LocaleModel::clearCache(); + $this->asExtension('FormController')->update_onDelete(post('record_id')); + + return $this->listRefresh(); + } + + public function onReorder() + { + LocaleModel::clearCache(); + $this->asExtension('ReorderController')->onReorder(); + } +} diff --git a/plugins/rainlab/translate/controllers/Messages.php b/plugins/rainlab/translate/controllers/Messages.php new file mode 100644 index 0000000..4f84286 --- /dev/null +++ b/plugins/rainlab/translate/controllers/Messages.php @@ -0,0 +1,237 @@ +addJs('/plugins/rainlab/translate/assets/js/messages.js'); + $this->addCss('/plugins/rainlab/translate/assets/css/messages.css'); + + $this->importColumns = MessageExport::getColumns(); + $this->exportColumns = MessageExport::getColumns(); + } + + public function index() + { + $this->pageTitle = 'rainlab.translate::lang.messages.title'; + $this->prepareTable(); + } + + public function onRefresh() + { + $this->prepareTable(); + return ['#messagesContainer' => $this->makePartial('messages')]; + } + + public function onClearCache() + { + CacheHelper::clear(); + + Flash::success(Lang::get('rainlab.translate::lang.messages.clear_cache_success')); + } + + public function onLoadScanMessagesForm() + { + return $this->makePartial('scan_messages_form'); + } + + public function onScanMessages() + { + if (post('purge_messages', false)) { + Message::truncate(); + } + + ThemeScanner::scan(); + + if (post('purge_deleted_messages', false)) { + Message::where('found', 0)->delete(); + } + + Flash::success(Lang::get('rainlab.translate::lang.messages.scan_messages_success')); + + return $this->onRefresh(); + } + + public function prepareTable() + { + $fromCode = post('locale_from', null); + $toCode = post('locale_to', Locale::getDefault()->code); + $this->hideTranslated = post('hide_translated', false); + + /* + * Page vars + */ + $this->vars['hideTranslated'] = $this->hideTranslated; + $this->vars['defaultLocale'] = Locale::getDefault(); + $this->vars['locales'] = Locale::all(); + $this->vars['selectedFrom'] = $selectedFrom = Locale::findByCode($fromCode); + $this->vars['selectedTo'] = $selectedTo = Locale::findByCode($toCode); + + /* + * Make table config, make default column read only + */ + $config = $this->makeConfig('config_table.yaml'); + + if (!$selectedFrom) { + $config->columns['from']['readOnly'] = true; + } + if (!$selectedTo) { + $config->columns['to']['readOnly'] = true; + } + + /* + * Make table widget + */ + $widget = $this->makeWidget(\Backend\Widgets\Table::class, $config); + $widget->bindToController(); + + /* + * Populate data + */ + $dataSource = $widget->getDataSource(); + + $dataSource->bindEvent('data.getRecords', function($offset, $count) use ($selectedFrom, $selectedTo) { + $messages = $this->listMessagesForDatasource([ + 'offset' => $offset, + 'count' => $count + ]); + + return $this->processTableData($messages, $selectedFrom, $selectedTo); + }); + + $dataSource->bindEvent('data.searchRecords', function($search, $offset, $count) use ($selectedFrom, $selectedTo) { + $messages = $this->listMessagesForDatasource([ + 'search' => $search, + 'offset' => $offset, + 'count' => $count + ]); + + return $this->processTableData($messages, $selectedFrom, $selectedTo); + }); + + $dataSource->bindEvent('data.getCount', function() { + return Message::count(); + }); + + $dataSource->bindEvent('data.updateRecord', function($key, $data) { + $message = Message::find($key); + $this->updateTableData($message, $data); + CacheHelper::clear(); + }); + + $dataSource->bindEvent('data.deleteRecord', function($key) { + if ($message = Message::find($key)) { + $message->delete(); + } + }); + + $this->vars['table'] = $widget; + } + + protected function isHideTranslated() + { + return post('hide_translated', false); + } + + protected function listMessagesForDatasource($options = []) + { + extract(array_merge([ + 'search' => null, + 'offset' => null, + 'count' => null, + ], $options)); + + $query = Message::orderBy('message_data','asc'); + + if ($search) { + $query = $query->searchWhere($search, ['message_data']); + } + + if ($count) { + $query = $query->limit($count)->offset($offset); + } + + return $query->get(); + } + + protected function processTableData($messages, $from, $to) + { + $fromCode = $from ? $from->code : null; + $toCode = $to ? $to->code : null; + + $data = []; + foreach ($messages as $message) { + $toContent = $message->forLocale($toCode); + if ($this->hideTranslated && $toContent) { + continue; + } + + $data[] = [ + 'id' => $message->id, + 'code' => $message->code, + 'from' => $message->forLocale($fromCode), + 'to' => $toContent, + 'found' => $message->found ? '' : Lang::get('rainlab.translate::lang.messages.not_found'), + ]; + } + + return $data; + } + + protected function updateTableData($message, $data) + { + if (!$message) { + return; + } + + $fromCode = post('locale_from'); + $toCode = post('locale_to'); + + // @todo This should be unified to a single save() + if ($fromCode) { + $fromValue = array_get($data, 'from'); + if ($fromValue != $message->forLocale($fromCode)) { + $message->toLocale($fromCode, $fromValue); + } + } + + if ($toCode) { + $toValue = array_get($data, 'to'); + if ($toValue != $message->forLocale($toCode)) { + $message->toLocale($toCode, $toValue); + } + } + } +} diff --git a/plugins/rainlab/translate/controllers/locales/_create_form.htm b/plugins/rainlab/translate/controllers/locales/_create_form.htm new file mode 100644 index 0000000..e33ba27 --- /dev/null +++ b/plugins/rainlab/translate/controllers/locales/_create_form.htm @@ -0,0 +1,55 @@ + 'createForm']) ?> + + + + fatalError): ?> + + + + + + + + + + + + + + diff --git a/plugins/rainlab/translate/controllers/locales/_hint.htm b/plugins/rainlab/translate/controllers/locales/_hint.htm new file mode 100644 index 0000000..45d85a4 --- /dev/null +++ b/plugins/rainlab/translate/controllers/locales/_hint.htm @@ -0,0 +1,4 @@ + +

    + +

    \ No newline at end of file diff --git a/plugins/rainlab/translate/controllers/locales/_list_toolbar.htm b/plugins/rainlab/translate/controllers/locales/_list_toolbar.htm new file mode 100644 index 0000000..126253b --- /dev/null +++ b/plugins/rainlab/translate/controllers/locales/_list_toolbar.htm @@ -0,0 +1,15 @@ +
    diff --git a/plugins/rainlab/translate/controllers/locales/_reorder_toolbar.htm b/plugins/rainlab/translate/controllers/locales/_reorder_toolbar.htm new file mode 100644 index 0000000..30a2fd6 --- /dev/null +++ b/plugins/rainlab/translate/controllers/locales/_reorder_toolbar.htm @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/plugins/rainlab/translate/controllers/locales/_update_form.htm b/plugins/rainlab/translate/controllers/locales/_update_form.htm new file mode 100644 index 0000000..c820921 --- /dev/null +++ b/plugins/rainlab/translate/controllers/locales/_update_form.htm @@ -0,0 +1,67 @@ + 'updateForm']) ?> + + + + + + fatalError): ?> + + + + + + + + + + + + + + diff --git a/plugins/rainlab/translate/controllers/locales/config_form.yaml b/plugins/rainlab/translate/controllers/locales/config_form.yaml new file mode 100644 index 0000000..781bcfb --- /dev/null +++ b/plugins/rainlab/translate/controllers/locales/config_form.yaml @@ -0,0 +1,7 @@ +# =================================== +# Form Behavior Config +# =================================== + +form: ~/plugins/rainlab/translate/models/locale/fields.yaml +modelClass: RainLab\Translate\Models\Locale +defaultRedirect: rainlab/translate/locales diff --git a/plugins/rainlab/translate/controllers/locales/config_list.yaml b/plugins/rainlab/translate/controllers/locales/config_list.yaml new file mode 100644 index 0000000..6447ec8 --- /dev/null +++ b/plugins/rainlab/translate/controllers/locales/config_list.yaml @@ -0,0 +1,52 @@ +# =================================== +# List Behavior Config +# =================================== + +# Model List Column configuration +list: ~/plugins/rainlab/translate/models/locale/columns.yaml + +# Model Class name +modelClass: RainLab\Translate\Models\Locale + +# List Title +title: rainlab.translate::lang.locale.title + +# Link URL for each record +# recordUrl: rainlab/translate/locale/update/:id + +recordOnClick: $.translateLocales.clickRecord(:id) + +# Message to display if the list is empty +noRecordsMessage: backend::lang.list.no_records + +# Records to display per page +recordsPerPage: 20 + +# Displays the list column set up button +showSetup: true + +# Displays the sorting link on each column +showSorting: true + +# Default sorting column +defaultSort: + column: sort_order + direction: asc + +# 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 + +# Reordering +structure: + showTree: false + showReorder: true + maxDepth: 1 diff --git a/plugins/rainlab/translate/controllers/locales/config_reorder.yaml b/plugins/rainlab/translate/controllers/locales/config_reorder.yaml new file mode 100644 index 0000000..797a21f --- /dev/null +++ b/plugins/rainlab/translate/controllers/locales/config_reorder.yaml @@ -0,0 +1,17 @@ +# =================================== +# Reorder Behavior Config +# =================================== + +# Reorder Title +title: rainlab.translate::lang.locale.reorder_title + +# Attribute name +nameFrom: name + +# Model Class name +modelClass: RainLab\Translate\Models\Locale + +# Toolbar widget configuration +toolbar: + # Partial for toolbar buttons + buttons: reorder_toolbar \ No newline at end of file diff --git a/plugins/rainlab/translate/controllers/locales/index.htm b/plugins/rainlab/translate/controllers/locales/index.htm new file mode 100644 index 0000000..5bdfd58 --- /dev/null +++ b/plugins/rainlab/translate/controllers/locales/index.htm @@ -0,0 +1,12 @@ + +
      +
    • +
    • pageTitle)) ?>
    • +
    + + +
    + makeHintPartial('translation_locales_hint', 'hint') ?> +
    + +listRender() ?> diff --git a/plugins/rainlab/translate/controllers/locales/reorder.htm b/plugins/rainlab/translate/controllers/locales/reorder.htm new file mode 100644 index 0000000..f820c6a --- /dev/null +++ b/plugins/rainlab/translate/controllers/locales/reorder.htm @@ -0,0 +1,9 @@ + +
      +
    • +
    • +
    • pageTitle)) ?>
    • +
    + + +reorderRender() ?> diff --git a/plugins/rainlab/translate/controllers/messages/_hint.htm b/plugins/rainlab/translate/controllers/messages/_hint.htm new file mode 100644 index 0000000..18a041b --- /dev/null +++ b/plugins/rainlab/translate/controllers/messages/_hint.htm @@ -0,0 +1,6 @@ + +

    + + + +

    \ No newline at end of file diff --git a/plugins/rainlab/translate/controllers/messages/_messages.htm b/plugins/rainlab/translate/controllers/messages/_messages.htm new file mode 100644 index 0000000..87ed504 --- /dev/null +++ b/plugins/rainlab/translate/controllers/messages/_messages.htm @@ -0,0 +1,10 @@ +
    +
    + makePartial('table_headers') ?> +
    +
    + makePartial('table_toolbar') ?> +
    + + render() ?> +
    diff --git a/plugins/rainlab/translate/controllers/messages/_scan_messages_form.htm b/plugins/rainlab/translate/controllers/messages/_scan_messages_form.htm new file mode 100644 index 0000000..101f82a --- /dev/null +++ b/plugins/rainlab/translate/controllers/messages/_scan_messages_form.htm @@ -0,0 +1,80 @@ +
    + 'scanMessagesForm']) ?> + + + + + + +
    + + diff --git a/plugins/rainlab/translate/controllers/messages/_table_headers.htm b/plugins/rainlab/translate/controllers/messages/_table_headers.htm new file mode 100644 index 0000000..8a5c03c --- /dev/null +++ b/plugins/rainlab/translate/controllers/messages/_table_headers.htm @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + diff --git a/plugins/rainlab/translate/controllers/messages/_table_toolbar.htm b/plugins/rainlab/translate/controllers/messages/_table_toolbar.htm new file mode 100644 index 0000000..eb24d78 --- /dev/null +++ b/plugins/rainlab/translate/controllers/messages/_table_toolbar.htm @@ -0,0 +1,24 @@ + diff --git a/plugins/rainlab/translate/controllers/messages/config_import_export.yaml b/plugins/rainlab/translate/controllers/messages/config_import_export.yaml new file mode 100644 index 0000000..3aaf39f --- /dev/null +++ b/plugins/rainlab/translate/controllers/messages/config_import_export.yaml @@ -0,0 +1,9 @@ +import: + title: 'rainlab.translate::lang.messages.import_messages_link' + modelClass: RainLab\Translate\Models\MessageImport + redirect: rainlab/translate/messages + +export: + title: 'rainlab.translate::lang.messages.export_messages_link' + modelClass: RainLab\Translate\Models\MessageExport + redirect: rainlab/translate/messages diff --git a/plugins/rainlab/translate/controllers/messages/config_table.yaml b/plugins/rainlab/translate/controllers/messages/config_table.yaml new file mode 100644 index 0000000..331f33e --- /dev/null +++ b/plugins/rainlab/translate/controllers/messages/config_table.yaml @@ -0,0 +1,17 @@ +# =================================== +# Grid Widget Configuration +# =================================== + +dataSource: server +keyFrom: id +recordsPerPage: 500 +adding: false +searching: true + +columns: + from: + title: From + to: + title: To + found: + title: Scan errors diff --git a/plugins/rainlab/translate/controllers/messages/export.htm b/plugins/rainlab/translate/controllers/messages/export.htm new file mode 100644 index 0000000..589b191 --- /dev/null +++ b/plugins/rainlab/translate/controllers/messages/export.htm @@ -0,0 +1,26 @@ + +
      +
    • +
    • +
    • pageTitle)) ?>
    • +
    + + + 'layout']) ?> + +
    + exportRender() ?> +
    + +
    + +
    + + diff --git a/plugins/rainlab/translate/controllers/messages/import.htm b/plugins/rainlab/translate/controllers/messages/import.htm new file mode 100644 index 0000000..9538215 --- /dev/null +++ b/plugins/rainlab/translate/controllers/messages/import.htm @@ -0,0 +1,26 @@ + +
      +
    • +
    • +
    • pageTitle)) ?>
    • +
    + + + 'layout']) ?> + +
    + importRender() ?> +
    + +
    + +
    + + diff --git a/plugins/rainlab/translate/controllers/messages/index.htm b/plugins/rainlab/translate/controllers/messages/index.htm new file mode 100644 index 0000000..3f3777a --- /dev/null +++ b/plugins/rainlab/translate/controllers/messages/index.htm @@ -0,0 +1,34 @@ + +
      +
    • +
    • pageTitle)) ?>
    • +
    + + +
    + makeHintPartial('translation_messages_hint', 'hint') ?> +
    + + 'messagesForm', 'class'=>'layout-item stretch layout-column', 'onsubmit'=>'return false']) ?> + +
    + makePartial('messages') ?> +
    + + + + + + + + + + diff --git a/plugins/rainlab/translate/formwidgets/MLMarkdownEditor.php b/plugins/rainlab/translate/formwidgets/MLMarkdownEditor.php new file mode 100644 index 0000000..ec74673 --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/MLMarkdownEditor.php @@ -0,0 +1,107 @@ +initLocale(); + } + + /** + * {@inheritDoc} + */ + public function render() + { + $this->actAsParent(); + $parentContent = parent::render(); + $this->actAsParent(false); + + if (!$this->isAvailable) { + return $parentContent; + } + + $this->vars['markdowneditor'] = $parentContent; + return $this->makePartial('mlmarkdowneditor'); + } + + public function prepareVars() + { + parent::prepareVars(); + $this->prepareLocaleVars(); + } + + /** + * getSaveValue returns an array of translated values for this field + * @return array + */ + public function getSaveValue($value) + { + return $this->getLocaleSaveValue($value); + } + + /** + * {@inheritDoc} + */ + protected function loadAssets() + { + $this->actAsParent(); + parent::loadAssets(); + $this->actAsParent(false); + + if (Locale::isAvailable()) { + $this->loadLocaleAssets(); + $this->addJs('js/mlmarkdowneditor.js'); + } + } + + /** + * {@inheritDoc} + */ + protected function getParentViewPath() + { + return base_path().'/modules/backend/formwidgets/markdowneditor/partials'; + } + + /** + * {@inheritDoc} + */ + protected function getParentAssetPath() + { + return '/modules/backend/formwidgets/markdowneditor/assets'; + } +} diff --git a/plugins/rainlab/translate/formwidgets/MLMediaFinder.php b/plugins/rainlab/translate/formwidgets/MLMediaFinder.php new file mode 100755 index 0000000..5e21269 --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/MLMediaFinder.php @@ -0,0 +1,104 @@ +initLocale(); + } + + /** + * @inheritDoc + */ + public function render() + { + $this->actAsParent(); + $parentContent = parent::render(); + $this->actAsParent(false); + + if (!$this->isAvailable) { + return $parentContent; + } + + $this->vars['mediafinder'] = $parentContent; + return $this->makePartial('mlmediafinder'); + } + + /** + * Prepares the form widget view data + */ + public function prepareVars() + { + parent::prepareVars(); + $this->prepareLocaleVars(); + // make root path of media files accessible + $this->vars['mediaPath'] = $this->mediaPath = MediaLibrary::url('/'); + } + + /** + * @inheritDoc + */ + public function getSaveValue($value) + { + return $this->getLocaleSaveValue($value); + } + + /** + * @inheritDoc + */ + public function loadAssets() + { + $this->actAsParent(); + parent::loadAssets(); + $this->actAsParent(false); + + if (Locale::isAvailable()) { + $this->loadLocaleAssets(); + $this->addJs('js/mlmediafinder.js'); + $this->addCss('css/mlmediafinder.css'); + } + } + + /** + * {@inheritDoc} + */ + protected function getParentViewPath() + { + return base_path().'/modules/backend/formwidgets/mediafinder/partials'; + } + + /** + * {@inheritDoc} + */ + protected function getParentAssetPath() + { + return '/modules/backend/formwidgets/mediafinder/assets'; + } +} diff --git a/plugins/rainlab/translate/formwidgets/MLMediaFinderv2.php b/plugins/rainlab/translate/formwidgets/MLMediaFinderv2.php new file mode 100644 index 0000000..250463b --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/MLMediaFinderv2.php @@ -0,0 +1,108 @@ +initLocale(); + } + + /** + * @inheritDoc + */ + public function render() + { + $this->actAsParent(); + $parentContent = parent::render(); + $this->actAsParent(false); + + if (!$this->isAvailable) { + return $parentContent; + } + + $this->vars['mediafinder'] = $parentContent; + return $this->makePartial('mlmediafinder'); + } + + /** + * prepareVars prepares the form widget view data + */ + public function prepareVars() + { + parent::prepareVars(); + $this->prepareLocaleVars(); + // make root path of media files accessible + $this->vars['mediaPath'] = $this->mediaPath = MediaLibrary::url('/'); + } + + /** + * @inheritDoc + */ + public function getSaveValue($value) + { + if ($this->isAvailable) { + return $this->getLocaleSaveValue($value); + } + + return parent::getSaveValue($value); + } + + /** + * @inheritDoc + */ + public function loadAssets() + { + $this->actAsParent(); + parent::loadAssets(); + $this->actAsParent(false); + + if (Locale::isAvailable()) { + $this->loadLocaleAssets(); + $this->addJs('js/mlmediafinder.js'); + $this->addCss('../../mlmediafinder/assets/css/mlmediafinder.css'); + } + } + + /** + * {@inheritDoc} + */ + protected function getParentViewPath() + { + return base_path().'/modules/media/formwidgets/mediafinder/partials'; + } + + /** + * {@inheritDoc} + */ + protected function getParentAssetPath() + { + return '/modules/media/formwidgets/mediafinder/assets'; + } +} diff --git a/plugins/rainlab/translate/formwidgets/MLNestedForm.php b/plugins/rainlab/translate/formwidgets/MLNestedForm.php new file mode 100644 index 0000000..f04896b --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/MLNestedForm.php @@ -0,0 +1,187 @@ +initLocale(); + } + + /** + * {@inheritDoc} + */ + public function render() + { + $this->actAsParent(); + $parentContent = parent::render(); + $this->actAsParent(false); + + if (!$this->isAvailable) { + return $parentContent; + } + + $this->vars['nestedform'] = $parentContent; + + return $this->makePartial('mlnestedform'); + } + + /** + * prepareVars for viewing + */ + public function prepareVars() + { + parent::prepareVars(); + + $this->prepareLocaleVars(); + } + + /** + * getSaveValue returns an array of translated values for this field + * @return array + */ + public function getSaveValue($value) + { + $this->rewritePostValues(); + + return $this->getLocaleSaveValue($value); + } + + /** + * {@inheritDoc} + */ + protected function loadAssets() + { + $this->actAsParent(); + parent::loadAssets(); + $this->actAsParent(false); + + if (Locale::isAvailable()) { + $this->loadLocaleAssets(); + $this->addJs('js/mlnestedform.js'); + } + } + + /** + * {@inheritDoc} + */ + protected function getParentViewPath() + { + return base_path().'/modules/backend/formwidgets/nestedform/partials'; + } + + /** + * {@inheritDoc} + */ + protected function getParentAssetPath() + { + return '/modules/backend/formwidgets/nestedform/assets'; + } + + /** + * onSwitchItemLocale handler + */ + public function onSwitchItemLocale() + { + if (!$locale = post('_nestedform_locale')) { + throw new ApplicationException('Unable to find a nested form locale for: '.$locale); + } + + // Store previous value + $previousLocale = post('_nestedform_previous_locale'); + $previousValue = $this->getPrimarySaveDataAsArray(); + + // Update widget to show form for switched locale + $lockerData = $this->getLocaleSaveDataAsArray($locale) ?: []; + $this->formWidget->setFormValues($lockerData); + + $this->actAsParent(); + $parentContent = parent::render(); + $this->actAsParent(false); + + return [ + '#'.$this->getId('mlNestedForm') => $parentContent, + 'updateValue' => json_encode($previousValue), + 'updateLocale' => $previousLocale, + ]; + } + + /** + * getPrimarySaveDataAsArray gets the active values from the selected locale. + */ + protected function getPrimarySaveDataAsArray(): array + { + return post($this->formField->getName()) ?: []; + } + + /** + * getLocaleSaveDataAsArray returns the stored locale data as an array. + */ + protected function getLocaleSaveDataAsArray($locale): ?array + { + $saveData = array_get($this->getLocaleSaveData(), $locale, []); + + if (!is_array($saveData)) { + $saveData = json_decode($saveData, true); + } + + return $saveData; + } + + /** + * rewritePostValues since the locker does always contain the latest values, + * this method will take the save data from the nested form and merge it in to + * the locker based on which ever locale is selected using an item map + */ + protected function rewritePostValues() + { + // Get the selected locale at postback + $data = post('RLTranslateNestedFormLocale'); + $fieldName = implode('.', HtmlHelper::nameToArray($this->fieldName)); + $locale = array_get($data, $fieldName); + + if (!$locale) { + return; + } + + // Splice the save data in to the locker data for selected locale + $data = $this->getPrimarySaveDataAsArray(); + $fieldName = 'RLTranslate.'.$locale.'.'.implode('.', HtmlHelper::nameToArray($this->fieldName)); + + $requestData = Request::all(); + array_set($requestData, $fieldName, json_encode($data)); + $this->mergeWithPost($requestData); + } + + /** + * mergeWithPost will apply postback values globally + */ + protected function mergeWithPost(array $values) + { + Request::merge($values); + $_POST = array_merge($_POST, $values); + } +} diff --git a/plugins/rainlab/translate/formwidgets/MLRepeater.php b/plugins/rainlab/translate/formwidgets/MLRepeater.php new file mode 100644 index 0000000..237d145 --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/MLRepeater.php @@ -0,0 +1,239 @@ +initLocale(); + } + + /** + * {@inheritDoc} + */ + public function render() + { + $this->actAsParent(); + $parentContent = parent::render(); + $this->actAsParent(false); + + if (!$this->isAvailable) { + return $parentContent; + } + + $this->vars['repeater'] = $parentContent; + return $this->makePartial('mlrepeater'); + } + + /** + * prepareVars + */ + public function prepareVars() + { + parent::prepareVars(); + $this->prepareLocaleVars(); + } + + /** + * getSaveValue returns an array of translated values for this field + * @return array + */ + public function getSaveValue($value) + { + $this->rewritePostValues(); + + return $this->getLocaleSaveValue(is_array($value) ? array_values($value) : $value); + } + + /** + * {@inheritDoc} + */ + protected function loadAssets() + { + $this->actAsParent(); + parent::loadAssets(); + $this->actAsParent(false); + + if (Locale::isAvailable()) { + $this->loadLocaleAssets(); + $this->addJs('js/mlrepeater.js'); + } + } + + /** + * {@inheritDoc} + */ + protected function getParentViewPath() + { + return base_path().'/modules/backend/formwidgets/repeater/partials'; + } + + /** + * {@inheritDoc} + */ + protected function getParentAssetPath() + { + return '/modules/backend/formwidgets/repeater/assets'; + } + + /** + * onAddItem + */ + public function onAddItem() + { + $this->actAsParent(); + return parent::onAddItem(); + } + + /** + * onDuplicateItem + */ + public function onDuplicateItem() + { + $this->actAsParent(); + return parent::onDuplicateItem(); + } + + /** + * onSwitchItemLocale + */ + public function onSwitchItemLocale() + { + if (!$locale = post('_repeater_locale')) { + throw new ApplicationException('Unable to find a repeater locale for: '.$locale); + } + + // Store previous value + $previousLocale = post('_repeater_previous_locale'); + $previousValue = $this->getPrimarySaveDataAsArray(); + + // Update widget to show form for switched locale + $lockerData = $this->getLocaleSaveDataAsArray($locale) ?: []; + $this->reprocessLocaleItems($lockerData); + + foreach ($this->formWidgets as $key => $widget) { + $value = array_shift($lockerData); + if (!$value) { + unset($this->formWidgets[$key]); + } + else { + $widget->setFormValues($value); + } + } + + $this->actAsParent(); + $parentContent = parent::render(); + $this->actAsParent(false); + + return [ + '#'.$this->getId('mlRepeater') => $parentContent, + 'updateValue' => json_encode($previousValue), + 'updateLocale' => $previousLocale, + ]; + } + + /** + * reprocessLocaleItems ensures that the current locale data is processed by + * the repeater instead of the original non-translated data + * @return void + */ + protected function reprocessLocaleItems($data) + { + $this->formWidgets = []; + + $this->formField->value = $data; + + $key = implode('.', HtmlHelper::nameToArray($this->formField->getName())); + + $requestData = Request::all(); + + array_set($requestData, $key, $data); + + $this->mergeWithPost($requestData); + + $this->processItems(); + } + + /** + * getPrimarySaveDataAsArray gets the active values from the selected locale. + * @return array + */ + protected function getPrimarySaveDataAsArray() + { + $data = post($this->formField->getName()) ?: []; + + return $this->processSaveValue($data); + } + + /** + * getLocaleSaveDataAsArray returns the stored locale data as an array. + * @return array + */ + protected function getLocaleSaveDataAsArray($locale) + { + $saveData = array_get($this->getLocaleSaveData(), $locale, []); + + if (!is_array($saveData)) { + $saveData = json_decode($saveData, true); + } + + return $saveData; + } + + /** + * rewritePostValues since the locker does always contain the latest values, this method + * will take the save data from the repeater and merge it in to the + * locker based on which ever locale is selected using an item map + * @return void + */ + protected function rewritePostValues() + { + // Get the selected locale at postback + $data = post('RLTranslateRepeaterLocale'); + $fieldName = implode('.', HtmlHelper::nameToArray($this->fieldName)); + $locale = array_get($data, $fieldName); + + if (!$locale) { + return; + } + + // Splice the save data in to the locker data for selected locale + $data = $this->getPrimarySaveDataAsArray(); + $fieldName = 'RLTranslate.'.$locale.'.'.implode('.', HtmlHelper::nameToArray($this->fieldName)); + + $requestData = Request::all(); + array_set($requestData, $fieldName, json_encode($data)); + $this->mergeWithPost($requestData); + } + + /** + * mergeWithPost will apply postback values globally + */ + protected function mergeWithPost(array $values) + { + Request::merge($values); + $_POST = array_merge($_POST, $values); + } +} diff --git a/plugins/rainlab/translate/formwidgets/MLRichEditor.php b/plugins/rainlab/translate/formwidgets/MLRichEditor.php new file mode 100644 index 0000000..92f4bd2 --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/MLRichEditor.php @@ -0,0 +1,119 @@ +initLocale(); + } + + /** + * {@inheritDoc} + */ + public function render() + { + $this->actAsParent(); + $parentContent = parent::render(); + $this->actAsParent(false); + + if (!$this->isAvailable) { + return $parentContent; + } + + $this->vars['richeditor'] = $parentContent; + return $this->makePartial('mlricheditor'); + } + + /** + * prepareVars + */ + public function prepareVars() + { + parent::prepareVars(); + $this->prepareLocaleVars(); + } + + /** + * getSaveValue returns an array of translated values for this field + * @return array + */ + public function getSaveValue($value) + { + return $this->getLocaleSaveValue($value); + } + + /** + * {@inheritDoc} + */ + protected function loadAssets() + { + $this->actAsParent(); + parent::loadAssets(); + $this->actAsParent(false); + + if (Locale::isAvailable()) { + $this->loadLocaleAssets(); + $this->addJs('js/mlricheditor.js'); + } + } + + /** + * {@inheritDoc} + */ + public function onLoadPageLinksForm() + { + $this->actAsParent(); + return parent::onLoadPageLinksForm(); + } + + /** + * {@inheritDoc} + */ + protected function getParentViewPath() + { + return base_path().'/modules/backend/formwidgets/richeditor/partials'; + } + + /** + * {@inheritDoc} + */ + protected function getParentAssetPath() + { + return '/modules/backend/formwidgets/richeditor/assets'; + } +} diff --git a/plugins/rainlab/translate/formwidgets/MLText.php b/plugins/rainlab/translate/formwidgets/MLText.php new file mode 100644 index 0000000..c0a74bc --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/MLText.php @@ -0,0 +1,59 @@ +initLocale(); + } + + /** + * {@inheritDoc} + */ + public function render() + { + $this->prepareLocaleVars(); + + if ($this->isAvailable) { + return $this->makePartial('mltext'); + } + else { + return $this->renderFallbackField(); + } + } + + /** + * getSaveValue returns an array of translated values for this field + * @return array + */ + public function getSaveValue($value) + { + return $this->getLocaleSaveValue($value); + } + + /** + * {@inheritDoc} + */ + protected function loadAssets() + { + $this->loadLocaleAssets(); + } +} diff --git a/plugins/rainlab/translate/formwidgets/MLTextarea.php b/plugins/rainlab/translate/formwidgets/MLTextarea.php new file mode 100644 index 0000000..12b0837 --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/MLTextarea.php @@ -0,0 +1,64 @@ +initLocale(); + } + + /** + * {@inheritDoc} + */ + public function render() + { + $this->prepareLocaleVars(); + + if ($this->isAvailable) { + return $this->makePartial('mltextarea'); + } + else { + return $this->renderFallbackField(); + } + } + + /** + * getSaveValue returns an array of translated values for this field + * @return array + */ + public function getSaveValue($value) + { + return $this->getLocaleSaveValue($value); + } + + /** + * {@inheritDoc} + */ + protected function loadAssets() + { + $this->loadLocaleAssets(); + } +} diff --git a/plugins/rainlab/translate/formwidgets/mlmarkdowneditor/assets/js/mlmarkdowneditor.js b/plugins/rainlab/translate/formwidgets/mlmarkdowneditor/assets/js/mlmarkdowneditor.js new file mode 100644 index 0000000..e6b0f56 --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/mlmarkdowneditor/assets/js/mlmarkdowneditor.js @@ -0,0 +1,107 @@ +/* + * MLMarkdownEditor plugin + * + * Data attributes: + * - data-control="mlmarkdowneditor" - enables the plugin on an element + * - data-textarea-element="textarea#id" - an option with a value + * + * JavaScript API: + * $('a#someElement').mlMarkdownEditor({ option: 'value' }) + * + */ + ++function ($) { "use strict"; + + var Base = $.oc.foundation.base, + BaseProto = Base.prototype + + // MLMARKDOWNEDITOR CLASS DEFINITION + // ============================ + + var MLMarkdownEditor = function(element, options) { + this.options = options + this.$el = $(element) + this.$textarea = $(options.textareaElement) + this.$markdownEditor = $('[data-control=markdowneditor]:first', this.$el) + + $.oc.foundation.controlUtils.markDisposable(element) + Base.call(this) + + // Init + this.init() + } + + MLMarkdownEditor.prototype = Object.create(BaseProto) + MLMarkdownEditor.prototype.constructor = MLMarkdownEditor + + MLMarkdownEditor.DEFAULTS = { + textareaElement: null, + placeholderField: null, + defaultLocale: 'en' + } + + MLMarkdownEditor.prototype.init = function() { + this.$el.multiLingual() + + this.$el.on('setLocale.oc.multilingual', this.proxy(this.onSetLocale)) + this.$textarea.on('changeContent.oc.markdowneditor', this.proxy(this.onChangeContent)) + + this.$el.one('dispose-control', this.proxy(this.dispose)) + } + + MLMarkdownEditor.prototype.dispose = function() { + this.$el.off('setLocale.oc.multilingual', this.proxy(this.onSetLocale)) + this.$textarea.off('changeContent.oc.markdowneditor', this.proxy(this.onChangeContent)) + this.$el.off('dispose-control', this.proxy(this.dispose)) + + this.$el.removeData('oc.mlMarkdownEditor') + + this.$textarea = null + this.$markdownEditor = null + this.$el = null + + this.options = null + + BaseProto.dispose.call(this) + } + + MLMarkdownEditor.prototype.onSetLocale = function(e, locale, localeValue) { + if (typeof localeValue === 'string' && this.$markdownEditor.data('oc.markdownEditor')) { + this.$markdownEditor.markdownEditor('setContent', localeValue); + } + } + + MLMarkdownEditor.prototype.onChangeContent = function(ev, markdowneditor, value) { + this.$el.multiLingual('setLocaleValue', value) + } + + var old = $.fn.mlMarkdownEditor + + $.fn.mlMarkdownEditor = function (option) { + var args = Array.prototype.slice.call(arguments, 1), result + + this.each(function () { + var $this = $(this) + var data = $this.data('oc.mlMarkdownEditor') + var options = $.extend({}, MLMarkdownEditor.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.mlMarkdownEditor', (data = new MLMarkdownEditor(this, options))) + if (typeof option == 'string') result = data[option].apply(data, args) + if (typeof result != 'undefined') return false + }) + + return result ? result : this + } + + $.fn.mlMarkdownEditor.Constructor = MLMarkdownEditor; + + $.fn.mlMarkdownEditor.noConflict = function () { + $.fn.mlMarkdownEditor = old + return this + } + + $(document).render(function (){ + $('[data-control="mlmarkdowneditor"]').mlMarkdownEditor() + }) + + +}(window.jQuery); diff --git a/plugins/rainlab/translate/formwidgets/mlmarkdowneditor/partials/_mlmarkdowneditor.htm b/plugins/rainlab/translate/formwidgets/mlmarkdowneditor/partials/_mlmarkdowneditor.htm new file mode 100644 index 0000000..03179f9 --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/mlmarkdowneditor/partials/_mlmarkdowneditor.htm @@ -0,0 +1,23 @@ + + diff --git a/plugins/rainlab/translate/formwidgets/mlmediafinder/assets/css/mlmediafinder.css b/plugins/rainlab/translate/formwidgets/mlmediafinder/assets/css/mlmediafinder.css new file mode 100644 index 0000000..9bd687b --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/mlmediafinder/assets/css/mlmediafinder.css @@ -0,0 +1,8 @@ +.field-multilingual-mediafinder > .ml-btn { + top: -28px; + right: 4px; +} + +.field-multilingual-mediafinder > .ml-dropdown-menu { + top: 1px; +} diff --git a/plugins/rainlab/translate/formwidgets/mlmediafinder/assets/js/mlmediafinder.js b/plugins/rainlab/translate/formwidgets/mlmediafinder/assets/js/mlmediafinder.js new file mode 100755 index 0000000..1b51234 --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/mlmediafinder/assets/js/mlmediafinder.js @@ -0,0 +1,136 @@ +/* + * MLMediaFinder plugin + * + * Data attributes: + * - data-control="mlmediafinder" - enables the plugin on an element + * - data-option="value" - an option with a value + * + * JavaScript API: + * $('a#someElement').mlMediaFinder({ option: 'value' }) + * + * Dependences: + * - mediafinder (mediafinder.js) + */ + ++function($) { "use strict"; + var Base = $.oc.foundation.base, + BaseProto = Base.prototype + + // MLMEDIAFINDER CLASS DEFINITION + // ============================ + + var MLMediaFinder = function(element, options) { + this.options = options + this.$el = $(element) + this.$mediafinder = $('[data-control=mediafinder]', this.$el) + this.$findValue = $('[data-find-value]', this.$el) + + $.oc.foundation.controlUtils.markDisposable(element) + Base.call(this) + this.init() + } + + MLMediaFinder.prototype = Object.create(BaseProto) + MLMediaFinder.prototype.constructor = MLMediaFinder + + MLMediaFinder.DEFAULTS = { + placeholderField: null, + defaultLocale: 'en', + mediaPath: '/', + } + + MLMediaFinder.prototype.init = function() { + + this.$el.multiLingual() + this.$el.on('setLocale.oc.multilingual', this.proxy(this.onSetLocale)) + this.$el.one('dispose-control', this.proxy(this.dispose)) + // Listen for change event from mediafinder + this.$findValue.on('change', this.proxy(this.setValue)) + + // Stop here for preview mode + if (this.options.isPreview) + return + } + + // Simplify setPath + MLMediaFinder.prototype.setValue = function(e) { + this.setPath($(e.target).val()) + } + + MLMediaFinder.prototype.dispose = function() { + this.$el.off('setLocale.oc.multilingual', this.proxy(this.onSetLocale)) + this.$el.off('dispose-control', this.proxy(this.dispose)) + this.$findValue.off('change', this.proxy(this.setValue)) + + this.$el.removeData('oc.mlMediaFinder') + + this.$findValue = null + this.$mediafinder = null; + this.$el = null + + // In some cases options could contain callbacks, + // so it's better to clean them up too. + this.options = null + + BaseProto.dispose.call(this) + } + + + MLMediaFinder.prototype.onSetLocale = function(e, locale, localeValue) { + this.setPath(localeValue) + } + + MLMediaFinder.prototype.setPath = function(localeValue) { + if (typeof localeValue === 'string') { + this.$findValue = localeValue; + + var path = localeValue ? this.options.mediaPath + localeValue : '' + + $('[data-find-image]', this.$mediafinder).attr('src', path) + $('[data-find-file-name]', this.$mediafinder).text(localeValue.substring(1)) + + // if value is present display image/file, else display open icon for media manager + this.$mediafinder.toggleClass('is-populated', !!localeValue) + + this.$el.multiLingual('setLocaleValue', localeValue); + } + } + + // MLMEDIAFINDER PLUGIN DEFINITION + // ============================ + + var old = $.fn.mlMediaFinder + + $.fn.mlMediaFinder = function (option) { + var args = Array.prototype.slice.call(arguments, 1), result + this.each(function () { + var $this = $(this) + var data = $this.data('oc.mlMediaFinder') + var options = $.extend({}, MLMediaFinder.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.mlMediaFinder', (data = new MLMediaFinder(this, options))) + if (typeof option === 'string') result = data[option].apply(data, args) + if (typeof result !== 'undefined') return false + }) + + return result ? result : this + } + + $.fn.mlMediaFinder.Constructor = MLMediaFinder + + // MLMEDIAFINDER NO CONFLICT + // ================= + + $.fn.mlMediaFinder.noConflict = function () { + $.fn.mlMediaFinder = old + return this + } + + // MLMEDIAFINDER DATA-API + // =============== + + $(document).render(function () { + $('[data-control="mlmediafinder"]').mlMediaFinder() + }) + + +}(window.jQuery); diff --git a/plugins/rainlab/translate/formwidgets/mlmediafinder/partials/_mlmediafinder.htm b/plugins/rainlab/translate/formwidgets/mlmediafinder/partials/_mlmediafinder.htm new file mode 100755 index 0000000..8c0d86e --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/mlmediafinder/partials/_mlmediafinder.htm @@ -0,0 +1,22 @@ + + diff --git a/plugins/rainlab/translate/formwidgets/mlmediafinderv2/assets/js/mlmediafinder.js b/plugins/rainlab/translate/formwidgets/mlmediafinderv2/assets/js/mlmediafinder.js new file mode 100644 index 0000000..4e050e5 --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/mlmediafinderv2/assets/js/mlmediafinder.js @@ -0,0 +1,182 @@ +/* + * MLMediaFinder plugin + * + * Data attributes: + * - data-control="mlmediafinder" - enables the plugin on an element + * - data-option="value" - an option with a value + * + * JavaScript API: + * $('a#someElement').mlMediaFinder({ option: 'value' }) + * + * Dependences: + * - mediafinder (mediafinder.js) + */ + ++function($) { "use strict"; + var Base = $.oc.foundation.base, + BaseProto = Base.prototype + + // MLMEDIAFINDER CLASS DEFINITION + // ============================ + + var MLMediaFinder = function(element, options) { + this.options = options + this.$el = $(element) + this.$mediafinder = $('[data-control=mediafinder]', this.$el) + this.$dataLocker = $('[data-data-locker]', this.$el) + this.isMulti = this.$mediafinder.hasClass('is-multi') + + $.oc.foundation.controlUtils.markDisposable(element) + Base.call(this) + this.init() + } + + MLMediaFinder.prototype = Object.create(BaseProto) + MLMediaFinder.prototype.constructor = MLMediaFinder + + MLMediaFinder.DEFAULTS = { + placeholderField: null, + defaultLocale: 'en', + mediaPath: '/', + } + + MLMediaFinder.prototype.init = function() { + + this.$el.multiLingual() + this.$el.on('setLocale.oc.multilingual', this.proxy(this.onSetLocale)) + this.$el.one('dispose-control', this.proxy(this.dispose)) + + // Listen for change event from mediafinder + this.$dataLocker.on('change', this.proxy(this.setValue)) + + // Stop here for preview mode + if (this.options.isPreview) { + return; + } + } + + MLMediaFinder.prototype.dispose = function() { + this.$el.off('setLocale.oc.multilingual', this.proxy(this.onSetLocale)); + this.$el.off('dispose-control', this.proxy(this.dispose)); + this.$dataLocker.off('change', this.proxy(this.setValue)); + + this.$el.removeData('oc.mlMediaFinder'); + + this.$dataLocker = null; + this.$mediafinder = null; + this.$el = null; + + // In some cases options could contain callbacks, + // so it's better to clean them up too. + this.options = null; + + BaseProto.dispose.call(this) + } + + MLMediaFinder.prototype.setValue = function(e) { + var mediafinder = this.$mediafinder.data('oc.mediaFinder'), + value = mediafinder.getValue(); + + if (value) { + if (this.isMulti) { + value = JSON.stringify(value); + } + else { + value = value[0]; + } + } + + this.setPath(value); + } + + MLMediaFinder.prototype.onSetLocale = function(e, locale, localeValue) { + this.setPath(localeValue) + } + + MLMediaFinder.prototype.setPath = function(localeValue) { + if (typeof localeValue === 'string') { + var self = this, + isMulti = this.isMulti, + mediaFinder = this.$mediafinder.data('oc.mediaFinder'), + items = [], + localeValueArr = []; + + try { + localeValueArr = JSON.parse(localeValue); + if (!$.isArray(localeValueArr)) { + localeValueArr = [localeValueArr]; + } + } + catch(e) { + isMulti = false; + } + + mediaFinder.$filesContainer.empty(); + + if (isMulti) { + $.each(localeValueArr, function(k, v) { + if (v) { + items.push({ + path: v, + publicUrl: self.options.mediaPath + v, + thumbUrl: self.options.mediaPath + v, + title: v.substring(1) + }); + } + }); + } + else { + if (localeValue) { + items = [{ + path: localeValue, + publicUrl: this.options.mediaPath + localeValue, + thumbUrl: this.options.mediaPath + localeValue, + title: localeValue.substring(1) + }]; + } + } + + mediaFinder.addItems(items); + mediaFinder.evalIsPopulated(); + mediaFinder.evalIsMaxReached(); + + this.$el.multiLingual('setLocaleValue', localeValue); + } + } + + // MLMEDIAFINDER PLUGIN DEFINITION + // ============================ + + var old = $.fn.mlMediaFinder + + $.fn.mlMediaFinder = function (option) { + var args = Array.prototype.slice.call(arguments, 1), result + this.each(function () { + var $this = $(this) + var data = $this.data('oc.mlMediaFinder') + var options = $.extend({}, MLMediaFinder.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.mlMediaFinder', (data = new MLMediaFinder(this, options))) + if (typeof option === 'string') result = data[option].apply(data, args) + if (typeof result !== 'undefined') return false + }) + + return result ? result : this + } + + $.fn.mlMediaFinder.Constructor = MLMediaFinder + + // MLMEDIAFINDER NO CONFLICT + // ================= + + $.fn.mlMediaFinder.noConflict = function () { + $.fn.mlMediaFinder = old + return this + } + + // MLMEDIAFINDER DATA-API + // =============== + + $(document).render(function () { + $('[data-control="mlmediafinder"]').mlMediaFinder() + }); +}(window.jQuery); diff --git a/plugins/rainlab/translate/formwidgets/mlmediafinderv2/partials/_mlmediafinder.htm b/plugins/rainlab/translate/formwidgets/mlmediafinderv2/partials/_mlmediafinder.htm new file mode 100644 index 0000000..8c0d86e --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/mlmediafinderv2/partials/_mlmediafinder.htm @@ -0,0 +1,22 @@ + + diff --git a/plugins/rainlab/translate/formwidgets/mlnestedform/assets/js/mlnestedform.js b/plugins/rainlab/translate/formwidgets/mlnestedform/assets/js/mlnestedform.js new file mode 100644 index 0000000..ace10ad --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/mlnestedform/assets/js/mlnestedform.js @@ -0,0 +1,126 @@ +/* + * MLNestedForm plugin + * + * Data attributes: + * - data-control="mlnestedform" - enables the plugin on an element + * + * JavaScript API: + * $('a#someElement').mlNestedForm({ option: 'value' }) + * + */ ++function ($) { "use strict"; + + var Base = $.oc.foundation.base, + BaseProto = Base.prototype + + // MLREPEATER CLASS DEFINITION + // ============================ + + var MLNestedForm = function(element, options) { + this.options = options; + this.$el = $(element); + this.$selector = $('[data-locale-dropdown]', this.$el); + this.$locale = $('[data-nestedform-active-locale]', this.$el); + this.locale = options.defaultLocale; + + $.oc.foundation.controlUtils.markDisposable(element); + Base.call(this); + + // Init + this.init(); + } + + MLNestedForm.prototype = Object.create(BaseProto); + MLNestedForm.prototype.constructor = MLNestedForm; + + MLNestedForm.DEFAULTS = { + switchHandler: null, + defaultLocale: 'en' + } + + MLNestedForm.prototype.init = function() { + this.$el.multiLingual(); + + this.$el.on('setLocale.oc.multilingual', this.proxy(this.onSetLocale)); + + this.$el.one('dispose-control', this.proxy(this.dispose)); + } + + MLNestedForm.prototype.dispose = function() { + this.$el.off('setLocale.oc.multilingual', this.proxy(this.onSetLocale)); + + this.$el.off('dispose-control', this.proxy(this.dispose)); + + this.$el.removeData('oc.mlNestedForm'); + + this.$selector = null; + this.$locale = null; + this.locale = null; + this.$el = null; + + this.options = null; + + BaseProto.dispose.call(this); + } + + MLNestedForm.prototype.onSetLocale = function(e, locale, localeValue) { + var self = this, + previousLocale = this.locale; + + this.$el + .addClass('loading-indicator-container size-form-field') + .loadIndicator(); + + this.locale = locale; + this.$locale.val(locale); + + this.$el.request(this.options.switchHandler, { + data: { + _nestedform_previous_locale: previousLocale, + _nestedform_locale: locale + }, + success: function(data) { + self.$el.multiLingual('setLocaleValue', data.updateValue, data.updateLocale); + self.$el.loadIndicator('hide'); + this.success(data); + } + }); + } + + // MLREPEATER PLUGIN DEFINITION + // ============================ + + var old = $.fn.mlNestedForm; + + $.fn.mlNestedForm = function (option) { + var args = Array.prototype.slice.call(arguments, 1), result; + this.each(function () { + var $this = $(this); + var data = $this.data('oc.mlNestedForm'); + var options = $.extend({}, MLNestedForm.DEFAULTS, $this.data(), typeof option == 'object' && option); + if (!data) $this.data('oc.mlNestedForm', (data = new MLNestedForm(this, options))); + if (typeof option == 'string') result = data[option].apply(data, args); + if (typeof result != 'undefined') return false; + }) + + return result ? result : this; + } + + $.fn.mlNestedForm.Constructor = MLNestedForm; + + // MLREPEATER NO CONFLICT + // ================= + + $.fn.mlNestedForm.noConflict = function () { + $.fn.mlNestedForm = old + return this + } + + // MLREPEATER DATA-API + // =============== + + $(document).render(function () { + $('[data-control="mlnestedform"]').mlNestedForm(); + }); + +}(window.jQuery); diff --git a/plugins/rainlab/translate/formwidgets/mlnestedform/partials/_mlnestedform.htm b/plugins/rainlab/translate/formwidgets/mlnestedform/partials/_mlnestedform.htm new file mode 100644 index 0000000..d46d6f9 --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/mlnestedform/partials/_mlnestedform.htm @@ -0,0 +1,31 @@ + + diff --git a/plugins/rainlab/translate/formwidgets/mlrepeater/assets/js/mlrepeater.js b/plugins/rainlab/translate/formwidgets/mlrepeater/assets/js/mlrepeater.js new file mode 100644 index 0000000..d412b0d --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/mlrepeater/assets/js/mlrepeater.js @@ -0,0 +1,139 @@ +/* + * MLRepeater plugin + * + * Data attributes: + * - data-control="mlrepeater" - enables the plugin on an element + * + * JavaScript API: + * $('a#someElement').mlRepeater({ option: 'value' }) + * + */ + ++function ($) { "use strict"; + + var Base = $.oc.foundation.base, + BaseProto = Base.prototype + + // MLREPEATER CLASS DEFINITION + // ============================ + + var MLRepeater = function(element, options) { + this.options = options + this.$el = $(element) + this.$selector = $('[data-locale-dropdown]', this.$el) + this.$locale = $('[data-repeater-active-locale]', this.$el) + this.locale = options.defaultLocale + + $.oc.foundation.controlUtils.markDisposable(element) + Base.call(this) + + // Init + this.init() + } + + MLRepeater.prototype = Object.create(BaseProto) + MLRepeater.prototype.constructor = MLRepeater + + MLRepeater.DEFAULTS = { + switchHandler: null, + defaultLocale: 'en' + } + + MLRepeater.prototype.init = function() { + this.$el.multiLingual() + + this.checkEmptyItems() + + $(document).on('render', this.proxy(this.checkEmptyItems)) + + this.$el.on('setLocale.oc.multilingual', this.proxy(this.onSetLocale)) + + this.$el.one('dispose-control', this.proxy(this.dispose)) + } + + MLRepeater.prototype.dispose = function() { + + $(document).off('render', this.proxy(this.checkEmptyItems)) + + this.$el.off('setLocale.oc.multilingual', this.proxy(this.onSetLocale)) + + this.$el.off('dispose-control', this.proxy(this.dispose)) + + this.$el.removeData('oc.mlRepeater') + + this.$selector = null + this.$locale = null + this.locale = null + this.$el = null + + this.options = null + + BaseProto.dispose.call(this) + } + + MLRepeater.prototype.checkEmptyItems = function() { + var isEmpty = !$('ul.field-repeater-items > li', this.$el).length + this.$el.toggleClass('is-empty', isEmpty) + } + + MLRepeater.prototype.onSetLocale = function(e, locale, localeValue) { + var self = this, + previousLocale = this.locale + + this.$el + .addClass('loading-indicator-container size-form-field') + .loadIndicator() + + this.locale = locale + this.$locale.val(locale) + + this.$el.request(this.options.switchHandler, { + data: { + _repeater_previous_locale: previousLocale, + _repeater_locale: locale + }, + success: function(data) { + self.$el.multiLingual('setLocaleValue', data.updateValue, data.updateLocale) + self.$el.loadIndicator('hide') + this.success(data) + } + }) + } + + // MLREPEATER PLUGIN DEFINITION + // ============================ + + var old = $.fn.mlRepeater + + $.fn.mlRepeater = function (option) { + var args = Array.prototype.slice.call(arguments, 1), result + this.each(function () { + var $this = $(this) + var data = $this.data('oc.mlRepeater') + var options = $.extend({}, MLRepeater.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.mlRepeater', (data = new MLRepeater(this, options))) + if (typeof option == 'string') result = data[option].apply(data, args) + if (typeof result != 'undefined') return false + }) + + return result ? result : this + } + + $.fn.mlRepeater.Constructor = MLRepeater + + // MLREPEATER NO CONFLICT + // ================= + + $.fn.mlRepeater.noConflict = function () { + $.fn.mlRepeater = old + return this + } + + // MLREPEATER DATA-API + // =============== + + $(document).render(function () { + $('[data-control="mlrepeater"]').mlRepeater() + }) + +}(window.jQuery); diff --git a/plugins/rainlab/translate/formwidgets/mlrepeater/partials/_mlrepeater.htm b/plugins/rainlab/translate/formwidgets/mlrepeater/partials/_mlrepeater.htm new file mode 100644 index 0000000..1d6480e --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/mlrepeater/partials/_mlrepeater.htm @@ -0,0 +1,31 @@ + + diff --git a/plugins/rainlab/translate/formwidgets/mlricheditor/assets/js/mlricheditor.js b/plugins/rainlab/translate/formwidgets/mlricheditor/assets/js/mlricheditor.js new file mode 100644 index 0000000..807848a --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/mlricheditor/assets/js/mlricheditor.js @@ -0,0 +1,135 @@ +/* + * MLRichEditor plugin + * + * Data attributes: + * - data-control="mlricheditor" - enables the plugin on an element + * - data-textarea-element="textarea#id" - an option with a value + * + * JavaScript API: + * $('a#someElement').mlRichEditor({ option: 'value' }) + * + */ + ++function ($) { "use strict"; + + var Base = $.oc.foundation.base, + BaseProto = Base.prototype + + // MLRICHEDITOR CLASS DEFINITION + // ============================ + + var MLRichEditor = function(element, options) { + this.options = options + this.$el = $(element) + this.$textarea = $(options.textareaElement) + this.$richeditor = $('[data-control=richeditor]:first', this.$el) + + $.oc.foundation.controlUtils.markDisposable(element) + Base.call(this) + + // Init + this.init() + } + + MLRichEditor.prototype = Object.create(BaseProto) + MLRichEditor.prototype.constructor = MLRichEditor + + MLRichEditor.DEFAULTS = { + textareaElement: null, + placeholderField: null, + defaultLocale: 'en' + } + + MLRichEditor.prototype.init = function() { + this.$el.multiLingual() + + this.$el.on('setLocale.oc.multilingual', this.proxy(this.onSetLocale)) + this.$textarea.on('syncContent.oc.richeditor', this.proxy(this.onSyncContent)) + + this.updateLayout() + + $(window).on('resize', this.proxy(this.updateLayout)) + $(window).on('oc.updateUi', this.proxy(this.updateLayout)) + this.$el.one('dispose-control', this.proxy(this.dispose)) + } + + MLRichEditor.prototype.dispose = function() { + this.$el.off('setLocale.oc.multilingual', this.proxy(this.onSetLocale)) + this.$textarea.off('syncContent.oc.richeditor', this.proxy(this.onSyncContent)) + $(window).off('resize', this.proxy(this.updateLayout)) + $(window).off('oc.updateUi', this.proxy(this.updateLayout)) + + this.$el.off('dispose-control', this.proxy(this.dispose)) + + this.$el.removeData('oc.mlRichEditor') + + this.$textarea = null + this.$richeditor = null + this.$el = null + + this.options = null + + BaseProto.dispose.call(this) + } + + MLRichEditor.prototype.onSetLocale = function(e, locale, localeValue) { + if (typeof localeValue === 'string' && this.$richeditor.data('oc.richEditor')) { + this.$richeditor.richEditor('setContent', localeValue); + } + } + + MLRichEditor.prototype.onSyncContent = function(ev, richeditor, value) { + this.$el.multiLingual('setLocaleValue', value.html) + } + + MLRichEditor.prototype.updateLayout = function() { + var $toolbar = $('.fr-toolbar', this.$el), + $btn = $('.ml-btn[data-active-locale]:first', this.$el), + $dropdown = $('.ml-dropdown-menu[data-locale-dropdown]:first', this.$el) + + if (!$toolbar.length) { + return + } + + var height = $toolbar.outerHeight(true) + $btn.css('top', height + 6) + $dropdown.css('top', height + 40) + } + + // MLRICHEDITOR PLUGIN DEFINITION + // ============================ + + var old = $.fn.mlRichEditor + + $.fn.mlRichEditor = function (option) { + var args = Array.prototype.slice.call(arguments, 1), result + this.each(function () { + var $this = $(this) + var data = $this.data('oc.mlRichEditor') + var options = $.extend({}, MLRichEditor.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.mlRichEditor', (data = new MLRichEditor(this, options))) + if (typeof option == 'string') result = data[option].apply(data, args) + if (typeof result != 'undefined') return false + }) + + return result ? result : this + } + + $.fn.mlRichEditor.Constructor = MLRichEditor + + // MLRICHEDITOR NO CONFLICT + // ================= + + $.fn.mlRichEditor.noConflict = function () { + $.fn.mlRichEditor = old + return this + } + + // MLRICHEDITOR DATA-API + // =============== + + $(document).render(function () { + $('[data-control="mlricheditor"]').mlRichEditor() + }) + +}(window.jQuery); diff --git a/plugins/rainlab/translate/formwidgets/mlricheditor/partials/_mlricheditor.htm b/plugins/rainlab/translate/formwidgets/mlricheditor/partials/_mlricheditor.htm new file mode 100644 index 0000000..6f3e19c --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/mlricheditor/partials/_mlricheditor.htm @@ -0,0 +1,23 @@ + + diff --git a/plugins/rainlab/translate/formwidgets/mltext/partials/_mltext.htm b/plugins/rainlab/translate/formwidgets/mltext/partials/_mltext.htm new file mode 100644 index 0000000..b8a5735 --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/mltext/partials/_mltext.htm @@ -0,0 +1,36 @@ + +previewMode): ?> + value ? e($field->value) : ' ' ?> + + + diff --git a/plugins/rainlab/translate/formwidgets/mltextarea/partials/_mltextarea.htm b/plugins/rainlab/translate/formwidgets/mltextarea/partials/_mltextarea.htm new file mode 100644 index 0000000..1a710bd --- /dev/null +++ b/plugins/rainlab/translate/formwidgets/mltextarea/partials/_mltextarea.htm @@ -0,0 +1,32 @@ + +previewMode): ?> +
    value)) ?>
    + + + diff --git a/plugins/rainlab/translate/lang/ar/ar.php b/plugins/rainlab/translate/lang/ar/ar.php new file mode 100644 index 0000000..aee91f4 --- /dev/null +++ b/plugins/rainlab/translate/lang/ar/ar.php @@ -0,0 +1,59 @@ + [ + 'name' => 'ترجمة', + 'description' => 'تفعيل تعدد اللغات للموقع.', + 'tab' => 'ترجمة', + 'manage_locales' => 'إدارة اللغات', + 'manage_messages' => 'إدارة النصوص', + ], + 'locale_picker' => [ + 'component_name' => 'محدد اللغات', + 'component_description' => 'عرض قائمة لتحديد لغة الواجهة.', + ], + 'alternate_hreflang' => [ + 'component_name' => 'عناصر بدائل hrefLang', + 'component_description' => 'إضافة بدائل اللغة للصفحة كعنصر hreflang ' + ], + 'locale' => [ + 'title' => 'إدارة اللغات', + 'update_title' => 'تحديث اللغة', + 'create_title' => 'إنشاء لغة', + 'select_label' => 'تحديد اللغة', + 'default_suffix' => 'افتراضي', + 'unset_default' => '":locale" بالفعل افتراضي ولايمكن نزع الافتراضية عنها.', + 'delete_default' => '":locale" هو افتراضي فلا يمكن حذفه.', + 'disabled_default' => '":locale" معطل فلايمكن تعيينه كافتراضي.', + 'name' => 'اسم', + 'code' => 'رمز', + 'is_default' => 'افتراضي', + 'is_default_help' => 'اللغة الافتراضية تمثل المحتوى قبل ترجمته.', + 'is_enabled' => 'مفعل', + 'is_enabled_help' => 'اللغات المعطلة ستكون غير متاحة في الواجهة.', + 'not_available_help' => 'لا توجد لغات أخرى لإعدادها.', + 'hint_locales' => 'إنشاء لغة جديدة هنا لترجمة محتويات الواجهة. اللغة الافتراضية تمثل المحتوى قبل ترجمته.', + 'reorder_title' => 'إعادة ترتيب لغات', + 'sort_order' => 'اتجاه الترتيب', + ], + 'messages' => [ + 'title' => 'ترجمة النصوص', + 'description' => 'تحديث النصوص', + 'clear_cache_link' => 'مسح المخبآت', + 'clear_cache_loading' => 'يتم مسح مخبآت التطبيق...', + 'clear_cache_success' => 'تم مسح مخبآت التطبيق بنجاح!', + 'clear_cache_hint' => 'ربما يجب عليك الضغط على مسح المخبآت لترى التغييرات في الواجهة.', + 'scan_messages_link' => 'استكشاف النصوص', + 'scan_messages_begin_scan' => 'بدء الاستكشاف', + 'scan_messages_loading' => 'يتم استكشاف نصوص جديدة...', + 'scan_messages_success' => 'تم استكشاف ملفات القالب بنجاح!', + 'scan_messages_hint' => 'عند الضغط على استكشاف النصوص سيتم استكشاف ملفات القالب النشط لإيجاد نصوص جديدة لترجمتها.', + 'scan_messages_process' => 'هذه العملية ستقوم باستكشاف ملفات القالب النشط لإيجاد أي نصوص جديدة يمكن ترجمتها.', + 'scan_messages_process_limitations' => 'بعض النصوص قد لا يتم التقاطها وستظهر بعد أول استعمال لها.', + 'scan_messages_purge_label' => 'إفراغ جميع الرسائل أولا', + 'scan_messages_purge_help' => 'عند تحديد هذه الخاصية سيتم حذف جميع النصوص قبل علية الاستكشاف.', + 'scan_messages_purge_confirm' => 'هل أنت متأكد من حذف جميع النصوص? لن يمكنك التراجع بعد الآن!', + 'hint_translate' => 'هنا يمكن ترجمة النصوص المستعملة في الواجهة، سيتم الحفظ آليا.', + 'hide_translated' => 'إخفاء النصوص المترجمة', + 'export_messages_link' => 'تصدير النصوص', + 'import_messages_link' => 'استيراد النصوص', + ], +]; diff --git a/plugins/rainlab/translate/lang/bg/lang.php b/plugins/rainlab/translate/lang/bg/lang.php new file mode 100644 index 0000000..99d362c --- /dev/null +++ b/plugins/rainlab/translate/lang/bg/lang.php @@ -0,0 +1,46 @@ + [ + 'name' => 'Превод', + 'description' => 'Активира функцията многоезични уебсайтове.', + 'tab' => 'Преводи', + 'manage_locales' => 'Настройка на локация', + 'manage_messages' => 'Настройка на съобщения' + ], + 'locale_picker' => [ + 'component_name' => 'Избор на местоположение', + 'component_description' => 'Показва меню за избор на езика на сайта.', + ], + 'locale' => [ + 'title' => 'Настройка на езици', + 'update_title' => 'Актуализация на език', + 'create_title' => 'Създай език', + 'select_label' => 'Избери език', + 'default_suffix' => 'по подразбиране', + 'unset_default' => '":locale" вече е по подразбиране и не може да бъде изключен по подразбиране.', + 'disabled_default' => '":locale" е забранен и не може да бъде зададен по подразбиране.', + 'name' => 'Име', + 'code' => 'Код', + 'is_default' => 'По подразбиране', + 'is_default_help' => 'Основният език представлява съдържанието на сайта преди превод.', + 'is_enabled' => 'Включен', + 'is_enabled_help' => 'Изключените езици няма да са налични за преглед в сайта.', + 'not_available_help' => 'Не съществуват други езици за настройка.', + 'hint_locales' => 'Създайте нови езици за превод на съдържанието на сайта. Основният език представлява съдържанието, преди той да бъде преведен.', + ], + 'messages' => [ + 'title' => 'Преведени Съобщения', + 'description' => 'Актуализарай Съобщения', + 'clear_cache_link' => 'Изтрий кеш-паметта', + 'clear_cache_loading' => 'Изчистване кеша на приложението...', + 'clear_cache_success' => 'Кеш кеш-паметта успешно изтрита!', + 'clear_cache_hint' => 'Може да е необходимо да кликнете на бутона Изтрий кеш-паметта за да видите промените на вашата страница.', + 'scan_messages_link' => 'Сканирай за съобщения', + 'scan_messages_loading' => 'Сканиране за нови съобщения...', + 'scan_messages_success' => 'Темата е сканирана успешно!', + 'scan_messages_hint' => 'Ако кликнете на Сканирай за съобщения това ще провери темата за нови съобщения (изречения) за превод.', + 'hint_translate' => 'Тук може да превеждате съобщенията (изреченията) на самият сайт, полетата ще се запазят автоматично.', + 'hide_translated' => 'Скрий преведените', + ], +]; \ No newline at end of file diff --git a/plugins/rainlab/translate/lang/cs/lang.php b/plugins/rainlab/translate/lang/cs/lang.php new file mode 100644 index 0000000..8bc9f5d --- /dev/null +++ b/plugins/rainlab/translate/lang/cs/lang.php @@ -0,0 +1,46 @@ + [ + 'name' => 'Překlady', + 'description' => 'Aktivuje vícejazyčné stránky a překlady.', + 'tab' => 'Překlad', + 'manage_locales' => 'Správa jazyků', + 'manage_messages' => 'Správa překladů' + ], + 'locale_picker' => [ + 'component_name' => 'Výběr jazyka', + 'component_description' => 'Zobrazí možnost výberu jazyka ve stránkách.', + ], + 'locale' => [ + 'title' => 'Správa jazyků', + 'update_title' => 'Upravit jazyk', + 'create_title' => 'Přidat jazyk', + 'select_label' => 'Výběr jazyka', + 'default_suffix' => 'výchozí', + 'unset_default' => '":locale" je již výchozí a nemůže být odnastavena. Zkuste nastavit jiný jazyk jako výchozí.', + 'disabled_default' => '":locale" je neaktivní, takže nemůže být nastavený jako výchozí.', + 'name' => 'Název', + 'code' => 'Kód', + 'is_default' => 'Výchozí', + 'is_default_help' => 'Výchozí jazyk je jazyk webových stránek před překladem.', + 'is_enabled' => 'Aktivní', + 'is_enabled_help' => 'Neaktivní jazyky nepůjdou vybrat na webových stránkách.', + 'not_available_help' => 'Nemáte nastavené žádné jiné jazyky.', + 'hint_locales' => 'Zde můžete přidat nový jazyk pro překlad webových stránek. Výchozí jazyk reprezentuje obsah stránek ještě před překladem.', + ], + 'messages' => [ + 'title' => 'Překlad textů', + 'description' => 'Upravit text', + 'clear_cache_link' => 'Vymazat cache', + 'clear_cache_loading' => 'Mazání aplikační cache...', + 'clear_cache_success' => 'Aplikační cache úspěšně vymazána!', + 'clear_cache_hint' => 'Možná bude potřeba kliknout na Vymazat cache, aby se změny projevily na webobých stránkách.', + 'scan_messages_link' => 'Najít texty k překladu', + 'scan_messages_loading' => 'Hledání textů k překladu...', + 'scan_messages_success' => 'Prohledávání šablon pro získání textů k překladu úspěšně dokončeno!', + 'scan_messages_hint' => 'Kliknutím na Najít texty k překladu zkontroluje soubory aktivních témat a najde texty k překladu.', + 'hint_translate' => 'Zde můžete přeložit texty použité na webových stránkách. Pole budou automaticky uložena.', + 'hide_translated' => 'Schovat přeložené', + ], +]; diff --git a/plugins/rainlab/translate/lang/de/lang.php b/plugins/rainlab/translate/lang/de/lang.php new file mode 100755 index 0000000..bd6e366 --- /dev/null +++ b/plugins/rainlab/translate/lang/de/lang.php @@ -0,0 +1,47 @@ + [ + 'name' => 'Translate', + 'description' => 'Ermöglicht mehrsprachige Seiten.', + 'manage_locales' => 'Sprachen verwalten', + 'manage_messages' => 'Übersetzungen verwalten', + ], + 'locale_picker' => [ + 'component_name' => 'Sprachauswahl', + 'component_description' => 'Zeigt ein Dropdown-Menü zur Auswahl der Sprache im Frontend.', + ], + 'locale' => [ + 'title' => 'Sprachen verwalten', + 'update_title' => 'Sprache bearbeiten', + 'create_title' => 'Sprache erstellen', + 'select_label' => 'Sprache auswählen', + 'default_suffix' => 'Standard', + 'unset_default' => '":locale" ist bereits die Standardsprache und kann nicht abgewählt werden.', + 'disabled_default' => '":locale" ist deaktiviert und kann deshalb nicht als Standardsprache festgelegt werden.', + 'name' => 'Name', + 'code' => 'Code', + 'is_default' => 'Standard', + 'is_default_help' => 'Die Übersetzung der Standardsprache wird verwendet, um Inhalte anzuzeigen, die in der Sprache des Nutzers nicht vorhanden sind.', + 'is_enabled' => 'Aktiv', + 'is_enabled_help' => 'Deaktivierte Sprachen sind im Frontend nicht verfügbar.', + 'not_available_help' => 'Es gibt keine anderen Sprachen.', + 'hint_locales' => 'Hier können neue Sprachen angelegt werden, in die Inhalte im Frontend übersetzt werden können. Die Standardsprache dient als Ausgangssprache für Übersetzungen.', + 'reorder_title' => 'Sprachen sortieren', + 'sort_order' => 'Sortierung', + ], + 'messages' => [ + 'title' => 'Übersetzungen verwalten', + 'description' => 'Inhalte verwalten und übersetzen', + 'clear_cache_link' => 'Cache leeren', + 'clear_cache_loading' => 'Leere Application-Cache...', + 'clear_cache_success' => 'Application-Cache erfolgreich geleert!', + 'clear_cache_hint' => 'Möglicherweise muss der Cache geleert werden (Button Cache leeren), bevor Änderungen im Frontend sichtbar werden.', + 'scan_messages_link' => 'Nach Inhalten suchen', + 'scan_messages_loading' => 'Suche nach neuen Inhalte...', + 'scan_messages_success' => 'Suche nach neuen Inhalte erfolgreich abgeschlossen!', + 'scan_messages_hint' => 'Ein Klick auf Nach Inhalten suchen sucht nach neuen Inhalten, die übersetzt werden können.', + 'hint_translate' => 'Hier können Inhalte aus dem Frontend übersetzt werden. Die Felder werden automatisch gespeichert.', + 'hide_translated' => 'Bereits übersetzte Inhalte ausblenden', + 'export_messages_link' => 'Übersetzungen exportieren', + 'import_messages_link' => 'Übersetzungen importieren', + ], +]; diff --git a/plugins/rainlab/translate/lang/en/lang.php b/plugins/rainlab/translate/lang/en/lang.php new file mode 100755 index 0000000..8fe2ce3 --- /dev/null +++ b/plugins/rainlab/translate/lang/en/lang.php @@ -0,0 +1,64 @@ + [ + 'name' => 'Translate', + 'description' => 'Enables multi-lingual websites.', + 'tab' => 'Translation', + 'manage_locales' => 'Manage locales', + 'manage_messages' => 'Manage messages', + ], + 'locale_picker' => [ + 'component_name' => 'Locale Picker', + 'component_description' => 'Shows a dropdown to select a front-end language.', + ], + 'alternate_hreflang' => [ + 'component_name' => 'Alternate hrefLang elements', + 'component_description' => 'Injects the language alternatives for page as hreflang elements' + ], + 'locale' => [ + 'title' => 'Manage Languages', + 'update_title' => 'Update Language', + 'create_title' => 'Create Language', + 'select_label' => 'Select Language', + 'default_suffix' => 'default', + 'unset_default' => '":locale" is already default and cannot be unset as default.', + 'delete_default' => '":locale" is the default and cannot be deleted.', + 'disabled_default' => '":locale" is disabled and cannot be set as default.', + 'name' => 'Name', + 'code' => 'Code', + 'is_default' => 'Default', + 'is_default_help' => 'The default language represents the content before translation.', + 'is_enabled' => 'Enabled', + 'is_enabled_help' => 'Disabled languages will not be available in the front-end.', + 'not_available_help' => 'There are no other languages set up.', + 'hint_locales' => 'Create new languages here for translating front-end content. The default language represents the content before it has been translated.', + 'reorder_title' => 'Reorder Languages', + 'sort_order' => 'Sort Order', + ], + 'messages' => [ + 'title' => 'Translate Messages', + 'description' => 'Update messages', + 'clear_cache_link' => 'Clear Cache', + 'clear_cache_loading' => 'Clearing application cache...', + 'clear_cache_success' => 'Cleared the application cache successfully!', + 'clear_cache_hint' => 'You may need to click Clear cache to see the changes on the front-end.', + 'scan_messages_link' => 'Scan for Messages', + 'scan_messages_begin_scan' => 'Begin Scan', + 'scan_messages_loading' => 'Scanning for new messages...', + 'scan_messages_success' => 'Scanned theme template files successfully!', + 'scan_messages_hint' => 'Clicking Scan for messages will check the active theme files for any new messages to translate.', + 'scan_messages_process' => 'This process will attempt to scan the active theme for messages that can be translated.', + 'scan_messages_process_limitations' => 'Some messages may not be captured and will only appear after the first time they are used.', + 'scan_messages_purge_label' => 'Purge all messages first', + 'scan_messages_purge_help' => 'If checked, this will delete all messages, including their translations, before performing the scan.', + 'scan_messages_purge_confirm' => 'Are you sure you want to delete all messages? This cannot be undone!', + 'scan_messages_purge_deleted_label' => 'Purge missing messages after scan', + 'scan_messages_purge_deleted_help' => 'If checked, after the scan is done, any messages the scanner did not find, including their translations, will be deleted. This cannot be undone!', + 'hint_translate' => 'Here you can translate messages used on the front-end, the fields will save automatically.', + 'hide_translated' => 'Hide translated', + 'export_messages_link' => 'Export Messages', + 'import_messages_link' => 'Import Messages', + 'not_found' => 'Not found', + 'found_help' => 'Whether any errors occurred during scanning.', + 'found_title' => 'Scan errors', + ], +]; diff --git a/plugins/rainlab/translate/lang/es/lang.php b/plugins/rainlab/translate/lang/es/lang.php new file mode 100644 index 0000000..f7a11c6 --- /dev/null +++ b/plugins/rainlab/translate/lang/es/lang.php @@ -0,0 +1,51 @@ + [ + 'name' => 'Multilenguaje', + 'description' => 'Permite sitios web multilingües', + 'manage_locales' => 'Manage locales', + 'manage_messages' => 'Manage messages' + ], + 'locale_picker' => [ + 'component_name' => 'Selección de idioma', + 'component_description' => 'Muestra una lista desplegable para seleccionar un idioma para el usuario', + ], + 'locale' => [ + 'title' => 'Administrar idiomas', + 'update_title' => 'Actualizar idioma', + 'create_title' => 'Crear idioma', + 'select_label' => 'Seleccionar idioma', + 'default_suffix' => 'Defecto', + 'unset_default' => '": locale" ya está predeterminado y no puede ser nulo por defecto.', + 'disabled_default' => '":locale" esta desactivado y no puede ser idioma por defecto', + 'name' => 'Nombre', + 'code' => 'Código', + 'is_default' => 'Por defecto', + 'is_default_help' => 'El idioma por defecto con el que se representa el contenido antes de la traducción.', + 'is_enabled' => 'Habilitado', + 'is_enabled_help' => 'Los idiomas desactivados no estarán disponibles en el front-end', + 'not_available_help' => 'No hay otros idiomas establecidos.', + 'hint_locales' => 'Crear nuevos idiomas aquí para traducir el contenido de front-end. El idioma por defecto representa el contenido antes de que haya sido traducido.', + ], + 'messages' => [ + 'title' => 'Traducir mensajes', + 'description' => 'Editar mensajes', + 'clear_cache_link' => 'Limpiar cache', + 'clear_cache_loading' => 'Borrado de la memoria caché de aplicaciones ...', + 'clear_cache_success' => 'Se ha borrado la memoria cache dela aplicación con éxito', + 'clear_cache_hint' => 'Es posible que tenga que hacer clic en Borrar caché para ver los cambios en el front-end.', + 'scan_messages_link' => 'Escanear mensajes', + 'scan_messages_loading' => 'Escaneando nuevos mensajes...', + 'scan_messages_success' => 'Escaneado de los archivos del tema completado!', + 'scan_messages_hint' => 'Al hacer click en Escanear comprobaremos los mensajes de los archivos de los temas activos para localizar nuevos mensajes a traducir.', + 'hint_translate' => 'Aquí usted puede traducir los mensajes utilizados en el front-end, los campos se guardará automáticamente.', + 'hide_translated' => 'Ocultar traducción', + ], +]; \ No newline at end of file diff --git a/plugins/rainlab/translate/lang/fa/lang.php b/plugins/rainlab/translate/lang/fa/lang.php new file mode 100644 index 0000000..ed608e0 --- /dev/null +++ b/plugins/rainlab/translate/lang/fa/lang.php @@ -0,0 +1,46 @@ + [ + 'name' => 'مترجم', + 'description' => 'فعال سازی وب سایت چند زبانه', + 'tab' => 'ترجمه', + 'manage_locales' => 'مدیریت مناطق', + 'manage_messages' => 'مدیریت پیغام ها' + ], + 'locale_picker' => [ + 'component_name' => 'انتخابگر منطقه', + 'component_description' => 'نمایش انتخابگر کشویی جهت انتخاب زبان.', + ], + 'locale' => [ + 'title' => 'مدیریت زبان ها', + 'update_title' => 'به روز رسانی زبان', + 'create_title' => 'ایجاد زبان', + 'select_label' => 'انتخاب زبان', + 'default_suffix' => 'پیشفرض', + 'unset_default' => '":locale" در حال حاظر پیشفرض می باشد و نمیتوانید آن را خارج کنید.', + 'disabled_default' => '":locale" غیر فعال می باشد و نمیتوانید آن را پیشفرض قرار دهید.', + 'name' => 'نام', + 'code' => 'کد یکتا', + 'is_default' => 'پیشفرض', + 'is_default_help' => 'زبان پیشفرضی که داده ها قبل از ترجمه به آن زبان وارد می شوند', + 'is_enabled' => 'فعال', + 'is_enabled_help' => 'زبان های غیر فعال در دسترس نخواهند بود.', + 'not_available_help' => 'زبان دیگری جهت نصب وجود ندارد.', + 'hint_locales' => 'زبان جدیدی را جهت ترجمه محتوی ایجاد نمایید.', + ], + 'messages' => [ + 'title' => 'ترجمه پیغام ها', + 'description' => 'به روز رسانی پیغام ها', + 'clear_cache_link' => 'پاکسازی حافظه کش', + 'clear_cache_loading' => 'در حال پاکسازی حافظه کش برنامه...', + 'clear_cache_success' => 'عملیات پاکسازی حافظه کش به اتمام رسید.', + 'clear_cache_hint' => 'جهت نمایش تغیرات در سایت نیاز است که شما بر رور پاکسازی حافظه کش کلیک نمایید.', + 'scan_messages_link' => 'جستجوی پیغام ها', + 'scan_messages_loading' => 'جستجوی پیغام های جدید...', + 'scan_messages_success' => 'جستجوی پیغام های جدید به اتمام رسید.', + 'scan_messages_hint' => 'جهت جستجو و نمایش پیغامهای جدیدی که باید ترجمه شوند بر روی جستجوی پیغام های جدید کلیک نمایید.', + 'hint_translate' => 'در این قسمت شما میتوانید پیغام ها را ترجمه نمایید. گزینه ها به صورت خودکار ذخیره میشوند.', + 'hide_translated' => 'مخفی سازی ترجمه شده ها', + ], +]; diff --git a/plugins/rainlab/translate/lang/fr/lang.php b/plugins/rainlab/translate/lang/fr/lang.php new file mode 100644 index 0000000..3d12f86 --- /dev/null +++ b/plugins/rainlab/translate/lang/fr/lang.php @@ -0,0 +1,59 @@ + [ + 'name' => 'Traductions', + 'description' => 'Permet de créer des sites Internet multilingues', + 'tab' => 'Traduction', + 'manage_locales' => 'Manage locales', + 'manage_messages' => 'Manage messages' + ], + 'locale_picker' => [ + 'component_name' => 'Sélection de la langue', + 'component_description' => 'Affiche un menu déroulant pour sélectionner la langue sur le site.', + ], + 'alternate_hreflang' => [ + 'component_name' => 'Éléments hrefLang alternatifs', + 'component_description' => "Injecte les alternatives linguistiques pour la page en tant qu'éléments hreflang" + ], + 'locale' => [ + 'title' => 'Gestion des langues', + 'update_title' => 'Mettre à jour la langue', + 'create_title' => 'Ajouter une langue', + 'select_label' => 'Sélectionner une langue', + 'default_suffix' => 'défaut', + 'unset_default' => '":locale" est déjà la langue par défaut et ne peut être désactivée', + 'delete_default' => '":locale" est la valeur par défaut et ne peut pas être supprimé.', + 'disabled_default' => '":locale" est désactivé et ne peut être utilisé comme paramètre par défaut.', + 'name' => 'Nom', + 'code' => 'Code', + 'is_default' => 'Défaut', + 'is_default_help' => 'La langue par défaut représente le contenu avant la traduction.', + 'is_enabled' => 'Activé', + 'is_enabled_help' => 'Les langues désactivées ne seront plus disponibles sur le site.', + 'not_available_help' => 'Aucune autre langue n\'est définie.', + 'hint_locales' => 'Vous pouvez ajouter de nouvelles langues et traduire les messages du site. La langue par défaut est celle utilisée pour les contenus avant toute traduction.', + 'reorder_title' => 'Réorganiser les langues', + 'sort_order' => 'Ordre de tri', + ], + 'messages' => [ + 'title' => 'Traduction des Messages', + 'description' => 'Mettre à jour Messages', + 'clear_cache_link' => 'Supprimer le cache', + 'clear_cache_loading' => 'Suppression du cache de l\'application...', + 'clear_cache_success' => 'Le cache de l\'application a été supprimé !', + 'clear_cache_hint' => 'Vous devez cliquer sur Supprimer le cache pour voir les modifications sur le site.', + 'scan_messages_link' => 'Rechercher des messages à traduire', + 'scan_messages_begin_scan' => 'Commencer la recherche', + 'scan_messages_loading' => 'Recherche de nouveaux messages...', + 'scan_messages_success' => 'Recherche dans les fichiers du thème effectuée !', + 'scan_messages_hint' => 'Cliquez sur Rechercher des messages à traduire pour parcourir les fichiers du thème actif à la recherche de messages à traduire.', + 'scan_messages_process' => 'Ce processus tentera d\'analyser le thème actif pour les messages qui peuvent être traduits.', + 'scan_messages_process_limitations' => 'Certains messages peuvent ne pas être capturés et n\'apparaîtront qu\'après leur première utilisation.', + 'scan_messages_purge_label' => 'Purger tous les messages en premier', + 'scan_messages_purge_help' => 'Si cette case est cochée, tous les messages seront supprimés avant d\'effectuer l\'analyse.', + 'scan_messages_purge_confirm' => 'Êtes-vous sûr de vouloir supprimer tous les messages? Cela ne peut pas être annulé!', + 'hint_translate' => 'Vous pouvez traduire les messages affichés sur le site, les champs s\'enregistrent automatiquement.', + 'hide_translated' => 'Masquer les traductions', + 'export_messages_link' => 'Exporter les messages', + 'import_messages_link' => 'Importer les messages', + ], +]; diff --git a/plugins/rainlab/translate/lang/gr/lang.php b/plugins/rainlab/translate/lang/gr/lang.php new file mode 100644 index 0000000..b49eac4 --- /dev/null +++ b/plugins/rainlab/translate/lang/gr/lang.php @@ -0,0 +1,64 @@ + [ + 'name' => 'Μετέφρασε', + 'description' => 'Ενεργοποίηση πολύγλωσσων ιστότοπων.', + 'tab' => 'Μετάφραση', + 'manage_locales' => 'Διαχείριση τοπικών ρυθμίσεων', + 'manage_messages' => 'Διαχείριση μηνυμάτων', + ], + 'locale_picker' => [ + 'component_name' => 'Επιλογή τοπικών ρυθμίσεων', + 'component_description' => 'Εμφάνιση αναπτυσσόμενου μενού για επιλογή γλώσσας front-end.', + ], + 'alternate_hreflang' => [ + 'component_name' => 'Εναλλακτικά στοιχεία hrefLang', + 'component_description' => 'Εισαγωγή εναλλακτικών γλωσσών για τη σελίδα ως στοιχεία hreflang' + ], + 'locale' => [ + 'title' => 'Διαχείριση γλώσσας', + 'update_title' => 'Ενημέρωση γλώσσας', + 'create_title' => 'Δημιουργία γλώσσας', + 'select_label' => 'Επιλογή γλώσσας', + 'default_suffix' => 'Προεπιλογή', + 'unset_default' => '":locale" είναι ήδη προεπιλογή και δεν μπορεί να οριστεί ως προεπιλογή.', + 'delete_default' => '":locale" είναι ήδη προεπιλογή και δεν μπορεί να διαγραφεί.', + 'disabled_default' => '":locale" είναι απενεργοποιημένο και δεν μπορεί να οριστεί ως προεπιλογή.', + 'name' => 'Όνομα', + 'code' => 'Κωδικός', + 'is_default' => 'Προεπιλογή', + 'is_default_help' => 'Η προεπιλεγμένη γλώσσα αντιπροσωπεύει το περιεχόμενο πριν από τη μετάφραση.', + 'is_enabled' => 'Ενεργοποίηση', + 'is_enabled_help' => 'Οι απενεργοποιημένες γλώσσες δεν θα είναι διαθέσιμες στο front-end.', + 'not_available_help' => 'Δεν έχουν ρυθμιστεί άλλες γλώσσες.', + 'hint_locales' => 'Δημιουργήστε νέες γλώσσες εδώ για τη μετάφραση περιεχομένου front-end. Η προεπιλεγμένη γλώσσα αντιπροσωπεύει το περιεχόμενο προτού μεταφραστεί.', + 'reorder_title' => 'Αναδιάταξη γλωσσών', + 'sort_order' => 'Σειρά ταξινόμησης', + ], + 'messages' => [ + 'title' => 'Μετάφραση μηνυμάτων', + 'description' => 'Ενημέρωση μηνυμάτων', + 'clear_cache_link' => 'Εκκαθάριση προσωρινής μνήμης', + 'clear_cache_loading' => 'Εκκαθάριση προσωρινής μνήμης εφαρμογής ...', + 'clear_cache_success' => 'Επιτυχής εκκαθάριση της προσωρινής μνήμης της εφαρμογής!', + 'clear_cache_hint' => 'Ίσως χρειαστεί να κάνετε κλικ στην επιλογή Clear cashe για να δείτε τις αλλαγές στο front-end.', + 'scan_messages_link' => 'Σάρωση για μηνύματα', + 'scan_messages_begin_scan' => 'Έναρξη σάρωσης', + 'scan_messages_loading' => 'Σάρωση για νέα μηνύματα ...', + 'scan_messages_success' => 'Επιτυχής σάρωση θεματικών πρότυπων αρχείων!', + 'scan_messages_hint' => 'Κάνοντας κλικ στην επιλογή Scan για messages θα ελεγθούν τα ενεργά αρχεία θεμάτων για τυχόν νέα μηνύματα που χρειάζονται μετάφραση.', + 'scan_messages_process' => 'Αυτή η διαδικασία θα προσπαθήσει να σαρώσει το ενεργό θέμα για μηνύματα που μπορούν να μεταφραστούν.', + 'scan_messages_process_limitations' => 'Ορισμένα μηνύματα ενδέχεται να μην καταγράφονται και θα εμφανίζονται μόνο μετά την πρώτη φορά που χρησιμοποιούνται.', + 'scan_messages_purge_label' => 'Εκκαθάριση πρώτα όλων των μηνυμάτων', + 'scan_messages_purge_help' => 'Επιλέγοντας εδώ θα διαγραφούν όλα τα μηνύματα, συμπεριλαμβανομένων και των μεταφράσεών τους, πριν από τη σάρωση.', + 'scan_messages_purge_confirm' => 'Είστε βέβαιοι ότι θέλετε να διαγράψετε όλα τα μηνύματα; Αυτό δεν μπορεί να αναιρεθεί!', + 'scan_messages_purge_deleted_label' => 'Εκκαθάριση απολεσθέντων μηνυμάτων μετά τη σάρωση', + 'scan_messages_purge_deleted_help' => 'Επιλέγοντας εδώ, αφού ολοκληρωθεί η σάρωση, τυχόν μηνύματα που δεν βρήκε ο σαρωτής, συμπεριλαμβανομένων και των μεταφράσεών τους, θα διαγραφούν. Αυτό δεν μπορεί να αναιρεθεί!', + 'hint_translate' => 'Εδώ μπορείτε να μεταφράσετε μηνύματα που χρησιμοποιούνται στο front-end, τα πεδία θα αποθηκεύονται αυτόματα.', + 'hide_translated' => 'Απόκρυψη μετάφρασης', + 'export_messages_link' => 'Εξαγωγή μηνυμάτων', + 'import_messages_link' => 'Εισαγωγή μηνυμάτων', + 'not_found' => 'Δεν βρέθηκε', + 'found_help' => 'Εάν τυχόν σφάλματα παρουσιάστηκαν κατά τη σάρωση.', + 'found_title' => 'Σάρωση σφαλμάτων', + ], +]; \ No newline at end of file diff --git a/plugins/rainlab/translate/lang/hu/lang.php b/plugins/rainlab/translate/lang/hu/lang.php new file mode 100644 index 0000000..364613f --- /dev/null +++ b/plugins/rainlab/translate/lang/hu/lang.php @@ -0,0 +1,66 @@ + [ + 'name' => 'Fordítás', + 'description' => 'Többnyelvű weboldal létrehozását teszi lehetővé.', + 'tab' => 'Fordítás', + 'manage_locales' => 'Nyelvek kezelése', + 'manage_messages' => 'Szövegek fordítása' + ], + 'locale_picker' => [ + 'component_name' => 'Nyelvi választó', + 'component_description' => 'Legördülő menüt jelenít meg a nyelv kiválasztásához.' + ], + 'alternate_hreflang' => [ + 'component_name' => 'Nyelvi oldalak', + 'component_description' => 'A hreflang HTML meta sorok generálása a keresők számára.' + ], + 'locale' => [ + 'title' => 'Nyelvek', + 'update_title' => 'Nyelv frissítése', + 'create_title' => 'Nyelv hozzáadása', + 'select_label' => 'Nyelv választása', + 'default_suffix' => 'alapértelmezett', + 'unset_default' => 'Már a(z) ":locale" nyelv az alapértelmezett, így nem használható alapértelmezettként.', + 'delete_default' => 'A(z) ":locale" nyelv az alapértelmezett, így nem törölhető.', + 'disabled_default' => 'A(z) ":locale" nyelv letiltott, így nem állítható be alapértelmezettként.', + 'name' => 'Név', + 'code' => 'Kód', + 'is_default' => 'Alapértelmezett', + 'is_default_help' => 'Az alapértelmezett nyelv a fordítás előtti tartalmat képviseli.', + 'is_enabled' => 'Engedélyezve', + 'is_enabled_help' => 'A letiltott nyelvek nem lesznek elérhetőek a látogatói oldalon.', + 'not_available_help' => 'Nincsenek más beállított nyelvek.', + 'hint_locales' => 'Itt hozhat létre új nyelveket a látogatói oldal tartalmának lefordításához. Az alapértelmezett nyelv képviseli a fordítás előtti tartalmat.', + 'reorder_title' => 'Rendezés', + 'sort_order' => 'Sorrend' + ], + 'messages' => [ + 'title' => 'Szövegek', + 'description' => 'Nyelvi változatok menedzselése.', + 'clear_cache_link' => 'Gyorsítótár kiürítése', + 'clear_cache_loading' => 'A weboldal gyorsítótár kiürítése...', + 'clear_cache_success' => 'Sikerült a weboldal gyorsítótár kiürítése!', + 'clear_cache_hint' => 'Kattintson a Gyorsítótár kiürítése gombra, hogy biztosan láthatóvá váljanak a beírt módosítások a látogatói oldalon is.', + 'scan_messages_link' => 'Szövegek keresése', + 'scan_messages_begin_scan' => 'Keresés indítása', + 'scan_messages_loading' => 'Új szövegek keresése...', + 'scan_messages_success' => 'Sikerült a szövegek beolvasása!', + 'scan_messages_hint' => 'A Szövegek keresése gombra kattintva pedig beolvashatja a lefordítandó szövegeket.', + 'scan_messages_process' => 'A folyamat megkisérli beolvasni az aktív témában lévő lefordítandó szövegeket.', + 'scan_messages_process_limitations' => 'Néhány szöveg nem biztos, hogy azonnal meg fog jelenni a listában.', + 'scan_messages_purge_label' => 'Szövegek törlése a művelet előtt', + 'scan_messages_purge_help' => 'Amennyiben bejelöli, úgy minden szöveg törlésre kerül a beolvasást megelőzően.', + 'scan_messages_purge_confirm' => 'Biztos, hogy töröljük az összes szöveget?', + 'scan_messages_purge_deleted_label' => 'Törölje a hiányzó üzeneteket a vizsgálat után', + 'scan_messages_purge_deleted_help' => 'Ha be van jelölve, akkor a keresés befejezése után minden olyan üzenet törlődik, amelyet a keresés nem talált. A művelet nem visszavonható!', + 'hint_translate' => 'Itt fordíthatja le a látogatók által elérhető oldalon megjelenő szövegeket. A beírt változtatások automatikusan mentésre kerülnek.', + 'hide_translated' => 'Lefordítottak elrejtése', + 'export_messages_link' => 'Szövegek exportálása', + 'import_messages_link' => 'Szövegek importálása', + 'not_found' => 'Nem található', + 'found_help' => 'Történt-e hiba a keresés során.', + 'found_title' => 'Hibák', + ] +]; diff --git a/plugins/rainlab/translate/lang/it/lang.php b/plugins/rainlab/translate/lang/it/lang.php new file mode 100644 index 0000000..d1213b4 --- /dev/null +++ b/plugins/rainlab/translate/lang/it/lang.php @@ -0,0 +1,53 @@ + [ + 'name' => 'Traduci', + 'description' => 'Abilita siti multi-lingua.', + 'tab' => 'Traduzioni', + 'manage_locales' => 'Gestisci lingue', + 'manage_messages' => 'Gestisci messaggi', + ], + 'locale_picker' => [ + 'component_name' => 'Selezione lingua', + 'component_description' => 'Mostra un elenco a discesa per selezionare una delle lingue del sito web.', + ], + 'locale' => [ + 'title' => 'Gestisci lingue', + 'update_title' => 'Aggiorna lingua', + 'create_title' => 'Crea lingua', + 'select_label' => 'Scegli lingua', + 'default_suffix' => 'default', + 'unset_default' => '":locale" è già impostato come default e non si può modificare.', + 'delete_default' => '":locale" è la lingua di default e non può essere cancellata.', + 'disabled_default' => '":locale" è disabilitata e non può essere impostata come default.', + 'name' => 'Nome', + 'code' => 'Codice', + 'is_default' => 'Default', + 'is_default_help' => 'La lingua di default rappresenta il contenuto prima che sia tradotto.', + 'is_enabled' => 'Abilitata', + 'is_enabled_help' => 'Le lingue disabilitate non saranno visualizzate nel sito web.', + 'not_available_help' => 'Non ci sono altre lingue da impostare.', + 'hint_locales' => 'Crea qui le nuove lingue per tradurre i contenuti del sito web. La lingua di default rappresenta il contenuto prima che sia tradotto', + 'reorder_title' => 'Riordina lingue', + 'sort_order' => 'Criterio di ordinamento', + ], + 'messages' => [ + 'title' => 'Traduci messaggi', + 'description' => 'Aggiorna messaggi', + 'clear_cache_link' => 'Pulisci cache', + 'clear_cache_loading' => 'Pulizia della cache dell\'applicazione in corso...', + 'clear_cache_success' => 'La cache è stata pulita con successo!', + 'clear_cache_hint' => 'Potrebbe essere necessario cliccare il bottobe Pulisci cache per vedere i cambiamenti nel sito web.', + 'scan_messages_link' => 'Scansiona per nuovi messaggi', + 'scan_messages_begin_scan' => 'Inizio scansione', + 'scan_messages_loading' => 'Scansione in corso per nuovi messaggi...', + 'scan_messages_success' => 'File del template scansionati con successo!', + 'scan_messages_hint' => 'Cliccando Scansiona per nuovi messaggi avvierai la ricerca di nuovi messaggi da tradurre nel template attivo.', + 'scan_messages_process' => 'Questo processo cercherà di scansionare il tema attivo per trovare messaggi che possono essere tradotti.', + 'scan_messages_process_limitations' => 'Qualche messaggio potrebbe non essere individuato e apparirà solo dopo la prima volta che verrà usato.', + 'scan_messages_purge_label' => 'Rimuovi prima tutti i messaggi', + 'scan_messages_purge_help' => 'Se selezionato, prima di eseguire la scansione verranno eliminati tutti i messaggi già presenti.', + 'scan_messages_purge_confirm' => 'Sei sicuro di voler cancellare tutti i messaggi? Questa operazione non può essere annullata!', + 'hint_translate' => 'Qui puoi tradurre i messaggi usati nel sito web, i campi verranno salvati automaticamente.', + 'hide_translated' => 'Nascondi i messaggi tradotti', + ], +]; diff --git a/plugins/rainlab/translate/lang/nl/lang.php b/plugins/rainlab/translate/lang/nl/lang.php new file mode 100644 index 0000000..26823d8 --- /dev/null +++ b/plugins/rainlab/translate/lang/nl/lang.php @@ -0,0 +1,57 @@ + [ + 'name' => 'Vertaal', + 'description' => 'Stelt meerdere talen in voor een website.', + 'tab' => 'Vertalingen', + 'manage_locales' => 'Beheer talen', + 'manage_messages' => 'Beheer vertaalde berichten' + ], + 'locale_picker' => [ + 'component_name' => 'Taalkeuze menu', + 'component_description' => 'Geeft een taal keuzemenu weer om de taal te wijzigen voor de website.', + ], + 'alternate_hreflang' => [ + 'component_name' => 'Alternatieve hrefLang elementen', + 'component_description' => 'Toont hreflang elementen voor de alt. talen' + ], + 'locale' => [ + 'title' => 'Beheer talen', + 'update_title' => 'Wijzig taal', + 'create_title' => 'Taal toevoegen', + 'select_label' => 'Selecteer taal', + 'default_suffix' => 'standaard', + 'unset_default' => '":locale" is de standaard taal en kan niet worden uitgeschakeld', + 'delete_default' => '":locale" is de standaard taal en kan niet worden verwijderd.', + 'disabled_default' => '":locale" is uitgeschakeld en kan niet als standaard taal worden ingesteld.', + 'name' => 'Naam', + 'code' => 'Code', + 'is_default' => 'Standaard', + 'is_default_help' => 'De standaard taal voor de inhoud.', + 'is_enabled' => 'Geactiveerd', + 'is_enabled_help' => 'Uitgeschakelde talen zijn niet beschikbaar op de website.', + 'not_available_help' => 'Er zijn geen andere talen beschikbaar.', + 'hint_locales' => 'Voeg hier nieuwe talen toe voor het vertalen van de website inhoud. De standaard taal geeft de inhoud weer voordat het is vertaald.', + 'reorder_title' => 'Talen rangschikken', + 'sort_order' => 'Volgorde', + ], + 'messages' => [ + 'title' => 'Vertaal berichten', + 'description' => 'Wijzig berichten', + 'clear_cache_link' => 'Leeg cache', + 'clear_cache_loading' => 'Applicatie cache legen...', + 'clear_cache_success' => 'De applicatie cache is succesvol geleegd.', + 'clear_cache_hint' => 'Het kan zijn dat het nodig is om op cache legen" te klikken om wijzigingen op de website te zien.', + 'scan_messages_link' => 'Zoek naar nieuwe berichten', + 'scan_messages_begin_scan' => 'Begin Scan', + 'scan_messages_loading' => 'Zoeken naar nieuwe berichten...', + 'scan_messages_success' => 'De thema bestanden zijn succesvol gescand!', + 'scan_messages_hint' => 'Klikken op Zoeken naar nieuwe berichten controleert de bestanden van het huidige thema op nieuwe berichten om te vertalen.', + 'scan_messages_process' => 'Dit proces zal proberen het huidige thema te scannen voor berichten om te vertalen', + 'scan_messages_process_limitations' => 'Sommige berichten zullen niet worden herkend en zullen pas verschijnen nadat ze voor de eerste keer zijn gebruikt', + 'scan_messages_purge_label' => 'Verwijder eerst alle berichten', + 'scan_messages_purge_help' => 'Als dit is aangevinkt zullen alle berichten worden verwijderd voordat de scan wordt uitgevoerd.', + 'scan_messages_purge_confirm' => 'Weet je zeker dat je alle berichten wilt verwijderen? Dit kan niet ongedaan gemaakt worden', + 'hint_translate' => 'Hier kan je berichten vertalen die worden gebruikt op de website. De velden worden automatisch opgeslagen.', + 'hide_translated' => 'Verberg vertaalde berichten', + ], +]; diff --git a/plugins/rainlab/translate/lang/pl/lang.php b/plugins/rainlab/translate/lang/pl/lang.php new file mode 100644 index 0000000..1b6e4af --- /dev/null +++ b/plugins/rainlab/translate/lang/pl/lang.php @@ -0,0 +1,66 @@ + [ + 'name' => 'Tłumaczenia', + 'description' => 'Umożliwia tworzenie stron wielojęzycznych.', + 'tab' => 'Tłumaczenie', + 'manage_locales' => 'Zarządzaj językami', + 'manage_messages' => 'Zarządzaj treścią' + ], + 'locale_picker' => [ + 'component_name' => 'Lista języków', + 'component_description' => 'Wyświetla menu wyboru języków strony.', + ], + 'alternate_hreflang' => [ + 'component_name' => 'Alternatywne ustawienia hreflang', + 'component_description' => 'Ustawia alternatywne języki dla strony jako parametry hreflang' + ], + 'locale' => [ + 'title' => 'Zarządzaj językami', + 'update_title' => 'Edytuj język', + 'create_title' => 'Stwórz język', + 'select_label' => 'Wybierz język', + 'default_suffix' => 'domyślny', + 'unset_default' => 'Język ":locale" jest już domyślny i nie można go zmienić.', + 'delete_default' => 'Język ":locale" jest już domyślny i nie może zostać usunięty.', + 'disabled_default' => 'Język ":locale" jest wyłączony i nie można go ustawić jako domyślny.', + 'name' => 'Nazwa', + 'code' => 'Kod', + 'is_default' => 'Domyślny', + 'is_default_help' => 'Domyślny język to język treści strony przed tłumaczeniem.', + 'is_enabled' => 'Włączony', + 'is_enabled_help' => 'Wyłączone języki nie będą dostępne na stronie.', + 'not_available_help' => 'Nie skonfigurowano innych języków.', + 'hint_locales' => 'Stwórz nowe języki, na które chcesz tłumaczyć treść strony. Domyślny język to język treści strony przed tłumaczeniem. ', + 'reorder_title' => 'Zmień kolejność języków', + 'sort_order' => 'Sortowanie', + ], + 'messages' => [ + 'title' => 'Tłumacz Treść', + 'description' => 'Tłumaczenie treści strony', + 'clear_cache_link' => 'Wyczyść Cache', + 'clear_cache_loading' => 'Czyszczenie cache...', + 'clear_cache_success' => 'Pomyślnie wyczyszczono cache aplikacji!', + 'clear_cache_hint' => 'Jeśli nie widzisz zmian na stronie, kliknij przycisk Wyczyść cache.', + 'scan_messages_link' => 'Skanuj treść', + 'scan_messages_begin_scan' => 'Rozpocznij skanowanie', + 'scan_messages_loading' => 'Szukanie nowych pozycji...', + 'scan_messages_success' => 'Skanowanie plików motywu zakończyło się powodzeniem!', + 'scan_messages_hint' => 'Kliknięcie przycisku Skanuj treść rozpocznie skanowanie w poszukiwaniu nowych pozycji do przetłumaczenia.', + 'scan_messages_process' => 'Ten proces podejmie próbę przeskanowania aktywnego motywu w poszukiwaniu wiadomości, które można przetłumaczyć.', + 'scan_messages_process_limitations' => 'Niektóre wiadomości mogą nie zostać przechwycone i pojawią się dopiero po pierwszym użyciu.', + 'scan_messages_purge_label' => 'Najpierw usuń wszystkie wiadomości', + 'scan_messages_purge_help' => 'Zaznaczenie tej opcji spowoduje usunięcie wszystkich wiadomości, w tym ich tłumaczeń, przed wykonaniem skanowania.', + 'scan_messages_purge_confirm' => 'Czy jesteś pewny że chcesz usunąć wszystkie wiadomości? Po usunięciu nie będzie można ich przywrócić', + 'scan_messages_purge_deleted_label' => 'Usuń utracone wiadomości po zeskanowaniu', + 'scan_messages_purge_deleted_help' => 'Jeśli ta opcja jest zaznaczona, po zakończeniu skanowania wszystkie wiadomości, których skaner nie znalazł (w tym ich tłumaczenia) zostaną usunięte. Po zaznaczeniu tej opcji nie będzie możliwości przywrócenia zmian!', + 'hint_translate' => 'Możesz tu przetłumaczyć treść strony. Pola zapisują się automatycznie.', + 'hide_translated' => 'Ukryj przetłumaczone', + 'export_messages_link' => 'Wyeksportuj treść', + 'import_messages_link' => 'Zaimportuj treść', + 'not_found' => 'Nie znaleziono', + 'found_help' => 'Wystąpiły błędy podczas skanowania', + 'found_title' => 'Błąd skanowania', + ], +]; diff --git a/plugins/rainlab/translate/lang/pt-br/lang.php b/plugins/rainlab/translate/lang/pt-br/lang.php new file mode 100644 index 0000000..e1995f9 --- /dev/null +++ b/plugins/rainlab/translate/lang/pt-br/lang.php @@ -0,0 +1,53 @@ + [ + 'name' => 'Traduções', + 'description' => 'Permite sites com multi-idiomas.', + 'tab' => 'Tradução', + 'manage_locales' => 'Gerenciar locais', + 'manage_messages' => 'Gerenciar mensagens' + ], + 'locale_picker' => [ + 'component_name' => 'Seleção de idiomas', + 'component_description' => 'Exibe um campo de seleção de idiomas.', + ], + 'locale' => [ + 'title' => 'Gerenciar idiomas', + 'update_title' => 'Atualizar idioma', + 'create_title' => 'Criar idioma', + 'select_label' => 'Selecionar idioma', + 'default_suffix' => 'padrão', + 'unset_default' => '":locale" é o idioma padrão e não pode ser desativado.', + 'delete_default' => '":locale" é o padrão e não pode ser excluído.', + 'disabled_default' => '":locale" está desativado e não pode ser definido como padrão.', + 'name' => 'Nome', + 'code' => 'Código', + 'is_default' => 'Padrão', + 'is_default_help' => 'O idioma padrão apresenta o conteúdo antes das traduções.', + 'is_enabled' => 'Ativo', + 'is_enabled_help' => 'Idiomas desativados não estarão disponíveis na página.', + 'not_available_help' => 'Não há outros idiomas configurados.', + 'hint_locales' => 'Crie novos idiomas para traduzir o conteúdo da página. O idioma padrão apresenta o conteúdo antes das traduções.', + ], + 'messages' => [ + 'title' => 'Traduzir mensagens', + 'description' => 'Atualizar mensagens', + 'clear_cache_link' => 'Limpar cache', + 'clear_cache_loading' => 'Limpando o cache da aplicação...', + 'clear_cache_success' => 'Cache da aplicação limpo com sucesso!', + 'clear_cache_hint' => 'Talvez você terá que clicar em Limpar cache para visualizar as modificações na página.', + 'scan_messages_link' => 'Buscar por mensagens', + 'scan_messages_begin_scan' => 'Inciar Busca', + 'scan_messages_loading' => 'Buscando por novas mensagens...', + 'scan_messages_success' => 'Busca por novas mensagens nos arquivos concluída com sucesso!', + 'scan_messages_hint' => 'Clicando em Buscar por mensagens o sistema buscará por qualquer mensagem da aplicação que possa ser traduzida.', + 'scan_messages_process' => 'Este processo tentará scanear o tema ativo para mensagens que podem ser traduzidas.', + 'scan_messages_process_limitations' => 'Algumas mensagens podem não ser capturadas e só aparecerão depois da primeira vez que forem usadas.', + 'scan_messages_purge_label' => 'Limpar primeiro todas as mensagens', + 'scan_messages_purge_help' => 'Se selecionado, isso excluirá todas as mensagens antes de executar a verificação.', + 'scan_messages_purge_confirm' => 'Tem certeza de que deseja excluir todas as mensagens? Isto não pode ser desfeito!', + 'hint_translate' => 'Aqui você pode raduzir as mensagens utilizadas na página, os campos são salvos automaticamente.', + 'hide_translated' => 'Ocultar traduzidas', + ], +]; diff --git a/plugins/rainlab/translate/lang/ru/lang.php b/plugins/rainlab/translate/lang/ru/lang.php new file mode 100644 index 0000000..a3b9177 --- /dev/null +++ b/plugins/rainlab/translate/lang/ru/lang.php @@ -0,0 +1,61 @@ + [ + 'name' => 'Translate', + 'description' => 'Настройки мультиязычности сайта.', + 'tab' => 'Перевод', + 'manage_locales' => 'Управление языками', + 'manage_messages' => 'Управление сообщениями' + ], + 'locale_picker' => [ + 'component_name' => 'Выбор языка', + 'component_description' => 'Просмотр списка языков интерфейса.', + ], + 'alternate_hreflang' => [ + 'component_name' => 'Альтернативные элементы hrefLang', + 'component_description' => 'Внедряет языковые альтернативы для страницы в качестве элементов hreflang' + ], + 'locale' => [ + 'title' => 'Управление языками', + 'update_title' => 'Обновить язык', + 'create_title' => 'Создать язык', + 'select_label' => 'Выбрать язык', + 'default_suffix' => 'По умолчанию', + 'unset_default' => '":locale" уже установлен как язык по умолчанию.', + 'delete_default' => '":locale" используется по умолчанию и не может быть удален.', + 'disabled_default' => '":locale" отключен и не может быть использован как язык по умолчанию.', + 'name' => 'Название', + 'code' => 'Код', + 'is_default' => 'По умолчанию', + 'is_default_help' => 'Использовать этот язык, как язык по умолчанию.', + 'is_enabled' => 'Включено', + 'is_enabled_help' => 'Сделать язык доступным в интерфейсе сайта.', + 'not_available_help' => 'Нет настроек других языков.', + 'hint_locales' => 'Создание новых переводов содержимого интерфейса сайта.', + 'reorder_title' => 'Изменить порядок языков', + 'sort_order' => 'Порядок сортировки', + ], + 'messages' => [ + 'title' => 'Перевод сообщений', + 'description' => 'Перевод статических сообщений в шаблоне', + 'clear_cache_link' => 'Очистить кэш', + 'clear_cache_loading' => 'Очистка кэша приложения...', + 'clear_cache_success' => 'Очистка кэша завершена успешно!', + 'clear_cache_hint' => 'Используйте кнопку Очистить кэш, чтобы увидеть изменения в интерфейсе сайта.', + 'scan_messages_link' => 'Сканирование сообщений', + 'scan_messages_begin_scan' => 'Начать сканирование', + 'scan_messages_loading' => 'Сканирование наличия новых сообщений...', + 'scan_messages_success' => 'Сканирование файлов шаблона темы успешно завершено!', + 'scan_messages_hint' => 'Используйте кнопку Сканирование сообщений для поиска новых ключей перевода активной темы интерфейса сайта.', + 'scan_messages_process' => 'Этот процесс попытается отсканировать активную тему для сообщений, которые можно перевести.', + 'scan_messages_process_limitations' => 'Некоторые сообщения могут не быть отсканированы и появлятся только после первого использования.', + 'scan_messages_purge_label' => 'Сначала очистить все сообщения', + 'scan_messages_purge_help' => 'Если этот флажок установлен, это приведет к удалению всех сообщений перед выполнением сканирования.', + 'scan_messages_purge_confirm' => 'Вы действительно хотите удалить все сообщения? Операция не может быть отменена!', + 'hint_translate' => 'Здесь вы можете переводить сообщения, которые используются в интерфейсе сайта.', + 'hide_translated' => 'Скрыть перевод', + 'export_messages_link' => 'Экспорт сообщений', + 'import_messages_link' => 'Импорт сообщений', + ], +]; diff --git a/plugins/rainlab/translate/lang/sk/lang.php b/plugins/rainlab/translate/lang/sk/lang.php new file mode 100644 index 0000000..82b4827 --- /dev/null +++ b/plugins/rainlab/translate/lang/sk/lang.php @@ -0,0 +1,59 @@ + [ + 'name' => 'Preklady', + 'description' => 'Umožňuje viacjazyčné webové stránky.', + 'tab' => 'Preklad', + 'manage_locales' => 'Spravovať jazyky', + 'manage_messages' => 'Spravovať správy', + ], + 'locale_picker' => [ + 'component_name' => 'Výber jazyka', + 'component_description' => 'Zobrazí rozbaľovaciu ponuku na výber jazyka front-endu.', + ], + 'alternate_hreflang' => [ + 'component_name' => 'Alternatívne prvky hrefLang', + 'component_description' => 'Vloží jazykové alternatívy pre stránku ako prvky hreflang' + ], + 'locale' => [ + 'title' => 'Spravovať jazyky', + 'update_title' => 'Aktualizovať jazyk', + 'create_title' => 'Vytvoriť jazyk', + 'select_label' => 'Zvoliť jazyk', + 'default_suffix' => 'predvolený', + 'unset_default' => '":locale" je už predvolený a nemožno ho nastaviť ako predvolený.', + 'delete_default' => '":locale" je predvolený a nemôže byť zmazaný.', + 'disabled_default' => '":locale" je neaktívny a nemôýe byť nastavený ako predvolený.', + 'name' => 'Meno', + 'code' => 'Kód', + 'is_default' => 'Predvolený', + 'is_default_help' => 'Predvolený jazyk predstavuje obsah pred prekladom.', + 'is_enabled' => 'Aktívny', + 'is_enabled_help' => 'Neaktívne jazyky nebudú dostupné na front-ende.', + 'not_available_help' => 'Nie sú nastavené žiadne ďalšie jazyky.', + 'hint_locales' => 'Vytvárajte tu nové jazyky pre preklad obsahu front-endu. Predvolený jazyk predstavuje obsah pred tým, než bol preložený.', + 'reorder_title' => 'Zmeniť poradie jazykov', + 'sort_order' => 'Smer zoradenia', + ], + 'messages' => [ + 'title' => 'Preložiť správy', + 'description' => 'Aktualizovať správy', + 'clear_cache_link' => 'Vymazať vyrovnávaciu pamäť', + 'clear_cache_loading' => 'Čistenie vyrovnávacej pamäte aplikácie...', + 'clear_cache_success' => 'Vyrovnávacia pamäť aplikácie vyčistená!', + 'clear_cache_hint' => 'Možno budete musieť kliknúť Vymazať vyrovnávaciu pamäť aby sa zmeny prejavili na front-ende.', + 'scan_messages_link' => 'Vyhľadávanie správ', + 'scan_messages_begin_scan' => 'Začať vyhľadávanie', + 'scan_messages_loading' => 'Vyhľadávanie nových správ...', + 'scan_messages_success' => 'Vyhľadávanie nových správ úspešne ukončené!', + 'scan_messages_hint' => 'Kliknutie na Vyhľadávanie správ skontroluje súbory aktívnej témy a nájde nové správy na preklad.', + 'scan_messages_process' => 'Tento proces vyhľadí v aktívnej téme správy, ktoré môžu byť preložené.', + 'scan_messages_process_limitations' => 'Niektoré správy nemusia byť zachytené a objavia sa po ich prvom použití.', + 'scan_messages_purge_label' => 'Najprv vyčistiť všetky správy', + 'scan_messages_purge_help' => 'Ak zaškrtnuté zmaže všetky správy pred vykonaním vyhľadávania.', + 'scan_messages_purge_confirm' => 'Naozaj chcete odstrániť všetky správy? Toto sa nedá vrátiť späť!', + 'hint_translate' => 'Tu môžete preložiť správy používané na front-ende, polia sa ukladajú automaticky.', + 'hide_translated' => 'Skryť preložené', + 'export_messages_link' => 'Exportovať správy', + 'import_messages_link' => 'Importovať správy', + ], +]; diff --git a/plugins/rainlab/translate/lang/sl/lang.php b/plugins/rainlab/translate/lang/sl/lang.php new file mode 100644 index 0000000..db99d8e --- /dev/null +++ b/plugins/rainlab/translate/lang/sl/lang.php @@ -0,0 +1,59 @@ + [ + 'name' => 'Večjezičnost', + 'description' => 'Podpora za večjezične spletne strani.', + 'tab' => 'Večjezičnost', + 'manage_locales' => 'Upravljanje jezikov', + 'manage_messages' => 'Upravljanje besedil', + ], + 'locale_picker' => [ + 'component_name' => 'Izbirnik jezikov', + 'component_description' => 'Prikaže spustni seznam jezikov na spletni strani.', + ], + 'alternate_hreflang' => [ + 'component_name' => 'Jezikovne alternative', + 'component_description' => 'Vstavi jezikovne alternative za stran kot elemente "hreflang".', + ], + 'locale' => [ + 'title' => 'Upravljanje jezikov', + 'update_title' => 'Posodobitev jezika', + 'create_title' => 'Ustvari nov jezik', + 'select_label' => 'Izberi jezik', + 'default_suffix' => 'privzeto', + 'unset_default' => '":locale" je že privzeti jezik in ga ni možno nastaviti za ne-privzetega.', + 'delete_default' => '":locale" je privzeti jezik in se ga ne da izbrisati.', + 'disabled_default' => '":locale" je onemogočen jezik in ga ni možno nastaviti za privzetega.', + 'name' => 'Ime', + 'code' => 'Koda', + 'is_default' => 'Privzeto', + 'is_default_help' => 'Privzeti jezik predstavlja vsebino pred prevodom.', + 'is_enabled' => 'Omogočeno', + 'is_enabled_help' => 'Onemogočeni jeziki na spletni strani ne bodo na voljo.', + 'not_available_help' => 'Ni nastavljenih drugih jezikov.', + 'hint_locales' => 'Tukaj lahko ustvarite nove jezike za prevajanje vsebine. Privzeti jezik predstavlja vsebino, preden je prevedena.', + 'reorder_title' => 'Spremeni vrstni red jezikov', + 'sort_order' => 'Vrstni red', + ], + 'messages' => [ + 'title' => 'Prevajanje besedil', + 'description' => 'Urejanje prevodov besedil.', + 'clear_cache_link' => 'Počisti predpomnilnik', + 'clear_cache_loading' => 'Praznenje predpomnilnika aplikacije...', + 'clear_cache_success' => 'Predpomnilnik aplikacije je uspešno izpraznjen!', + 'clear_cache_hint' => 'Morda boste morali klikniti Počisti predpomnilnik za ogled sprememb na spletni strani.', + 'scan_messages_link' => 'Skeniraj besedila', + 'scan_messages_begin_scan' => 'Začni skeniranje', + 'scan_messages_loading' => 'Skeniram za nova besedila...', + 'scan_messages_success' => 'Datoteke aktivne teme so bile uspešno skenirane!', + 'scan_messages_hint' => 'Klik na Skeniraj besedila bo preveril datoteke aktivne teme, če vsebujejo morebitna besedila za prevode.', + 'scan_messages_process' => 'Ta postopek bo poskusil skenirati aktivno temo za besedila, ki jih je mogoče prevesti.', + 'scan_messages_process_limitations' => 'Nekatera besedila morda ne bodo prikazana in se bodo prikazala šele po prvi uporabi.', + 'scan_messages_purge_label' => 'Najprej izbriši vsa besedila', + 'scan_messages_purge_help' => 'Če je označeno, bodo pred skeniranjem izbrisana vsa besedila, vključno z njihovimi prevodi!', + 'scan_messages_purge_confirm' => 'Ali ste prepričani, da želite izbrisati vsa besedila? Tega ukaza ni mogoče razveljaviti!', + 'hint_translate' => 'Tukaj lahko prevedete besedila, uporabljena na spletni strani. Vrednosti v poljih se shranijo samodejno.', + 'hide_translated' => 'Skrij prevedena besedila', + 'export_messages_link' => 'Izvozi besedila', + 'import_messages_link' => 'Uvozi besedila', + ], +]; diff --git a/plugins/rainlab/translate/lang/tr/lang.php b/plugins/rainlab/translate/lang/tr/lang.php new file mode 100644 index 0000000..5a20147 --- /dev/null +++ b/plugins/rainlab/translate/lang/tr/lang.php @@ -0,0 +1,64 @@ + [ + 'name' => 'Çeviri', + 'description' => 'Çoklu dil destekli websiteleri oluşturmanızı sağlar.', + 'tab' => 'Çeviri', + 'manage_locales' => 'Dilleri yönet', + 'manage_messages' => 'Çevirileri yönet', + ], + 'locale_picker' => [ + 'component_name' => 'Çoklu Dil Seçimi', + 'component_description' => 'Sitenizin dilini değiştirebileceğiniz diller listesini gösterir.', + ], + 'alternate_hreflang' => [ + 'component_name' => 'Alternatif hrefLang elemanları', + 'component_description' => 'Sayfa için dil alternatiflerini hreflang elemanları olarak ekler.', + ], + 'locale' => [ + 'title' => 'Dilleri yönet', + 'update_title' => 'Dili güncelle', + 'create_title' => 'Dil ekle', + 'select_label' => 'Dil seç', + 'default_suffix' => 'ön tanımlı', + 'unset_default' => '":locale" zaten ön tanımlı olarak seçili.', + 'delete_default' => '":locale" ön tanımlı olarak seçilmiş olduğu için silinemez.', + 'disabled_default' => '":locale" pasifleştirilmiş olduğu için ön tanımlı yapılamaz.', + 'name' => 'Dil İsmi', + 'code' => 'Dil Kodu', + 'is_default' => 'Ön tanımlı', + 'is_default_help' => 'Ön tanımlı seçilen dil, sitenin orjinal içeriğini belirtmektedir.', + 'is_enabled' => 'Aktif', + 'is_enabled_help' => 'Pasifleştirilen diller site ön yüzünde görüntülenmez.', + 'not_available_help' => 'Başka dil ayarı yok.', + 'hint_locales' => 'Ön yüz çevirilerini yapmak için buradan dil ekleyebilirsiniz. Ön tanımlı seçilen dil, sitenin orjinal içeriğini belirtmektedir.', + 'reorder_title' => 'Dilleri sırala', + 'sort_order' => 'Sıralama', + ], + 'messages' => [ + 'title' => 'Metinleri çevir', + 'description' => 'Metinler ve çevirileri', + 'clear_cache_link' => 'Önbelleği temizle', + 'clear_cache_loading' => 'Önbellek temizleniyor..', + 'clear_cache_success' => 'Önbellek temizlendi!', + 'clear_cache_hint' => 'Yaptığınız çeviriler site ön yüzünde görünmüyorsa Önbelleği temizle butonuna tıklayabilirsiniz.', + 'scan_messages_link' => 'Yeni metinleri tara', + 'scan_messages_begin_scan' => 'Taramaya başla', + 'scan_messages_loading' => 'Yeni metinler taranıyor...', + 'scan_messages_success' => 'Tema dosyaları tarandı!', + 'scan_messages_hint' => 'Yeni metinleri tara butonuna tıklayarak tema içerisine yeni eklediğiniz metinleri de çevirebilirsiniz.', + 'scan_messages_process' => 'Bu işlem tema dosyaları içerisindeki çevrilecek metinleri tarar.', + 'scan_messages_process_limitations' => 'Bazı metinler yakalanamayabilir veya ilk kez kullanımdan sonra görüntülenebilir.', + 'scan_messages_purge_label' => 'Önce tüm eski çevirileri sil', + 'scan_messages_purge_help' => 'Eğer seçerseniz şimdiye kadar yaptığınız tüm çeviriler silinecek, tekrar çevirmeniz gerekecektir.', + 'scan_messages_purge_confirm' => 'Tüm çevirileri silmek istediğinize emin misiniz? Bu işlem geri alınamaz!', + 'scan_messages_purge_deleted_label' => 'Tarama tamamlandıktan sonra eksik çevirileri temizle', + 'scan_messages_purge_deleted_help' => 'İşaretlerseniz, tarama tamamlandıktan sonra tarayıcının bulamadığı tüm metinler (diğer dil çevirileri de dahil olmak üzere) silinecektir. Bu işlem geri alınamaz!', + 'hint_translate' => 'Bu kısımda site ön yüzünde görüntülenecek çeviri metinlerini bulabilirsiniz, çeviri yaptıktan sonra bir işlem yapmanıza gerek yoktur, hepsi otomatik kaydedilecek.', + 'hide_translated' => 'Çevrilen metinleri gizle', + 'export_messages_link' => 'Metinleri Dışa Aktar', + 'import_messages_link' => 'Metinleri İçe Aktar', + 'not_found' => 'Bulunamadı', + 'found_help' => 'Tarama sırasında herhangi bir hata oluşup oluşmadığı.', + 'found_title' => 'Tarama hataları', + ], +]; diff --git a/plugins/rainlab/translate/lang/zh-cn/lang.php b/plugins/rainlab/translate/lang/zh-cn/lang.php new file mode 100644 index 0000000..9ed1aa0 --- /dev/null +++ b/plugins/rainlab/translate/lang/zh-cn/lang.php @@ -0,0 +1,64 @@ + [ + 'name' => '翻译', + 'description' => '启用多语言网站。', + 'tab' => '翻译', + 'manage_locales' => '管理语言环境', + 'manage_messages' => '管理消息', + ], + 'locale_picker' => [ + 'component_name' => '语言环境选择器', + 'component_description' => '显示用于选择前端语言的下拉列表。', + ], + 'alternate_hreflang' => [ + 'component_name' => '备用 hrefLang 元素', + 'component_description' => '将页面的语言替代项作为 hreflang 元素注入' + ], + 'locale' => [ + 'title' => '管理语言', + 'update_title' => '更新语言', + 'create_title' => '创建语言', + 'select_label' => '选择语言', + 'default_suffix' => '默认', + 'unset_default' => '":locale" 已经是默认值,不能取消设置为默认值。', + 'delete_default' => '":locale" 是默认值,不能删除。', + 'disabled_default' => '":locale" 已禁用且不能设置为默认值。', + 'name' => '名称', + 'code' => '代码', + 'is_default' => '默认', + 'is_default_help' => '默认语言代表翻译前的内容。', + 'is_enabled' => '启用', + 'is_enabled_help' => '禁用的语言在前端将不可用。', + 'not_available_help' => '没有设置其他语言。', + 'hint_locales' => '在此处创建用于翻译前端内容的新语言。默认语言代表翻译之前的内容。', + 'reorder_title' => '重新排序语言', + 'sort_order' => '排序顺序', + ], + 'messages' => [ + 'title' => '翻译消息', + 'description' => '更新消息', + 'clear_cache_link' => '清除缓存', + 'clear_cache_loading' => '清除应用程序缓存...', + 'clear_cache_success' => '清除应用缓存成功!', + 'clear_cache_hint' => '您可能需要点击清除缓存才能查看前端的更改。', + 'scan_messages_link' => '扫描消息', + 'scan_messages_begin_scan' => '开始扫描', + 'scan_messages_loading' => '正在扫描新消息...', + 'scan_messages_success' => '已成功扫描主题模板文件!', + 'scan_messages_hint' => '点击扫描消息将检查活动主题文件中是否有任何要翻译的新消息。', + 'scan_messages_process' => '此进程将尝试扫描活动主题以查找可翻译的消息。', + 'scan_messages_process_limitations' => '有些消息可能无法捕获,只有在第一次使用后才会出现。', + 'scan_messages_purge_label' => '先清除所有消息', + 'scan_messages_purge_help' => '如果选中,这将在执行扫描之前删除所有消息,包括它们的翻译。', + 'scan_messages_purge_confirm' => '您确定要删除所有消息吗?这不能被撤消!', + 'scan_messages_purge_deleted_label' => '扫描后清除丢失的消息', + 'scan_messages_purge_deleted_help' => '如果选中,在扫描完成后,扫描器未找到的任何消息,包括它们的翻译,都将被删除。这不能被撤消!', + 'hint_translate' => '这里可以翻译前端使用的消息,字段会自动保存。', + 'hide_translated' => '隐藏翻译', + 'export_messages_link' => '导出消息', + 'import_messages_link' => '导入消息', + 'not_found' => '未找到', + 'found_help' => '扫描过程中是否发生任何错误。', + 'found_title' => '扫描错误', + ], +]; diff --git a/plugins/rainlab/translate/models/Attribute.php b/plugins/rainlab/translate/models/Attribute.php new file mode 100644 index 0000000..a6e7a41 --- /dev/null +++ b/plugins/rainlab/translate/models/Attribute.php @@ -0,0 +1,18 @@ + [] + ]; +} diff --git a/plugins/rainlab/translate/models/Locale.php b/plugins/rainlab/translate/models/Locale.php new file mode 100644 index 0000000..938643c --- /dev/null +++ b/plugins/rainlab/translate/models/Locale.php @@ -0,0 +1,218 @@ + 'required', + 'name' => 'required', + ]; + + public $timestamps = false; + + /** + * @var array Object cache of self, by code. + */ + protected static $cacheByCode = []; + + /** + * @var array A cache of enabled locales. + */ + protected static $cacheListEnabled; + + /** + * @var array A cache of available locales. + */ + protected static $cacheListAvailable; + + /** + * @var self Default locale cache. + */ + protected static $defaultLocale; + + public function afterCreate() + { + if ($this->is_default) { + $this->makeDefault(); + } + } + + public function beforeDelete() + { + if ($this->is_default) { + throw new ApplicationException(Lang::get('rainlab.translate::lang.locale.delete_default', ['locale'=>$this->name])); + } + } + + public function beforeUpdate() + { + if ($this->isDirty('is_default')) { + $this->makeDefault(); + + if (!$this->is_default) { + throw new ValidationException(['is_default' => Lang::get('rainlab.translate::lang.locale.unset_default', ['locale'=>$this->name])]); + } + } + } + + /** + * Makes this model the default + * @return void + */ + public function makeDefault() + { + if (!$this->is_enabled) { + throw new ValidationException(['is_enabled' => Lang::get('rainlab.translate::lang.locale.disabled_default', ['locale'=>$this->name])]); + } + + $this->newQuery()->where('id', $this->id)->update(['is_default' => true]); + $this->newQuery()->where('id', '<>', $this->id)->update(['is_default' => false]); + } + + /** + * Returns the default locale defined. + * @return self + */ + public static function getDefault() + { + if (self::$defaultLocale !== null) { + return self::$defaultLocale; + } + + if ($forceDefault = Config::get('rainlab.translate::forceDefaultLocale')) { + $locale = new self; + $locale->name = $locale->code = $forceDefault; + $locale->is_default = $locale->is_enabled = true; + return self::$defaultLocale = $locale; + } + + return self::$defaultLocale = self::where('is_default', true) + ->remember(1440, 'rainlab.translate.defaultLocale') + ->first() + ; + } + + /** + * Locate a locale table by its code, cached. + * @param string $code + * @return Model + */ + public static function findByCode($code = null) + { + if (!$code) { + return null; + } + + if (isset(self::$cacheByCode[$code])) { + return self::$cacheByCode[$code]; + } + + return self::$cacheByCode[$code] = self::whereCode($code)->first(); + } + + /** + * Scope for checking if model is enabled + * @param Builder $query + * @return Builder + */ + public function scopeIsEnabled($query) + { + return $query->where('is_enabled', true); + } + + /** + * Scope for ordering the locales + * @param Builder $query + * @return Builder + */ + public function scopeOrder($query) + { + return $query + ->orderBy('sort_order', 'asc') + ; + } + + /** + * Returns true if there are at least 2 locales available. + * @return boolean + */ + public static function isAvailable() + { + return count(self::listAvailable()) > 1; + } + + /** + * Lists available locales, used on the back-end. + * @return array + */ + public static function listAvailable() + { + if (self::$cacheListAvailable) { + return self::$cacheListAvailable; + } + + return self::$cacheListAvailable = self::order()->pluck('name', 'code')->all(); + } + + /** + * Lists the enabled locales, used on the front-end. + * @return array + */ + public static function listEnabled() + { + if (self::$cacheListEnabled) { + return self::$cacheListEnabled; + } + + $expiresAt = now()->addMinutes(1440); + $isEnabled = Cache::remember('rainlab.translate.locales', $expiresAt, function() { + return self::isEnabled()->order()->pluck('name', 'code')->all(); + }); + + return self::$cacheListEnabled = $isEnabled; + } + + /** + * Returns true if the supplied locale is valid. + * @return boolean + */ + public static function isValid($locale) + { + $languages = array_keys(Locale::listEnabled()); + + return in_array($locale, $languages); + } + + /** + * Clears all cache keys used by this model + * @return void + */ + public static function clearCache() + { + Cache::forget('rainlab.translate.locales'); + Cache::forget('rainlab.translate.defaultLocale'); + self::$cacheListEnabled = null; + self::$cacheListAvailable = null; + self::$cacheByCode = []; + } +} diff --git a/plugins/rainlab/translate/models/MLFile.php b/plugins/rainlab/translate/models/MLFile.php new file mode 100644 index 0000000..d3f04c3 --- /dev/null +++ b/plugins/rainlab/translate/models/MLFile.php @@ -0,0 +1,24 @@ +getFormFields() as $id => $field) { + if (!empty($field['translatable'])) { + $this->translatable[] = $id; + } + } + } +} diff --git a/plugins/rainlab/translate/models/Message.php b/plugins/rainlab/translate/models/Message.php new file mode 100644 index 0000000..e468585 --- /dev/null +++ b/plugins/rainlab/translate/models/Message.php @@ -0,0 +1,311 @@ +forLocale(Lang::getLocale()); + } + + /** + * Gets a message for a given locale, or the default. + * @param string $locale + * @return string + */ + public function forLocale($locale = null, $default = null) + { + if ($locale === null) { + $locale = self::DEFAULT_LOCALE; + } + + if (!array_key_exists($locale, $this->message_data)) { + // search parent locale (e.g. en-US -> en) before returning default + list($locale) = explode('-', $locale); + } + + if (array_key_exists($locale, $this->message_data)) { + return $this->message_data[$locale]; + } + + return $default; + } + + /** + * Writes a translated message to a locale. + * @param string $locale + * @param string $message + * @return void + */ + public function toLocale($locale = null, $message = null) + { + if ($locale === null) { + return; + } + + $data = $this->message_data; + $data[$locale] = $message; + + if (!$message) { + unset($data[$locale]); + } + + $this->message_data = $data; + $this->save(); + } + + /** + * Creates or finds an untranslated message string. + * @param string $messageId + * @param string $locale + * @return string + */ + public static function get($messageId, $locale = null) + { + $locale = $locale ?: self::$locale; + if (!$locale) { + return $messageId; + } + + $messageCode = static::makeMessageCode($messageId); + + /* + * Found in cache + */ + if (array_key_exists($locale . $messageCode, self::$cache)) { + return self::$cache[$locale . $messageCode]; + } + + /* + * Uncached item + */ + $item = static::firstOrNew([ + 'code' => $messageCode + ]); + + /* + * Create a default entry + */ + if (!$item->exists) { + $data = [static::DEFAULT_LOCALE => $messageId]; + $item->message_data = $item->message_data ?: $data; + $item->save(); + } + + /* + * Schedule new cache and go + */ + $msg = $item->forLocale($locale, $messageId); + self::$cache[$locale . $messageCode] = $msg; + self::$hasNew = true; + + return $msg; + } + + /** + * Import an array of messages. Only known messages are imported. + * @param array $messages + * @param string $locale + * @return void + */ + public static function importMessages($messages, $locale = null) + { + self::importMessageCodes(array_combine($messages, $messages), $locale); + } + + /** + * Import an array of messages. Only known messages are imported. + * @param array $messages + * @param string $locale + * @return void + */ + public static function importMessageCodes($messages, $locale = null) + { + if ($locale === null) { + $locale = static::DEFAULT_LOCALE; + } + + $existingIds = []; + + foreach ($messages as $code => $message) { + // Ignore empties + if (!strlen(trim($message))) { + continue; + } + + $code = static::makeMessageCode($code); + + $item = static::firstOrNew([ + 'code' => $code + ]); + + // Do not import non-default messages that do not exist + if (!$item->exists && $locale != static::DEFAULT_LOCALE) { + continue; + } + + $messageData = $item->exists || $item->message_data ? $item->message_data : []; + + // Do not overwrite existing translations. + if (isset($messageData[$locale])) { + $existingIds[] = $item->id; + continue; + } + + $messageData[$locale] = $message; + + $item->message_data = $messageData; + $item->found = true; + + $item->save(); + } + + // Set all messages found by the scanner as found + self::whereIn('id', $existingIds)->update(['found' => true]); + } + + /** + * Looks up and translates a message by its string. + * @param string $messageId + * @param array $params + * @param string $locale + * @return string + */ + public static function trans($messageId, $params = [], $locale = null) + { + $msg = static::get($messageId, $locale); + + $params = array_build($params, function($key, $value){ + return [':'.$key, e($value)]; + }); + + $msg = strtr($msg, $params); + + return $msg; + } + + /** + * Looks up and translates a message by its string WITHOUT escaping params. + * @param string $messageId + * @param array $params + * @param string $locale + * @return string + */ + public static function transRaw($messageId, $params = [], $locale = null) + { + $msg = static::get($messageId, $locale); + + $params = array_build($params, function($key, $value){ + return [':'.$key, $value]; + }); + + $msg = strtr($msg, $params); + + return $msg; + } + + /** + * Set the caching context, the page url. + * @param string $locale + * @param string $url + */ + public static function setContext($locale, $url = null) + { + if (!strlen($url)) { + $url = '/'; + } + + self::$url = $url; + self::$locale = $locale; + + if ($cached = Cache::get(static::makeCacheKey())) { + self::$cache = (array) $cached; + } + } + + /** + * Save context messages to cache. + * @return void + */ + public static function saveToCache() + { + if (!self::$hasNew || !self::$url || !self::$locale) { + return; + } + + $expiresAt = now()->addMinutes(Config::get('rainlab.translate::cacheTimeout', 1440)); + Cache::put(static::makeCacheKey(), self::$cache, $expiresAt); + } + + /** + * Creates a cache key for storing context messages. + * @return string + */ + protected static function makeCacheKey() + { + return 'translation.'.self::$locale.self::$url; + } + + /** + * Creates a sterile key for a message. + * @param string $messageId + * @return string + */ + protected static function makeMessageCode($messageId) + { + $separator = '.'; + + // Convert all dashes/underscores into separator + $messageId = preg_replace('!['.preg_quote('_').'|'.preg_quote('-').']+!u', $separator, $messageId); + + // Remove all characters that are not the separator, letters, numbers, or whitespace. + $messageId = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', mb_strtolower($messageId)); + + // Replace all separator characters and whitespace by a single separator + $messageId = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $messageId); + + return Str::limit(trim($messageId, $separator), 250); + } +} diff --git a/plugins/rainlab/translate/models/MessageExport.php b/plugins/rainlab/translate/models/MessageExport.php new file mode 100644 index 0000000..415e88d --- /dev/null +++ b/plugins/rainlab/translate/models/MessageExport.php @@ -0,0 +1,52 @@ +map(function ($message) use ($columns) { + $data = $message->message_data; + // Add code to data to simplify algorithm + $data[self::CODE_COLUMN_NAME] = $message->code; + + $result = []; + foreach ($columns as $column) { + $result[$column] = isset($data[$column]) ? $data[$column] : ''; + } + return $result; + })->toArray(); + } + + /** + * getColumns + * + * code, default column + all existing locales + * + * @return array + */ + public static function getColumns() + { + return array_merge([ + self::CODE_COLUMN_NAME => self::CODE_COLUMN_NAME, + Message::DEFAULT_LOCALE => self::DEFAULT_COLUMN_NAME, + ], Locale::lists(self::CODE_COLUMN_NAME, self::CODE_COLUMN_NAME)); + } +} diff --git a/plugins/rainlab/translate/models/MessageImport.php b/plugins/rainlab/translate/models/MessageImport.php new file mode 100644 index 0000000..3657727 --- /dev/null +++ b/plugins/rainlab/translate/models/MessageImport.php @@ -0,0 +1,70 @@ + 'required' + ]; + + /** + * Import the message data from a csv with the following schema: + * + * code | en | de | fr + * ------------------------------- + * title | Title | Titel | Titre + * name | Name | Name | Prénom + * ... + * + * The code column is required and must not be empty. + * + * Note: Messages with an existing code are not removed/touched if the import + * doesn't contain this code. As a result you can incrementally update the + * messages by just adding the new codes and messages to the csv. + * + * @param $results + * @param null $sessionKey + */ + public function importData($results, $sessionKey = null) + { + $codeName = MessageExport::CODE_COLUMN_NAME; + $defaultName = Message::DEFAULT_LOCALE; + + foreach ($results as $index => $result) { + try { + if (isset($result[$codeName]) && !empty($result[$codeName])) { + $code = $result[$codeName]; + + // Modify result to match the expected message_data schema + unset($result[$codeName]); + + $message = Message::firstOrNew(['code' => $code]); + + // Create empty array, if $message is new + $message->message_data = $message->message_data ?: []; + + if (!isset($message->message_data[$defaultName])) { + $default = (isset($result[$defaultName]) && !empty($result[$defaultName])) ? $result[$defaultName] : $code; + $result[$defaultName] = $default; + } + + $message->message_data = array_merge($message->message_data, $result); + + if ($message->exists) { + $this->logUpdated(); + } else { + $this->logCreated(); + } + + $message->save(); + } else { + $this->logSkipped($index, 'No code provided'); + } + } catch (\Exception $exception) { + $this->logError($index, $exception->getMessage()); + } + } + } +} diff --git a/plugins/rainlab/translate/models/locale/columns.yaml b/plugins/rainlab/translate/models/locale/columns.yaml new file mode 100644 index 0000000..602eae2 --- /dev/null +++ b/plugins/rainlab/translate/models/locale/columns.yaml @@ -0,0 +1,26 @@ +# =================================== +# Column Definitions +# =================================== + +columns: + name: + label: rainlab.translate::lang.locale.name + searchable: yes + + code: + label: rainlab.translate::lang.locale.code + searchable: yes + + is_default: + label: rainlab.translate::lang.locale.is_default + type: switch + + is_enabled: + label: rainlab.translate::lang.locale.is_enabled + type: switch + invisible: true + + sort_order: + label: rainlab.translate::lang.locale.sort_order + type: number + invisible: true diff --git a/plugins/rainlab/translate/models/locale/fields.yaml b/plugins/rainlab/translate/models/locale/fields.yaml new file mode 100644 index 0000000..dbda60d --- /dev/null +++ b/plugins/rainlab/translate/models/locale/fields.yaml @@ -0,0 +1,24 @@ +# =================================== +# Field Definitions +# =================================== + +fields: + name: + label: rainlab.translate::lang.locale.name + span: auto + + code: + label: rainlab.translate::lang.locale.code + span: auto + + is_enabled: + label: rainlab.translate::lang.locale.is_enabled + type: checkbox + comment: rainlab.translate::lang.locale.is_enabled_help + span: auto + + is_default: + label: rainlab.translate::lang.locale.is_default + type: checkbox + comment: rainlab.translate::lang.locale.is_default_help + span: auto diff --git a/plugins/rainlab/translate/phpunit.xml b/plugins/rainlab/translate/phpunit.xml new file mode 100644 index 0000000..1fb393c --- /dev/null +++ b/plugins/rainlab/translate/phpunit.xml @@ -0,0 +1,23 @@ + + + + + ./tests + + + + + + + + diff --git a/plugins/rainlab/translate/routes.php b/plugins/rainlab/translate/routes.php new file mode 100644 index 0000000..66f247b --- /dev/null +++ b/plugins/rainlab/translate/routes.php @@ -0,0 +1,42 @@ +handleLocaleRoute(); + if (!$locale) { + return; + } + + /* + * Register routes + */ + Route::group(['prefix' => $locale, 'middleware' => 'web'], function () { + Route::any('{slug?}', 'Cms\Classes\CmsController@run')->where('slug', '(.*)?'); + }); + + Route::any($locale, 'Cms\Classes\CmsController@run')->middleware('web'); + + /* + * Ensure Url::action() retains the localized URL + * by re-registering the route after the CMS. + */ + Event::listen('cms.route', function () use ($locale) { + Route::group(['prefix' => $locale, 'middleware' => 'web'], function () { + Route::any('{slug?}', 'Cms\Classes\CmsController@run')->where('slug', '(.*)?'); + }); + }); +}); + +/* + * Save any used messages to the contextual cache. + */ +App::after(function ($request) { + if (class_exists('RainLab\Translate\Models\Message')) { + Message::saveToCache(); + } +}); diff --git a/plugins/rainlab/translate/tests/fixtures/classes/Feature.php b/plugins/rainlab/translate/tests/fixtures/classes/Feature.php new file mode 100644 index 0000000..eabe987 --- /dev/null +++ b/plugins/rainlab/translate/tests/fixtures/classes/Feature.php @@ -0,0 +1,24 @@ + true], 'states']; + + /** + * @var string The database table used by the model. + */ + public $table = 'translate_test_countries'; + + /** + * @var array Guarded fields + */ + protected $guarded = []; + + /** + * @var array Jsonable fields + */ + protected $jsonable = ['states']; +} diff --git a/plugins/rainlab/translate/tests/fixtures/themes/test/.gitignore b/plugins/rainlab/translate/tests/fixtures/themes/test/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/plugins/rainlab/translate/tests/fixtures/themes/test/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/plugins/rainlab/translate/tests/unit/behaviors/TranslatableCmsObjectTest.php b/plugins/rainlab/translate/tests/unit/behaviors/TranslatableCmsObjectTest.php new file mode 100644 index 0000000..1228656 --- /dev/null +++ b/plugins/rainlab/translate/tests/unit/behaviors/TranslatableCmsObjectTest.php @@ -0,0 +1,110 @@ +themePath = __DIR__ . '/../../fixtures/themes/test'; + + $this->seedSampleSourceAndData(); + } + + public function tearDown(): void + { + $this->cleanUp(); + } + + protected function cleanUp() + { + @unlink($this->themePath.'/features/winning.htm'); + @unlink($this->themePath.'/features-fr/winning.htm'); + File::deleteDirectory($this->themePath.'/features'); + File::deleteDirectory($this->themePath.'/features-fr'); + } + + protected function seedSampleSourceAndData() + { + $datasource = new FileDatasource($this->themePath, new Filesystem); + $resolver = new Resolver(['theme1' => $datasource]); + $resolver->setDefaultDatasource('theme1'); + Model::setDatasourceResolver($resolver); + + LocaleModel::unguard(); + + LocaleModel::firstOrCreate([ + 'code' => 'fr', + 'name' => 'French', + 'is_enabled' => 1 + ]); + + LocaleModel::reguard(); + + $this->recycleSampleData(); + } + + protected function recycleSampleData() + { + $this->cleanUp(); + + FeatureModel::create([ + 'fileName' => 'winning.htm', + 'settings' => ['title' => 'Hash tag winning'], + 'markup' => 'Awww yiss', + ]); + } + + public function testGetTranslationValue() + { + $obj = FeatureModel::first(); + + $this->assertEquals('Awww yiss', $obj->markup); + + $obj->translateContext('fr'); + + $this->assertEquals('Awww yiss', $obj->markup); + } + + public function testGetTranslationValueNoFallback() + { + $obj = FeatureModel::first(); + + $this->assertEquals('Awww yiss', $obj->markup); + + $obj->noFallbackLocale()->translateContext('fr'); + + $this->assertEquals(null, $obj->markup); + } + + public function testSetTranslationValue() + { + $this->recycleSampleData(); + + $obj = FeatureModel::first(); + $obj->markup = 'Aussie'; + $obj->save(); + + $obj->translateContext('fr'); + $obj->markup = 'Australie'; + $obj->save(); + + $obj = FeatureModel::first(); + $this->assertEquals('Aussie', $obj->markup); + + $obj->translateContext('fr'); + $this->assertEquals('Australie', $obj->markup); + } + +} diff --git a/plugins/rainlab/translate/tests/unit/behaviors/TranslatableModelTest.php b/plugins/rainlab/translate/tests/unit/behaviors/TranslatableModelTest.php new file mode 100755 index 0000000..f33509d --- /dev/null +++ b/plugins/rainlab/translate/tests/unit/behaviors/TranslatableModelTest.php @@ -0,0 +1,202 @@ +seedSampleTableAndData(); + } + + protected function seedSampleTableAndData() + { + if (Schema::hasTable('translate_test_countries')) { + return; + } + + Model::unguard(); + + Schema::create('translate_test_countries', function($table) + { + $table->engine = 'InnoDB'; + $table->increments('id'); + $table->string('name')->nullable(); + $table->string('code')->nullable(); + $table->text('states')->nullable(); + $table->timestamps(); + }); + + LocaleModel::firstOrCreate([ + 'code' => 'fr', + 'name' => 'French', + 'is_enabled' => 1 + ]); + + $this->recycleSampleData(); + + Model::reguard(); + } + + protected function recycleSampleData() + { + CountryModel::truncate(); + + CountryModel::create([ + 'name' => 'Australia', + 'code' => 'AU', + 'states' => ['NSW', 'ACT', 'QLD'], + ]); + } + + public function testGetTranslationValue() + { + $obj = CountryModel::first(); + + $this->assertEquals('Australia', $obj->name); + $this->assertEquals(['NSW', 'ACT', 'QLD'], $obj->states); + + $obj->translateContext('fr'); + + $this->assertEquals('Australia', $obj->name); + } + + public function testGetTranslationValueNoFallback() + { + $obj = CountryModel::first(); + + $this->assertEquals('Australia', $obj->name); + + $obj->noFallbackLocale()->translateContext('fr'); + + $this->assertEquals(null, $obj->name); + } + + public function testSetTranslationValue() + { + $this->recycleSampleData(); + + $obj = CountryModel::first(); + $obj->name = 'Aussie'; + $obj->states = ['VIC', 'SA', 'NT']; + $obj->save(); + + $obj->translateContext('fr'); + $obj->name = 'Australie'; + $obj->states = ['a', 'b', 'c']; + $obj->save(); + + $obj = CountryModel::first(); + $this->assertEquals('Aussie', $obj->name); + $this->assertEquals(['VIC', 'SA', 'NT'], $obj->states); + + $obj->translateContext('fr'); + $this->assertEquals('Australie', $obj->name); + $this->assertEquals(['a', 'b', 'c'], $obj->states); + } + + public function testGetTranslationValueEagerLoading() + { + $this->recycleSampleData(); + + $obj = CountryModel::first(); + $obj->translateContext('fr'); + $obj->name = 'Australie'; + $obj->states = ['a', 'b', 'c']; + $obj->save(); + + $objList = CountryModel::with([ + 'translations' + ])->get(); + + $obj = $objList[0]; + $this->assertEquals('Australia', $obj->name); + $this->assertEquals(['NSW', 'ACT', 'QLD'], $obj->states); + + $obj->translateContext('fr'); + $this->assertEquals('Australie', $obj->name); + $this->assertEquals(['a', 'b', 'c'], $obj->states); + } + + public function testTranslateWhere() + { + $this->recycleSampleData(); + + $obj = CountryModel::first(); + + $obj->translateContext('fr'); + $obj->name = 'Australie'; + $obj->save(); + + $this->assertEquals(0, CountryModel::transWhere('name', 'Australie')->count()); + + Translator::instance()->setLocale('fr'); + $this->assertEquals(1, CountryModel::transWhere('name', 'Australie')->count()); + + Translator::instance()->setLocale('en'); + } + + public function testTranslateOrderBy() + { + $this->recycleSampleData(); + + $obj = CountryModel::first(); + + $obj->translateContext('fr'); + $obj->name = 'Australie'; + $obj->save(); + + $obj = CountryModel::create([ + 'name' => 'Germany', + 'code' => 'DE' + ]); + + $obj->translateContext('fr'); + $obj->name = 'Allemagne'; + $obj->save(); + + $res = CountryModel::transOrderBy('name')->get()->pluck('name'); + $this->assertEquals(['Australia', 'Germany'], $res->toArray()); + + Translator::instance()->setLocale('fr'); + $res = CountryModel::transOrderBy('name')->get()->pluck('name'); + $this->assertEquals(['Allemagne', 'Australie'], $res->toArray()); + + Translator::instance()->setLocale('en'); + } + + public function testGetTranslationValueEagerLoadingWithMorphMap() + { + Relation::morphMap([ + 'morph.key' => CountryModel::class, + ]); + + $this->recycleSampleData(); + + $obj = CountryModel::first(); + $obj->translateContext('fr'); + $obj->name = 'Australie'; + $obj->states = ['a', 'b', 'c']; + $obj->save(); + + $objList = CountryModel::with([ + 'translations' + ])->get(); + + $obj = $objList[0]; + $this->assertEquals('Australia', $obj->name); + $this->assertEquals(['NSW', 'ACT', 'QLD'], $obj->states); + + $obj->translateContext('fr'); + $this->assertEquals('Australie', $obj->name); + $this->assertEquals(['a', 'b', 'c'], $obj->states); + } +} diff --git a/plugins/rainlab/translate/tests/unit/behaviors/TranslatablePageTest.php b/plugins/rainlab/translate/tests/unit/behaviors/TranslatablePageTest.php new file mode 100644 index 0000000..0bbfa44 --- /dev/null +++ b/plugins/rainlab/translate/tests/unit/behaviors/TranslatablePageTest.php @@ -0,0 +1,67 @@ +themePath = __DIR__ . '/../../fixtures/themes/test'; + + $datasource = new FileDatasource($this->themePath, new Filesystem); + $resolver = new Resolver(['theme1' => $datasource]); + $resolver->setDefaultDatasource('theme1'); + Model::setDatasourceResolver($resolver); + + TranslatablePage::extend(function($page) { + if (!$page->isClassExtendedWith('RainLab\Translate\Behaviors\TranslatablePage')) { + $page->addDynamicProperty('translatable', ['title']); + $page->extendClassWith('RainLab\Translate\Behaviors\TranslatablePage'); + } + }); + + } + + public function tearDown(): void + { + File::deleteDirectory($this->themePath.'/pages'); + } + + public function testUseFallback() + { + $page = TranslatablePage::create([ + 'fileName' => 'translatable', + 'title' => 'english title', + 'url' => '/test', + ]); + $page->translateContext('fr'); + $this->assertEquals('english title', $page->title); + $page->noFallbackLocale()->translateContext('fr'); + $this->assertEquals(null, $page->title); + } + + public function testAlternateLocale() + { + $page = TranslatablePage::create([ + 'fileName' => 'translatable', + 'title' => 'english title', + 'url' => '/test', + ]); + $page->setAttributeTranslated('title', 'titre francais', 'fr'); + $title_en = $page->title; + $this->assertEquals('english title', $title_en); + $page->translateContext('fr'); + $title_fr = $page->title; + $this->assertEquals('titre francais', $title_fr); + } +} diff --git a/plugins/rainlab/translate/tests/unit/models/ExportMessageTest.php b/plugins/rainlab/translate/tests/unit/models/ExportMessageTest.php new file mode 100644 index 0000000..76262c9 --- /dev/null +++ b/plugins/rainlab/translate/tests/unit/models/ExportMessageTest.php @@ -0,0 +1,98 @@ +exportData([]); + + $this->assertEquals($expected, $result); + } + + public function testCanHandleNoColumn() + { + $exportModel = new MessageExport(); + $this->createMessages(); + $expected = [[], []]; + + $result = $exportModel->exportData([]); + + $this->assertEquals($expected, $result); + } + + public function testExportSomeColumns() + { + $exportMode = new MessageExport(); + $this->createMessages(); + $expected = [ + ['code' => 'hello'], + ['code' => 'bye'], + ]; + + $result = $exportMode->exportData(['code']); + + $this->assertEquals($expected, $result); + } + + public function testExportAllColumns() + { + $exportMode = new MessageExport(); + $this->createMessages(); + $expected = [ + ['code' => 'hello', 'de' => 'Hallo, Welt', 'en' => 'Hello, World'], + ['code' => 'bye', 'de' => 'Auf Wiedersehen', 'en' => 'Goodbye'], + ]; + + $result = $exportMode->exportData(['code', 'de', 'en']); + + $this->assertEquals($expected, $result); + } + + public function testCanHandleNonExistingColumns() + { + $exportMode = new MessageExport(); + $this->createMessages(); + $expected = [ + ['dummy' => ''], + ['dummy' => ''], + ]; + + $result = $exportMode->exportData(['dummy']); + + $this->assertEquals($expected, $result); + } + + private function createMessages() + { + Message::create([ + 'code' => 'hello', 'message_data' => ['de' => 'Hallo, Welt', 'en' => 'Hello, World'] + ]); + Message::create([ + 'code' => 'bye', 'message_data' => ['de' => 'Auf Wiedersehen', 'en' => 'Goodbye'] + ]); + } + + public function testGetColumns() + { + Locale::unguard(); + Locale::create(['code' => 'de', 'name' => 'German', 'is_enabled' => true]); + + $columns = MessageExport::getColumns(); + + $this->assertEquals([ + MessageExport::CODE_COLUMN_NAME => MessageExport::CODE_COLUMN_NAME, + Message::DEFAULT_LOCALE => MessageExport::DEFAULT_COLUMN_NAME, + 'en' => 'en', + 'de' => 'de', + ], $columns); + } +} diff --git a/plugins/rainlab/translate/tests/unit/models/ImportMessageTest.php b/plugins/rainlab/translate/tests/unit/models/ImportMessageTest.php new file mode 100644 index 0000000..8b9c02a --- /dev/null +++ b/plugins/rainlab/translate/tests/unit/models/ImportMessageTest.php @@ -0,0 +1,95 @@ +importData($data); + + $stats = $messageImport->getResultStats(); + $this->assertEquals(false, $stats->hasMessages); + } + + public function testCreateMessage() + { + $messageImport = new MessageImport(); + $data = [ + ['code' => 'new', 'de' => 'Neu', 'en' => 'new'] + ]; + + $messageImport->importData($data); + + $stats = $messageImport->getResultStats(); + $this->assertEquals(1, $stats->created); + $this->assertEquals(0, $stats->updated); + $this->assertEquals(0, $stats->skippedCount); + $this->assertEquals(false, $stats->hasMessages); + } + + public function testUpdateMessage() + { + $messageImport = new MessageImport(); + Message::create(['code' => 'update', 'message_data' => ['en' => 'update', 'de' => 'aktualisieren']]); + $data = [ + ['code' => 'update', 'de' => 'Neu 2', 'en' => 'new 2'] + ]; + $expected = [ + Message::DEFAULT_LOCALE => 'update', 'de' => 'Neu 2', 'en' => 'new 2' + ]; + + $messageImport->importData($data); + + $stats = $messageImport->getResultStats(); + $this->assertEquals(0, $stats->created); + $this->assertEquals(1, $stats->updated); + $this->assertEquals(0, $stats->skippedCount); + $this->assertEquals(false, $stats->hasMessages); + $updatedMessage = Message::whereCode('update')->first(); + $this->assertEquals($expected, $updatedMessage->message_data); + } + + public function testMissingCodeIsSkipped() + { + $messageImport = new MessageImport(); + $data = [ + ['de' => 'Neu 2', 'en' => 'new 2'] + ]; + + $messageImport->importData($data); + + $stats = $messageImport->getResultStats(); + $this->assertEquals(0, $stats->created); + $this->assertEquals(0, $stats->updated); + $this->assertEquals(1, $stats->skippedCount); + $this->assertEquals(true, $stats->hasMessages); + $this->assertEquals(Message::count(), 0); + } + + public function testDefaultLocaleIsImported() + { + $messageImport = new MessageImport(); + $data = [ + ['code' => 'test.me', 'x' => 'foo bar', 'de' => 'Neu 2', 'en' => 'new 2'] + ]; + + $messageImport->importData($data); + + $stats = $messageImport->getResultStats(); + $this->assertEquals(1, $stats->created); + $this->assertEquals(0, $stats->updated); + $this->assertEquals(0, $stats->skippedCount); + $this->assertEquals(false, $stats->hasMessages); + $this->assertEquals(Message::count(), 1); + + $message = Message::where('code', 'test.me')->first(); + + $this->assertEquals('foo bar', $message->message_data['x']); + } +} diff --git a/plugins/rainlab/translate/tests/unit/models/MessageTest.php b/plugins/rainlab/translate/tests/unit/models/MessageTest.php new file mode 100644 index 0000000..32a33eb --- /dev/null +++ b/plugins/rainlab/translate/tests/unit/models/MessageTest.php @@ -0,0 +1,61 @@ +assertNotNull(Message::whereCode('hello.world')->first()); + $this->assertNotNull(Message::whereCode('hello.piñata')->first()); + + Message::truncate(); + } + + public function testMakeMessageCode() + { + $this->assertEquals('hello.world', Message::makeMessageCode('hello world')); + $this->assertEquals('hello.world', Message::makeMessageCode(' hello world ')); + $this->assertEquals('hello.world', Message::makeMessageCode('hello-world')); + $this->assertEquals('hello.world', Message::makeMessageCode('hello--world')); + + // casing + $this->assertEquals('hello.world', Message::makeMessageCode('Hello World')); + $this->assertEquals('hello.world', Message::makeMessageCode('Hello World!')); + + // underscores + $this->assertEquals('hello.world', Message::makeMessageCode('hello_world')); + $this->assertEquals('hello.world', Message::makeMessageCode('hello__world')); + + // length limit + $veryLongString = str_repeat("10 charstr", 30); + $this->assertTrue(strlen($veryLongString) > 250); + $this->assertEquals(253, strlen(Message::makeMessageCode($veryLongString))); + $this->assertStringEndsWith('...', Message::makeMessageCode($veryLongString)); + + // unicode characters + // brrowered some test cases from Stringy, the library Laravel's + // `slug()` function depends on + // https://github.com/danielstjules/Stringy/blob/master/tests/CommonTest.php + $this->assertEquals('fòô.bàř', Message::makeMessageCode('fòô bàř')); + $this->assertEquals('ťéśţ', Message::makeMessageCode(' ŤÉŚŢ ')); + $this->assertEquals('φ.ź.3', Message::makeMessageCode('φ = ź = 3')); + $this->assertEquals('перевірка', Message::makeMessageCode('перевірка')); + $this->assertEquals('лысая.гора', Message::makeMessageCode('лысая гора')); + $this->assertEquals('щука', Message::makeMessageCode('щука')); + $this->assertEquals('foo.漢字', Message::makeMessageCode('foo 漢字')); // Chinese + $this->assertEquals('xin.chào.thế.giới', Message::makeMessageCode('xin chào thế giới')); + $this->assertEquals('xin.chào.thế.giới', Message::makeMessageCode('XIN CHÀO THẾ GIỚI')); + $this->assertEquals('đấm.phát.chết.luôn', Message::makeMessageCode('đấm phát chết luôn')); + $this->assertEquals('foo', Message::makeMessageCode('foo ')); // no-break space (U+00A0) + $this->assertEquals('foo', Message::makeMessageCode('foo           ')); // spaces U+2000 to U+200A + $this->assertEquals('foo', Message::makeMessageCode('foo ')); // narrow no-break space (U+202F) + $this->assertEquals('foo', Message::makeMessageCode('foo ')); // medium mathematical space (U+205F) + $this->assertEquals('foo', Message::makeMessageCode('foo ')); // ideographic space (U+3000) + } +} diff --git a/plugins/rainlab/translate/traits/MLControl.php b/plugins/rainlab/translate/traits/MLControl.php new file mode 100644 index 0000000..cbef397 --- /dev/null +++ b/plugins/rainlab/translate/traits/MLControl.php @@ -0,0 +1,279 @@ +defaultLocale = Locale::getDefault(); + $this->isAvailable = Locale::isAvailable(); + } + + /** + * getParentViewPath returns the parent control's view path + * + * @return string + */ + protected function getParentViewPath() + { + // return base_path().'/modules/backend/formwidgets/parentcontrol/partials'; + } + + /** + * getParentAssetPath returns the parent control's asset path + * + * @return string + */ + protected function getParentAssetPath() + { + // return '/modules/backend/formwidgets/parentcontrol/assets'; + } + + /** + * actAsParent swaps the asset & view paths with the parent control's to + * act as the parent control + * + * @param boolean $switch Defaults to true, determines whether to act as the parent or revert to current + */ + protected function actAsParent($switch = true) + { + if ($switch) { + $this->originalAssetPath = $this->assetPath; + $this->originalViewPath = $this->viewPath; + $this->assetPath = $this->getParentAssetPath(); + $this->viewPath = $this->getParentViewPath(); + } + else { + $this->assetPath = $this->originalAssetPath; + $this->viewPath = $this->originalViewPath; + } + } + + /** + * {@inheritDoc} + */ + public function renderFallbackField() + { + return $this->makeMLPartial('fallback_field'); + } + + /** + * makeMLPartial is used by child classes to render in context of this view path. + * @param string $partial The view to load. + * @param array $params Parameter variables to pass to the view. + * @return string The view contents. + */ + public function makeMLPartial($partial, $params = []) + { + $oldViewPath = $this->viewPath; + $this->viewPath = $this->guessViewPathFrom(__TRAIT__, '/partials'); + $result = $this->makePartial($partial, $params); + $this->viewPath = $oldViewPath; + + return $result; + } + + /** + * prepareLocaleVars prepares the list data + */ + public function prepareLocaleVars() + { + $this->vars['defaultLocale'] = $this->defaultLocale; + $this->vars['locales'] = Locale::listAvailable(); + $this->vars['field'] = $this->makeRenderFormField(); + } + + /** + * loadLocaleAssets loads assets specific to ML Controls + */ + public function loadLocaleAssets() + { + $this->addJs('/plugins/rainlab/translate/assets/js/multilingual.js', 'RainLab.Translate'); + $this->addCss('/plugins/rainlab/translate/assets/css/multilingual.css', 'RainLab.Translate'); + + if (!class_exists('System')) { + $this->addCss('/plugins/rainlab/translate/assets/css/multilingual-v1.css', 'RainLab.Translate'); + } + } + + /** + * getLocaleValue returns a translated value for a given locale. + * @param string $locale + * @return string + */ + public function getLocaleValue($locale) + { + $key = $this->valueFrom ?: $this->fieldName; + + /* + * Get the translated values from the model + */ + $studKey = Str::studly(implode(' ', HtmlHelper::nameToArray($key))); + $mutateMethod = 'get'.$studKey.'AttributeTranslated'; + + if ($this->objectMethodExists($this->model, $mutateMethod)) { + $value = $this->model->$mutateMethod($locale); + } + elseif ($this->objectMethodExists($this->model, 'getAttributeTranslated') && $this->defaultLocale->code != $locale) { + $value = $this->model->noFallbackLocale()->getAttributeTranslated($key, $locale); + } + else { + $value = $this->formField->value; + } + + return $value; + } + + /** + * makeRenderFormField if translation is unavailable, render the original field type (text). + */ + protected function makeRenderFormField() + { + if ($this->isAvailable) { + return $this->formField; + } + + $field = clone $this->formField; + $field->type = $this->getFallbackType(); + + return $field; + } + + /** + * {@inheritDoc} + */ + public function getLocaleSaveValue($value) + { + $localeData = $this->getLocaleSaveData(); + $key = $this->valueFrom ?: $this->fieldName; + + /* + * Set the translated values to the model + */ + $studKey = Str::studly(implode(' ', HtmlHelper::nameToArray($key))); + $mutateMethod = 'set'.$studKey.'AttributeTranslated'; + + if ($this->objectMethodExists($this->model, $mutateMethod)) { + foreach ($localeData as $locale => $value) { + $this->model->$mutateMethod($value, $locale); + } + } + elseif ($this->objectMethodExists($this->model, 'setAttributeTranslated')) { + foreach ($localeData as $locale => $value) { + $this->model->setAttributeTranslated($key, $value, $locale); + } + } + + return array_get($localeData, $this->defaultLocale->code, $value); + } + + /** + * getLocaleSaveData returns an array of translated values for this field + * @return array + */ + public function getLocaleSaveData() + { + $values = []; + $data = post('RLTranslate'); + + if (!is_array($data)) { + return $values; + } + + $fieldName = implode('.', HtmlHelper::nameToArray($this->fieldName)); + $isJson = $this->isLocaleFieldJsonable(); + + foreach ($data as $locale => $_data) { + $value = array_get($_data, $fieldName); + $values[$locale] = $isJson ? json_decode($value, true) : $value; + } + + return $values; + } + + /** + * getFallbackType returns the fallback field type. + * @return string + */ + public function getFallbackType() + { + return defined('static::FALLBACK_TYPE') ? static::FALLBACK_TYPE : 'text'; + } + + /** + * isLocaleFieldJsonable returns true if widget is a repeater, or the field is specified + * as jsonable in the model. + * @return bool + */ + public function isLocaleFieldJsonable() + { + if ( + $this instanceof \Backend\FormWidgets\Repeater || + $this instanceof \Backend\FormWidgets\NestedForm + ) { + return true; + } + + if ($this instanceof \Media\FormWidgets\MediaFinder && $this->maxItems !== 1) { + return true; + } + + if ( + method_exists($this->model, 'isJsonable') && + $this->model->isJsonable($this->fieldName) + ) { + return true; + } + + return false; + } + + /** + * objectMethodExists is an internal helper for method existence checks. + * + * @param object $object + * @param string $method + * @return boolean + */ + protected function objectMethodExists($object, $method) + { + if (method_exists($object, 'methodExists')) { + return $object->methodExists($method); + } + + return method_exists($object, $method); + } +} diff --git a/plugins/rainlab/translate/traits/mlcontrol/partials/_fallback_field.htm b/plugins/rainlab/translate/traits/mlcontrol/partials/_fallback_field.htm new file mode 100644 index 0000000..0ffd1ab --- /dev/null +++ b/plugins/rainlab/translate/traits/mlcontrol/partials/_fallback_field.htm @@ -0,0 +1,3 @@ +
    + makePartial('~/modules/backend/widgets/form/partials/_field_'.$field->type.'.htm', ['field' => $field]) ?> +
    \ No newline at end of file diff --git a/plugins/rainlab/translate/traits/mlcontrol/partials/_locale_selector.htm b/plugins/rainlab/translate/traits/mlcontrol/partials/_locale_selector.htm new file mode 100644 index 0000000..fb2c0b6 --- /dev/null +++ b/plugins/rainlab/translate/traits/mlcontrol/partials/_locale_selector.htm @@ -0,0 +1,18 @@ + + diff --git a/plugins/rainlab/translate/traits/mlcontrol/partials/_locale_values.htm b/plugins/rainlab/translate/traits/mlcontrol/partials/_locale_values.htm new file mode 100644 index 0000000..ae24007 --- /dev/null +++ b/plugins/rainlab/translate/traits/mlcontrol/partials/_locale_values.htm @@ -0,0 +1,15 @@ + + $name): ?> + getLocaleValue($code); + $value = $this->isLocaleFieldJsonable() ? json_encode($value) : $value; + if (is_array($value)) $value = array_first($value); + ?> + getAttributes() ?> + /> + diff --git a/plugins/rainlab/translate/updates/builder_table_update_rainlab_translate_locales.php b/plugins/rainlab/translate/updates/builder_table_update_rainlab_translate_locales.php new file mode 100755 index 0000000..0c1f319 --- /dev/null +++ b/plugins/rainlab/translate/updates/builder_table_update_rainlab_translate_locales.php @@ -0,0 +1,44 @@ +integer('sort_order')->default(0); + }); + } + + $locales = Locale::all(); + foreach($locales as $locale) { + $locale->sort_order = $locale->id; + $locale->save(); + } + } + + public function down() + { + if (!Schema::hasTable(self::TABLE_NAME)) { + return; + } + + if (Schema::hasColumn(self::TABLE_NAME, 'sort_order')) { + Schema::table(self::TABLE_NAME, function($table) + { + $table->dropColumn(['sort_order']); + }); + } + } +} diff --git a/plugins/rainlab/translate/updates/create_attributes_table.php b/plugins/rainlab/translate/updates/create_attributes_table.php new file mode 100644 index 0000000..7dc5b96 --- /dev/null +++ b/plugins/rainlab/translate/updates/create_attributes_table.php @@ -0,0 +1,27 @@ +engine = 'InnoDB'; + $table->increments('id'); + $table->string('locale')->index(); + $table->string('model_id')->index()->nullable(); + $table->string('model_type')->index()->nullable(); + $table->mediumText('attribute_data')->nullable(); + }); + } + + public function down() + { + Schema::dropIfExists('rainlab_translate_attributes'); + } + +} diff --git a/plugins/rainlab/translate/updates/create_indexes_table.php b/plugins/rainlab/translate/updates/create_indexes_table.php new file mode 100644 index 0000000..2e90ece --- /dev/null +++ b/plugins/rainlab/translate/updates/create_indexes_table.php @@ -0,0 +1,28 @@ +engine = 'InnoDB'; + $table->increments('id'); + $table->string('locale')->index(); + $table->string('model_id')->index()->nullable(); + $table->string('model_type')->index()->nullable(); + $table->string('item')->nullable()->index(); + $table->mediumText('value')->nullable(); + }); + } + + public function down() + { + Schema::dropIfExists('rainlab_translate_indexes'); + } + +} diff --git a/plugins/rainlab/translate/updates/create_locales_table.php b/plugins/rainlab/translate/updates/create_locales_table.php new file mode 100644 index 0000000..4d24e9e --- /dev/null +++ b/plugins/rainlab/translate/updates/create_locales_table.php @@ -0,0 +1,27 @@ +engine = 'InnoDB'; + $table->increments('id'); + $table->string('code')->index(); + $table->string('name')->index()->nullable(); + $table->boolean('is_default')->default(0); + $table->boolean('is_enabled')->default(0); + }); + } + + public function down() + { + Schema::dropIfExists('rainlab_translate_locales'); + } + +} diff --git a/plugins/rainlab/translate/updates/create_messages_table.php b/plugins/rainlab/translate/updates/create_messages_table.php new file mode 100644 index 0000000..2532405 --- /dev/null +++ b/plugins/rainlab/translate/updates/create_messages_table.php @@ -0,0 +1,25 @@ +engine = 'InnoDB'; + $table->increments('id'); + $table->string('code')->index()->nullable(); + $table->mediumText('message_data')->nullable(); + }); + } + + public function down() + { + Schema::dropIfExists('rainlab_translate_messages'); + } + +} diff --git a/plugins/rainlab/translate/updates/migrate_morphed_attributes.php b/plugins/rainlab/translate/updates/migrate_morphed_attributes.php new file mode 100644 index 0000000..10b9b07 --- /dev/null +++ b/plugins/rainlab/translate/updates/migrate_morphed_attributes.php @@ -0,0 +1,32 @@ +getTable(); + foreach (Relation::$morphMap as $alias => $class) { + Db::table($table)->where('model_type', $class)->update(['model_type' => $alias]); + } + } + + public function down() + { + $table = (new Attribute())->getTable(); + foreach (Relation::$morphMap as $alias => $class) { + Db::table($table)->where('model_type', $alias)->update(['model_type' => $class]); + } + } +} diff --git a/plugins/rainlab/translate/updates/migrate_morphed_indexes.php b/plugins/rainlab/translate/updates/migrate_morphed_indexes.php new file mode 100644 index 0000000..29300f3 --- /dev/null +++ b/plugins/rainlab/translate/updates/migrate_morphed_indexes.php @@ -0,0 +1,32 @@ + $class) { + Db::table($this->table)->where('model_type', $class)->update(['model_type' => $alias]); + } + } + + public function down() + { + foreach (Relation::$morphMap as $alias => $class) { + Db::table($this->table)->where('model_type', $alias)->update(['model_type' => $class]); + } + } +} diff --git a/plugins/rainlab/translate/updates/seed_all_tables.php b/plugins/rainlab/translate/updates/seed_all_tables.php new file mode 100644 index 0000000..3157681 --- /dev/null +++ b/plugins/rainlab/translate/updates/seed_all_tables.php @@ -0,0 +1,21 @@ + 'en', + 'name' => 'English', + 'is_default' => true, + 'is_enabled' => true + ]); + } + } + +} diff --git a/plugins/rainlab/translate/updates/update_messages_table.php b/plugins/rainlab/translate/updates/update_messages_table.php new file mode 100644 index 0000000..5d9955b --- /dev/null +++ b/plugins/rainlab/translate/updates/update_messages_table.php @@ -0,0 +1,37 @@ +boolean('found')->default(1); + }); + } + } + + public function down() + { + if (!Schema::hasTable(self::TABLE_NAME)) { + return; + } + + if (Schema::hasColumn(self::TABLE_NAME, 'found')) { + Schema::table(self::TABLE_NAME, function($table) + { + $table->dropColumn(['found']); + }); + } + } +} diff --git a/plugins/rainlab/translate/updates/version.yaml b/plugins/rainlab/translate/updates/version.yaml new file mode 100755 index 0000000..a731208 --- /dev/null +++ b/plugins/rainlab/translate/updates/version.yaml @@ -0,0 +1,99 @@ +v1.0.1: + - First version of Translate + - create_messages_table.php + - create_attributes_table.php + - create_locales_table.php +v1.0.2: Languages and Messages can now be deleted. +v1.0.3: Minor updates for latest October release. +v1.0.4: Locale cache will clear when updating a language. +v1.0.5: Add Spanish language and fix plugin config. +v1.0.6: Minor improvements to the code. +v1.0.7: Fixes major bug where translations are skipped entirely! +v1.0.8: Minor bug fixes. +v1.0.9: Fixes an issue where newly created models lose their translated values. +v1.0.10: Minor fix for latest build. +v1.0.11: Fix multilingual rich editor when used in stretch mode. +v1.1.0: Introduce compatibility with RainLab.Pages plugin. +v1.1.1: Minor UI fix to the language picker. +v1.1.2: Add support for translating Static Content files. +v1.1.3: Improved support for the multilingual rich editor. +v1.1.4: Adds new multilingual markdown editor. +v1.1.5: Minor update to the multilingual control API. +v1.1.6: Minor improvements in the message editor. +v1.1.7: Fixes bug not showing content when first loading multilingual textarea controls. +v1.2.0: CMS pages now support translating the URL. +v1.2.1: Minor update in the rich editor and code editor language control position. +v1.2.2: Static Pages now support translating the URL. +v1.2.3: Fixes Rich Editor when inserting a page link. +v1.2.4: + - Translatable attributes can now be declared as indexes. + - create_indexes_table.php +v1.2.5: Adds new multilingual repeater form widget. +v1.2.6: Fixes repeater usage with static pages plugin. +v1.2.7: Fixes placeholder usage with static pages plugin. +v1.2.8: Improvements to code for latest October build compatibility. +v1.2.9: Fixes context for translated strings when used with Static Pages. +v1.2.10: Minor UI fix to the multilingual repeater. +v1.2.11: Fixes translation not working with partials loaded via AJAX. +v1.2.12: Add support for translating the new grouped repeater feature. +v1.3.0: Added search to the translate messages page. +v1.3.1: + - Added reordering to languages + - builder_table_update_rainlab_translate_locales.php + - seed_all_tables.php +v1.3.2: Improved compatibility with RainLab.Pages, added ability to scan Mail Messages for translatable variables. +v1.3.3: Fix to the locale picker session handling in Build 420 onwards. +v1.3.4: Add alternate hreflang elements and adds prefixDefaultLocale setting. +v1.3.5: Fix MLRepeater bug when switching locales. +v1.3.6: Fix Middleware to use the prefixDefaultLocale setting introduced in 1.3.4 +v1.3.7: Fix config reference in LocaleMiddleware +v1.3.8: Keep query string when switching locales +v1.4.0: Add importer and exporter for messages +v1.4.1: Updated Hungarian translation. Added Arabic translation. Fixed issue where default texts are overwritten by import. Fixed issue where the language switcher for repeater fields would overlap with the first repeater row. +v1.4.2: Add multilingual MediaFinder +v1.4.3: "!!! Please update OctoberCMS to Build 444 before updating this plugin. Added ability to translate CMS Pages fields (e.g. title, description, meta-title, meta-description)" +v1.4.4: Minor improvements to compatibility with Laravel framework. +v1.4.5: Fixed issue when using the language switcher +v1.5.0: Compatibility fix with Build 451 +v1.6.0: Make File Upload widget properties translatable. Merge Repeater core changes into MLRepeater widget. Add getter method to retrieve original translate data. +v1.6.1: Add ability for models to provide translated computed data, add option to disable locale prefix routing +v1.6.2: Implement localeUrl filter, add per-locale theme configuration support +v1.6.3: Add eager loading for translations, restore support for accessors & mutators +v1.6.4: Fixes PHP 7.4 compatibility +v1.6.5: Fixes compatibility issue when other plugins use a custom model morph map +v1.6.6: + - Introduce migration to patch existing translations using morph map + - migrate_morphed_attributes.php +v1.6.7: + - Introduce migration to patch existing indexes using morph map + - migrate_morphed_indexes.php +v1.6.8: Add support for transOrderBy; Add translation support for ThemeData; Update russian localization. +v1.6.9: Clear Static Page menu cache after saving the model; CSS fix for Text/Textarea input fields language selector. +v1.6.10: + - Add option to purge deleted messages when scanning messages, Add Scan error column on Messages page, Fix translations that were lost when clicking locale twice while holding ctrl key, Fix error with nested fields default locale value, Escape Message translate params value. + - update_messages_table.php +v1.7.0: "!!! Breaking change for the Message::trans() method (params are now escaped), fix message translation documentation, fix string translation key for scan errors column header." +v1.7.1: Fix YAML issue with previous tag/release. +v1.7.2: Fix regex when "|_" filter is followed by another filter, Try locale without country before returning default translation, Allow exporting default locale, Fire 'rainlab.translate.themeScanner.afterScan' event in the theme scanner for extendability. +v1.7.3: Make plugin ready for Laravel 6 update, Add support for translating RainLab.Pages MenuItem properties (requires RainLab.Pages v1.3.6), Restore multilingual button position for textarea, Fix translatableAttributes. +v1.7.4: Faster version of transWhere, Mail templates/views can now be localized, Fix messages table layout on mobile, Fix scopeTransOrderBy duplicates, Polish localization updates, Turkish localization updates, Add Greek language localization. +v1.8.0: Adds initial support for October v2.0 +v1.8.1: Minor bugfix +v1.8.2: Fixes translated file models and theme data for v2.0. The parent model must implement translatable behavior for their related file models to be translated. +v1.8.4: Fixes the multilingual mediafinder to work with the media module. +v1.8.6: Fixes invisible checkboxes when scanning for messages. +v1.8.7: Fixes Markdown editor translation. +v1.8.8: Fixes Laravel compatibility in custom Repeater. +v1.9.0: Restores ability to translate URLs with CMS Editor in October v2.0 +v1.9.1: Minor styling improvements +v1.9.2: Fixes issue creating new content in CMS Editor +v1.9.3: Improves support when using child themes +v1.10.0: Adds new multilingual nested form widget. Adds withFallbackLocale method. +v1.10.1: Improve support with October v2.0 +v1.10.2: Improve support with October v2.2 +v1.10.3: Multilingual control improvements +v1.10.4: Improve media finder support with October v2.2 +v1.10.5: Fixes media finder when only 1 locale is available +v1.11.0: Update to latest Media Finder changes in October v2.2 +v1.11.1: Improve support with October v3.0 +v1.12.0: Adds scopeTransWhereNoFallback method diff --git a/storage/.gitignore b/storage/.gitignore new file mode 100644 index 0000000..9b1dffd --- /dev/null +++ b/storage/.gitignore @@ -0,0 +1 @@ +*.sqlite diff --git a/storage/app/.gitignore b/storage/app/.gitignore new file mode 100644 index 0000000..8dcd22f --- /dev/null +++ b/storage/app/.gitignore @@ -0,0 +1,5 @@ +* +!.gitignore +!media +!uploads +!resources diff --git a/storage/app/media/.gitignore b/storage/app/media/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/app/media/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/app/resources/.gitignore b/storage/app/resources/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/app/resources/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/app/uploads/.gitignore b/storage/app/uploads/.gitignore new file mode 100644 index 0000000..3984efe --- /dev/null +++ b/storage/app/uploads/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!public diff --git a/storage/app/uploads/public/.gitignore b/storage/app/uploads/public/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/app/uploads/public/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/cms/.gitignore b/storage/cms/.gitignore new file mode 100644 index 0000000..cde8069 --- /dev/null +++ b/storage/cms/.gitignore @@ -0,0 +1 @@ +*.php diff --git a/storage/cms/cache/.gitignore b/storage/cms/cache/.gitignore new file mode 100644 index 0000000..c96a04f --- /dev/null +++ b/storage/cms/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/storage/cms/combiner/.gitignore b/storage/cms/combiner/.gitignore new file mode 100644 index 0000000..c96a04f --- /dev/null +++ b/storage/cms/combiner/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/storage/cms/twig/.gitignore b/storage/cms/twig/.gitignore new file mode 100644 index 0000000..c96a04f --- /dev/null +++ b/storage/cms/twig/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/storage/framework/.gitignore b/storage/framework/.gitignore new file mode 100644 index 0000000..cde8069 --- /dev/null +++ b/storage/framework/.gitignore @@ -0,0 +1 @@ +*.php diff --git a/storage/framework/cache/.gitignore b/storage/framework/cache/.gitignore new file mode 100644 index 0000000..01e4a6c --- /dev/null +++ b/storage/framework/cache/.gitignore @@ -0,0 +1,3 @@ +* +!data/ +!.gitignore diff --git a/storage/framework/sessions/.gitignore b/storage/framework/sessions/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/sessions/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/framework/views/.gitignore b/storage/framework/views/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/views/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/logs/.gitignore b/storage/logs/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/logs/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/temp/.gitignore b/storage/temp/.gitignore new file mode 100644 index 0000000..3984efe --- /dev/null +++ b/storage/temp/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!public diff --git a/storage/temp/public/.gitignore b/storage/temp/public/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/temp/public/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..1828e6c --- /dev/null +++ b/tests/README.md @@ -0,0 +1,99 @@ +# Plugin testing + +Plugin unit tests can be performed by running `phpunit` in the base plugin directory. + +### Creating plugin tests + +Plugins can be tested by creating a file called `phpunit.xml` in the base directory with the following content, for example, in a file **/plugins/acme/blog/phpunit.xml**: + + + + + + ./tests + + + + + + + + + +Then a **tests/** directory can be created to contain the test classes. The file structure should mimic the base directory with classes having a `Test` suffix. Using a namespace for the class is also recommended. + + 'Hi!']); + $this->assertEquals(1, $post->id); + } + } + +The test class should extend the base class `PluginTestCase` and this is a special class that will set up the October database stored in memory, as part of the `setUp` method. It will also refresh the plugin being tested, along with any of the defined dependencies in the plugin registration file. This is the equivalent of running the following before each test: + + php artisan october:up + php artisan plugin:refresh Acme.Blog + [php artisan plugin:refresh , ...] + +> **Note:** If your plugin uses [configuration files](../plugin/settings#file-configuration), then you will need to run `System\Classes\PluginManager::instance()->registerAll(true);` in the `setUp` method of your tests. Below is an example of a base test case class that should be used if you need to test your plugin working with other plugins instead of in isolation. + + use System\Classes\PluginManager; + + class BaseTestCase extends PluginTestCase + { + public function setUp(): void + { + parent::setUp(); + + // Get the plugin manager + $pluginManager = PluginManager::instance(); + + // Register the plugins to make features like file configuration available + $pluginManager->registerAll(true); + + // Boot all the plugins to test with dependencies of this plugin + $pluginManager->bootAll(true); + } + + public function tearDown(): void + { + parent::tearDown(); + + // Get the plugin manager + $pluginManager = PluginManager::instance(); + + // Ensure that plugins are registered again for the next test + $pluginManager->unregisterAll(); + } + } + +#### Changing database engine for plugins tests + +By default OctoberCMS uses SQLite stored in memory for the plugin testing environment. If you want to override the default behavior set the `useConfigForTesting` config to `true` in your `/config/database.php` file. When the `APP_ENV` is `testing` and the `useConfigForTesting` is `true` database parameters will be taken from `/config/database.php`. + +You can override the `/config/database.php` file by creating `/config/testing/database.php`. In this case variables from the latter file will be taken. + +## System testing + +To perform unit testing on the core October files, you should download a development copy using composer or cloning the git repo. This will ensure you have the `tests/` directory. + +### Unit tests + +Unit tests can be performed by running `phpunit` in the root directory or inside `/tests/unit`. diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..4fe5ab5 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,3 @@ + + + +Combined stylesheets: + + + +> **Note**: October also includes an SCSS compiler, if you prefer. + +Uncombined JavaScript: + + + + + {% framework extras turbo %} + +Combined JavaScript: + + + +> **Important**: Make sure you keep the `{% styles %}` and `{% scripts %}` placeholder tags as these are used by plugins for injecting assets. diff --git a/themes/demo/assets/images/about-chart.png b/themes/demo/assets/images/about-chart.png new file mode 100644 index 0000000..afdfe18 Binary files /dev/null and b/themes/demo/assets/images/about-chart.png differ diff --git a/themes/demo/assets/images/about-team.png b/themes/demo/assets/images/about-team.png new file mode 100644 index 0000000..92092f7 Binary files /dev/null and b/themes/demo/assets/images/about-team.png differ diff --git a/themes/demo/assets/images/avatars/avatar-1.png b/themes/demo/assets/images/avatars/avatar-1.png new file mode 100644 index 0000000..75fcbe7 Binary files /dev/null and b/themes/demo/assets/images/avatars/avatar-1.png differ diff --git a/themes/demo/assets/images/avatars/avatar-2.png b/themes/demo/assets/images/avatars/avatar-2.png new file mode 100644 index 0000000..1e22634 Binary files /dev/null and b/themes/demo/assets/images/avatars/avatar-2.png differ diff --git a/themes/demo/assets/images/avatars/avatar-3.png b/themes/demo/assets/images/avatars/avatar-3.png new file mode 100644 index 0000000..af348b1 Binary files /dev/null and b/themes/demo/assets/images/avatars/avatar-3.png differ diff --git a/themes/demo/assets/images/avatars/avatar-4.png b/themes/demo/assets/images/avatars/avatar-4.png new file mode 100644 index 0000000..7b66771 Binary files /dev/null and b/themes/demo/assets/images/avatars/avatar-4.png differ diff --git a/themes/demo/assets/images/avatars/avatar-5.png b/themes/demo/assets/images/avatars/avatar-5.png new file mode 100644 index 0000000..c5977f0 Binary files /dev/null and b/themes/demo/assets/images/avatars/avatar-5.png differ diff --git a/themes/demo/assets/images/calculator.png b/themes/demo/assets/images/calculator.png new file mode 100644 index 0000000..ef87818 Binary files /dev/null and b/themes/demo/assets/images/calculator.png differ diff --git a/themes/demo/assets/images/cms-template-diagram.png b/themes/demo/assets/images/cms-template-diagram.png new file mode 100644 index 0000000..45614e9 Binary files /dev/null and b/themes/demo/assets/images/cms-template-diagram.png differ diff --git a/themes/demo/assets/images/cms-template-diagram@2x.png b/themes/demo/assets/images/cms-template-diagram@2x.png new file mode 100644 index 0000000..35583e7 Binary files /dev/null and b/themes/demo/assets/images/cms-template-diagram@2x.png differ diff --git a/themes/demo/assets/images/code-tab.png b/themes/demo/assets/images/code-tab.png new file mode 100644 index 0000000..1d8d3f8 Binary files /dev/null and b/themes/demo/assets/images/code-tab.png differ diff --git a/themes/demo/assets/images/components.png b/themes/demo/assets/images/components.png new file mode 100644 index 0000000..04592b6 Binary files /dev/null and b/themes/demo/assets/images/components.png differ diff --git a/themes/demo/assets/images/contact-image.png b/themes/demo/assets/images/contact-image.png new file mode 100644 index 0000000..fea1796 Binary files /dev/null and b/themes/demo/assets/images/contact-image.png differ diff --git a/themes/demo/assets/images/default-avatar.png b/themes/demo/assets/images/default-avatar.png new file mode 100644 index 0000000..4cafcf2 Binary files /dev/null and b/themes/demo/assets/images/default-avatar.png differ diff --git a/themes/demo/assets/images/default-post.png b/themes/demo/assets/images/default-post.png new file mode 100644 index 0000000..b8c902e Binary files /dev/null and b/themes/demo/assets/images/default-post.png differ diff --git a/themes/demo/assets/images/footer-waves.svg b/themes/demo/assets/images/footer-waves.svg new file mode 100644 index 0000000..85d97a2 --- /dev/null +++ b/themes/demo/assets/images/footer-waves.svg @@ -0,0 +1,7 @@ + + + footer-waves + + + + \ No newline at end of file diff --git a/themes/demo/assets/images/home-waves-dark.svg b/themes/demo/assets/images/home-waves-dark.svg new file mode 100644 index 0000000..d9119af --- /dev/null +++ b/themes/demo/assets/images/home-waves-dark.svg @@ -0,0 +1,7 @@ + + + home-waves-dark + + + + \ No newline at end of file diff --git a/themes/demo/assets/images/homepage-about-page.png b/themes/demo/assets/images/homepage-about-page.png new file mode 100644 index 0000000..bb056b0 Binary files /dev/null and b/themes/demo/assets/images/homepage-about-page.png differ diff --git a/themes/demo/assets/images/homepage-header-image.png b/themes/demo/assets/images/homepage-header-image.png new file mode 100644 index 0000000..351458c Binary files /dev/null and b/themes/demo/assets/images/homepage-header-image.png differ diff --git a/themes/demo/assets/images/icons/icon-address.png b/themes/demo/assets/images/icons/icon-address.png new file mode 100644 index 0000000..fedd5cf Binary files /dev/null and b/themes/demo/assets/images/icons/icon-address.png differ diff --git a/themes/demo/assets/images/icons/icon-assets.png b/themes/demo/assets/images/icons/icon-assets.png new file mode 100644 index 0000000..941434a Binary files /dev/null and b/themes/demo/assets/images/icons/icon-assets.png differ diff --git a/themes/demo/assets/images/icons/icon-basket.png b/themes/demo/assets/images/icons/icon-basket.png new file mode 100644 index 0000000..33b95ea Binary files /dev/null and b/themes/demo/assets/images/icons/icon-basket.png differ diff --git a/themes/demo/assets/images/icons/icon-briefcase.png b/themes/demo/assets/images/icons/icon-briefcase.png new file mode 100644 index 0000000..6e02183 Binary files /dev/null and b/themes/demo/assets/images/icons/icon-briefcase.png differ diff --git a/themes/demo/assets/images/icons/icon-calendar.png b/themes/demo/assets/images/icons/icon-calendar.png new file mode 100644 index 0000000..8cf5bb7 Binary files /dev/null and b/themes/demo/assets/images/icons/icon-calendar.png differ diff --git a/themes/demo/assets/images/icons/icon-check.png b/themes/demo/assets/images/icons/icon-check.png new file mode 100644 index 0000000..cc7520e Binary files /dev/null and b/themes/demo/assets/images/icons/icon-check.png differ diff --git a/themes/demo/assets/images/icons/icon-collapse.png b/themes/demo/assets/images/icons/icon-collapse.png new file mode 100644 index 0000000..3811b00 Binary files /dev/null and b/themes/demo/assets/images/icons/icon-collapse.png differ diff --git a/themes/demo/assets/images/icons/icon-contentblocks.png b/themes/demo/assets/images/icons/icon-contentblocks.png new file mode 100644 index 0000000..e1d71c8 Binary files /dev/null and b/themes/demo/assets/images/icons/icon-contentblocks.png differ diff --git a/themes/demo/assets/images/icons/icon-email.png b/themes/demo/assets/images/icons/icon-email.png new file mode 100644 index 0000000..c5cd353 Binary files /dev/null and b/themes/demo/assets/images/icons/icon-email.png differ diff --git a/themes/demo/assets/images/icons/icon-keyboard-return.png b/themes/demo/assets/images/icons/icon-keyboard-return.png new file mode 100644 index 0000000..09777f3 Binary files /dev/null and b/themes/demo/assets/images/icons/icon-keyboard-return.png differ diff --git a/themes/demo/assets/images/icons/icon-layouts.png b/themes/demo/assets/images/icons/icon-layouts.png new file mode 100644 index 0000000..07d2d93 Binary files /dev/null and b/themes/demo/assets/images/icons/icon-layouts.png differ diff --git a/themes/demo/assets/images/icons/icon-notepad.png b/themes/demo/assets/images/icons/icon-notepad.png new file mode 100644 index 0000000..553d8b7 Binary files /dev/null and b/themes/demo/assets/images/icons/icon-notepad.png differ diff --git a/themes/demo/assets/images/icons/icon-pages.png b/themes/demo/assets/images/icons/icon-pages.png new file mode 100644 index 0000000..f7a5743 Binary files /dev/null and b/themes/demo/assets/images/icons/icon-pages.png differ diff --git a/themes/demo/assets/images/icons/icon-pagination-arrow.png b/themes/demo/assets/images/icons/icon-pagination-arrow.png new file mode 100644 index 0000000..e58b4f1 Binary files /dev/null and b/themes/demo/assets/images/icons/icon-pagination-arrow.png differ diff --git a/themes/demo/assets/images/icons/icon-partials.png b/themes/demo/assets/images/icons/icon-partials.png new file mode 100644 index 0000000..b40ffdf Binary files /dev/null and b/themes/demo/assets/images/icons/icon-partials.png differ diff --git a/themes/demo/assets/images/icons/icon-phone.png b/themes/demo/assets/images/icons/icon-phone.png new file mode 100644 index 0000000..7566bbd Binary files /dev/null and b/themes/demo/assets/images/icons/icon-phone.png differ diff --git a/themes/demo/assets/images/icons/icon-placeholders.png b/themes/demo/assets/images/icons/icon-placeholders.png new file mode 100644 index 0000000..b705d64 Binary files /dev/null and b/themes/demo/assets/images/icons/icon-placeholders.png differ diff --git a/themes/demo/assets/images/icons/icon-search.png b/themes/demo/assets/images/icons/icon-search.png new file mode 100644 index 0000000..94464d6 Binary files /dev/null and b/themes/demo/assets/images/icons/icon-search.png differ diff --git a/themes/demo/assets/images/icons/icon-share.png b/themes/demo/assets/images/icons/icon-share.png new file mode 100644 index 0000000..fe6cc78 Binary files /dev/null and b/themes/demo/assets/images/icons/icon-share.png differ diff --git a/themes/demo/assets/images/icons/icon-shield.png b/themes/demo/assets/images/icons/icon-shield.png new file mode 100644 index 0000000..57e1c8d Binary files /dev/null and b/themes/demo/assets/images/icons/icon-shield.png differ diff --git a/themes/demo/assets/images/icons/icon-tick.png b/themes/demo/assets/images/icons/icon-tick.png new file mode 100644 index 0000000..68d4152 Binary files /dev/null and b/themes/demo/assets/images/icons/icon-tick.png differ diff --git a/themes/demo/assets/images/icons/icon-todo.png b/themes/demo/assets/images/icons/icon-todo.png new file mode 100644 index 0000000..bf2045e Binary files /dev/null and b/themes/demo/assets/images/icons/icon-todo.png differ diff --git a/themes/demo/assets/images/icons/icon-user.png b/themes/demo/assets/images/icons/icon-user.png new file mode 100644 index 0000000..a8e4908 Binary files /dev/null and b/themes/demo/assets/images/icons/icon-user.png differ diff --git a/themes/demo/assets/images/landing-page-slice.svg b/themes/demo/assets/images/landing-page-slice.svg new file mode 100644 index 0000000..552cd8b --- /dev/null +++ b/themes/demo/assets/images/landing-page-slice.svg @@ -0,0 +1,3 @@ + + + diff --git a/themes/demo/assets/images/layouts-image.png b/themes/demo/assets/images/layouts-image.png new file mode 100644 index 0000000..25ccec8 Binary files /dev/null and b/themes/demo/assets/images/layouts-image.png differ diff --git a/themes/demo/assets/images/leaf.png b/themes/demo/assets/images/leaf.png new file mode 100644 index 0000000..0410d20 Binary files /dev/null and b/themes/demo/assets/images/leaf.png differ diff --git a/themes/demo/assets/images/logo.svg b/themes/demo/assets/images/logo.svg new file mode 100644 index 0000000..1687240 --- /dev/null +++ b/themes/demo/assets/images/logo.svg @@ -0,0 +1,27 @@ + + + logo + + + + + + + + + \ No newline at end of file diff --git a/themes/demo/assets/images/october.png b/themes/demo/assets/images/october.png new file mode 100644 index 0000000..bb6415d Binary files /dev/null and b/themes/demo/assets/images/october.png differ diff --git a/themes/demo/assets/images/pages-image.png b/themes/demo/assets/images/pages-image.png new file mode 100644 index 0000000..9488ffd Binary files /dev/null and b/themes/demo/assets/images/pages-image.png differ diff --git a/themes/demo/assets/images/partials-image.png b/themes/demo/assets/images/partials-image.png new file mode 100644 index 0000000..aa1923b Binary files /dev/null and b/themes/demo/assets/images/partials-image.png differ diff --git a/themes/demo/assets/images/platform-demo.png b/themes/demo/assets/images/platform-demo.png new file mode 100644 index 0000000..739ec6d Binary files /dev/null and b/themes/demo/assets/images/platform-demo.png differ diff --git a/themes/demo/assets/images/social-icons-share/facebook.png b/themes/demo/assets/images/social-icons-share/facebook.png new file mode 100644 index 0000000..4b1ad83 Binary files /dev/null and b/themes/demo/assets/images/social-icons-share/facebook.png differ diff --git a/themes/demo/assets/images/social-icons-share/linkedin.png b/themes/demo/assets/images/social-icons-share/linkedin.png new file mode 100644 index 0000000..c8ccbff Binary files /dev/null and b/themes/demo/assets/images/social-icons-share/linkedin.png differ diff --git a/themes/demo/assets/images/social-icons-share/twitter.png b/themes/demo/assets/images/social-icons-share/twitter.png new file mode 100644 index 0000000..f54d47a Binary files /dev/null and b/themes/demo/assets/images/social-icons-share/twitter.png differ diff --git a/themes/demo/assets/images/social-icons-white/dribbble-white.png b/themes/demo/assets/images/social-icons-white/dribbble-white.png new file mode 100644 index 0000000..50327bc Binary files /dev/null and b/themes/demo/assets/images/social-icons-white/dribbble-white.png differ diff --git a/themes/demo/assets/images/social-icons-white/facebook-white.png b/themes/demo/assets/images/social-icons-white/facebook-white.png new file mode 100644 index 0000000..d4bc8dd Binary files /dev/null and b/themes/demo/assets/images/social-icons-white/facebook-white.png differ diff --git a/themes/demo/assets/images/social-icons-white/linkedin-white.png b/themes/demo/assets/images/social-icons-white/linkedin-white.png new file mode 100644 index 0000000..0a3dc4d Binary files /dev/null and b/themes/demo/assets/images/social-icons-white/linkedin-white.png differ diff --git a/themes/demo/assets/images/social-icons-white/twitter-white.png b/themes/demo/assets/images/social-icons-white/twitter-white.png new file mode 100644 index 0000000..098bc09 Binary files /dev/null and b/themes/demo/assets/images/social-icons-white/twitter-white.png differ diff --git a/themes/demo/assets/images/social-icons/dribbble.png b/themes/demo/assets/images/social-icons/dribbble.png new file mode 100644 index 0000000..8b31568 Binary files /dev/null and b/themes/demo/assets/images/social-icons/dribbble.png differ diff --git a/themes/demo/assets/images/social-icons/facebook.png b/themes/demo/assets/images/social-icons/facebook.png new file mode 100644 index 0000000..9679340 Binary files /dev/null and b/themes/demo/assets/images/social-icons/facebook.png differ diff --git a/themes/demo/assets/images/social-icons/linkedin.png b/themes/demo/assets/images/social-icons/linkedin.png new file mode 100644 index 0000000..c54df29 Binary files /dev/null and b/themes/demo/assets/images/social-icons/linkedin.png differ diff --git a/themes/demo/assets/images/social-icons/rss.png b/themes/demo/assets/images/social-icons/rss.png new file mode 100644 index 0000000..5f21240 Binary files /dev/null and b/themes/demo/assets/images/social-icons/rss.png differ diff --git a/themes/demo/assets/images/social-icons/twitter.png b/themes/demo/assets/images/social-icons/twitter.png new file mode 100644 index 0000000..d36e0c5 Binary files /dev/null and b/themes/demo/assets/images/social-icons/twitter.png differ diff --git a/themes/demo/assets/images/social-icons/youtube.png b/themes/demo/assets/images/social-icons/youtube.png new file mode 100644 index 0000000..fa6cdf6 Binary files /dev/null and b/themes/demo/assets/images/social-icons/youtube.png differ diff --git a/themes/demo/assets/images/stock/desks-cropped.png b/themes/demo/assets/images/stock/desks-cropped.png new file mode 100644 index 0000000..266a636 Binary files /dev/null and b/themes/demo/assets/images/stock/desks-cropped.png differ diff --git a/themes/demo/assets/images/stock/desks.png b/themes/demo/assets/images/stock/desks.png new file mode 100644 index 0000000..3c3143e Binary files /dev/null and b/themes/demo/assets/images/stock/desks.png differ diff --git a/themes/demo/assets/images/stock/desktop.png b/themes/demo/assets/images/stock/desktop.png new file mode 100644 index 0000000..79c3bae Binary files /dev/null and b/themes/demo/assets/images/stock/desktop.png differ diff --git a/themes/demo/assets/images/stock/doughnuts.png b/themes/demo/assets/images/stock/doughnuts.png new file mode 100644 index 0000000..8742b7a Binary files /dev/null and b/themes/demo/assets/images/stock/doughnuts.png differ diff --git a/themes/demo/assets/images/stock/pancakes.png b/themes/demo/assets/images/stock/pancakes.png new file mode 100644 index 0000000..b50dc9f Binary files /dev/null and b/themes/demo/assets/images/stock/pancakes.png differ diff --git a/themes/demo/assets/images/stock/workspace.png b/themes/demo/assets/images/stock/workspace.png new file mode 100644 index 0000000..fe61889 Binary files /dev/null and b/themes/demo/assets/images/stock/workspace.png differ diff --git a/themes/demo/assets/images/theme-preview.png b/themes/demo/assets/images/theme-preview.png new file mode 100644 index 0000000..5af698a Binary files /dev/null and b/themes/demo/assets/images/theme-preview.png differ diff --git a/themes/demo/assets/images/waves/footer-blue-wave.svg b/themes/demo/assets/images/waves/footer-blue-wave.svg new file mode 100644 index 0000000..b8e8e50 --- /dev/null +++ b/themes/demo/assets/images/waves/footer-blue-wave.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/themes/demo/assets/images/waves/footer-wave.svg b/themes/demo/assets/images/waves/footer-wave.svg new file mode 100644 index 0000000..a5b0cf7 --- /dev/null +++ b/themes/demo/assets/images/waves/footer-wave.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/themes/demo/assets/images/waves/header-wave.svg b/themes/demo/assets/images/waves/header-wave.svg new file mode 100644 index 0000000..9ac7319 --- /dev/null +++ b/themes/demo/assets/images/waves/header-wave.svg @@ -0,0 +1,4 @@ + + + + diff --git a/themes/demo/assets/js/app.js b/themes/demo/assets/js/app.js new file mode 100644 index 0000000..5668a83 --- /dev/null +++ b/themes/demo/assets/js/app.js @@ -0,0 +1,33 @@ +addEventListener('render', function() { + + // Auto Collapsed List + // + $('ul.bullet-list li.active:first').each(function() { + $(this).parents('ul.collapse').each(function() { + $(this).addClass('show').prevAll('.collapse-caret:first').removeClass('collapsed'); + }); + }); + + // Popovers + // + $('[data-bs-toggle="popover"]').each(function() { + var $el = $(this); + if ($el.data('content-target')) { + $el + .popover({ html: true, content: $($el.data('content-target')).get(0) }) + .on('shown.bs.popover', function() { + $('input:first', $($el.data('content-target'))).focus(); + }) + ; + } + else { + $el.popover(); + } + }); + + // How it is made + // + setTimeout(function() { + $('.how-its-made').removeClass('init'); + }, 1); +}); diff --git a/themes/demo/assets/js/blocks/team-leaders.js b/themes/demo/assets/js/blocks/team-leaders.js new file mode 100644 index 0000000..c1dd267 --- /dev/null +++ b/themes/demo/assets/js/blocks/team-leaders.js @@ -0,0 +1,36 @@ +$(document).on('render', function() { + $('[data-control="team-leaders"]').each(function() { + $(this).slick({ + dots: true, + infinite: false, + speed: 300, + slidesToShow: 4, + slidesToScroll: 4, + responsive: [ + { + breakpoint: 1200, + settings: { + slidesToShow: 3, + slidesToScroll: 3, + infinite: true, + dots: true + } + }, + { + breakpoint: 992, + settings: { + slidesToShow: 2, + slidesToScroll: 2 + } + }, + { + breakpoint: 576, + settings: { + slidesToShow: 1, + slidesToScroll: 1 + } + } + ] + }); + }); +}); diff --git a/themes/demo/assets/js/controls/image-carousel.js b/themes/demo/assets/js/controls/image-carousel.js new file mode 100644 index 0000000..c94619e --- /dev/null +++ b/themes/demo/assets/js/controls/image-carousel.js @@ -0,0 +1,56 @@ +$(document).on('render', function() { + $('[data-control="image-carousel"]').each(function () { + var carousel = this; + + $(this).slick({ + dots: true, + infinite: false, + speed: 300, + slidesToShow: 3, + slidesToScroll: 3, + responsive: [ + { + breakpoint: 992, + settings: { + slidesToShow: 2, + slidesToScroll: 2 + } + }, + { + breakpoint: 576, + settings: { + slidesToShow: 1, + slidesToScroll: 1 + } + } + ] + }); + + setTimeout(function () { + var links = $('.slick-slide a', carousel); + links.each(function () { + var image = new Image(), + link = this; + + image.src = this.getAttribute('href'); + image.onload = function () { + link.setAttribute('data-pswp-width', image.naturalWidth); + link.setAttribute('data-pswp-height', image.naturalHeight); + }; + }); + }, 1); + + var lightbox = new PhotoSwipeLightbox({ + gallery: this, + children: '.slick-slide', + pswpModule: PhotoSwipeModule, + showHideAnimationType: 'none' + }); + + new PhotoSwipeDynamicCaption(lightbox, { + type: 'auto' + }); + + lightbox.init(); + }); +}); diff --git a/themes/demo/assets/less/blocks/hero-image.less b/themes/demo/assets/less/blocks/hero-image.less new file mode 100644 index 0000000..3d3e46f --- /dev/null +++ b/themes/demo/assets/less/blocks/hero-image.less @@ -0,0 +1,21 @@ +.block-hero-image { + background-size: 125%; + background-position: 45% 25%; + background-repeat: no-repeat; + height: 520px; + position: relative; + + &:after { + content: ''; + position: absolute; + left: 0; + bottom: -3px; + height: 120px; + width: 100%; + z-index: 1; + background-image: url('../../images/landing-page-slice.svg'); + background-repeat: no-repeat; + background-position: left bottom; + background-size: 100%; + } +} diff --git a/themes/demo/assets/less/blocks/scoreboard-metrics.less b/themes/demo/assets/less/blocks/scoreboard-metrics.less new file mode 100644 index 0000000..34f35f1 --- /dev/null +++ b/themes/demo/assets/less/blocks/scoreboard-metrics.less @@ -0,0 +1,16 @@ +.block-scoreboard-metrics { + background: linear-gradient(102.01deg, #eff4fd 0.3%, #f6f2ff 106.31%); + + .metrics { + .metric { + padding: 60px 0; + h3 { + font-weight: 700; + font-size: 40px; + margin-bottom: 5px; + } + + text-align: center; + } + } +} diff --git a/themes/demo/assets/less/blocks/team-leaders.less b/themes/demo/assets/less/blocks/team-leaders.less new file mode 100644 index 0000000..b7f5eae --- /dev/null +++ b/themes/demo/assets/less/blocks/team-leaders.less @@ -0,0 +1,33 @@ +.block-team-leaders { + position: relative; + + .team-leaders { + white-space: nowrap; + + .slick-list { + padding: 30px; + margin-top: -30px; + margin-bottom: -30px; + margin-left: -30px; + margin-right: -30px; + } + + .slick-arrow { + display: none!important; + } + + .team-member-container { + padding: 0 15px; + + .team-member { + white-space: normal; + } + } + + .slick-dots { + li.slick-active button:before { + font-size: 10px; + } + } + } +} \ No newline at end of file diff --git a/themes/demo/assets/less/controls/example.less b/themes/demo/assets/less/controls/example.less new file mode 100644 index 0000000..fb33baf --- /dev/null +++ b/themes/demo/assets/less/controls/example.less @@ -0,0 +1,5 @@ +// +// Example control +// + +.example-control {} diff --git a/themes/demo/assets/less/controls/image-carousel.less b/themes/demo/assets/less/controls/image-carousel.less new file mode 100644 index 0000000..36afbfc --- /dev/null +++ b/themes/demo/assets/less/controls/image-carousel.less @@ -0,0 +1,23 @@ +[data-control=image-carousel] { + margin-left: -10px; + margin-right: -10px; + + .slick-slide { + padding: 10px; + outline: none; + + .image-container { + a { + display: block; + overflow: hidden; + border-radius: 6px; + box-shadow: 0 0 10px rgba(129, 138, 166, 0.21); + outline: none; + + img { + max-width: 100%; + } + } + } + } +} \ No newline at end of file diff --git a/themes/demo/assets/less/elements/buttons.less b/themes/demo/assets/less/elements/buttons.less new file mode 100644 index 0000000..8660fc0 --- /dev/null +++ b/themes/demo/assets/less/elements/buttons.less @@ -0,0 +1,72 @@ +.btn:hover, .btn:focus, .btn.focus { + text-decoration: none; +} + +.btn { + &.btn-pill { + border-radius: 100px; + padding-left: 25px; + padding-right: 25px; + } + + &.btn-primary { + &:not(:hover):not(:active) { + border-color: transparent; + background: linear-gradient(102.01deg, #5799EB 0.3%, #9F74FB 106.31%); + } + } +} + +.share-button { + display: inline-block; + + .btn { + position: relative; + padding-left: 47px; + padding-right: 25px; + + &:before { + content: ""; + position: absolute; + left: 17px; + top: 12px; + width: 14px; + height: 14px; + background-repeat: no-repeat; + background-size: 14px 14px; + background-image: url('@{assets-url}/images/icons/icon-share.png'); + } + + &.btn-sm { + padding-left: 37px; + padding-right: 15px; + + &:before { + left: 12px; + top: 7px; + } + } + } +} + +.share-button-popover { + padding: 0; + margin: -1rem; + overflow: hidden; + border-radius: 8px; + + .nav-link { + padding: 10px 15px; + + color: #343F52; + text-decoration: none; + > i { + margin-right: 5px; + } + + &:hover { + color: #fff; + background: @brand-primary; + } + } +} diff --git a/themes/demo/assets/less/elements/callouts.less b/themes/demo/assets/less/elements/callouts.less new file mode 100644 index 0000000..0ee5734 --- /dev/null +++ b/themes/demo/assets/less/elements/callouts.less @@ -0,0 +1,48 @@ +// +// Callouts +// -------------------------------------------------- + +.callout { + margin-bottom: 20px; + padding: @callout-padding; + border-left: 3px solid @callout-border; + h4 { + margin-top: 0; + margin-bottom: 5px; + } + p:last-child { + margin-bottom: 0; + } +} + +.callout-danger { + background-color: @callout-danger-bg; + border-color: @callout-danger-border; + h4 { + color: @callout-danger-text; + } +} + +.callout-warning { + background-color: @callout-warning-bg; + border-color: @callout-warning-border; + h4 { + color: @callout-warning-text; + } +} + +.callout-info { + background-color: @callout-info-bg; + border-color: @callout-info-border; + h4 { + color: @callout-info-text; + } +} + +.callout-success { + background-color: @callout-success-bg; + border-color: @callout-success-border; + h4 { + color: @callout-success-text; + } +} diff --git a/themes/demo/assets/less/elements/card.less b/themes/demo/assets/less/elements/card.less new file mode 100644 index 0000000..9f2730e --- /dev/null +++ b/themes/demo/assets/less/elements/card.less @@ -0,0 +1,82 @@ +.card { + border-radius: 13px; + box-shadow: 0px 0px 22px rgba(0, 0, 0, 0.07); + border-color: #EBEBEB; + overflow: hidden; + + .card-banner { + width: 100%; + height: 191px; + background-position: center center; + background-size: cover; + + &.banner-lg { + height: 268px; + } + } + + .card-divider { + padding: 1.5rem; + + &:after { + content: ''; + border-bottom: 1px solid #EBEBEB; + display: block; + } + } + + .card-body { + padding: 1.5rem; + + &.card-lg { + padding-right: 2.5rem; + padding-left: 2.5rem; + } + } + + .card-footer { + background-color: #fff; + padding: 1rem 1.5rem; + border-bottom-left-radius: 13px; + border-bottom-right-radius: 13px; + } +} + +.post-card { + &.card-primary { + margin-bottom: -25px; + position: relative; + z-index: 3; + } + + .blog-post-title { + a { + color: #000; + text-decoration: none; + } + } + + .blog-post-featured-text { + p:last-child { + margin-bottom: 0; + } + } + + .blog-post-share-button { + margin-top: -5px; + } + + .blog-post-meta { + .meta-item { + display: inline-block; + position: relative; + color: #A2A2A2; + font-size: 14px; + } + + .meta-divider { + width: 20px; + text-align: center; + } + } +} diff --git a/themes/demo/assets/less/elements/code.less b/themes/demo/assets/less/elements/code.less new file mode 100644 index 0000000..71b4f98 --- /dev/null +++ b/themes/demo/assets/less/elements/code.less @@ -0,0 +1,96 @@ +pre { + padding: 0; + background-color: white; + border: 1px solid #ECF0F1; + border-radius: 6px; + + .CodeMirror { + height: auto; + color: #2C3E4F; + } + + .CodeMirror-gutters { + background: transparent; + border-right: 1px solid #ECF0F1; + } + + .CodeMirror-linenumber { + padding-right: 15px; + background: white; + } + + .CodeMirror-lines { + padding: 10px 0; + } + + .CodeMirror pre.CodeMirror-line { + padding-left: 20px; + } +} + +.collapsed-code-block { + position: relative; + + .expand-code { + display: none; + } + + &.collapsed { + margin-bottom: 36px; + + > pre { + height: 143px; + overflow: hidden; + position: relative; + } + + .expand-code { + border-radius: 20px; + user-select: none; + cursor: pointer; + display: block; + position: absolute; + bottom: -15px; + left: 50%; + font-size: 14px; + background-color: white; + border: 1px solid #ECF0F1; + z-index: 5; + transform: translateX(-50%); + padding: 4px 18px; + box-shadow: 0 0 0 3px white; + + &:hover { + color: white; + background-color: #7F8C8D; + } + } + } +} + +.code-tab { + display: inline-block; + font-size: 14px; + padding: 8px 0 0 13px; + position: relative; + + &, &:after { + height: 38px; + background: url('@{assets-url}/images/code-tab.png') no-repeat 0 0; + background-size: 335px 38px; + } + + &:after { + content: ''; + width: 34px; + display: block; + position: absolute; + right: -34px; + top: 0; + background-position: right top; + } + + + pre { + border-radius: 0 6px 6px 6px; + } +} diff --git a/themes/demo/assets/less/elements/footer.less b/themes/demo/assets/less/elements/footer.less new file mode 100644 index 0000000..bb1b2ea --- /dev/null +++ b/themes/demo/assets/less/elements/footer.less @@ -0,0 +1,108 @@ +// Extend footer to the entire page +body > * { + background: #fff; +} + +body, .element-footer { + background: linear-gradient(97.23deg, #2D8BFF -7.32%, #9F74FB 106.79%); +} + +.element-footer { + position: relative; + overflow: hidden; + min-height: 298px; + padding-top: 70px; + z-index: 1; + + &:before { + content: ''; + position: absolute; + width: 100%; + height: 106px; + background: url('@{assets-url}/images/waves/footer-wave.svg') repeat-x 0 0; + background-repeat: repeat-x; + z-index: 1; + top: -1px; + } + + &.footer-bluezone:before { + background: url('@{assets-url}/images/waves/footer-blue-wave.svg') repeat-x 0 0; + } + + > .container { + position: relative; + padding: 30px 0; + color: #fff; + z-index: 2; + } + + // Decorations + .footer-decoration-1 { + .decoration-circle(); + width: 524px; + height: 524px; + left: -42px; + top: 120px; + opacity: .02; + } + + .footer-decoration-2 { + .decoration-circle(); + width: 524px; + height: 524px; + right: -150px; + top: -160px; + opacity: .05; + } + + .footer-nav { + padding-bottom: 22px; + + .nav { + padding-right: 50px; + + .nav-item { + font-size: 16px; + + &.nav-item-header > a { + font-weight: 700; + } + + > a { + color: #fff; + padding: 4px 0; + } + } + } + } + + .footer-brand { + padding: 32px 0; + } + + .footer-social .nav { + .nav-item { + &:first-child > a { + padding-left: 0; + } + + img { + height: 28px; + } + } + } + + .footer-copyright { + text-align: right; + p { + margin: 0; + padding: 0; + line-height: 28px; + } + } + + @media (max-width: @screen-sm-max) { + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/themes/demo/assets/less/elements/form.less b/themes/demo/assets/less/elements/form.less new file mode 100644 index 0000000..8516b2a --- /dev/null +++ b/themes/demo/assets/less/elements/form.less @@ -0,0 +1,26 @@ + +.form-control { + border-color: @input-border-color; + box-shadow: 0px 0px 23px rgba(129, 138, 166, 0.1); + border-radius: 0.7rem; +} + +.form-control-search { + width: 100%; + + input { + padding: 8px 38px 8px 18px; + border-radius: 100px; + } + + .search-icon { + position: absolute; + right: 18px; + top: 8px; + width: 24px; + height: 24px; + display: block; + background-image: url('@{assets-url}/images/icons/icon-search.png'); + background-size: 24px 24px; + } +} diff --git a/themes/demo/assets/less/elements/how-its-made.less b/themes/demo/assets/less/elements/how-its-made.less new file mode 100644 index 0000000..a03ab27 --- /dev/null +++ b/themes/demo/assets/less/elements/how-its-made.less @@ -0,0 +1,41 @@ +div.how-its-made { + position: fixed; + bottom: 50px; + width: 800px; + max-width: 100%; + z-index: 3; + padding: 0 30px; + margin: 0 0 0 50%; + transform: translateX(-50%) scale(1); + background-color: transparent; + transition: all 0.4s cubic-bezier(.25,-0.59,.35,1.58); + + &.init { + opacity: 0; + transform: translateX(-50%) scale(0.3); + } + + > div { + background-color: #FFE297; + box-shadow: 14px -8px 52px rgba(129, 138, 166, 0.42); + text-align: center; + padding: 10px 20px; + border-radius: 14px; + + p { + margin-bottom: 0; + + a { + color: inherit; + text-decoration: underline; + } + } + } +} + +html[data-turbo-preview] { + div.how-its-made { + opacity: 0; + transform: translateX(-50%) scale(0.3); + } +} diff --git a/themes/demo/assets/less/elements/jumbotron.less b/themes/demo/assets/less/elements/jumbotron.less new file mode 100644 index 0000000..faf7a96 --- /dev/null +++ b/themes/demo/assets/less/elements/jumbotron.less @@ -0,0 +1,62 @@ +// +// Jumbotron +// -------------------------------------------------- + +.jumbotron { + padding-top: @jumbotron-padding; + padding-bottom: @jumbotron-padding; + margin-bottom: @jumbotron-padding; + color: @jumbotron-color; + background-color: @jumbotron-bg; + + h1, + .h1 { + color: @jumbotron-heading-color; + position: relative; + padding-top: 66px; + + &:before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 46px; + height: 46px; + background-size: 46px 46px!important; + } + } + + p { + margin-top: 60px; + margin-bottom: (@jumbotron-padding / 2); + font-size: @jumbotron-font-size; + font-weight: normal; + } + + > hr { + border-top-color: darken(@jumbotron-bg, 10%); + } + + .container &, + .container-fluid & { + border-radius: @border-radius-base; + padding-left: 15px; + padding-right: 15px; + } + + @media screen and (min-width: @screen-sm-min) { + padding-top: (@jumbotron-padding * 1.6); + padding-bottom: (@jumbotron-padding * 1.6); + + .container &, + .container-fluid & { + padding-left: (@jumbotron-padding * 2); + padding-right: (@jumbotron-padding * 2); + } + + h1, + .h1 { + font-size: @jumbotron-heading-font-size; + } + } +} diff --git a/themes/demo/assets/less/elements/lists.less b/themes/demo/assets/less/elements/lists.less new file mode 100644 index 0000000..15d1c2e --- /dev/null +++ b/themes/demo/assets/less/elements/lists.less @@ -0,0 +1,67 @@ + +ul.bullet-list { + &, ul { + list-style: none; + padding: 0; + } + + li { + position: relative; + padding: 0 0 0 20px; + > a { + color: #6B7482; + } + &.active > a { + color: #8284F8; + } + } + + li:before { + content: ""; + position: absolute; + background-color: #7B61FF; + border-radius: 5px; + width: 5px; + height: 5px; + top: 11px; + left: 6px; + } + + li.collapsible { + &:before { + display: none; + } + + > .collapse-caret { + position: absolute; + display: block; + width: 20px; + height: 16px; + background-image: url('@{assets-url}/images/icons/icon-collapse.png'); + background-size: 10px 6px; + background-repeat: no-repeat; + background-position: center center; + top: 6px; + left: -1px; + &.collapsed { + transform: rotate(270deg) translate(0, 0); + } + } + } + + &.list-content { + &, ul { + padding-left: 10px; + } + + a { + color: #3097d1; + text-decoration: none; + } + + a:hover, a:focus { + color: #216a94; + text-decoration: underline; + } + } +} diff --git a/themes/demo/assets/less/elements/navbar.less b/themes/demo/assets/less/elements/navbar.less new file mode 100644 index 0000000..2aa439d --- /dev/null +++ b/themes/demo/assets/less/elements/navbar.less @@ -0,0 +1,127 @@ +.navbar { + padding-top: 15px; + padding-bottom: 15px; + + &.navbar-dark { + background-color: transparent; + } + + .navbar-brand { + margin-top: -5px; + } + + a:hover, a:focus, a.focus { + text-decoration: none; + } + + .dropdown-item.active, .dropdown-item:active { + background-color: #6bc48d; + } +} + +@media screen and (min-width: @screen-md-min) { + .navbar { + .navbar-nav > li.nav-item { + padding: 0 8px; + + > a.btn { + padding: 3px 22px; + border-radius: 100px; + font-size: 14px; + margin-top: 7px; + } + + > a.nav-link { + position: relative; + transition: color 0.2s ease 0.05s; + color: #fff; + + &:before { + position: absolute; + height: 4px; + bottom: 2px; + content: ''; + border-radius: 4px; + z-index: 5; + width: 20px; + left: 50%; + transform: translateX(-50%); + transition: all 0.2s ease 0.05s; + } + + &.active:before, + &.active:hover:before { + background: #fff; + } + + &:hover:before { + background: #fff; + } + } + } + } +} + +// Mobile Nav +.navbar-mobile { + display: none; +} + +@media (max-width: @screen-sm-max) { + .navbar-mobile { + display: block; + + .navbar-collapse { + background: #2d3134; + position: fixed; + z-index: 10001; + right: -260px; + top: 0; + bottom: 0; + width: 260px; + padding: 20px; + height: 100% !important; + box-sizing: border-box; + overflow-x: hidden; + overflow-y: auto; + text-align: left; + backface-visibility: hidden; + transform: translate3d(0, 0, 0); + transform-origin: 0 10%; + transform: perspective(1000px) scale(1.3); + transition: all 0.4s 0s ease-in; + + &.collapsing { + transition-duration: 0.1s; + } + + &.show { + transition: all 0.3s 0s ease-out; + transform: perspective(1000px) scale(1) translate3d(-260px, 0, 0); + } + } + + .navbar-toggler { + color: #fff; + padding: 10px; + opacity: .8; + + &:hover, &:focus { + opacity: 1; + } + } + + .nav-item { + .nav-link { + color: #e0e0e0; + &:hover { + color: #fff; + } + } + .btn { + margin-top: 1rem; + margin-left: 1rem; + } + } + } +} diff --git a/themes/demo/assets/less/elements/pagination.less b/themes/demo/assets/less/elements/pagination.less new file mode 100644 index 0000000..e5b48c3 --- /dev/null +++ b/themes/demo/assets/less/elements/pagination.less @@ -0,0 +1,118 @@ +// +// Base Styles +// -------------------------------------------------- + +.pagination { + display: flex; + padding-left: 0; + list-style: none; + + > .page-item { + > .page-link { + margin-left: -1px; + padding: 5px 15px; + color: #666666; + background-color: #FFFFFF; + border: 1px solid #EBEBEB; + text-decoration: none; + + &:hover { + background-color: #f0f0f0; + } + } + + &.active > .page-link { + color: #000000; + font-weight: bold; + + &:hover { + background-color: #FFFFFF; + } + } + + &.disabled > .page-link { + color: #A1A1A1; + + &:hover { + background-color: #FFFFFF; + } + } + } +} + +// +// Custom Styles +// -------------------------------------------------- + +.blog-pagination { + display: inline-block; + .oc-pagination { + box-shadow: 0px 0px 22px rgba(0, 0, 0, 0.07); + } +} + +ul.pagination { + > li.page-item > .page-link { + padding: 8px 15px; + color: #A1A1A1; + background: #fff; + border-color: #EBEBEB; + text-decoration: none; + + &:focus { + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); + } + } + + > li.page-item { + &.active > .page-link { + font-weight: 700; + color: #343F52; + background: #fff; + } + + &.first { + > .page-link { + border-bottom-left-radius: 0.25rem; + border-top-left-radius: 0.25rem; + } + .render-pagination-arrow(); + + > .page-link:before { + transform: scaleX(-1); + } + } + + &.last { + > .page-link { + border-bottom-right-radius: 0.25rem; + border-top-right-radius: 0.25rem; + } + .render-pagination-arrow(); + } + } +} + +.render-pagination-arrow() { + > .page-link { + position: relative; + color: #fff; + width: 44px; + + &:before { + content: ''; + display: block; + width: 15px; + height: 12.5px; + background: url('@{assets-url}/images/icons/icon-pagination-arrow.png') no-repeat 0 0; + background-size: 15px 12.5px; + position: absolute; + top: 16px; + left: 14px; + } + } + + &.disabled > .page-link:before { + opacity: .5; + } +} diff --git a/themes/demo/assets/less/elements/popover.less b/themes/demo/assets/less/elements/popover.less new file mode 100644 index 0000000..8b17a46 --- /dev/null +++ b/themes/demo/assets/less/elements/popover.less @@ -0,0 +1,9 @@ +.popover { + border: none; + box-shadow: 0px 0px 22px rgba(0, 0, 0, 0.1); + border-radius: 8px; + + .popover-arrow { + display: none; + } +} \ No newline at end of file diff --git a/themes/demo/assets/less/elements/social-links.less b/themes/demo/assets/less/elements/social-links.less new file mode 100644 index 0000000..d0b3f89 --- /dev/null +++ b/themes/demo/assets/less/elements/social-links.less @@ -0,0 +1,23 @@ +.element-social-links { + .nav { + .nav-item { + &:first-child > a { + padding-left: 0; + } + + > a { + padding-right: 8px; + padding-left: 8px; + } + + img { + height: 20px; + } + + i { + position: relative; + top: 2px; + } + } + } +} diff --git a/themes/demo/assets/less/elements/text.less b/themes/demo/assets/less/elements/text.less new file mode 100644 index 0000000..0a90fbe --- /dev/null +++ b/themes/demo/assets/less/elements/text.less @@ -0,0 +1,45 @@ +.text-muted { + color: #A2A2A2; +} + +.text-icon { + position: relative; + display: inline-block; + padding-left: 24px; + line-height: 16px; + + &:before { + content: ""; + position: absolute; + left: 0px; + top: -1px; + width: 16px; + height: 16px; + background-repeat: no-repeat; + background-size: 16px 16px; + } + + &.text-icon-date { + &:before { + background-image: url('@{assets-url}/images/icons/icon-calendar.png'); + } + } + + &.text-icon-author { + &:before { + background-image: url('@{assets-url}/images/icons/icon-user.png'); + } + } +} + +.text-banner { + border-radius: 13px; + width: 100%; + height: 191px; + background-position: center center; + background-size: cover; + + &.banner-lg { + height: 268px; + } +} diff --git a/themes/demo/assets/less/elements/user-panel.less b/themes/demo/assets/less/elements/user-panel.less new file mode 100644 index 0000000..93bea67 --- /dev/null +++ b/themes/demo/assets/less/elements/user-panel.less @@ -0,0 +1,41 @@ +.element-user-panel { + .user-avatar { + padding: 0 25px 20px 0; + + img { + width: 85px; + height: 85px; + border-radius: 100px; + } + } + + .user-details { + padding: 15px 0 0 0; + + p { + color: #A1A1A1; + } + + p:last-child { + margin-bottom: 0; + } + } + + .user-profile { + color: #6B7482; + + p:last-child { + margin-bottom: 0; + } + } + + &.team-panel { + .user-avatar { + padding-bottom: 0; + } + + .user-social { + padding-bottom: 15px; + } + } +} diff --git a/themes/demo/assets/less/layouts/blog.less b/themes/demo/assets/less/layouts/blog.less new file mode 100644 index 0000000..1ed9a15 --- /dev/null +++ b/themes/demo/assets/less/layouts/blog.less @@ -0,0 +1,28 @@ +@import "../theme/boot"; + +// +// Blog Layout Stylesheet +// + +body.blog-layout { + .sidebar-search { + padding-bottom: 40px; + } + + .sidebar-about { + font-size: 16px; + padding-bottom: 20px; + + p:last-child { + margin-bottom: 0; + } + } + + .sidebar-social { + padding-bottom: 20px; + } + + .sidebar-categories { + padding-bottom: 20px; + } +} diff --git a/themes/demo/assets/less/layouts/default.less b/themes/demo/assets/less/layouts/default.less new file mode 100644 index 0000000..fff5d8d --- /dev/null +++ b/themes/demo/assets/less/layouts/default.less @@ -0,0 +1,106 @@ +@import "../theme/boot"; + +// +// Default Layout Stylesheet (All pages) +// + +#layout-header { + &, &.navbar { + background: linear-gradient(102.01deg, #DB6A26 0.3%, #DBB326 106.31%); + } + + .header-extra { + color: #fff; + padding-top: 40px; + padding-bottom: 50px; + + h1 { + font-size: 60px; + } + p.lead { + font-size: 22px; + } + } +} + +#layout-header .navbar { + min-height: 155px; + + > .navbar-container.container { + position: relative; + z-index: 2; + } +} + +#layout-nav-decorations { + position: absolute; + z-index: 1; + top: 0; + left: 0; + right: 0; + overflow: hidden; + height: 150px; + + // Decorations + .navbar-decorations { + position: absolute; + z-index: 1; + top: 0; + bottom: 0; + left: 0; + right: 0; + } + + .navbar-decoration-1 { + .decoration-circle(); + width: 524px; + height: 524px; + left: -105px; + top: -420px; + opacity: .04; + } + + .navbar-decoration-2 { + .decoration-circle(); + width: 524px; + height: 524px; + left: 548px; + top: -385px; + opacity: .05; + } +} + + +#layout-content { + padding-top: 30px; + + header { + padding: 0 0 30px 0; + } + + main.header-flush { + margin-top: -30px; + } +} + +ul.list-with-ticks { + padding: 0; + + li { + list-style: none; + position: relative; + padding-left: 23px; + + &:before { + content: ''; + display: block; + width: 15px; + height: 15px; + background: url('@{assets-url}/images/icons/icon-tick.png') no-repeat 0 0; + background-size: 15px 15px; + position: absolute; + left: 0; + top: 6px; + } + } +} diff --git a/themes/demo/assets/less/layouts/home.less b/themes/demo/assets/less/layouts/home.less new file mode 100644 index 0000000..2b25a12 --- /dev/null +++ b/themes/demo/assets/less/layouts/home.less @@ -0,0 +1,23 @@ +@import "../theme/boot"; + +// +// Home Layout Stylesheet +// + +body.home-layout { + #layout-nav.navbar { + padding-top: 30px; + padding-bottom: 30px; + + // Fixed top + position: absolute; + left: 0; + right: 0; + top: 0; + z-index: 1030; + } + + #layout-content { + padding-top: 0; + } +} diff --git a/themes/demo/assets/less/layouts/wiki.less b/themes/demo/assets/less/layouts/wiki.less new file mode 100644 index 0000000..a5e9e16 --- /dev/null +++ b/themes/demo/assets/less/layouts/wiki.less @@ -0,0 +1,11 @@ +@import "../theme/boot"; + +// +// Wiki Layout Stylesheet +// + +body.wiki-layout { + .sidebar-search { + padding-bottom: 40px; + } +} diff --git a/themes/demo/assets/less/pages/404.less b/themes/demo/assets/less/pages/404.less new file mode 100644 index 0000000..9d3ac74 --- /dev/null +++ b/themes/demo/assets/less/pages/404.less @@ -0,0 +1,3 @@ +.banner-404 { + padding: 40px 0; +} \ No newline at end of file diff --git a/themes/demo/assets/less/pages/ajax.less b/themes/demo/assets/less/pages/ajax.less new file mode 100644 index 0000000..19face5 --- /dev/null +++ b/themes/demo/assets/less/pages/ajax.less @@ -0,0 +1,164 @@ +@import "../theme/boot"; + +// +// AJAX Page Stylesheet +// + +// +// Calculator form +// +.panel { + border: none; + overflow: hidden; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.16); + margin-bottom: 27px; + border-radius: 4px; + + @media (min-width: @screen-md-min) { + .control-panel { + padding-right: 0!important; + } + } +} + +.panel-body { + padding: 25px; + display: table; + width: 100%; + + form { + display: table-row; + + .form-group { + display: table-cell; + vertical-align: top; + padding-right: 10px; + margin-bottom: 15px; + white-space: nowrap; + + &:last-child { + padding-right: 0; + width: 41px; + + button { + width: 41px; + height: 41px; + background: @brand-accent; + } + } + + &.operation-buttons { + width: 100px; + text-align: center; + + label { + display: inline-block; + cursor: pointer; + width: 41px; + height: 41px; + line-height: 41px; + position: relative; + margin: 0 10px 0 0; + vertical-align: top; + text-align: center; + + &:last-child { + margin-right: 0; + } + + span { + display: block; + position: absolute; + width: 100%; + height: 100%; + border-radius: @border-radius-base; + background: #ECF0F1; + } + + input { + display: none; + + &:checked + span { + background-color: @brand-accent; + color: white; + } + } + } + } + } + + @media (max-width: @screen-xs-max) { + .form-group { + display: block; + padding-right: 0; + width: 100%!important; + + &:last-child button { + width: 100%; + } + } + } + } + + input.form-control { + border: none; + display: block; + width: 100%; + background-color: #ECF0F1; + font-size: 14px; + text-align: right; + border: none; + box-shadow: none; + height: 41px; + } +} + +#result { + background: @brand-accent; + color: white; + font-size: 54px; + padding: 0 15px; + + font-weight: bold; + text-align: center; + overflow: hidden; + text-overflow: ellipsis; +} + +.explanation { + background: #f6f2ff; + padding: 50px 0 70px; + position: relative; + overflow: hidden; + z-index: 1; + + > .container { + position: relative; + } + + h3 { + font-size: 26px; + margin: 60px 0 20px; + } + + // Decorations + .explanation-decoration-1 { + .decoration-circle(); + background-color: #fff; + width: 321px; + height: 321px; + left: -140px; + top: -140px; + opacity: .5; + } + + .explanation-decoration-2 { + .decoration-circle(); + background-color: #fff; + width: 380px; + height: 380px; + right: -165px; + top: -180px; + opacity: .5; + } +} diff --git a/themes/demo/assets/less/pages/components.less b/themes/demo/assets/less/pages/components.less new file mode 100644 index 0000000..2487b64 --- /dev/null +++ b/themes/demo/assets/less/pages/components.less @@ -0,0 +1,157 @@ +@import "../theme/boot"; + +// +// Plugins Page Stylesheet +// + +// +// TODO list +// +.panel { + margin-bottom: 27px; + background-color: #fff; +} + +.panel.panel-default { + border: 2px solid @brand-accent; + overflow: hidden; + margin-top: 40px; + border-radius: 9px; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.16); + + .panel-heading { + background: transparent; + padding: 15px; + border-bottom: 1px solid #ddd; + color: #333333; + + h3 { + position: relative; + padding-left: 32px; + margin-top: 0; + margin-bottom: 0; + font-size: 18px; + + &:before { + content: ''; + position: absolute; + top: -1px; + left: 0; + width: 24px; + height: 24px; + background: url('@{assets-url}/images/icons/icon-todo.png') no-repeat 0 0; + background-size: 24px 24px !important; + } + } + } + + .panel-body { + padding: 0; + + input.form-control { + border: none; + padding-left: 17px; + box-shadow: none; + } + + input.form-control, button.btn { + height: 41px; + } + + .input-group-btn { + margin-left: 0 !important; + } + + button.btn.btn-primary { + background: transparent; + border: none; + outline: none; + box-shadow: none; + color: @text-color; + padding-left: 20px; + padding-right: 45px; + + &:before { + content: ''; + position: absolute; + top: 9px; + right: 9px; + width: 23px; + height: 23px; + background: url('@{assets-url}/images/icons/icon-keyboard-return.png') no-repeat 0 0; + background-size: 23px 23px !important; + } + } + } + + .list-group { + border-radius: 0; + li { + padding: 10px 15px 10px 37px; + position: relative; + border-left: none; + border-right: none; + + &:last-child { + border-bottom: none; + } + + button { + .text-hide(); + position: absolute; + left: 15px; + top: 16px; + width: 15px; + height: 15px; + opacity: 1; + outline: none!important; + border: 1px solid #BDC3C7; + border-radius: 100%; + } + } + } +} + +.explanation { + background: #f6f2ff; + padding: 90px 0 70px; + position: relative; + overflow: hidden; + z-index: 1; + + > .container { + position: relative; + } + + h3 { + font-size: 26px; + margin-bottom: 45px; + } + + p.lead { + font-weight: 400; + font-size: 20px; + margin-bottom: 40px; + } + + // Decorations + .explanation-decoration-1 { + .decoration-circle(); + background-color: #fff; + width: 321px; + height: 321px; + left: -140px; + top: -140px; + opacity: .5; + } + + .explanation-decoration-2 { + .decoration-circle(); + background-color: #fff; + width: 380px; + height: 380px; + right: -165px; + top: -180px; + opacity: .5; + } +} diff --git a/themes/demo/assets/less/pages/contact.less b/themes/demo/assets/less/pages/contact.less new file mode 100644 index 0000000..05bee52 --- /dev/null +++ b/themes/demo/assets/less/pages/contact.less @@ -0,0 +1,47 @@ +@import "../theme/boot"; + +.contactform { + text-align: center; + background: #f6f2ff; + padding: 70px 0; + position: relative; + overflow: hidden; + z-index: 1; + + > .container { + position: relative; + } + + h3 { + font-weight: 700; + font-size: 26px; + margin-bottom: 45px; + } + + p.lead { + font-weight: 400; + font-size: 20px; + margin-bottom: 40px; + } + + // Decorations + .contactform-decoration-1 { + .decoration-circle(); + background-color: #fff; + width: 321px; + height: 321px; + left: -140px; + top: -140px; + opacity: .5; + } + + .contactform-decoration-2 { + .decoration-circle(); + background-color: #fff; + width: 380px; + height: 380px; + right: -165px; + top: -180px; + opacity: .5; + } +} diff --git a/themes/demo/assets/less/pages/index.less b/themes/demo/assets/less/pages/index.less new file mode 100644 index 0000000..581b957 --- /dev/null +++ b/themes/demo/assets/less/pages/index.less @@ -0,0 +1,252 @@ +@import "../theme/boot"; + +// +// Index Page Stylesheet +// + +.jumbotron { + background: linear-gradient(102.01deg, #DB6A26 0.3%, #DBB326 106.31%); + padding-bottom: 0; + position: relative; + overflow: hidden; + z-index: 1; + + &:before { + content: ''; + position: absolute; + width: 100%; + height: 186px; + background-image: url('@{assets-url}/images/waves/header-wave.svg'); + background-repeat: repeat-x; + z-index: 1; + bottom: -1px; + } + + > .container { + position: relative; + z-index: 2; + } + + // Decorations + .jumbotron-decoration-1 { + .decoration-circle(); + width: 524px; + height: 524px; + left: -10px; + top: -84px; + opacity: .04; + } + + .jumbotron-decoration-2 { + .decoration-circle(); + width: 524px; + height: 524px; + left: 648px; + top: 260px; + opacity: .05; + } + + .jumbotron-intro { + padding: 70px 100px; + h1 { + color: #fff; + font-weight: 700; + } + p { + color: #fff; + margin-top: 30px; + } + .btn { + &:not(:hover):not(:active) { + border-color: transparent; + background: rgba(255, 216, 170, 0.46); + } + } + } + + .jumbotron-product { + padding: 90px 0 35px 0; + margin-right: -40px; + margin-left: -100px; + + img { + position: relative; + z-index: 2; + } + } + + @media (max-width: @screen-lg-max) { + .jumbotron-intro { + h1 { font-size: 45px; } + } + } + + @media (max-width: @screen-md-max) { + .jumbotron-intro { + padding-left: 0; + h1 { font-size: 45px; } + } + } + + @media (max-width: @screen-sm-max) { + .jumbotron-intro { + padding: 20px 0 0; + h1 { font-size: 35px; } + } + .jumbotron-product { + padding-top: 20px; + } + } +} + +.intro { + background-image: url('@{assets-url}/images/homepage-about-page.png'); + background-repeat: no-repeat; + background-position: bottom center; + background-size: 1427px auto; + padding: 25px 0 568px; + text-align: center; + + .img-leaf { + width: 49px; + margin: 35px 0; + } + + h2 { + font-weight: 700; + font-size: 40px; + margin: 0; + padding-bottom: 40px; + } + + p.lead { + max-width: 850px; + margin: 0 auto; + display: block; + font-weight: 400; + font-size: 20px; + } +} + +.feature { + .feature-content { + padding: 50px 0 0; + } + + .feature-pill { + display: inline-block; + background: #FFE9B4; + border-radius: 100px; + padding: 3px 20px; + > span { + opacity: 0.45; + color: #000; + font-weight: 400; + font-size: 16px; + line-height: 28px; + } + } + + .feature-image { + padding: 0 20px; + } + + h3 { + font-weight: 700; + font-size: 26px; + margin-bottom: 30px; + } + + p { + line-height: 28px; + margin-bottom: 30px; + } + + @media (max-width: @screen-md-max) { + .feature-content { + padding-top: 0; + padding-bottom: 50px; + } + } + + @media (max-width: @screen-sm-max) { + .feature-image { + display: none; + } + } +} + +.actioncall { + text-align: center; + background: linear-gradient(102.01deg, #eff4fd 0.3%, #f6f2ff 106.31%); + padding: 70px 0; + position: relative; + overflow: hidden; + z-index: 1; + + > .container { + position: relative; + } + + h3 { + font-weight: 700; + font-size: 60px; + margin-bottom: 45px; + } + + p.lead { + font-weight: 400; + font-size: 20px; + margin-bottom: 40px; + color: #586667; + } + + // Decorations + .actioncall-decoration-1 { + .decoration-circle(); + background-color: #fff; + width: 321px; + height: 321px; + left: -140px; + top: -140px; + opacity: .5; + } + + .actioncall-decoration-2 { + .decoration-circle(); + background-color: #fff; + width: 380px; + height: 380px; + right: -165px; + top: -180px; + opacity: .5; + } + + .actioncall-decoration-3 { + .decoration-circle(); + background-color: #fff; + width: 493px; + height: 493px; + left: 235px; + bottom: -380px; + opacity: .3; + } + + @media (max-width: @screen-md-max) { + h3 { font-size: 50px; } + } + + @media (max-width: @screen-sm-max) { + h3 { font-size: 40px; } + } +} + +.latestnews { + h3 { + margin: 50px 0; + text-align: center; + color: #000; + font-weight: 700; + font-size: 40px; + } +} \ No newline at end of file diff --git a/themes/demo/assets/less/theme.less b/themes/demo/assets/less/theme.less new file mode 100644 index 0000000..ad16467 --- /dev/null +++ b/themes/demo/assets/less/theme.less @@ -0,0 +1,53 @@ +@import "theme/boot"; + +// For first level entry path +@assets-url: "../../assets"; + +// +// Common Styles +// +// These are styles that apply everywhere +// + +@import "theme/common"; + +// +// Layouts +// +// These are layout specific stylesheets +// + +@import "layouts/default"; +@import "layouts/home"; +@import "layouts/blog"; +@import "layouts/wiki"; + +// +// Controls +// +// These are interactive controls used in the site. +// + +@import "controls/example"; + +// +// Elements +// +// These are reusable elements used in the site. +// + +@import "elements/text"; +@import "elements/card"; +@import "elements/callouts"; +@import "elements/navbar"; +@import "elements/jumbotron"; +@import "elements/pagination"; +@import "elements/code"; +@import "elements/buttons"; +@import "elements/footer"; +@import "elements/social-links"; +@import "elements/user-panel"; +@import "elements/lists"; +@import "elements/form"; +@import "elements/popover"; +@import "elements/how-its-made"; diff --git a/themes/demo/assets/less/theme/boot.less b/themes/demo/assets/less/theme/boot.less new file mode 100644 index 0000000..ab2b2fa --- /dev/null +++ b/themes/demo/assets/less/theme/boot.less @@ -0,0 +1,8 @@ +// +// Boot file +// +// Includes non-output LESS files such as mixins and variables +// + +@import "mixins.less"; +@import "variables.less"; diff --git a/themes/demo/assets/less/theme/common.less b/themes/demo/assets/less/theme/common.less new file mode 100644 index 0000000..21eea75 --- /dev/null +++ b/themes/demo/assets/less/theme/common.less @@ -0,0 +1,59 @@ +// +// Common Styles +// + +// BS vars +:root { + --bs-body-line-height: 1.7; + --bs-body-color: #343F52; +} + +a { + color: #3097d1; + text-decoration: none; +} + +a:hover, a:focus { + color: #216a94; + text-decoration: underline; +} + +h1, .h1 { + font-size: 40px; +} +h2, .h2 { + font-size: 26px; +} +h3, .h3 { + font-size: 22px; +} +h4, .h4 { + font-size: 19px; +} +h5, .h5 { + font-size: 16px; +} +h6, .h6 { + font-size: 14px; +} + +h1, .h1, h2, .h2 { + font-weight: 700; +} + +h1, .h1, h2, .h2, h3, .h3 { + margin-bottom: 13.5px; +} + +p.lead { + font-size: 20px; + font-weight: 400; +} + +code { + padding: 2px 4px; + font-size: 90%; + color: #D35400; + background-color: #ECF0F1; + border-radius: 4px; +} diff --git a/themes/demo/assets/less/theme/mixins.less b/themes/demo/assets/less/theme/mixins.less new file mode 100644 index 0000000..5739a11 --- /dev/null +++ b/themes/demo/assets/less/theme/mixins.less @@ -0,0 +1,22 @@ +// +// Mixins file +// +// Space for any custom mixins used by this application +// + +.decoration-circle() { + content: ''; + border-radius: 100%; + background-color: #F4F7F8; + display: block; + position: absolute; + z-index: -1; +} + +.text-hide() { + font: ~"0/0" a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} diff --git a/themes/demo/assets/less/theme/variables.less b/themes/demo/assets/less/theme/variables.less new file mode 100644 index 0000000..d11b6b2 --- /dev/null +++ b/themes/demo/assets/less/theme/variables.less @@ -0,0 +1,121 @@ +// +// Variables file +// +// Space for any custom variables used by this application +// + +// Assets +// -------------------------------------------------- +// For second level entry paths (pages, layouts, etc.) +@assets-url: "../../../assets"; + +// Brands +// -------------------------------------------------- +@brand-primary: #3097d1; +@brand-info: #8eb4cb; +@brand-success: #4eb76e; +@brand-warning: #cbb956; +@brand-danger: #bf5329; +@brand-accent: #6A6CF7; + +@gray-base: #000; +@gray-darker: lighten(@gray-base, 13.5%); // #222 +@gray-dark: lighten(@gray-base, 20%); // #333 +@gray: lighten(@gray-base, 33.5%); // #555 +@gray-light: lighten(@gray-base, 46.7%); // #777 +@gray-lighter: lighten(@gray-base, 93.5%); // #eee + +// Typography +// -------------------------------------------------- +@font-family-sans-serif: "lato", sans-serif; +@line-height-base: 1.7; +@font-size-base: 16px; +@font-size-h3: 18px; +@text-color: #586667; +@headings-color: #2C3E4F; +@headings-font-weight: bold; +@jumbotron-heading-color: @headings-color; +@border-radius-base: 4px; + +@code-color: #D35400; +@code-bg: #ECF0F1; + +// Breakpoints +// -------------------------------------------------- + +// Extra small screen +@screen-xs-min: 576px; + +// Small screen / tablet +@screen-sm-min: 768px; + +// Medium screen / desktop +@screen-md-min: 992px; + +// Large screen / wide desktop +@screen-lg-min: 1200px; + +// Extra large screen +@screen-xl-min: 1400px; + +// So media queries don't overlap when required, provide a maximum +@screen-xs-max: (@screen-sm-min - 1); +@screen-sm-max: (@screen-md-min - 1); +@screen-md-max: (@screen-lg-min - 1); +@screen-lg-max: (@screen-xl-min - 1); + +// Jumbotron +// -------------------------------------------------- + +@jumbotron-padding: 40px; +@jumbotron-bg: transparent; +@jumbotron-color: #34495E; +@jumbotron-heading-color: @headings-color; +@jumbotron-font-size: 20px; +@jumbotron-heading-font-size: 65px; + +// Spacing +// -------------------------------------------------- +@spacer: 20px; +@spacer-y: @spacer; +@spacer-x: @spacer; + +// Navbar +// -------------------------------------------------- +@navbar-inverse-bg: #DB6A26; +@navbar-inverse-link-color: rgba(255,255,255,0.6); + +@navbar-inverse-stripe-color-active: #ffffff; +@navbar-inverse-stripe-color-hover: #e67e22; +@navbar-default-stripe-color-active: #64ae5b; +@navbar-default-stripe-color-hover: #93dc8a; +@navbar-inverse-toggle-border-color: #ffffff; +@navbar-inverse-toggle-hover-bg: rgba(255, 255, 255, 0.3); + +@navbar-padding-horizontal: 0; + +// Callouts +// -------------------------------------------------- +@callout-padding: 20px; +@callout-border-radius: @border-radius-base; +@callout-border: @gray-lighter; + +@callout-info-bg: #f4f8fa; +@callout-info-text: #31708f; +@callout-info-border: darken(spin(@callout-info-bg, -10), 7%); + +@callout-warning-bg: #faf8f0; +@callout-warning-text: #8a6d3b; +@callout-warning-border: darken(spin(@callout-warning-bg, -10), 5%); + +@callout-danger-bg: #fdf7f7; +@callout-danger-text: #a94442; +@callout-danger-border: darken(spin(@callout-danger-bg, -10), 5%); + +@callout-success-bg: #f9fdf7; +@callout-success-text: #3c763d; +@callout-success-border: darken(spin(@callout-success-bg, -10), 5%); + +// Forms +// -------------------------------------------------- +@input-border-color: #D7D7D7; \ No newline at end of file diff --git a/themes/demo/assets/vendor/bootstrap-icons/bootstrap-icons.css b/themes/demo/assets/vendor/bootstrap-icons/bootstrap-icons.css new file mode 100644 index 0000000..8ee1d8e --- /dev/null +++ b/themes/demo/assets/vendor/bootstrap-icons/bootstrap-icons.css @@ -0,0 +1 @@ +@font-face{font-family:bootstrap-icons;src:url(fonts/bootstrap-icons.woff2?08efbba7c53d8c5413793eecb19b20bb) format("woff2"),url(fonts/bootstrap-icons.woff?08efbba7c53d8c5413793eecb19b20bb) format("woff")}.bi:before,[class*=" bi-"]:before,[class^=bi-]:before{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;font-family:bootstrap-icons!important;font-style:normal;font-variant:normal;font-weight:400!important;line-height:1;text-transform:none;vertical-align:-.125em}.bi-123:before{content:"\f67f"}.bi-alarm-fill:before{content:"\f101"}.bi-alarm:before{content:"\f102"}.bi-align-bottom:before{content:"\f103"}.bi-align-center:before{content:"\f104"}.bi-align-end:before{content:"\f105"}.bi-align-middle:before{content:"\f106"}.bi-align-start:before{content:"\f107"}.bi-align-top:before{content:"\f108"}.bi-alt:before{content:"\f109"}.bi-app-indicator:before{content:"\f10a"}.bi-app:before{content:"\f10b"}.bi-archive-fill:before{content:"\f10c"}.bi-archive:before{content:"\f10d"}.bi-arrow-90deg-down:before{content:"\f10e"}.bi-arrow-90deg-left:before{content:"\f10f"}.bi-arrow-90deg-right:before{content:"\f110"}.bi-arrow-90deg-up:before{content:"\f111"}.bi-arrow-bar-down:before{content:"\f112"}.bi-arrow-bar-left:before{content:"\f113"}.bi-arrow-bar-right:before{content:"\f114"}.bi-arrow-bar-up:before{content:"\f115"}.bi-arrow-clockwise:before{content:"\f116"}.bi-arrow-counterclockwise:before{content:"\f117"}.bi-arrow-down-circle-fill:before{content:"\f118"}.bi-arrow-down-circle:before{content:"\f119"}.bi-arrow-down-left-circle-fill:before{content:"\f11a"}.bi-arrow-down-left-circle:before{content:"\f11b"}.bi-arrow-down-left-square-fill:before{content:"\f11c"}.bi-arrow-down-left-square:before{content:"\f11d"}.bi-arrow-down-left:before{content:"\f11e"}.bi-arrow-down-right-circle-fill:before{content:"\f11f"}.bi-arrow-down-right-circle:before{content:"\f120"}.bi-arrow-down-right-square-fill:before{content:"\f121"}.bi-arrow-down-right-square:before{content:"\f122"}.bi-arrow-down-right:before{content:"\f123"}.bi-arrow-down-short:before{content:"\f124"}.bi-arrow-down-square-fill:before{content:"\f125"}.bi-arrow-down-square:before{content:"\f126"}.bi-arrow-down-up:before{content:"\f127"}.bi-arrow-down:before{content:"\f128"}.bi-arrow-left-circle-fill:before{content:"\f129"}.bi-arrow-left-circle:before{content:"\f12a"}.bi-arrow-left-right:before{content:"\f12b"}.bi-arrow-left-short:before{content:"\f12c"}.bi-arrow-left-square-fill:before{content:"\f12d"}.bi-arrow-left-square:before{content:"\f12e"}.bi-arrow-left:before{content:"\f12f"}.bi-arrow-repeat:before{content:"\f130"}.bi-arrow-return-left:before{content:"\f131"}.bi-arrow-return-right:before{content:"\f132"}.bi-arrow-right-circle-fill:before{content:"\f133"}.bi-arrow-right-circle:before{content:"\f134"}.bi-arrow-right-short:before{content:"\f135"}.bi-arrow-right-square-fill:before{content:"\f136"}.bi-arrow-right-square:before{content:"\f137"}.bi-arrow-right:before{content:"\f138"}.bi-arrow-up-circle-fill:before{content:"\f139"}.bi-arrow-up-circle:before{content:"\f13a"}.bi-arrow-up-left-circle-fill:before{content:"\f13b"}.bi-arrow-up-left-circle:before{content:"\f13c"}.bi-arrow-up-left-square-fill:before{content:"\f13d"}.bi-arrow-up-left-square:before{content:"\f13e"}.bi-arrow-up-left:before{content:"\f13f"}.bi-arrow-up-right-circle-fill:before{content:"\f140"}.bi-arrow-up-right-circle:before{content:"\f141"}.bi-arrow-up-right-square-fill:before{content:"\f142"}.bi-arrow-up-right-square:before{content:"\f143"}.bi-arrow-up-right:before{content:"\f144"}.bi-arrow-up-short:before{content:"\f145"}.bi-arrow-up-square-fill:before{content:"\f146"}.bi-arrow-up-square:before{content:"\f147"}.bi-arrow-up:before{content:"\f148"}.bi-arrows-angle-contract:before{content:"\f149"}.bi-arrows-angle-expand:before{content:"\f14a"}.bi-arrows-collapse:before{content:"\f14b"}.bi-arrows-expand:before{content:"\f14c"}.bi-arrows-fullscreen:before{content:"\f14d"}.bi-arrows-move:before{content:"\f14e"}.bi-aspect-ratio-fill:before{content:"\f14f"}.bi-aspect-ratio:before{content:"\f150"}.bi-asterisk:before{content:"\f151"}.bi-at:before{content:"\f152"}.bi-award-fill:before{content:"\f153"}.bi-award:before{content:"\f154"}.bi-back:before{content:"\f155"}.bi-backspace-fill:before{content:"\f156"}.bi-backspace-reverse-fill:before{content:"\f157"}.bi-backspace-reverse:before{content:"\f158"}.bi-backspace:before{content:"\f159"}.bi-badge-3d-fill:before{content:"\f15a"}.bi-badge-3d:before{content:"\f15b"}.bi-badge-4k-fill:before{content:"\f15c"}.bi-badge-4k:before{content:"\f15d"}.bi-badge-8k-fill:before{content:"\f15e"}.bi-badge-8k:before{content:"\f15f"}.bi-badge-ad-fill:before{content:"\f160"}.bi-badge-ad:before{content:"\f161"}.bi-badge-ar-fill:before{content:"\f162"}.bi-badge-ar:before{content:"\f163"}.bi-badge-cc-fill:before{content:"\f164"}.bi-badge-cc:before{content:"\f165"}.bi-badge-hd-fill:before{content:"\f166"}.bi-badge-hd:before{content:"\f167"}.bi-badge-tm-fill:before{content:"\f168"}.bi-badge-tm:before{content:"\f169"}.bi-badge-vo-fill:before{content:"\f16a"}.bi-badge-vo:before{content:"\f16b"}.bi-badge-vr-fill:before{content:"\f16c"}.bi-badge-vr:before{content:"\f16d"}.bi-badge-wc-fill:before{content:"\f16e"}.bi-badge-wc:before{content:"\f16f"}.bi-bag-check-fill:before{content:"\f170"}.bi-bag-check:before{content:"\f171"}.bi-bag-dash-fill:before{content:"\f172"}.bi-bag-dash:before{content:"\f173"}.bi-bag-fill:before{content:"\f174"}.bi-bag-plus-fill:before{content:"\f175"}.bi-bag-plus:before{content:"\f176"}.bi-bag-x-fill:before{content:"\f177"}.bi-bag-x:before{content:"\f178"}.bi-bag:before{content:"\f179"}.bi-bar-chart-fill:before{content:"\f17a"}.bi-bar-chart-line-fill:before{content:"\f17b"}.bi-bar-chart-line:before{content:"\f17c"}.bi-bar-chart-steps:before{content:"\f17d"}.bi-bar-chart:before{content:"\f17e"}.bi-basket-fill:before{content:"\f17f"}.bi-basket:before{content:"\f180"}.bi-basket2-fill:before{content:"\f181"}.bi-basket2:before{content:"\f182"}.bi-basket3-fill:before{content:"\f183"}.bi-basket3:before{content:"\f184"}.bi-battery-charging:before{content:"\f185"}.bi-battery-full:before{content:"\f186"}.bi-battery-half:before{content:"\f187"}.bi-battery:before{content:"\f188"}.bi-bell-fill:before{content:"\f189"}.bi-bell:before{content:"\f18a"}.bi-bezier:before{content:"\f18b"}.bi-bezier2:before{content:"\f18c"}.bi-bicycle:before{content:"\f18d"}.bi-binoculars-fill:before{content:"\f18e"}.bi-binoculars:before{content:"\f18f"}.bi-blockquote-left:before{content:"\f190"}.bi-blockquote-right:before{content:"\f191"}.bi-book-fill:before{content:"\f192"}.bi-book-half:before{content:"\f193"}.bi-book:before{content:"\f194"}.bi-bookmark-check-fill:before{content:"\f195"}.bi-bookmark-check:before{content:"\f196"}.bi-bookmark-dash-fill:before{content:"\f197"}.bi-bookmark-dash:before{content:"\f198"}.bi-bookmark-fill:before{content:"\f199"}.bi-bookmark-heart-fill:before{content:"\f19a"}.bi-bookmark-heart:before{content:"\f19b"}.bi-bookmark-plus-fill:before{content:"\f19c"}.bi-bookmark-plus:before{content:"\f19d"}.bi-bookmark-star-fill:before{content:"\f19e"}.bi-bookmark-star:before{content:"\f19f"}.bi-bookmark-x-fill:before{content:"\f1a0"}.bi-bookmark-x:before{content:"\f1a1"}.bi-bookmark:before{content:"\f1a2"}.bi-bookmarks-fill:before{content:"\f1a3"}.bi-bookmarks:before{content:"\f1a4"}.bi-bookshelf:before{content:"\f1a5"}.bi-bootstrap-fill:before{content:"\f1a6"}.bi-bootstrap-reboot:before{content:"\f1a7"}.bi-bootstrap:before{content:"\f1a8"}.bi-border-all:before{content:"\f1a9"}.bi-border-bottom:before{content:"\f1aa"}.bi-border-center:before{content:"\f1ab"}.bi-border-inner:before{content:"\f1ac"}.bi-border-left:before{content:"\f1ad"}.bi-border-middle:before{content:"\f1ae"}.bi-border-outer:before{content:"\f1af"}.bi-border-right:before{content:"\f1b0"}.bi-border-style:before{content:"\f1b1"}.bi-border-top:before{content:"\f1b2"}.bi-border-width:before{content:"\f1b3"}.bi-border:before{content:"\f1b4"}.bi-bounding-box-circles:before{content:"\f1b5"}.bi-bounding-box:before{content:"\f1b6"}.bi-box-arrow-down-left:before{content:"\f1b7"}.bi-box-arrow-down-right:before{content:"\f1b8"}.bi-box-arrow-down:before{content:"\f1b9"}.bi-box-arrow-in-down-left:before{content:"\f1ba"}.bi-box-arrow-in-down-right:before{content:"\f1bb"}.bi-box-arrow-in-down:before{content:"\f1bc"}.bi-box-arrow-in-left:before{content:"\f1bd"}.bi-box-arrow-in-right:before{content:"\f1be"}.bi-box-arrow-in-up-left:before{content:"\f1bf"}.bi-box-arrow-in-up-right:before{content:"\f1c0"}.bi-box-arrow-in-up:before{content:"\f1c1"}.bi-box-arrow-left:before{content:"\f1c2"}.bi-box-arrow-right:before{content:"\f1c3"}.bi-box-arrow-up-left:before{content:"\f1c4"}.bi-box-arrow-up-right:before{content:"\f1c5"}.bi-box-arrow-up:before{content:"\f1c6"}.bi-box-seam:before{content:"\f1c7"}.bi-box:before{content:"\f1c8"}.bi-braces:before{content:"\f1c9"}.bi-bricks:before{content:"\f1ca"}.bi-briefcase-fill:before{content:"\f1cb"}.bi-briefcase:before{content:"\f1cc"}.bi-brightness-alt-high-fill:before{content:"\f1cd"}.bi-brightness-alt-high:before{content:"\f1ce"}.bi-brightness-alt-low-fill:before{content:"\f1cf"}.bi-brightness-alt-low:before{content:"\f1d0"}.bi-brightness-high-fill:before{content:"\f1d1"}.bi-brightness-high:before{content:"\f1d2"}.bi-brightness-low-fill:before{content:"\f1d3"}.bi-brightness-low:before{content:"\f1d4"}.bi-broadcast-pin:before{content:"\f1d5"}.bi-broadcast:before{content:"\f1d6"}.bi-brush-fill:before{content:"\f1d7"}.bi-brush:before{content:"\f1d8"}.bi-bucket-fill:before{content:"\f1d9"}.bi-bucket:before{content:"\f1da"}.bi-bug-fill:before{content:"\f1db"}.bi-bug:before{content:"\f1dc"}.bi-building:before{content:"\f1dd"}.bi-bullseye:before{content:"\f1de"}.bi-calculator-fill:before{content:"\f1df"}.bi-calculator:before{content:"\f1e0"}.bi-calendar-check-fill:before{content:"\f1e1"}.bi-calendar-check:before{content:"\f1e2"}.bi-calendar-date-fill:before{content:"\f1e3"}.bi-calendar-date:before{content:"\f1e4"}.bi-calendar-day-fill:before{content:"\f1e5"}.bi-calendar-day:before{content:"\f1e6"}.bi-calendar-event-fill:before{content:"\f1e7"}.bi-calendar-event:before{content:"\f1e8"}.bi-calendar-fill:before{content:"\f1e9"}.bi-calendar-minus-fill:before{content:"\f1ea"}.bi-calendar-minus:before{content:"\f1eb"}.bi-calendar-month-fill:before{content:"\f1ec"}.bi-calendar-month:before{content:"\f1ed"}.bi-calendar-plus-fill:before{content:"\f1ee"}.bi-calendar-plus:before{content:"\f1ef"}.bi-calendar-range-fill:before{content:"\f1f0"}.bi-calendar-range:before{content:"\f1f1"}.bi-calendar-week-fill:before{content:"\f1f2"}.bi-calendar-week:before{content:"\f1f3"}.bi-calendar-x-fill:before{content:"\f1f4"}.bi-calendar-x:before{content:"\f1f5"}.bi-calendar:before{content:"\f1f6"}.bi-calendar2-check-fill:before{content:"\f1f7"}.bi-calendar2-check:before{content:"\f1f8"}.bi-calendar2-date-fill:before{content:"\f1f9"}.bi-calendar2-date:before{content:"\f1fa"}.bi-calendar2-day-fill:before{content:"\f1fb"}.bi-calendar2-day:before{content:"\f1fc"}.bi-calendar2-event-fill:before{content:"\f1fd"}.bi-calendar2-event:before{content:"\f1fe"}.bi-calendar2-fill:before{content:"\f1ff"}.bi-calendar2-minus-fill:before{content:"\f200"}.bi-calendar2-minus:before{content:"\f201"}.bi-calendar2-month-fill:before{content:"\f202"}.bi-calendar2-month:before{content:"\f203"}.bi-calendar2-plus-fill:before{content:"\f204"}.bi-calendar2-plus:before{content:"\f205"}.bi-calendar2-range-fill:before{content:"\f206"}.bi-calendar2-range:before{content:"\f207"}.bi-calendar2-week-fill:before{content:"\f208"}.bi-calendar2-week:before{content:"\f209"}.bi-calendar2-x-fill:before{content:"\f20a"}.bi-calendar2-x:before{content:"\f20b"}.bi-calendar2:before{content:"\f20c"}.bi-calendar3-event-fill:before{content:"\f20d"}.bi-calendar3-event:before{content:"\f20e"}.bi-calendar3-fill:before{content:"\f20f"}.bi-calendar3-range-fill:before{content:"\f210"}.bi-calendar3-range:before{content:"\f211"}.bi-calendar3-week-fill:before{content:"\f212"}.bi-calendar3-week:before{content:"\f213"}.bi-calendar3:before{content:"\f214"}.bi-calendar4-event:before{content:"\f215"}.bi-calendar4-range:before{content:"\f216"}.bi-calendar4-week:before{content:"\f217"}.bi-calendar4:before{content:"\f218"}.bi-camera-fill:before{content:"\f219"}.bi-camera-reels-fill:before{content:"\f21a"}.bi-camera-reels:before{content:"\f21b"}.bi-camera-video-fill:before{content:"\f21c"}.bi-camera-video-off-fill:before{content:"\f21d"}.bi-camera-video-off:before{content:"\f21e"}.bi-camera-video:before{content:"\f21f"}.bi-camera:before{content:"\f220"}.bi-camera2:before{content:"\f221"}.bi-capslock-fill:before{content:"\f222"}.bi-capslock:before{content:"\f223"}.bi-card-checklist:before{content:"\f224"}.bi-card-heading:before{content:"\f225"}.bi-card-image:before{content:"\f226"}.bi-card-list:before{content:"\f227"}.bi-card-text:before{content:"\f228"}.bi-caret-down-fill:before{content:"\f229"}.bi-caret-down-square-fill:before{content:"\f22a"}.bi-caret-down-square:before{content:"\f22b"}.bi-caret-down:before{content:"\f22c"}.bi-caret-left-fill:before{content:"\f22d"}.bi-caret-left-square-fill:before{content:"\f22e"}.bi-caret-left-square:before{content:"\f22f"}.bi-caret-left:before{content:"\f230"}.bi-caret-right-fill:before{content:"\f231"}.bi-caret-right-square-fill:before{content:"\f232"}.bi-caret-right-square:before{content:"\f233"}.bi-caret-right:before{content:"\f234"}.bi-caret-up-fill:before{content:"\f235"}.bi-caret-up-square-fill:before{content:"\f236"}.bi-caret-up-square:before{content:"\f237"}.bi-caret-up:before{content:"\f238"}.bi-cart-check-fill:before{content:"\f239"}.bi-cart-check:before{content:"\f23a"}.bi-cart-dash-fill:before{content:"\f23b"}.bi-cart-dash:before{content:"\f23c"}.bi-cart-fill:before{content:"\f23d"}.bi-cart-plus-fill:before{content:"\f23e"}.bi-cart-plus:before{content:"\f23f"}.bi-cart-x-fill:before{content:"\f240"}.bi-cart-x:before{content:"\f241"}.bi-cart:before{content:"\f242"}.bi-cart2:before{content:"\f243"}.bi-cart3:before{content:"\f244"}.bi-cart4:before{content:"\f245"}.bi-cash-stack:before{content:"\f246"}.bi-cash:before{content:"\f247"}.bi-cast:before{content:"\f248"}.bi-chat-dots-fill:before{content:"\f249"}.bi-chat-dots:before{content:"\f24a"}.bi-chat-fill:before{content:"\f24b"}.bi-chat-left-dots-fill:before{content:"\f24c"}.bi-chat-left-dots:before{content:"\f24d"}.bi-chat-left-fill:before{content:"\f24e"}.bi-chat-left-quote-fill:before{content:"\f24f"}.bi-chat-left-quote:before{content:"\f250"}.bi-chat-left-text-fill:before{content:"\f251"}.bi-chat-left-text:before{content:"\f252"}.bi-chat-left:before{content:"\f253"}.bi-chat-quote-fill:before{content:"\f254"}.bi-chat-quote:before{content:"\f255"}.bi-chat-right-dots-fill:before{content:"\f256"}.bi-chat-right-dots:before{content:"\f257"}.bi-chat-right-fill:before{content:"\f258"}.bi-chat-right-quote-fill:before{content:"\f259"}.bi-chat-right-quote:before{content:"\f25a"}.bi-chat-right-text-fill:before{content:"\f25b"}.bi-chat-right-text:before{content:"\f25c"}.bi-chat-right:before{content:"\f25d"}.bi-chat-square-dots-fill:before{content:"\f25e"}.bi-chat-square-dots:before{content:"\f25f"}.bi-chat-square-fill:before{content:"\f260"}.bi-chat-square-quote-fill:before{content:"\f261"}.bi-chat-square-quote:before{content:"\f262"}.bi-chat-square-text-fill:before{content:"\f263"}.bi-chat-square-text:before{content:"\f264"}.bi-chat-square:before{content:"\f265"}.bi-chat-text-fill:before{content:"\f266"}.bi-chat-text:before{content:"\f267"}.bi-chat:before{content:"\f268"}.bi-check-all:before{content:"\f269"}.bi-check-circle-fill:before{content:"\f26a"}.bi-check-circle:before{content:"\f26b"}.bi-check-square-fill:before{content:"\f26c"}.bi-check-square:before{content:"\f26d"}.bi-check:before{content:"\f26e"}.bi-check2-all:before{content:"\f26f"}.bi-check2-circle:before{content:"\f270"}.bi-check2-square:before{content:"\f271"}.bi-check2:before{content:"\f272"}.bi-chevron-bar-contract:before{content:"\f273"}.bi-chevron-bar-down:before{content:"\f274"}.bi-chevron-bar-expand:before{content:"\f275"}.bi-chevron-bar-left:before{content:"\f276"}.bi-chevron-bar-right:before{content:"\f277"}.bi-chevron-bar-up:before{content:"\f278"}.bi-chevron-compact-down:before{content:"\f279"}.bi-chevron-compact-left:before{content:"\f27a"}.bi-chevron-compact-right:before{content:"\f27b"}.bi-chevron-compact-up:before{content:"\f27c"}.bi-chevron-contract:before{content:"\f27d"}.bi-chevron-double-down:before{content:"\f27e"}.bi-chevron-double-left:before{content:"\f27f"}.bi-chevron-double-right:before{content:"\f280"}.bi-chevron-double-up:before{content:"\f281"}.bi-chevron-down:before{content:"\f282"}.bi-chevron-expand:before{content:"\f283"}.bi-chevron-left:before{content:"\f284"}.bi-chevron-right:before{content:"\f285"}.bi-chevron-up:before{content:"\f286"}.bi-circle-fill:before{content:"\f287"}.bi-circle-half:before{content:"\f288"}.bi-circle-square:before{content:"\f289"}.bi-circle:before{content:"\f28a"}.bi-clipboard-check:before{content:"\f28b"}.bi-clipboard-data:before{content:"\f28c"}.bi-clipboard-minus:before{content:"\f28d"}.bi-clipboard-plus:before{content:"\f28e"}.bi-clipboard-x:before{content:"\f28f"}.bi-clipboard:before{content:"\f290"}.bi-clock-fill:before{content:"\f291"}.bi-clock-history:before{content:"\f292"}.bi-clock:before{content:"\f293"}.bi-cloud-arrow-down-fill:before{content:"\f294"}.bi-cloud-arrow-down:before{content:"\f295"}.bi-cloud-arrow-up-fill:before{content:"\f296"}.bi-cloud-arrow-up:before{content:"\f297"}.bi-cloud-check-fill:before{content:"\f298"}.bi-cloud-check:before{content:"\f299"}.bi-cloud-download-fill:before{content:"\f29a"}.bi-cloud-download:before{content:"\f29b"}.bi-cloud-drizzle-fill:before{content:"\f29c"}.bi-cloud-drizzle:before{content:"\f29d"}.bi-cloud-fill:before{content:"\f29e"}.bi-cloud-fog-fill:before{content:"\f29f"}.bi-cloud-fog:before{content:"\f2a0"}.bi-cloud-fog2-fill:before{content:"\f2a1"}.bi-cloud-fog2:before{content:"\f2a2"}.bi-cloud-hail-fill:before{content:"\f2a3"}.bi-cloud-hail:before{content:"\f2a4"}.bi-cloud-haze-1:before{content:"\f2a5"}.bi-cloud-haze-fill:before{content:"\f2a6"}.bi-cloud-haze:before{content:"\f2a7"}.bi-cloud-haze2-fill:before{content:"\f2a8"}.bi-cloud-lightning-fill:before{content:"\f2a9"}.bi-cloud-lightning-rain-fill:before{content:"\f2aa"}.bi-cloud-lightning-rain:before{content:"\f2ab"}.bi-cloud-lightning:before{content:"\f2ac"}.bi-cloud-minus-fill:before{content:"\f2ad"}.bi-cloud-minus:before{content:"\f2ae"}.bi-cloud-moon-fill:before{content:"\f2af"}.bi-cloud-moon:before{content:"\f2b0"}.bi-cloud-plus-fill:before{content:"\f2b1"}.bi-cloud-plus:before{content:"\f2b2"}.bi-cloud-rain-fill:before{content:"\f2b3"}.bi-cloud-rain-heavy-fill:before{content:"\f2b4"}.bi-cloud-rain-heavy:before{content:"\f2b5"}.bi-cloud-rain:before{content:"\f2b6"}.bi-cloud-slash-fill:before{content:"\f2b7"}.bi-cloud-slash:before{content:"\f2b8"}.bi-cloud-sleet-fill:before{content:"\f2b9"}.bi-cloud-sleet:before{content:"\f2ba"}.bi-cloud-snow-fill:before{content:"\f2bb"}.bi-cloud-snow:before{content:"\f2bc"}.bi-cloud-sun-fill:before{content:"\f2bd"}.bi-cloud-sun:before{content:"\f2be"}.bi-cloud-upload-fill:before{content:"\f2bf"}.bi-cloud-upload:before{content:"\f2c0"}.bi-cloud:before{content:"\f2c1"}.bi-clouds-fill:before{content:"\f2c2"}.bi-clouds:before{content:"\f2c3"}.bi-cloudy-fill:before{content:"\f2c4"}.bi-cloudy:before{content:"\f2c5"}.bi-code-slash:before{content:"\f2c6"}.bi-code-square:before{content:"\f2c7"}.bi-code:before{content:"\f2c8"}.bi-collection-fill:before{content:"\f2c9"}.bi-collection-play-fill:before{content:"\f2ca"}.bi-collection-play:before{content:"\f2cb"}.bi-collection:before{content:"\f2cc"}.bi-columns-gap:before{content:"\f2cd"}.bi-columns:before{content:"\f2ce"}.bi-command:before{content:"\f2cf"}.bi-compass-fill:before{content:"\f2d0"}.bi-compass:before{content:"\f2d1"}.bi-cone-striped:before{content:"\f2d2"}.bi-cone:before{content:"\f2d3"}.bi-controller:before{content:"\f2d4"}.bi-cpu-fill:before{content:"\f2d5"}.bi-cpu:before{content:"\f2d6"}.bi-credit-card-2-back-fill:before{content:"\f2d7"}.bi-credit-card-2-back:before{content:"\f2d8"}.bi-credit-card-2-front-fill:before{content:"\f2d9"}.bi-credit-card-2-front:before{content:"\f2da"}.bi-credit-card-fill:before{content:"\f2db"}.bi-credit-card:before{content:"\f2dc"}.bi-crop:before{content:"\f2dd"}.bi-cup-fill:before{content:"\f2de"}.bi-cup-straw:before{content:"\f2df"}.bi-cup:before{content:"\f2e0"}.bi-cursor-fill:before{content:"\f2e1"}.bi-cursor-text:before{content:"\f2e2"}.bi-cursor:before{content:"\f2e3"}.bi-dash-circle-dotted:before{content:"\f2e4"}.bi-dash-circle-fill:before{content:"\f2e5"}.bi-dash-circle:before{content:"\f2e6"}.bi-dash-square-dotted:before{content:"\f2e7"}.bi-dash-square-fill:before{content:"\f2e8"}.bi-dash-square:before{content:"\f2e9"}.bi-dash:before{content:"\f2ea"}.bi-diagram-2-fill:before{content:"\f2eb"}.bi-diagram-2:before{content:"\f2ec"}.bi-diagram-3-fill:before{content:"\f2ed"}.bi-diagram-3:before{content:"\f2ee"}.bi-diamond-fill:before{content:"\f2ef"}.bi-diamond-half:before{content:"\f2f0"}.bi-diamond:before{content:"\f2f1"}.bi-dice-1-fill:before{content:"\f2f2"}.bi-dice-1:before{content:"\f2f3"}.bi-dice-2-fill:before{content:"\f2f4"}.bi-dice-2:before{content:"\f2f5"}.bi-dice-3-fill:before{content:"\f2f6"}.bi-dice-3:before{content:"\f2f7"}.bi-dice-4-fill:before{content:"\f2f8"}.bi-dice-4:before{content:"\f2f9"}.bi-dice-5-fill:before{content:"\f2fa"}.bi-dice-5:before{content:"\f2fb"}.bi-dice-6-fill:before{content:"\f2fc"}.bi-dice-6:before{content:"\f2fd"}.bi-disc-fill:before{content:"\f2fe"}.bi-disc:before{content:"\f2ff"}.bi-discord:before{content:"\f300"}.bi-display-fill:before{content:"\f301"}.bi-display:before{content:"\f302"}.bi-distribute-horizontal:before{content:"\f303"}.bi-distribute-vertical:before{content:"\f304"}.bi-door-closed-fill:before{content:"\f305"}.bi-door-closed:before{content:"\f306"}.bi-door-open-fill:before{content:"\f307"}.bi-door-open:before{content:"\f308"}.bi-dot:before{content:"\f309"}.bi-download:before{content:"\f30a"}.bi-droplet-fill:before{content:"\f30b"}.bi-droplet-half:before{content:"\f30c"}.bi-droplet:before{content:"\f30d"}.bi-earbuds:before{content:"\f30e"}.bi-easel-fill:before{content:"\f30f"}.bi-easel:before{content:"\f310"}.bi-egg-fill:before{content:"\f311"}.bi-egg-fried:before{content:"\f312"}.bi-egg:before{content:"\f313"}.bi-eject-fill:before{content:"\f314"}.bi-eject:before{content:"\f315"}.bi-emoji-angry-fill:before{content:"\f316"}.bi-emoji-angry:before{content:"\f317"}.bi-emoji-dizzy-fill:before{content:"\f318"}.bi-emoji-dizzy:before{content:"\f319"}.bi-emoji-expressionless-fill:before{content:"\f31a"}.bi-emoji-expressionless:before{content:"\f31b"}.bi-emoji-frown-fill:before{content:"\f31c"}.bi-emoji-frown:before{content:"\f31d"}.bi-emoji-heart-eyes-fill:before{content:"\f31e"}.bi-emoji-heart-eyes:before{content:"\f31f"}.bi-emoji-laughing-fill:before{content:"\f320"}.bi-emoji-laughing:before{content:"\f321"}.bi-emoji-neutral-fill:before{content:"\f322"}.bi-emoji-neutral:before{content:"\f323"}.bi-emoji-smile-fill:before{content:"\f324"}.bi-emoji-smile-upside-down-fill:before{content:"\f325"}.bi-emoji-smile-upside-down:before{content:"\f326"}.bi-emoji-smile:before{content:"\f327"}.bi-emoji-sunglasses-fill:before{content:"\f328"}.bi-emoji-sunglasses:before{content:"\f329"}.bi-emoji-wink-fill:before{content:"\f32a"}.bi-emoji-wink:before{content:"\f32b"}.bi-envelope-fill:before{content:"\f32c"}.bi-envelope-open-fill:before{content:"\f32d"}.bi-envelope-open:before{content:"\f32e"}.bi-envelope:before{content:"\f32f"}.bi-eraser-fill:before{content:"\f330"}.bi-eraser:before{content:"\f331"}.bi-exclamation-circle-fill:before{content:"\f332"}.bi-exclamation-circle:before{content:"\f333"}.bi-exclamation-diamond-fill:before{content:"\f334"}.bi-exclamation-diamond:before{content:"\f335"}.bi-exclamation-octagon-fill:before{content:"\f336"}.bi-exclamation-octagon:before{content:"\f337"}.bi-exclamation-square-fill:before{content:"\f338"}.bi-exclamation-square:before{content:"\f339"}.bi-exclamation-triangle-fill:before{content:"\f33a"}.bi-exclamation-triangle:before{content:"\f33b"}.bi-exclamation:before{content:"\f33c"}.bi-exclude:before{content:"\f33d"}.bi-eye-fill:before{content:"\f33e"}.bi-eye-slash-fill:before{content:"\f33f"}.bi-eye-slash:before{content:"\f340"}.bi-eye:before{content:"\f341"}.bi-eyedropper:before{content:"\f342"}.bi-eyeglasses:before{content:"\f343"}.bi-facebook:before{content:"\f344"}.bi-file-arrow-down-fill:before{content:"\f345"}.bi-file-arrow-down:before{content:"\f346"}.bi-file-arrow-up-fill:before{content:"\f347"}.bi-file-arrow-up:before{content:"\f348"}.bi-file-bar-graph-fill:before{content:"\f349"}.bi-file-bar-graph:before{content:"\f34a"}.bi-file-binary-fill:before{content:"\f34b"}.bi-file-binary:before{content:"\f34c"}.bi-file-break-fill:before{content:"\f34d"}.bi-file-break:before{content:"\f34e"}.bi-file-check-fill:before{content:"\f34f"}.bi-file-check:before{content:"\f350"}.bi-file-code-fill:before{content:"\f351"}.bi-file-code:before{content:"\f352"}.bi-file-diff-fill:before{content:"\f353"}.bi-file-diff:before{content:"\f354"}.bi-file-earmark-arrow-down-fill:before{content:"\f355"}.bi-file-earmark-arrow-down:before{content:"\f356"}.bi-file-earmark-arrow-up-fill:before{content:"\f357"}.bi-file-earmark-arrow-up:before{content:"\f358"}.bi-file-earmark-bar-graph-fill:before{content:"\f359"}.bi-file-earmark-bar-graph:before{content:"\f35a"}.bi-file-earmark-binary-fill:before{content:"\f35b"}.bi-file-earmark-binary:before{content:"\f35c"}.bi-file-earmark-break-fill:before{content:"\f35d"}.bi-file-earmark-break:before{content:"\f35e"}.bi-file-earmark-check-fill:before{content:"\f35f"}.bi-file-earmark-check:before{content:"\f360"}.bi-file-earmark-code-fill:before{content:"\f361"}.bi-file-earmark-code:before{content:"\f362"}.bi-file-earmark-diff-fill:before{content:"\f363"}.bi-file-earmark-diff:before{content:"\f364"}.bi-file-earmark-easel-fill:before{content:"\f365"}.bi-file-earmark-easel:before{content:"\f366"}.bi-file-earmark-excel-fill:before{content:"\f367"}.bi-file-earmark-excel:before{content:"\f368"}.bi-file-earmark-fill:before{content:"\f369"}.bi-file-earmark-font-fill:before{content:"\f36a"}.bi-file-earmark-font:before{content:"\f36b"}.bi-file-earmark-image-fill:before{content:"\f36c"}.bi-file-earmark-image:before{content:"\f36d"}.bi-file-earmark-lock-fill:before{content:"\f36e"}.bi-file-earmark-lock:before{content:"\f36f"}.bi-file-earmark-lock2-fill:before{content:"\f370"}.bi-file-earmark-lock2:before{content:"\f371"}.bi-file-earmark-medical-fill:before{content:"\f372"}.bi-file-earmark-medical:before{content:"\f373"}.bi-file-earmark-minus-fill:before{content:"\f374"}.bi-file-earmark-minus:before{content:"\f375"}.bi-file-earmark-music-fill:before{content:"\f376"}.bi-file-earmark-music:before{content:"\f377"}.bi-file-earmark-person-fill:before{content:"\f378"}.bi-file-earmark-person:before{content:"\f379"}.bi-file-earmark-play-fill:before{content:"\f37a"}.bi-file-earmark-play:before{content:"\f37b"}.bi-file-earmark-plus-fill:before{content:"\f37c"}.bi-file-earmark-plus:before{content:"\f37d"}.bi-file-earmark-post-fill:before{content:"\f37e"}.bi-file-earmark-post:before{content:"\f37f"}.bi-file-earmark-ppt-fill:before{content:"\f380"}.bi-file-earmark-ppt:before{content:"\f381"}.bi-file-earmark-richtext-fill:before{content:"\f382"}.bi-file-earmark-richtext:before{content:"\f383"}.bi-file-earmark-ruled-fill:before{content:"\f384"}.bi-file-earmark-ruled:before{content:"\f385"}.bi-file-earmark-slides-fill:before{content:"\f386"}.bi-file-earmark-slides:before{content:"\f387"}.bi-file-earmark-spreadsheet-fill:before{content:"\f388"}.bi-file-earmark-spreadsheet:before{content:"\f389"}.bi-file-earmark-text-fill:before{content:"\f38a"}.bi-file-earmark-text:before{content:"\f38b"}.bi-file-earmark-word-fill:before{content:"\f38c"}.bi-file-earmark-word:before{content:"\f38d"}.bi-file-earmark-x-fill:before{content:"\f38e"}.bi-file-earmark-x:before{content:"\f38f"}.bi-file-earmark-zip-fill:before{content:"\f390"}.bi-file-earmark-zip:before{content:"\f391"}.bi-file-earmark:before{content:"\f392"}.bi-file-easel-fill:before{content:"\f393"}.bi-file-easel:before{content:"\f394"}.bi-file-excel-fill:before{content:"\f395"}.bi-file-excel:before{content:"\f396"}.bi-file-fill:before{content:"\f397"}.bi-file-font-fill:before{content:"\f398"}.bi-file-font:before{content:"\f399"}.bi-file-image-fill:before{content:"\f39a"}.bi-file-image:before{content:"\f39b"}.bi-file-lock-fill:before{content:"\f39c"}.bi-file-lock:before{content:"\f39d"}.bi-file-lock2-fill:before{content:"\f39e"}.bi-file-lock2:before{content:"\f39f"}.bi-file-medical-fill:before{content:"\f3a0"}.bi-file-medical:before{content:"\f3a1"}.bi-file-minus-fill:before{content:"\f3a2"}.bi-file-minus:before{content:"\f3a3"}.bi-file-music-fill:before{content:"\f3a4"}.bi-file-music:before{content:"\f3a5"}.bi-file-person-fill:before{content:"\f3a6"}.bi-file-person:before{content:"\f3a7"}.bi-file-play-fill:before{content:"\f3a8"}.bi-file-play:before{content:"\f3a9"}.bi-file-plus-fill:before{content:"\f3aa"}.bi-file-plus:before{content:"\f3ab"}.bi-file-post-fill:before{content:"\f3ac"}.bi-file-post:before{content:"\f3ad"}.bi-file-ppt-fill:before{content:"\f3ae"}.bi-file-ppt:before{content:"\f3af"}.bi-file-richtext-fill:before{content:"\f3b0"}.bi-file-richtext:before{content:"\f3b1"}.bi-file-ruled-fill:before{content:"\f3b2"}.bi-file-ruled:before{content:"\f3b3"}.bi-file-slides-fill:before{content:"\f3b4"}.bi-file-slides:before{content:"\f3b5"}.bi-file-spreadsheet-fill:before{content:"\f3b6"}.bi-file-spreadsheet:before{content:"\f3b7"}.bi-file-text-fill:before{content:"\f3b8"}.bi-file-text:before{content:"\f3b9"}.bi-file-word-fill:before{content:"\f3ba"}.bi-file-word:before{content:"\f3bb"}.bi-file-x-fill:before{content:"\f3bc"}.bi-file-x:before{content:"\f3bd"}.bi-file-zip-fill:before{content:"\f3be"}.bi-file-zip:before{content:"\f3bf"}.bi-file:before{content:"\f3c0"}.bi-files-alt:before{content:"\f3c1"}.bi-files:before{content:"\f3c2"}.bi-film:before{content:"\f3c3"}.bi-filter-circle-fill:before{content:"\f3c4"}.bi-filter-circle:before{content:"\f3c5"}.bi-filter-left:before{content:"\f3c6"}.bi-filter-right:before{content:"\f3c7"}.bi-filter-square-fill:before{content:"\f3c8"}.bi-filter-square:before{content:"\f3c9"}.bi-filter:before{content:"\f3ca"}.bi-flag-fill:before{content:"\f3cb"}.bi-flag:before{content:"\f3cc"}.bi-flower1:before{content:"\f3cd"}.bi-flower2:before{content:"\f3ce"}.bi-flower3:before{content:"\f3cf"}.bi-folder-check:before{content:"\f3d0"}.bi-folder-fill:before{content:"\f3d1"}.bi-folder-minus:before{content:"\f3d2"}.bi-folder-plus:before{content:"\f3d3"}.bi-folder-symlink-fill:before{content:"\f3d4"}.bi-folder-symlink:before{content:"\f3d5"}.bi-folder-x:before{content:"\f3d6"}.bi-folder:before{content:"\f3d7"}.bi-folder2-open:before{content:"\f3d8"}.bi-folder2:before{content:"\f3d9"}.bi-fonts:before{content:"\f3da"}.bi-forward-fill:before{content:"\f3db"}.bi-forward:before{content:"\f3dc"}.bi-front:before{content:"\f3dd"}.bi-fullscreen-exit:before{content:"\f3de"}.bi-fullscreen:before{content:"\f3df"}.bi-funnel-fill:before{content:"\f3e0"}.bi-funnel:before{content:"\f3e1"}.bi-gear-fill:before{content:"\f3e2"}.bi-gear-wide-connected:before{content:"\f3e3"}.bi-gear-wide:before{content:"\f3e4"}.bi-gear:before{content:"\f3e5"}.bi-gem:before{content:"\f3e6"}.bi-geo-alt-fill:before{content:"\f3e7"}.bi-geo-alt:before{content:"\f3e8"}.bi-geo-fill:before{content:"\f3e9"}.bi-geo:before{content:"\f3ea"}.bi-gift-fill:before{content:"\f3eb"}.bi-gift:before{content:"\f3ec"}.bi-github:before{content:"\f3ed"}.bi-globe:before{content:"\f3ee"}.bi-globe2:before{content:"\f3ef"}.bi-google:before{content:"\f3f0"}.bi-graph-down:before{content:"\f3f1"}.bi-graph-up:before{content:"\f3f2"}.bi-grid-1x2-fill:before{content:"\f3f3"}.bi-grid-1x2:before{content:"\f3f4"}.bi-grid-3x2-gap-fill:before{content:"\f3f5"}.bi-grid-3x2-gap:before{content:"\f3f6"}.bi-grid-3x2:before{content:"\f3f7"}.bi-grid-3x3-gap-fill:before{content:"\f3f8"}.bi-grid-3x3-gap:before{content:"\f3f9"}.bi-grid-3x3:before{content:"\f3fa"}.bi-grid-fill:before{content:"\f3fb"}.bi-grid:before{content:"\f3fc"}.bi-grip-horizontal:before{content:"\f3fd"}.bi-grip-vertical:before{content:"\f3fe"}.bi-hammer:before{content:"\f3ff"}.bi-hand-index-fill:before{content:"\f400"}.bi-hand-index-thumb-fill:before{content:"\f401"}.bi-hand-index-thumb:before{content:"\f402"}.bi-hand-index:before{content:"\f403"}.bi-hand-thumbs-down-fill:before{content:"\f404"}.bi-hand-thumbs-down:before{content:"\f405"}.bi-hand-thumbs-up-fill:before{content:"\f406"}.bi-hand-thumbs-up:before{content:"\f407"}.bi-handbag-fill:before{content:"\f408"}.bi-handbag:before{content:"\f409"}.bi-hash:before{content:"\f40a"}.bi-hdd-fill:before{content:"\f40b"}.bi-hdd-network-fill:before{content:"\f40c"}.bi-hdd-network:before{content:"\f40d"}.bi-hdd-rack-fill:before{content:"\f40e"}.bi-hdd-rack:before{content:"\f40f"}.bi-hdd-stack-fill:before{content:"\f410"}.bi-hdd-stack:before{content:"\f411"}.bi-hdd:before{content:"\f412"}.bi-headphones:before{content:"\f413"}.bi-headset:before{content:"\f414"}.bi-heart-fill:before{content:"\f415"}.bi-heart-half:before{content:"\f416"}.bi-heart:before{content:"\f417"}.bi-heptagon-fill:before{content:"\f418"}.bi-heptagon-half:before{content:"\f419"}.bi-heptagon:before{content:"\f41a"}.bi-hexagon-fill:before{content:"\f41b"}.bi-hexagon-half:before{content:"\f41c"}.bi-hexagon:before{content:"\f41d"}.bi-hourglass-bottom:before{content:"\f41e"}.bi-hourglass-split:before{content:"\f41f"}.bi-hourglass-top:before{content:"\f420"}.bi-hourglass:before{content:"\f421"}.bi-house-door-fill:before{content:"\f422"}.bi-house-door:before{content:"\f423"}.bi-house-fill:before{content:"\f424"}.bi-house:before{content:"\f425"}.bi-hr:before{content:"\f426"}.bi-hurricane:before{content:"\f427"}.bi-image-alt:before{content:"\f428"}.bi-image-fill:before{content:"\f429"}.bi-image:before{content:"\f42a"}.bi-images:before{content:"\f42b"}.bi-inbox-fill:before{content:"\f42c"}.bi-inbox:before{content:"\f42d"}.bi-inboxes-fill:before{content:"\f42e"}.bi-inboxes:before{content:"\f42f"}.bi-info-circle-fill:before{content:"\f430"}.bi-info-circle:before{content:"\f431"}.bi-info-square-fill:before{content:"\f432"}.bi-info-square:before{content:"\f433"}.bi-info:before{content:"\f434"}.bi-input-cursor-text:before{content:"\f435"}.bi-input-cursor:before{content:"\f436"}.bi-instagram:before{content:"\f437"}.bi-intersect:before{content:"\f438"}.bi-journal-album:before{content:"\f439"}.bi-journal-arrow-down:before{content:"\f43a"}.bi-journal-arrow-up:before{content:"\f43b"}.bi-journal-bookmark-fill:before{content:"\f43c"}.bi-journal-bookmark:before{content:"\f43d"}.bi-journal-check:before{content:"\f43e"}.bi-journal-code:before{content:"\f43f"}.bi-journal-medical:before{content:"\f440"}.bi-journal-minus:before{content:"\f441"}.bi-journal-plus:before{content:"\f442"}.bi-journal-richtext:before{content:"\f443"}.bi-journal-text:before{content:"\f444"}.bi-journal-x:before{content:"\f445"}.bi-journal:before{content:"\f446"}.bi-journals:before{content:"\f447"}.bi-joystick:before{content:"\f448"}.bi-justify-left:before{content:"\f449"}.bi-justify-right:before{content:"\f44a"}.bi-justify:before{content:"\f44b"}.bi-kanban-fill:before{content:"\f44c"}.bi-kanban:before{content:"\f44d"}.bi-key-fill:before{content:"\f44e"}.bi-key:before{content:"\f44f"}.bi-keyboard-fill:before{content:"\f450"}.bi-keyboard:before{content:"\f451"}.bi-ladder:before{content:"\f452"}.bi-lamp-fill:before{content:"\f453"}.bi-lamp:before{content:"\f454"}.bi-laptop-fill:before{content:"\f455"}.bi-laptop:before{content:"\f456"}.bi-layer-backward:before{content:"\f457"}.bi-layer-forward:before{content:"\f458"}.bi-layers-fill:before{content:"\f459"}.bi-layers-half:before{content:"\f45a"}.bi-layers:before{content:"\f45b"}.bi-layout-sidebar-inset-reverse:before{content:"\f45c"}.bi-layout-sidebar-inset:before{content:"\f45d"}.bi-layout-sidebar-reverse:before{content:"\f45e"}.bi-layout-sidebar:before{content:"\f45f"}.bi-layout-split:before{content:"\f460"}.bi-layout-text-sidebar-reverse:before{content:"\f461"}.bi-layout-text-sidebar:before{content:"\f462"}.bi-layout-text-window-reverse:before{content:"\f463"}.bi-layout-text-window:before{content:"\f464"}.bi-layout-three-columns:before{content:"\f465"}.bi-layout-wtf:before{content:"\f466"}.bi-life-preserver:before{content:"\f467"}.bi-lightbulb-fill:before{content:"\f468"}.bi-lightbulb-off-fill:before{content:"\f469"}.bi-lightbulb-off:before{content:"\f46a"}.bi-lightbulb:before{content:"\f46b"}.bi-lightning-charge-fill:before{content:"\f46c"}.bi-lightning-charge:before{content:"\f46d"}.bi-lightning-fill:before{content:"\f46e"}.bi-lightning:before{content:"\f46f"}.bi-link-45deg:before{content:"\f470"}.bi-link:before{content:"\f471"}.bi-linkedin:before{content:"\f472"}.bi-list-check:before{content:"\f473"}.bi-list-nested:before{content:"\f474"}.bi-list-ol:before{content:"\f475"}.bi-list-stars:before{content:"\f476"}.bi-list-task:before{content:"\f477"}.bi-list-ul:before{content:"\f478"}.bi-list:before{content:"\f479"}.bi-lock-fill:before{content:"\f47a"}.bi-lock:before{content:"\f47b"}.bi-mailbox:before{content:"\f47c"}.bi-mailbox2:before{content:"\f47d"}.bi-map-fill:before{content:"\f47e"}.bi-map:before{content:"\f47f"}.bi-markdown-fill:before{content:"\f480"}.bi-markdown:before{content:"\f481"}.bi-mask:before{content:"\f482"}.bi-megaphone-fill:before{content:"\f483"}.bi-megaphone:before{content:"\f484"}.bi-menu-app-fill:before{content:"\f485"}.bi-menu-app:before{content:"\f486"}.bi-menu-button-fill:before{content:"\f487"}.bi-menu-button-wide-fill:before{content:"\f488"}.bi-menu-button-wide:before{content:"\f489"}.bi-menu-button:before{content:"\f48a"}.bi-menu-down:before{content:"\f48b"}.bi-menu-up:before{content:"\f48c"}.bi-mic-fill:before{content:"\f48d"}.bi-mic-mute-fill:before{content:"\f48e"}.bi-mic-mute:before{content:"\f48f"}.bi-mic:before{content:"\f490"}.bi-minecart-loaded:before{content:"\f491"}.bi-minecart:before{content:"\f492"}.bi-moisture:before{content:"\f493"}.bi-moon-fill:before{content:"\f494"}.bi-moon-stars-fill:before{content:"\f495"}.bi-moon-stars:before{content:"\f496"}.bi-moon:before{content:"\f497"}.bi-mouse-fill:before{content:"\f498"}.bi-mouse:before{content:"\f499"}.bi-mouse2-fill:before{content:"\f49a"}.bi-mouse2:before{content:"\f49b"}.bi-mouse3-fill:before{content:"\f49c"}.bi-mouse3:before{content:"\f49d"}.bi-music-note-beamed:before{content:"\f49e"}.bi-music-note-list:before{content:"\f49f"}.bi-music-note:before{content:"\f4a0"}.bi-music-player-fill:before{content:"\f4a1"}.bi-music-player:before{content:"\f4a2"}.bi-newspaper:before{content:"\f4a3"}.bi-node-minus-fill:before{content:"\f4a4"}.bi-node-minus:before{content:"\f4a5"}.bi-node-plus-fill:before{content:"\f4a6"}.bi-node-plus:before{content:"\f4a7"}.bi-nut-fill:before{content:"\f4a8"}.bi-nut:before{content:"\f4a9"}.bi-octagon-fill:before{content:"\f4aa"}.bi-octagon-half:before{content:"\f4ab"}.bi-octagon:before{content:"\f4ac"}.bi-option:before{content:"\f4ad"}.bi-outlet:before{content:"\f4ae"}.bi-paint-bucket:before{content:"\f4af"}.bi-palette-fill:before{content:"\f4b0"}.bi-palette:before{content:"\f4b1"}.bi-palette2:before{content:"\f4b2"}.bi-paperclip:before{content:"\f4b3"}.bi-paragraph:before{content:"\f4b4"}.bi-patch-check-fill:before{content:"\f4b5"}.bi-patch-check:before{content:"\f4b6"}.bi-patch-exclamation-fill:before{content:"\f4b7"}.bi-patch-exclamation:before{content:"\f4b8"}.bi-patch-minus-fill:before{content:"\f4b9"}.bi-patch-minus:before{content:"\f4ba"}.bi-patch-plus-fill:before{content:"\f4bb"}.bi-patch-plus:before{content:"\f4bc"}.bi-patch-question-fill:before{content:"\f4bd"}.bi-patch-question:before{content:"\f4be"}.bi-pause-btn-fill:before{content:"\f4bf"}.bi-pause-btn:before{content:"\f4c0"}.bi-pause-circle-fill:before{content:"\f4c1"}.bi-pause-circle:before{content:"\f4c2"}.bi-pause-fill:before{content:"\f4c3"}.bi-pause:before{content:"\f4c4"}.bi-peace-fill:before{content:"\f4c5"}.bi-peace:before{content:"\f4c6"}.bi-pen-fill:before{content:"\f4c7"}.bi-pen:before{content:"\f4c8"}.bi-pencil-fill:before{content:"\f4c9"}.bi-pencil-square:before{content:"\f4ca"}.bi-pencil:before{content:"\f4cb"}.bi-pentagon-fill:before{content:"\f4cc"}.bi-pentagon-half:before{content:"\f4cd"}.bi-pentagon:before{content:"\f4ce"}.bi-people-fill:before{content:"\f4cf"}.bi-people:before{content:"\f4d0"}.bi-percent:before{content:"\f4d1"}.bi-person-badge-fill:before{content:"\f4d2"}.bi-person-badge:before{content:"\f4d3"}.bi-person-bounding-box:before{content:"\f4d4"}.bi-person-check-fill:before{content:"\f4d5"}.bi-person-check:before{content:"\f4d6"}.bi-person-circle:before{content:"\f4d7"}.bi-person-dash-fill:before{content:"\f4d8"}.bi-person-dash:before{content:"\f4d9"}.bi-person-fill:before{content:"\f4da"}.bi-person-lines-fill:before{content:"\f4db"}.bi-person-plus-fill:before{content:"\f4dc"}.bi-person-plus:before{content:"\f4dd"}.bi-person-square:before{content:"\f4de"}.bi-person-x-fill:before{content:"\f4df"}.bi-person-x:before{content:"\f4e0"}.bi-person:before{content:"\f4e1"}.bi-phone-fill:before{content:"\f4e2"}.bi-phone-landscape-fill:before{content:"\f4e3"}.bi-phone-landscape:before{content:"\f4e4"}.bi-phone-vibrate-fill:before{content:"\f4e5"}.bi-phone-vibrate:before{content:"\f4e6"}.bi-phone:before{content:"\f4e7"}.bi-pie-chart-fill:before{content:"\f4e8"}.bi-pie-chart:before{content:"\f4e9"}.bi-pin-angle-fill:before{content:"\f4ea"}.bi-pin-angle:before{content:"\f4eb"}.bi-pin-fill:before{content:"\f4ec"}.bi-pin:before{content:"\f4ed"}.bi-pip-fill:before{content:"\f4ee"}.bi-pip:before{content:"\f4ef"}.bi-play-btn-fill:before{content:"\f4f0"}.bi-play-btn:before{content:"\f4f1"}.bi-play-circle-fill:before{content:"\f4f2"}.bi-play-circle:before{content:"\f4f3"}.bi-play-fill:before{content:"\f4f4"}.bi-play:before{content:"\f4f5"}.bi-plug-fill:before{content:"\f4f6"}.bi-plug:before{content:"\f4f7"}.bi-plus-circle-dotted:before{content:"\f4f8"}.bi-plus-circle-fill:before{content:"\f4f9"}.bi-plus-circle:before{content:"\f4fa"}.bi-plus-square-dotted:before{content:"\f4fb"}.bi-plus-square-fill:before{content:"\f4fc"}.bi-plus-square:before{content:"\f4fd"}.bi-plus:before{content:"\f4fe"}.bi-power:before{content:"\f4ff"}.bi-printer-fill:before{content:"\f500"}.bi-printer:before{content:"\f501"}.bi-puzzle-fill:before{content:"\f502"}.bi-puzzle:before{content:"\f503"}.bi-question-circle-fill:before{content:"\f504"}.bi-question-circle:before{content:"\f505"}.bi-question-diamond-fill:before{content:"\f506"}.bi-question-diamond:before{content:"\f507"}.bi-question-octagon-fill:before{content:"\f508"}.bi-question-octagon:before{content:"\f509"}.bi-question-square-fill:before{content:"\f50a"}.bi-question-square:before{content:"\f50b"}.bi-question:before{content:"\f50c"}.bi-rainbow:before{content:"\f50d"}.bi-receipt-cutoff:before{content:"\f50e"}.bi-receipt:before{content:"\f50f"}.bi-reception-0:before{content:"\f510"}.bi-reception-1:before{content:"\f511"}.bi-reception-2:before{content:"\f512"}.bi-reception-3:before{content:"\f513"}.bi-reception-4:before{content:"\f514"}.bi-record-btn-fill:before{content:"\f515"}.bi-record-btn:before{content:"\f516"}.bi-record-circle-fill:before{content:"\f517"}.bi-record-circle:before{content:"\f518"}.bi-record-fill:before{content:"\f519"}.bi-record:before{content:"\f51a"}.bi-record2-fill:before{content:"\f51b"}.bi-record2:before{content:"\f51c"}.bi-reply-all-fill:before{content:"\f51d"}.bi-reply-all:before{content:"\f51e"}.bi-reply-fill:before{content:"\f51f"}.bi-reply:before{content:"\f520"}.bi-rss-fill:before{content:"\f521"}.bi-rss:before{content:"\f522"}.bi-rulers:before{content:"\f523"}.bi-save-fill:before{content:"\f524"}.bi-save:before{content:"\f525"}.bi-save2-fill:before{content:"\f526"}.bi-save2:before{content:"\f527"}.bi-scissors:before{content:"\f528"}.bi-screwdriver:before{content:"\f529"}.bi-search:before{content:"\f52a"}.bi-segmented-nav:before{content:"\f52b"}.bi-server:before{content:"\f52c"}.bi-share-fill:before{content:"\f52d"}.bi-share:before{content:"\f52e"}.bi-shield-check:before{content:"\f52f"}.bi-shield-exclamation:before{content:"\f530"}.bi-shield-fill-check:before{content:"\f531"}.bi-shield-fill-exclamation:before{content:"\f532"}.bi-shield-fill-minus:before{content:"\f533"}.bi-shield-fill-plus:before{content:"\f534"}.bi-shield-fill-x:before{content:"\f535"}.bi-shield-fill:before{content:"\f536"}.bi-shield-lock-fill:before{content:"\f537"}.bi-shield-lock:before{content:"\f538"}.bi-shield-minus:before{content:"\f539"}.bi-shield-plus:before{content:"\f53a"}.bi-shield-shaded:before{content:"\f53b"}.bi-shield-slash-fill:before{content:"\f53c"}.bi-shield-slash:before{content:"\f53d"}.bi-shield-x:before{content:"\f53e"}.bi-shield:before{content:"\f53f"}.bi-shift-fill:before{content:"\f540"}.bi-shift:before{content:"\f541"}.bi-shop-window:before{content:"\f542"}.bi-shop:before{content:"\f543"}.bi-shuffle:before{content:"\f544"}.bi-signpost-2-fill:before{content:"\f545"}.bi-signpost-2:before{content:"\f546"}.bi-signpost-fill:before{content:"\f547"}.bi-signpost-split-fill:before{content:"\f548"}.bi-signpost-split:before{content:"\f549"}.bi-signpost:before{content:"\f54a"}.bi-sim-fill:before{content:"\f54b"}.bi-sim:before{content:"\f54c"}.bi-skip-backward-btn-fill:before{content:"\f54d"}.bi-skip-backward-btn:before{content:"\f54e"}.bi-skip-backward-circle-fill:before{content:"\f54f"}.bi-skip-backward-circle:before{content:"\f550"}.bi-skip-backward-fill:before{content:"\f551"}.bi-skip-backward:before{content:"\f552"}.bi-skip-end-btn-fill:before{content:"\f553"}.bi-skip-end-btn:before{content:"\f554"}.bi-skip-end-circle-fill:before{content:"\f555"}.bi-skip-end-circle:before{content:"\f556"}.bi-skip-end-fill:before{content:"\f557"}.bi-skip-end:before{content:"\f558"}.bi-skip-forward-btn-fill:before{content:"\f559"}.bi-skip-forward-btn:before{content:"\f55a"}.bi-skip-forward-circle-fill:before{content:"\f55b"}.bi-skip-forward-circle:before{content:"\f55c"}.bi-skip-forward-fill:before{content:"\f55d"}.bi-skip-forward:before{content:"\f55e"}.bi-skip-start-btn-fill:before{content:"\f55f"}.bi-skip-start-btn:before{content:"\f560"}.bi-skip-start-circle-fill:before{content:"\f561"}.bi-skip-start-circle:before{content:"\f562"}.bi-skip-start-fill:before{content:"\f563"}.bi-skip-start:before{content:"\f564"}.bi-slack:before{content:"\f565"}.bi-slash-circle-fill:before{content:"\f566"}.bi-slash-circle:before{content:"\f567"}.bi-slash-square-fill:before{content:"\f568"}.bi-slash-square:before{content:"\f569"}.bi-slash:before{content:"\f56a"}.bi-sliders:before{content:"\f56b"}.bi-smartwatch:before{content:"\f56c"}.bi-snow:before{content:"\f56d"}.bi-snow2:before{content:"\f56e"}.bi-snow3:before{content:"\f56f"}.bi-sort-alpha-down-alt:before{content:"\f570"}.bi-sort-alpha-down:before{content:"\f571"}.bi-sort-alpha-up-alt:before{content:"\f572"}.bi-sort-alpha-up:before{content:"\f573"}.bi-sort-down-alt:before{content:"\f574"}.bi-sort-down:before{content:"\f575"}.bi-sort-numeric-down-alt:before{content:"\f576"}.bi-sort-numeric-down:before{content:"\f577"}.bi-sort-numeric-up-alt:before{content:"\f578"}.bi-sort-numeric-up:before{content:"\f579"}.bi-sort-up-alt:before{content:"\f57a"}.bi-sort-up:before{content:"\f57b"}.bi-soundwave:before{content:"\f57c"}.bi-speaker-fill:before{content:"\f57d"}.bi-speaker:before{content:"\f57e"}.bi-speedometer:before{content:"\f57f"}.bi-speedometer2:before{content:"\f580"}.bi-spellcheck:before{content:"\f581"}.bi-square-fill:before{content:"\f582"}.bi-square-half:before{content:"\f583"}.bi-square:before{content:"\f584"}.bi-stack:before{content:"\f585"}.bi-star-fill:before{content:"\f586"}.bi-star-half:before{content:"\f587"}.bi-star:before{content:"\f588"}.bi-stars:before{content:"\f589"}.bi-stickies-fill:before{content:"\f58a"}.bi-stickies:before{content:"\f58b"}.bi-sticky-fill:before{content:"\f58c"}.bi-sticky:before{content:"\f58d"}.bi-stop-btn-fill:before{content:"\f58e"}.bi-stop-btn:before{content:"\f58f"}.bi-stop-circle-fill:before{content:"\f590"}.bi-stop-circle:before{content:"\f591"}.bi-stop-fill:before{content:"\f592"}.bi-stop:before{content:"\f593"}.bi-stoplights-fill:before{content:"\f594"}.bi-stoplights:before{content:"\f595"}.bi-stopwatch-fill:before{content:"\f596"}.bi-stopwatch:before{content:"\f597"}.bi-subtract:before{content:"\f598"}.bi-suit-club-fill:before{content:"\f599"}.bi-suit-club:before{content:"\f59a"}.bi-suit-diamond-fill:before{content:"\f59b"}.bi-suit-diamond:before{content:"\f59c"}.bi-suit-heart-fill:before{content:"\f59d"}.bi-suit-heart:before{content:"\f59e"}.bi-suit-spade-fill:before{content:"\f59f"}.bi-suit-spade:before{content:"\f5a0"}.bi-sun-fill:before{content:"\f5a1"}.bi-sun:before{content:"\f5a2"}.bi-sunglasses:before{content:"\f5a3"}.bi-sunrise-fill:before{content:"\f5a4"}.bi-sunrise:before{content:"\f5a5"}.bi-sunset-fill:before{content:"\f5a6"}.bi-sunset:before{content:"\f5a7"}.bi-symmetry-horizontal:before{content:"\f5a8"}.bi-symmetry-vertical:before{content:"\f5a9"}.bi-table:before{content:"\f5aa"}.bi-tablet-fill:before{content:"\f5ab"}.bi-tablet-landscape-fill:before{content:"\f5ac"}.bi-tablet-landscape:before{content:"\f5ad"}.bi-tablet:before{content:"\f5ae"}.bi-tag-fill:before{content:"\f5af"}.bi-tag:before{content:"\f5b0"}.bi-tags-fill:before{content:"\f5b1"}.bi-tags:before{content:"\f5b2"}.bi-telegram:before{content:"\f5b3"}.bi-telephone-fill:before{content:"\f5b4"}.bi-telephone-forward-fill:before{content:"\f5b5"}.bi-telephone-forward:before{content:"\f5b6"}.bi-telephone-inbound-fill:before{content:"\f5b7"}.bi-telephone-inbound:before{content:"\f5b8"}.bi-telephone-minus-fill:before{content:"\f5b9"}.bi-telephone-minus:before{content:"\f5ba"}.bi-telephone-outbound-fill:before{content:"\f5bb"}.bi-telephone-outbound:before{content:"\f5bc"}.bi-telephone-plus-fill:before{content:"\f5bd"}.bi-telephone-plus:before{content:"\f5be"}.bi-telephone-x-fill:before{content:"\f5bf"}.bi-telephone-x:before{content:"\f5c0"}.bi-telephone:before{content:"\f5c1"}.bi-terminal-fill:before{content:"\f5c2"}.bi-terminal:before{content:"\f5c3"}.bi-text-center:before{content:"\f5c4"}.bi-text-indent-left:before{content:"\f5c5"}.bi-text-indent-right:before{content:"\f5c6"}.bi-text-left:before{content:"\f5c7"}.bi-text-paragraph:before{content:"\f5c8"}.bi-text-right:before{content:"\f5c9"}.bi-textarea-resize:before{content:"\f5ca"}.bi-textarea-t:before{content:"\f5cb"}.bi-textarea:before{content:"\f5cc"}.bi-thermometer-half:before{content:"\f5cd"}.bi-thermometer-high:before{content:"\f5ce"}.bi-thermometer-low:before{content:"\f5cf"}.bi-thermometer-snow:before{content:"\f5d0"}.bi-thermometer-sun:before{content:"\f5d1"}.bi-thermometer:before{content:"\f5d2"}.bi-three-dots-vertical:before{content:"\f5d3"}.bi-three-dots:before{content:"\f5d4"}.bi-toggle-off:before{content:"\f5d5"}.bi-toggle-on:before{content:"\f5d6"}.bi-toggle2-off:before{content:"\f5d7"}.bi-toggle2-on:before{content:"\f5d8"}.bi-toggles:before{content:"\f5d9"}.bi-toggles2:before{content:"\f5da"}.bi-tools:before{content:"\f5db"}.bi-tornado:before{content:"\f5dc"}.bi-trash-fill:before{content:"\f5dd"}.bi-trash:before{content:"\f5de"}.bi-trash2-fill:before{content:"\f5df"}.bi-trash2:before{content:"\f5e0"}.bi-tree-fill:before{content:"\f5e1"}.bi-tree:before{content:"\f5e2"}.bi-triangle-fill:before{content:"\f5e3"}.bi-triangle-half:before{content:"\f5e4"}.bi-triangle:before{content:"\f5e5"}.bi-trophy-fill:before{content:"\f5e6"}.bi-trophy:before{content:"\f5e7"}.bi-tropical-storm:before{content:"\f5e8"}.bi-truck-flatbed:before{content:"\f5e9"}.bi-truck:before{content:"\f5ea"}.bi-tsunami:before{content:"\f5eb"}.bi-tv-fill:before{content:"\f5ec"}.bi-tv:before{content:"\f5ed"}.bi-twitch:before{content:"\f5ee"}.bi-twitter:before{content:"\f5ef"}.bi-type-bold:before{content:"\f5f0"}.bi-type-h1:before{content:"\f5f1"}.bi-type-h2:before{content:"\f5f2"}.bi-type-h3:before{content:"\f5f3"}.bi-type-italic:before{content:"\f5f4"}.bi-type-strikethrough:before{content:"\f5f5"}.bi-type-underline:before{content:"\f5f6"}.bi-type:before{content:"\f5f7"}.bi-ui-checks-grid:before{content:"\f5f8"}.bi-ui-checks:before{content:"\f5f9"}.bi-ui-radios-grid:before{content:"\f5fa"}.bi-ui-radios:before{content:"\f5fb"}.bi-umbrella-fill:before{content:"\f5fc"}.bi-umbrella:before{content:"\f5fd"}.bi-union:before{content:"\f5fe"}.bi-unlock-fill:before{content:"\f5ff"}.bi-unlock:before{content:"\f600"}.bi-upc-scan:before{content:"\f601"}.bi-upc:before{content:"\f602"}.bi-upload:before{content:"\f603"}.bi-vector-pen:before{content:"\f604"}.bi-view-list:before{content:"\f605"}.bi-view-stacked:before{content:"\f606"}.bi-vinyl-fill:before{content:"\f607"}.bi-vinyl:before{content:"\f608"}.bi-voicemail:before{content:"\f609"}.bi-volume-down-fill:before{content:"\f60a"}.bi-volume-down:before{content:"\f60b"}.bi-volume-mute-fill:before{content:"\f60c"}.bi-volume-mute:before{content:"\f60d"}.bi-volume-off-fill:before{content:"\f60e"}.bi-volume-off:before{content:"\f60f"}.bi-volume-up-fill:before{content:"\f610"}.bi-volume-up:before{content:"\f611"}.bi-vr:before{content:"\f612"}.bi-wallet-fill:before{content:"\f613"}.bi-wallet:before{content:"\f614"}.bi-wallet2:before{content:"\f615"}.bi-watch:before{content:"\f616"}.bi-water:before{content:"\f617"}.bi-whatsapp:before{content:"\f618"}.bi-wifi-1:before{content:"\f619"}.bi-wifi-2:before{content:"\f61a"}.bi-wifi-off:before{content:"\f61b"}.bi-wifi:before{content:"\f61c"}.bi-wind:before{content:"\f61d"}.bi-window-dock:before{content:"\f61e"}.bi-window-sidebar:before{content:"\f61f"}.bi-window:before{content:"\f620"}.bi-wrench:before{content:"\f621"}.bi-x-circle-fill:before{content:"\f622"}.bi-x-circle:before{content:"\f623"}.bi-x-diamond-fill:before{content:"\f624"}.bi-x-diamond:before{content:"\f625"}.bi-x-octagon-fill:before{content:"\f626"}.bi-x-octagon:before{content:"\f627"}.bi-x-square-fill:before{content:"\f628"}.bi-x-square:before{content:"\f629"}.bi-x:before{content:"\f62a"}.bi-youtube:before{content:"\f62b"}.bi-zoom-in:before{content:"\f62c"}.bi-zoom-out:before{content:"\f62d"}.bi-bank:before{content:"\f62e"}.bi-bank2:before{content:"\f62f"}.bi-bell-slash-fill:before{content:"\f630"}.bi-bell-slash:before{content:"\f631"}.bi-cash-coin:before{content:"\f632"}.bi-check-lg:before{content:"\f633"}.bi-coin:before{content:"\f634"}.bi-currency-bitcoin:before{content:"\f635"}.bi-currency-dollar:before{content:"\f636"}.bi-currency-euro:before{content:"\f637"}.bi-currency-exchange:before{content:"\f638"}.bi-currency-pound:before{content:"\f639"}.bi-currency-yen:before{content:"\f63a"}.bi-dash-lg:before{content:"\f63b"}.bi-exclamation-lg:before{content:"\f63c"}.bi-file-earmark-pdf-fill:before{content:"\f63d"}.bi-file-earmark-pdf:before{content:"\f63e"}.bi-file-pdf-fill:before{content:"\f63f"}.bi-file-pdf:before{content:"\f640"}.bi-gender-ambiguous:before{content:"\f641"}.bi-gender-female:before{content:"\f642"}.bi-gender-male:before{content:"\f643"}.bi-gender-trans:before{content:"\f644"}.bi-headset-vr:before{content:"\f645"}.bi-info-lg:before{content:"\f646"}.bi-mastodon:before{content:"\f647"}.bi-messenger:before{content:"\f648"}.bi-piggy-bank-fill:before{content:"\f649"}.bi-piggy-bank:before{content:"\f64a"}.bi-pin-map-fill:before{content:"\f64b"}.bi-pin-map:before{content:"\f64c"}.bi-plus-lg:before{content:"\f64d"}.bi-question-lg:before{content:"\f64e"}.bi-recycle:before{content:"\f64f"}.bi-reddit:before{content:"\f650"}.bi-safe-fill:before{content:"\f651"}.bi-safe2-fill:before{content:"\f652"}.bi-safe2:before{content:"\f653"}.bi-sd-card-fill:before{content:"\f654"}.bi-sd-card:before{content:"\f655"}.bi-skype:before{content:"\f656"}.bi-slash-lg:before{content:"\f657"}.bi-translate:before{content:"\f658"}.bi-x-lg:before{content:"\f659"}.bi-safe:before{content:"\f65a"}.bi-apple:before{content:"\f65b"}.bi-microsoft:before{content:"\f65d"}.bi-windows:before{content:"\f65e"}.bi-behance:before{content:"\f65c"}.bi-dribbble:before{content:"\f65f"}.bi-line:before{content:"\f660"}.bi-medium:before{content:"\f661"}.bi-paypal:before{content:"\f662"}.bi-pinterest:before{content:"\f663"}.bi-signal:before{content:"\f664"}.bi-snapchat:before{content:"\f665"}.bi-spotify:before{content:"\f666"}.bi-stack-overflow:before{content:"\f667"}.bi-strava:before{content:"\f668"}.bi-wordpress:before{content:"\f669"}.bi-vimeo:before{content:"\f66a"}.bi-activity:before{content:"\f66b"}.bi-easel2-fill:before{content:"\f66c"}.bi-easel2:before{content:"\f66d"}.bi-easel3-fill:before{content:"\f66e"}.bi-easel3:before{content:"\f66f"}.bi-fan:before{content:"\f670"}.bi-fingerprint:before{content:"\f671"}.bi-graph-down-arrow:before{content:"\f672"}.bi-graph-up-arrow:before{content:"\f673"}.bi-hypnotize:before{content:"\f674"}.bi-magic:before{content:"\f675"}.bi-person-rolodex:before{content:"\f676"}.bi-person-video:before{content:"\f677"}.bi-person-video2:before{content:"\f678"}.bi-person-video3:before{content:"\f679"}.bi-person-workspace:before{content:"\f67a"}.bi-radioactive:before{content:"\f67b"}.bi-webcam-fill:before{content:"\f67c"}.bi-webcam:before{content:"\f67d"}.bi-yin-yang:before{content:"\f67e"}.bi-bandaid-fill:before{content:"\f680"}.bi-bandaid:before{content:"\f681"}.bi-bluetooth:before{content:"\f682"}.bi-body-text:before{content:"\f683"}.bi-boombox:before{content:"\f684"}.bi-boxes:before{content:"\f685"}.bi-dpad-fill:before{content:"\f686"}.bi-dpad:before{content:"\f687"}.bi-ear-fill:before{content:"\f688"}.bi-ear:before{content:"\f689"}.bi-envelope-check-1:before{content:"\f68a"}.bi-envelope-check-fill:before{content:"\f68b"}.bi-envelope-check:before{content:"\f68c"}.bi-envelope-dash-1:before{content:"\f68d"}.bi-envelope-dash-fill:before{content:"\f68e"}.bi-envelope-dash:before{content:"\f68f"}.bi-envelope-exclamation-1:before{content:"\f690"}.bi-envelope-exclamation-fill:before{content:"\f691"}.bi-envelope-exclamation:before{content:"\f692"}.bi-envelope-plus-fill:before{content:"\f693"}.bi-envelope-plus:before{content:"\f694"}.bi-envelope-slash-1:before{content:"\f695"}.bi-envelope-slash-fill:before{content:"\f696"}.bi-envelope-slash:before{content:"\f697"}.bi-envelope-x-1:before{content:"\f698"}.bi-envelope-x-fill:before{content:"\f699"}.bi-envelope-x:before{content:"\f69a"}.bi-explicit-fill:before{content:"\f69b"}.bi-explicit:before{content:"\f69c"}.bi-git:before{content:"\f69d"}.bi-infinity:before{content:"\f69e"}.bi-list-columns-reverse:before{content:"\f69f"}.bi-list-columns:before{content:"\f6a0"}.bi-meta:before{content:"\f6a1"}.bi-mortorboard-fill:before{content:"\f6a2"}.bi-mortorboard:before{content:"\f6a3"}.bi-nintendo-switch:before{content:"\f6a4"}.bi-pc-display-horizontal:before{content:"\f6a5"}.bi-pc-display:before{content:"\f6a6"}.bi-pc-horizontal:before{content:"\f6a7"}.bi-pc:before{content:"\f6a8"}.bi-playstation:before{content:"\f6a9"}.bi-plus-slash-minus:before{content:"\f6aa"}.bi-projector-fill:before{content:"\f6ab"}.bi-projector:before{content:"\f6ac"}.bi-qr-code-scan:before{content:"\f6ad"}.bi-qr-code:before{content:"\f6ae"}.bi-quora:before{content:"\f6af"}.bi-quote:before{content:"\f6b0"}.bi-robot:before{content:"\f6b1"}.bi-send-check-fill:before{content:"\f6b2"}.bi-send-check:before{content:"\f6b3"}.bi-send-dash-fill:before{content:"\f6b4"}.bi-send-dash:before{content:"\f6b5"}.bi-send-exclamation-1:before{content:"\f6b6"}.bi-send-exclamation-fill:before{content:"\f6b7"}.bi-send-exclamation:before{content:"\f6b8"}.bi-send-fill:before{content:"\f6b9"}.bi-send-plus-fill:before{content:"\f6ba"}.bi-send-plus:before{content:"\f6bb"}.bi-send-slash-fill:before{content:"\f6bc"}.bi-send-slash:before{content:"\f6bd"}.bi-send-x-fill:before{content:"\f6be"}.bi-send-x:before{content:"\f6bf"}.bi-send:before{content:"\f6c0"}.bi-steam:before{content:"\f6c1"}.bi-terminal-dash-1:before{content:"\f6c2"}.bi-terminal-dash:before{content:"\f6c3"}.bi-terminal-plus:before{content:"\f6c4"}.bi-terminal-split:before{content:"\f6c5"}.bi-ticket-detailed-fill:before{content:"\f6c6"}.bi-ticket-detailed:before{content:"\f6c7"}.bi-ticket-fill:before{content:"\f6c8"}.bi-ticket-perforated-fill:before{content:"\f6c9"}.bi-ticket-perforated:before{content:"\f6ca"}.bi-ticket:before{content:"\f6cb"}.bi-tiktok:before{content:"\f6cc"}.bi-window-dash:before{content:"\f6cd"}.bi-window-desktop:before{content:"\f6ce"}.bi-window-fullscreen:before{content:"\f6cf"}.bi-window-plus:before{content:"\f6d0"}.bi-window-split:before{content:"\f6d1"}.bi-window-stack:before{content:"\f6d2"}.bi-window-x:before{content:"\f6d3"}.bi-xbox:before{content:"\f6d4"}.bi-ethernet:before{content:"\f6d5"}.bi-hdmi-fill:before{content:"\f6d6"}.bi-hdmi:before{content:"\f6d7"}.bi-usb-c-fill:before{content:"\f6d8"}.bi-usb-c:before{content:"\f6d9"}.bi-usb-fill:before{content:"\f6da"}.bi-usb-plug-fill:before{content:"\f6db"}.bi-usb-plug:before{content:"\f6dc"}.bi-usb-symbol:before{content:"\f6dd"}.bi-usb:before{content:"\f6de"}.bi-boombox-fill:before{content:"\f6df"}.bi-displayport-1:before{content:"\f6e0"}.bi-displayport:before{content:"\f6e1"}.bi-gpu-card:before{content:"\f6e2"}.bi-memory:before{content:"\f6e3"}.bi-modem-fill:before{content:"\f6e4"}.bi-modem:before{content:"\f6e5"}.bi-motherboard-fill:before{content:"\f6e6"}.bi-motherboard:before{content:"\f6e7"}.bi-optical-audio-fill:before{content:"\f6e8"}.bi-optical-audio:before{content:"\f6e9"}.bi-pci-card:before{content:"\f6ea"}.bi-router-fill:before{content:"\f6eb"}.bi-router:before{content:"\f6ec"}.bi-ssd-fill:before{content:"\f6ed"}.bi-ssd:before{content:"\f6ee"}.bi-thunderbolt-fill:before{content:"\f6ef"}.bi-thunderbolt:before{content:"\f6f0"}.bi-usb-drive-fill:before{content:"\f6f1"}.bi-usb-drive:before{content:"\f6f2"}.bi-usb-micro-fill:before{content:"\f6f3"}.bi-usb-micro:before{content:"\f6f4"}.bi-usb-mini-fill:before{content:"\f6f5"}.bi-usb-mini:before{content:"\f6f6"}.bi-cloud-haze2:before{content:"\f6f7"}.bi-device-hdd-fill:before{content:"\f6f8"}.bi-device-hdd:before{content:"\f6f9"}.bi-device-ssd-fill:before{content:"\f6fa"}.bi-device-ssd:before{content:"\f6fb"}.bi-displayport-fill:before{content:"\f6fc"}.bi-mortarboard-fill:before{content:"\f6fd"}.bi-mortarboard:before{content:"\f6fe"}.bi-terminal-x:before{content:"\f6ff"}.bi-arrow-through-heart-fill:before{content:"\f700"}.bi-arrow-through-heart:before{content:"\f701"}.bi-badge-sd-fill:before{content:"\f702"}.bi-badge-sd:before{content:"\f703"}.bi-bag-heart-fill:before{content:"\f704"}.bi-bag-heart:before{content:"\f705"}.bi-balloon-fill:before{content:"\f706"}.bi-balloon-heart-fill:before{content:"\f707"}.bi-balloon-heart:before{content:"\f708"}.bi-balloon:before{content:"\f709"}.bi-box2-fill:before{content:"\f70a"}.bi-box2-heart-fill:before{content:"\f70b"}.bi-box2-heart:before{content:"\f70c"}.bi-box2:before{content:"\f70d"}.bi-braces-asterisk:before{content:"\f70e"}.bi-calendar-heart-fill:before{content:"\f70f"}.bi-calendar-heart:before{content:"\f710"}.bi-calendar2-heart-fill:before{content:"\f711"}.bi-calendar2-heart:before{content:"\f712"}.bi-chat-heart-fill:before{content:"\f713"}.bi-chat-heart:before{content:"\f714"}.bi-chat-left-heart-fill:before{content:"\f715"}.bi-chat-left-heart:before{content:"\f716"}.bi-chat-right-heart-fill:before{content:"\f717"}.bi-chat-right-heart:before{content:"\f718"}.bi-chat-square-heart-fill:before{content:"\f719"}.bi-chat-square-heart:before{content:"\f71a"}.bi-clipboard-check-fill:before{content:"\f71b"}.bi-clipboard-data-fill:before{content:"\f71c"}.bi-clipboard-fill:before{content:"\f71d"}.bi-clipboard-heart-fill:before{content:"\f71e"}.bi-clipboard-heart:before{content:"\f71f"}.bi-clipboard-minus-fill:before{content:"\f720"}.bi-clipboard-plus-fill:before{content:"\f721"}.bi-clipboard-pulse:before{content:"\f722"}.bi-clipboard-x-fill:before{content:"\f723"}.bi-clipboard2-check-fill:before{content:"\f724"}.bi-clipboard2-check:before{content:"\f725"}.bi-clipboard2-data-fill:before{content:"\f726"}.bi-clipboard2-data:before{content:"\f727"}.bi-clipboard2-fill:before{content:"\f728"}.bi-clipboard2-heart-fill:before{content:"\f729"}.bi-clipboard2-heart:before{content:"\f72a"}.bi-clipboard2-minus-fill:before{content:"\f72b"}.bi-clipboard2-minus:before{content:"\f72c"}.bi-clipboard2-plus-fill:before{content:"\f72d"}.bi-clipboard2-plus:before{content:"\f72e"}.bi-clipboard2-pulse-fill:before{content:"\f72f"}.bi-clipboard2-pulse:before{content:"\f730"}.bi-clipboard2-x-fill:before{content:"\f731"}.bi-clipboard2-x:before{content:"\f732"}.bi-clipboard2:before{content:"\f733"}.bi-emoji-kiss-fill:before{content:"\f734"}.bi-emoji-kiss:before{content:"\f735"}.bi-envelope-heart-fill:before{content:"\f736"}.bi-envelope-heart:before{content:"\f737"}.bi-envelope-open-heart-fill:before{content:"\f738"}.bi-envelope-open-heart:before{content:"\f739"}.bi-envelope-paper-fill:before{content:"\f73a"}.bi-envelope-paper-heart-fill:before{content:"\f73b"}.bi-envelope-paper-heart:before{content:"\f73c"}.bi-envelope-paper:before{content:"\f73d"}.bi-filetype-aac:before{content:"\f73e"}.bi-filetype-ai:before{content:"\f73f"}.bi-filetype-bmp:before{content:"\f740"}.bi-filetype-cs:before{content:"\f741"}.bi-filetype-css:before{content:"\f742"}.bi-filetype-csv:before{content:"\f743"}.bi-filetype-doc:before{content:"\f744"}.bi-filetype-docx:before{content:"\f745"}.bi-filetype-exe:before{content:"\f746"}.bi-filetype-gif:before{content:"\f747"}.bi-filetype-heic:before{content:"\f748"}.bi-filetype-html:before{content:"\f749"}.bi-filetype-java:before{content:"\f74a"}.bi-filetype-jpg:before{content:"\f74b"}.bi-filetype-js:before{content:"\f74c"}.bi-filetype-jsx:before{content:"\f74d"}.bi-filetype-key:before{content:"\f74e"}.bi-filetype-m4p:before{content:"\f74f"}.bi-filetype-md:before{content:"\f750"}.bi-filetype-mdx:before{content:"\f751"}.bi-filetype-mov:before{content:"\f752"}.bi-filetype-mp3:before{content:"\f753"}.bi-filetype-mp4:before{content:"\f754"}.bi-filetype-otf:before{content:"\f755"}.bi-filetype-pdf:before{content:"\f756"}.bi-filetype-php:before{content:"\f757"}.bi-filetype-png:before{content:"\f758"}.bi-filetype-ppt-1:before{content:"\f759"}.bi-filetype-ppt:before{content:"\f75a"}.bi-filetype-psd:before{content:"\f75b"}.bi-filetype-py:before{content:"\f75c"}.bi-filetype-raw:before{content:"\f75d"}.bi-filetype-rb:before{content:"\f75e"}.bi-filetype-sass:before{content:"\f75f"}.bi-filetype-scss:before{content:"\f760"}.bi-filetype-sh:before{content:"\f761"}.bi-filetype-svg:before{content:"\f762"}.bi-filetype-tiff:before{content:"\f763"}.bi-filetype-tsx:before{content:"\f764"}.bi-filetype-ttf:before{content:"\f765"}.bi-filetype-txt:before{content:"\f766"}.bi-filetype-wav:before{content:"\f767"}.bi-filetype-woff:before{content:"\f768"}.bi-filetype-xls-1:before{content:"\f769"}.bi-filetype-xls:before{content:"\f76a"}.bi-filetype-xml:before{content:"\f76b"}.bi-filetype-yml:before{content:"\f76c"}.bi-heart-arrow:before{content:"\f76d"}.bi-heart-pulse-fill:before{content:"\f76e"}.bi-heart-pulse:before{content:"\f76f"}.bi-heartbreak-fill:before{content:"\f770"}.bi-heartbreak:before{content:"\f771"}.bi-hearts:before{content:"\f772"}.bi-hospital-fill:before{content:"\f773"}.bi-hospital:before{content:"\f774"}.bi-house-heart-fill:before{content:"\f775"}.bi-house-heart:before{content:"\f776"}.bi-incognito:before{content:"\f777"}.bi-magnet-fill:before{content:"\f778"}.bi-magnet:before{content:"\f779"}.bi-person-heart:before{content:"\f77a"}.bi-person-hearts:before{content:"\f77b"}.bi-phone-flip:before{content:"\f77c"}.bi-plugin:before{content:"\f77d"}.bi-postage-fill:before{content:"\f77e"}.bi-postage-heart-fill:before{content:"\f77f"}.bi-postage-heart:before{content:"\f780"}.bi-postage:before{content:"\f781"}.bi-postcard-fill:before{content:"\f782"}.bi-postcard-heart-fill:before{content:"\f783"}.bi-postcard-heart:before{content:"\f784"}.bi-postcard:before{content:"\f785"}.bi-search-heart-fill:before{content:"\f786"}.bi-search-heart:before{content:"\f787"}.bi-sliders2-vertical:before{content:"\f788"}.bi-sliders2:before{content:"\f789"}.bi-trash3-fill:before{content:"\f78a"}.bi-trash3:before{content:"\f78b"}.bi-valentine:before{content:"\f78c"}.bi-valentine2:before{content:"\f78d"}.bi-wrench-adjustable-circle-fill:before{content:"\f78e"}.bi-wrench-adjustable-circle:before{content:"\f78f"}.bi-wrench-adjustable:before{content:"\f790"}.bi-filetype-json:before{content:"\f791"}.bi-filetype-pptx:before{content:"\f792"}.bi-filetype-xlsx:before{content:"\f793"} diff --git a/themes/demo/assets/vendor/bootstrap-icons/bootstrap-icons.scss b/themes/demo/assets/vendor/bootstrap-icons/bootstrap-icons.scss new file mode 100644 index 0000000..e041b04 --- /dev/null +++ b/themes/demo/assets/vendor/bootstrap-icons/bootstrap-icons.scss @@ -0,0 +1,5 @@ +// +// Bring in Bootstrap Icons +// + +@import "bootstrap-icons/font/bootstrap-icons"; diff --git a/themes/demo/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff b/themes/demo/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff new file mode 100644 index 0000000..4cd66b7 Binary files /dev/null and b/themes/demo/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff differ diff --git a/themes/demo/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 b/themes/demo/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 new file mode 100644 index 0000000..de01cad Binary files /dev/null and b/themes/demo/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 differ diff --git a/themes/demo/assets/vendor/bootstrap/bootstrap.css b/themes/demo/assets/vendor/bootstrap/bootstrap.css new file mode 100644 index 0000000..62bb16e --- /dev/null +++ b/themes/demo/assets/vendor/bootstrap/bootstrap.css @@ -0,0 +1,7 @@ +@charset "UTF-8"; +/*! + * Bootstrap v5.1.3 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors + * Copyright 2011-2021 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-body-color-rgb:33,37,41;--bs-body-bg-rgb:255,255,255;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg,hsla(0,0%,100%,.15),hsla(0,0%,100%,0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-bg:#fff}*,:after,:before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);background-color:var(--bs-body-bg);color:var(--bs-body-color);font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);margin:0;text-align:var(--bs-body-text-align)}hr{background-color:currentColor;border:0;color:inherit;margin:1rem 0;opacity:.25}hr:not([size]){height:1px}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-weight:500;line-height:1.2;margin-bottom:.5rem;margin-top:0}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}p{margin-bottom:1rem;margin-top:0}abbr[data-bs-original-title],abbr[title]{cursor:help;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{font-style:normal;line-height:inherit;margin-bottom:1rem}ol,ul{padding-left:2rem}dl,ol,ul{margin-bottom:1rem;margin-top:0}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}.small,small{font-size:.875em}.mark,mark{background-color:#fcf8e3;padding:.2em}sub,sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{direction:ltr;font-family:var(--bs-font-monospace);font-size:1em;unicode-bidi:bidi-override}pre{display:block;font-size:.875em;margin-bottom:1rem;margin-top:0;overflow:auto}pre code{color:inherit;font-size:inherit;word-break:normal}code{word-wrap:break-word;color:#d63384;font-size:.875em}a>code{color:inherit}kbd{background-color:#212529;border-radius:.2rem;color:#fff;font-size:.875em;padding:.2rem .4rem}kbd kbd{font-size:1em;font-weight:700;padding:0}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{border-collapse:collapse;caption-side:bottom}caption{color:#6c757d;padding-bottom:.5rem;padding-top:.5rem;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border:0 solid;border-color:inherit}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit;margin:0}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{border-style:none;padding:0}textarea{resize:vertical}fieldset{border:0;margin:0;min-width:0;padding:0}legend{float:left;font-size:calc(1.275rem + .3vw);line-height:inherit;margin-bottom:.5rem;padding:0;width:100%}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}output{display:inline-block}iframe{border:0}summary{cursor:pointer;display:list-item}progress{vertical-align:baseline}[hidden]{display:none!important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-6{font-size:2.5rem}}.list-inline,.list-unstyled{list-style:none;padding-left:0}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{font-size:1.25rem;margin-bottom:1rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{color:#6c757d;font-size:.875em;margin-bottom:1rem;margin-top:-1rem}.blockquote-footer:before{content:"— "}.img-fluid,.img-thumbnail{height:auto;max-width:100%}.img-thumbnail{background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;padding:.25rem}.figure{display:inline-block}.figure-img{line-height:1;margin-bottom:.5rem}.figure-caption{color:#6c757d;font-size:.875em}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{margin-left:auto;margin-right:auto;padding-left:var(--bs-gutter-x,.75rem);padding-right:var(--bs-gutter-x,.75rem);width:100%}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}@media (min-width:1400px){.container,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{max-width:1320px}}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-left:calc(var(--bs-gutter-x)*-.5);margin-right:calc(var(--bs-gutter-x)*-.5);margin-top:calc(var(--bs-gutter-y)*-1)}.row>*{flex-shrink:0;margin-top:var(--bs-gutter-y);max-width:100%;padding-left:calc(var(--bs-gutter-x)*.5);padding-right:calc(var(--bs-gutter-x)*.5);width:100%}.col{flex:1 0 0%}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.6666666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.33333333%}.col-2{flex:0 0 auto;width:16.66666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.33333333%}.col-5{flex:0 0 auto;width:41.66666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.33333333%}.col-8{flex:0 0 auto;width:66.66666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.33333333%}.col-11{flex:0 0 auto;width:91.66666667%}.col-12{flex:0 0 auto;width:100%}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}.g-0,.gx-0{--bs-gutter-x:0}.g-0,.gy-0{--bs-gutter-y:0}.g-1,.gx-1{--bs-gutter-x:0.25rem}.g-1,.gy-1{--bs-gutter-y:0.25rem}.g-2,.gx-2{--bs-gutter-x:0.5rem}.g-2,.gy-2{--bs-gutter-y:0.5rem}.g-3,.gx-3{--bs-gutter-x:1rem}.g-3,.gy-3{--bs-gutter-y:1rem}.g-4,.gx-4{--bs-gutter-x:1.5rem}.g-4,.gy-4{--bs-gutter-y:1.5rem}.g-5,.gx-5{--bs-gutter-x:3rem}.g-5,.gy-5{--bs-gutter-y:3rem}@media (min-width:576px){.col-sm{flex:1 0 0%}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.6666666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.33333333%}.col-sm-2{flex:0 0 auto;width:16.66666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.33333333%}.col-sm-5{flex:0 0 auto;width:41.66666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.33333333%}.col-sm-8{flex:0 0 auto;width:66.66666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.33333333%}.col-sm-11{flex:0 0 auto;width:91.66666667%}.col-sm-12{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}.g-sm-0,.gx-sm-0{--bs-gutter-x:0}.g-sm-0,.gy-sm-0{--bs-gutter-y:0}.g-sm-1,.gx-sm-1{--bs-gutter-x:0.25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y:0.25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x:0.5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y:0.5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x:1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y:1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x:1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y:1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x:3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y:3rem}}@media (min-width:768px){.col-md{flex:1 0 0%}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.6666666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.33333333%}.col-md-2{flex:0 0 auto;width:16.66666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.33333333%}.col-md-5{flex:0 0 auto;width:41.66666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.33333333%}.col-md-8{flex:0 0 auto;width:66.66666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.33333333%}.col-md-11{flex:0 0 auto;width:91.66666667%}.col-md-12{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}.g-md-0,.gx-md-0{--bs-gutter-x:0}.g-md-0,.gy-md-0{--bs-gutter-y:0}.g-md-1,.gx-md-1{--bs-gutter-x:0.25rem}.g-md-1,.gy-md-1{--bs-gutter-y:0.25rem}.g-md-2,.gx-md-2{--bs-gutter-x:0.5rem}.g-md-2,.gy-md-2{--bs-gutter-y:0.5rem}.g-md-3,.gx-md-3{--bs-gutter-x:1rem}.g-md-3,.gy-md-3{--bs-gutter-y:1rem}.g-md-4,.gx-md-4{--bs-gutter-x:1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y:1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x:3rem}.g-md-5,.gy-md-5{--bs-gutter-y:3rem}}@media (min-width:992px){.col-lg{flex:1 0 0%}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.6666666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.33333333%}.col-lg-2{flex:0 0 auto;width:16.66666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.33333333%}.col-lg-5{flex:0 0 auto;width:41.66666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.33333333%}.col-lg-8{flex:0 0 auto;width:66.66666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.33333333%}.col-lg-11{flex:0 0 auto;width:91.66666667%}.col-lg-12{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}.g-lg-0,.gx-lg-0{--bs-gutter-x:0}.g-lg-0,.gy-lg-0{--bs-gutter-y:0}.g-lg-1,.gx-lg-1{--bs-gutter-x:0.25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y:0.25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x:0.5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y:0.5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x:1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y:1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x:1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y:1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x:3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y:3rem}}@media (min-width:1200px){.col-xl{flex:1 0 0%}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.33333333%}.col-xl-2{flex:0 0 auto;width:16.66666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.33333333%}.col-xl-5{flex:0 0 auto;width:41.66666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.33333333%}.col-xl-8{flex:0 0 auto;width:66.66666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.33333333%}.col-xl-11{flex:0 0 auto;width:91.66666667%}.col-xl-12{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}.g-xl-0,.gx-xl-0{--bs-gutter-x:0}.g-xl-0,.gy-xl-0{--bs-gutter-y:0}.g-xl-1,.gx-xl-1{--bs-gutter-x:0.25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y:0.25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x:0.5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y:0.5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x:1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y:1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x:1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y:1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x:3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y:3rem}}@media (min-width:1400px){.col-xxl{flex:1 0 0%}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.33333333%}.col-xxl-2{flex:0 0 auto;width:16.66666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.33333333%}.col-xxl-5{flex:0 0 auto;width:41.66666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.33333333%}.col-xxl-8{flex:0 0 auto;width:66.66666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.33333333%}.col-xxl-11{flex:0 0 auto;width:91.66666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.33333333%}.offset-xxl-2{margin-left:16.66666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.33333333%}.offset-xxl-5{margin-left:41.66666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.33333333%}.offset-xxl-8{margin-left:66.66666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.33333333%}.offset-xxl-11{margin-left:91.66666667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x:0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y:0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x:0.25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y:0.25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x:0.5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y:0.5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x:1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y:1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x:1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y:1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x:3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y:3rem}}.table{--bs-table-bg:transparent;--bs-table-accent-bg:transparent;--bs-table-striped-color:#212529;--bs-table-striped-bg:rgba(0,0,0,.05);--bs-table-active-color:#212529;--bs-table-active-bg:rgba(0,0,0,.1);--bs-table-hover-color:#212529;--bs-table-hover-bg:rgba(0,0,0,.075);border-color:#dee2e6;color:#212529;margin-bottom:1rem;vertical-align:top;width:100%}.table>:not(caption)>*>*{background-color:var(--bs-table-bg);border-bottom-width:1px;box-shadow:inset 0 0 0 9999px var(--bs-table-accent-bg);padding:.5rem}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table>:not(:first-child){border-top:2px solid}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem}.table-bordered>:not(caption)>*{border-width:1px 0}.table-bordered>:not(caption)>*>*{border-width:0 1px}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(odd)>*{--bs-table-accent-bg:var(--bs-table-striped-bg);color:var(--bs-table-striped-color)}.table-active{--bs-table-accent-bg:var(--bs-table-active-bg);color:var(--bs-table-active-color)}.table-hover>tbody>tr:hover>*{--bs-table-accent-bg:var(--bs-table-hover-bg);color:var(--bs-table-hover-color)}.table-primary{--bs-table-bg:#cfe2ff;--bs-table-striped-bg:#c5d7f2;--bs-table-striped-color:#000;--bs-table-active-bg:#bacbe6;--bs-table-active-color:#000;--bs-table-hover-bg:#bfd1ec;--bs-table-hover-color:#000;border-color:#bacbe6;color:#000}.table-secondary{--bs-table-bg:#e2e3e5;--bs-table-striped-bg:#d7d8da;--bs-table-striped-color:#000;--bs-table-active-bg:#cbccce;--bs-table-active-color:#000;--bs-table-hover-bg:#d1d2d4;--bs-table-hover-color:#000;border-color:#cbccce;color:#000}.table-success{--bs-table-bg:#d1e7dd;--bs-table-striped-bg:#c7dbd2;--bs-table-striped-color:#000;--bs-table-active-bg:#bcd0c7;--bs-table-active-color:#000;--bs-table-hover-bg:#c1d6cc;--bs-table-hover-color:#000;border-color:#bcd0c7;color:#000}.table-info{--bs-table-bg:#cff4fc;--bs-table-striped-bg:#c5e8ef;--bs-table-striped-color:#000;--bs-table-active-bg:#badce3;--bs-table-active-color:#000;--bs-table-hover-bg:#bfe2e9;--bs-table-hover-color:#000;border-color:#badce3;color:#000}.table-warning{--bs-table-bg:#fff3cd;--bs-table-striped-bg:#f2e7c3;--bs-table-striped-color:#000;--bs-table-active-bg:#e6dbb9;--bs-table-active-color:#000;--bs-table-hover-bg:#ece1be;--bs-table-hover-color:#000;border-color:#e6dbb9;color:#000}.table-danger{--bs-table-bg:#f8d7da;--bs-table-striped-bg:#eccccf;--bs-table-striped-color:#000;--bs-table-active-bg:#dfc2c4;--bs-table-active-color:#000;--bs-table-hover-bg:#e5c7ca;--bs-table-hover-color:#000;border-color:#dfc2c4;color:#000}.table-light{--bs-table-bg:#f8f9fa;--bs-table-striped-bg:#ecedee;--bs-table-striped-color:#000;--bs-table-active-bg:#dfe0e1;--bs-table-active-color:#000;--bs-table-hover-bg:#e5e6e7;--bs-table-hover-color:#000;border-color:#dfe0e1;color:#000}.table-dark{--bs-table-bg:#212529;--bs-table-striped-bg:#2c3034;--bs-table-striped-color:#fff;--bs-table-active-bg:#373b3e;--bs-table-active-color:#fff;--bs-table-hover-bg:#323539;--bs-table-hover-color:#fff;border-color:#373b3e;color:#fff}.table-responsive{-webkit-overflow-scrolling:touch;overflow-x:auto}@media (max-width:575.98px){.table-responsive-sm{-webkit-overflow-scrolling:touch;overflow-x:auto}}@media (max-width:767.98px){.table-responsive-md{-webkit-overflow-scrolling:touch;overflow-x:auto}}@media (max-width:991.98px){.table-responsive-lg{-webkit-overflow-scrolling:touch;overflow-x:auto}}@media (max-width:1199.98px){.table-responsive-xl{-webkit-overflow-scrolling:touch;overflow-x:auto}}@media (max-width:1399.98px){.table-responsive-xxl{-webkit-overflow-scrolling:touch;overflow-x:auto}}.form-label{margin-bottom:.5rem}.col-form-label{font-size:inherit;line-height:1.5;margin-bottom:0;padding-bottom:calc(.375rem + 1px);padding-top:calc(.375rem + 1px)}.col-form-label-lg{font-size:1.25rem;padding-bottom:calc(.5rem + 1px);padding-top:calc(.5rem + 1px)}.col-form-label-sm{font-size:.875rem;padding-bottom:calc(.25rem + 1px);padding-top:calc(.25rem + 1px)}.form-text{color:#6c757d;font-size:.875em;margin-top:.25rem}.form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-clip:padding-box;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem;color:#212529;display:block;font-size:1rem;font-weight:400;line-height:1.5;padding:.375rem .75rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{background-color:#fff;border-color:#86b7fe;box-shadow:0 0 0 .25rem rgba(13,110,253,.25);color:#212529;outline:0}.form-control::-webkit-date-and-time-value{height:1.5em}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}.form-control::file-selector-button{-webkit-margin-end:.75rem;background-color:#e9ecef;border:0 solid;border-color:inherit;border-inline-end-width:1px;border-radius:0;color:#212529;margin:-.375rem -.75rem;margin-inline-end:.75rem;padding:.375rem .75rem;pointer-events:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::-webkit-file-upload-button{-webkit-transition:none;transition:none}.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:#dde0e3}.form-control::-webkit-file-upload-button{-webkit-margin-end:.75rem;background-color:#e9ecef;border:0 solid;border-color:inherit;border-inline-end-width:1px;border-radius:0;color:#212529;margin:-.375rem -.75rem;margin-inline-end:.75rem;padding:.375rem .75rem;pointer-events:none;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::-webkit-file-upload-button{-webkit-transition:none;transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:#dde0e3}.form-control-plaintext{background-color:transparent;border:solid transparent;border-width:1px 0;color:#212529;display:block;line-height:1.5;margin-bottom:0;padding:.375rem 0;width:100%}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-left:0;padding-right:0}.form-control-sm{border-radius:.2rem;font-size:.875rem;min-height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem}.form-control-sm::file-selector-button{-webkit-margin-end:.5rem;margin:-.25rem -.5rem;margin-inline-end:.5rem;padding:.25rem .5rem}.form-control-sm::-webkit-file-upload-button{-webkit-margin-end:.5rem;margin:-.25rem -.5rem;margin-inline-end:.5rem;padding:.25rem .5rem}.form-control-lg{border-radius:.3rem;font-size:1.25rem;min-height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem}.form-control-lg::file-selector-button{-webkit-margin-end:1rem;margin:-.5rem -1rem;margin-inline-end:1rem;padding:.5rem 1rem}.form-control-lg::-webkit-file-upload-button{-webkit-margin-end:1rem;margin:-.5rem -1rem;margin-inline-end:1rem;padding:.5rem 1rem}textarea.form-control{min-height:calc(1.5em + .75rem + 2px)}textarea.form-control-sm{min-height:calc(1.5em + .5rem + 2px)}textarea.form-control-lg{min-height:calc(1.5em + 1rem + 2px)}.form-control-color{height:auto;padding:.375rem;width:3rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{border-radius:.25rem;height:1.5em}.form-control-color::-webkit-color-swatch{border-radius:.25rem;height:1.5em}.form-select{-moz-padding-start:calc(.75rem - 3px);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3E%3C/svg%3E");background-position:right .75rem center;background-repeat:no-repeat;background-size:16px 12px;border:1px solid #ced4da;border-radius:.25rem;color:#212529;display:block;font-size:1rem;font-weight:400;line-height:1.5;padding:.375rem 2.25rem .375rem .75rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.form-select{transition:none}}.form-select:focus{border-color:#86b7fe;box-shadow:0 0 0 .25rem rgba(13,110,253,.25);outline:0}.form-select[multiple],.form-select[size]:not([size="1"]){background-image:none;padding-right:.75rem}.form-select:disabled{background-color:#e9ecef}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #212529}.form-select-sm{border-radius:.2rem;font-size:.875rem;padding-bottom:.25rem;padding-left:.5rem;padding-top:.25rem}.form-select-lg{border-radius:.3rem;font-size:1.25rem;padding-bottom:.5rem;padding-left:1rem;padding-top:.5rem}.form-check{display:block;margin-bottom:.125rem;min-height:1.5rem;padding-left:1.5em}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-input{color-adjust:exact;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;background-position:50%;background-repeat:no-repeat;background-size:contain;border:1px solid rgba(0,0,0,.25);height:1em;margin-top:.25em;-webkit-print-color-adjust:exact;vertical-align:top;width:1em}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#86b7fe;box-shadow:0 0 0 .25rem rgba(13,110,253,.25);outline:0}.form-check-input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-input:checked[type=checkbox]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3E%3C/svg%3E")}.form-check-input:checked[type=radio]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='2' fill='%23fff'/%3E%3C/svg%3E")}.form-check-input[type=checkbox]:indeterminate{background-color:#0d6efd;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3E%3C/svg%3E");border-color:#0d6efd}.form-check-input:disabled{filter:none;opacity:.5;pointer-events:none}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='rgba(0, 0, 0, 0.25)'/%3E%3C/svg%3E");background-position:0;border-radius:2em;margin-left:-2.5em;transition:background-position .15s ease-in-out;width:2em}@media (prefers-reduced-motion:reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2386b7fe'/%3E%3C/svg%3E")}.form-switch .form-check-input:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E");background-position:100%}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{clip:rect(0,0,0,0);pointer-events:none;position:absolute}.btn-check:disabled+.btn,.btn-check[disabled]+.btn{filter:none;opacity:.65;pointer-events:none}.form-range{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;height:1.5rem;padding:0;width:100%}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;background-color:#0d6efd;border:0;border-radius:1rem;height:1rem;margin-top:-.25rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.form-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b6d4fe}.form-range::-webkit-slider-runnable-track{background-color:#dee2e6;border-color:transparent;border-radius:1rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.form-range::-moz-range-thumb{-moz-appearance:none;appearance:none;background-color:#0d6efd;border:0;border-radius:1rem;height:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.form-range::-moz-range-thumb{-moz-transition:none;transition:none}}.form-range::-moz-range-thumb:active{background-color:#b6d4fe}.form-range::-moz-range-track{background-color:#dee2e6;border-color:transparent;border-radius:1rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.form-range:disabled::-moz-range-thumb{background-color:#adb5bd}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-select{height:calc(3.5rem + 2px);line-height:1.25}.form-floating>label{border:1px solid transparent;height:100%;left:0;padding:1rem .75rem;pointer-events:none;position:absolute;top:0;transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media (prefers-reduced-motion:reduce){.form-floating>label{transition:none}}.form-floating>.form-control{padding:1rem .75rem}.form-floating>.form-control::-moz-placeholder{color:transparent}.form-floating>.form-control:-ms-input-placeholder{color:transparent}.form-floating>.form-control::placeholder{color:transparent}.form-floating>.form-control:not(:-moz-placeholder-shown){padding-bottom:.625rem;padding-top:1.625rem}.form-floating>.form-control:not(:-ms-input-placeholder){padding-bottom:.625rem;padding-top:1.625rem}.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown){padding-bottom:.625rem;padding-top:1.625rem}.form-floating>.form-control:-webkit-autofill{padding-bottom:.625rem;padding-top:1.625rem}.form-floating>.form-select{padding-bottom:.625rem;padding-top:1.625rem}.form-floating>.form-control:not(:-moz-placeholder-shown)~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:not(:-ms-input-placeholder)~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:-webkit-autofill~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.input-group{align-items:stretch;display:flex;flex-wrap:wrap;position:relative;width:100%}.input-group>.form-control,.input-group>.form-select{flex:1 1 auto;min-width:0;position:relative;width:1%}.input-group>.form-control:focus,.input-group>.form-select:focus{z-index:3}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:3}.input-group-text{align-items:center;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem;color:#212529;display:flex;font-size:1rem;font-weight:400;line-height:1.5;padding:.375rem .75rem;text-align:center;white-space:nowrap}.input-group-lg>.btn,.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text{border-radius:.3rem;font-size:1.25rem;padding:.5rem 1rem}.input-group-sm>.btn,.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text{border-radius:.2rem;font-size:.875rem;padding:.25rem .5rem}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu),.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu){border-bottom-right-radius:0;border-top-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){border-bottom-left-radius:0;border-top-left-radius:0;margin-left:-1px}.valid-feedback{color:#198754;display:none;font-size:.875em;margin-top:.25rem;width:100%}.valid-tooltip{background-color:rgba(25,135,84,.9);border-radius:.25rem;color:#fff;display:none;font-size:.875rem;margin-top:.1rem;max-width:100%;padding:.25rem .5rem;position:absolute;top:100%;z-index:5}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:#198754;padding-right:calc(1.5em + .75rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem);padding-right:calc(1.5em + .75rem)}.form-select.is-valid,.was-validated .form-select:valid{border-color:#198754}.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"],.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3E%3C/svg%3E"),url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem);padding-right:4.125rem}.form-select.is-valid:focus,.was-validated .form-select:valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.form-check-input.is-valid,.was-validated .form-check-input:valid{border-color:#198754}.form-check-input.is-valid:checked,.was-validated .form-check-input:valid:checked{background-color:#198754}.form-check-input.is-valid:focus,.was-validated .form-check-input:valid:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#198754}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.input-group .form-control.is-valid,.input-group .form-select.is-valid,.was-validated .input-group .form-control:valid,.was-validated .input-group .form-select:valid{z-index:1}.input-group .form-control.is-valid:focus,.input-group .form-select.is-valid:focus,.was-validated .input-group .form-control:valid:focus,.was-validated .input-group .form-select:valid:focus{z-index:3}.invalid-feedback{color:#dc3545;display:none;font-size:.875em;margin-top:.25rem;width:100%}.invalid-tooltip{background-color:rgba(220,53,69,.9);border-radius:.25rem;color:#fff;display:none;font-size:.875rem;margin-top:.1rem;max-width:100%;padding:.25rem .5rem;position:absolute;top:100%;z-index:5}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:#dc3545;padding-right:calc(1.5em + .75rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem);padding-right:calc(1.5em + .75rem)}.form-select.is-invalid,.was-validated .form-select:invalid{border-color:#dc3545}.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"],.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3E%3C/svg%3E"),url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3E%3C/svg%3E");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem);padding-right:4.125rem}.form-select.is-invalid:focus,.was-validated .form-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.form-check-input.is-invalid,.was-validated .form-check-input:invalid{border-color:#dc3545}.form-check-input.is-invalid:checked,.was-validated .form-check-input:invalid:checked{background-color:#dc3545}.form-check-input.is-invalid:focus,.was-validated .form-check-input:invalid:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.input-group .form-control.is-invalid,.input-group .form-select.is-invalid,.was-validated .input-group .form-control:invalid,.was-validated .input-group .form-select:invalid{z-index:2}.input-group .form-control.is-invalid:focus,.input-group .form-select.is-invalid:focus,.was-validated .input-group .form-control:invalid:focus,.was-validated .input-group .form-select:invalid:focus{z-index:3}.btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;color:#212529;cursor:pointer;display:inline-block;font-size:1rem;font-weight:400;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529}.btn-check:focus+.btn,.btn:focus{box-shadow:0 0 0 .25rem rgba(13,110,253,.25);outline:0}.btn.disabled,.btn:disabled,fieldset:disabled .btn{opacity:.65;pointer-events:none}.btn-primary{background-color:#0d6efd;border-color:#0d6efd;color:#fff}.btn-check:focus+.btn-primary,.btn-primary:focus,.btn-primary:hover{background-color:#0b5ed7;border-color:#0a58ca;color:#fff}.btn-check:focus+.btn-primary,.btn-primary:focus{box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.btn-check:active+.btn-primary,.btn-check:checked+.btn-primary,.btn-primary.active,.btn-primary:active,.show>.btn-primary.dropdown-toggle{background-color:#0a58ca;border-color:#0a53be;color:#fff}.btn-check:active+.btn-primary:focus,.btn-check:checked+.btn-primary:focus,.btn-primary.active:focus,.btn-primary:active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.btn-primary.disabled,.btn-primary:disabled{background-color:#0d6efd;border-color:#0d6efd;color:#fff}.btn-secondary{background-color:#6c757d;border-color:#6c757d;color:#fff}.btn-check:focus+.btn-secondary,.btn-secondary:focus,.btn-secondary:hover{background-color:#5c636a;border-color:#565e64;color:#fff}.btn-check:focus+.btn-secondary,.btn-secondary:focus{box-shadow:0 0 0 .25rem hsla(208,6%,54%,.5)}.btn-check:active+.btn-secondary,.btn-check:checked+.btn-secondary,.btn-secondary.active,.btn-secondary:active,.show>.btn-secondary.dropdown-toggle{background-color:#565e64;border-color:#51585e;color:#fff}.btn-check:active+.btn-secondary:focus,.btn-check:checked+.btn-secondary:focus,.btn-secondary.active:focus,.btn-secondary:active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem hsla(208,6%,54%,.5)}.btn-secondary.disabled,.btn-secondary:disabled{background-color:#6c757d;border-color:#6c757d;color:#fff}.btn-success{background-color:#198754;border-color:#198754;color:#fff}.btn-check:focus+.btn-success,.btn-success:focus,.btn-success:hover{background-color:#157347;border-color:#146c43;color:#fff}.btn-check:focus+.btn-success,.btn-success:focus{box-shadow:0 0 0 .25rem rgba(60,153,110,.5)}.btn-check:active+.btn-success,.btn-check:checked+.btn-success,.btn-success.active,.btn-success:active,.show>.btn-success.dropdown-toggle{background-color:#146c43;border-color:#13653f;color:#fff}.btn-check:active+.btn-success:focus,.btn-check:checked+.btn-success:focus,.btn-success.active:focus,.btn-success:active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(60,153,110,.5)}.btn-success.disabled,.btn-success:disabled{background-color:#198754;border-color:#198754;color:#fff}.btn-info{background-color:#0dcaf0;border-color:#0dcaf0;color:#000}.btn-check:focus+.btn-info,.btn-info:focus,.btn-info:hover{background-color:#31d2f2;border-color:#25cff2;color:#000}.btn-check:focus+.btn-info,.btn-info:focus{box-shadow:0 0 0 .25rem rgba(11,172,204,.5)}.btn-check:active+.btn-info,.btn-check:checked+.btn-info,.btn-info.active,.btn-info:active,.show>.btn-info.dropdown-toggle{background-color:#3dd5f3;border-color:#25cff2;color:#000}.btn-check:active+.btn-info:focus,.btn-check:checked+.btn-info:focus,.btn-info.active:focus,.btn-info:active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(11,172,204,.5)}.btn-info.disabled,.btn-info:disabled{background-color:#0dcaf0;border-color:#0dcaf0;color:#000}.btn-warning{background-color:#ffc107;border-color:#ffc107;color:#000}.btn-check:focus+.btn-warning,.btn-warning:focus,.btn-warning:hover{background-color:#ffca2c;border-color:#ffc720;color:#000}.btn-check:focus+.btn-warning,.btn-warning:focus{box-shadow:0 0 0 .25rem rgba(217,164,6,.5)}.btn-check:active+.btn-warning,.btn-check:checked+.btn-warning,.btn-warning.active,.btn-warning:active,.show>.btn-warning.dropdown-toggle{background-color:#ffcd39;border-color:#ffc720;color:#000}.btn-check:active+.btn-warning:focus,.btn-check:checked+.btn-warning:focus,.btn-warning.active:focus,.btn-warning:active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(217,164,6,.5)}.btn-warning.disabled,.btn-warning:disabled{background-color:#ffc107;border-color:#ffc107;color:#000}.btn-danger{background-color:#dc3545;border-color:#dc3545;color:#fff}.btn-check:focus+.btn-danger,.btn-danger:focus,.btn-danger:hover{background-color:#bb2d3b;border-color:#b02a37;color:#fff}.btn-check:focus+.btn-danger,.btn-danger:focus{box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.btn-check:active+.btn-danger,.btn-check:checked+.btn-danger,.btn-danger.active,.btn-danger:active,.show>.btn-danger.dropdown-toggle{background-color:#b02a37;border-color:#a52834;color:#fff}.btn-check:active+.btn-danger:focus,.btn-check:checked+.btn-danger:focus,.btn-danger.active:focus,.btn-danger:active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{background-color:#dc3545;border-color:#dc3545;color:#fff}.btn-light{background-color:#f8f9fa;border-color:#f8f9fa;color:#000}.btn-check:focus+.btn-light,.btn-light:focus,.btn-light:hover{background-color:#f9fafb;border-color:#f9fafb;color:#000}.btn-check:focus+.btn-light,.btn-light:focus{box-shadow:0 0 0 .25rem hsla(210,2%,83%,.5)}.btn-check:active+.btn-light,.btn-check:checked+.btn-light,.btn-light.active,.btn-light:active,.show>.btn-light.dropdown-toggle{background-color:#f9fafb;border-color:#f9fafb;color:#000}.btn-check:active+.btn-light:focus,.btn-check:checked+.btn-light:focus,.btn-light.active:focus,.btn-light:active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .25rem hsla(210,2%,83%,.5)}.btn-light.disabled,.btn-light:disabled{background-color:#f8f9fa;border-color:#f8f9fa;color:#000}.btn-dark{background-color:#212529;border-color:#212529;color:#fff}.btn-check:focus+.btn-dark,.btn-dark:focus,.btn-dark:hover{background-color:#1c1f23;border-color:#1a1e21;color:#fff}.btn-check:focus+.btn-dark,.btn-dark:focus{box-shadow:0 0 0 .25rem rgba(66,70,73,.5)}.btn-check:active+.btn-dark,.btn-check:checked+.btn-dark,.btn-dark.active,.btn-dark:active,.show>.btn-dark.dropdown-toggle{background-color:#1a1e21;border-color:#191c1f;color:#fff}.btn-check:active+.btn-dark:focus,.btn-check:checked+.btn-dark:focus,.btn-dark.active:focus,.btn-dark:active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(66,70,73,.5)}.btn-dark.disabled,.btn-dark:disabled{background-color:#212529;border-color:#212529;color:#fff}.btn-outline-primary{border-color:#0d6efd;color:#0d6efd}.btn-outline-primary:hover{background-color:#0d6efd;border-color:#0d6efd;color:#fff}.btn-check:focus+.btn-outline-primary,.btn-outline-primary:focus{box-shadow:0 0 0 .25rem rgba(13,110,253,.5)}.btn-check:active+.btn-outline-primary,.btn-check:checked+.btn-outline-primary,.btn-outline-primary.active,.btn-outline-primary.dropdown-toggle.show,.btn-outline-primary:active{background-color:#0d6efd;border-color:#0d6efd;color:#fff}.btn-check:active+.btn-outline-primary:focus,.btn-check:checked+.btn-outline-primary:focus,.btn-outline-primary.active:focus,.btn-outline-primary.dropdown-toggle.show:focus,.btn-outline-primary:active:focus{box-shadow:0 0 0 .25rem rgba(13,110,253,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{background-color:transparent;color:#0d6efd}.btn-outline-secondary{border-color:#6c757d;color:#6c757d}.btn-outline-secondary:hover{background-color:#6c757d;border-color:#6c757d;color:#fff}.btn-check:focus+.btn-outline-secondary,.btn-outline-secondary:focus{box-shadow:0 0 0 .25rem hsla(208,7%,46%,.5)}.btn-check:active+.btn-outline-secondary,.btn-check:checked+.btn-outline-secondary,.btn-outline-secondary.active,.btn-outline-secondary.dropdown-toggle.show,.btn-outline-secondary:active{background-color:#6c757d;border-color:#6c757d;color:#fff}.btn-check:active+.btn-outline-secondary:focus,.btn-check:checked+.btn-outline-secondary:focus,.btn-outline-secondary.active:focus,.btn-outline-secondary.dropdown-toggle.show:focus,.btn-outline-secondary:active:focus{box-shadow:0 0 0 .25rem hsla(208,7%,46%,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{background-color:transparent;color:#6c757d}.btn-outline-success{border-color:#198754;color:#198754}.btn-outline-success:hover{background-color:#198754;border-color:#198754;color:#fff}.btn-check:focus+.btn-outline-success,.btn-outline-success:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.5)}.btn-check:active+.btn-outline-success,.btn-check:checked+.btn-outline-success,.btn-outline-success.active,.btn-outline-success.dropdown-toggle.show,.btn-outline-success:active{background-color:#198754;border-color:#198754;color:#fff}.btn-check:active+.btn-outline-success:focus,.btn-check:checked+.btn-outline-success:focus,.btn-outline-success.active:focus,.btn-outline-success.dropdown-toggle.show:focus,.btn-outline-success:active:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{background-color:transparent;color:#198754}.btn-outline-info{border-color:#0dcaf0;color:#0dcaf0}.btn-outline-info:hover{background-color:#0dcaf0;border-color:#0dcaf0;color:#000}.btn-check:focus+.btn-outline-info,.btn-outline-info:focus{box-shadow:0 0 0 .25rem rgba(13,202,240,.5)}.btn-check:active+.btn-outline-info,.btn-check:checked+.btn-outline-info,.btn-outline-info.active,.btn-outline-info.dropdown-toggle.show,.btn-outline-info:active{background-color:#0dcaf0;border-color:#0dcaf0;color:#000}.btn-check:active+.btn-outline-info:focus,.btn-check:checked+.btn-outline-info:focus,.btn-outline-info.active:focus,.btn-outline-info.dropdown-toggle.show:focus,.btn-outline-info:active:focus{box-shadow:0 0 0 .25rem rgba(13,202,240,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{background-color:transparent;color:#0dcaf0}.btn-outline-warning{border-color:#ffc107;color:#ffc107}.btn-outline-warning:hover{background-color:#ffc107;border-color:#ffc107;color:#000}.btn-check:focus+.btn-outline-warning,.btn-outline-warning:focus{box-shadow:0 0 0 .25rem rgba(255,193,7,.5)}.btn-check:active+.btn-outline-warning,.btn-check:checked+.btn-outline-warning,.btn-outline-warning.active,.btn-outline-warning.dropdown-toggle.show,.btn-outline-warning:active{background-color:#ffc107;border-color:#ffc107;color:#000}.btn-check:active+.btn-outline-warning:focus,.btn-check:checked+.btn-outline-warning:focus,.btn-outline-warning.active:focus,.btn-outline-warning.dropdown-toggle.show:focus,.btn-outline-warning:active:focus{box-shadow:0 0 0 .25rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{background-color:transparent;color:#ffc107}.btn-outline-danger{border-color:#dc3545;color:#dc3545}.btn-outline-danger:hover{background-color:#dc3545;border-color:#dc3545;color:#fff}.btn-check:focus+.btn-outline-danger,.btn-outline-danger:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.5)}.btn-check:active+.btn-outline-danger,.btn-check:checked+.btn-outline-danger,.btn-outline-danger.active,.btn-outline-danger.dropdown-toggle.show,.btn-outline-danger:active{background-color:#dc3545;border-color:#dc3545;color:#fff}.btn-check:active+.btn-outline-danger:focus,.btn-check:checked+.btn-outline-danger:focus,.btn-outline-danger.active:focus,.btn-outline-danger.dropdown-toggle.show:focus,.btn-outline-danger:active:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{background-color:transparent;color:#dc3545}.btn-outline-light{border-color:#f8f9fa;color:#f8f9fa}.btn-outline-light:hover{background-color:#f8f9fa;border-color:#f8f9fa;color:#000}.btn-check:focus+.btn-outline-light,.btn-outline-light:focus{box-shadow:0 0 0 .25rem rgba(248,249,250,.5)}.btn-check:active+.btn-outline-light,.btn-check:checked+.btn-outline-light,.btn-outline-light.active,.btn-outline-light.dropdown-toggle.show,.btn-outline-light:active{background-color:#f8f9fa;border-color:#f8f9fa;color:#000}.btn-check:active+.btn-outline-light:focus,.btn-check:checked+.btn-outline-light:focus,.btn-outline-light.active:focus,.btn-outline-light.dropdown-toggle.show:focus,.btn-outline-light:active:focus{box-shadow:0 0 0 .25rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{background-color:transparent;color:#f8f9fa}.btn-outline-dark{border-color:#212529;color:#212529}.btn-outline-dark:hover{background-color:#212529;border-color:#212529;color:#fff}.btn-check:focus+.btn-outline-dark,.btn-outline-dark:focus{box-shadow:0 0 0 .25rem rgba(33,37,41,.5)}.btn-check:active+.btn-outline-dark,.btn-check:checked+.btn-outline-dark,.btn-outline-dark.active,.btn-outline-dark.dropdown-toggle.show,.btn-outline-dark:active{background-color:#212529;border-color:#212529;color:#fff}.btn-check:active+.btn-outline-dark:focus,.btn-check:checked+.btn-outline-dark:focus,.btn-outline-dark.active:focus,.btn-outline-dark.dropdown-toggle.show:focus,.btn-outline-dark:active:focus{box-shadow:0 0 0 .25rem rgba(33,37,41,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{background-color:transparent;color:#212529}.btn-link{color:#0d6efd;font-weight:400;text-decoration:underline}.btn-link:hover{color:#0a58ca}.btn-link.disabled,.btn-link:disabled{color:#6c757d}.btn-group-lg>.btn,.btn-lg{border-radius:.3rem;font-size:1.25rem;padding:.5rem 1rem}.btn-group-sm>.btn,.btn-sm{border-radius:.2rem;font-size:.875rem;padding:.25rem .5rem}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{height:auto;transition:width .35s ease;width:0}@media (prefers-reduced-motion:reduce){.collapsing.collapse-horizontal{transition:none}}.dropdown,.dropend,.dropstart,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle:after{border-bottom:0;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:.3em solid;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropdown-toggle:empty:after{margin-left:0}.dropdown-menu{background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;color:#212529;display:none;font-size:1rem;list-style:none;margin:0;min-width:10rem;padding:.5rem 0;position:absolute;text-align:left;z-index:1000}.dropdown-menu[data-bs-popper]{left:0;margin-top:.125rem;top:100%}.dropdown-menu-start{--bs-position:start}.dropdown-menu-start[data-bs-popper]{left:0;right:auto}.dropdown-menu-end{--bs-position:end}.dropdown-menu-end[data-bs-popper]{left:auto;right:0}@media (min-width:576px){.dropdown-menu-sm-start{--bs-position:start}.dropdown-menu-sm-start[data-bs-popper]{left:0;right:auto}.dropdown-menu-sm-end{--bs-position:end}.dropdown-menu-sm-end[data-bs-popper]{left:auto;right:0}}@media (min-width:768px){.dropdown-menu-md-start{--bs-position:start}.dropdown-menu-md-start[data-bs-popper]{left:0;right:auto}.dropdown-menu-md-end{--bs-position:end}.dropdown-menu-md-end[data-bs-popper]{left:auto;right:0}}@media (min-width:992px){.dropdown-menu-lg-start{--bs-position:start}.dropdown-menu-lg-start[data-bs-popper]{left:0;right:auto}.dropdown-menu-lg-end{--bs-position:end}.dropdown-menu-lg-end[data-bs-popper]{left:auto;right:0}}@media (min-width:1200px){.dropdown-menu-xl-start{--bs-position:start}.dropdown-menu-xl-start[data-bs-popper]{left:0;right:auto}.dropdown-menu-xl-end{--bs-position:end}.dropdown-menu-xl-end[data-bs-popper]{left:auto;right:0}}@media (min-width:1400px){.dropdown-menu-xxl-start{--bs-position:start}.dropdown-menu-xxl-start[data-bs-popper]{left:0;right:auto}.dropdown-menu-xxl-end{--bs-position:end}.dropdown-menu-xxl-end[data-bs-popper]{left:auto;right:0}}.dropup .dropdown-menu[data-bs-popper]{bottom:100%;margin-bottom:.125rem;margin-top:0;top:auto}.dropup .dropdown-toggle:after{border-bottom:.3em solid;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:0;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropup .dropdown-toggle:empty:after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{left:100%;margin-left:.125rem;margin-top:0;right:auto;top:0}.dropend .dropdown-toggle:after{border-bottom:.3em solid transparent;border-left:.3em solid;border-right:0;border-top:.3em solid transparent;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropend .dropdown-toggle:empty:after{margin-left:0}.dropend .dropdown-toggle:after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{left:auto;margin-right:.125rem;margin-top:0;right:100%;top:0}.dropstart .dropdown-toggle:after{content:"";display:inline-block;display:none;margin-left:.255em;vertical-align:.255em}.dropstart .dropdown-toggle:before{border-bottom:.3em solid transparent;border-right:.3em solid;border-top:.3em solid transparent;content:"";display:inline-block;margin-right:.255em;vertical-align:.255em}.dropstart .dropdown-toggle:empty:after{margin-left:0}.dropstart .dropdown-toggle:before{vertical-align:0}.dropdown-divider{border-top:1px solid rgba(0,0,0,.15);height:0;margin:.5rem 0;overflow:hidden}.dropdown-item{background-color:transparent;border:0;clear:both;color:#212529;display:block;font-weight:400;padding:.25rem 1rem;text-align:inherit;text-decoration:none;white-space:nowrap;width:100%}.dropdown-item:focus,.dropdown-item:hover{background-color:#e9ecef;color:#1e2125}.dropdown-item.active,.dropdown-item:active{background-color:#0d6efd;color:#fff;text-decoration:none}.dropdown-item.disabled,.dropdown-item:disabled{background-color:transparent;color:#adb5bd;pointer-events:none}.dropdown-menu.show{display:block}.dropdown-header{color:#6c757d;display:block;font-size:.875rem;margin-bottom:0;padding:.5rem 1rem;white-space:nowrap}.dropdown-item-text{color:#212529;display:block;padding:.25rem 1rem}.dropdown-menu-dark{background-color:#343a40;border-color:rgba(0,0,0,.15);color:#dee2e6}.dropdown-menu-dark .dropdown-item{color:#dee2e6}.dropdown-menu-dark .dropdown-item:focus,.dropdown-menu-dark .dropdown-item:hover{background-color:hsla(0,0%,100%,.15);color:#fff}.dropdown-menu-dark .dropdown-item.active,.dropdown-menu-dark .dropdown-item:active{background-color:#0d6efd;color:#fff}.dropdown-menu-dark .dropdown-item.disabled,.dropdown-menu-dark .dropdown-item:disabled{color:#adb5bd}.dropdown-menu-dark .dropdown-divider{border-color:rgba(0,0,0,.15)}.dropdown-menu-dark .dropdown-item-text{color:#dee2e6}.dropdown-menu-dark .dropdown-header{color:#adb5bd}.btn-group,.btn-group-vertical{display:inline-flex;position:relative;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{flex:1 1 auto;position:relative}.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn{border-bottom-left-radius:0;border-top-left-radius:0}.dropdown-toggle-split{padding-left:.5625rem;padding-right:.5625rem}.dropdown-toggle-split:after,.dropend .dropdown-toggle-split:after,.dropup .dropdown-toggle-split:after{margin-left:0}.dropstart .dropdown-toggle-split:before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-left:.375rem;padding-right:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-left:.75rem;padding-right:.75rem}.btn-group-vertical{align-items:flex-start;flex-direction:column;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-left-radius:0;border-bottom-right-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn~.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{display:flex;flex-wrap:wrap;list-style:none;margin-bottom:0;padding-left:0}.nav-link{color:#0d6efd;display:block;padding:.5rem 1rem;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link:focus,.nav-link:hover{color:#0a58ca}.nav-link.disabled{color:#6c757d;cursor:default;pointer-events:none}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link{background:none;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem;margin-bottom:-1px}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6;isolation:isolate}.nav-tabs .nav-link.disabled{background-color:transparent;border-color:transparent;color:#6c757d}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{background-color:#fff;border-color:#dee2e6 #dee2e6 #fff;color:#495057}.nav-tabs .dropdown-menu{border-top-left-radius:0;border-top-right-radius:0;margin-top:-1px}.nav-pills .nav-link{background:none;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{background-color:#0d6efd;color:#fff}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-basis:0;flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{align-items:center;display:flex;flex-wrap:wrap;justify-content:space-between;padding-bottom:.5rem;padding-top:.5rem;position:relative}.navbar>.container,.navbar>.container-fluid,.navbar>.container-lg,.navbar>.container-md,.navbar>.container-sm,.navbar>.container-xl,.navbar>.container-xxl{align-items:center;display:flex;flex-wrap:inherit;justify-content:space-between}.navbar-brand{font-size:1.25rem;margin-right:1rem;padding-bottom:.3125rem;padding-top:.3125rem;text-decoration:none;white-space:nowrap}.navbar-nav{display:flex;flex-direction:column;list-style:none;margin-bottom:0;padding-left:0}.navbar-nav .nav-link{padding-left:0;padding-right:0}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-bottom:.5rem;padding-top:.5rem}.navbar-collapse{align-items:center;flex-basis:100%;flex-grow:1}.navbar-toggler{background-color:transparent;border:1px solid transparent;border-radius:.25rem;font-size:1.25rem;line-height:1;padding:.25rem .75rem;transition:box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{box-shadow:0 0 0 .25rem;outline:0;text-decoration:none}.navbar-toggler-icon{background-position:50%;background-repeat:no-repeat;background-size:100%;display:inline-block;height:1.5em;vertical-align:middle;width:1.5em}.navbar-nav-scroll{max-height:var(--bs-scroll-height,75vh);overflow-y:auto}@media (min-width:576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler,.navbar-expand-sm .offcanvas-header{display:none}.navbar-expand-sm .offcanvas{background-color:transparent;border-left:0;border-right:0;bottom:0;flex-grow:1;position:inherit;transform:none;transition:none;visibility:visible!important;z-index:1000}.navbar-expand-sm .offcanvas-bottom,.navbar-expand-sm .offcanvas-top{border-bottom:0;border-top:0;height:auto}.navbar-expand-sm .offcanvas-body{display:flex;flex-grow:0;overflow-y:visible;padding:0}}@media (min-width:768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler,.navbar-expand-md .offcanvas-header{display:none}.navbar-expand-md .offcanvas{background-color:transparent;border-left:0;border-right:0;bottom:0;flex-grow:1;position:inherit;transform:none;transition:none;visibility:visible!important;z-index:1000}.navbar-expand-md .offcanvas-bottom,.navbar-expand-md .offcanvas-top{border-bottom:0;border-top:0;height:auto}.navbar-expand-md .offcanvas-body{display:flex;flex-grow:0;overflow-y:visible;padding:0}}@media (min-width:992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler,.navbar-expand-lg .offcanvas-header{display:none}.navbar-expand-lg .offcanvas{background-color:transparent;border-left:0;border-right:0;bottom:0;flex-grow:1;position:inherit;transform:none;transition:none;visibility:visible!important;z-index:1000}.navbar-expand-lg .offcanvas-bottom,.navbar-expand-lg .offcanvas-top{border-bottom:0;border-top:0;height:auto}.navbar-expand-lg .offcanvas-body{display:flex;flex-grow:0;overflow-y:visible;padding:0}}@media (min-width:1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler,.navbar-expand-xl .offcanvas-header{display:none}.navbar-expand-xl .offcanvas{background-color:transparent;border-left:0;border-right:0;bottom:0;flex-grow:1;position:inherit;transform:none;transition:none;visibility:visible!important;z-index:1000}.navbar-expand-xl .offcanvas-bottom,.navbar-expand-xl .offcanvas-top{border-bottom:0;border-top:0;height:auto}.navbar-expand-xl .offcanvas-body{display:flex;flex-grow:0;overflow-y:visible;padding:0}}@media (min-width:1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler,.navbar-expand-xxl .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas{background-color:transparent;border-left:0;border-right:0;bottom:0;flex-grow:1;position:inherit;transform:none;transition:none;visibility:visible!important;z-index:1000}.navbar-expand-xxl .offcanvas-bottom,.navbar-expand-xxl .offcanvas-top{border-bottom:0;border-top:0;height:auto}.navbar-expand-xxl .offcanvas-body{display:flex;flex-grow:0;overflow-y:visible;padding:0}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler,.navbar-expand .offcanvas-header{display:none}.navbar-expand .offcanvas{background-color:transparent;border-left:0;border-right:0;bottom:0;flex-grow:1;position:inherit;transform:none;transition:none;visibility:visible!important;z-index:1000}.navbar-expand .offcanvas-bottom,.navbar-expand .offcanvas-top{border-bottom:0;border-top:0;height:auto}.navbar-expand .offcanvas-body{display:flex;flex-grow:0;overflow-y:visible;padding:0}.navbar-light .navbar-brand,.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.55)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{border-color:rgba(0,0,0,.1);color:rgba(0,0,0,.55)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3E%3Cpath stroke='rgba(0, 0, 0, 0.55)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.55)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand,.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:hsla(0,0%,100%,.55)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:hsla(0,0%,100%,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:hsla(0,0%,100%,.25)}.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{border-color:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.55)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3E%3Cpath stroke='rgba(255, 255, 255, 0.55)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:hsla(0,0%,100%,.55)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{word-wrap:break-word;background-clip:border-box;background-color:#fff;border:1px solid rgba(0,0,0,.125);border-radius:.25rem;display:flex;flex-direction:column;min-width:0;position:relative}.card>hr{margin-left:0;margin-right:0}.card>.list-group{border-bottom:inherit;border-top:inherit}.card>.list-group:first-child{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px);border-top-width:0}.card>.list-group:last-child{border-bottom-left-radius:calc(.25rem - 1px);border-bottom-right-radius:calc(.25rem - 1px);border-bottom-width:0}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;padding:1rem}.card-title{margin-bottom:.5rem}.card-subtitle{margin-top:-.25rem}.card-subtitle,.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:1rem}.card-header{background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125);margin-bottom:0;padding:.5rem 1rem}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125);padding:.5rem 1rem}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{border-bottom:0;margin-bottom:-.5rem}.card-header-pills,.card-header-tabs{margin-left:-.5rem;margin-right:-.5rem}.card-img-overlay{border-radius:calc(.25rem - 1px);bottom:0;left:0;padding:1rem;position:absolute;right:0;top:0}.card-img,.card-img-bottom,.card-img-top{width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-left-radius:calc(.25rem - 1px);border-bottom-right-radius:calc(.25rem - 1px)}.card-group>.card{margin-bottom:.75rem}@media (min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{border-left:0;margin-left:0}.card-group>.card:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.accordion-button{align-items:center;background-color:#fff;border:0;border-radius:0;color:#212529;display:flex;font-size:1rem;overflow-anchor:none;padding:1rem 1.25rem;position:relative;text-align:left;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,border-radius .15s ease;width:100%}@media (prefers-reduced-motion:reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){background-color:#e7f1ff;box-shadow:inset 0 -1px 0 rgba(0,0,0,.125);color:#0c63e4}.accordion-button:not(.collapsed):after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3E%3Cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3E%3C/svg%3E");transform:rotate(-180deg)}.accordion-button:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3E%3Cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-size:1.25rem;content:"";flex-shrink:0;height:1.25rem;margin-left:auto;transition:transform .2s ease-in-out;width:1.25rem}@media (prefers-reduced-motion:reduce){.accordion-button:after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{border-color:#86b7fe;box-shadow:0 0 0 .25rem rgba(13,110,253,.25);outline:0;z-index:3}.accordion-header{margin-bottom:0}.accordion-item{background-color:#fff;border:1px solid rgba(0,0,0,.125)}.accordion-item:first-of-type{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.accordion-item:first-of-type .accordion-button{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.accordion-item:last-of-type .accordion-button.collapsed{border-bottom-left-radius:calc(.25rem - 1px);border-bottom-right-radius:calc(.25rem - 1px)}.accordion-item:last-of-type .accordion-collapse{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.accordion-body{padding:1rem 1.25rem}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item{border-left:0;border-radius:0;border-right:0}.accordion-flush .accordion-item:first-child{border-top:0}.accordion-flush .accordion-item:last-child{border-bottom:0}.accordion-flush .accordion-item .accordion-button{border-radius:0}.breadcrumb{display:flex;flex-wrap:wrap;list-style:none;margin-bottom:1rem;padding:0}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item:before{color:#6c757d;content:var(--bs-breadcrumb-divider,"/");float:left;padding-right:.5rem}.breadcrumb-item.active{color:#6c757d}.pagination{display:flex;list-style:none;padding-left:0}.page-link{background-color:#fff;border:1px solid #dee2e6;color:#0d6efd;display:block;position:relative;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.page-link{transition:none}}.page-link:hover{border-color:#dee2e6;z-index:2}.page-link:focus,.page-link:hover{background-color:#e9ecef;color:#0a58ca}.page-link:focus{box-shadow:0 0 0 .25rem rgba(13,110,253,.25);outline:0;z-index:3}.page-item:not(:first-child) .page-link{margin-left:-1px}.page-item.active .page-link{background-color:#0d6efd;border-color:#0d6efd;color:#fff;z-index:3}.page-item.disabled .page-link{background-color:#fff;border-color:#dee2e6;color:#6c757d;pointer-events:none}.page-link{padding:.375rem .75rem}.page-item:first-child .page-link{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.page-item:last-child .page-link{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.pagination-lg .page-link{font-size:1.25rem;padding:.75rem 1.5rem}.pagination-lg .page-item:first-child .page-link{border-bottom-left-radius:.3rem;border-top-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-bottom-right-radius:.3rem;border-top-right-radius:.3rem}.pagination-sm .page-link{font-size:.875rem;padding:.25rem .5rem}.pagination-sm .page-item:first-child .page-link{border-bottom-left-radius:.2rem;border-top-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-bottom-right-radius:.2rem;border-top-right-radius:.2rem}.badge{border-radius:.25rem;color:#fff;display:inline-block;font-size:.75em;font-weight:700;line-height:1;padding:.35em .65em;text-align:center;vertical-align:baseline;white-space:nowrap}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{border:1px solid transparent;border-radius:.25rem;margin-bottom:1rem;padding:1rem;position:relative}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{padding:1.25rem 1rem;position:absolute;right:0;top:0;z-index:2}.alert-primary{background-color:#cfe2ff;border-color:#b6d4fe;color:#084298}.alert-primary .alert-link{color:#06357a}.alert-secondary{background-color:#e2e3e5;border-color:#d3d6d8;color:#41464b}.alert-secondary .alert-link{color:#34383c}.alert-success{background-color:#d1e7dd;border-color:#badbcc;color:#0f5132}.alert-success .alert-link{color:#0c4128}.alert-info{background-color:#cff4fc;border-color:#b6effb;color:#055160}.alert-info .alert-link{color:#04414d}.alert-warning{background-color:#fff3cd;border-color:#ffecb5;color:#664d03}.alert-warning .alert-link{color:#523e02}.alert-danger{background-color:#f8d7da;border-color:#f5c2c7;color:#842029}.alert-danger .alert-link{color:#6a1a21}.alert-light{background-color:#fefefe;border-color:#fdfdfe;color:#636464}.alert-light .alert-link{color:#4f5050}.alert-dark{background-color:#d3d3d4;border-color:#bcbebf;color:#141619}.alert-dark .alert-link{color:#101214}@-webkit-keyframes progress-bar-stripes{0%{background-position-x:1rem}}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress{background-color:#e9ecef;border-radius:.25rem;font-size:.75rem;height:1rem}.progress,.progress-bar{display:flex;overflow:hidden}.progress-bar{background-color:#0d6efd;color:#fff;flex-direction:column;justify-content:center;text-align:center;transition:width .6s ease;white-space:nowrap}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.list-group{border-radius:.25rem;display:flex;flex-direction:column;margin-bottom:0;padding-left:0}.list-group-numbered{counter-reset:section;list-style-type:none}.list-group-numbered>li:before{content:counters(section,".") ". ";counter-increment:section}.list-group-item-action{color:#495057;text-align:inherit;width:100%}.list-group-item-action:focus,.list-group-item-action:hover{background-color:#f8f9fa;color:#495057;text-decoration:none;z-index:1}.list-group-item-action:active{background-color:#e9ecef;color:#212529}.list-group-item{background-color:#fff;border:1px solid rgba(0,0,0,.125);color:#212529;display:block;padding:.5rem 1rem;position:relative;text-decoration:none}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{background-color:#fff;color:#6c757d;pointer-events:none}.list-group-item.active{background-color:#0d6efd;border-color:#0d6efd;color:#fff;z-index:2}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{border-top-width:1px;margin-top:-1px}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}@media (min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-md>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{background-color:#cfe2ff;color:#084298}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{background-color:#bacbe6;color:#084298}.list-group-item-primary.list-group-item-action.active{background-color:#084298;border-color:#084298;color:#fff}.list-group-item-secondary{background-color:#e2e3e5;color:#41464b}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{background-color:#cbccce;color:#41464b}.list-group-item-secondary.list-group-item-action.active{background-color:#41464b;border-color:#41464b;color:#fff}.list-group-item-success{background-color:#d1e7dd;color:#0f5132}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{background-color:#bcd0c7;color:#0f5132}.list-group-item-success.list-group-item-action.active{background-color:#0f5132;border-color:#0f5132;color:#fff}.list-group-item-info{background-color:#cff4fc;color:#055160}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{background-color:#badce3;color:#055160}.list-group-item-info.list-group-item-action.active{background-color:#055160;border-color:#055160;color:#fff}.list-group-item-warning{background-color:#fff3cd;color:#664d03}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{background-color:#e6dbb9;color:#664d03}.list-group-item-warning.list-group-item-action.active{background-color:#664d03;border-color:#664d03;color:#fff}.list-group-item-danger{background-color:#f8d7da;color:#842029}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{background-color:#dfc2c4;color:#842029}.list-group-item-danger.list-group-item-action.active{background-color:#842029;border-color:#842029;color:#fff}.list-group-item-light{background-color:#fefefe;color:#636464}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{background-color:#e5e5e5;color:#636464}.list-group-item-light.list-group-item-action.active{background-color:#636464;border-color:#636464;color:#fff}.list-group-item-dark{background-color:#d3d3d4;color:#141619}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{background-color:#bebebf;color:#141619}.list-group-item-dark.list-group-item-action.active{background-color:#141619;border-color:#141619;color:#fff}.btn-close{background:transparent url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3E%3C/svg%3E") 50%/1em auto no-repeat;border:0;border-radius:.25rem;box-sizing:content-box;color:#000;height:1em;opacity:.5;padding:.25em;width:1em}.btn-close:hover{color:#000;opacity:.75;text-decoration:none}.btn-close:focus{box-shadow:0 0 0 .25rem rgba(13,110,253,.25);opacity:1;outline:0}.btn-close.disabled,.btn-close:disabled{opacity:.25;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn-close-white{filter:invert(1) grayscale(100%) brightness(200%)}.toast{background-clip:padding-box;background-color:hsla(0,0%,100%,.85);border:1px solid rgba(0,0,0,.1);border-radius:.25rem;box-shadow:0 .5rem 1rem rgba(0,0,0,.15);font-size:.875rem;max-width:100%;pointer-events:auto;width:350px}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{max-width:100%;pointer-events:none;width:-webkit-max-content;width:-moz-max-content;width:max-content}.toast-container>:not(:last-child){margin-bottom:.75rem}.toast-header{align-items:center;background-clip:padding-box;background-color:hsla(0,0%,100%,.85);border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px);color:#6c757d;display:flex;padding:.5rem .75rem}.toast-header .btn-close{margin-left:.75rem;margin-right:-.375rem}.toast-body{word-wrap:break-word;padding:.75rem}.modal{display:none;height:100%;left:0;outline:0;overflow-x:hidden;overflow-y:auto;position:fixed;top:0;width:100%;z-index:1055}.modal-dialog{margin:.5rem;pointer-events:none;position:relative;width:auto}.modal.fade .modal-dialog{transform:translateY(-50px);transition:transform .3s ease-out}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{align-items:center;display:flex;min-height:calc(100% - 1rem)}.modal-content{background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;display:flex;flex-direction:column;outline:0;pointer-events:auto;position:relative;width:100%}.modal-backdrop{background-color:#000;height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:1050}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{align-items:center;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px);display:flex;flex-shrink:0;justify-content:space-between;padding:1rem}.modal-header .btn-close{margin:-.5rem -.5rem -.5rem auto;padding:.5rem}.modal-title{line-height:1.5;margin-bottom:0}.modal-body{flex:1 1 auto;padding:1rem;position:relative}.modal-footer{align-items:center;border-bottom-left-radius:calc(.3rem - 1px);border-bottom-right-radius:calc(.3rem - 1px);border-top:1px solid #dee2e6;display:flex;flex-shrink:0;flex-wrap:wrap;justify-content:flex-end;padding:.75rem}.modal-footer>*{margin:.25rem}@media (min-width:576px){.modal-dialog{margin:1.75rem auto;max-width:500px}.modal-dialog-scrollable{height:calc(100% - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.modal-fullscreen{height:100%;margin:0;max-width:none;width:100vw}.modal-fullscreen .modal-content{border:0;border-radius:0;height:100%}.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}.modal-fullscreen .modal-footer{border-radius:0}@media (max-width:575.98px){.modal-fullscreen-sm-down{height:100%;margin:0;max-width:none;width:100vw}.modal-fullscreen-sm-down .modal-content{border:0;border-radius:0;height:100%}.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}.modal-fullscreen-sm-down .modal-footer{border-radius:0}}@media (max-width:767.98px){.modal-fullscreen-md-down{height:100%;margin:0;max-width:none;width:100vw}.modal-fullscreen-md-down .modal-content{border:0;border-radius:0;height:100%}.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}.modal-fullscreen-md-down .modal-footer{border-radius:0}}@media (max-width:991.98px){.modal-fullscreen-lg-down{height:100%;margin:0;max-width:none;width:100vw}.modal-fullscreen-lg-down .modal-content{border:0;border-radius:0;height:100%}.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}.modal-fullscreen-lg-down .modal-footer{border-radius:0}}@media (max-width:1199.98px){.modal-fullscreen-xl-down{height:100%;margin:0;max-width:none;width:100vw}.modal-fullscreen-xl-down .modal-content{border:0;border-radius:0;height:100%}.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}.modal-fullscreen-xl-down .modal-footer{border-radius:0}}@media (max-width:1399.98px){.modal-fullscreen-xxl-down{height:100%;margin:0;max-width:none;width:100vw}.modal-fullscreen-xxl-down .modal-content{border:0;border-radius:0;height:100%}.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}.modal-fullscreen-xxl-down .modal-footer{border-radius:0}}.tooltip{word-wrap:break-word;display:block;font-family:var(--bs-font-sans-serif);font-size:.875rem;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.5;margin:0;opacity:0;position:absolute;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;z-index:1080}.tooltip.show{opacity:.9}.tooltip .tooltip-arrow{display:block;height:.4rem;position:absolute;width:.8rem}.tooltip .tooltip-arrow:before{border-color:transparent;border-style:solid;content:"";position:absolute}.bs-tooltip-auto[data-popper-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow,.bs-tooltip-top .tooltip-arrow{bottom:0}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow:before,.bs-tooltip-top .tooltip-arrow:before{border-top-color:#000;border-width:.4rem .4rem 0;top:-1px}.bs-tooltip-auto[data-popper-placement^=right],.bs-tooltip-end{padding:0 .4rem}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow,.bs-tooltip-end .tooltip-arrow{height:.8rem;left:0;width:.4rem}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow:before,.bs-tooltip-end .tooltip-arrow:before{border-right-color:#000;border-width:.4rem .4rem .4rem 0;right:-1px}.bs-tooltip-auto[data-popper-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow,.bs-tooltip-bottom .tooltip-arrow{top:0}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow:before,.bs-tooltip-bottom .tooltip-arrow:before{border-bottom-color:#000;border-width:0 .4rem .4rem;bottom:-1px}.bs-tooltip-auto[data-popper-placement^=left],.bs-tooltip-start{padding:0 .4rem}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow,.bs-tooltip-start .tooltip-arrow{height:.8rem;right:0;width:.4rem}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow:before,.bs-tooltip-start .tooltip-arrow:before{border-left-color:#000;border-width:.4rem 0 .4rem .4rem;left:-1px}.tooltip-inner{background-color:#000;border-radius:.25rem;color:#fff;max-width:200px;padding:.25rem .5rem;text-align:center}.popover{word-wrap:break-word;background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;display:block;font-family:var(--bs-font-sans-serif);font-size:.875rem;font-style:normal;font-weight:400;left:0;letter-spacing:normal;line-break:auto;line-height:1.5;max-width:276px;position:absolute;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;top:0;white-space:normal;word-break:normal;word-spacing:normal;z-index:1070}.popover .popover-arrow{display:block;height:.5rem;position:absolute;width:1rem}.popover .popover-arrow:after,.popover .popover-arrow:before{border-color:transparent;border-style:solid;content:"";display:block;position:absolute}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow,.bs-popover-top>.popover-arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:before,.bs-popover-top>.popover-arrow:before{border-top-color:rgba(0,0,0,.25);border-width:.5rem .5rem 0;bottom:0}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:after,.bs-popover-top>.popover-arrow:after{border-top-color:#fff;border-width:.5rem .5rem 0;bottom:1px}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow,.bs-popover-end>.popover-arrow{height:1rem;left:calc(-.5rem - 1px);width:.5rem}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:before,.bs-popover-end>.popover-arrow:before{border-right-color:rgba(0,0,0,.25);border-width:.5rem .5rem .5rem 0;left:0}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:after,.bs-popover-end>.popover-arrow:after{border-right-color:#fff;border-width:.5rem .5rem .5rem 0;left:1px}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow,.bs-popover-bottom>.popover-arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:before,.bs-popover-bottom>.popover-arrow:before{border-bottom-color:rgba(0,0,0,.25);border-width:0 .5rem .5rem;top:0}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:after,.bs-popover-bottom>.popover-arrow:after{border-bottom-color:#fff;border-width:0 .5rem .5rem;top:1px}.bs-popover-auto[data-popper-placement^=bottom] .popover-header:before,.bs-popover-bottom .popover-header:before{border-bottom:1px solid #f0f0f0;content:"";display:block;left:50%;margin-left:-.5rem;position:absolute;top:0;width:1rem}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow,.bs-popover-start>.popover-arrow{height:1rem;right:calc(-.5rem - 1px);width:.5rem}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:before,.bs-popover-start>.popover-arrow:before{border-left-color:rgba(0,0,0,.25);border-width:.5rem 0 .5rem .5rem;right:0}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:after,.bs-popover-start>.popover-arrow:after{border-left-color:#fff;border-width:.5rem 0 .5rem .5rem;right:1px}.popover-header{background-color:#f0f0f0;border-bottom:1px solid rgba(0,0,0,.2);border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px);font-size:1rem;margin-bottom:0;padding:.5rem 1rem}.popover-header:empty{display:none}.popover-body{color:#212529;padding:1rem}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{overflow:hidden;position:relative;width:100%}.carousel-inner:after{clear:both;content:"";display:block}.carousel-item{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:none;float:left;margin-right:-100%;position:relative;transition:transform .6s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-end,.carousel-item-next:not(.carousel-item-start){transform:translateX(100%)}.active.carousel-item-start,.carousel-item-prev:not(.carousel-item-end){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transform:none;transition-property:opacity}.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end,.carousel-fade .carousel-item.active{opacity:1;z-index:1}.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{opacity:0;transition:opacity 0s .6s;z-index:0}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{transition:none}}.carousel-control-next,.carousel-control-prev{align-items:center;background:none;border:0;bottom:0;color:#fff;display:flex;justify-content:center;opacity:.5;padding:0;position:absolute;text-align:center;top:0;transition:opacity .15s ease;width:15%;z-index:1}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;opacity:.9;outline:0;text-decoration:none}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{background-position:50%;background-repeat:no-repeat;background-size:100% 100%;display:inline-block;height:2rem;width:2rem}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3E%3Cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3E%3Cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3E%3C/svg%3E")}.carousel-indicators{bottom:0;display:flex;justify-content:center;left:0;list-style:none;margin-bottom:1rem;margin-left:15%;margin-right:15%;padding:0;position:absolute;right:0;z-index:2}.carousel-indicators [data-bs-target]{background-clip:padding-box;background-color:#fff;border:0;border-bottom:10px solid transparent;border-top:10px solid transparent;box-sizing:content-box;cursor:pointer;flex:0 1 auto;height:3px;margin-left:3px;margin-right:3px;opacity:.5;padding:0;text-indent:-999px;transition:opacity .6s ease;width:30px}@media (prefers-reduced-motion:reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{bottom:1.25rem;color:#fff;left:15%;padding-bottom:1.25rem;padding-top:1.25rem;position:absolute;right:15%;text-align:center}.carousel-dark .carousel-control-next-icon,.carousel-dark .carousel-control-prev-icon{filter:invert(1) grayscale(100)}.carousel-dark .carousel-indicators [data-bs-target]{background-color:#000}.carousel-dark .carousel-caption{color:#000}@-webkit-keyframes spinner-border{to{transform:rotate(1turn)}}@keyframes spinner-border{to{transform:rotate(1turn)}}.spinner-border{-webkit-animation:spinner-border .75s linear infinite;animation:spinner-border .75s linear infinite;border:.25em solid;border-radius:50%;border-right:.25em solid transparent;display:inline-block;height:2rem;vertical-align:-.125em;width:2rem}.spinner-border-sm{border-width:.2em;height:1rem;width:1rem}@-webkit-keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{-webkit-animation:spinner-grow .75s linear infinite;animation:spinner-grow .75s linear infinite;background-color:currentColor;border-radius:50%;display:inline-block;height:2rem;opacity:0;vertical-align:-.125em;width:2rem}.spinner-grow-sm{height:1rem;width:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{-webkit-animation-duration:1.5s;animation-duration:1.5s}}.offcanvas{background-clip:padding-box;background-color:#fff;bottom:0;display:flex;flex-direction:column;max-width:100%;outline:0;position:fixed;transition:transform .3s ease-in-out;visibility:hidden;z-index:1045}@media (prefers-reduced-motion:reduce){.offcanvas{transition:none}}.offcanvas-backdrop{background-color:#000;height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:1040}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{align-items:center;display:flex;justify-content:space-between;padding:1rem}.offcanvas-header .btn-close{margin-bottom:-.5rem;margin-right:-.5rem;margin-top:-.5rem;padding:.5rem}.offcanvas-title{line-height:1.5;margin-bottom:0}.offcanvas-body{flex-grow:1;overflow-y:auto;padding:1rem}.offcanvas-start{border-right:1px solid rgba(0,0,0,.2);left:0;top:0;transform:translateX(-100%);width:400px}.offcanvas-end{border-left:1px solid rgba(0,0,0,.2);right:0;top:0;transform:translateX(100%);width:400px}.offcanvas-top{border-bottom:1px solid rgba(0,0,0,.2);top:0;transform:translateY(-100%)}.offcanvas-bottom,.offcanvas-top{height:30vh;left:0;max-height:100%;right:0}.offcanvas-bottom{border-top:1px solid rgba(0,0,0,.2);transform:translateY(100%)}.offcanvas.show{transform:none}.placeholder{background-color:currentColor;cursor:wait;display:inline-block;min-height:1em;opacity:.5;vertical-align:middle}.placeholder.btn:before{content:"";display:inline-block}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{-webkit-animation:placeholder-glow 2s ease-in-out infinite;animation:placeholder-glow 2s ease-in-out infinite}@-webkit-keyframes placeholder-glow{50%{opacity:.2}}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{-webkit-animation:placeholder-wave 2s linear infinite;animation:placeholder-wave 2s linear infinite;-webkit-mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,.8) 75%,#000 95%);mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,.8) 75%,#000 95%);-webkit-mask-size:200% 100%;mask-size:200% 100%}@-webkit-keyframes placeholder-wave{to{-webkit-mask-position:-200% 0;mask-position:-200% 0}}@keyframes placeholder-wave{to{-webkit-mask-position:-200% 0;mask-position:-200% 0}}.clearfix:after{clear:both;content:"";display:block}.link-primary{color:#0d6efd}.link-primary:focus,.link-primary:hover{color:#0a58ca}.link-secondary{color:#6c757d}.link-secondary:focus,.link-secondary:hover{color:#565e64}.link-success{color:#198754}.link-success:focus,.link-success:hover{color:#146c43}.link-info{color:#0dcaf0}.link-info:focus,.link-info:hover{color:#3dd5f3}.link-warning{color:#ffc107}.link-warning:focus,.link-warning:hover{color:#ffcd39}.link-danger{color:#dc3545}.link-danger:focus,.link-danger:hover{color:#b02a37}.link-light{color:#f8f9fa}.link-light:focus,.link-light:hover{color:#f9fafb}.link-dark{color:#212529}.link-dark:focus,.link-dark:hover{color:#1a1e21}.ratio{position:relative;width:100%}.ratio:before{content:"";display:block;padding-top:var(--bs-aspect-ratio)}.ratio>*{height:100%;left:0;position:absolute;top:0;width:100%}.ratio-1x1{--bs-aspect-ratio:100%}.ratio-4x3{--bs-aspect-ratio:75%}.ratio-16x9{--bs-aspect-ratio:56.25%}.ratio-21x9{--bs-aspect-ratio:42.8571428571%}.fixed-top{top:0}.fixed-bottom,.fixed-top{left:0;position:fixed;right:0;z-index:1030}.fixed-bottom{bottom:0}.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}@media (min-width:576px){.sticky-sm-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:768px){.sticky-md-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:992px){.sticky-lg-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:1200px){.sticky-xl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:1400px){.sticky-xxl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.hstack{align-items:center;flex-direction:row}.hstack,.vstack{align-self:stretch;display:flex}.vstack{flex:1 1 auto;flex-direction:column}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;margin:-1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.stretched-link:after{bottom:0;content:"";left:0;position:absolute;right:0;top:0;z-index:1}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{align-self:stretch;background-color:currentColor;display:inline-block;min-height:1em;opacity:.25;width:1px}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.float-start{float:left!important}.float-end{float:right!important}.float-none{float:none!important}.opacity-0{opacity:0!important}.opacity-25{opacity:.25!important}.opacity-50{opacity:.5!important}.opacity-75{opacity:.75!important}.opacity-100{opacity:1!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-scroll{overflow:scroll!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-grid{display:grid!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}.d-none{display:none!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.top-0{top:0!important}.top-50{top:50%!important}.top-100{top:100%!important}.bottom-0{bottom:0!important}.bottom-50{bottom:50%!important}.bottom-100{bottom:100%!important}.start-0{left:0!important}.start-50{left:50%!important}.start-100{left:100%!important}.end-0{right:0!important}.end-50{right:50%!important}.end-100{right:100%!important}.translate-middle{transform:translate(-50%,-50%)!important}.translate-middle-x{transform:translateX(-50%)!important}.translate-middle-y{transform:translateY(-50%)!important}.border{border:1px solid #dee2e6!important}.border-0{border:0!important}.border-top{border-top:1px solid #dee2e6!important}.border-top-0{border-top:0!important}.border-end{border-right:1px solid #dee2e6!important}.border-end-0{border-right:0!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-bottom-0{border-bottom:0!important}.border-start{border-left:1px solid #dee2e6!important}.border-start-0{border-left:0!important}.border-primary{border-color:#0d6efd!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#198754!important}.border-info{border-color:#0dcaf0!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#212529!important}.border-white{border-color:#fff!important}.border-1{border-width:1px!important}.border-2{border-width:2px!important}.border-3{border-width:3px!important}.border-4{border-width:4px!important}.border-5{border-width:5px!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mh-100{max-height:100%!important}.vh-100{height:100vh!important}.min-vh-100{min-height:100vh!important}.flex-fill{flex:1 1 auto!important}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:1rem!important}.gap-4{gap:1.5rem!important}.gap-5{gap:3rem!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.justify-content-evenly{justify-content:space-evenly!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}.order-first{order:-1!important}.order-0{order:0!important}.order-1{order:1!important}.order-2{order:2!important}.order-3{order:3!important}.order-4{order:4!important}.order-5{order:5!important}.order-last{order:6!important}.m-0{margin:0!important}.m-1{margin:.25rem!important}.m-2{margin:.5rem!important}.m-3{margin:1rem!important}.m-4{margin:1.5rem!important}.m-5{margin:3rem!important}.m-auto{margin:auto!important}.mx-0{margin-left:0!important;margin-right:0!important}.mx-1{margin-left:.25rem!important;margin-right:.25rem!important}.mx-2{margin-left:.5rem!important;margin-right:.5rem!important}.mx-3{margin-left:1rem!important;margin-right:1rem!important}.mx-4{margin-left:1.5rem!important;margin-right:1.5rem!important}.mx-5{margin-left:3rem!important;margin-right:3rem!important}.mx-auto{margin-left:auto!important;margin-right:auto!important}.my-0{margin-bottom:0!important;margin-top:0!important}.my-1{margin-bottom:.25rem!important;margin-top:.25rem!important}.my-2{margin-bottom:.5rem!important;margin-top:.5rem!important}.my-3{margin-bottom:1rem!important;margin-top:1rem!important}.my-4{margin-bottom:1.5rem!important;margin-top:1.5rem!important}.my-5{margin-bottom:3rem!important;margin-top:3rem!important}.my-auto{margin-bottom:auto!important;margin-top:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:3rem!important}.mt-auto{margin-top:auto!important}.me-0{margin-right:0!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.me-3{margin-right:1rem!important}.me-4{margin-right:1.5rem!important}.me-5{margin-right:3rem!important}.me-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:3rem!important}.mb-auto{margin-bottom:auto!important}.ms-0{margin-left:0!important}.ms-1{margin-left:.25rem!important}.ms-2{margin-left:.5rem!important}.ms-3{margin-left:1rem!important}.ms-4{margin-left:1.5rem!important}.ms-5{margin-left:3rem!important}.ms-auto{margin-left:auto!important}.p-0{padding:0!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:3rem!important}.px-0{padding-left:0!important;padding-right:0!important}.px-1{padding-left:.25rem!important;padding-right:.25rem!important}.px-2{padding-left:.5rem!important;padding-right:.5rem!important}.px-3{padding-left:1rem!important;padding-right:1rem!important}.px-4{padding-left:1.5rem!important;padding-right:1.5rem!important}.px-5{padding-left:3rem!important;padding-right:3rem!important}.py-0{padding-bottom:0!important;padding-top:0!important}.py-1{padding-bottom:.25rem!important;padding-top:.25rem!important}.py-2{padding-bottom:.5rem!important;padding-top:.5rem!important}.py-3{padding-bottom:1rem!important;padding-top:1rem!important}.py-4{padding-bottom:1.5rem!important;padding-top:1.5rem!important}.py-5{padding-bottom:3rem!important;padding-top:3rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:3rem!important}.pe-0{padding-right:0!important}.pe-1{padding-right:.25rem!important}.pe-2{padding-right:.5rem!important}.pe-3{padding-right:1rem!important}.pe-4{padding-right:1.5rem!important}.pe-5{padding-right:3rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-3{padding-bottom:1rem!important}.pb-4{padding-bottom:1.5rem!important}.pb-5{padding-bottom:3rem!important}.ps-0{padding-left:0!important}.ps-1{padding-left:.25rem!important}.ps-2{padding-left:.5rem!important}.ps-3{padding-left:1rem!important}.ps-4{padding-left:1.5rem!important}.ps-5{padding-left:3rem!important}.font-monospace{font-family:var(--bs-font-monospace)!important}.fs-1{font-size:calc(1.375rem + 1.5vw)!important}.fs-2{font-size:calc(1.325rem + .9vw)!important}.fs-3{font-size:calc(1.3rem + .6vw)!important}.fs-4{font-size:calc(1.275rem + .3vw)!important}.fs-5{font-size:1.25rem!important}.fs-6{font-size:1rem!important}.fst-italic{font-style:italic!important}.fst-normal{font-style:normal!important}.fw-light{font-weight:300!important}.fw-lighter{font-weight:lighter!important}.fw-normal{font-weight:400!important}.fw-bold{font-weight:700!important}.fw-bolder{font-weight:bolder!important}.lh-1{line-height:1!important}.lh-sm{line-height:1.25!important}.lh-base{line-height:1.5!important}.lh-lg{line-height:2!important}.text-start{text-align:left!important}.text-end{text-align:right!important}.text-center{text-align:center!important}.text-decoration-none{text-decoration:none!important}.text-decoration-underline{text-decoration:underline!important}.text-decoration-line-through{text-decoration:line-through!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-primary{--bs-text-opacity:1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))!important}.text-secondary{--bs-text-opacity:1;color:rgba(var(--bs-secondary-rgb),var(--bs-text-opacity))!important}.text-success{--bs-text-opacity:1;color:rgba(var(--bs-success-rgb),var(--bs-text-opacity))!important}.text-info{--bs-text-opacity:1;color:rgba(var(--bs-info-rgb),var(--bs-text-opacity))!important}.text-warning{--bs-text-opacity:1;color:rgba(var(--bs-warning-rgb),var(--bs-text-opacity))!important}.text-danger{--bs-text-opacity:1;color:rgba(var(--bs-danger-rgb),var(--bs-text-opacity))!important}.text-light{--bs-text-opacity:1;color:rgba(var(--bs-light-rgb),var(--bs-text-opacity))!important}.text-dark{--bs-text-opacity:1;color:rgba(var(--bs-dark-rgb),var(--bs-text-opacity))!important}.text-black{--bs-text-opacity:1;color:rgba(var(--bs-black-rgb),var(--bs-text-opacity))!important}.text-white{--bs-text-opacity:1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.text-body{--bs-text-opacity:1;color:rgba(var(--bs-body-color-rgb),var(--bs-text-opacity))!important}.text-muted{--bs-text-opacity:1;color:#6c757d!important}.text-black-50{--bs-text-opacity:1;color:rgba(0,0,0,.5)!important}.text-white-50{--bs-text-opacity:1;color:hsla(0,0%,100%,.5)!important}.text-reset{--bs-text-opacity:1;color:inherit!important}.text-opacity-25{--bs-text-opacity:0.25}.text-opacity-50{--bs-text-opacity:0.5}.text-opacity-75{--bs-text-opacity:0.75}.text-opacity-100{--bs-text-opacity:1}.bg-primary{--bs-bg-opacity:1;background-color:rgba(var(--bs-primary-rgb),var(--bs-bg-opacity))!important}.bg-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-rgb),var(--bs-bg-opacity))!important}.bg-success{--bs-bg-opacity:1;background-color:rgba(var(--bs-success-rgb),var(--bs-bg-opacity))!important}.bg-info{--bs-bg-opacity:1;background-color:rgba(var(--bs-info-rgb),var(--bs-bg-opacity))!important}.bg-warning{--bs-bg-opacity:1;background-color:rgba(var(--bs-warning-rgb),var(--bs-bg-opacity))!important}.bg-danger{--bs-bg-opacity:1;background-color:rgba(var(--bs-danger-rgb),var(--bs-bg-opacity))!important}.bg-light{--bs-bg-opacity:1;background-color:rgba(var(--bs-light-rgb),var(--bs-bg-opacity))!important}.bg-dark{--bs-bg-opacity:1;background-color:rgba(var(--bs-dark-rgb),var(--bs-bg-opacity))!important}.bg-black{--bs-bg-opacity:1;background-color:rgba(var(--bs-black-rgb),var(--bs-bg-opacity))!important}.bg-white{--bs-bg-opacity:1;background-color:rgba(var(--bs-white-rgb),var(--bs-bg-opacity))!important}.bg-body{--bs-bg-opacity:1;background-color:rgba(var(--bs-body-bg-rgb),var(--bs-bg-opacity))!important}.bg-transparent{--bs-bg-opacity:1;background-color:transparent!important}.bg-opacity-10{--bs-bg-opacity:0.1}.bg-opacity-25{--bs-bg-opacity:0.25}.bg-opacity-50{--bs-bg-opacity:0.5}.bg-opacity-75{--bs-bg-opacity:0.75}.bg-opacity-100{--bs-bg-opacity:1}.bg-gradient{background-image:var(--bs-gradient)!important}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;-ms-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.pe-none{pointer-events:none!important}.pe-auto{pointer-events:auto!important}.rounded{border-radius:.25rem!important}.rounded-0{border-radius:0!important}.rounded-1{border-radius:.2rem!important}.rounded-2{border-radius:.25rem!important}.rounded-3{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-top{border-top-left-radius:.25rem!important}.rounded-end,.rounded-top{border-top-right-radius:.25rem!important}.rounded-bottom,.rounded-end{border-bottom-right-radius:.25rem!important}.rounded-bottom,.rounded-start{border-bottom-left-radius:.25rem!important}.rounded-start{border-top-left-radius:.25rem!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media (min-width:576px){.float-sm-start{float:left!important}.float-sm-end{float:right!important}.float-sm-none{float:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-grid{display:grid!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}.d-sm-none{display:none!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-sm-0{gap:0!important}.gap-sm-1{gap:.25rem!important}.gap-sm-2{gap:.5rem!important}.gap-sm-3{gap:1rem!important}.gap-sm-4{gap:1.5rem!important}.gap-sm-5{gap:3rem!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.justify-content-sm-evenly{justify-content:space-evenly!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}.order-sm-first{order:-1!important}.order-sm-0{order:0!important}.order-sm-1{order:1!important}.order-sm-2{order:2!important}.order-sm-3{order:3!important}.order-sm-4{order:4!important}.order-sm-5{order:5!important}.order-sm-last{order:6!important}.m-sm-0{margin:0!important}.m-sm-1{margin:.25rem!important}.m-sm-2{margin:.5rem!important}.m-sm-3{margin:1rem!important}.m-sm-4{margin:1.5rem!important}.m-sm-5{margin:3rem!important}.m-sm-auto{margin:auto!important}.mx-sm-0{margin-left:0!important;margin-right:0!important}.mx-sm-1{margin-left:.25rem!important;margin-right:.25rem!important}.mx-sm-2{margin-left:.5rem!important;margin-right:.5rem!important}.mx-sm-3{margin-left:1rem!important;margin-right:1rem!important}.mx-sm-4{margin-left:1.5rem!important;margin-right:1.5rem!important}.mx-sm-5{margin-left:3rem!important;margin-right:3rem!important}.mx-sm-auto{margin-left:auto!important;margin-right:auto!important}.my-sm-0{margin-bottom:0!important;margin-top:0!important}.my-sm-1{margin-bottom:.25rem!important;margin-top:.25rem!important}.my-sm-2{margin-bottom:.5rem!important;margin-top:.5rem!important}.my-sm-3{margin-bottom:1rem!important;margin-top:1rem!important}.my-sm-4{margin-bottom:1.5rem!important;margin-top:1.5rem!important}.my-sm-5{margin-bottom:3rem!important;margin-top:3rem!important}.my-sm-auto{margin-bottom:auto!important;margin-top:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:.25rem!important}.mt-sm-2{margin-top:.5rem!important}.mt-sm-3{margin-top:1rem!important}.mt-sm-4{margin-top:1.5rem!important}.mt-sm-5{margin-top:3rem!important}.mt-sm-auto{margin-top:auto!important}.me-sm-0{margin-right:0!important}.me-sm-1{margin-right:.25rem!important}.me-sm-2{margin-right:.5rem!important}.me-sm-3{margin-right:1rem!important}.me-sm-4{margin-right:1.5rem!important}.me-sm-5{margin-right:3rem!important}.me-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:.25rem!important}.mb-sm-2{margin-bottom:.5rem!important}.mb-sm-3{margin-bottom:1rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.mb-sm-5{margin-bottom:3rem!important}.mb-sm-auto{margin-bottom:auto!important}.ms-sm-0{margin-left:0!important}.ms-sm-1{margin-left:.25rem!important}.ms-sm-2{margin-left:.5rem!important}.ms-sm-3{margin-left:1rem!important}.ms-sm-4{margin-left:1.5rem!important}.ms-sm-5{margin-left:3rem!important}.ms-sm-auto{margin-left:auto!important}.p-sm-0{padding:0!important}.p-sm-1{padding:.25rem!important}.p-sm-2{padding:.5rem!important}.p-sm-3{padding:1rem!important}.p-sm-4{padding:1.5rem!important}.p-sm-5{padding:3rem!important}.px-sm-0{padding-left:0!important;padding-right:0!important}.px-sm-1{padding-left:.25rem!important;padding-right:.25rem!important}.px-sm-2{padding-left:.5rem!important;padding-right:.5rem!important}.px-sm-3{padding-left:1rem!important;padding-right:1rem!important}.px-sm-4{padding-left:1.5rem!important;padding-right:1.5rem!important}.px-sm-5{padding-left:3rem!important;padding-right:3rem!important}.py-sm-0{padding-bottom:0!important;padding-top:0!important}.py-sm-1{padding-bottom:.25rem!important;padding-top:.25rem!important}.py-sm-2{padding-bottom:.5rem!important;padding-top:.5rem!important}.py-sm-3{padding-bottom:1rem!important;padding-top:1rem!important}.py-sm-4{padding-bottom:1.5rem!important;padding-top:1.5rem!important}.py-sm-5{padding-bottom:3rem!important;padding-top:3rem!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:.25rem!important}.pt-sm-2{padding-top:.5rem!important}.pt-sm-3{padding-top:1rem!important}.pt-sm-4{padding-top:1.5rem!important}.pt-sm-5{padding-top:3rem!important}.pe-sm-0{padding-right:0!important}.pe-sm-1{padding-right:.25rem!important}.pe-sm-2{padding-right:.5rem!important}.pe-sm-3{padding-right:1rem!important}.pe-sm-4{padding-right:1.5rem!important}.pe-sm-5{padding-right:3rem!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:.25rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pb-sm-3{padding-bottom:1rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pb-sm-5{padding-bottom:3rem!important}.ps-sm-0{padding-left:0!important}.ps-sm-1{padding-left:.25rem!important}.ps-sm-2{padding-left:.5rem!important}.ps-sm-3{padding-left:1rem!important}.ps-sm-4{padding-left:1.5rem!important}.ps-sm-5{padding-left:3rem!important}.text-sm-start{text-align:left!important}.text-sm-end{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.float-md-start{float:left!important}.float-md-end{float:right!important}.float-md-none{float:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-grid{display:grid!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}.d-md-none{display:none!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-md-0{gap:0!important}.gap-md-1{gap:.25rem!important}.gap-md-2{gap:.5rem!important}.gap-md-3{gap:1rem!important}.gap-md-4{gap:1.5rem!important}.gap-md-5{gap:3rem!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.justify-content-md-evenly{justify-content:space-evenly!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}.order-md-first{order:-1!important}.order-md-0{order:0!important}.order-md-1{order:1!important}.order-md-2{order:2!important}.order-md-3{order:3!important}.order-md-4{order:4!important}.order-md-5{order:5!important}.order-md-last{order:6!important}.m-md-0{margin:0!important}.m-md-1{margin:.25rem!important}.m-md-2{margin:.5rem!important}.m-md-3{margin:1rem!important}.m-md-4{margin:1.5rem!important}.m-md-5{margin:3rem!important}.m-md-auto{margin:auto!important}.mx-md-0{margin-left:0!important;margin-right:0!important}.mx-md-1{margin-left:.25rem!important;margin-right:.25rem!important}.mx-md-2{margin-left:.5rem!important;margin-right:.5rem!important}.mx-md-3{margin-left:1rem!important;margin-right:1rem!important}.mx-md-4{margin-left:1.5rem!important;margin-right:1.5rem!important}.mx-md-5{margin-left:3rem!important;margin-right:3rem!important}.mx-md-auto{margin-left:auto!important;margin-right:auto!important}.my-md-0{margin-bottom:0!important;margin-top:0!important}.my-md-1{margin-bottom:.25rem!important;margin-top:.25rem!important}.my-md-2{margin-bottom:.5rem!important;margin-top:.5rem!important}.my-md-3{margin-bottom:1rem!important;margin-top:1rem!important}.my-md-4{margin-bottom:1.5rem!important;margin-top:1.5rem!important}.my-md-5{margin-bottom:3rem!important;margin-top:3rem!important}.my-md-auto{margin-bottom:auto!important;margin-top:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:.25rem!important}.mt-md-2{margin-top:.5rem!important}.mt-md-3{margin-top:1rem!important}.mt-md-4{margin-top:1.5rem!important}.mt-md-5{margin-top:3rem!important}.mt-md-auto{margin-top:auto!important}.me-md-0{margin-right:0!important}.me-md-1{margin-right:.25rem!important}.me-md-2{margin-right:.5rem!important}.me-md-3{margin-right:1rem!important}.me-md-4{margin-right:1.5rem!important}.me-md-5{margin-right:3rem!important}.me-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:.25rem!important}.mb-md-2{margin-bottom:.5rem!important}.mb-md-3{margin-bottom:1rem!important}.mb-md-4{margin-bottom:1.5rem!important}.mb-md-5{margin-bottom:3rem!important}.mb-md-auto{margin-bottom:auto!important}.ms-md-0{margin-left:0!important}.ms-md-1{margin-left:.25rem!important}.ms-md-2{margin-left:.5rem!important}.ms-md-3{margin-left:1rem!important}.ms-md-4{margin-left:1.5rem!important}.ms-md-5{margin-left:3rem!important}.ms-md-auto{margin-left:auto!important}.p-md-0{padding:0!important}.p-md-1{padding:.25rem!important}.p-md-2{padding:.5rem!important}.p-md-3{padding:1rem!important}.p-md-4{padding:1.5rem!important}.p-md-5{padding:3rem!important}.px-md-0{padding-left:0!important;padding-right:0!important}.px-md-1{padding-left:.25rem!important;padding-right:.25rem!important}.px-md-2{padding-left:.5rem!important;padding-right:.5rem!important}.px-md-3{padding-left:1rem!important;padding-right:1rem!important}.px-md-4{padding-left:1.5rem!important;padding-right:1.5rem!important}.px-md-5{padding-left:3rem!important;padding-right:3rem!important}.py-md-0{padding-bottom:0!important;padding-top:0!important}.py-md-1{padding-bottom:.25rem!important;padding-top:.25rem!important}.py-md-2{padding-bottom:.5rem!important;padding-top:.5rem!important}.py-md-3{padding-bottom:1rem!important;padding-top:1rem!important}.py-md-4{padding-bottom:1.5rem!important;padding-top:1.5rem!important}.py-md-5{padding-bottom:3rem!important;padding-top:3rem!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:.25rem!important}.pt-md-2{padding-top:.5rem!important}.pt-md-3{padding-top:1rem!important}.pt-md-4{padding-top:1.5rem!important}.pt-md-5{padding-top:3rem!important}.pe-md-0{padding-right:0!important}.pe-md-1{padding-right:.25rem!important}.pe-md-2{padding-right:.5rem!important}.pe-md-3{padding-right:1rem!important}.pe-md-4{padding-right:1.5rem!important}.pe-md-5{padding-right:3rem!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:.25rem!important}.pb-md-2{padding-bottom:.5rem!important}.pb-md-3{padding-bottom:1rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pb-md-5{padding-bottom:3rem!important}.ps-md-0{padding-left:0!important}.ps-md-1{padding-left:.25rem!important}.ps-md-2{padding-left:.5rem!important}.ps-md-3{padding-left:1rem!important}.ps-md-4{padding-left:1.5rem!important}.ps-md-5{padding-left:3rem!important}.text-md-start{text-align:left!important}.text-md-end{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.float-lg-start{float:left!important}.float-lg-end{float:right!important}.float-lg-none{float:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-grid{display:grid!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}.d-lg-none{display:none!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-lg-0{gap:0!important}.gap-lg-1{gap:.25rem!important}.gap-lg-2{gap:.5rem!important}.gap-lg-3{gap:1rem!important}.gap-lg-4{gap:1.5rem!important}.gap-lg-5{gap:3rem!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.justify-content-lg-evenly{justify-content:space-evenly!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}.order-lg-first{order:-1!important}.order-lg-0{order:0!important}.order-lg-1{order:1!important}.order-lg-2{order:2!important}.order-lg-3{order:3!important}.order-lg-4{order:4!important}.order-lg-5{order:5!important}.order-lg-last{order:6!important}.m-lg-0{margin:0!important}.m-lg-1{margin:.25rem!important}.m-lg-2{margin:.5rem!important}.m-lg-3{margin:1rem!important}.m-lg-4{margin:1.5rem!important}.m-lg-5{margin:3rem!important}.m-lg-auto{margin:auto!important}.mx-lg-0{margin-left:0!important;margin-right:0!important}.mx-lg-1{margin-left:.25rem!important;margin-right:.25rem!important}.mx-lg-2{margin-left:.5rem!important;margin-right:.5rem!important}.mx-lg-3{margin-left:1rem!important;margin-right:1rem!important}.mx-lg-4{margin-left:1.5rem!important;margin-right:1.5rem!important}.mx-lg-5{margin-left:3rem!important;margin-right:3rem!important}.mx-lg-auto{margin-left:auto!important;margin-right:auto!important}.my-lg-0{margin-bottom:0!important;margin-top:0!important}.my-lg-1{margin-bottom:.25rem!important;margin-top:.25rem!important}.my-lg-2{margin-bottom:.5rem!important;margin-top:.5rem!important}.my-lg-3{margin-bottom:1rem!important;margin-top:1rem!important}.my-lg-4{margin-bottom:1.5rem!important;margin-top:1.5rem!important}.my-lg-5{margin-bottom:3rem!important;margin-top:3rem!important}.my-lg-auto{margin-bottom:auto!important;margin-top:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:.25rem!important}.mt-lg-2{margin-top:.5rem!important}.mt-lg-3{margin-top:1rem!important}.mt-lg-4{margin-top:1.5rem!important}.mt-lg-5{margin-top:3rem!important}.mt-lg-auto{margin-top:auto!important}.me-lg-0{margin-right:0!important}.me-lg-1{margin-right:.25rem!important}.me-lg-2{margin-right:.5rem!important}.me-lg-3{margin-right:1rem!important}.me-lg-4{margin-right:1.5rem!important}.me-lg-5{margin-right:3rem!important}.me-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:.25rem!important}.mb-lg-2{margin-bottom:.5rem!important}.mb-lg-3{margin-bottom:1rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.mb-lg-5{margin-bottom:3rem!important}.mb-lg-auto{margin-bottom:auto!important}.ms-lg-0{margin-left:0!important}.ms-lg-1{margin-left:.25rem!important}.ms-lg-2{margin-left:.5rem!important}.ms-lg-3{margin-left:1rem!important}.ms-lg-4{margin-left:1.5rem!important}.ms-lg-5{margin-left:3rem!important}.ms-lg-auto{margin-left:auto!important}.p-lg-0{padding:0!important}.p-lg-1{padding:.25rem!important}.p-lg-2{padding:.5rem!important}.p-lg-3{padding:1rem!important}.p-lg-4{padding:1.5rem!important}.p-lg-5{padding:3rem!important}.px-lg-0{padding-left:0!important;padding-right:0!important}.px-lg-1{padding-left:.25rem!important;padding-right:.25rem!important}.px-lg-2{padding-left:.5rem!important;padding-right:.5rem!important}.px-lg-3{padding-left:1rem!important;padding-right:1rem!important}.px-lg-4{padding-left:1.5rem!important;padding-right:1.5rem!important}.px-lg-5{padding-left:3rem!important;padding-right:3rem!important}.py-lg-0{padding-bottom:0!important;padding-top:0!important}.py-lg-1{padding-bottom:.25rem!important;padding-top:.25rem!important}.py-lg-2{padding-bottom:.5rem!important;padding-top:.5rem!important}.py-lg-3{padding-bottom:1rem!important;padding-top:1rem!important}.py-lg-4{padding-bottom:1.5rem!important;padding-top:1.5rem!important}.py-lg-5{padding-bottom:3rem!important;padding-top:3rem!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:.25rem!important}.pt-lg-2{padding-top:.5rem!important}.pt-lg-3{padding-top:1rem!important}.pt-lg-4{padding-top:1.5rem!important}.pt-lg-5{padding-top:3rem!important}.pe-lg-0{padding-right:0!important}.pe-lg-1{padding-right:.25rem!important}.pe-lg-2{padding-right:.5rem!important}.pe-lg-3{padding-right:1rem!important}.pe-lg-4{padding-right:1.5rem!important}.pe-lg-5{padding-right:3rem!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:.25rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pb-lg-3{padding-bottom:1rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pb-lg-5{padding-bottom:3rem!important}.ps-lg-0{padding-left:0!important}.ps-lg-1{padding-left:.25rem!important}.ps-lg-2{padding-left:.5rem!important}.ps-lg-3{padding-left:1rem!important}.ps-lg-4{padding-left:1.5rem!important}.ps-lg-5{padding-left:3rem!important}.text-lg-start{text-align:left!important}.text-lg-end{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.float-xl-start{float:left!important}.float-xl-end{float:right!important}.float-xl-none{float:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-grid{display:grid!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}.d-xl-none{display:none!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-xl-0{gap:0!important}.gap-xl-1{gap:.25rem!important}.gap-xl-2{gap:.5rem!important}.gap-xl-3{gap:1rem!important}.gap-xl-4{gap:1.5rem!important}.gap-xl-5{gap:3rem!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.justify-content-xl-evenly{justify-content:space-evenly!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}.order-xl-first{order:-1!important}.order-xl-0{order:0!important}.order-xl-1{order:1!important}.order-xl-2{order:2!important}.order-xl-3{order:3!important}.order-xl-4{order:4!important}.order-xl-5{order:5!important}.order-xl-last{order:6!important}.m-xl-0{margin:0!important}.m-xl-1{margin:.25rem!important}.m-xl-2{margin:.5rem!important}.m-xl-3{margin:1rem!important}.m-xl-4{margin:1.5rem!important}.m-xl-5{margin:3rem!important}.m-xl-auto{margin:auto!important}.mx-xl-0{margin-left:0!important;margin-right:0!important}.mx-xl-1{margin-left:.25rem!important;margin-right:.25rem!important}.mx-xl-2{margin-left:.5rem!important;margin-right:.5rem!important}.mx-xl-3{margin-left:1rem!important;margin-right:1rem!important}.mx-xl-4{margin-left:1.5rem!important;margin-right:1.5rem!important}.mx-xl-5{margin-left:3rem!important;margin-right:3rem!important}.mx-xl-auto{margin-left:auto!important;margin-right:auto!important}.my-xl-0{margin-bottom:0!important;margin-top:0!important}.my-xl-1{margin-bottom:.25rem!important;margin-top:.25rem!important}.my-xl-2{margin-bottom:.5rem!important;margin-top:.5rem!important}.my-xl-3{margin-bottom:1rem!important;margin-top:1rem!important}.my-xl-4{margin-bottom:1.5rem!important;margin-top:1.5rem!important}.my-xl-5{margin-bottom:3rem!important;margin-top:3rem!important}.my-xl-auto{margin-bottom:auto!important;margin-top:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:.25rem!important}.mt-xl-2{margin-top:.5rem!important}.mt-xl-3{margin-top:1rem!important}.mt-xl-4{margin-top:1.5rem!important}.mt-xl-5{margin-top:3rem!important}.mt-xl-auto{margin-top:auto!important}.me-xl-0{margin-right:0!important}.me-xl-1{margin-right:.25rem!important}.me-xl-2{margin-right:.5rem!important}.me-xl-3{margin-right:1rem!important}.me-xl-4{margin-right:1.5rem!important}.me-xl-5{margin-right:3rem!important}.me-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:.25rem!important}.mb-xl-2{margin-bottom:.5rem!important}.mb-xl-3{margin-bottom:1rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.mb-xl-5{margin-bottom:3rem!important}.mb-xl-auto{margin-bottom:auto!important}.ms-xl-0{margin-left:0!important}.ms-xl-1{margin-left:.25rem!important}.ms-xl-2{margin-left:.5rem!important}.ms-xl-3{margin-left:1rem!important}.ms-xl-4{margin-left:1.5rem!important}.ms-xl-5{margin-left:3rem!important}.ms-xl-auto{margin-left:auto!important}.p-xl-0{padding:0!important}.p-xl-1{padding:.25rem!important}.p-xl-2{padding:.5rem!important}.p-xl-3{padding:1rem!important}.p-xl-4{padding:1.5rem!important}.p-xl-5{padding:3rem!important}.px-xl-0{padding-left:0!important;padding-right:0!important}.px-xl-1{padding-left:.25rem!important;padding-right:.25rem!important}.px-xl-2{padding-left:.5rem!important;padding-right:.5rem!important}.px-xl-3{padding-left:1rem!important;padding-right:1rem!important}.px-xl-4{padding-left:1.5rem!important;padding-right:1.5rem!important}.px-xl-5{padding-left:3rem!important;padding-right:3rem!important}.py-xl-0{padding-bottom:0!important;padding-top:0!important}.py-xl-1{padding-bottom:.25rem!important;padding-top:.25rem!important}.py-xl-2{padding-bottom:.5rem!important;padding-top:.5rem!important}.py-xl-3{padding-bottom:1rem!important;padding-top:1rem!important}.py-xl-4{padding-bottom:1.5rem!important;padding-top:1.5rem!important}.py-xl-5{padding-bottom:3rem!important;padding-top:3rem!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:.25rem!important}.pt-xl-2{padding-top:.5rem!important}.pt-xl-3{padding-top:1rem!important}.pt-xl-4{padding-top:1.5rem!important}.pt-xl-5{padding-top:3rem!important}.pe-xl-0{padding-right:0!important}.pe-xl-1{padding-right:.25rem!important}.pe-xl-2{padding-right:.5rem!important}.pe-xl-3{padding-right:1rem!important}.pe-xl-4{padding-right:1.5rem!important}.pe-xl-5{padding-right:3rem!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:.25rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pb-xl-3{padding-bottom:1rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pb-xl-5{padding-bottom:3rem!important}.ps-xl-0{padding-left:0!important}.ps-xl-1{padding-left:.25rem!important}.ps-xl-2{padding-left:.5rem!important}.ps-xl-3{padding-left:1rem!important}.ps-xl-4{padding-left:1.5rem!important}.ps-xl-5{padding-left:3rem!important}.text-xl-start{text-align:left!important}.text-xl-end{text-align:right!important}.text-xl-center{text-align:center!important}}@media (min-width:1400px){.float-xxl-start{float:left!important}.float-xxl-end{float:right!important}.float-xxl-none{float:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!important}.d-xxl-grid{display:grid!important}.d-xxl-table{display:table!important}.d-xxl-table-row{display:table-row!important}.d-xxl-table-cell{display:table-cell!important}.d-xxl-flex{display:flex!important}.d-xxl-inline-flex{display:inline-flex!important}.d-xxl-none{display:none!important}.flex-xxl-fill{flex:1 1 auto!important}.flex-xxl-row{flex-direction:row!important}.flex-xxl-column{flex-direction:column!important}.flex-xxl-row-reverse{flex-direction:row-reverse!important}.flex-xxl-column-reverse{flex-direction:column-reverse!important}.flex-xxl-grow-0{flex-grow:0!important}.flex-xxl-grow-1{flex-grow:1!important}.flex-xxl-shrink-0{flex-shrink:0!important}.flex-xxl-shrink-1{flex-shrink:1!important}.flex-xxl-wrap{flex-wrap:wrap!important}.flex-xxl-nowrap{flex-wrap:nowrap!important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-xxl-0{gap:0!important}.gap-xxl-1{gap:.25rem!important}.gap-xxl-2{gap:.5rem!important}.gap-xxl-3{gap:1rem!important}.gap-xxl-4{gap:1.5rem!important}.gap-xxl-5{gap:3rem!important}.justify-content-xxl-start{justify-content:flex-start!important}.justify-content-xxl-end{justify-content:flex-end!important}.justify-content-xxl-center{justify-content:center!important}.justify-content-xxl-between{justify-content:space-between!important}.justify-content-xxl-around{justify-content:space-around!important}.justify-content-xxl-evenly{justify-content:space-evenly!important}.align-items-xxl-start{align-items:flex-start!important}.align-items-xxl-end{align-items:flex-end!important}.align-items-xxl-center{align-items:center!important}.align-items-xxl-baseline{align-items:baseline!important}.align-items-xxl-stretch{align-items:stretch!important}.align-content-xxl-start{align-content:flex-start!important}.align-content-xxl-end{align-content:flex-end!important}.align-content-xxl-center{align-content:center!important}.align-content-xxl-between{align-content:space-between!important}.align-content-xxl-around{align-content:space-around!important}.align-content-xxl-stretch{align-content:stretch!important}.align-self-xxl-auto{align-self:auto!important}.align-self-xxl-start{align-self:flex-start!important}.align-self-xxl-end{align-self:flex-end!important}.align-self-xxl-center{align-self:center!important}.align-self-xxl-baseline{align-self:baseline!important}.align-self-xxl-stretch{align-self:stretch!important}.order-xxl-first{order:-1!important}.order-xxl-0{order:0!important}.order-xxl-1{order:1!important}.order-xxl-2{order:2!important}.order-xxl-3{order:3!important}.order-xxl-4{order:4!important}.order-xxl-5{order:5!important}.order-xxl-last{order:6!important}.m-xxl-0{margin:0!important}.m-xxl-1{margin:.25rem!important}.m-xxl-2{margin:.5rem!important}.m-xxl-3{margin:1rem!important}.m-xxl-4{margin:1.5rem!important}.m-xxl-5{margin:3rem!important}.m-xxl-auto{margin:auto!important}.mx-xxl-0{margin-left:0!important;margin-right:0!important}.mx-xxl-1{margin-left:.25rem!important;margin-right:.25rem!important}.mx-xxl-2{margin-left:.5rem!important;margin-right:.5rem!important}.mx-xxl-3{margin-left:1rem!important;margin-right:1rem!important}.mx-xxl-4{margin-left:1.5rem!important;margin-right:1.5rem!important}.mx-xxl-5{margin-left:3rem!important;margin-right:3rem!important}.mx-xxl-auto{margin-left:auto!important;margin-right:auto!important}.my-xxl-0{margin-bottom:0!important;margin-top:0!important}.my-xxl-1{margin-bottom:.25rem!important;margin-top:.25rem!important}.my-xxl-2{margin-bottom:.5rem!important;margin-top:.5rem!important}.my-xxl-3{margin-bottom:1rem!important;margin-top:1rem!important}.my-xxl-4{margin-bottom:1.5rem!important;margin-top:1.5rem!important}.my-xxl-5{margin-bottom:3rem!important;margin-top:3rem!important}.my-xxl-auto{margin-bottom:auto!important;margin-top:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:.25rem!important}.mt-xxl-2{margin-top:.5rem!important}.mt-xxl-3{margin-top:1rem!important}.mt-xxl-4{margin-top:1.5rem!important}.mt-xxl-5{margin-top:3rem!important}.mt-xxl-auto{margin-top:auto!important}.me-xxl-0{margin-right:0!important}.me-xxl-1{margin-right:.25rem!important}.me-xxl-2{margin-right:.5rem!important}.me-xxl-3{margin-right:1rem!important}.me-xxl-4{margin-right:1.5rem!important}.me-xxl-5{margin-right:3rem!important}.me-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:.25rem!important}.mb-xxl-2{margin-bottom:.5rem!important}.mb-xxl-3{margin-bottom:1rem!important}.mb-xxl-4{margin-bottom:1.5rem!important}.mb-xxl-5{margin-bottom:3rem!important}.mb-xxl-auto{margin-bottom:auto!important}.ms-xxl-0{margin-left:0!important}.ms-xxl-1{margin-left:.25rem!important}.ms-xxl-2{margin-left:.5rem!important}.ms-xxl-3{margin-left:1rem!important}.ms-xxl-4{margin-left:1.5rem!important}.ms-xxl-5{margin-left:3rem!important}.ms-xxl-auto{margin-left:auto!important}.p-xxl-0{padding:0!important}.p-xxl-1{padding:.25rem!important}.p-xxl-2{padding:.5rem!important}.p-xxl-3{padding:1rem!important}.p-xxl-4{padding:1.5rem!important}.p-xxl-5{padding:3rem!important}.px-xxl-0{padding-left:0!important;padding-right:0!important}.px-xxl-1{padding-left:.25rem!important;padding-right:.25rem!important}.px-xxl-2{padding-left:.5rem!important;padding-right:.5rem!important}.px-xxl-3{padding-left:1rem!important;padding-right:1rem!important}.px-xxl-4{padding-left:1.5rem!important;padding-right:1.5rem!important}.px-xxl-5{padding-left:3rem!important;padding-right:3rem!important}.py-xxl-0{padding-bottom:0!important;padding-top:0!important}.py-xxl-1{padding-bottom:.25rem!important;padding-top:.25rem!important}.py-xxl-2{padding-bottom:.5rem!important;padding-top:.5rem!important}.py-xxl-3{padding-bottom:1rem!important;padding-top:1rem!important}.py-xxl-4{padding-bottom:1.5rem!important;padding-top:1.5rem!important}.py-xxl-5{padding-bottom:3rem!important;padding-top:3rem!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:.25rem!important}.pt-xxl-2{padding-top:.5rem!important}.pt-xxl-3{padding-top:1rem!important}.pt-xxl-4{padding-top:1.5rem!important}.pt-xxl-5{padding-top:3rem!important}.pe-xxl-0{padding-right:0!important}.pe-xxl-1{padding-right:.25rem!important}.pe-xxl-2{padding-right:.5rem!important}.pe-xxl-3{padding-right:1rem!important}.pe-xxl-4{padding-right:1.5rem!important}.pe-xxl-5{padding-right:3rem!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:.25rem!important}.pb-xxl-2{padding-bottom:.5rem!important}.pb-xxl-3{padding-bottom:1rem!important}.pb-xxl-4{padding-bottom:1.5rem!important}.pb-xxl-5{padding-bottom:3rem!important}.ps-xxl-0{padding-left:0!important}.ps-xxl-1{padding-left:.25rem!important}.ps-xxl-2{padding-left:.5rem!important}.ps-xxl-3{padding-left:1rem!important}.ps-xxl-4{padding-left:1.5rem!important}.ps-xxl-5{padding-left:3rem!important}.text-xxl-start{text-align:left!important}.text-xxl-end{text-align:right!important}.text-xxl-center{text-align:center!important}}@media (min-width:1200px){.fs-1{font-size:2.5rem!important}.fs-2{font-size:2rem!important}.fs-3{font-size:1.75rem!important}.fs-4{font-size:1.5rem!important}}@media print{.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-grid{display:grid!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}.d-print-none{display:none!important}} diff --git a/themes/demo/assets/vendor/bootstrap/bootstrap.js b/themes/demo/assets/vendor/bootstrap/bootstrap.js new file mode 100644 index 0000000..a06b321 --- /dev/null +++ b/themes/demo/assets/vendor/bootstrap/bootstrap.js @@ -0,0 +1,22 @@ +// Importing JavaScript +// +// You have two choices for including Bootstrap's JS files—the whole thing, +// or just the bits that you need. + + +// Option 1 +// +// Import Bootstrap's bundle (all of Bootstrap's JS + Popper.js dependency) + +import "../../../node_modules/bootstrap/dist/js/bootstrap.bundle.js"; + + +// Option 2 +// +// Import just what we need + +// If you're importing tooltips or popovers, be sure to include our Popper.js dependency +// import "../../../node_modules/popper.js/dist/popper.min.js"; + +// import "../../../node_modules/bootstrap/js/dist/util.js"; +// import "../../../node_modules/bootstrap/js/dist/modal.js"; diff --git a/themes/demo/assets/vendor/bootstrap/bootstrap.min.js b/themes/demo/assets/vendor/bootstrap/bootstrap.min.js new file mode 100644 index 0000000..c7a5e26 --- /dev/null +++ b/themes/demo/assets/vendor/bootstrap/bootstrap.min.js @@ -0,0 +1,3 @@ +/*! For license information please see bootstrap.min.js.LICENSE.txt */ +(()=>{var t={577:function(t){t.exports=function(){"use strict";const t=1e6,e=1e3,i="transitionend",n=t=>null==t?`${t}`:{}.toString.call(t).match(/\s([a-z]+)/i)[1].toLowerCase(),s=e=>{do{e+=Math.floor(Math.random()*t)}while(document.getElementById(e));return e},o=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return e},r=t=>{const e=o(t);return e&&document.querySelector(e)?e:null},a=t=>{const e=o(t);return e?document.querySelector(e):null},l=t=>{if(!t)return 0;let{transitionDuration:i,transitionDelay:n}=window.getComputedStyle(t);const s=Number.parseFloat(i),o=Number.parseFloat(n);return s||o?(i=i.split(",")[0],n=n.split(",")[0],(Number.parseFloat(i)+Number.parseFloat(n))*e):0},c=t=>{t.dispatchEvent(new Event(i))},h=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),d=t=>h(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(t):null,u=(t,e,i)=>{Object.keys(i).forEach((s=>{const o=i[s],r=e[s],a=r&&h(r)?"element":n(r);if(!new RegExp(o).test(a))throw new TypeError(`${t.toUpperCase()}: Option "${s}" provided type "${a}" but expected type "${o}".`)}))},f=t=>!(!h(t)||0===t.getClientRects().length)&&"visible"===getComputedStyle(t).getPropertyValue("visibility"),p=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),g=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?g(t.parentNode):null},m=()=>{},_=t=>{t.offsetHeight},v=()=>{const{jQuery:t}=window;return t&&!document.body.hasAttribute("data-bs-no-jquery")?t:null},b=[],y=t=>{"loading"===document.readyState?(b.length||document.addEventListener("DOMContentLoaded",(()=>{b.forEach((t=>t()))})),b.push(t)):t()},w=()=>"rtl"===document.documentElement.dir,E=t=>{y((()=>{const e=v();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}}))},A=t=>{"function"==typeof t&&t()},T=(t,e,n=!0)=>{if(!n)return void A(t);const s=5,o=l(e)+s;let r=!1;const a=({target:n})=>{n===e&&(r=!0,e.removeEventListener(i,a),A(t))};e.addEventListener(i,a),setTimeout((()=>{r||c(e)}),o)},O=(t,e,i,n)=>{let s=t.indexOf(e);if(-1===s)return t[!i&&n?t.length-1:0];const o=t.length;return s+=i?1:-1,n&&(s=(s+o)%o),t[Math.max(0,Math.min(s,o-1))]},C=/[^.]*(?=\..*)\.|.*/,k=/\..*/,L=/::\d+$/,x={};let $=1;const D={mouseenter:"mouseover",mouseleave:"mouseout"},S=/^(mouseenter|mouseleave)/i,N=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function I(t,e){return e&&`${e}::${$++}`||t.uidEvent||$++}function P(t){const e=I(t);return t.uidEvent=e,x[e]=x[e]||{},x[e]}function j(t,e){return function i(n){return n.delegateTarget=t,i.oneOff&&F.off(t,n.type,e),e.apply(t,[n])}}function M(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(let a=o.length;a--;)if(o[a]===r)return s.delegateTarget=r,n.oneOff&&F.off(t,s.type,e,i),i.apply(r,[s]);return null}}function H(t,e,i=null){const n=Object.keys(t);for(let s=0,o=n.length;sfunction(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};n?n=t(n):i=t(i)}const[o,r,a]=B(e,i,n),l=P(t),c=l[a]||(l[a]={}),h=H(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=I(r,e.replace(C,"")),u=o?M(t,i,n):j(t,i);u.delegationSelector=o?i:null,u.originalHandler=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function W(t,e,i,n,s){const o=H(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function z(t,e,i,n){const s=e[i]||{};Object.keys(s).forEach((o=>{if(o.includes(n)){const n=s[o];W(t,e,i,n.originalHandler,n.delegationSelector)}}))}function q(t){return t=t.replace(k,""),D[t]||t}const F={on(t,e,i,n){R(t,e,i,n,!1)},one(t,e,i,n){R(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=B(e,i,n),a=r!==e,l=P(t),c=e.startsWith(".");if(void 0!==o){if(!l||!l[r])return;return void W(t,l,r,o,s?i:null)}c&&Object.keys(l).forEach((i=>{z(t,l,i,e.slice(1))}));const h=l[r]||{};Object.keys(h).forEach((i=>{const n=i.replace(L,"");if(!a||e.includes(n)){const e=h[i];W(t,l,r,e.originalHandler,e.delegationSelector)}}))},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=v(),s=q(e),o=e!==s,r=N.has(s);let a,l=!0,c=!0,h=!1,d=null;return o&&n&&(a=n.Event(e,i),n(t).trigger(a),l=!a.isPropagationStopped(),c=!a.isImmediatePropagationStopped(),h=a.isDefaultPrevented()),r?(d=document.createEvent("HTMLEvents"),d.initEvent(s,l,!0)):d=new CustomEvent(e,{bubbles:l,cancelable:!0}),void 0!==i&&Object.keys(i).forEach((t=>{Object.defineProperty(d,t,{get:()=>i[t]})})),h&&d.preventDefault(),c&&t.dispatchEvent(d),d.defaultPrevented&&void 0!==a&&a.preventDefault(),d}},U=new Map,V={set(t,e,i){U.has(t)||U.set(t,new Map);const n=U.get(t);n.has(e)||0===n.size?n.set(e,i):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(n.keys())[0]}.`)},get:(t,e)=>U.has(t)&&U.get(t).get(e)||null,remove(t,e){if(!U.has(t))return;const i=U.get(t);i.delete(e),0===i.size&&U.delete(t)}},K="5.1.3";class X{constructor(t){(t=d(t))&&(this._element=t,V.set(this._element,this.constructor.DATA_KEY,this))}dispose(){V.remove(this._element,this.constructor.DATA_KEY),F.off(this._element,this.constructor.EVENT_KEY),Object.getOwnPropertyNames(this).forEach((t=>{this[t]=null}))}_queueCallback(t,e,i=!0){T(t,e,i)}static getInstance(t){return V.get(d(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return K}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}}const Y=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,n=t.NAME;F.on(document,i,`[data-bs-dismiss="${n}"]`,(function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),p(this))return;const s=a(this)||this.closest(`.${n}`);t.getOrCreateInstance(s)[e]()}))},Q="alert",G=".bs.alert",Z=`close${G}`,J=`closed${G}`,tt="fade",et="show";class it extends X{static get NAME(){return Q}close(){if(F.trigger(this._element,Z).defaultPrevented)return;this._element.classList.remove(et);const t=this._element.classList.contains(tt);this._queueCallback((()=>this._destroyElement()),this._element,t)}_destroyElement(){this._element.remove(),F.trigger(this._element,J),this.dispose()}static jQueryInterface(t){return this.each((function(){const e=it.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}Y(it,"close"),E(it);const nt="button",st="active",ot='[data-bs-toggle="button"]',rt="click.bs.button.data-api";class at extends X{static get NAME(){return nt}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle(st))}static jQueryInterface(t){return this.each((function(){const e=at.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}function lt(t){return"true"===t||"false"!==t&&(t===Number(t).toString()?Number(t):""===t||"null"===t?null:t)}function ct(t){return t.replace(/[A-Z]/g,(t=>`-${t.toLowerCase()}`))}F.on(document,rt,ot,(t=>{t.preventDefault();const e=t.target.closest(ot);at.getOrCreateInstance(e).toggle()})),E(at);const ht={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${ct(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${ct(e)}`)},getDataAttributes(t){if(!t)return{};const e={};return Object.keys(t.dataset).filter((t=>t.startsWith("bs"))).forEach((i=>{let n=i.replace(/^bs/,"");n=n.charAt(0).toLowerCase()+n.slice(1,n.length),e[n]=lt(t.dataset[i])})),e},getDataAttribute:(t,e)=>lt(t.getAttribute(`data-bs-${ct(e)}`)),offset(t){const e=t.getBoundingClientRect();return{top:e.top+window.pageYOffset,left:e.left+window.pageXOffset}},position:t=>({top:t.offsetTop,left:t.offsetLeft})},dt=3,ut={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter((t=>t.matches(e))),parents(t,e){const i=[];let n=t.parentNode;for(;n&&n.nodeType===Node.ELEMENT_NODE&&n.nodeType!==dt;)n.matches(e)&&i.push(n),n=n.parentNode;return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((t=>`${t}:not([tabindex^="-"])`)).join(", ");return this.find(e,t).filter((t=>!p(t)&&f(t)))}},ft="carousel",pt=".bs.carousel",gt=".data-api",mt=500,_t=40,vt={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},bt={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},yt="next",wt="prev",Et="left",At="right",Tt={ArrowLeft:At,ArrowRight:Et},Ot=`slide${pt}`,Ct=`slid${pt}`,kt=`keydown${pt}`,Lt=`mouseenter${pt}`,xt=`mouseleave${pt}`,$t=`touchstart${pt}`,Dt=`touchmove${pt}`,St=`touchend${pt}`,Nt=`pointerdown${pt}`,It=`pointerup${pt}`,Pt=`dragstart${pt}`,jt=`load${pt}${gt}`,Mt=`click${pt}${gt}`,Ht="carousel",Bt="active",Rt="slide",Wt="carousel-item-end",zt="carousel-item-start",qt="carousel-item-next",Ft="carousel-item-prev",Ut="pointer-event",Vt=".active",Kt=".active.carousel-item",Xt=".carousel-item",Yt=".carousel-item img",Qt=".carousel-item-next, .carousel-item-prev",Gt=".carousel-indicators",Zt="[data-bs-target]",Jt="[data-bs-slide], [data-bs-slide-to]",te='[data-bs-ride="carousel"]',ee="touch",ie="pen";class ne extends X{constructor(t,e){super(t),this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._indicatorsElement=ut.findOne(Gt,this._element),this._touchSupported="ontouchstart"in document.documentElement||navigator.maxTouchPoints>0,this._pointerEvent=Boolean(window.PointerEvent),this._addEventListeners()}static get Default(){return vt}static get NAME(){return ft}next(){this._slide(yt)}nextWhenVisible(){!document.hidden&&f(this._element)&&this.next()}prev(){this._slide(wt)}pause(t){t||(this._isPaused=!0),ut.findOne(Qt,this._element)&&(c(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null}cycle(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config&&this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))}to(t){this._activeElement=ut.findOne(Kt,this._element);const e=this._getItemIndex(this._activeElement);if(t>this._items.length-1||t<0)return;if(this._isSliding)return void F.one(this._element,Ct,(()=>this.to(t)));if(e===t)return this.pause(),void this.cycle();const i=t>e?yt:wt;this._slide(i,this._items[t])}_getConfig(t){return t={...vt,...ht.getDataAttributes(this._element),..."object"==typeof t?t:{}},u(ft,t,bt),t}_handleSwipe(){const t=Math.abs(this.touchDeltaX);if(t<=_t)return;const e=t/this.touchDeltaX;this.touchDeltaX=0,e&&this._slide(e>0?At:Et)}_addEventListeners(){this._config.keyboard&&F.on(this._element,kt,(t=>this._keydown(t))),"hover"===this._config.pause&&(F.on(this._element,Lt,(t=>this.pause(t))),F.on(this._element,xt,(t=>this.cycle(t)))),this._config.touch&&this._touchSupported&&this._addTouchEventListeners()}_addTouchEventListeners(){const t=t=>this._pointerEvent&&(t.pointerType===ie||t.pointerType===ee),e=e=>{t(e)?this.touchStartX=e.clientX:this._pointerEvent||(this.touchStartX=e.touches[0].clientX)},i=t=>{this.touchDeltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this.touchStartX},n=e=>{t(e)&&(this.touchDeltaX=e.clientX-this.touchStartX),this._handleSwipe(),"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout((t=>this.cycle(t)),mt+this._config.interval))};ut.find(Yt,this._element).forEach((t=>{F.on(t,Pt,(t=>t.preventDefault()))})),this._pointerEvent?(F.on(this._element,Nt,(t=>e(t))),F.on(this._element,It,(t=>n(t))),this._element.classList.add(Ut)):(F.on(this._element,$t,(t=>e(t))),F.on(this._element,Dt,(t=>i(t))),F.on(this._element,St,(t=>n(t))))}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=Tt[t.key];e&&(t.preventDefault(),this._slide(e))}_getItemIndex(t){return this._items=t&&t.parentNode?ut.find(Xt,t.parentNode):[],this._items.indexOf(t)}_getItemByOrder(t,e){const i=t===yt;return O(this._items,e,i,this._config.wrap)}_triggerSlideEvent(t,e){const i=this._getItemIndex(t),n=this._getItemIndex(ut.findOne(Kt,this._element));return F.trigger(this._element,Ot,{relatedTarget:t,direction:e,from:n,to:i})}_setActiveIndicatorElement(t){if(this._indicatorsElement){const e=ut.findOne(Vt,this._indicatorsElement);e.classList.remove(Bt),e.removeAttribute("aria-current");const i=ut.find(Zt,this._indicatorsElement);for(let e=0;e{F.trigger(this._element,Ct,{relatedTarget:o,direction:d,from:s,to:r})};if(this._element.classList.contains(Rt)){o.classList.add(h),_(o),n.classList.add(c),o.classList.add(c);const t=()=>{o.classList.remove(c,h),o.classList.add(Bt),n.classList.remove(Bt,h,c),this._isSliding=!1,setTimeout(u,0)};this._queueCallback(t,n,!0)}else n.classList.remove(Bt),o.classList.add(Bt),this._isSliding=!1,u();a&&this.cycle()}_directionToOrder(t){return[At,Et].includes(t)?w()?t===Et?wt:yt:t===Et?yt:wt:t}_orderToDirection(t){return[yt,wt].includes(t)?w()?t===wt?Et:At:t===wt?At:Et:t}static carouselInterface(t,e){const i=ne.getOrCreateInstance(t,e);let{_config:n}=i;"object"==typeof e&&(n={...n,...e});const s="string"==typeof e?e:n.slide;if("number"==typeof e)i.to(e);else if("string"==typeof s){if(void 0===i[s])throw new TypeError(`No method named "${s}"`);i[s]()}else n.interval&&n.ride&&(i.pause(),i.cycle())}static jQueryInterface(t){return this.each((function(){ne.carouselInterface(this,t)}))}static dataApiClickHandler(t){const e=a(this);if(!e||!e.classList.contains(Ht))return;const i={...ht.getDataAttributes(e),...ht.getDataAttributes(this)},n=this.getAttribute("data-bs-slide-to");n&&(i.interval=!1),ne.carouselInterface(e,i),n&&ne.getInstance(e).to(n),t.preventDefault()}}F.on(document,Mt,Jt,ne.dataApiClickHandler),F.on(window,jt,(()=>{const t=ut.find(te);for(let e=0,i=t.length;et===this._element));null!==n&&s.length&&(this._selector=n,this._triggerArray.push(e))}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return ae}static get NAME(){return se}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t,e=[];if(this._config.parent){const t=ut.find(ve,this._config.parent);e=ut.find(Ee,this._config.parent).filter((e=>!t.includes(e)))}const i=ut.findOne(this._selector);if(e.length){const n=e.find((t=>i!==t));if(t=n?Te.getInstance(n):null,t&&t._isTransitioning)return}if(F.trigger(this._element,ce).defaultPrevented)return;e.forEach((e=>{i!==e&&Te.getOrCreateInstance(e,{toggle:!1}).hide(),t||V.set(e,oe,null)}));const n=this._getDimension();this._element.classList.remove(ge),this._element.classList.add(me),this._element.style[n]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const s=()=>{this._isTransitioning=!1,this._element.classList.remove(me),this._element.classList.add(ge,pe),this._element.style[n]="",F.trigger(this._element,he)},o=`scroll${n[0].toUpperCase()+n.slice(1)}`;this._queueCallback(s,this._element,!0),this._element.style[n]=`${this._element[o]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(F.trigger(this._element,de).defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,_(this._element),this._element.classList.add(me),this._element.classList.remove(ge,pe);const e=this._triggerArray.length;for(let t=0;t{this._isTransitioning=!1,this._element.classList.remove(me),this._element.classList.add(ge),F.trigger(this._element,ue)};this._element.style[t]="",this._queueCallback(i,this._element,!0)}_isShown(t=this._element){return t.classList.contains(pe)}_getConfig(t){return(t={...ae,...ht.getDataAttributes(this._element),...t}).toggle=Boolean(t.toggle),t.parent=d(t.parent),u(se,t,le),t}_getDimension(){return this._element.classList.contains(be)?ye:we}_initializeChildren(){if(!this._config.parent)return;const t=ut.find(ve,this._config.parent);ut.find(Ae,this._config.parent).filter((e=>!t.includes(e))).forEach((t=>{const e=a(t);e&&this._addAriaAndCollapsedClass([t],this._isShown(e))}))}_addAriaAndCollapsedClass(t,e){t.length&&t.forEach((t=>{e?t.classList.remove(_e):t.classList.add(_e),t.setAttribute("aria-expanded",e)}))}static jQueryInterface(t){return this.each((function(){const e={};"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1);const i=Te.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}}))}}F.on(document,fe,Ae,(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();const e=r(this);ut.find(e).forEach((t=>{Te.getOrCreateInstance(t,{toggle:!1}).toggle()}))})),E(Te);var Oe="top",Ce="bottom",ke="right",Le="left",xe="auto",$e=[Oe,Ce,ke,Le],De="start",Se="end",Ne="clippingParents",Ie="viewport",Pe="popper",je="reference",Me=$e.reduce((function(t,e){return t.concat([e+"-"+De,e+"-"+Se])}),[]),He=[].concat($e,[xe]).reduce((function(t,e){return t.concat([e,e+"-"+De,e+"-"+Se])}),[]),Be="beforeRead",Re="read",We="afterRead",ze="beforeMain",qe="main",Fe="afterMain",Ue="beforeWrite",Ve="write",Ke="afterWrite",Xe=[Be,Re,We,ze,qe,Fe,Ue,Ve,Ke];function Ye(t){return t?(t.nodeName||"").toLowerCase():null}function Qe(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function Ge(t){return t instanceof Qe(t).Element||t instanceof Element}function Ze(t){return t instanceof Qe(t).HTMLElement||t instanceof HTMLElement}function Je(t){return"undefined"!=typeof ShadowRoot&&(t instanceof Qe(t).ShadowRoot||t instanceof ShadowRoot)}function ti(t){var e=t.state;Object.keys(e.elements).forEach((function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];Ze(s)&&Ye(s)&&(Object.assign(s.style,i),Object.keys(n).forEach((function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)})))}))}function ei(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach((function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce((function(t,e){return t[e]="",t}),{});Ze(n)&&Ye(n)&&(Object.assign(n.style,o),Object.keys(s).forEach((function(t){n.removeAttribute(t)})))}))}}const ii={name:"applyStyles",enabled:!0,phase:"write",fn:ti,effect:ei,requires:["computeStyles"]};function ni(t){return t.split("-")[0]}function si(t,e){var i=t.getBoundingClientRect(),n=1,s=1;return{width:i.width/n,height:i.height/s,top:i.top/s,right:i.right/n,bottom:i.bottom/s,left:i.left/n,x:i.left/n,y:i.top/s}}function oi(t){var e=si(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function ri(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&Je(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function ai(t){return Qe(t).getComputedStyle(t)}function li(t){return["table","td","th"].indexOf(Ye(t))>=0}function ci(t){return((Ge(t)?t.ownerDocument:t.document)||window.document).documentElement}function hi(t){return"html"===Ye(t)?t:t.assignedSlot||t.parentNode||(Je(t)?t.host:null)||ci(t)}function di(t){return Ze(t)&&"fixed"!==ai(t).position?t.offsetParent:null}function ui(t){var e=-1!==navigator.userAgent.toLowerCase().indexOf("firefox");if(-1!==navigator.userAgent.indexOf("Trident")&&Ze(t)&&"fixed"===ai(t).position)return null;for(var i=hi(t);Ze(i)&&["html","body"].indexOf(Ye(i))<0;){var n=ai(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}function fi(t){for(var e=Qe(t),i=di(t);i&&li(i)&&"static"===ai(i).position;)i=di(i);return i&&("html"===Ye(i)||"body"===Ye(i)&&"static"===ai(i).position)?e:i||ui(t)||e}function pi(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}var gi=Math.max,mi=Math.min,_i=Math.round;function vi(t,e,i){return gi(t,mi(e,i))}function bi(){return{top:0,right:0,bottom:0,left:0}}function yi(t){return Object.assign({},bi(),t)}function wi(t,e){return e.reduce((function(e,i){return e[i]=t,e}),{})}var Ei=function(t,e){return yi("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:wi(t,$e))};function Ai(t){var e,i=t.state,n=t.name,s=t.options,o=i.elements.arrow,r=i.modifiersData.popperOffsets,a=ni(i.placement),l=pi(a),c=[Le,ke].indexOf(a)>=0?"height":"width";if(o&&r){var h=Ei(s.padding,i),d=oi(o),u="y"===l?Oe:Le,f="y"===l?Ce:ke,p=i.rects.reference[c]+i.rects.reference[l]-r[l]-i.rects.popper[c],g=r[l]-i.rects.reference[l],m=fi(o),_=m?"y"===l?m.clientHeight||0:m.clientWidth||0:0,v=p/2-g/2,b=h[u],y=_-d[c]-h[f],w=_/2-d[c]/2+v,E=vi(b,w,y),A=l;i.modifiersData[n]=((e={})[A]=E,e.centerOffset=E-w,e)}}function Ti(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&ri(e.elements.popper,n)&&(e.elements.arrow=n)}const Oi={name:"arrow",enabled:!0,phase:"main",fn:Ai,effect:Ti,requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function Ci(t){return t.split("-")[1]}var ki={top:"auto",right:"auto",bottom:"auto",left:"auto"};function Li(t){var e=t.x,i=t.y,n=window.devicePixelRatio||1;return{x:_i(_i(e*n)/n)||0,y:_i(_i(i*n)/n)||0}}function xi(t){var e,i=t.popper,n=t.popperRect,s=t.placement,o=t.variation,r=t.offsets,a=t.position,l=t.gpuAcceleration,c=t.adaptive,h=t.roundOffsets,d=!0===h?Li(r):"function"==typeof h?h(r):r,u=d.x,f=void 0===u?0:u,p=d.y,g=void 0===p?0:p,m=r.hasOwnProperty("x"),_=r.hasOwnProperty("y"),v=Le,b=Oe,y=window;if(c){var w=fi(i),E="clientHeight",A="clientWidth";w===Qe(i)&&"static"!==ai(w=ci(i)).position&&"absolute"===a&&(E="scrollHeight",A="scrollWidth"),s!==Oe&&(s!==Le&&s!==ke||o!==Se)||(b=Ce,g-=w[E]-n.height,g*=l?1:-1),s!==Le&&(s!==Oe&&s!==Ce||o!==Se)||(v=ke,f-=w[A]-n.width,f*=l?1:-1)}var T,O=Object.assign({position:a},c&&ki);return l?Object.assign({},O,((T={})[b]=_?"0":"",T[v]=m?"0":"",T.transform=(y.devicePixelRatio||1)<=1?"translate("+f+"px, "+g+"px)":"translate3d("+f+"px, "+g+"px, 0)",T)):Object.assign({},O,((e={})[b]=_?g+"px":"",e[v]=m?f+"px":"",e.transform="",e))}function $i(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:ni(e.placement),variation:Ci(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,xi(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,xi(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})}const Di={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:$i,data:{}};var Si={passive:!0};function Ni(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=Qe(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach((function(t){t.addEventListener("scroll",i.update,Si)})),a&&l.addEventListener("resize",i.update,Si),function(){o&&c.forEach((function(t){t.removeEventListener("scroll",i.update,Si)})),a&&l.removeEventListener("resize",i.update,Si)}}const Ii={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:Ni,data:{}};var Pi={left:"right",right:"left",bottom:"top",top:"bottom"};function ji(t){return t.replace(/left|right|bottom|top/g,(function(t){return Pi[t]}))}var Mi={start:"end",end:"start"};function Hi(t){return t.replace(/start|end/g,(function(t){return Mi[t]}))}function Bi(t){var e=Qe(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function Ri(t){return si(ci(t)).left+Bi(t).scrollLeft}function Wi(t){var e=Qe(t),i=ci(t),n=e.visualViewport,s=i.clientWidth,o=i.clientHeight,r=0,a=0;return n&&(s=n.width,o=n.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(r=n.offsetLeft,a=n.offsetTop)),{width:s,height:o,x:r+Ri(t),y:a}}function zi(t){var e,i=ci(t),n=Bi(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=gi(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=gi(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+Ri(t),l=-n.scrollTop;return"rtl"===ai(s||i).direction&&(a+=gi(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}function qi(t){var e=ai(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function Fi(t){return["html","body","#document"].indexOf(Ye(t))>=0?t.ownerDocument.body:Ze(t)&&qi(t)?t:Fi(hi(t))}function Ui(t,e){var i;void 0===e&&(e=[]);var n=Fi(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=Qe(n),r=s?[o].concat(o.visualViewport||[],qi(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(Ui(hi(r)))}function Vi(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function Ki(t){var e=si(t);return e.top=e.top+t.clientTop,e.left=e.left+t.clientLeft,e.bottom=e.top+t.clientHeight,e.right=e.left+t.clientWidth,e.width=t.clientWidth,e.height=t.clientHeight,e.x=e.left,e.y=e.top,e}function Xi(t,e){return e===Ie?Vi(Wi(t)):Ze(e)?Ki(e):Vi(zi(ci(t)))}function Yi(t){var e=Ui(hi(t)),i=["absolute","fixed"].indexOf(ai(t).position)>=0&&Ze(t)?fi(t):t;return Ge(i)?e.filter((function(t){return Ge(t)&&ri(t,i)&&"body"!==Ye(t)})):[]}function Qi(t,e,i){var n="clippingParents"===e?Yi(t):[].concat(e),s=[].concat(n,[i]),o=s[0],r=s.reduce((function(e,i){var n=Xi(t,i);return e.top=gi(n.top,e.top),e.right=mi(n.right,e.right),e.bottom=mi(n.bottom,e.bottom),e.left=gi(n.left,e.left),e}),Xi(t,o));return r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}function Gi(t){var e,i=t.reference,n=t.element,s=t.placement,o=s?ni(s):null,r=s?Ci(s):null,a=i.x+i.width/2-n.width/2,l=i.y+i.height/2-n.height/2;switch(o){case Oe:e={x:a,y:i.y-n.height};break;case Ce:e={x:a,y:i.y+i.height};break;case ke:e={x:i.x+i.width,y:l};break;case Le:e={x:i.x-n.width,y:l};break;default:e={x:i.x,y:i.y}}var c=o?pi(o):null;if(null!=c){var h="y"===c?"height":"width";switch(r){case De:e[c]=e[c]-(i[h]/2-n[h]/2);break;case Se:e[c]=e[c]+(i[h]/2-n[h]/2)}}return e}function Zi(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=void 0===n?t.placement:n,o=i.boundary,r=void 0===o?Ne:o,a=i.rootBoundary,l=void 0===a?Ie:a,c=i.elementContext,h=void 0===c?Pe:c,d=i.altBoundary,u=void 0!==d&&d,f=i.padding,p=void 0===f?0:f,g=yi("number"!=typeof p?p:wi(p,$e)),m=h===Pe?je:Pe,_=t.rects.popper,v=t.elements[u?m:h],b=Qi(Ge(v)?v:v.contextElement||ci(t.elements.popper),r,l),y=si(t.elements.reference),w=Gi({reference:y,element:_,strategy:"absolute",placement:s}),E=Vi(Object.assign({},_,w)),A=h===Pe?E:y,T={top:b.top-A.top+g.top,bottom:A.bottom-b.bottom+g.bottom,left:b.left-A.left+g.left,right:A.right-b.right+g.right},O=t.modifiersData.offset;if(h===Pe&&O){var C=O[s];Object.keys(T).forEach((function(t){var e=[ke,Ce].indexOf(t)>=0?1:-1,i=[Oe,Ce].indexOf(t)>=0?"y":"x";T[t]+=C[i]*e}))}return T}function Ji(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,l=i.allowedAutoPlacements,c=void 0===l?He:l,h=Ci(n),d=h?a?Me:Me.filter((function(t){return Ci(t)===h})):$e,u=d.filter((function(t){return c.indexOf(t)>=0}));0===u.length&&(u=d);var f=u.reduce((function(e,i){return e[i]=Zi(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[ni(i)],e}),{});return Object.keys(f).sort((function(t,e){return f[t]-f[e]}))}function tn(t){if(ni(t)===xe)return[];var e=ji(t);return[Hi(t),e,Hi(e)]}function en(t){var e=t.state,i=t.options,n=t.name;if(!e.modifiersData[n]._skip){for(var s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0===r||r,l=i.fallbackPlacements,c=i.padding,h=i.boundary,d=i.rootBoundary,u=i.altBoundary,f=i.flipVariations,p=void 0===f||f,g=i.allowedAutoPlacements,m=e.options.placement,_=ni(m),v=l||(_!==m&&p?tn(m):[ji(m)]),b=[m].concat(v).reduce((function(t,i){return t.concat(ni(i)===xe?Ji(e,{placement:i,boundary:h,rootBoundary:d,padding:c,flipVariations:p,allowedAutoPlacements:g}):i)}),[]),y=e.rects.reference,w=e.rects.popper,E=new Map,A=!0,T=b[0],O=0;O=0,$=x?"width":"height",D=Zi(e,{placement:C,boundary:h,rootBoundary:d,altBoundary:u,padding:c}),S=x?L?ke:Le:L?Ce:Oe;y[$]>w[$]&&(S=ji(S));var N=ji(S),I=[];if(o&&I.push(D[k]<=0),a&&I.push(D[S]<=0,D[N]<=0),I.every((function(t){return t}))){T=C,A=!1;break}E.set(C,I)}if(A)for(var P=function(t){var e=b.find((function(e){var i=E.get(e);if(i)return i.slice(0,t).every((function(t){return t}))}));if(e)return T=e,"break"},j=p?3:1;j>0&&"break"!==P(j);j--);e.placement!==T&&(e.modifiersData[n]._skip=!0,e.placement=T,e.reset=!0)}}const nn={name:"flip",enabled:!0,phase:"main",fn:en,requiresIfExists:["offset"],data:{_skip:!1}};function sn(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function on(t){return[Oe,ke,Ce,Le].some((function(e){return t[e]>=0}))}function rn(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=Zi(e,{elementContext:"reference"}),a=Zi(e,{altBoundary:!0}),l=sn(r,n),c=sn(a,s,o),h=on(l),d=on(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}const an={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:rn};function ln(t,e,i){var n=ni(t),s=[Le,Oe].indexOf(n)>=0?-1:1,o="function"==typeof i?i(Object.assign({},e,{placement:t})):i,r=o[0],a=o[1];return r=r||0,a=(a||0)*s,[Le,ke].indexOf(n)>=0?{x:a,y:r}:{x:r,y:a}}function cn(t){var e=t.state,i=t.options,n=t.name,s=i.offset,o=void 0===s?[0,0]:s,r=He.reduce((function(t,i){return t[i]=ln(i,e.rects,o),t}),{}),a=r[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[n]=r}const hn={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:cn};function dn(t){var e=t.state,i=t.name;e.modifiersData[i]=Gi({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})}const un={name:"popperOffsets",enabled:!0,phase:"read",fn:dn,data:{}};function fn(t){return"x"===t?"y":"x"}function pn(t){var e=t.state,i=t.options,n=t.name,s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0!==r&&r,l=i.boundary,c=i.rootBoundary,h=i.altBoundary,d=i.padding,u=i.tether,f=void 0===u||u,p=i.tetherOffset,g=void 0===p?0:p,m=Zi(e,{boundary:l,rootBoundary:c,padding:d,altBoundary:h}),_=ni(e.placement),v=Ci(e.placement),b=!v,y=pi(_),w=fn(y),E=e.modifiersData.popperOffsets,A=e.rects.reference,T=e.rects.popper,O="function"==typeof g?g(Object.assign({},e.rects,{placement:e.placement})):g,C={x:0,y:0};if(E){if(o||a){var k="y"===y?Oe:Le,L="y"===y?Ce:ke,x="y"===y?"height":"width",$=E[y],D=E[y]+m[k],S=E[y]-m[L],N=f?-T[x]/2:0,I=v===De?A[x]:T[x],P=v===De?-T[x]:-A[x],j=e.elements.arrow,M=f&&j?oi(j):{width:0,height:0},H=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:bi(),B=H[k],R=H[L],W=vi(0,A[x],M[x]),z=b?A[x]/2-N-W-B-O:I-W-B-O,q=b?-A[x]/2+N+W+R+O:P+W+R+O,F=e.elements.arrow&&fi(e.elements.arrow),U=F?"y"===y?F.clientTop||0:F.clientLeft||0:0,V=e.modifiersData.offset?e.modifiersData.offset[e.placement][y]:0,K=E[y]+z-V-U,X=E[y]+q-V;if(o){var Y=vi(f?mi(D,K):D,$,f?gi(S,X):S);E[y]=Y,C[y]=Y-$}if(a){var Q="x"===y?Oe:Le,G="x"===y?Ce:ke,Z=E[w],J=Z+m[Q],tt=Z-m[G],et=vi(f?mi(J,K):J,Z,f?gi(tt,X):tt);E[w]=et,C[w]=et-Z}}e.modifiersData[n]=C}}const gn={name:"preventOverflow",enabled:!0,phase:"main",fn:pn,requiresIfExists:["offset"]};function mn(t){return{scrollLeft:t.scrollLeft,scrollTop:t.scrollTop}}function _n(t){return t!==Qe(t)&&Ze(t)?mn(t):Bi(t)}function vn(t){var e=t.getBoundingClientRect(),i=e.width/t.offsetWidth||1,n=e.height/t.offsetHeight||1;return 1!==i||1!==n}function bn(t,e,i){void 0===i&&(i=!1);var n=Ze(e);Ze(e)&&vn(e);var s=ci(e),o=si(t),r={scrollLeft:0,scrollTop:0},a={x:0,y:0};return(n||!n&&!i)&&(("body"!==Ye(e)||qi(s))&&(r=_n(e)),Ze(e)?((a=si(e)).x+=e.clientLeft,a.y+=e.clientTop):s&&(a.x=Ri(s))),{x:o.left+r.scrollLeft-a.x,y:o.top+r.scrollTop-a.y,width:o.width,height:o.height}}function yn(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach((function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}})),n.push(t)}return t.forEach((function(t){e.set(t.name,t)})),t.forEach((function(t){i.has(t.name)||s(t)})),n}function wn(t){var e=yn(t);return Xe.reduce((function(t,i){return t.concat(e.filter((function(t){return t.phase===i})))}),[])}function En(t){var e;return function(){return e||(e=new Promise((function(i){Promise.resolve().then((function(){e=void 0,i(t())}))}))),e}}function An(t){var e=t.reduce((function(t,e){var i=t[e.name];return t[e.name]=i?Object.assign({},i,e,{options:Object.assign({},i.options,e.options),data:Object.assign({},i.data,e.data)}):e,t}),{});return Object.keys(e).map((function(t){return e[t]}))}var Tn={placement:"bottom",modifiers:[],strategy:"absolute"};function On(){for(var t=arguments.length,e=new Array(t),i=0;iF.on(t,"mouseover",m))),this._element.focus(),this._element.setAttribute("aria-expanded",!0),this._menu.classList.add(Xn),this._element.classList.add(Xn),F.trigger(this._element,Fn,t)}hide(){if(p(this._element)||!this._isShown(this._menu))return;const t={relatedTarget:this._element};this._completeHide(t)}dispose(){this._popper&&this._popper.destroy(),super.dispose()}update(){this._inNavbar=this._detectNavbar(),this._popper&&this._popper.update()}_completeHide(t){F.trigger(this._element,Wn,t).defaultPrevented||("ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach((t=>F.off(t,"mouseover",m))),this._popper&&this._popper.destroy(),this._menu.classList.remove(Xn),this._element.classList.remove(Xn),this._element.setAttribute("aria-expanded","false"),ht.removeDataAttribute(this._menu,"popper"),F.trigger(this._element,zn,t))}_getConfig(t){if(t={...this.constructor.Default,...ht.getDataAttributes(this._element),...t},u(Dn,t,this.constructor.DefaultType),"object"==typeof t.reference&&!h(t.reference)&&"function"!=typeof t.reference.getBoundingClientRect)throw new TypeError(`${Dn.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`);return t}_createPopper(t){if(void 0===$n)throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");let e=this._element;"parent"===this._config.reference?e=t:h(this._config.reference)?e=d(this._config.reference):"object"==typeof this._config.reference&&(e=this._config.reference);const i=this._getPopperConfig(),n=i.modifiers.find((t=>"applyStyles"===t.name&&!1===t.enabled));this._popper=xn(e,this._menu,i),n&&ht.setDataAttribute(this._menu,"popper","static")}_isShown(t=this._element){return t.classList.contains(Xn)}_getMenuElement(){return ut.next(this._element,ts)[0]}_getPlacement(){const t=this._element.parentNode;if(t.classList.contains(Qn))return as;if(t.classList.contains(Gn))return ls;const e="end"===getComputedStyle(this._menu).getPropertyValue("--bs-position").trim();return t.classList.contains(Yn)?e?ss:ns:e?rs:os}_detectNavbar(){return null!==this._element.closest(`.${Zn}`)}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return"static"===this._config.display&&(t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,..."function"==typeof this._config.popperConfig?this._config.popperConfig(t):this._config.popperConfig}}_selectMenuItem({key:t,target:e}){const i=ut.find(is,this._menu).filter(f);i.length&&O(i,e,t===Hn,!i.includes(e)).focus()}static jQueryInterface(t){return this.each((function(){const e=ds.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}static clearMenus(t){if(t&&(t.button===Bn||"keyup"===t.type&&t.key!==jn))return;const e=ut.find(Jn);for(let i=0,n=e.length;ie+t)),this._setElementAttributes(us,"paddingRight",(e=>e+t)),this._setElementAttributes(fs,"marginRight",(e=>e-t))}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth(),s=t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t)[e];t.style[e]=`${i(Number.parseFloat(s))}px`};this._applyManipulationCallback(t,s)}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,"paddingRight"),this._resetElementAttributes(us,"paddingRight"),this._resetElementAttributes(fs,"marginRight")}_saveInitialAttribute(t,e){const i=t.style[e];i&&ht.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){const i=t=>{const i=ht.getDataAttribute(t,e);void 0===i?t.style.removeProperty(e):(ht.removeDataAttribute(t,e),t.style[e]=i)};this._applyManipulationCallback(t,i)}_applyManipulationCallback(t,e){h(t)?e(t):ut.find(t,this._element).forEach(e)}isOverflowing(){return this.getWidth()>0}}const gs={className:"modal-backdrop",isVisible:!0,isAnimated:!1,rootElement:"body",clickCallback:null},ms={className:"string",isVisible:"boolean",isAnimated:"boolean",rootElement:"(element|string)",clickCallback:"(function|null)"},_s="backdrop",vs="fade",bs="show",ys=`mousedown.bs.${_s}`;class ws{constructor(t){this._config=this._getConfig(t),this._isAppended=!1,this._element=null}show(t){this._config.isVisible?(this._append(),this._config.isAnimated&&_(this._getElement()),this._getElement().classList.add(bs),this._emulateAnimation((()=>{A(t)}))):A(t)}hide(t){this._config.isVisible?(this._getElement().classList.remove(bs),this._emulateAnimation((()=>{this.dispose(),A(t)}))):A(t)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add(vs),this._element=t}return this._element}_getConfig(t){return(t={...gs,..."object"==typeof t?t:{}}).rootElement=d(t.rootElement),u(_s,t,ms),t}_append(){this._isAppended||(this._config.rootElement.append(this._getElement()),F.on(this._getElement(),ys,(()=>{A(this._config.clickCallback)})),this._isAppended=!0)}dispose(){this._isAppended&&(F.off(this._element,ys),this._element.remove(),this._isAppended=!1)}_emulateAnimation(t){T(t,this._getElement(),this._config.isAnimated)}}const Es={trapElement:null,autofocus:!0},As={trapElement:"element",autofocus:"boolean"},Ts="focustrap",Os=".bs.focustrap",Cs=`focusin${Os}`,ks=`keydown.tab${Os}`,Ls="Tab",xs="forward",$s="backward";class Ds{constructor(t){this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}activate(){const{trapElement:t,autofocus:e}=this._config;this._isActive||(e&&t.focus(),F.off(document,Os),F.on(document,Cs,(t=>this._handleFocusin(t))),F.on(document,ks,(t=>this._handleKeydown(t))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,F.off(document,Os))}_handleFocusin(t){const{target:e}=t,{trapElement:i}=this._config;if(e===document||e===i||i.contains(e))return;const n=ut.focusableChildren(i);0===n.length?i.focus():this._lastTabNavDirection===$s?n[n.length-1].focus():n[0].focus()}_handleKeydown(t){t.key===Ls&&(this._lastTabNavDirection=t.shiftKey?$s:xs)}_getConfig(t){return t={...Es,..."object"==typeof t?t:{}},u(Ts,t,As),t}}const Ss="modal",Ns=".bs.modal",Is="Escape",Ps={backdrop:!0,keyboard:!0,focus:!0},js={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean"},Ms=`hide${Ns}`,Hs=`hidePrevented${Ns}`,Bs=`hidden${Ns}`,Rs=`show${Ns}`,Ws=`shown${Ns}`,zs=`resize${Ns}`,qs=`click.dismiss${Ns}`,Fs=`keydown.dismiss${Ns}`,Us=`mouseup.dismiss${Ns}`,Vs=`mousedown.dismiss${Ns}`,Ks=`click${Ns}.data-api`,Xs="modal-open",Ys="fade",Qs="show",Gs="modal-static",Zs=".modal.show",Js=".modal-dialog",to=".modal-body",eo='[data-bs-toggle="modal"]';class io extends X{constructor(t,e){super(t),this._config=this._getConfig(e),this._dialog=ut.findOne(Js,this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._ignoreBackdropClick=!1,this._isTransitioning=!1,this._scrollBar=new ps}static get Default(){return Ps}static get NAME(){return Ss}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||F.trigger(this._element,Rs,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isAnimated()&&(this._isTransitioning=!0),this._scrollBar.hide(),document.body.classList.add(Xs),this._adjustDialog(),this._setEscapeEvent(),this._setResizeEvent(),F.on(this._dialog,Vs,(()=>{F.one(this._element,Us,(t=>{t.target===this._element&&(this._ignoreBackdropClick=!0)}))})),this._showBackdrop((()=>this._showElement(t))))}hide(){if(!this._isShown||this._isTransitioning)return;if(F.trigger(this._element,Ms).defaultPrevented)return;this._isShown=!1;const t=this._isAnimated();t&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),this._focustrap.deactivate(),this._element.classList.remove(Qs),F.off(this._element,qs),F.off(this._dialog,Vs),this._queueCallback((()=>this._hideModal()),this._element,t)}dispose(){[window,this._dialog].forEach((t=>F.off(t,Ns))),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new ws({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new Ds({trapElement:this._element})}_getConfig(t){return t={...Ps,...ht.getDataAttributes(this._element),..."object"==typeof t?t:{}},u(Ss,t,js),t}_showElement(t){const e=this._isAnimated(),i=ut.findOne(to,this._dialog);this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0,i&&(i.scrollTop=0),e&&_(this._element),this._element.classList.add(Qs);const n=()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,F.trigger(this._element,Ws,{relatedTarget:t})};this._queueCallback(n,this._dialog,e)}_setEscapeEvent(){this._isShown?F.on(this._element,Fs,(t=>{this._config.keyboard&&t.key===Is?(t.preventDefault(),this.hide()):this._config.keyboard||t.key!==Is||this._triggerBackdropTransition()})):F.off(this._element,Fs)}_setResizeEvent(){this._isShown?F.on(window,zs,(()=>this._adjustDialog())):F.off(window,zs)}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(Xs),this._resetAdjustments(),this._scrollBar.reset(),F.trigger(this._element,Bs)}))}_showBackdrop(t){F.on(this._element,qs,(t=>{this._ignoreBackdropClick?this._ignoreBackdropClick=!1:t.target===t.currentTarget&&(!0===this._config.backdrop?this.hide():"static"===this._config.backdrop&&this._triggerBackdropTransition())})),this._backdrop.show(t)}_isAnimated(){return this._element.classList.contains(Ys)}_triggerBackdropTransition(){if(F.trigger(this._element,Hs).defaultPrevented)return;const{classList:t,scrollHeight:e,style:i}=this._element,n=e>document.documentElement.clientHeight;!n&&"hidden"===i.overflowY||t.contains(Gs)||(n||(i.overflowY="hidden"),t.add(Gs),this._queueCallback((()=>{t.remove(Gs),n||this._queueCallback((()=>{i.overflowY=""}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;(!i&&t&&!w()||i&&!t&&w())&&(this._element.style.paddingLeft=`${e}px`),(i&&!t&&!w()||!i&&t&&w())&&(this._element.style.paddingRight=`${e}px`)}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const i=io.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}F.on(document,Ks,eo,(function(t){const e=a(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),F.one(e,Rs,(t=>{t.defaultPrevented||F.one(e,Bs,(()=>{f(this)&&this.focus()}))}));const i=ut.findOne(Zs);i&&io.getInstance(i).hide(),io.getOrCreateInstance(e).toggle(this)})),Y(io),E(io);const no="offcanvas",so=".bs.offcanvas",oo=".data-api",ro=`load${so}${oo}`,ao="Escape",lo={backdrop:!0,keyboard:!0,scroll:!1},co={backdrop:"boolean",keyboard:"boolean",scroll:"boolean"},ho="show",uo="offcanvas-backdrop",fo=".offcanvas.show",po=`show${so}`,go=`shown${so}`,mo=`hide${so}`,_o=`hidden${so}`,vo=`click${so}${oo}`,bo=`keydown.dismiss${so}`,yo='[data-bs-toggle="offcanvas"]';class wo extends X{constructor(t,e){super(t),this._config=this._getConfig(e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get NAME(){return no}static get Default(){return lo}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){if(this._isShown)return;if(F.trigger(this._element,po,{relatedTarget:t}).defaultPrevented)return;this._isShown=!0,this._element.style.visibility="visible",this._backdrop.show(),this._config.scroll||(new ps).hide(),this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(ho);const e=()=>{this._config.scroll||this._focustrap.activate(),F.trigger(this._element,go,{relatedTarget:t})};this._queueCallback(e,this._element,!0)}hide(){if(!this._isShown)return;if(F.trigger(this._element,mo).defaultPrevented)return;this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.remove(ho),this._backdrop.hide();const t=()=>{this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._element.style.visibility="hidden",this._config.scroll||(new ps).reset(),F.trigger(this._element,_o)};this._queueCallback(t,this._element,!0)}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_getConfig(t){return t={...lo,...ht.getDataAttributes(this._element),..."object"==typeof t?t:{}},u(no,t,co),t}_initializeBackDrop(){return new ws({className:uo,isVisible:this._config.backdrop,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:()=>this.hide()})}_initializeFocusTrap(){return new Ds({trapElement:this._element})}_addEventListeners(){F.on(this._element,bo,(t=>{this._config.keyboard&&t.key===ao&&this.hide()}))}static jQueryInterface(t){return this.each((function(){const e=wo.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}F.on(document,vo,yo,(function(t){const e=a(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),p(this))return;F.one(e,_o,(()=>{f(this)&&this.focus()}));const i=ut.findOne(fo);i&&i!==e&&wo.getInstance(i).hide(),wo.getOrCreateInstance(e).toggle(this)})),F.on(window,ro,(()=>ut.find(fo).forEach((t=>wo.getOrCreateInstance(t).show())))),Y(wo),E(wo);const Eo=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Ao=/^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i,To=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i,Oo=(t,e)=>{const i=t.nodeName.toLowerCase();if(e.includes(i))return!Eo.has(i)||Boolean(Ao.test(t.nodeValue)||To.test(t.nodeValue));const n=e.filter((t=>t instanceof RegExp));for(let t=0,e=n.length;t{Oo(t,r)||i.removeAttribute(t.nodeName)}))}return n.body.innerHTML}const Lo="tooltip",xo=".bs.tooltip",$o="bs-tooltip",Do=new Set(["sanitize","allowList","sanitizeFn"]),So={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(array|string|function)",container:"(string|element|boolean)",fallbackPlacements:"array",boundary:"(string|element)",customClass:"(string|function)",sanitize:"boolean",sanitizeFn:"(null|function)",allowList:"object",popperConfig:"(null|object|function)"},No={AUTO:"auto",TOP:"top",RIGHT:w()?"left":"right",BOTTOM:"bottom",LEFT:w()?"right":"left"},Io={animation:!0,template:'',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:[0,0],container:!1,fallbackPlacements:["top","right","bottom","left"],boundary:"clippingParents",customClass:"",sanitize:!0,sanitizeFn:null,allowList:Co,popperConfig:null},Po={HIDE:`hide${xo}`,HIDDEN:`hidden${xo}`,SHOW:`show${xo}`,SHOWN:`shown${xo}`,INSERTED:`inserted${xo}`,CLICK:`click${xo}`,FOCUSIN:`focusin${xo}`,FOCUSOUT:`focusout${xo}`,MOUSEENTER:`mouseenter${xo}`,MOUSELEAVE:`mouseleave${xo}`},jo="fade",Mo="show",Ho="show",Bo="out",Ro=".tooltip-inner",Wo=".modal",zo="hide.bs.modal",qo="hover",Fo="focus",Uo="click",Vo="manual";class Ko extends X{constructor(t,e){if(void 0===$n)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t),this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this._config=this._getConfig(e),this.tip=null,this._setListeners()}static get Default(){return Io}static get NAME(){return Lo}static get Event(){return Po}static get DefaultType(){return So}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(t){if(this._isEnabled)if(t){const e=this._initializeOnDelegatedTarget(t);e._activeTrigger.click=!e._activeTrigger.click,e._isWithActiveTrigger()?e._enter(null,e):e._leave(null,e)}else{if(this.getTipElement().classList.contains(Mo))return void this._leave(null,this);this._enter(null,this)}}dispose(){clearTimeout(this._timeout),F.off(this._element.closest(Wo),zo,this._hideModalHandler),this.tip&&this.tip.remove(),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this.isWithContent()||!this._isEnabled)return;const t=F.trigger(this._element,this.constructor.Event.SHOW),e=g(this._element),i=null===e?this._element.ownerDocument.documentElement.contains(this._element):e.contains(this._element);if(t.defaultPrevented||!i)return;"tooltip"===this.constructor.NAME&&this.tip&&this.getTitle()!==this.tip.querySelector(Ro).innerHTML&&(this._disposePopper(),this.tip.remove(),this.tip=null);const n=this.getTipElement(),o=s(this.constructor.NAME);n.setAttribute("id",o),this._element.setAttribute("aria-describedby",o),this._config.animation&&n.classList.add(jo);const r="function"==typeof this._config.placement?this._config.placement.call(this,n,this._element):this._config.placement,a=this._getAttachment(r);this._addAttachmentClass(a);const{container:l}=this._config;V.set(n,this.constructor.DATA_KEY,this),this._element.ownerDocument.documentElement.contains(this.tip)||(l.append(n),F.trigger(this._element,this.constructor.Event.INSERTED)),this._popper?this._popper.update():this._popper=xn(this._element,n,this._getPopperConfig(a)),n.classList.add(Mo);const c=this._resolvePossibleFunction(this._config.customClass);c&&n.classList.add(...c.split(" ")),"ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach((t=>{F.on(t,"mouseover",m)}));const h=()=>{const t=this._hoverState;this._hoverState=null,F.trigger(this._element,this.constructor.Event.SHOWN),t===Bo&&this._leave(null,this)},d=this.tip.classList.contains(jo);this._queueCallback(h,this.tip,d)}hide(){if(!this._popper)return;const t=this.getTipElement(),e=()=>{this._isWithActiveTrigger()||(this._hoverState!==Ho&&t.remove(),this._cleanTipClass(),this._element.removeAttribute("aria-describedby"),F.trigger(this._element,this.constructor.Event.HIDDEN),this._disposePopper())};if(F.trigger(this._element,this.constructor.Event.HIDE).defaultPrevented)return;t.classList.remove(Mo),"ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach((t=>F.off(t,"mouseover",m))),this._activeTrigger[Uo]=!1,this._activeTrigger[Fo]=!1,this._activeTrigger[qo]=!1;const i=this.tip.classList.contains(jo);this._queueCallback(e,this.tip,i),this._hoverState=""}update(){null!==this._popper&&this._popper.update()}isWithContent(){return Boolean(this.getTitle())}getTipElement(){if(this.tip)return this.tip;const t=document.createElement("div");t.innerHTML=this._config.template;const e=t.children[0];return this.setContent(e),e.classList.remove(jo,Mo),this.tip=e,this.tip}setContent(t){this._sanitizeAndSetContent(t,this.getTitle(),Ro)}_sanitizeAndSetContent(t,e,i){const n=ut.findOne(i,t);e||!n?this.setElementContent(n,e):n.remove()}setElementContent(t,e){if(null!==t)return h(e)?(e=d(e),void(this._config.html?e.parentNode!==t&&(t.innerHTML="",t.append(e)):t.textContent=e.textContent)):void(this._config.html?(this._config.sanitize&&(e=ko(e,this._config.allowList,this._config.sanitizeFn)),t.innerHTML=e):t.textContent=e)}getTitle(){const t=this._element.getAttribute("data-bs-original-title")||this._config.title;return this._resolvePossibleFunction(t)}updateAttachment(t){return"right"===t?"end":"left"===t?"start":t}_initializeOnDelegatedTarget(t,e){return e||this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return"function"==typeof t?t.call(this._element):t}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"onChange",enabled:!0,phase:"afterWrite",fn:t=>this._handlePopperPlacementChange(t)}],onFirstUpdate:t=>{t.options.placement!==t.placement&&this._handlePopperPlacementChange(t)}};return{...e,..."function"==typeof this._config.popperConfig?this._config.popperConfig(e):this._config.popperConfig}}_addAttachmentClass(t){this.getTipElement().classList.add(`${this._getBasicClassPrefix()}-${this.updateAttachment(t)}`)}_getAttachment(t){return No[t.toUpperCase()]}_setListeners(){this._config.trigger.split(" ").forEach((t=>{if("click"===t)F.on(this._element,this.constructor.Event.CLICK,this._config.selector,(t=>this.toggle(t)));else if(t!==Vo){const e=t===qo?this.constructor.Event.MOUSEENTER:this.constructor.Event.FOCUSIN,i=t===qo?this.constructor.Event.MOUSELEAVE:this.constructor.Event.FOCUSOUT;F.on(this._element,e,this._config.selector,(t=>this._enter(t))),F.on(this._element,i,this._config.selector,(t=>this._leave(t)))}})),this._hideModalHandler=()=>{this._element&&this.hide()},F.on(this._element.closest(Wo),zo,this._hideModalHandler),this._config.selector?this._config={...this._config,trigger:"manual",selector:""}:this._fixTitle()}_fixTitle(){const t=this._element.getAttribute("title"),e=typeof this._element.getAttribute("data-bs-original-title");(t||"string"!==e)&&(this._element.setAttribute("data-bs-original-title",t||""),!t||this._element.getAttribute("aria-label")||this._element.textContent||this._element.setAttribute("aria-label",t),this._element.setAttribute("title",""))}_enter(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusin"===t.type?Fo:qo]=!0),e.getTipElement().classList.contains(Mo)||e._hoverState===Ho?e._hoverState=Ho:(clearTimeout(e._timeout),e._hoverState=Ho,e._config.delay&&e._config.delay.show?e._timeout=setTimeout((()=>{e._hoverState===Ho&&e.show()}),e._config.delay.show):e.show())}_leave(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusout"===t.type?Fo:qo]=e._element.contains(t.relatedTarget)),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=Bo,e._config.delay&&e._config.delay.hide?e._timeout=setTimeout((()=>{e._hoverState===Bo&&e.hide()}),e._config.delay.hide):e.hide())}_isWithActiveTrigger(){for(const t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1}_getConfig(t){const e=ht.getDataAttributes(this._element);return Object.keys(e).forEach((t=>{Do.has(t)&&delete e[t]})),(t={...this.constructor.Default,...e,..."object"==typeof t&&t?t:{}}).container=!1===t.container?document.body:d(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),u(Lo,t,this.constructor.DefaultType),t.sanitize&&(t.template=ko(t.template,t.allowList,t.sanitizeFn)),t}_getDelegateConfig(){const t={};for(const e in this._config)this.constructor.Default[e]!==this._config[e]&&(t[e]=this._config[e]);return t}_cleanTipClass(){const t=this.getTipElement(),e=new RegExp(`(^|\\s)${this._getBasicClassPrefix()}\\S+`,"g"),i=t.getAttribute("class").match(e);null!==i&&i.length>0&&i.map((t=>t.trim())).forEach((e=>t.classList.remove(e)))}_getBasicClassPrefix(){return $o}_handlePopperPlacementChange(t){const{state:e}=t;e&&(this.tip=e.elements.popper,this._cleanTipClass(),this._addAttachmentClass(this._getAttachment(e.placement)))}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null)}static jQueryInterface(t){return this.each((function(){const e=Ko.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}E(Ko);const Xo="popover",Yo=".bs.popover",Qo="bs-popover",Go={...Ko.Default,placement:"right",offset:[0,8],trigger:"click",content:"",template:''},Zo={...Ko.DefaultType,content:"(string|element|function)"},Jo={HIDE:`hide${Yo}`,HIDDEN:`hidden${Yo}`,SHOW:`show${Yo}`,SHOWN:`shown${Yo}`,INSERTED:`inserted${Yo}`,CLICK:`click${Yo}`,FOCUSIN:`focusin${Yo}`,FOCUSOUT:`focusout${Yo}`,MOUSEENTER:`mouseenter${Yo}`,MOUSELEAVE:`mouseleave${Yo}`},tr=".popover-header",er=".popover-body";class ir extends Ko{static get Default(){return Go}static get NAME(){return Xo}static get Event(){return Jo}static get DefaultType(){return Zo}isWithContent(){return this.getTitle()||this._getContent()}setContent(t){this._sanitizeAndSetContent(t,this.getTitle(),tr),this._sanitizeAndSetContent(t,this._getContent(),er)}_getContent(){return this._resolvePossibleFunction(this._config.content)}_getBasicClassPrefix(){return Qo}static jQueryInterface(t){return this.each((function(){const e=ir.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}E(ir);const nr="scrollspy",sr=".bs.scrollspy",or={offset:10,method:"auto",target:""},rr={offset:"number",method:"string",target:"(string|element)"},ar=`activate${sr}`,lr=`scroll${sr}`,cr=`load${sr}.data-api`,hr="dropdown-item",dr="active",ur='[data-bs-spy="scroll"]',fr=".nav, .list-group",pr=".nav-link",gr=".nav-item",mr=".list-group-item",_r=`${pr}, ${mr}, .${hr}`,vr=".dropdown",br=".dropdown-toggle",yr="offset",wr="position";class Er extends X{constructor(t,e){super(t),this._scrollElement="BODY"===this._element.tagName?window:this._element,this._config=this._getConfig(e),this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,F.on(this._scrollElement,lr,(()=>this._process())),this.refresh(),this._process()}static get Default(){return or}static get NAME(){return nr}refresh(){const t=this._scrollElement===this._scrollElement.window?yr:wr,e="auto"===this._config.method?t:this._config.method,i=e===wr?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),ut.find(_r,this._config.target).map((t=>{const n=r(t),s=n?ut.findOne(n):null;if(s){const t=s.getBoundingClientRect();if(t.width||t.height)return[ht[e](s).top+i,n]}return null})).filter((t=>t)).sort(((t,e)=>t[0]-e[0])).forEach((t=>{this._offsets.push(t[0]),this._targets.push(t[1])}))}dispose(){F.off(this._scrollElement,sr),super.dispose()}_getConfig(t){return(t={...or,...ht.getDataAttributes(this._element),..."object"==typeof t&&t?t:{}}).target=d(t.target)||document.documentElement,u(nr,t,rr),t}_getScrollTop(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop}_getScrollHeight(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)}_getOffsetHeight(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height}_process(){const t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),i=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=i){const t=this._targets[this._targets.length-1];this._activeTarget!==t&&this._activate(t)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(let e=this._offsets.length;e--;)this._activeTarget!==this._targets[e]&&t>=this._offsets[e]&&(void 0===this._offsets[e+1]||t`${e}[data-bs-target="${t}"],${e}[href="${t}"]`)),i=ut.findOne(e.join(","),this._config.target);i.classList.add(dr),i.classList.contains(hr)?ut.findOne(br,i.closest(vr)).classList.add(dr):ut.parents(i,fr).forEach((t=>{ut.prev(t,`${pr}, ${mr}`).forEach((t=>t.classList.add(dr))),ut.prev(t,gr).forEach((t=>{ut.children(t,pr).forEach((t=>t.classList.add(dr)))}))})),F.trigger(this._scrollElement,ar,{relatedTarget:t})}_clear(){ut.find(_r,this._config.target).filter((t=>t.classList.contains(dr))).forEach((t=>t.classList.remove(dr)))}static jQueryInterface(t){return this.each((function(){const e=Er.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}F.on(window,cr,(()=>{ut.find(ur).forEach((t=>new Er(t)))})),E(Er);const Ar="tab",Tr=".bs.tab",Or=`hide${Tr}`,Cr=`hidden${Tr}`,kr=`show${Tr}`,Lr=`shown${Tr}`,xr=`click${Tr}.data-api`,$r="dropdown-menu",Dr="active",Sr="fade",Nr="show",Ir=".dropdown",Pr=".nav, .list-group",jr=".active",Mr=":scope > li > .active",Hr='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',Br=".dropdown-toggle",Rr=":scope > .dropdown-menu .active";class Wr extends X{static get NAME(){return Ar}show(){if(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&this._element.classList.contains(Dr))return;let t;const e=a(this._element),i=this._element.closest(Pr);if(i){const e="UL"===i.nodeName||"OL"===i.nodeName?Mr:jr;t=ut.find(e,i),t=t[t.length-1]}const n=t?F.trigger(t,Or,{relatedTarget:this._element}):null;if(F.trigger(this._element,kr,{relatedTarget:t}).defaultPrevented||null!==n&&n.defaultPrevented)return;this._activate(this._element,i);const s=()=>{F.trigger(t,Cr,{relatedTarget:this._element}),F.trigger(this._element,Lr,{relatedTarget:t})};e?this._activate(e,e.parentNode,s):s()}_activate(t,e,i){const n=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?ut.children(e,jr):ut.find(Mr,e))[0],s=i&&n&&n.classList.contains(Sr),o=()=>this._transitionComplete(t,n,i);n&&s?(n.classList.remove(Nr),this._queueCallback(o,t,!0)):o()}_transitionComplete(t,e,i){if(e){e.classList.remove(Dr);const t=ut.findOne(Rr,e.parentNode);t&&t.classList.remove(Dr),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}t.classList.add(Dr),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),_(t),t.classList.contains(Sr)&&t.classList.add(Nr);let n=t.parentNode;if(n&&"LI"===n.nodeName&&(n=n.parentNode),n&&n.classList.contains($r)){const e=t.closest(Ir);e&&ut.find(Br,e).forEach((t=>t.classList.add(Dr))),t.setAttribute("aria-expanded",!0)}i&&i()}static jQueryInterface(t){return this.each((function(){const e=Wr.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}F.on(document,xr,Hr,(function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),p(this)||Wr.getOrCreateInstance(this).show()})),E(Wr);const zr="toast",qr=".bs.toast",Fr=`mouseover${qr}`,Ur=`mouseout${qr}`,Vr=`focusin${qr}`,Kr=`focusout${qr}`,Xr=`hide${qr}`,Yr=`hidden${qr}`,Qr=`show${qr}`,Gr=`shown${qr}`,Zr="fade",Jr="hide",ta="show",ea="showing",ia={animation:"boolean",autohide:"boolean",delay:"number"},na={animation:!0,autohide:!0,delay:5e3};class sa extends X{constructor(t,e){super(t),this._config=this._getConfig(e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get DefaultType(){return ia}static get Default(){return na}static get NAME(){return zr}show(){if(F.trigger(this._element,Qr).defaultPrevented)return;this._clearTimeout(),this._config.animation&&this._element.classList.add(Zr);const t=()=>{this._element.classList.remove(ea),F.trigger(this._element,Gr),this._maybeScheduleHide()};this._element.classList.remove(Jr),_(this._element),this._element.classList.add(ta),this._element.classList.add(ea),this._queueCallback(t,this._element,this._config.animation)}hide(){if(!this._element.classList.contains(ta))return;if(F.trigger(this._element,Xr).defaultPrevented)return;const t=()=>{this._element.classList.add(Jr),this._element.classList.remove(ea),this._element.classList.remove(ta),F.trigger(this._element,Yr)};this._element.classList.add(ea),this._queueCallback(t,this._element,this._config.animation)}dispose(){this._clearTimeout(),this._element.classList.contains(ta)&&this._element.classList.remove(ta),super.dispose()}_getConfig(t){return t={...na,...ht.getDataAttributes(this._element),..."object"==typeof t&&t?t:{}},u(zr,t,this.constructor.DefaultType),t}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){F.on(this._element,Fr,(t=>this._onInteraction(t,!0))),F.on(this._element,Ur,(t=>this._onInteraction(t,!1))),F.on(this._element,Vr,(t=>this._onInteraction(t,!0))),F.on(this._element,Kr,(t=>this._onInteraction(t,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=sa.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}return Y(sa),E(sa),{Alert:it,Button:at,Carousel:ne,Collapse:Te,Dropdown:ds,Modal:io,Offcanvas:wo,Popover:ir,ScrollSpy:Er,Tab:Wr,Toast:sa,Tooltip:Ko}}()}},e={};function i(n){var s=e[n];if(void 0!==s)return s.exports;var o=e[n]={exports:{}};return t[n].call(o.exports,o,o.exports,i),o.exports}i.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return i.d(e,{a:e}),e},i.d=(t,e)=>{for(var n in e)i.o(e,n)&&!i.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),(()=>{"use strict";i(577)})()})(); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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RCxFQUFRQSxFQUFPQyxRQUFTMHdDLEdBR3BFM3dDLEVBQU9DLFFDcEJmMHdDLEVBQW9CSSxFQUFLL3dDLElBQ3hCLElBQUlneEMsRUFBU2h4QyxHQUFVQSxFQUFPaXhDLFdBQzdCLElBQU9qeEMsRUFBaUIsUUFDeEIsSUFBTSxFQUVQLE9BREEyd0MsRUFBb0JPLEVBQUVGLEVBQVEsQ0FBRXprQixFQUFHeWtCLElBQzVCQSxHQ0xSTCxFQUFvQk8sRUFBSSxDQUFDanhDLEVBQVNreEMsS0FDakMsSUFBSSxJQUFJN2tDLEtBQU82a0MsRUFDWFIsRUFBb0JTLEVBQUVELEVBQVk3a0MsS0FBU3FrQyxFQUFvQlMsRUFBRW54QyxFQUFTcU0sSUFDNUVuSixPQUFPb0osZUFBZXRNLEVBQVNxTSxFQUFLLENBQUUra0MsWUFBWSxFQUFNN2tDLElBQUsya0MsRUFBVzdrQyxNQ0ozRXFrQyxFQUFvQlMsRUFBSSxDQUFDOXdDLEVBQUtneEMsSUFBVW51QyxPQUFPMk8sVUFBVStPLGVBQWVyZ0IsS0FBS0YsRUFBS2d4QyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ib290c3RyYXAvZGlzdC9qcy9ib290c3RyYXAuYnVuZGxlLmpzIiwid2VicGFjazovLy93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly8vd2VicGFjay9ydW50aW1lL2NvbXBhdCBnZXQgZGVmYXVsdCBleHBvcnQiLCJ3ZWJwYWNrOi8vL3dlYnBhY2svcnVudGltZS9kZWZpbmUgcHJvcGVydHkgZ2V0dGVycyIsIndlYnBhY2s6Ly8vd2VicGFjay9ydW50aW1lL2hhc093blByb3BlcnR5IHNob3J0aGFuZCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAgKiBCb290c3RyYXAgdjUuMS4zIChodHRwczovL2dldGJvb3RzdHJhcC5jb20vKVxuICAqIENvcHlyaWdodCAyMDExLTIwMjEgVGhlIEJvb3RzdHJhcCBBdXRob3JzIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvZ3JhcGhzL2NvbnRyaWJ1dG9ycylcbiAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgKi9cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpIDpcbiAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKGZhY3RvcnkpIDpcbiAgKGdsb2JhbCA9IHR5cGVvZiBnbG9iYWxUaGlzICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbFRoaXMgOiBnbG9iYWwgfHwgc2VsZiwgZ2xvYmFsLmJvb3RzdHJhcCA9IGZhY3RvcnkoKSk7XG59KSh0aGlzLCAoZnVuY3Rpb24gKCkgeyAndXNlIHN0cmljdCc7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjUuMS4zKTogdXRpbC9pbmRleC5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIGNvbnN0IE1BWF9VSUQgPSAxMDAwMDAwO1xuICBjb25zdCBNSUxMSVNFQ09ORFNfTVVMVElQTElFUiA9IDEwMDA7XG4gIGNvbnN0IFRSQU5TSVRJT05fRU5EID0gJ3RyYW5zaXRpb25lbmQnOyAvLyBTaG91dG91dCBBbmd1c0Nyb2xsIChodHRwczovL2dvby5nbC9weHdRR3ApXG5cbiAgY29uc3QgdG9UeXBlID0gb2JqID0+IHtcbiAgICBpZiAob2JqID09PSBudWxsIHx8IG9iaiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gYCR7b2JqfWA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHt9LnRvU3RyaW5nLmNhbGwob2JqKS5tYXRjaCgvXFxzKFthLXpdKykvaSlbMV0udG9Mb3dlckNhc2UoKTtcbiAgfTtcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIFB1YmxpYyBVdGlsIEFwaVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuXG4gIGNvbnN0IGdldFVJRCA9IHByZWZpeCA9PiB7XG4gICAgZG8ge1xuICAgICAgcHJlZml4ICs9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIE1BWF9VSUQpO1xuICAgIH0gd2hpbGUgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHByZWZpeCkpO1xuXG4gICAgcmV0dXJuIHByZWZpeDtcbiAgfTtcblxuICBjb25zdCBnZXRTZWxlY3RvciA9IGVsZW1lbnQgPT4ge1xuICAgIGxldCBzZWxlY3RvciA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLWJzLXRhcmdldCcpO1xuXG4gICAgaWYgKCFzZWxlY3RvciB8fCBzZWxlY3RvciA9PT0gJyMnKSB7XG4gICAgICBsZXQgaHJlZkF0dHIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnaHJlZicpOyAvLyBUaGUgb25seSB2YWxpZCBjb250ZW50IHRoYXQgY291bGQgZG91YmxlIGFzIGEgc2VsZWN0b3IgYXJlIElEcyBvciBjbGFzc2VzLFxuICAgICAgLy8gc28gZXZlcnl0aGluZyBzdGFydGluZyB3aXRoIGAjYCBvciBgLmAuIElmIGEgXCJyZWFsXCIgVVJMIGlzIHVzZWQgYXMgdGhlIHNlbGVjdG9yLFxuICAgICAgLy8gYGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JgIHdpbGwgcmlnaHRmdWxseSBjb21wbGFpbiBpdCBpcyBpbnZhbGlkLlxuICAgICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9pc3N1ZXMvMzIyNzNcblxuICAgICAgaWYgKCFocmVmQXR0ciB8fCAhaHJlZkF0dHIuaW5jbHVkZXMoJyMnKSAmJiAhaHJlZkF0dHIuc3RhcnRzV2l0aCgnLicpKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfSAvLyBKdXN0IGluIGNhc2Ugc29tZSBDTVMgcHV0cyBvdXQgYSBmdWxsIFVSTCB3aXRoIHRoZSBhbmNob3IgYXBwZW5kZWRcblxuXG4gICAgICBpZiAoaHJlZkF0dHIuaW5jbHVkZXMoJyMnKSAmJiAhaHJlZkF0dHIuc3RhcnRzV2l0aCgnIycpKSB7XG4gICAgICAgIGhyZWZBdHRyID0gYCMke2hyZWZBdHRyLnNwbGl0KCcjJylbMV19YDtcbiAgICAgIH1cblxuICAgICAgc2VsZWN0b3IgPSBocmVmQXR0ciAmJiBocmVmQXR0ciAhPT0gJyMnID8gaHJlZkF0dHIudHJpbSgpIDogbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZWN0b3I7XG4gIH07XG5cbiAgY29uc3QgZ2V0U2VsZWN0b3JGcm9tRWxlbWVudCA9IGVsZW1lbnQgPT4ge1xuICAgIGNvbnN0IHNlbGVjdG9yID0gZ2V0U2VsZWN0b3IoZWxlbWVudCk7XG5cbiAgICBpZiAoc2VsZWN0b3IpIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHNlbGVjdG9yKSA/IHNlbGVjdG9yIDogbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfTtcblxuICBjb25zdCBnZXRFbGVtZW50RnJvbVNlbGVjdG9yID0gZWxlbWVudCA9PiB7XG4gICAgY29uc3Qgc2VsZWN0b3IgPSBnZXRTZWxlY3RvcihlbGVtZW50KTtcbiAgICByZXR1cm4gc2VsZWN0b3IgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHNlbGVjdG9yKSA6IG51bGw7XG4gIH07XG5cbiAgY29uc3QgZ2V0VHJhbnNpdGlvbkR1cmF0aW9uRnJvbUVsZW1lbnQgPSBlbGVtZW50ID0+IHtcbiAgICBpZiAoIWVsZW1lbnQpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gLy8gR2V0IHRyYW5zaXRpb24tZHVyYXRpb24gb2YgdGhlIGVsZW1lbnRcblxuXG4gICAgbGV0IHtcbiAgICAgIHRyYW5zaXRpb25EdXJhdGlvbixcbiAgICAgIHRyYW5zaXRpb25EZWxheVxuICAgIH0gPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50KTtcbiAgICBjb25zdCBmbG9hdFRyYW5zaXRpb25EdXJhdGlvbiA9IE51bWJlci5wYXJzZUZsb2F0KHRyYW5zaXRpb25EdXJhdGlvbik7XG4gICAgY29uc3QgZmxvYXRUcmFuc2l0aW9uRGVsYXkgPSBOdW1iZXIucGFyc2VGbG9hdCh0cmFuc2l0aW9uRGVsYXkpOyAvLyBSZXR1cm4gMCBpZiBlbGVtZW50IG9yIHRyYW5zaXRpb24gZHVyYXRpb24gaXMgbm90IGZvdW5kXG5cbiAgICBpZiAoIWZsb2F0VHJhbnNpdGlvbkR1cmF0aW9uICYmICFmbG9hdFRyYW5zaXRpb25EZWxheSkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfSAvLyBJZiBtdWx0aXBsZSBkdXJhdGlvbnMgYXJlIGRlZmluZWQsIHRha2UgdGhlIGZpcnN0XG5cblxuICAgIHRyYW5zaXRpb25EdXJhdGlvbiA9IHRyYW5zaXRpb25EdXJhdGlvbi5zcGxpdCgnLCcpWzBdO1xuICAgIHRyYW5zaXRpb25EZWxheSA9IHRyYW5zaXRpb25EZWxheS5zcGxpdCgnLCcpWzBdO1xuICAgIHJldHVybiAoTnVtYmVyLnBhcnNlRmxvYXQodHJhbnNpdGlvbkR1cmF0aW9uKSArIE51bWJlci5wYXJzZUZsb2F0KHRyYW5zaXRpb25EZWxheSkpICogTUlMTElTRUNPTkRTX01VTFRJUExJRVI7XG4gIH07XG5cbiAgY29uc3QgdHJpZ2dlclRyYW5zaXRpb25FbmQgPSBlbGVtZW50ID0+IHtcbiAgICBlbGVtZW50LmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KFRSQU5TSVRJT05fRU5EKSk7XG4gIH07XG5cbiAgY29uc3QgaXNFbGVtZW50JDEgPSBvYmogPT4ge1xuICAgIGlmICghb2JqIHx8IHR5cGVvZiBvYmogIT09ICdvYmplY3QnKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBvYmouanF1ZXJ5ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgb2JqID0gb2JqWzBdO1xuICAgIH1cblxuICAgIHJldHVybiB0eXBlb2Ygb2JqLm5vZGVUeXBlICE9PSAndW5kZWZpbmVkJztcbiAgfTtcblxuICBjb25zdCBnZXRFbGVtZW50ID0gb2JqID0+IHtcbiAgICBpZiAoaXNFbGVtZW50JDEob2JqKSkge1xuICAgICAgLy8gaXQncyBhIGpRdWVyeSBvYmplY3Qgb3IgYSBub2RlIGVsZW1lbnRcbiAgICAgIHJldHVybiBvYmouanF1ZXJ5ID8gb2JqWzBdIDogb2JqO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2Ygb2JqID09PSAnc3RyaW5nJyAmJiBvYmoubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3Iob2JqKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfTtcblxuICBjb25zdCB0eXBlQ2hlY2tDb25maWcgPSAoY29tcG9uZW50TmFtZSwgY29uZmlnLCBjb25maWdUeXBlcykgPT4ge1xuICAgIE9iamVjdC5rZXlzKGNvbmZpZ1R5cGVzKS5mb3JFYWNoKHByb3BlcnR5ID0+IHtcbiAgICAgIGNvbnN0IGV4cGVjdGVkVHlwZXMgPSBjb25maWdUeXBlc1twcm9wZXJ0eV07XG4gICAgICBjb25zdCB2YWx1ZSA9IGNvbmZpZ1twcm9wZXJ0eV07XG4gICAgICBjb25zdCB2YWx1ZVR5cGUgPSB2YWx1ZSAmJiBpc0VsZW1lbnQkMSh2YWx1ZSkgPyAnZWxlbWVudCcgOiB0b1R5cGUodmFsdWUpO1xuXG4gICAgICBpZiAoIW5ldyBSZWdFeHAoZXhwZWN0ZWRUeXBlcykudGVzdCh2YWx1ZVR5cGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYCR7Y29tcG9uZW50TmFtZS50b1VwcGVyQ2FzZSgpfTogT3B0aW9uIFwiJHtwcm9wZXJ0eX1cIiBwcm92aWRlZCB0eXBlIFwiJHt2YWx1ZVR5cGV9XCIgYnV0IGV4cGVjdGVkIHR5cGUgXCIke2V4cGVjdGVkVHlwZXN9XCIuYCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgY29uc3QgaXNWaXNpYmxlID0gZWxlbWVudCA9PiB7XG4gICAgaWYgKCFpc0VsZW1lbnQkMShlbGVtZW50KSB8fCBlbGVtZW50LmdldENsaWVudFJlY3RzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIGdldENvbXB1dGVkU3R5bGUoZWxlbWVudCkuZ2V0UHJvcGVydHlWYWx1ZSgndmlzaWJpbGl0eScpID09PSAndmlzaWJsZSc7XG4gIH07XG5cbiAgY29uc3QgaXNEaXNhYmxlZCA9IGVsZW1lbnQgPT4ge1xuICAgIGlmICghZWxlbWVudCB8fCBlbGVtZW50Lm5vZGVUeXBlICE9PSBOb2RlLkVMRU1FTlRfTk9ERSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgaWYgKGVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKCdkaXNhYmxlZCcpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGVsZW1lbnQuZGlzYWJsZWQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gZWxlbWVudC5kaXNhYmxlZDtcbiAgICB9XG5cbiAgICByZXR1cm4gZWxlbWVudC5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJykgJiYgZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2Rpc2FibGVkJykgIT09ICdmYWxzZSc7XG4gIH07XG5cbiAgY29uc3QgZmluZFNoYWRvd1Jvb3QgPSBlbGVtZW50ID0+IHtcbiAgICBpZiAoIWRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5hdHRhY2hTaGFkb3cpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0gLy8gQ2FuIGZpbmQgdGhlIHNoYWRvdyByb290IG90aGVyd2lzZSBpdCdsbCByZXR1cm4gdGhlIGRvY3VtZW50XG5cblxuICAgIGlmICh0eXBlb2YgZWxlbWVudC5nZXRSb290Tm9kZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY29uc3Qgcm9vdCA9IGVsZW1lbnQuZ2V0Um9vdE5vZGUoKTtcbiAgICAgIHJldHVybiByb290IGluc3RhbmNlb2YgU2hhZG93Um9vdCA/IHJvb3QgOiBudWxsO1xuICAgIH1cblxuICAgIGlmIChlbGVtZW50IGluc3RhbmNlb2YgU2hhZG93Um9vdCkge1xuICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgfSAvLyB3aGVuIHdlIGRvbid0IGZpbmQgYSBzaGFkb3cgcm9vdFxuXG5cbiAgICBpZiAoIWVsZW1lbnQucGFyZW50Tm9kZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZpbmRTaGFkb3dSb290KGVsZW1lbnQucGFyZW50Tm9kZSk7XG4gIH07XG5cbiAgY29uc3Qgbm9vcCA9ICgpID0+IHt9O1xuICAvKipcbiAgICogVHJpY2sgdG8gcmVzdGFydCBhbiBlbGVtZW50J3MgYW5pbWF0aW9uXG4gICAqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAgICogQHJldHVybiB2b2lkXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly93d3cuY2hhcmlzdGhlby5pby9ibG9nLzIwMjEvMDIvcmVzdGFydC1hLWNzcy1hbmltYXRpb24td2l0aC1qYXZhc2NyaXB0LyNyZXN0YXJ0aW5nLWEtY3NzLWFuaW1hdGlvblxuICAgKi9cblxuXG4gIGNvbnN0IHJlZmxvdyA9IGVsZW1lbnQgPT4ge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtZXhwcmVzc2lvbnNcbiAgICBlbGVtZW50Lm9mZnNldEhlaWdodDtcbiAgfTtcblxuICBjb25zdCBnZXRqUXVlcnkgPSAoKSA9PiB7XG4gICAgY29uc3Qge1xuICAgICAgalF1ZXJ5XG4gICAgfSA9IHdpbmRvdztcblxuICAgIGlmIChqUXVlcnkgJiYgIWRvY3VtZW50LmJvZHkuaGFzQXR0cmlidXRlKCdkYXRhLWJzLW5vLWpxdWVyeScpKSB7XG4gICAgICByZXR1cm4galF1ZXJ5O1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9O1xuXG4gIGNvbnN0IERPTUNvbnRlbnRMb2FkZWRDYWxsYmFja3MgPSBbXTtcblxuICBjb25zdCBvbkRPTUNvbnRlbnRMb2FkZWQgPSBjYWxsYmFjayA9PiB7XG4gICAgaWYgKGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdsb2FkaW5nJykge1xuICAgICAgLy8gYWRkIGxpc3RlbmVyIG9uIHRoZSBmaXJzdCBjYWxsIHdoZW4gdGhlIGRvY3VtZW50IGlzIGluIGxvYWRpbmcgc3RhdGVcbiAgICAgIGlmICghRE9NQ29udGVudExvYWRlZENhbGxiYWNrcy5sZW5ndGgpIHtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsICgpID0+IHtcbiAgICAgICAgICBET01Db250ZW50TG9hZGVkQ2FsbGJhY2tzLmZvckVhY2goY2FsbGJhY2sgPT4gY2FsbGJhY2soKSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBET01Db250ZW50TG9hZGVkQ2FsbGJhY2tzLnB1c2goY2FsbGJhY2spO1xuICAgIH0gZWxzZSB7XG4gICAgICBjYWxsYmFjaygpO1xuICAgIH1cbiAgfTtcblxuICBjb25zdCBpc1JUTCA9ICgpID0+IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5kaXIgPT09ICdydGwnO1xuXG4gIGNvbnN0IGRlZmluZUpRdWVyeVBsdWdpbiA9IHBsdWdpbiA9PiB7XG4gICAgb25ET01Db250ZW50TG9hZGVkKCgpID0+IHtcbiAgICAgIGNvbnN0ICQgPSBnZXRqUXVlcnkoKTtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuXG4gICAgICBpZiAoJCkge1xuICAgICAgICBjb25zdCBuYW1lID0gcGx1Z2luLk5BTUU7XG4gICAgICAgIGNvbnN0IEpRVUVSWV9OT19DT05GTElDVCA9ICQuZm5bbmFtZV07XG4gICAgICAgICQuZm5bbmFtZV0gPSBwbHVnaW4ualF1ZXJ5SW50ZXJmYWNlO1xuICAgICAgICAkLmZuW25hbWVdLkNvbnN0cnVjdG9yID0gcGx1Z2luO1xuXG4gICAgICAgICQuZm5bbmFtZV0ubm9Db25mbGljdCA9ICgpID0+IHtcbiAgICAgICAgICAkLmZuW25hbWVdID0gSlFVRVJZX05PX0NPTkZMSUNUO1xuICAgICAgICAgIHJldHVybiBwbHVnaW4ualF1ZXJ5SW50ZXJmYWNlO1xuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIGNvbnN0IGV4ZWN1dGUgPSBjYWxsYmFjayA9PiB7XG4gICAgaWYgKHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY2FsbGJhY2soKTtcbiAgICB9XG4gIH07XG5cbiAgY29uc3QgZXhlY3V0ZUFmdGVyVHJhbnNpdGlvbiA9IChjYWxsYmFjaywgdHJhbnNpdGlvbkVsZW1lbnQsIHdhaXRGb3JUcmFuc2l0aW9uID0gdHJ1ZSkgPT4ge1xuICAgIGlmICghd2FpdEZvclRyYW5zaXRpb24pIHtcbiAgICAgIGV4ZWN1dGUoY2FsbGJhY2spO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGR1cmF0aW9uUGFkZGluZyA9IDU7XG4gICAgY29uc3QgZW11bGF0ZWREdXJhdGlvbiA9IGdldFRyYW5zaXRpb25EdXJhdGlvbkZyb21FbGVtZW50KHRyYW5zaXRpb25FbGVtZW50KSArIGR1cmF0aW9uUGFkZGluZztcbiAgICBsZXQgY2FsbGVkID0gZmFsc2U7XG5cbiAgICBjb25zdCBoYW5kbGVyID0gKHtcbiAgICAgIHRhcmdldFxuICAgIH0pID0+IHtcbiAgICAgIGlmICh0YXJnZXQgIT09IHRyYW5zaXRpb25FbGVtZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY2FsbGVkID0gdHJ1ZTtcbiAgICAgIHRyYW5zaXRpb25FbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoVFJBTlNJVElPTl9FTkQsIGhhbmRsZXIpO1xuICAgICAgZXhlY3V0ZShjYWxsYmFjayk7XG4gICAgfTtcblxuICAgIHRyYW5zaXRpb25FbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoVFJBTlNJVElPTl9FTkQsIGhhbmRsZXIpO1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgaWYgKCFjYWxsZWQpIHtcbiAgICAgICAgdHJpZ2dlclRyYW5zaXRpb25FbmQodHJhbnNpdGlvbkVsZW1lbnQpO1xuICAgICAgfVxuICAgIH0sIGVtdWxhdGVkRHVyYXRpb24pO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIHRoZSBwcmV2aW91cy9uZXh0IGVsZW1lbnQgb2YgYSBsaXN0LlxuICAgKlxuICAgKiBAcGFyYW0ge2FycmF5fSBsaXN0ICAgIFRoZSBsaXN0IG9mIGVsZW1lbnRzXG4gICAqIEBwYXJhbSBhY3RpdmVFbGVtZW50ICAgVGhlIGFjdGl2ZSBlbGVtZW50XG4gICAqIEBwYXJhbSBzaG91bGRHZXROZXh0ICAgQ2hvb3NlIHRvIGdldCBuZXh0IG9yIHByZXZpb3VzIGVsZW1lbnRcbiAgICogQHBhcmFtIGlzQ3ljbGVBbGxvd2VkXG4gICAqIEByZXR1cm4ge0VsZW1lbnR8ZWxlbX0gVGhlIHByb3BlciBlbGVtZW50XG4gICAqL1xuXG5cbiAgY29uc3QgZ2V0TmV4dEFjdGl2ZUVsZW1lbnQgPSAobGlzdCwgYWN0aXZlRWxlbWVudCwgc2hvdWxkR2V0TmV4dCwgaXNDeWNsZUFsbG93ZWQpID0+IHtcbiAgICBsZXQgaW5kZXggPSBsaXN0LmluZGV4T2YoYWN0aXZlRWxlbWVudCk7IC8vIGlmIHRoZSBlbGVtZW50IGRvZXMgbm90IGV4aXN0IGluIHRoZSBsaXN0IHJldHVybiBhbiBlbGVtZW50IGRlcGVuZGluZyBvbiB0aGUgZGlyZWN0aW9uIGFuZCBpZiBjeWNsZSBpcyBhbGxvd2VkXG5cbiAgICBpZiAoaW5kZXggPT09IC0xKSB7XG4gICAgICByZXR1cm4gbGlzdFshc2hvdWxkR2V0TmV4dCAmJiBpc0N5Y2xlQWxsb3dlZCA/IGxpc3QubGVuZ3RoIC0gMSA6IDBdO1xuICAgIH1cblxuICAgIGNvbnN0IGxpc3RMZW5ndGggPSBsaXN0Lmxlbmd0aDtcbiAgICBpbmRleCArPSBzaG91bGRHZXROZXh0ID8gMSA6IC0xO1xuXG4gICAgaWYgKGlzQ3ljbGVBbGxvd2VkKSB7XG4gICAgICBpbmRleCA9IChpbmRleCArIGxpc3RMZW5ndGgpICUgbGlzdExlbmd0aDtcbiAgICB9XG5cbiAgICByZXR1cm4gbGlzdFtNYXRoLm1heCgwLCBNYXRoLm1pbihpbmRleCwgbGlzdExlbmd0aCAtIDEpKV07XG4gIH07XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjUuMS4zKTogZG9tL2V2ZW50LWhhbmRsZXIuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYWluL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIENvbnN0YW50c1xuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgY29uc3QgbmFtZXNwYWNlUmVnZXggPSAvW14uXSooPz1cXC4uKilcXC58LiovO1xuICBjb25zdCBzdHJpcE5hbWVSZWdleCA9IC9cXC4uKi87XG4gIGNvbnN0IHN0cmlwVWlkUmVnZXggPSAvOjpcXGQrJC87XG4gIGNvbnN0IGV2ZW50UmVnaXN0cnkgPSB7fTsgLy8gRXZlbnRzIHN0b3JhZ2VcblxuICBsZXQgdWlkRXZlbnQgPSAxO1xuICBjb25zdCBjdXN0b21FdmVudHMgPSB7XG4gICAgbW91c2VlbnRlcjogJ21vdXNlb3ZlcicsXG4gICAgbW91c2VsZWF2ZTogJ21vdXNlb3V0J1xuICB9O1xuICBjb25zdCBjdXN0b21FdmVudHNSZWdleCA9IC9eKG1vdXNlZW50ZXJ8bW91c2VsZWF2ZSkvaTtcbiAgY29uc3QgbmF0aXZlRXZlbnRzID0gbmV3IFNldChbJ2NsaWNrJywgJ2RibGNsaWNrJywgJ21vdXNldXAnLCAnbW91c2Vkb3duJywgJ2NvbnRleHRtZW51JywgJ21vdXNld2hlZWwnLCAnRE9NTW91c2VTY3JvbGwnLCAnbW91c2VvdmVyJywgJ21vdXNlb3V0JywgJ21vdXNlbW92ZScsICdzZWxlY3RzdGFydCcsICdzZWxlY3RlbmQnLCAna2V5ZG93bicsICdrZXlwcmVzcycsICdrZXl1cCcsICdvcmllbnRhdGlvbmNoYW5nZScsICd0b3VjaHN0YXJ0JywgJ3RvdWNobW92ZScsICd0b3VjaGVuZCcsICd0b3VjaGNhbmNlbCcsICdwb2ludGVyZG93bicsICdwb2ludGVybW92ZScsICdwb2ludGVydXAnLCAncG9pbnRlcmxlYXZlJywgJ3BvaW50ZXJjYW5jZWwnLCAnZ2VzdHVyZXN0YXJ0JywgJ2dlc3R1cmVjaGFuZ2UnLCAnZ2VzdHVyZWVuZCcsICdmb2N1cycsICdibHVyJywgJ2NoYW5nZScsICdyZXNldCcsICdzZWxlY3QnLCAnc3VibWl0JywgJ2ZvY3VzaW4nLCAnZm9jdXNvdXQnLCAnbG9hZCcsICd1bmxvYWQnLCAnYmVmb3JldW5sb2FkJywgJ3Jlc2l6ZScsICdtb3ZlJywgJ0RPTUNvbnRlbnRMb2FkZWQnLCAncmVhZHlzdGF0ZWNoYW5nZScsICdlcnJvcicsICdhYm9ydCcsICdzY3JvbGwnXSk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogUHJpdmF0ZSBtZXRob2RzXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICBmdW5jdGlvbiBnZXRVaWRFdmVudChlbGVtZW50LCB1aWQpIHtcbiAgICByZXR1cm4gdWlkICYmIGAke3VpZH06OiR7dWlkRXZlbnQrK31gIHx8IGVsZW1lbnQudWlkRXZlbnQgfHwgdWlkRXZlbnQrKztcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldEV2ZW50KGVsZW1lbnQpIHtcbiAgICBjb25zdCB1aWQgPSBnZXRVaWRFdmVudChlbGVtZW50KTtcbiAgICBlbGVtZW50LnVpZEV2ZW50ID0gdWlkO1xuICAgIGV2ZW50UmVnaXN0cnlbdWlkXSA9IGV2ZW50UmVnaXN0cnlbdWlkXSB8fCB7fTtcbiAgICByZXR1cm4gZXZlbnRSZWdpc3RyeVt1aWRdO1xuICB9XG5cbiAgZnVuY3Rpb24gYm9vdHN0cmFwSGFuZGxlcihlbGVtZW50LCBmbikge1xuICAgIHJldHVybiBmdW5jdGlvbiBoYW5kbGVyKGV2ZW50KSB7XG4gICAgICBldmVudC5kZWxlZ2F0ZVRhcmdldCA9IGVsZW1lbnQ7XG5cbiAgICAgIGlmIChoYW5kbGVyLm9uZU9mZikge1xuICAgICAgICBFdmVudEhhbmRsZXIub2ZmKGVsZW1lbnQsIGV2ZW50LnR5cGUsIGZuKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGZuLmFwcGx5KGVsZW1lbnQsIFtldmVudF0pO1xuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBib290c3RyYXBEZWxlZ2F0aW9uSGFuZGxlcihlbGVtZW50LCBzZWxlY3RvciwgZm4pIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gaGFuZGxlcihldmVudCkge1xuICAgICAgY29uc3QgZG9tRWxlbWVudHMgPSBlbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpO1xuXG4gICAgICBmb3IgKGxldCB7XG4gICAgICAgIHRhcmdldFxuICAgICAgfSA9IGV2ZW50OyB0YXJnZXQgJiYgdGFyZ2V0ICE9PSB0aGlzOyB0YXJnZXQgPSB0YXJnZXQucGFyZW50Tm9kZSkge1xuICAgICAgICBmb3IgKGxldCBpID0gZG9tRWxlbWVudHMubGVuZ3RoOyBpLS07KSB7XG4gICAgICAgICAgaWYgKGRvbUVsZW1lbnRzW2ldID09PSB0YXJnZXQpIHtcbiAgICAgICAgICAgIGV2ZW50LmRlbGVnYXRlVGFyZ2V0ID0gdGFyZ2V0O1xuXG4gICAgICAgICAgICBpZiAoaGFuZGxlci5vbmVPZmYpIHtcbiAgICAgICAgICAgICAgRXZlbnRIYW5kbGVyLm9mZihlbGVtZW50LCBldmVudC50eXBlLCBzZWxlY3RvciwgZm4pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gZm4uYXBwbHkodGFyZ2V0LCBbZXZlbnRdKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gLy8gVG8gcGxlYXNlIEVTTGludFxuXG5cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBmaW5kSGFuZGxlcihldmVudHMsIGhhbmRsZXIsIGRlbGVnYXRpb25TZWxlY3RvciA9IG51bGwpIHtcbiAgICBjb25zdCB1aWRFdmVudExpc3QgPSBPYmplY3Qua2V5cyhldmVudHMpO1xuXG4gICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IHVpZEV2ZW50TGlzdC5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgY29uc3QgZXZlbnQgPSBldmVudHNbdWlkRXZlbnRMaXN0W2ldXTtcblxuICAgICAgaWYgKGV2ZW50Lm9yaWdpbmFsSGFuZGxlciA9PT0gaGFuZGxlciAmJiBldmVudC5kZWxlZ2F0aW9uU2VsZWN0b3IgPT09IGRlbGVnYXRpb25TZWxlY3Rvcikge1xuICAgICAgICByZXR1cm4gZXZlbnQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBmdW5jdGlvbiBub3JtYWxpemVQYXJhbXMob3JpZ2luYWxUeXBlRXZlbnQsIGhhbmRsZXIsIGRlbGVnYXRpb25Gbikge1xuICAgIGNvbnN0IGRlbGVnYXRpb24gPSB0eXBlb2YgaGFuZGxlciA9PT0gJ3N0cmluZyc7XG4gICAgY29uc3Qgb3JpZ2luYWxIYW5kbGVyID0gZGVsZWdhdGlvbiA/IGRlbGVnYXRpb25GbiA6IGhhbmRsZXI7XG4gICAgbGV0IHR5cGVFdmVudCA9IGdldFR5cGVFdmVudChvcmlnaW5hbFR5cGVFdmVudCk7XG4gICAgY29uc3QgaXNOYXRpdmUgPSBuYXRpdmVFdmVudHMuaGFzKHR5cGVFdmVudCk7XG5cbiAgICBpZiAoIWlzTmF0aXZlKSB7XG4gICAgICB0eXBlRXZlbnQgPSBvcmlnaW5hbFR5cGVFdmVudDtcbiAgICB9XG5cbiAgICByZXR1cm4gW2RlbGVnYXRpb24sIG9yaWdpbmFsSGFuZGxlciwgdHlwZUV2ZW50XTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGFkZEhhbmRsZXIoZWxlbWVudCwgb3JpZ2luYWxUeXBlRXZlbnQsIGhhbmRsZXIsIGRlbGVnYXRpb25Gbiwgb25lT2ZmKSB7XG4gICAgaWYgKHR5cGVvZiBvcmlnaW5hbFR5cGVFdmVudCAhPT0gJ3N0cmluZycgfHwgIWVsZW1lbnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgIGhhbmRsZXIgPSBkZWxlZ2F0aW9uRm47XG4gICAgICBkZWxlZ2F0aW9uRm4gPSBudWxsO1xuICAgIH0gLy8gaW4gY2FzZSBvZiBtb3VzZWVudGVyIG9yIG1vdXNlbGVhdmUgd3JhcCB0aGUgaGFuZGxlciB3aXRoaW4gYSBmdW5jdGlvbiB0aGF0IGNoZWNrcyBmb3IgaXRzIERPTSBwb3NpdGlvblxuICAgIC8vIHRoaXMgcHJldmVudHMgdGhlIGhhbmRsZXIgZnJvbSBiZWluZyBkaXNwYXRjaGVkIHRoZSBzYW1lIHdheSBhcyBtb3VzZW92ZXIgb3IgbW91c2VvdXQgZG9lc1xuXG5cbiAgICBpZiAoY3VzdG9tRXZlbnRzUmVnZXgudGVzdChvcmlnaW5hbFR5cGVFdmVudCkpIHtcbiAgICAgIGNvbnN0IHdyYXBGbiA9IGZuID0+IHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgIGlmICghZXZlbnQucmVsYXRlZFRhcmdldCB8fCBldmVudC5yZWxhdGVkVGFyZ2V0ICE9PSBldmVudC5kZWxlZ2F0ZVRhcmdldCAmJiAhZXZlbnQuZGVsZWdhdGVUYXJnZXQuY29udGFpbnMoZXZlbnQucmVsYXRlZFRhcmdldCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmbi5jYWxsKHRoaXMsIGV2ZW50KTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICB9O1xuXG4gICAgICBpZiAoZGVsZWdhdGlvbkZuKSB7XG4gICAgICAgIGRlbGVnYXRpb25GbiA9IHdyYXBGbihkZWxlZ2F0aW9uRm4pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaGFuZGxlciA9IHdyYXBGbihoYW5kbGVyKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBbZGVsZWdhdGlvbiwgb3JpZ2luYWxIYW5kbGVyLCB0eXBlRXZlbnRdID0gbm9ybWFsaXplUGFyYW1zKG9yaWdpbmFsVHlwZUV2ZW50LCBoYW5kbGVyLCBkZWxlZ2F0aW9uRm4pO1xuICAgIGNvbnN0IGV2ZW50cyA9IGdldEV2ZW50KGVsZW1lbnQpO1xuICAgIGNvbnN0IGhhbmRsZXJzID0gZXZlbnRzW3R5cGVFdmVudF0gfHwgKGV2ZW50c1t0eXBlRXZlbnRdID0ge30pO1xuICAgIGNvbnN0IHByZXZpb3VzRm4gPSBmaW5kSGFuZGxlcihoYW5kbGVycywgb3JpZ2luYWxIYW5kbGVyLCBkZWxlZ2F0aW9uID8gaGFuZGxlciA6IG51bGwpO1xuXG4gICAgaWYgKHByZXZpb3VzRm4pIHtcbiAgICAgIHByZXZpb3VzRm4ub25lT2ZmID0gcHJldmlvdXNGbi5vbmVPZmYgJiYgb25lT2ZmO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHVpZCA9IGdldFVpZEV2ZW50KG9yaWdpbmFsSGFuZGxlciwgb3JpZ2luYWxUeXBlRXZlbnQucmVwbGFjZShuYW1lc3BhY2VSZWdleCwgJycpKTtcbiAgICBjb25zdCBmbiA9IGRlbGVnYXRpb24gPyBib290c3RyYXBEZWxlZ2F0aW9uSGFuZGxlcihlbGVtZW50LCBoYW5kbGVyLCBkZWxlZ2F0aW9uRm4pIDogYm9vdHN0cmFwSGFuZGxlcihlbGVtZW50LCBoYW5kbGVyKTtcbiAgICBmbi5kZWxlZ2F0aW9uU2VsZWN0b3IgPSBkZWxlZ2F0aW9uID8gaGFuZGxlciA6IG51bGw7XG4gICAgZm4ub3JpZ2luYWxIYW5kbGVyID0gb3JpZ2luYWxIYW5kbGVyO1xuICAgIGZuLm9uZU9mZiA9IG9uZU9mZjtcbiAgICBmbi51aWRFdmVudCA9IHVpZDtcbiAgICBoYW5kbGVyc1t1aWRdID0gZm47XG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHR5cGVFdmVudCwgZm4sIGRlbGVnYXRpb24pO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVtb3ZlSGFuZGxlcihlbGVtZW50LCBldmVudHMsIHR5cGVFdmVudCwgaGFuZGxlciwgZGVsZWdhdGlvblNlbGVjdG9yKSB7XG4gICAgY29uc3QgZm4gPSBmaW5kSGFuZGxlcihldmVudHNbdHlwZUV2ZW50XSwgaGFuZGxlciwgZGVsZWdhdGlvblNlbGVjdG9yKTtcblxuICAgIGlmICghZm4pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIodHlwZUV2ZW50LCBmbiwgQm9vbGVhbihkZWxlZ2F0aW9uU2VsZWN0b3IpKTtcbiAgICBkZWxldGUgZXZlbnRzW3R5cGVFdmVudF1bZm4udWlkRXZlbnRdO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVtb3ZlTmFtZXNwYWNlZEhhbmRsZXJzKGVsZW1lbnQsIGV2ZW50cywgdHlwZUV2ZW50LCBuYW1lc3BhY2UpIHtcbiAgICBjb25zdCBzdG9yZUVsZW1lbnRFdmVudCA9IGV2ZW50c1t0eXBlRXZlbnRdIHx8IHt9O1xuICAgIE9iamVjdC5rZXlzKHN0b3JlRWxlbWVudEV2ZW50KS5mb3JFYWNoKGhhbmRsZXJLZXkgPT4ge1xuICAgICAgaWYgKGhhbmRsZXJLZXkuaW5jbHVkZXMobmFtZXNwYWNlKSkge1xuICAgICAgICBjb25zdCBldmVudCA9IHN0b3JlRWxlbWVudEV2ZW50W2hhbmRsZXJLZXldO1xuICAgICAgICByZW1vdmVIYW5kbGVyKGVsZW1lbnQsIGV2ZW50cywgdHlwZUV2ZW50LCBldmVudC5vcmlnaW5hbEhhbmRsZXIsIGV2ZW50LmRlbGVnYXRpb25TZWxlY3Rvcik7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRUeXBlRXZlbnQoZXZlbnQpIHtcbiAgICAvLyBhbGxvdyB0byBnZXQgdGhlIG5hdGl2ZSBldmVudHMgZnJvbSBuYW1lc3BhY2VkIGV2ZW50cyAoJ2NsaWNrLmJzLmJ1dHRvbicgLS0+ICdjbGljaycpXG4gICAgZXZlbnQgPSBldmVudC5yZXBsYWNlKHN0cmlwTmFtZVJlZ2V4LCAnJyk7XG4gICAgcmV0dXJuIGN1c3RvbUV2ZW50c1tldmVudF0gfHwgZXZlbnQ7XG4gIH1cblxuICBjb25zdCBFdmVudEhhbmRsZXIgPSB7XG4gICAgb24oZWxlbWVudCwgZXZlbnQsIGhhbmRsZXIsIGRlbGVnYXRpb25Gbikge1xuICAgICAgYWRkSGFuZGxlcihlbGVtZW50LCBldmVudCwgaGFuZGxlciwgZGVsZWdhdGlvbkZuLCBmYWxzZSk7XG4gICAgfSxcblxuICAgIG9uZShlbGVtZW50LCBldmVudCwgaGFuZGxlciwgZGVsZWdhdGlvbkZuKSB7XG4gICAgICBhZGRIYW5kbGVyKGVsZW1lbnQsIGV2ZW50LCBoYW5kbGVyLCBkZWxlZ2F0aW9uRm4sIHRydWUpO1xuICAgIH0sXG5cbiAgICBvZmYoZWxlbWVudCwgb3JpZ2luYWxUeXBlRXZlbnQsIGhhbmRsZXIsIGRlbGVnYXRpb25Gbikge1xuICAgICAgaWYgKHR5cGVvZiBvcmlnaW5hbFR5cGVFdmVudCAhPT0gJ3N0cmluZycgfHwgIWVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBbZGVsZWdhdGlvbiwgb3JpZ2luYWxIYW5kbGVyLCB0eXBlRXZlbnRdID0gbm9ybWFsaXplUGFyYW1zKG9yaWdpbmFsVHlwZUV2ZW50LCBoYW5kbGVyLCBkZWxlZ2F0aW9uRm4pO1xuICAgICAgY29uc3QgaW5OYW1lc3BhY2UgPSB0eXBlRXZlbnQgIT09IG9yaWdpbmFsVHlwZUV2ZW50O1xuICAgICAgY29uc3QgZXZlbnRzID0gZ2V0RXZlbnQoZWxlbWVudCk7XG4gICAgICBjb25zdCBpc05hbWVzcGFjZSA9IG9yaWdpbmFsVHlwZUV2ZW50LnN0YXJ0c1dpdGgoJy4nKTtcblxuICAgICAgaWYgKHR5cGVvZiBvcmlnaW5hbEhhbmRsZXIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIC8vIFNpbXBsZXN0IGNhc2U6IGhhbmRsZXIgaXMgcGFzc2VkLCByZW1vdmUgdGhhdCBsaXN0ZW5lciBPTkxZLlxuICAgICAgICBpZiAoIWV2ZW50cyB8fCAhZXZlbnRzW3R5cGVFdmVudF0pIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICByZW1vdmVIYW5kbGVyKGVsZW1lbnQsIGV2ZW50cywgdHlwZUV2ZW50LCBvcmlnaW5hbEhhbmRsZXIsIGRlbGVnYXRpb24gPyBoYW5kbGVyIDogbnVsbCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzTmFtZXNwYWNlKSB7XG4gICAgICAgIE9iamVjdC5rZXlzKGV2ZW50cykuZm9yRWFjaChlbGVtZW50RXZlbnQgPT4ge1xuICAgICAgICAgIHJlbW92ZU5hbWVzcGFjZWRIYW5kbGVycyhlbGVtZW50LCBldmVudHMsIGVsZW1lbnRFdmVudCwgb3JpZ2luYWxUeXBlRXZlbnQuc2xpY2UoMSkpO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3RvcmVFbGVtZW50RXZlbnQgPSBldmVudHNbdHlwZUV2ZW50XSB8fCB7fTtcbiAgICAgIE9iamVjdC5rZXlzKHN0b3JlRWxlbWVudEV2ZW50KS5mb3JFYWNoKGtleUhhbmRsZXJzID0+IHtcbiAgICAgICAgY29uc3QgaGFuZGxlcktleSA9IGtleUhhbmRsZXJzLnJlcGxhY2Uoc3RyaXBVaWRSZWdleCwgJycpO1xuXG4gICAgICAgIGlmICghaW5OYW1lc3BhY2UgfHwgb3JpZ2luYWxUeXBlRXZlbnQuaW5jbHVkZXMoaGFuZGxlcktleSkpIHtcbiAgICAgICAgICBjb25zdCBldmVudCA9IHN0b3JlRWxlbWVudEV2ZW50W2tleUhhbmRsZXJzXTtcbiAgICAgICAgICByZW1vdmVIYW5kbGVyKGVsZW1lbnQsIGV2ZW50cywgdHlwZUV2ZW50LCBldmVudC5vcmlnaW5hbEhhbmRsZXIsIGV2ZW50LmRlbGVnYXRpb25TZWxlY3Rvcik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0sXG5cbiAgICB0cmlnZ2VyKGVsZW1lbnQsIGV2ZW50LCBhcmdzKSB7XG4gICAgICBpZiAodHlwZW9mIGV2ZW50ICE9PSAnc3RyaW5nJyB8fCAhZWxlbWVudCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgJCA9IGdldGpRdWVyeSgpO1xuICAgICAgY29uc3QgdHlwZUV2ZW50ID0gZ2V0VHlwZUV2ZW50KGV2ZW50KTtcbiAgICAgIGNvbnN0IGluTmFtZXNwYWNlID0gZXZlbnQgIT09IHR5cGVFdmVudDtcbiAgICAgIGNvbnN0IGlzTmF0aXZlID0gbmF0aXZlRXZlbnRzLmhhcyh0eXBlRXZlbnQpO1xuICAgICAgbGV0IGpRdWVyeUV2ZW50O1xuICAgICAgbGV0IGJ1YmJsZXMgPSB0cnVlO1xuICAgICAgbGV0IG5hdGl2ZURpc3BhdGNoID0gdHJ1ZTtcbiAgICAgIGxldCBkZWZhdWx0UHJldmVudGVkID0gZmFsc2U7XG4gICAgICBsZXQgZXZ0ID0gbnVsbDtcblxuICAgICAgaWYgKGluTmFtZXNwYWNlICYmICQpIHtcbiAgICAgICAgalF1ZXJ5RXZlbnQgPSAkLkV2ZW50KGV2ZW50LCBhcmdzKTtcbiAgICAgICAgJChlbGVtZW50KS50cmlnZ2VyKGpRdWVyeUV2ZW50KTtcbiAgICAgICAgYnViYmxlcyA9ICFqUXVlcnlFdmVudC5pc1Byb3BhZ2F0aW9uU3RvcHBlZCgpO1xuICAgICAgICBuYXRpdmVEaXNwYXRjaCA9ICFqUXVlcnlFdmVudC5pc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZCgpO1xuICAgICAgICBkZWZhdWx0UHJldmVudGVkID0galF1ZXJ5RXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChpc05hdGl2ZSkge1xuICAgICAgICBldnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnSFRNTEV2ZW50cycpO1xuICAgICAgICBldnQuaW5pdEV2ZW50KHR5cGVFdmVudCwgYnViYmxlcywgdHJ1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBldnQgPSBuZXcgQ3VzdG9tRXZlbnQoZXZlbnQsIHtcbiAgICAgICAgICBidWJibGVzLFxuICAgICAgICAgIGNhbmNlbGFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICB9IC8vIG1lcmdlIGN1c3RvbSBpbmZvcm1hdGlvbiBpbiBvdXIgZXZlbnRcblxuXG4gICAgICBpZiAodHlwZW9mIGFyZ3MgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIE9iamVjdC5rZXlzKGFyZ3MpLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXZ0LCBrZXksIHtcbiAgICAgICAgICAgIGdldCgpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGFyZ3Nba2V5XTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGRlZmF1bHRQcmV2ZW50ZWQpIHtcbiAgICAgICAgZXZ0LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChuYXRpdmVEaXNwYXRjaCkge1xuICAgICAgICBlbGVtZW50LmRpc3BhdGNoRXZlbnQoZXZ0KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGV2dC5kZWZhdWx0UHJldmVudGVkICYmIHR5cGVvZiBqUXVlcnlFdmVudCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgalF1ZXJ5RXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGV2dDtcbiAgICB9XG5cbiAgfTtcblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NS4xLjMpOiBkb20vZGF0YS5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDb25zdGFudHNcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuICBjb25zdCBlbGVtZW50TWFwID0gbmV3IE1hcCgpO1xuICBjb25zdCBEYXRhID0ge1xuICAgIHNldChlbGVtZW50LCBrZXksIGluc3RhbmNlKSB7XG4gICAgICBpZiAoIWVsZW1lbnRNYXAuaGFzKGVsZW1lbnQpKSB7XG4gICAgICAgIGVsZW1lbnRNYXAuc2V0KGVsZW1lbnQsIG5ldyBNYXAoKSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGluc3RhbmNlTWFwID0gZWxlbWVudE1hcC5nZXQoZWxlbWVudCk7IC8vIG1ha2UgaXQgY2xlYXIgd2Ugb25seSB3YW50IG9uZSBpbnN0YW5jZSBwZXIgZWxlbWVudFxuICAgICAgLy8gY2FuIGJlIHJlbW92ZWQgbGF0ZXIgd2hlbiBtdWx0aXBsZSBrZXkvaW5zdGFuY2VzIGFyZSBmaW5lIHRvIGJlIHVzZWRcblxuICAgICAgaWYgKCFpbnN0YW5jZU1hcC5oYXMoa2V5KSAmJiBpbnN0YW5jZU1hcC5zaXplICE9PSAwKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYEJvb3RzdHJhcCBkb2Vzbid0IGFsbG93IG1vcmUgdGhhbiBvbmUgaW5zdGFuY2UgcGVyIGVsZW1lbnQuIEJvdW5kIGluc3RhbmNlOiAke0FycmF5LmZyb20oaW5zdGFuY2VNYXAua2V5cygpKVswXX0uYCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaW5zdGFuY2VNYXAuc2V0KGtleSwgaW5zdGFuY2UpO1xuICAgIH0sXG5cbiAgICBnZXQoZWxlbWVudCwga2V5KSB7XG4gICAgICBpZiAoZWxlbWVudE1hcC5oYXMoZWxlbWVudCkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnRNYXAuZ2V0KGVsZW1lbnQpLmdldChrZXkpIHx8IG51bGw7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0sXG5cbiAgICByZW1vdmUoZWxlbWVudCwga2V5KSB7XG4gICAgICBpZiAoIWVsZW1lbnRNYXAuaGFzKGVsZW1lbnQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgaW5zdGFuY2VNYXAgPSBlbGVtZW50TWFwLmdldChlbGVtZW50KTtcbiAgICAgIGluc3RhbmNlTWFwLmRlbGV0ZShrZXkpOyAvLyBmcmVlIHVwIGVsZW1lbnQgcmVmZXJlbmNlcyBpZiB0aGVyZSBhcmUgbm8gaW5zdGFuY2VzIGxlZnQgZm9yIGFuIGVsZW1lbnRcblxuICAgICAgaWYgKGluc3RhbmNlTWFwLnNpemUgPT09IDApIHtcbiAgICAgICAgZWxlbWVudE1hcC5kZWxldGUoZWxlbWVudCk7XG4gICAgICB9XG4gICAgfVxuXG4gIH07XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjUuMS4zKTogYmFzZS1jb21wb25lbnQuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYWluL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIENvbnN0YW50c1xuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgY29uc3QgVkVSU0lPTiA9ICc1LjEuMyc7XG5cbiAgY2xhc3MgQmFzZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoZWxlbWVudCkge1xuICAgICAgZWxlbWVudCA9IGdldEVsZW1lbnQoZWxlbWVudCk7XG5cbiAgICAgIGlmICghZWxlbWVudCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgRGF0YS5zZXQodGhpcy5fZWxlbWVudCwgdGhpcy5jb25zdHJ1Y3Rvci5EQVRBX0tFWSwgdGhpcyk7XG4gICAgfVxuXG4gICAgZGlzcG9zZSgpIHtcbiAgICAgIERhdGEucmVtb3ZlKHRoaXMuX2VsZW1lbnQsIHRoaXMuY29uc3RydWN0b3IuREFUQV9LRVkpO1xuICAgICAgRXZlbnRIYW5kbGVyLm9mZih0aGlzLl9lbGVtZW50LCB0aGlzLmNvbnN0cnVjdG9yLkVWRU5UX0tFWSk7XG4gICAgICBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzKS5mb3JFYWNoKHByb3BlcnR5TmFtZSA9PiB7XG4gICAgICAgIHRoaXNbcHJvcGVydHlOYW1lXSA9IG51bGw7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBfcXVldWVDYWxsYmFjayhjYWxsYmFjaywgZWxlbWVudCwgaXNBbmltYXRlZCA9IHRydWUpIHtcbiAgICAgIGV4ZWN1dGVBZnRlclRyYW5zaXRpb24oY2FsbGJhY2ssIGVsZW1lbnQsIGlzQW5pbWF0ZWQpO1xuICAgIH1cbiAgICAvKiogU3RhdGljICovXG5cblxuICAgIHN0YXRpYyBnZXRJbnN0YW5jZShlbGVtZW50KSB7XG4gICAgICByZXR1cm4gRGF0YS5nZXQoZ2V0RWxlbWVudChlbGVtZW50KSwgdGhpcy5EQVRBX0tFWSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGdldE9yQ3JlYXRlSW5zdGFuY2UoZWxlbWVudCwgY29uZmlnID0ge30pIHtcbiAgICAgIHJldHVybiB0aGlzLmdldEluc3RhbmNlKGVsZW1lbnQpIHx8IG5ldyB0aGlzKGVsZW1lbnQsIHR5cGVvZiBjb25maWcgPT09ICdvYmplY3QnID8gY29uZmlnIDogbnVsbCk7XG4gICAgfVxuXG4gICAgc3RhdGljIGdldCBWRVJTSU9OKCkge1xuICAgICAgcmV0dXJuIFZFUlNJT047XG4gICAgfVxuXG4gICAgc3RhdGljIGdldCBOQU1FKCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgaGF2ZSB0byBpbXBsZW1lbnQgdGhlIHN0YXRpYyBtZXRob2QgXCJOQU1FXCIsIGZvciBlYWNoIGNvbXBvbmVudCEnKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZ2V0IERBVEFfS0VZKCkge1xuICAgICAgcmV0dXJuIGBicy4ke3RoaXMuTkFNRX1gO1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXQgRVZFTlRfS0VZKCkge1xuICAgICAgcmV0dXJuIGAuJHt0aGlzLkRBVEFfS0VZfWA7XG4gICAgfVxuXG4gIH1cblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NS4xLjMpOiB1dGlsL2NvbXBvbmVudC1mdW5jdGlvbnMuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYWluL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIGNvbnN0IGVuYWJsZURpc21pc3NUcmlnZ2VyID0gKGNvbXBvbmVudCwgbWV0aG9kID0gJ2hpZGUnKSA9PiB7XG4gICAgY29uc3QgY2xpY2tFdmVudCA9IGBjbGljay5kaXNtaXNzJHtjb21wb25lbnQuRVZFTlRfS0VZfWA7XG4gICAgY29uc3QgbmFtZSA9IGNvbXBvbmVudC5OQU1FO1xuICAgIEV2ZW50SGFuZGxlci5vbihkb2N1bWVudCwgY2xpY2tFdmVudCwgYFtkYXRhLWJzLWRpc21pc3M9XCIke25hbWV9XCJdYCwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICBpZiAoWydBJywgJ0FSRUEnXS5pbmNsdWRlcyh0aGlzLnRhZ05hbWUpKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChpc0Rpc2FibGVkKHRoaXMpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdGFyZ2V0ID0gZ2V0RWxlbWVudEZyb21TZWxlY3Rvcih0aGlzKSB8fCB0aGlzLmNsb3Nlc3QoYC4ke25hbWV9YCk7XG4gICAgICBjb25zdCBpbnN0YW5jZSA9IGNvbXBvbmVudC5nZXRPckNyZWF0ZUluc3RhbmNlKHRhcmdldCk7IC8vIE1ldGhvZCBhcmd1bWVudCBpcyBsZWZ0LCBmb3IgQWxlcnQgYW5kIG9ubHksIGFzIGl0IGRvZXNuJ3QgaW1wbGVtZW50IHRoZSAnaGlkZScgbWV0aG9kXG5cbiAgICAgIGluc3RhbmNlW21ldGhvZF0oKTtcbiAgICB9KTtcbiAgfTtcblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NS4xLjMpOiBhbGVydC5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQ29uc3RhbnRzXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICBjb25zdCBOQU1FJGQgPSAnYWxlcnQnO1xuICBjb25zdCBEQVRBX0tFWSRjID0gJ2JzLmFsZXJ0JztcbiAgY29uc3QgRVZFTlRfS0VZJGMgPSBgLiR7REFUQV9LRVkkY31gO1xuICBjb25zdCBFVkVOVF9DTE9TRSA9IGBjbG9zZSR7RVZFTlRfS0VZJGN9YDtcbiAgY29uc3QgRVZFTlRfQ0xPU0VEID0gYGNsb3NlZCR7RVZFTlRfS0VZJGN9YDtcbiAgY29uc3QgQ0xBU1NfTkFNRV9GQURFJDUgPSAnZmFkZSc7XG4gIGNvbnN0IENMQVNTX05BTUVfU0hPVyQ4ID0gJ3Nob3cnO1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIENsYXNzIERlZmluaXRpb25cbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIGNsYXNzIEFsZXJ0IGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgLy8gR2V0dGVyc1xuICAgIHN0YXRpYyBnZXQgTkFNRSgpIHtcbiAgICAgIHJldHVybiBOQU1FJGQ7XG4gICAgfSAvLyBQdWJsaWNcblxuXG4gICAgY2xvc2UoKSB7XG4gICAgICBjb25zdCBjbG9zZUV2ZW50ID0gRXZlbnRIYW5kbGVyLnRyaWdnZXIodGhpcy5fZWxlbWVudCwgRVZFTlRfQ0xPU0UpO1xuXG4gICAgICBpZiAoY2xvc2VFdmVudC5kZWZhdWx0UHJldmVudGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKENMQVNTX05BTUVfU0hPVyQ4KTtcblxuICAgICAgY29uc3QgaXNBbmltYXRlZCA9IHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKENMQVNTX05BTUVfRkFERSQ1KTtcblxuICAgICAgdGhpcy5fcXVldWVDYWxsYmFjaygoKSA9PiB0aGlzLl9kZXN0cm95RWxlbWVudCgpLCB0aGlzLl9lbGVtZW50LCBpc0FuaW1hdGVkKTtcbiAgICB9IC8vIFByaXZhdGVcblxuXG4gICAgX2Rlc3Ryb3lFbGVtZW50KCkge1xuICAgICAgdGhpcy5fZWxlbWVudC5yZW1vdmUoKTtcblxuICAgICAgRXZlbnRIYW5kbGVyLnRyaWdnZXIodGhpcy5fZWxlbWVudCwgRVZFTlRfQ0xPU0VEKTtcbiAgICAgIHRoaXMuZGlzcG9zZSgpO1xuICAgIH0gLy8gU3RhdGljXG5cblxuICAgIHN0YXRpYyBqUXVlcnlJbnRlcmZhY2UoY29uZmlnKSB7XG4gICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IEFsZXJ0LmdldE9yQ3JlYXRlSW5zdGFuY2UodGhpcyk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBjb25maWcgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRhdGFbY29uZmlnXSA9PT0gdW5kZWZpbmVkIHx8IGNvbmZpZy5zdGFydHNXaXRoKCdfJykgfHwgY29uZmlnID09PSAnY29uc3RydWN0b3InKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgTm8gbWV0aG9kIG5hbWVkIFwiJHtjb25maWd9XCJgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRhdGFbY29uZmlnXSh0aGlzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICB9XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogRGF0YSBBcGkgaW1wbGVtZW50YXRpb25cbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG5cbiAgZW5hYmxlRGlzbWlzc1RyaWdnZXIoQWxlcnQsICdjbG9zZScpO1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIGpRdWVyeVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogYWRkIC5BbGVydCB0byBqUXVlcnkgb25seSBpZiBqUXVlcnkgaXMgcHJlc2VudFxuICAgKi9cblxuICBkZWZpbmVKUXVlcnlQbHVnaW4oQWxlcnQpO1xuXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBCb290c3RyYXAgKHY1LjEuMyk6IGJ1dHRvbi5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQ29uc3RhbnRzXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICBjb25zdCBOQU1FJGMgPSAnYnV0dG9uJztcbiAgY29uc3QgREFUQV9LRVkkYiA9ICdicy5idXR0b24nO1xuICBjb25zdCBFVkVOVF9LRVkkYiA9IGAuJHtEQVRBX0tFWSRifWA7XG4gIGNvbnN0IERBVEFfQVBJX0tFWSQ3ID0gJy5kYXRhLWFwaSc7XG4gIGNvbnN0IENMQVNTX05BTUVfQUNUSVZFJDMgPSAnYWN0aXZlJztcbiAgY29uc3QgU0VMRUNUT1JfREFUQV9UT0dHTEUkNSA9ICdbZGF0YS1icy10b2dnbGU9XCJidXR0b25cIl0nO1xuICBjb25zdCBFVkVOVF9DTElDS19EQVRBX0FQSSQ2ID0gYGNsaWNrJHtFVkVOVF9LRVkkYn0ke0RBVEFfQVBJX0tFWSQ3fWA7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQ2xhc3MgRGVmaW5pdGlvblxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgY2xhc3MgQnV0dG9uIGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgLy8gR2V0dGVyc1xuICAgIHN0YXRpYyBnZXQgTkFNRSgpIHtcbiAgICAgIHJldHVybiBOQU1FJGM7XG4gICAgfSAvLyBQdWJsaWNcblxuXG4gICAgdG9nZ2xlKCkge1xuICAgICAgLy8gVG9nZ2xlIGNsYXNzIGFuZCBzeW5jIHRoZSBgYXJpYS1wcmVzc2VkYCBhdHRyaWJ1dGUgd2l0aCB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBgLnRvZ2dsZSgpYCBtZXRob2RcbiAgICAgIHRoaXMuX2VsZW1lbnQuc2V0QXR0cmlidXRlKCdhcmlhLXByZXNzZWQnLCB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC50b2dnbGUoQ0xBU1NfTkFNRV9BQ1RJVkUkMykpO1xuICAgIH0gLy8gU3RhdGljXG5cblxuICAgIHN0YXRpYyBqUXVlcnlJbnRlcmZhY2UoY29uZmlnKSB7XG4gICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IEJ1dHRvbi5nZXRPckNyZWF0ZUluc3RhbmNlKHRoaXMpO1xuXG4gICAgICAgIGlmIChjb25maWcgPT09ICd0b2dnbGUnKSB7XG4gICAgICAgICAgZGF0YVtjb25maWddKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICB9XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogRGF0YSBBcGkgaW1wbGVtZW50YXRpb25cbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG5cbiAgRXZlbnRIYW5kbGVyLm9uKGRvY3VtZW50LCBFVkVOVF9DTElDS19EQVRBX0FQSSQ2LCBTRUxFQ1RPUl9EQVRBX1RPR0dMRSQ1LCBldmVudCA9PiB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBjb25zdCBidXR0b24gPSBldmVudC50YXJnZXQuY2xvc2VzdChTRUxFQ1RPUl9EQVRBX1RPR0dMRSQ1KTtcbiAgICBjb25zdCBkYXRhID0gQnV0dG9uLmdldE9yQ3JlYXRlSW5zdGFuY2UoYnV0dG9uKTtcbiAgICBkYXRhLnRvZ2dsZSgpO1xuICB9KTtcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBqUXVlcnlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIGFkZCAuQnV0dG9uIHRvIGpRdWVyeSBvbmx5IGlmIGpRdWVyeSBpcyBwcmVzZW50XG4gICAqL1xuXG4gIGRlZmluZUpRdWVyeVBsdWdpbihCdXR0b24pO1xuXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBCb290c3RyYXAgKHY1LjEuMyk6IGRvbS9tYW5pcHVsYXRvci5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZURhdGEodmFsKSB7XG4gICAgaWYgKHZhbCA9PT0gJ3RydWUnKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAodmFsID09PSAnZmFsc2UnKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKHZhbCA9PT0gTnVtYmVyKHZhbCkudG9TdHJpbmcoKSkge1xuICAgICAgcmV0dXJuIE51bWJlcih2YWwpO1xuICAgIH1cblxuICAgIGlmICh2YWwgPT09ICcnIHx8IHZhbCA9PT0gJ251bGwnKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsO1xuICB9XG5cbiAgZnVuY3Rpb24gbm9ybWFsaXplRGF0YUtleShrZXkpIHtcbiAgICByZXR1cm4ga2V5LnJlcGxhY2UoL1tBLVpdL2csIGNociA9PiBgLSR7Y2hyLnRvTG93ZXJDYXNlKCl9YCk7XG4gIH1cblxuICBjb25zdCBNYW5pcHVsYXRvciA9IHtcbiAgICBzZXREYXRhQXR0cmlidXRlKGVsZW1lbnQsIGtleSwgdmFsdWUpIHtcbiAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKGBkYXRhLWJzLSR7bm9ybWFsaXplRGF0YUtleShrZXkpfWAsIHZhbHVlKTtcbiAgICB9LFxuXG4gICAgcmVtb3ZlRGF0YUF0dHJpYnV0ZShlbGVtZW50LCBrZXkpIHtcbiAgICAgIGVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKGBkYXRhLWJzLSR7bm9ybWFsaXplRGF0YUtleShrZXkpfWApO1xuICAgIH0sXG5cbiAgICBnZXREYXRhQXR0cmlidXRlcyhlbGVtZW50KSB7XG4gICAgICBpZiAoIWVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBhdHRyaWJ1dGVzID0ge307XG4gICAgICBPYmplY3Qua2V5cyhlbGVtZW50LmRhdGFzZXQpLmZpbHRlcihrZXkgPT4ga2V5LnN0YXJ0c1dpdGgoJ2JzJykpLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgbGV0IHB1cmVLZXkgPSBrZXkucmVwbGFjZSgvXmJzLywgJycpO1xuICAgICAgICBwdXJlS2V5ID0gcHVyZUtleS5jaGFyQXQoMCkudG9Mb3dlckNhc2UoKSArIHB1cmVLZXkuc2xpY2UoMSwgcHVyZUtleS5sZW5ndGgpO1xuICAgICAgICBhdHRyaWJ1dGVzW3B1cmVLZXldID0gbm9ybWFsaXplRGF0YShlbGVtZW50LmRhdGFzZXRba2V5XSk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBhdHRyaWJ1dGVzO1xuICAgIH0sXG5cbiAgICBnZXREYXRhQXR0cmlidXRlKGVsZW1lbnQsIGtleSkge1xuICAgICAgcmV0dXJuIG5vcm1hbGl6ZURhdGEoZWxlbWVudC5nZXRBdHRyaWJ1dGUoYGRhdGEtYnMtJHtub3JtYWxpemVEYXRhS2V5KGtleSl9YCkpO1xuICAgIH0sXG5cbiAgICBvZmZzZXQoZWxlbWVudCkge1xuICAgICAgY29uc3QgcmVjdCA9IGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0b3A6IHJlY3QudG9wICsgd2luZG93LnBhZ2VZT2Zmc2V0LFxuICAgICAgICBsZWZ0OiByZWN0LmxlZnQgKyB3aW5kb3cucGFnZVhPZmZzZXRcbiAgICAgIH07XG4gICAgfSxcblxuICAgIHBvc2l0aW9uKGVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHRvcDogZWxlbWVudC5vZmZzZXRUb3AsXG4gICAgICAgIGxlZnQ6IGVsZW1lbnQub2Zmc2V0TGVmdFxuICAgICAgfTtcbiAgICB9XG5cbiAgfTtcblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NS4xLjMpOiBkb20vc2VsZWN0b3ItZW5naW5lLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cbiAgY29uc3QgTk9ERV9URVhUID0gMztcbiAgY29uc3QgU2VsZWN0b3JFbmdpbmUgPSB7XG4gICAgZmluZChzZWxlY3RvciwgZWxlbWVudCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkge1xuICAgICAgcmV0dXJuIFtdLmNvbmNhdCguLi5FbGVtZW50LnByb3RvdHlwZS5xdWVyeVNlbGVjdG9yQWxsLmNhbGwoZWxlbWVudCwgc2VsZWN0b3IpKTtcbiAgICB9LFxuXG4gICAgZmluZE9uZShzZWxlY3RvciwgZWxlbWVudCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkge1xuICAgICAgcmV0dXJuIEVsZW1lbnQucHJvdG90eXBlLnF1ZXJ5U2VsZWN0b3IuY2FsbChlbGVtZW50LCBzZWxlY3Rvcik7XG4gICAgfSxcblxuICAgIGNoaWxkcmVuKGVsZW1lbnQsIHNlbGVjdG9yKSB7XG4gICAgICByZXR1cm4gW10uY29uY2F0KC4uLmVsZW1lbnQuY2hpbGRyZW4pLmZpbHRlcihjaGlsZCA9PiBjaGlsZC5tYXRjaGVzKHNlbGVjdG9yKSk7XG4gICAgfSxcblxuICAgIHBhcmVudHMoZWxlbWVudCwgc2VsZWN0b3IpIHtcbiAgICAgIGNvbnN0IHBhcmVudHMgPSBbXTtcbiAgICAgIGxldCBhbmNlc3RvciA9IGVsZW1lbnQucGFyZW50Tm9kZTtcblxuICAgICAgd2hpbGUgKGFuY2VzdG9yICYmIGFuY2VzdG9yLm5vZGVUeXBlID09PSBOb2RlLkVMRU1FTlRfTk9ERSAmJiBhbmNlc3Rvci5ub2RlVHlwZSAhPT0gTk9ERV9URVhUKSB7XG4gICAgICAgIGlmIChhbmNlc3Rvci5tYXRjaGVzKHNlbGVjdG9yKSkge1xuICAgICAgICAgIHBhcmVudHMucHVzaChhbmNlc3Rvcik7XG4gICAgICAgIH1cblxuICAgICAgICBhbmNlc3RvciA9IGFuY2VzdG9yLnBhcmVudE5vZGU7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBwYXJlbnRzO1xuICAgIH0sXG5cbiAgICBwcmV2KGVsZW1lbnQsIHNlbGVjdG9yKSB7XG4gICAgICBsZXQgcHJldmlvdXMgPSBlbGVtZW50LnByZXZpb3VzRWxlbWVudFNpYmxpbmc7XG5cbiAgICAgIHdoaWxlIChwcmV2aW91cykge1xuICAgICAgICBpZiAocHJldmlvdXMubWF0Y2hlcyhzZWxlY3RvcikpIHtcbiAgICAgICAgICByZXR1cm4gW3ByZXZpb3VzXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHByZXZpb3VzID0gcHJldmlvdXMucHJldmlvdXNFbGVtZW50U2libGluZztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIFtdO1xuICAgIH0sXG5cbiAgICBuZXh0KGVsZW1lbnQsIHNlbGVjdG9yKSB7XG4gICAgICBsZXQgbmV4dCA9IGVsZW1lbnQubmV4dEVsZW1lbnRTaWJsaW5nO1xuXG4gICAgICB3aGlsZSAobmV4dCkge1xuICAgICAgICBpZiAobmV4dC5tYXRjaGVzKHNlbGVjdG9yKSkge1xuICAgICAgICAgIHJldHVybiBbbmV4dF07XG4gICAgICAgIH1cblxuICAgICAgICBuZXh0ID0gbmV4dC5uZXh0RWxlbWVudFNpYmxpbmc7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBbXTtcbiAgICB9LFxuXG4gICAgZm9jdXNhYmxlQ2hpbGRyZW4oZWxlbWVudCkge1xuICAgICAgY29uc3QgZm9jdXNhYmxlcyA9IFsnYScsICdidXR0b24nLCAnaW5wdXQnLCAndGV4dGFyZWEnLCAnc2VsZWN0JywgJ2RldGFpbHMnLCAnW3RhYmluZGV4XScsICdbY29udGVudGVkaXRhYmxlPVwidHJ1ZVwiXSddLm1hcChzZWxlY3RvciA9PiBgJHtzZWxlY3Rvcn06bm90KFt0YWJpbmRleF49XCItXCJdKWApLmpvaW4oJywgJyk7XG4gICAgICByZXR1cm4gdGhpcy5maW5kKGZvY3VzYWJsZXMsIGVsZW1lbnQpLmZpbHRlcihlbCA9PiAhaXNEaXNhYmxlZChlbCkgJiYgaXNWaXNpYmxlKGVsKSk7XG4gICAgfVxuXG4gIH07XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjUuMS4zKTogY2Fyb3VzZWwuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYWluL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIENvbnN0YW50c1xuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgY29uc3QgTkFNRSRiID0gJ2Nhcm91c2VsJztcbiAgY29uc3QgREFUQV9LRVkkYSA9ICdicy5jYXJvdXNlbCc7XG4gIGNvbnN0IEVWRU5UX0tFWSRhID0gYC4ke0RBVEFfS0VZJGF9YDtcbiAgY29uc3QgREFUQV9BUElfS0VZJDYgPSAnLmRhdGEtYXBpJztcbiAgY29uc3QgQVJST1dfTEVGVF9LRVkgPSAnQXJyb3dMZWZ0JztcbiAgY29uc3QgQVJST1dfUklHSFRfS0VZID0gJ0Fycm93UmlnaHQnO1xuICBjb25zdCBUT1VDSEVWRU5UX0NPTVBBVF9XQUlUID0gNTAwOyAvLyBUaW1lIGZvciBtb3VzZSBjb21wYXQgZXZlbnRzIHRvIGZpcmUgYWZ0ZXIgdG91Y2hcblxuICBjb25zdCBTV0lQRV9USFJFU0hPTEQgPSA0MDtcbiAgY29uc3QgRGVmYXVsdCRhID0ge1xuICAgIGludGVydmFsOiA1MDAwLFxuICAgIGtleWJvYXJkOiB0cnVlLFxuICAgIHNsaWRlOiBmYWxzZSxcbiAgICBwYXVzZTogJ2hvdmVyJyxcbiAgICB3cmFwOiB0cnVlLFxuICAgIHRvdWNoOiB0cnVlXG4gIH07XG4gIGNvbnN0IERlZmF1bHRUeXBlJGEgPSB7XG4gICAgaW50ZXJ2YWw6ICcobnVtYmVyfGJvb2xlYW4pJyxcbiAgICBrZXlib2FyZDogJ2Jvb2xlYW4nLFxuICAgIHNsaWRlOiAnKGJvb2xlYW58c3RyaW5nKScsXG4gICAgcGF1c2U6ICcoc3RyaW5nfGJvb2xlYW4pJyxcbiAgICB3cmFwOiAnYm9vbGVhbicsXG4gICAgdG91Y2g6ICdib29sZWFuJ1xuICB9O1xuICBjb25zdCBPUkRFUl9ORVhUID0gJ25leHQnO1xuICBjb25zdCBPUkRFUl9QUkVWID0gJ3ByZXYnO1xuICBjb25zdCBESVJFQ1RJT05fTEVGVCA9ICdsZWZ0JztcbiAgY29uc3QgRElSRUNUSU9OX1JJR0hUID0gJ3JpZ2h0JztcbiAgY29uc3QgS0VZX1RPX0RJUkVDVElPTiA9IHtcbiAgICBbQVJST1dfTEVGVF9LRVldOiBESVJFQ1RJT05fUklHSFQsXG4gICAgW0FSUk9XX1JJR0hUX0tFWV06IERJUkVDVElPTl9MRUZUXG4gIH07XG4gIGNvbnN0IEVWRU5UX1NMSURFID0gYHNsaWRlJHtFVkVOVF9LRVkkYX1gO1xuICBjb25zdCBFVkVOVF9TTElEID0gYHNsaWQke0VWRU5UX0tFWSRhfWA7XG4gIGNvbnN0IEVWRU5UX0tFWURPV04gPSBga2V5ZG93biR7RVZFTlRfS0VZJGF9YDtcbiAgY29uc3QgRVZFTlRfTU9VU0VFTlRFUiA9IGBtb3VzZWVudGVyJHtFVkVOVF9LRVkkYX1gO1xuICBjb25zdCBFVkVOVF9NT1VTRUxFQVZFID0gYG1vdXNlbGVhdmUke0VWRU5UX0tFWSRhfWA7XG4gIGNvbnN0IEVWRU5UX1RPVUNIU1RBUlQgPSBgdG91Y2hzdGFydCR7RVZFTlRfS0VZJGF9YDtcbiAgY29uc3QgRVZFTlRfVE9VQ0hNT1ZFID0gYHRvdWNobW92ZSR7RVZFTlRfS0VZJGF9YDtcbiAgY29uc3QgRVZFTlRfVE9VQ0hFTkQgPSBgdG91Y2hlbmQke0VWRU5UX0tFWSRhfWA7XG4gIGNvbnN0IEVWRU5UX1BPSU5URVJET1dOID0gYHBvaW50ZXJkb3duJHtFVkVOVF9LRVkkYX1gO1xuICBjb25zdCBFVkVOVF9QT0lOVEVSVVAgPSBgcG9pbnRlcnVwJHtFVkVOVF9LRVkkYX1gO1xuICBjb25zdCBFVkVOVF9EUkFHX1NUQVJUID0gYGRyYWdzdGFydCR7RVZFTlRfS0VZJGF9YDtcbiAgY29uc3QgRVZFTlRfTE9BRF9EQVRBX0FQSSQyID0gYGxvYWQke0VWRU5UX0tFWSRhfSR7REFUQV9BUElfS0VZJDZ9YDtcbiAgY29uc3QgRVZFTlRfQ0xJQ0tfREFUQV9BUEkkNSA9IGBjbGljayR7RVZFTlRfS0VZJGF9JHtEQVRBX0FQSV9LRVkkNn1gO1xuICBjb25zdCBDTEFTU19OQU1FX0NBUk9VU0VMID0gJ2Nhcm91c2VsJztcbiAgY29uc3QgQ0xBU1NfTkFNRV9BQ1RJVkUkMiA9ICdhY3RpdmUnO1xuICBjb25zdCBDTEFTU19OQU1FX1NMSURFID0gJ3NsaWRlJztcbiAgY29uc3QgQ0xBU1NfTkFNRV9FTkQgPSAnY2Fyb3VzZWwtaXRlbS1lbmQnO1xuICBjb25zdCBDTEFTU19OQU1FX1NUQVJUID0gJ2Nhcm91c2VsLWl0ZW0tc3RhcnQnO1xuICBjb25zdCBDTEFTU19OQU1FX05FWFQgPSAnY2Fyb3VzZWwtaXRlbS1uZXh0JztcbiAgY29uc3QgQ0xBU1NfTkFNRV9QUkVWID0gJ2Nhcm91c2VsLWl0ZW0tcHJldic7XG4gIGNvbnN0IENMQVNTX05BTUVfUE9JTlRFUl9FVkVOVCA9ICdwb2ludGVyLWV2ZW50JztcbiAgY29uc3QgU0VMRUNUT1JfQUNUSVZFJDEgPSAnLmFjdGl2ZSc7XG4gIGNvbnN0IFNFTEVDVE9SX0FDVElWRV9JVEVNID0gJy5hY3RpdmUuY2Fyb3VzZWwtaXRlbSc7XG4gIGNvbnN0IFNFTEVDVE9SX0lURU0gPSAnLmNhcm91c2VsLWl0ZW0nO1xuICBjb25zdCBTRUxFQ1RPUl9JVEVNX0lNRyA9ICcuY2Fyb3VzZWwtaXRlbSBpbWcnO1xuICBjb25zdCBTRUxFQ1RPUl9ORVhUX1BSRVYgPSAnLmNhcm91c2VsLWl0ZW0tbmV4dCwgLmNhcm91c2VsLWl0ZW0tcHJldic7XG4gIGNvbnN0IFNFTEVDVE9SX0lORElDQVRPUlMgPSAnLmNhcm91c2VsLWluZGljYXRvcnMnO1xuICBjb25zdCBTRUxFQ1RPUl9JTkRJQ0FUT1IgPSAnW2RhdGEtYnMtdGFyZ2V0XSc7XG4gIGNvbnN0IFNFTEVDVE9SX0RBVEFfU0xJREUgPSAnW2RhdGEtYnMtc2xpZGVdLCBbZGF0YS1icy1zbGlkZS10b10nO1xuICBjb25zdCBTRUxFQ1RPUl9EQVRBX1JJREUgPSAnW2RhdGEtYnMtcmlkZT1cImNhcm91c2VsXCJdJztcbiAgY29uc3QgUE9JTlRFUl9UWVBFX1RPVUNIID0gJ3RvdWNoJztcbiAgY29uc3QgUE9JTlRFUl9UWVBFX1BFTiA9ICdwZW4nO1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIENsYXNzIERlZmluaXRpb25cbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIGNsYXNzIENhcm91c2VsIGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoZWxlbWVudCwgY29uZmlnKSB7XG4gICAgICBzdXBlcihlbGVtZW50KTtcbiAgICAgIHRoaXMuX2l0ZW1zID0gbnVsbDtcbiAgICAgIHRoaXMuX2ludGVydmFsID0gbnVsbDtcbiAgICAgIHRoaXMuX2FjdGl2ZUVsZW1lbnQgPSBudWxsO1xuICAgICAgdGhpcy5faXNQYXVzZWQgPSBmYWxzZTtcbiAgICAgIHRoaXMuX2lzU2xpZGluZyA9IGZhbHNlO1xuICAgICAgdGhpcy50b3VjaFRpbWVvdXQgPSBudWxsO1xuICAgICAgdGhpcy50b3VjaFN0YXJ0WCA9IDA7XG4gICAgICB0aGlzLnRvdWNoRGVsdGFYID0gMDtcbiAgICAgIHRoaXMuX2NvbmZpZyA9IHRoaXMuX2dldENvbmZpZyhjb25maWcpO1xuICAgICAgdGhpcy5faW5kaWNhdG9yc0VsZW1lbnQgPSBTZWxlY3RvckVuZ2luZS5maW5kT25lKFNFTEVDVE9SX0lORElDQVRPUlMsIHRoaXMuX2VsZW1lbnQpO1xuICAgICAgdGhpcy5fdG91Y2hTdXBwb3J0ZWQgPSAnb250b3VjaHN0YXJ0JyBpbiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgfHwgbmF2aWdhdG9yLm1heFRvdWNoUG9pbnRzID4gMDtcbiAgICAgIHRoaXMuX3BvaW50ZXJFdmVudCA9IEJvb2xlYW4od2luZG93LlBvaW50ZXJFdmVudCk7XG5cbiAgICAgIHRoaXMuX2FkZEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgfSAvLyBHZXR0ZXJzXG5cblxuICAgIHN0YXRpYyBnZXQgRGVmYXVsdCgpIHtcbiAgICAgIHJldHVybiBEZWZhdWx0JGE7XG4gICAgfVxuXG4gICAgc3RhdGljIGdldCBOQU1FKCkge1xuICAgICAgcmV0dXJuIE5BTUUkYjtcbiAgICB9IC8vIFB1YmxpY1xuXG5cbiAgICBuZXh0KCkge1xuICAgICAgdGhpcy5fc2xpZGUoT1JERVJfTkVYVCk7XG4gICAgfVxuXG4gICAgbmV4dFdoZW5WaXNpYmxlKCkge1xuICAgICAgLy8gRG9uJ3QgY2FsbCBuZXh0IHdoZW4gdGhlIHBhZ2UgaXNuJ3QgdmlzaWJsZVxuICAgICAgLy8gb3IgdGhlIGNhcm91c2VsIG9yIGl0cyBwYXJlbnQgaXNuJ3QgdmlzaWJsZVxuICAgICAgaWYgKCFkb2N1bWVudC5oaWRkZW4gJiYgaXNWaXNpYmxlKHRoaXMuX2VsZW1lbnQpKSB7XG4gICAgICAgIHRoaXMubmV4dCgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHByZXYoKSB7XG4gICAgICB0aGlzLl9zbGlkZShPUkRFUl9QUkVWKTtcbiAgICB9XG5cbiAgICBwYXVzZShldmVudCkge1xuICAgICAgaWYgKCFldmVudCkge1xuICAgICAgICB0aGlzLl9pc1BhdXNlZCA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChTZWxlY3RvckVuZ2luZS5maW5kT25lKFNFTEVDVE9SX05FWFRfUFJFViwgdGhpcy5fZWxlbWVudCkpIHtcbiAgICAgICAgdHJpZ2dlclRyYW5zaXRpb25FbmQodGhpcy5fZWxlbWVudCk7XG4gICAgICAgIHRoaXMuY3ljbGUodHJ1ZSk7XG4gICAgICB9XG5cbiAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy5faW50ZXJ2YWwpO1xuICAgICAgdGhpcy5faW50ZXJ2YWwgPSBudWxsO1xuICAgIH1cblxuICAgIGN5Y2xlKGV2ZW50KSB7XG4gICAgICBpZiAoIWV2ZW50KSB7XG4gICAgICAgIHRoaXMuX2lzUGF1c2VkID0gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9pbnRlcnZhbCkge1xuICAgICAgICBjbGVhckludGVydmFsKHRoaXMuX2ludGVydmFsKTtcbiAgICAgICAgdGhpcy5faW50ZXJ2YWwgPSBudWxsO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5fY29uZmlnICYmIHRoaXMuX2NvbmZpZy5pbnRlcnZhbCAmJiAhdGhpcy5faXNQYXVzZWQpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlSW50ZXJ2YWwoKTtcblxuICAgICAgICB0aGlzLl9pbnRlcnZhbCA9IHNldEludGVydmFsKChkb2N1bWVudC52aXNpYmlsaXR5U3RhdGUgPyB0aGlzLm5leHRXaGVuVmlzaWJsZSA6IHRoaXMubmV4dCkuYmluZCh0aGlzKSwgdGhpcy5fY29uZmlnLmludGVydmFsKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0byhpbmRleCkge1xuICAgICAgdGhpcy5fYWN0aXZlRWxlbWVudCA9IFNlbGVjdG9yRW5naW5lLmZpbmRPbmUoU0VMRUNUT1JfQUNUSVZFX0lURU0sIHRoaXMuX2VsZW1lbnQpO1xuXG4gICAgICBjb25zdCBhY3RpdmVJbmRleCA9IHRoaXMuX2dldEl0ZW1JbmRleCh0aGlzLl9hY3RpdmVFbGVtZW50KTtcblxuICAgICAgaWYgKGluZGV4ID4gdGhpcy5faXRlbXMubGVuZ3RoIC0gMSB8fCBpbmRleCA8IDApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5faXNTbGlkaW5nKSB7XG4gICAgICAgIEV2ZW50SGFuZGxlci5vbmUodGhpcy5fZWxlbWVudCwgRVZFTlRfU0xJRCwgKCkgPT4gdGhpcy50byhpbmRleCkpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmIChhY3RpdmVJbmRleCA9PT0gaW5kZXgpIHtcbiAgICAgICAgdGhpcy5wYXVzZSgpO1xuICAgICAgICB0aGlzLmN5Y2xlKCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb3JkZXIgPSBpbmRleCA+IGFjdGl2ZUluZGV4ID8gT1JERVJfTkVYVCA6IE9SREVSX1BSRVY7XG5cbiAgICAgIHRoaXMuX3NsaWRlKG9yZGVyLCB0aGlzLl9pdGVtc1tpbmRleF0pO1xuICAgIH0gLy8gUHJpdmF0ZVxuXG5cbiAgICBfZ2V0Q29uZmlnKGNvbmZpZykge1xuICAgICAgY29uZmlnID0geyAuLi5EZWZhdWx0JGEsXG4gICAgICAgIC4uLk1hbmlwdWxhdG9yLmdldERhdGFBdHRyaWJ1dGVzKHRoaXMuX2VsZW1lbnQpLFxuICAgICAgICAuLi4odHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcgPyBjb25maWcgOiB7fSlcbiAgICAgIH07XG4gICAgICB0eXBlQ2hlY2tDb25maWcoTkFNRSRiLCBjb25maWcsIERlZmF1bHRUeXBlJGEpO1xuICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICB9XG5cbiAgICBfaGFuZGxlU3dpcGUoKSB7XG4gICAgICBjb25zdCBhYnNEZWx0YXggPSBNYXRoLmFicyh0aGlzLnRvdWNoRGVsdGFYKTtcblxuICAgICAgaWYgKGFic0RlbHRheCA8PSBTV0lQRV9USFJFU0hPTEQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBkaXJlY3Rpb24gPSBhYnNEZWx0YXggLyB0aGlzLnRvdWNoRGVsdGFYO1xuICAgICAgdGhpcy50b3VjaERlbHRhWCA9IDA7XG5cbiAgICAgIGlmICghZGlyZWN0aW9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fc2xpZGUoZGlyZWN0aW9uID4gMCA/IERJUkVDVElPTl9SSUdIVCA6IERJUkVDVElPTl9MRUZUKTtcbiAgICB9XG5cbiAgICBfYWRkRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgICBpZiAodGhpcy5fY29uZmlnLmtleWJvYXJkKSB7XG4gICAgICAgIEV2ZW50SGFuZGxlci5vbih0aGlzLl9lbGVtZW50LCBFVkVOVF9LRVlET1dOLCBldmVudCA9PiB0aGlzLl9rZXlkb3duKGV2ZW50KSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9jb25maWcucGF1c2UgPT09ICdob3ZlcicpIHtcbiAgICAgICAgRXZlbnRIYW5kbGVyLm9uKHRoaXMuX2VsZW1lbnQsIEVWRU5UX01PVVNFRU5URVIsIGV2ZW50ID0+IHRoaXMucGF1c2UoZXZlbnQpKTtcbiAgICAgICAgRXZlbnRIYW5kbGVyLm9uKHRoaXMuX2VsZW1lbnQsIEVWRU5UX01PVVNFTEVBVkUsIGV2ZW50ID0+IHRoaXMuY3ljbGUoZXZlbnQpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX2NvbmZpZy50b3VjaCAmJiB0aGlzLl90b3VjaFN1cHBvcnRlZCkge1xuICAgICAgICB0aGlzLl9hZGRUb3VjaEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgX2FkZFRvdWNoRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgICBjb25zdCBoYXNQb2ludGVyUGVuVG91Y2ggPSBldmVudCA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9wb2ludGVyRXZlbnQgJiYgKGV2ZW50LnBvaW50ZXJUeXBlID09PSBQT0lOVEVSX1RZUEVfUEVOIHx8IGV2ZW50LnBvaW50ZXJUeXBlID09PSBQT0lOVEVSX1RZUEVfVE9VQ0gpO1xuICAgICAgfTtcblxuICAgICAgY29uc3Qgc3RhcnQgPSBldmVudCA9PiB7XG4gICAgICAgIGlmIChoYXNQb2ludGVyUGVuVG91Y2goZXZlbnQpKSB7XG4gICAgICAgICAgdGhpcy50b3VjaFN0YXJ0WCA9IGV2ZW50LmNsaWVudFg7XG4gICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuX3BvaW50ZXJFdmVudCkge1xuICAgICAgICAgIHRoaXMudG91Y2hTdGFydFggPSBldmVudC50b3VjaGVzWzBdLmNsaWVudFg7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IG1vdmUgPSBldmVudCA9PiB7XG4gICAgICAgIC8vIGVuc3VyZSBzd2lwaW5nIHdpdGggb25lIHRvdWNoIGFuZCBub3QgcGluY2hpbmdcbiAgICAgICAgdGhpcy50b3VjaERlbHRhWCA9IGV2ZW50LnRvdWNoZXMgJiYgZXZlbnQudG91Y2hlcy5sZW5ndGggPiAxID8gMCA6IGV2ZW50LnRvdWNoZXNbMF0uY2xpZW50WCAtIHRoaXMudG91Y2hTdGFydFg7XG4gICAgICB9O1xuXG4gICAgICBjb25zdCBlbmQgPSBldmVudCA9PiB7XG4gICAgICAgIGlmIChoYXNQb2ludGVyUGVuVG91Y2goZXZlbnQpKSB7XG4gICAgICAgICAgdGhpcy50b3VjaERlbHRhWCA9IGV2ZW50LmNsaWVudFggLSB0aGlzLnRvdWNoU3RhcnRYO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5faGFuZGxlU3dpcGUoKTtcblxuICAgICAgICBpZiAodGhpcy5fY29uZmlnLnBhdXNlID09PSAnaG92ZXInKSB7XG4gICAgICAgICAgLy8gSWYgaXQncyBhIHRvdWNoLWVuYWJsZWQgZGV2aWNlLCBtb3VzZWVudGVyL2xlYXZlIGFyZSBmaXJlZCBhc1xuICAgICAgICAgIC8vIHBhcnQgb2YgdGhlIG1vdXNlIGNvbXBhdGliaWxpdHkgZXZlbnRzIG9uIGZpcnN0IHRhcCAtIHRoZSBjYXJvdXNlbFxuICAgICAgICAgIC8vIHdvdWxkIHN0b3AgY3ljbGluZyB1bnRpbCB1c2VyIHRhcHBlZCBvdXQgb2YgaXQ7XG4gICAgICAgICAgLy8gaGVyZSwgd2UgbGlzdGVuIGZvciB0b3VjaGVuZCwgZXhwbGljaXRseSBwYXVzZSB0aGUgY2Fyb3VzZWxcbiAgICAgICAgICAvLyAoYXMgaWYgaXQncyB0aGUgc2Vjb25kIHRpbWUgd2UgdGFwIG9uIGl0LCBtb3VzZWVudGVyIGNvbXBhdCBldmVudFxuICAgICAgICAgIC8vIGlzIE5PVCBmaXJlZCkgYW5kIGFmdGVyIGEgdGltZW91dCAodG8gYWxsb3cgZm9yIG1vdXNlIGNvbXBhdGliaWxpdHlcbiAgICAgICAgICAvLyBldmVudHMgdG8gZmlyZSkgd2UgZXhwbGljaXRseSByZXN0YXJ0IGN5Y2xpbmdcbiAgICAgICAgICB0aGlzLnBhdXNlKCk7XG5cbiAgICAgICAgICBpZiAodGhpcy50b3VjaFRpbWVvdXQpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnRvdWNoVGltZW91dCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy50b3VjaFRpbWVvdXQgPSBzZXRUaW1lb3V0KGV2ZW50ID0+IHRoaXMuY3ljbGUoZXZlbnQpLCBUT1VDSEVWRU5UX0NPTVBBVF9XQUlUICsgdGhpcy5fY29uZmlnLmludGVydmFsKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgU2VsZWN0b3JFbmdpbmUuZmluZChTRUxFQ1RPUl9JVEVNX0lNRywgdGhpcy5fZWxlbWVudCkuZm9yRWFjaChpdGVtSW1nID0+IHtcbiAgICAgICAgRXZlbnRIYW5kbGVyLm9uKGl0ZW1JbWcsIEVWRU5UX0RSQUdfU1RBUlQsIGV2ZW50ID0+IGV2ZW50LnByZXZlbnREZWZhdWx0KCkpO1xuICAgICAgfSk7XG5cbiAgICAgIGlmICh0aGlzLl9wb2ludGVyRXZlbnQpIHtcbiAgICAgICAgRXZlbnRIYW5kbGVyLm9uKHRoaXMuX2VsZW1lbnQsIEVWRU5UX1BPSU5URVJET1dOLCBldmVudCA9PiBzdGFydChldmVudCkpO1xuICAgICAgICBFdmVudEhhbmRsZXIub24odGhpcy5fZWxlbWVudCwgRVZFTlRfUE9JTlRFUlVQLCBldmVudCA9PiBlbmQoZXZlbnQpKTtcblxuICAgICAgICB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9QT0lOVEVSX0VWRU5UKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIEV2ZW50SGFuZGxlci5vbih0aGlzLl9lbGVtZW50LCBFVkVOVF9UT1VDSFNUQVJULCBldmVudCA9PiBzdGFydChldmVudCkpO1xuICAgICAgICBFdmVudEhhbmRsZXIub24odGhpcy5fZWxlbWVudCwgRVZFTlRfVE9VQ0hNT1ZFLCBldmVudCA9PiBtb3ZlKGV2ZW50KSk7XG4gICAgICAgIEV2ZW50SGFuZGxlci5vbih0aGlzLl9lbGVtZW50LCBFVkVOVF9UT1VDSEVORCwgZXZlbnQgPT4gZW5kKGV2ZW50KSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgX2tleWRvd24oZXZlbnQpIHtcbiAgICAgIGlmICgvaW5wdXR8dGV4dGFyZWEvaS50ZXN0KGV2ZW50LnRhcmdldC50YWdOYW1lKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRpcmVjdGlvbiA9IEtFWV9UT19ESVJFQ1RJT05bZXZlbnQua2V5XTtcblxuICAgICAgaWYgKGRpcmVjdGlvbikge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIHRoaXMuX3NsaWRlKGRpcmVjdGlvbik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgX2dldEl0ZW1JbmRleChlbGVtZW50KSB7XG4gICAgICB0aGlzLl9pdGVtcyA9IGVsZW1lbnQgJiYgZWxlbWVudC5wYXJlbnROb2RlID8gU2VsZWN0b3JFbmdpbmUuZmluZChTRUxFQ1RPUl9JVEVNLCBlbGVtZW50LnBhcmVudE5vZGUpIDogW107XG4gICAgICByZXR1cm4gdGhpcy5faXRlbXMuaW5kZXhPZihlbGVtZW50KTtcbiAgICB9XG5cbiAgICBfZ2V0SXRlbUJ5T3JkZXIob3JkZXIsIGFjdGl2ZUVsZW1lbnQpIHtcbiAgICAgIGNvbnN0IGlzTmV4dCA9IG9yZGVyID09PSBPUkRFUl9ORVhUO1xuICAgICAgcmV0dXJuIGdldE5leHRBY3RpdmVFbGVtZW50KHRoaXMuX2l0ZW1zLCBhY3RpdmVFbGVtZW50LCBpc05leHQsIHRoaXMuX2NvbmZpZy53cmFwKTtcbiAgICB9XG5cbiAgICBfdHJpZ2dlclNsaWRlRXZlbnQocmVsYXRlZFRhcmdldCwgZXZlbnREaXJlY3Rpb25OYW1lKSB7XG4gICAgICBjb25zdCB0YXJnZXRJbmRleCA9IHRoaXMuX2dldEl0ZW1JbmRleChyZWxhdGVkVGFyZ2V0KTtcblxuICAgICAgY29uc3QgZnJvbUluZGV4ID0gdGhpcy5fZ2V0SXRlbUluZGV4KFNlbGVjdG9yRW5naW5lLmZpbmRPbmUoU0VMRUNUT1JfQUNUSVZFX0lURU0sIHRoaXMuX2VsZW1lbnQpKTtcblxuICAgICAgcmV0dXJuIEV2ZW50SGFuZGxlci50cmlnZ2VyKHRoaXMuX2VsZW1lbnQsIEVWRU5UX1NMSURFLCB7XG4gICAgICAgIHJlbGF0ZWRUYXJnZXQsXG4gICAgICAgIGRpcmVjdGlvbjogZXZlbnREaXJlY3Rpb25OYW1lLFxuICAgICAgICBmcm9tOiBmcm9tSW5kZXgsXG4gICAgICAgIHRvOiB0YXJnZXRJbmRleFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgX3NldEFjdGl2ZUluZGljYXRvckVsZW1lbnQoZWxlbWVudCkge1xuICAgICAgaWYgKHRoaXMuX2luZGljYXRvcnNFbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IGFjdGl2ZUluZGljYXRvciA9IFNlbGVjdG9yRW5naW5lLmZpbmRPbmUoU0VMRUNUT1JfQUNUSVZFJDEsIHRoaXMuX2luZGljYXRvcnNFbGVtZW50KTtcbiAgICAgICAgYWN0aXZlSW5kaWNhdG9yLmNsYXNzTGlzdC5yZW1vdmUoQ0xBU1NfTkFNRV9BQ1RJVkUkMik7XG4gICAgICAgIGFjdGl2ZUluZGljYXRvci5yZW1vdmVBdHRyaWJ1dGUoJ2FyaWEtY3VycmVudCcpO1xuICAgICAgICBjb25zdCBpbmRpY2F0b3JzID0gU2VsZWN0b3JFbmdpbmUuZmluZChTRUxFQ1RPUl9JTkRJQ0FUT1IsIHRoaXMuX2luZGljYXRvcnNFbGVtZW50KTtcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGluZGljYXRvcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpZiAoTnVtYmVyLnBhcnNlSW50KGluZGljYXRvcnNbaV0uZ2V0QXR0cmlidXRlKCdkYXRhLWJzLXNsaWRlLXRvJyksIDEwKSA9PT0gdGhpcy5fZ2V0SXRlbUluZGV4KGVsZW1lbnQpKSB7XG4gICAgICAgICAgICBpbmRpY2F0b3JzW2ldLmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9BQ1RJVkUkMik7XG4gICAgICAgICAgICBpbmRpY2F0b3JzW2ldLnNldEF0dHJpYnV0ZSgnYXJpYS1jdXJyZW50JywgJ3RydWUnKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIF91cGRhdGVJbnRlcnZhbCgpIHtcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLl9hY3RpdmVFbGVtZW50IHx8IFNlbGVjdG9yRW5naW5lLmZpbmRPbmUoU0VMRUNUT1JfQUNUSVZFX0lURU0sIHRoaXMuX2VsZW1lbnQpO1xuXG4gICAgICBpZiAoIWVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBlbGVtZW50SW50ZXJ2YWwgPSBOdW1iZXIucGFyc2VJbnQoZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2RhdGEtYnMtaW50ZXJ2YWwnKSwgMTApO1xuXG4gICAgICBpZiAoZWxlbWVudEludGVydmFsKSB7XG4gICAgICAgIHRoaXMuX2NvbmZpZy5kZWZhdWx0SW50ZXJ2YWwgPSB0aGlzLl9jb25maWcuZGVmYXVsdEludGVydmFsIHx8IHRoaXMuX2NvbmZpZy5pbnRlcnZhbDtcbiAgICAgICAgdGhpcy5fY29uZmlnLmludGVydmFsID0gZWxlbWVudEludGVydmFsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fY29uZmlnLmludGVydmFsID0gdGhpcy5fY29uZmlnLmRlZmF1bHRJbnRlcnZhbCB8fCB0aGlzLl9jb25maWcuaW50ZXJ2YWw7XG4gICAgICB9XG4gICAgfVxuXG4gICAgX3NsaWRlKGRpcmVjdGlvbk9yT3JkZXIsIGVsZW1lbnQpIHtcbiAgICAgIGNvbnN0IG9yZGVyID0gdGhpcy5fZGlyZWN0aW9uVG9PcmRlcihkaXJlY3Rpb25Pck9yZGVyKTtcblxuICAgICAgY29uc3QgYWN0aXZlRWxlbWVudCA9IFNlbGVjdG9yRW5naW5lLmZpbmRPbmUoU0VMRUNUT1JfQUNUSVZFX0lURU0sIHRoaXMuX2VsZW1lbnQpO1xuXG4gICAgICBjb25zdCBhY3RpdmVFbGVtZW50SW5kZXggPSB0aGlzLl9nZXRJdGVtSW5kZXgoYWN0aXZlRWxlbWVudCk7XG5cbiAgICAgIGNvbnN0IG5leHRFbGVtZW50ID0gZWxlbWVudCB8fCB0aGlzLl9nZXRJdGVtQnlPcmRlcihvcmRlciwgYWN0aXZlRWxlbWVudCk7XG5cbiAgICAgIGNvbnN0IG5leHRFbGVtZW50SW5kZXggPSB0aGlzLl9nZXRJdGVtSW5kZXgobmV4dEVsZW1lbnQpO1xuXG4gICAgICBjb25zdCBpc0N5Y2xpbmcgPSBCb29sZWFuKHRoaXMuX2ludGVydmFsKTtcbiAgICAgIGNvbnN0IGlzTmV4dCA9IG9yZGVyID09PSBPUkRFUl9ORVhUO1xuICAgICAgY29uc3QgZGlyZWN0aW9uYWxDbGFzc05hbWUgPSBpc05leHQgPyBDTEFTU19OQU1FX1NUQVJUIDogQ0xBU1NfTkFNRV9FTkQ7XG4gICAgICBjb25zdCBvcmRlckNsYXNzTmFtZSA9IGlzTmV4dCA/IENMQVNTX05BTUVfTkVYVCA6IENMQVNTX05BTUVfUFJFVjtcblxuICAgICAgY29uc3QgZXZlbnREaXJlY3Rpb25OYW1lID0gdGhpcy5fb3JkZXJUb0RpcmVjdGlvbihvcmRlcik7XG5cbiAgICAgIGlmIChuZXh0RWxlbWVudCAmJiBuZXh0RWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoQ0xBU1NfTkFNRV9BQ1RJVkUkMikpIHtcbiAgICAgICAgdGhpcy5faXNTbGlkaW5nID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX2lzU2xpZGluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNsaWRlRXZlbnQgPSB0aGlzLl90cmlnZ2VyU2xpZGVFdmVudChuZXh0RWxlbWVudCwgZXZlbnREaXJlY3Rpb25OYW1lKTtcblxuICAgICAgaWYgKHNsaWRlRXZlbnQuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICghYWN0aXZlRWxlbWVudCB8fCAhbmV4dEVsZW1lbnQpIHtcbiAgICAgICAgLy8gU29tZSB3ZWlyZG5lc3MgaXMgaGFwcGVuaW5nLCBzbyB3ZSBiYWlsXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5faXNTbGlkaW5nID0gdHJ1ZTtcblxuICAgICAgaWYgKGlzQ3ljbGluZykge1xuICAgICAgICB0aGlzLnBhdXNlKCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3NldEFjdGl2ZUluZGljYXRvckVsZW1lbnQobmV4dEVsZW1lbnQpO1xuXG4gICAgICB0aGlzLl9hY3RpdmVFbGVtZW50ID0gbmV4dEVsZW1lbnQ7XG5cbiAgICAgIGNvbnN0IHRyaWdnZXJTbGlkRXZlbnQgPSAoKSA9PiB7XG4gICAgICAgIEV2ZW50SGFuZGxlci50cmlnZ2VyKHRoaXMuX2VsZW1lbnQsIEVWRU5UX1NMSUQsIHtcbiAgICAgICAgICByZWxhdGVkVGFyZ2V0OiBuZXh0RWxlbWVudCxcbiAgICAgICAgICBkaXJlY3Rpb246IGV2ZW50RGlyZWN0aW9uTmFtZSxcbiAgICAgICAgICBmcm9tOiBhY3RpdmVFbGVtZW50SW5kZXgsXG4gICAgICAgICAgdG86IG5leHRFbGVtZW50SW5kZXhcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBpZiAodGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoQ0xBU1NfTkFNRV9TTElERSkpIHtcbiAgICAgICAgbmV4dEVsZW1lbnQuY2xhc3NMaXN0LmFkZChvcmRlckNsYXNzTmFtZSk7XG4gICAgICAgIHJlZmxvdyhuZXh0RWxlbWVudCk7XG4gICAgICAgIGFjdGl2ZUVsZW1lbnQuY2xhc3NMaXN0LmFkZChkaXJlY3Rpb25hbENsYXNzTmFtZSk7XG4gICAgICAgIG5leHRFbGVtZW50LmNsYXNzTGlzdC5hZGQoZGlyZWN0aW9uYWxDbGFzc05hbWUpO1xuXG4gICAgICAgIGNvbnN0IGNvbXBsZXRlQ2FsbEJhY2sgPSAoKSA9PiB7XG4gICAgICAgICAgbmV4dEVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShkaXJlY3Rpb25hbENsYXNzTmFtZSwgb3JkZXJDbGFzc05hbWUpO1xuICAgICAgICAgIG5leHRFbGVtZW50LmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9BQ1RJVkUkMik7XG4gICAgICAgICAgYWN0aXZlRWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKENMQVNTX05BTUVfQUNUSVZFJDIsIG9yZGVyQ2xhc3NOYW1lLCBkaXJlY3Rpb25hbENsYXNzTmFtZSk7XG4gICAgICAgICAgdGhpcy5faXNTbGlkaW5nID0gZmFsc2U7XG4gICAgICAgICAgc2V0VGltZW91dCh0cmlnZ2VyU2xpZEV2ZW50LCAwKTtcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLl9xdWV1ZUNhbGxiYWNrKGNvbXBsZXRlQ2FsbEJhY2ssIGFjdGl2ZUVsZW1lbnQsIHRydWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYWN0aXZlRWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKENMQVNTX05BTUVfQUNUSVZFJDIpO1xuICAgICAgICBuZXh0RWxlbWVudC5jbGFzc0xpc3QuYWRkKENMQVNTX05BTUVfQUNUSVZFJDIpO1xuICAgICAgICB0aGlzLl9pc1NsaWRpbmcgPSBmYWxzZTtcbiAgICAgICAgdHJpZ2dlclNsaWRFdmVudCgpO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNDeWNsaW5nKSB7XG4gICAgICAgIHRoaXMuY3ljbGUoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBfZGlyZWN0aW9uVG9PcmRlcihkaXJlY3Rpb24pIHtcbiAgICAgIGlmICghW0RJUkVDVElPTl9SSUdIVCwgRElSRUNUSU9OX0xFRlRdLmluY2x1ZGVzKGRpcmVjdGlvbikpIHtcbiAgICAgICAgcmV0dXJuIGRpcmVjdGlvbjtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzUlRMKCkpIHtcbiAgICAgICAgcmV0dXJuIGRpcmVjdGlvbiA9PT0gRElSRUNUSU9OX0xFRlQgPyBPUkRFUl9QUkVWIDogT1JERVJfTkVYVDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGRpcmVjdGlvbiA9PT0gRElSRUNUSU9OX0xFRlQgPyBPUkRFUl9ORVhUIDogT1JERVJfUFJFVjtcbiAgICB9XG5cbiAgICBfb3JkZXJUb0RpcmVjdGlvbihvcmRlcikge1xuICAgICAgaWYgKCFbT1JERVJfTkVYVCwgT1JERVJfUFJFVl0uaW5jbHVkZXMob3JkZXIpKSB7XG4gICAgICAgIHJldHVybiBvcmRlcjtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzUlRMKCkpIHtcbiAgICAgICAgcmV0dXJuIG9yZGVyID09PSBPUkRFUl9QUkVWID8gRElSRUNUSU9OX0xFRlQgOiBESVJFQ1RJT05fUklHSFQ7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBvcmRlciA9PT0gT1JERVJfUFJFViA/IERJUkVDVElPTl9SSUdIVCA6IERJUkVDVElPTl9MRUZUO1xuICAgIH0gLy8gU3RhdGljXG5cblxuICAgIHN0YXRpYyBjYXJvdXNlbEludGVyZmFjZShlbGVtZW50LCBjb25maWcpIHtcbiAgICAgIGNvbnN0IGRhdGEgPSBDYXJvdXNlbC5nZXRPckNyZWF0ZUluc3RhbmNlKGVsZW1lbnQsIGNvbmZpZyk7XG4gICAgICBsZXQge1xuICAgICAgICBfY29uZmlnXG4gICAgICB9ID0gZGF0YTtcblxuICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIF9jb25maWcgPSB7IC4uLl9jb25maWcsXG4gICAgICAgICAgLi4uY29uZmlnXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGFjdGlvbiA9IHR5cGVvZiBjb25maWcgPT09ICdzdHJpbmcnID8gY29uZmlnIDogX2NvbmZpZy5zbGlkZTtcblxuICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdudW1iZXInKSB7XG4gICAgICAgIGRhdGEudG8oY29uZmlnKTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGFjdGlvbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2FjdGlvbl0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgTm8gbWV0aG9kIG5hbWVkIFwiJHthY3Rpb259XCJgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRhdGFbYWN0aW9uXSgpO1xuICAgICAgfSBlbHNlIGlmIChfY29uZmlnLmludGVydmFsICYmIF9jb25maWcucmlkZSkge1xuICAgICAgICBkYXRhLnBhdXNlKCk7XG4gICAgICAgIGRhdGEuY3ljbGUoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBzdGF0aWMgalF1ZXJ5SW50ZXJmYWNlKGNvbmZpZykge1xuICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIENhcm91c2VsLmNhcm91c2VsSW50ZXJmYWNlKHRoaXMsIGNvbmZpZyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZGF0YUFwaUNsaWNrSGFuZGxlcihldmVudCkge1xuICAgICAgY29uc3QgdGFyZ2V0ID0gZ2V0RWxlbWVudEZyb21TZWxlY3Rvcih0aGlzKTtcblxuICAgICAgaWYgKCF0YXJnZXQgfHwgIXRhcmdldC5jbGFzc0xpc3QuY29udGFpbnMoQ0xBU1NfTkFNRV9DQVJPVVNFTCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjb25maWcgPSB7IC4uLk1hbmlwdWxhdG9yLmdldERhdGFBdHRyaWJ1dGVzKHRhcmdldCksXG4gICAgICAgIC4uLk1hbmlwdWxhdG9yLmdldERhdGFBdHRyaWJ1dGVzKHRoaXMpXG4gICAgICB9O1xuICAgICAgY29uc3Qgc2xpZGVJbmRleCA9IHRoaXMuZ2V0QXR0cmlidXRlKCdkYXRhLWJzLXNsaWRlLXRvJyk7XG5cbiAgICAgIGlmIChzbGlkZUluZGV4KSB7XG4gICAgICAgIGNvbmZpZy5pbnRlcnZhbCA9IGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBDYXJvdXNlbC5jYXJvdXNlbEludGVyZmFjZSh0YXJnZXQsIGNvbmZpZyk7XG5cbiAgICAgIGlmIChzbGlkZUluZGV4KSB7XG4gICAgICAgIENhcm91c2VsLmdldEluc3RhbmNlKHRhcmdldCkudG8oc2xpZGVJbmRleCk7XG4gICAgICB9XG5cbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuXG4gIH1cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBEYXRhIEFwaSBpbXBsZW1lbnRhdGlvblxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cblxuICBFdmVudEhhbmRsZXIub24oZG9jdW1lbnQsIEVWRU5UX0NMSUNLX0RBVEFfQVBJJDUsIFNFTEVDVE9SX0RBVEFfU0xJREUsIENhcm91c2VsLmRhdGFBcGlDbGlja0hhbmRsZXIpO1xuICBFdmVudEhhbmRsZXIub24od2luZG93LCBFVkVOVF9MT0FEX0RBVEFfQVBJJDIsICgpID0+IHtcbiAgICBjb25zdCBjYXJvdXNlbHMgPSBTZWxlY3RvckVuZ2luZS5maW5kKFNFTEVDVE9SX0RBVEFfUklERSk7XG5cbiAgICBmb3IgKGxldCBpID0gMCwgbGVuID0gY2Fyb3VzZWxzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBDYXJvdXNlbC5jYXJvdXNlbEludGVyZmFjZShjYXJvdXNlbHNbaV0sIENhcm91c2VsLmdldEluc3RhbmNlKGNhcm91c2Vsc1tpXSkpO1xuICAgIH1cbiAgfSk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogalF1ZXJ5XG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBhZGQgLkNhcm91c2VsIHRvIGpRdWVyeSBvbmx5IGlmIGpRdWVyeSBpcyBwcmVzZW50XG4gICAqL1xuXG4gIGRlZmluZUpRdWVyeVBsdWdpbihDYXJvdXNlbCk7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjUuMS4zKTogY29sbGFwc2UuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYWluL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIENvbnN0YW50c1xuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgY29uc3QgTkFNRSRhID0gJ2NvbGxhcHNlJztcbiAgY29uc3QgREFUQV9LRVkkOSA9ICdicy5jb2xsYXBzZSc7XG4gIGNvbnN0IEVWRU5UX0tFWSQ5ID0gYC4ke0RBVEFfS0VZJDl9YDtcbiAgY29uc3QgREFUQV9BUElfS0VZJDUgPSAnLmRhdGEtYXBpJztcbiAgY29uc3QgRGVmYXVsdCQ5ID0ge1xuICAgIHRvZ2dsZTogdHJ1ZSxcbiAgICBwYXJlbnQ6IG51bGxcbiAgfTtcbiAgY29uc3QgRGVmYXVsdFR5cGUkOSA9IHtcbiAgICB0b2dnbGU6ICdib29sZWFuJyxcbiAgICBwYXJlbnQ6ICcobnVsbHxlbGVtZW50KSdcbiAgfTtcbiAgY29uc3QgRVZFTlRfU0hPVyQ1ID0gYHNob3cke0VWRU5UX0tFWSQ5fWA7XG4gIGNvbnN0IEVWRU5UX1NIT1dOJDUgPSBgc2hvd24ke0VWRU5UX0tFWSQ5fWA7XG4gIGNvbnN0IEVWRU5UX0hJREUkNSA9IGBoaWRlJHtFVkVOVF9LRVkkOX1gO1xuICBjb25zdCBFVkVOVF9ISURERU4kNSA9IGBoaWRkZW4ke0VWRU5UX0tFWSQ5fWA7XG4gIGNvbnN0IEVWRU5UX0NMSUNLX0RBVEFfQVBJJDQgPSBgY2xpY2ske0VWRU5UX0tFWSQ5fSR7REFUQV9BUElfS0VZJDV9YDtcbiAgY29uc3QgQ0xBU1NfTkFNRV9TSE9XJDcgPSAnc2hvdyc7XG4gIGNvbnN0IENMQVNTX05BTUVfQ09MTEFQU0UgPSAnY29sbGFwc2UnO1xuICBjb25zdCBDTEFTU19OQU1FX0NPTExBUFNJTkcgPSAnY29sbGFwc2luZyc7XG4gIGNvbnN0IENMQVNTX05BTUVfQ09MTEFQU0VEID0gJ2NvbGxhcHNlZCc7XG4gIGNvbnN0IENMQVNTX05BTUVfREVFUEVSX0NISUxEUkVOID0gYDpzY29wZSAuJHtDTEFTU19OQU1FX0NPTExBUFNFfSAuJHtDTEFTU19OQU1FX0NPTExBUFNFfWA7XG4gIGNvbnN0IENMQVNTX05BTUVfSE9SSVpPTlRBTCA9ICdjb2xsYXBzZS1ob3Jpem9udGFsJztcbiAgY29uc3QgV0lEVEggPSAnd2lkdGgnO1xuICBjb25zdCBIRUlHSFQgPSAnaGVpZ2h0JztcbiAgY29uc3QgU0VMRUNUT1JfQUNUSVZFUyA9ICcuY29sbGFwc2Uuc2hvdywgLmNvbGxhcHNlLmNvbGxhcHNpbmcnO1xuICBjb25zdCBTRUxFQ1RPUl9EQVRBX1RPR0dMRSQ0ID0gJ1tkYXRhLWJzLXRvZ2dsZT1cImNvbGxhcHNlXCJdJztcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICBjbGFzcyBDb2xsYXBzZSBleHRlbmRzIEJhc2VDb21wb25lbnQge1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQsIGNvbmZpZykge1xuICAgICAgc3VwZXIoZWxlbWVudCk7XG4gICAgICB0aGlzLl9pc1RyYW5zaXRpb25pbmcgPSBmYWxzZTtcbiAgICAgIHRoaXMuX2NvbmZpZyA9IHRoaXMuX2dldENvbmZpZyhjb25maWcpO1xuICAgICAgdGhpcy5fdHJpZ2dlckFycmF5ID0gW107XG4gICAgICBjb25zdCB0b2dnbGVMaXN0ID0gU2VsZWN0b3JFbmdpbmUuZmluZChTRUxFQ1RPUl9EQVRBX1RPR0dMRSQ0KTtcblxuICAgICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IHRvZ2dsZUxpc3QubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgY29uc3QgZWxlbSA9IHRvZ2dsZUxpc3RbaV07XG4gICAgICAgIGNvbnN0IHNlbGVjdG9yID0gZ2V0U2VsZWN0b3JGcm9tRWxlbWVudChlbGVtKTtcbiAgICAgICAgY29uc3QgZmlsdGVyRWxlbWVudCA9IFNlbGVjdG9yRW5naW5lLmZpbmQoc2VsZWN0b3IpLmZpbHRlcihmb3VuZEVsZW0gPT4gZm91bmRFbGVtID09PSB0aGlzLl9lbGVtZW50KTtcblxuICAgICAgICBpZiAoc2VsZWN0b3IgIT09IG51bGwgJiYgZmlsdGVyRWxlbWVudC5sZW5ndGgpIHtcbiAgICAgICAgICB0aGlzLl9zZWxlY3RvciA9IHNlbGVjdG9yO1xuXG4gICAgICAgICAgdGhpcy5fdHJpZ2dlckFycmF5LnB1c2goZWxlbSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy5faW5pdGlhbGl6ZUNoaWxkcmVuKCk7XG5cbiAgICAgIGlmICghdGhpcy5fY29uZmlnLnBhcmVudCkge1xuICAgICAgICB0aGlzLl9hZGRBcmlhQW5kQ29sbGFwc2VkQ2xhc3ModGhpcy5fdHJpZ2dlckFycmF5LCB0aGlzLl9pc1Nob3duKCkpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5fY29uZmlnLnRvZ2dsZSkge1xuICAgICAgICB0aGlzLnRvZ2dsZSgpO1xuICAgICAgfVxuICAgIH0gLy8gR2V0dGVyc1xuXG5cbiAgICBzdGF0aWMgZ2V0IERlZmF1bHQoKSB7XG4gICAgICByZXR1cm4gRGVmYXVsdCQ5O1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXQgTkFNRSgpIHtcbiAgICAgIHJldHVybiBOQU1FJGE7XG4gICAgfSAvLyBQdWJsaWNcblxuXG4gICAgdG9nZ2xlKCkge1xuICAgICAgaWYgKHRoaXMuX2lzU2hvd24oKSkge1xuICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHNob3coKSB7XG4gICAgICBpZiAodGhpcy5faXNUcmFuc2l0aW9uaW5nIHx8IHRoaXMuX2lzU2hvd24oKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGxldCBhY3RpdmVzID0gW107XG4gICAgICBsZXQgYWN0aXZlc0RhdGE7XG5cbiAgICAgIGlmICh0aGlzLl9jb25maWcucGFyZW50KSB7XG4gICAgICAgIGNvbnN0IGNoaWxkcmVuID0gU2VsZWN0b3JFbmdpbmUuZmluZChDTEFTU19OQU1FX0RFRVBFUl9DSElMRFJFTiwgdGhpcy5fY29uZmlnLnBhcmVudCk7XG4gICAgICAgIGFjdGl2ZXMgPSBTZWxlY3RvckVuZ2luZS5maW5kKFNFTEVDVE9SX0FDVElWRVMsIHRoaXMuX2NvbmZpZy5wYXJlbnQpLmZpbHRlcihlbGVtID0+ICFjaGlsZHJlbi5pbmNsdWRlcyhlbGVtKSk7IC8vIHJlbW92ZSBjaGlsZHJlbiBpZiBncmVhdGVyIGRlcHRoXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNvbnRhaW5lciA9IFNlbGVjdG9yRW5naW5lLmZpbmRPbmUodGhpcy5fc2VsZWN0b3IpO1xuXG4gICAgICBpZiAoYWN0aXZlcy5sZW5ndGgpIHtcbiAgICAgICAgY29uc3QgdGVtcEFjdGl2ZURhdGEgPSBhY3RpdmVzLmZpbmQoZWxlbSA9PiBjb250YWluZXIgIT09IGVsZW0pO1xuICAgICAgICBhY3RpdmVzRGF0YSA9IHRlbXBBY3RpdmVEYXRhID8gQ29sbGFwc2UuZ2V0SW5zdGFuY2UodGVtcEFjdGl2ZURhdGEpIDogbnVsbDtcblxuICAgICAgICBpZiAoYWN0aXZlc0RhdGEgJiYgYWN0aXZlc0RhdGEuX2lzVHJhbnNpdGlvbmluZykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBzdGFydEV2ZW50ID0gRXZlbnRIYW5kbGVyLnRyaWdnZXIodGhpcy5fZWxlbWVudCwgRVZFTlRfU0hPVyQ1KTtcblxuICAgICAgaWYgKHN0YXJ0RXZlbnQuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGFjdGl2ZXMuZm9yRWFjaChlbGVtQWN0aXZlID0+IHtcbiAgICAgICAgaWYgKGNvbnRhaW5lciAhPT0gZWxlbUFjdGl2ZSkge1xuICAgICAgICAgIENvbGxhcHNlLmdldE9yQ3JlYXRlSW5zdGFuY2UoZWxlbUFjdGl2ZSwge1xuICAgICAgICAgICAgdG9nZ2xlOiBmYWxzZVxuICAgICAgICAgIH0pLmhpZGUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghYWN0aXZlc0RhdGEpIHtcbiAgICAgICAgICBEYXRhLnNldChlbGVtQWN0aXZlLCBEQVRBX0tFWSQ5LCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGRpbWVuc2lvbiA9IHRoaXMuX2dldERpbWVuc2lvbigpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoQ0xBU1NfTkFNRV9DT0xMQVBTRSk7XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmFkZChDTEFTU19OQU1FX0NPTExBUFNJTkcpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LnN0eWxlW2RpbWVuc2lvbl0gPSAwO1xuXG4gICAgICB0aGlzLl9hZGRBcmlhQW5kQ29sbGFwc2VkQ2xhc3ModGhpcy5fdHJpZ2dlckFycmF5LCB0cnVlKTtcblxuICAgICAgdGhpcy5faXNUcmFuc2l0aW9uaW5nID0gdHJ1ZTtcblxuICAgICAgY29uc3QgY29tcGxldGUgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMuX2lzVHJhbnNpdGlvbmluZyA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShDTEFTU19OQU1FX0NPTExBUFNJTkcpO1xuXG4gICAgICAgIHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmFkZChDTEFTU19OQU1FX0NPTExBUFNFLCBDTEFTU19OQU1FX1NIT1ckNyk7XG5cbiAgICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZVtkaW1lbnNpb25dID0gJyc7XG4gICAgICAgIEV2ZW50SGFuZGxlci50cmlnZ2VyKHRoaXMuX2VsZW1lbnQsIEVWRU5UX1NIT1dOJDUpO1xuICAgICAgfTtcblxuICAgICAgY29uc3QgY2FwaXRhbGl6ZWREaW1lbnNpb24gPSBkaW1lbnNpb25bMF0udG9VcHBlckNhc2UoKSArIGRpbWVuc2lvbi5zbGljZSgxKTtcbiAgICAgIGNvbnN0IHNjcm9sbFNpemUgPSBgc2Nyb2xsJHtjYXBpdGFsaXplZERpbWVuc2lvbn1gO1xuXG4gICAgICB0aGlzLl9xdWV1ZUNhbGxiYWNrKGNvbXBsZXRlLCB0aGlzLl9lbGVtZW50LCB0cnVlKTtcblxuICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZVtkaW1lbnNpb25dID0gYCR7dGhpcy5fZWxlbWVudFtzY3JvbGxTaXplXX1weGA7XG4gICAgfVxuXG4gICAgaGlkZSgpIHtcbiAgICAgIGlmICh0aGlzLl9pc1RyYW5zaXRpb25pbmcgfHwgIXRoaXMuX2lzU2hvd24oKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHN0YXJ0RXZlbnQgPSBFdmVudEhhbmRsZXIudHJpZ2dlcih0aGlzLl9lbGVtZW50LCBFVkVOVF9ISURFJDUpO1xuXG4gICAgICBpZiAoc3RhcnRFdmVudC5kZWZhdWx0UHJldmVudGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGltZW5zaW9uID0gdGhpcy5fZ2V0RGltZW5zaW9uKCk7XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGVbZGltZW5zaW9uXSA9IGAke3RoaXMuX2VsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClbZGltZW5zaW9uXX1weGA7XG4gICAgICByZWZsb3codGhpcy5fZWxlbWVudCk7XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmFkZChDTEFTU19OQU1FX0NPTExBUFNJTkcpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoQ0xBU1NfTkFNRV9DT0xMQVBTRSwgQ0xBU1NfTkFNRV9TSE9XJDcpO1xuXG4gICAgICBjb25zdCB0cmlnZ2VyQXJyYXlMZW5ndGggPSB0aGlzLl90cmlnZ2VyQXJyYXkubGVuZ3RoO1xuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRyaWdnZXJBcnJheUxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHRyaWdnZXIgPSB0aGlzLl90cmlnZ2VyQXJyYXlbaV07XG4gICAgICAgIGNvbnN0IGVsZW0gPSBnZXRFbGVtZW50RnJvbVNlbGVjdG9yKHRyaWdnZXIpO1xuXG4gICAgICAgIGlmIChlbGVtICYmICF0aGlzLl9pc1Nob3duKGVsZW0pKSB7XG4gICAgICAgICAgdGhpcy5fYWRkQXJpYUFuZENvbGxhcHNlZENsYXNzKFt0cmlnZ2VyXSwgZmFsc2UpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2lzVHJhbnNpdGlvbmluZyA9IHRydWU7XG5cbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gKCkgPT4ge1xuICAgICAgICB0aGlzLl9pc1RyYW5zaXRpb25pbmcgPSBmYWxzZTtcblxuICAgICAgICB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoQ0xBU1NfTkFNRV9DT0xMQVBTSU5HKTtcblxuICAgICAgICB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9DT0xMQVBTRSk7XG5cbiAgICAgICAgRXZlbnRIYW5kbGVyLnRyaWdnZXIodGhpcy5fZWxlbWVudCwgRVZFTlRfSElEREVOJDUpO1xuICAgICAgfTtcblxuICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZVtkaW1lbnNpb25dID0gJyc7XG5cbiAgICAgIHRoaXMuX3F1ZXVlQ2FsbGJhY2soY29tcGxldGUsIHRoaXMuX2VsZW1lbnQsIHRydWUpO1xuICAgIH1cblxuICAgIF9pc1Nob3duKGVsZW1lbnQgPSB0aGlzLl9lbGVtZW50KSB7XG4gICAgICByZXR1cm4gZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoQ0xBU1NfTkFNRV9TSE9XJDcpO1xuICAgIH0gLy8gUHJpdmF0ZVxuXG5cbiAgICBfZ2V0Q29uZmlnKGNvbmZpZykge1xuICAgICAgY29uZmlnID0geyAuLi5EZWZhdWx0JDksXG4gICAgICAgIC4uLk1hbmlwdWxhdG9yLmdldERhdGFBdHRyaWJ1dGVzKHRoaXMuX2VsZW1lbnQpLFxuICAgICAgICAuLi5jb25maWdcbiAgICAgIH07XG4gICAgICBjb25maWcudG9nZ2xlID0gQm9vbGVhbihjb25maWcudG9nZ2xlKTsgLy8gQ29lcmNlIHN0cmluZyB2YWx1ZXNcblxuICAgICAgY29uZmlnLnBhcmVudCA9IGdldEVsZW1lbnQoY29uZmlnLnBhcmVudCk7XG4gICAgICB0eXBlQ2hlY2tDb25maWcoTkFNRSRhLCBjb25maWcsIERlZmF1bHRUeXBlJDkpO1xuICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICB9XG5cbiAgICBfZ2V0RGltZW5zaW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKENMQVNTX05BTUVfSE9SSVpPTlRBTCkgPyBXSURUSCA6IEhFSUdIVDtcbiAgICB9XG5cbiAgICBfaW5pdGlhbGl6ZUNoaWxkcmVuKCkge1xuICAgICAgaWYgKCF0aGlzLl9jb25maWcucGFyZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2hpbGRyZW4gPSBTZWxlY3RvckVuZ2luZS5maW5kKENMQVNTX05BTUVfREVFUEVSX0NISUxEUkVOLCB0aGlzLl9jb25maWcucGFyZW50KTtcbiAgICAgIFNlbGVjdG9yRW5naW5lLmZpbmQoU0VMRUNUT1JfREFUQV9UT0dHTEUkNCwgdGhpcy5fY29uZmlnLnBhcmVudCkuZmlsdGVyKGVsZW0gPT4gIWNoaWxkcmVuLmluY2x1ZGVzKGVsZW0pKS5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICBjb25zdCBzZWxlY3RlZCA9IGdldEVsZW1lbnRGcm9tU2VsZWN0b3IoZWxlbWVudCk7XG5cbiAgICAgICAgaWYgKHNlbGVjdGVkKSB7XG4gICAgICAgICAgdGhpcy5fYWRkQXJpYUFuZENvbGxhcHNlZENsYXNzKFtlbGVtZW50XSwgdGhpcy5faXNTaG93bihzZWxlY3RlZCkpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBfYWRkQXJpYUFuZENvbGxhcHNlZENsYXNzKHRyaWdnZXJBcnJheSwgaXNPcGVuKSB7XG4gICAgICBpZiAoIXRyaWdnZXJBcnJheS5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0cmlnZ2VyQXJyYXkuZm9yRWFjaChlbGVtID0+IHtcbiAgICAgICAgaWYgKGlzT3Blbikge1xuICAgICAgICAgIGVsZW0uY2xhc3NMaXN0LnJlbW92ZShDTEFTU19OQU1FX0NPTExBUFNFRCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZWxlbS5jbGFzc0xpc3QuYWRkKENMQVNTX05BTUVfQ09MTEFQU0VEKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGVsZW0uc2V0QXR0cmlidXRlKCdhcmlhLWV4cGFuZGVkJywgaXNPcGVuKTtcbiAgICAgIH0pO1xuICAgIH0gLy8gU3RhdGljXG5cblxuICAgIHN0YXRpYyBqUXVlcnlJbnRlcmZhY2UoY29uZmlnKSB7XG4gICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgX2NvbmZpZyA9IHt9O1xuXG4gICAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnc3RyaW5nJyAmJiAvc2hvd3xoaWRlLy50ZXN0KGNvbmZpZykpIHtcbiAgICAgICAgICBfY29uZmlnLnRvZ2dsZSA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZGF0YSA9IENvbGxhcHNlLmdldE9yQ3JlYXRlSW5zdGFuY2UodGhpcywgX2NvbmZpZyk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2NvbmZpZ10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBObyBtZXRob2QgbmFtZWQgXCIke2NvbmZpZ31cImApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGRhdGFbY29uZmlnXSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgfVxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIERhdGEgQXBpIGltcGxlbWVudGF0aW9uXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuXG4gIEV2ZW50SGFuZGxlci5vbihkb2N1bWVudCwgRVZFTlRfQ0xJQ0tfREFUQV9BUEkkNCwgU0VMRUNUT1JfREFUQV9UT0dHTEUkNCwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgLy8gcHJldmVudERlZmF1bHQgb25seSBmb3IgPGE+IGVsZW1lbnRzICh3aGljaCBjaGFuZ2UgdGhlIFVSTCkgbm90IGluc2lkZSB0aGUgY29sbGFwc2libGUgZWxlbWVudFxuICAgIGlmIChldmVudC50YXJnZXQudGFnTmFtZSA9PT0gJ0EnIHx8IGV2ZW50LmRlbGVnYXRlVGFyZ2V0ICYmIGV2ZW50LmRlbGVnYXRlVGFyZ2V0LnRhZ05hbWUgPT09ICdBJykge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG5cbiAgICBjb25zdCBzZWxlY3RvciA9IGdldFNlbGVjdG9yRnJvbUVsZW1lbnQodGhpcyk7XG4gICAgY29uc3Qgc2VsZWN0b3JFbGVtZW50cyA9IFNlbGVjdG9yRW5naW5lLmZpbmQoc2VsZWN0b3IpO1xuICAgIHNlbGVjdG9yRWxlbWVudHMuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgIENvbGxhcHNlLmdldE9yQ3JlYXRlSW5zdGFuY2UoZWxlbWVudCwge1xuICAgICAgICB0b2dnbGU6IGZhbHNlXG4gICAgICB9KS50b2dnbGUoKTtcbiAgICB9KTtcbiAgfSk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogalF1ZXJ5XG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBhZGQgLkNvbGxhcHNlIHRvIGpRdWVyeSBvbmx5IGlmIGpRdWVyeSBpcyBwcmVzZW50XG4gICAqL1xuXG4gIGRlZmluZUpRdWVyeVBsdWdpbihDb2xsYXBzZSk7XG5cbiAgdmFyIHRvcCA9ICd0b3AnO1xuICB2YXIgYm90dG9tID0gJ2JvdHRvbSc7XG4gIHZhciByaWdodCA9ICdyaWdodCc7XG4gIHZhciBsZWZ0ID0gJ2xlZnQnO1xuICB2YXIgYXV0byA9ICdhdXRvJztcbiAgdmFyIGJhc2VQbGFjZW1lbnRzID0gW3RvcCwgYm90dG9tLCByaWdodCwgbGVmdF07XG4gIHZhciBzdGFydCA9ICdzdGFydCc7XG4gIHZhciBlbmQgPSAnZW5kJztcbiAgdmFyIGNsaXBwaW5nUGFyZW50cyA9ICdjbGlwcGluZ1BhcmVudHMnO1xuICB2YXIgdmlld3BvcnQgPSAndmlld3BvcnQnO1xuICB2YXIgcG9wcGVyID0gJ3BvcHBlcic7XG4gIHZhciByZWZlcmVuY2UgPSAncmVmZXJlbmNlJztcbiAgdmFyIHZhcmlhdGlvblBsYWNlbWVudHMgPSAvKiNfX1BVUkVfXyovYmFzZVBsYWNlbWVudHMucmVkdWNlKGZ1bmN0aW9uIChhY2MsIHBsYWNlbWVudCkge1xuICAgIHJldHVybiBhY2MuY29uY2F0KFtwbGFjZW1lbnQgKyBcIi1cIiArIHN0YXJ0LCBwbGFjZW1lbnQgKyBcIi1cIiArIGVuZF0pO1xuICB9LCBbXSk7XG4gIHZhciBwbGFjZW1lbnRzID0gLyojX19QVVJFX18qL1tdLmNvbmNhdChiYXNlUGxhY2VtZW50cywgW2F1dG9dKS5yZWR1Y2UoZnVuY3Rpb24gKGFjYywgcGxhY2VtZW50KSB7XG4gICAgcmV0dXJuIGFjYy5jb25jYXQoW3BsYWNlbWVudCwgcGxhY2VtZW50ICsgXCItXCIgKyBzdGFydCwgcGxhY2VtZW50ICsgXCItXCIgKyBlbmRdKTtcbiAgfSwgW10pOyAvLyBtb2RpZmllcnMgdGhhdCBuZWVkIHRvIHJlYWQgdGhlIERPTVxuXG4gIHZhciBiZWZvcmVSZWFkID0gJ2JlZm9yZVJlYWQnO1xuICB2YXIgcmVhZCA9ICdyZWFkJztcbiAgdmFyIGFmdGVyUmVhZCA9ICdhZnRlclJlYWQnOyAvLyBwdXJlLWxvZ2ljIG1vZGlmaWVyc1xuXG4gIHZhciBiZWZvcmVNYWluID0gJ2JlZm9yZU1haW4nO1xuICB2YXIgbWFpbiA9ICdtYWluJztcbiAgdmFyIGFmdGVyTWFpbiA9ICdhZnRlck1haW4nOyAvLyBtb2RpZmllciB3aXRoIHRoZSBwdXJwb3NlIHRvIHdyaXRlIHRvIHRoZSBET00gKG9yIHdyaXRlIGludG8gYSBmcmFtZXdvcmsgc3RhdGUpXG5cbiAgdmFyIGJlZm9yZVdyaXRlID0gJ2JlZm9yZVdyaXRlJztcbiAgdmFyIHdyaXRlID0gJ3dyaXRlJztcbiAgdmFyIGFmdGVyV3JpdGUgPSAnYWZ0ZXJXcml0ZSc7XG4gIHZhciBtb2RpZmllclBoYXNlcyA9IFtiZWZvcmVSZWFkLCByZWFkLCBhZnRlclJlYWQsIGJlZm9yZU1haW4sIG1haW4sIGFmdGVyTWFpbiwgYmVmb3JlV3JpdGUsIHdyaXRlLCBhZnRlcldyaXRlXTtcblxuICBmdW5jdGlvbiBnZXROb2RlTmFtZShlbGVtZW50KSB7XG4gICAgcmV0dXJuIGVsZW1lbnQgPyAoZWxlbWVudC5ub2RlTmFtZSB8fCAnJykudG9Mb3dlckNhc2UoKSA6IG51bGw7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRXaW5kb3cobm9kZSkge1xuICAgIGlmIChub2RlID09IG51bGwpIHtcbiAgICAgIHJldHVybiB3aW5kb3c7XG4gICAgfVxuXG4gICAgaWYgKG5vZGUudG9TdHJpbmcoKSAhPT0gJ1tvYmplY3QgV2luZG93XScpIHtcbiAgICAgIHZhciBvd25lckRvY3VtZW50ID0gbm9kZS5vd25lckRvY3VtZW50O1xuICAgICAgcmV0dXJuIG93bmVyRG9jdW1lbnQgPyBvd25lckRvY3VtZW50LmRlZmF1bHRWaWV3IHx8IHdpbmRvdyA6IHdpbmRvdztcbiAgICB9XG5cbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzRWxlbWVudChub2RlKSB7XG4gICAgdmFyIE93bkVsZW1lbnQgPSBnZXRXaW5kb3cobm9kZSkuRWxlbWVudDtcbiAgICByZXR1cm4gbm9kZSBpbnN0YW5jZW9mIE93bkVsZW1lbnQgfHwgbm9kZSBpbnN0YW5jZW9mIEVsZW1lbnQ7XG4gIH1cblxuICBmdW5jdGlvbiBpc0hUTUxFbGVtZW50KG5vZGUpIHtcbiAgICB2YXIgT3duRWxlbWVudCA9IGdldFdpbmRvdyhub2RlKS5IVE1MRWxlbWVudDtcbiAgICByZXR1cm4gbm9kZSBpbnN0YW5jZW9mIE93bkVsZW1lbnQgfHwgbm9kZSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50O1xuICB9XG5cbiAgZnVuY3Rpb24gaXNTaGFkb3dSb290KG5vZGUpIHtcbiAgICAvLyBJRSAxMSBoYXMgbm8gU2hhZG93Um9vdFxuICAgIGlmICh0eXBlb2YgU2hhZG93Um9vdCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB2YXIgT3duRWxlbWVudCA9IGdldFdpbmRvdyhub2RlKS5TaGFkb3dSb290O1xuICAgIHJldHVybiBub2RlIGluc3RhbmNlb2YgT3duRWxlbWVudCB8fCBub2RlIGluc3RhbmNlb2YgU2hhZG93Um9vdDtcbiAgfVxuXG4gIC8vIGFuZCBhcHBsaWVzIHRoZW0gdG8gdGhlIEhUTUxFbGVtZW50cyBzdWNoIGFzIHBvcHBlciBhbmQgYXJyb3dcblxuICBmdW5jdGlvbiBhcHBseVN0eWxlcyhfcmVmKSB7XG4gICAgdmFyIHN0YXRlID0gX3JlZi5zdGF0ZTtcbiAgICBPYmplY3Qua2V5cyhzdGF0ZS5lbGVtZW50cykuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgdmFyIHN0eWxlID0gc3RhdGUuc3R5bGVzW25hbWVdIHx8IHt9O1xuICAgICAgdmFyIGF0dHJpYnV0ZXMgPSBzdGF0ZS5hdHRyaWJ1dGVzW25hbWVdIHx8IHt9O1xuICAgICAgdmFyIGVsZW1lbnQgPSBzdGF0ZS5lbGVtZW50c1tuYW1lXTsgLy8gYXJyb3cgaXMgb3B0aW9uYWwgKyB2aXJ0dWFsIGVsZW1lbnRzXG5cbiAgICAgIGlmICghaXNIVE1MRWxlbWVudChlbGVtZW50KSB8fCAhZ2V0Tm9kZU5hbWUoZWxlbWVudCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSAvLyBGbG93IGRvZXNuJ3Qgc3VwcG9ydCB0byBleHRlbmQgdGhpcyBwcm9wZXJ0eSwgYnV0IGl0J3MgdGhlIG1vc3RcbiAgICAgIC8vIGVmZmVjdGl2ZSB3YXkgdG8gYXBwbHkgc3R5bGVzIHRvIGFuIEhUTUxFbGVtZW50XG4gICAgICAvLyAkRmxvd0ZpeE1lW2Nhbm5vdC13cml0ZV1cblxuXG4gICAgICBPYmplY3QuYXNzaWduKGVsZW1lbnQuc3R5bGUsIHN0eWxlKTtcbiAgICAgIE9iamVjdC5rZXlzKGF0dHJpYnV0ZXMpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXR0cmlidXRlc1tuYW1lXTtcblxuICAgICAgICBpZiAodmFsdWUgPT09IGZhbHNlKSB7XG4gICAgICAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUobmFtZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUobmFtZSwgdmFsdWUgPT09IHRydWUgPyAnJyA6IHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBlZmZlY3QkMihfcmVmMikge1xuICAgIHZhciBzdGF0ZSA9IF9yZWYyLnN0YXRlO1xuICAgIHZhciBpbml0aWFsU3R5bGVzID0ge1xuICAgICAgcG9wcGVyOiB7XG4gICAgICAgIHBvc2l0aW9uOiBzdGF0ZS5vcHRpb25zLnN0cmF0ZWd5LFxuICAgICAgICBsZWZ0OiAnMCcsXG4gICAgICAgIHRvcDogJzAnLFxuICAgICAgICBtYXJnaW46ICcwJ1xuICAgICAgfSxcbiAgICAgIGFycm93OiB7XG4gICAgICAgIHBvc2l0aW9uOiAnYWJzb2x1dGUnXG4gICAgICB9LFxuICAgICAgcmVmZXJlbmNlOiB7fVxuICAgIH07XG4gICAgT2JqZWN0LmFzc2lnbihzdGF0ZS5lbGVtZW50cy5wb3BwZXIuc3R5bGUsIGluaXRpYWxTdHlsZXMucG9wcGVyKTtcbiAgICBzdGF0ZS5zdHlsZXMgPSBpbml0aWFsU3R5bGVzO1xuXG4gICAgaWYgKHN0YXRlLmVsZW1lbnRzLmFycm93KSB7XG4gICAgICBPYmplY3QuYXNzaWduKHN0YXRlLmVsZW1lbnRzLmFycm93LnN0eWxlLCBpbml0aWFsU3R5bGVzLmFycm93KTtcbiAgICB9XG5cbiAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgT2JqZWN0LmtleXMoc3RhdGUuZWxlbWVudHMpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgdmFyIGVsZW1lbnQgPSBzdGF0ZS5lbGVtZW50c1tuYW1lXTtcbiAgICAgICAgdmFyIGF0dHJpYnV0ZXMgPSBzdGF0ZS5hdHRyaWJ1dGVzW25hbWVdIHx8IHt9O1xuICAgICAgICB2YXIgc3R5bGVQcm9wZXJ0aWVzID0gT2JqZWN0LmtleXMoc3RhdGUuc3R5bGVzLmhhc093blByb3BlcnR5KG5hbWUpID8gc3RhdGUuc3R5bGVzW25hbWVdIDogaW5pdGlhbFN0eWxlc1tuYW1lXSk7IC8vIFNldCBhbGwgdmFsdWVzIHRvIGFuIGVtcHR5IHN0cmluZyB0byB1bnNldCB0aGVtXG5cbiAgICAgICAgdmFyIHN0eWxlID0gc3R5bGVQcm9wZXJ0aWVzLnJlZHVjZShmdW5jdGlvbiAoc3R5bGUsIHByb3BlcnR5KSB7XG4gICAgICAgICAgc3R5bGVbcHJvcGVydHldID0gJyc7XG4gICAgICAgICAgcmV0dXJuIHN0eWxlO1xuICAgICAgICB9LCB7fSk7IC8vIGFycm93IGlzIG9wdGlvbmFsICsgdmlydHVhbCBlbGVtZW50c1xuXG4gICAgICAgIGlmICghaXNIVE1MRWxlbWVudChlbGVtZW50KSB8fCAhZ2V0Tm9kZU5hbWUoZWxlbWVudCkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBPYmplY3QuYXNzaWduKGVsZW1lbnQuc3R5bGUsIHN0eWxlKTtcbiAgICAgICAgT2JqZWN0LmtleXMoYXR0cmlidXRlcykuZm9yRWFjaChmdW5jdGlvbiAoYXR0cmlidXRlKSB7XG4gICAgICAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoYXR0cmlidXRlKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9O1xuICB9IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tdW51c2VkLW1vZHVsZXNcblxuXG4gIGNvbnN0IGFwcGx5U3R5bGVzJDEgPSB7XG4gICAgbmFtZTogJ2FwcGx5U3R5bGVzJyxcbiAgICBlbmFibGVkOiB0cnVlLFxuICAgIHBoYXNlOiAnd3JpdGUnLFxuICAgIGZuOiBhcHBseVN0eWxlcyxcbiAgICBlZmZlY3Q6IGVmZmVjdCQyLFxuICAgIHJlcXVpcmVzOiBbJ2NvbXB1dGVTdHlsZXMnXVxuICB9O1xuXG4gIGZ1bmN0aW9uIGdldEJhc2VQbGFjZW1lbnQocGxhY2VtZW50KSB7XG4gICAgcmV0dXJuIHBsYWNlbWVudC5zcGxpdCgnLScpWzBdO1xuICB9XG5cbiAgLy8gaW1wb3J0IHsgaXNIVE1MRWxlbWVudCB9IGZyb20gJy4vaW5zdGFuY2VPZic7XG4gIGZ1bmN0aW9uIGdldEJvdW5kaW5nQ2xpZW50UmVjdChlbGVtZW50LCAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgdW51c2VkLWltcG9ydHMvbm8tdW51c2VkLXZhcnNcbiAgaW5jbHVkZVNjYWxlKSB7XG5cbiAgICB2YXIgcmVjdCA9IGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgdmFyIHNjYWxlWCA9IDE7XG4gICAgdmFyIHNjYWxlWSA9IDE7IC8vIEZJWE1FOlxuICAgIC8vIGBvZmZzZXRXaWR0aGAgcmV0dXJucyBhbiBpbnRlZ2VyIHdoaWxlIGBnZXRCb3VuZGluZ0NsaWVudFJlY3RgXG4gICAgLy8gcmV0dXJucyBhIGZsb2F0LiBUaGlzIHJlc3VsdHMgaW4gYHNjYWxlWGAgb3IgYHNjYWxlWWAgYmVpbmdcbiAgICAvLyBub24tMSB3aGVuIGl0IHNob3VsZCBiZSBmb3IgZWxlbWVudHMgdGhhdCBhcmVuJ3QgYSBmdWxsIHBpeGVsIGluXG4gICAgLy8gd2lkdGggb3IgaGVpZ2h0LlxuICAgIC8vIGlmIChpc0hUTUxFbGVtZW50KGVsZW1lbnQpICYmIGluY2x1ZGVTY2FsZSkge1xuICAgIC8vICAgY29uc3Qgb2Zmc2V0SGVpZ2h0ID0gZWxlbWVudC5vZmZzZXRIZWlnaHQ7XG4gICAgLy8gICBjb25zdCBvZmZzZXRXaWR0aCA9IGVsZW1lbnQub2Zmc2V0V2lkdGg7XG4gICAgLy8gICAvLyBEbyBub3QgYXR0ZW1wdCB0byBkaXZpZGUgYnkgMCwgb3RoZXJ3aXNlIHdlIGdldCBgSW5maW5pdHlgIGFzIHNjYWxlXG4gICAgLy8gICAvLyBGYWxsYmFjayB0byAxIGluIGNhc2UgYm90aCB2YWx1ZXMgYXJlIGAwYFxuICAgIC8vICAgaWYgKG9mZnNldFdpZHRoID4gMCkge1xuICAgIC8vICAgICBzY2FsZVggPSByZWN0LndpZHRoIC8gb2Zmc2V0V2lkdGggfHwgMTtcbiAgICAvLyAgIH1cbiAgICAvLyAgIGlmIChvZmZzZXRIZWlnaHQgPiAwKSB7XG4gICAgLy8gICAgIHNjYWxlWSA9IHJlY3QuaGVpZ2h0IC8gb2Zmc2V0SGVpZ2h0IHx8IDE7XG4gICAgLy8gICB9XG4gICAgLy8gfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHdpZHRoOiByZWN0LndpZHRoIC8gc2NhbGVYLFxuICAgICAgaGVpZ2h0OiByZWN0LmhlaWdodCAvIHNjYWxlWSxcbiAgICAgIHRvcDogcmVjdC50b3AgLyBzY2FsZVksXG4gICAgICByaWdodDogcmVjdC5yaWdodCAvIHNjYWxlWCxcbiAgICAgIGJvdHRvbTogcmVjdC5ib3R0b20gLyBzY2FsZVksXG4gICAgICBsZWZ0OiByZWN0LmxlZnQgLyBzY2FsZVgsXG4gICAgICB4OiByZWN0LmxlZnQgLyBzY2FsZVgsXG4gICAgICB5OiByZWN0LnRvcCAvIHNjYWxlWVxuICAgIH07XG4gIH1cblxuICAvLyBtZWFucyBpdCBkb2Vzbid0IHRha2UgaW50byBhY2NvdW50IHRyYW5zZm9ybXMuXG5cbiAgZnVuY3Rpb24gZ2V0TGF5b3V0UmVjdChlbGVtZW50KSB7XG4gICAgdmFyIGNsaWVudFJlY3QgPSBnZXRCb3VuZGluZ0NsaWVudFJlY3QoZWxlbWVudCk7IC8vIFVzZSB0aGUgY2xpZW50UmVjdCBzaXplcyBpZiBpdCdzIG5vdCBiZWVuIHRyYW5zZm9ybWVkLlxuICAgIC8vIEZpeGVzIGh0dHBzOi8vZ2l0aHViLmNvbS9wb3BwZXJqcy9wb3BwZXItY29yZS9pc3N1ZXMvMTIyM1xuXG4gICAgdmFyIHdpZHRoID0gZWxlbWVudC5vZmZzZXRXaWR0aDtcbiAgICB2YXIgaGVpZ2h0ID0gZWxlbWVudC5vZmZzZXRIZWlnaHQ7XG5cbiAgICBpZiAoTWF0aC5hYnMoY2xpZW50UmVjdC53aWR0aCAtIHdpZHRoKSA8PSAxKSB7XG4gICAgICB3aWR0aCA9IGNsaWVudFJlY3Qud2lkdGg7XG4gICAgfVxuXG4gICAgaWYgKE1hdGguYWJzKGNsaWVudFJlY3QuaGVpZ2h0IC0gaGVpZ2h0KSA8PSAxKSB7XG4gICAgICBoZWlnaHQgPSBjbGllbnRSZWN0LmhlaWdodDtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgeDogZWxlbWVudC5vZmZzZXRMZWZ0LFxuICAgICAgeTogZWxlbWVudC5vZmZzZXRUb3AsXG4gICAgICB3aWR0aDogd2lkdGgsXG4gICAgICBoZWlnaHQ6IGhlaWdodFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBjb250YWlucyhwYXJlbnQsIGNoaWxkKSB7XG4gICAgdmFyIHJvb3ROb2RlID0gY2hpbGQuZ2V0Um9vdE5vZGUgJiYgY2hpbGQuZ2V0Um9vdE5vZGUoKTsgLy8gRmlyc3QsIGF0dGVtcHQgd2l0aCBmYXN0ZXIgbmF0aXZlIG1ldGhvZFxuXG4gICAgaWYgKHBhcmVudC5jb250YWlucyhjaGlsZCkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gLy8gdGhlbiBmYWxsYmFjayB0byBjdXN0b20gaW1wbGVtZW50YXRpb24gd2l0aCBTaGFkb3cgRE9NIHN1cHBvcnRcbiAgICBlbHNlIGlmIChyb290Tm9kZSAmJiBpc1NoYWRvd1Jvb3Qocm9vdE5vZGUpKSB7XG4gICAgICAgIHZhciBuZXh0ID0gY2hpbGQ7XG5cbiAgICAgICAgZG8ge1xuICAgICAgICAgIGlmIChuZXh0ICYmIHBhcmVudC5pc1NhbWVOb2RlKG5leHQpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9IC8vICRGbG93Rml4TWVbcHJvcC1taXNzaW5nXTogbmVlZCBhIGJldHRlciB3YXkgdG8gaGFuZGxlIHRoaXMuLi5cblxuXG4gICAgICAgICAgbmV4dCA9IG5leHQucGFyZW50Tm9kZSB8fCBuZXh0Lmhvc3Q7XG4gICAgICAgIH0gd2hpbGUgKG5leHQpO1xuICAgICAgfSAvLyBHaXZlIHVwLCB0aGUgcmVzdWx0IGlzIGZhbHNlXG5cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldENvbXB1dGVkU3R5bGUkMShlbGVtZW50KSB7XG4gICAgcmV0dXJuIGdldFdpbmRvdyhlbGVtZW50KS5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpO1xuICB9XG5cbiAgZnVuY3Rpb24gaXNUYWJsZUVsZW1lbnQoZWxlbWVudCkge1xuICAgIHJldHVybiBbJ3RhYmxlJywgJ3RkJywgJ3RoJ10uaW5kZXhPZihnZXROb2RlTmFtZShlbGVtZW50KSkgPj0gMDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldERvY3VtZW50RWxlbWVudChlbGVtZW50KSB7XG4gICAgLy8gJEZsb3dGaXhNZVtpbmNvbXBhdGlibGUtcmV0dXJuXTogYXNzdW1lIGJvZHkgaXMgYWx3YXlzIGF2YWlsYWJsZVxuICAgIHJldHVybiAoKGlzRWxlbWVudChlbGVtZW50KSA/IGVsZW1lbnQub3duZXJEb2N1bWVudCA6IC8vICRGbG93Rml4TWVbcHJvcC1taXNzaW5nXVxuICAgIGVsZW1lbnQuZG9jdW1lbnQpIHx8IHdpbmRvdy5kb2N1bWVudCkuZG9jdW1lbnRFbGVtZW50O1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0UGFyZW50Tm9kZShlbGVtZW50KSB7XG4gICAgaWYgKGdldE5vZGVOYW1lKGVsZW1lbnQpID09PSAnaHRtbCcpIHtcbiAgICAgIHJldHVybiBlbGVtZW50O1xuICAgIH1cblxuICAgIHJldHVybiAoLy8gdGhpcyBpcyBhIHF1aWNrZXIgKGJ1dCBsZXNzIHR5cGUgc2FmZSkgd2F5IHRvIHNhdmUgcXVpdGUgc29tZSBieXRlcyBmcm9tIHRoZSBidW5kbGVcbiAgICAgIC8vICRGbG93Rml4TWVbaW5jb21wYXRpYmxlLXJldHVybl1cbiAgICAgIC8vICRGbG93Rml4TWVbcHJvcC1taXNzaW5nXVxuICAgICAgZWxlbWVudC5hc3NpZ25lZFNsb3QgfHwgLy8gc3RlcCBpbnRvIHRoZSBzaGFkb3cgRE9NIG9mIHRoZSBwYXJlbnQgb2YgYSBzbG90dGVkIG5vZGVcbiAgICAgIGVsZW1lbnQucGFyZW50Tm9kZSB8fCAoIC8vIERPTSBFbGVtZW50IGRldGVjdGVkXG4gICAgICBpc1NoYWRvd1Jvb3QoZWxlbWVudCkgPyBlbGVtZW50Lmhvc3QgOiBudWxsKSB8fCAvLyBTaGFkb3dSb290IGRldGVjdGVkXG4gICAgICAvLyAkRmxvd0ZpeE1lW2luY29tcGF0aWJsZS1jYWxsXTogSFRNTEVsZW1lbnQgaXMgYSBOb2RlXG4gICAgICBnZXREb2N1bWVudEVsZW1lbnQoZWxlbWVudCkgLy8gZmFsbGJhY2tcblxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRUcnVlT2Zmc2V0UGFyZW50KGVsZW1lbnQpIHtcbiAgICBpZiAoIWlzSFRNTEVsZW1lbnQoZWxlbWVudCkgfHwgLy8gaHR0cHM6Ly9naXRodWIuY29tL3BvcHBlcmpzL3BvcHBlci1jb3JlL2lzc3Vlcy84MzdcbiAgICBnZXRDb21wdXRlZFN0eWxlJDEoZWxlbWVudCkucG9zaXRpb24gPT09ICdmaXhlZCcpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiBlbGVtZW50Lm9mZnNldFBhcmVudDtcbiAgfSAvLyBgLm9mZnNldFBhcmVudGAgcmVwb3J0cyBgbnVsbGAgZm9yIGZpeGVkIGVsZW1lbnRzLCB3aGlsZSBhYnNvbHV0ZSBlbGVtZW50c1xuICAvLyByZXR1cm4gdGhlIGNvbnRhaW5pbmcgYmxvY2tcblxuXG4gIGZ1bmN0aW9uIGdldENvbnRhaW5pbmdCbG9jayhlbGVtZW50KSB7XG4gICAgdmFyIGlzRmlyZWZveCA9IG5hdmlnYXRvci51c2VyQWdlbnQudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xO1xuICAgIHZhciBpc0lFID0gbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCdUcmlkZW50JykgIT09IC0xO1xuXG4gICAgaWYgKGlzSUUgJiYgaXNIVE1MRWxlbWVudChlbGVtZW50KSkge1xuICAgICAgLy8gSW4gSUUgOSwgMTAgYW5kIDExIGZpeGVkIGVsZW1lbnRzIGNvbnRhaW5pbmcgYmxvY2sgaXMgYWx3YXlzIGVzdGFibGlzaGVkIGJ5IHRoZSB2aWV3cG9ydFxuICAgICAgdmFyIGVsZW1lbnRDc3MgPSBnZXRDb21wdXRlZFN0eWxlJDEoZWxlbWVudCk7XG5cbiAgICAgIGlmIChlbGVtZW50Q3NzLnBvc2l0aW9uID09PSAnZml4ZWQnKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBjdXJyZW50Tm9kZSA9IGdldFBhcmVudE5vZGUoZWxlbWVudCk7XG5cbiAgICB3aGlsZSAoaXNIVE1MRWxlbWVudChjdXJyZW50Tm9kZSkgJiYgWydodG1sJywgJ2JvZHknXS5pbmRleE9mKGdldE5vZGVOYW1lKGN1cnJlbnROb2RlKSkgPCAwKSB7XG4gICAgICB2YXIgY3NzID0gZ2V0Q29tcHV0ZWRTdHlsZSQxKGN1cnJlbnROb2RlKTsgLy8gVGhpcyBpcyBub24tZXhoYXVzdGl2ZSBidXQgY292ZXJzIHRoZSBtb3N0IGNvbW1vbiBDU1MgcHJvcGVydGllcyB0aGF0XG4gICAgICAvLyBjcmVhdGUgYSBjb250YWluaW5nIGJsb2NrLlxuICAgICAgLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQ1NTL0NvbnRhaW5pbmdfYmxvY2sjaWRlbnRpZnlpbmdfdGhlX2NvbnRhaW5pbmdfYmxvY2tcblxuICAgICAgaWYgKGNzcy50cmFuc2Zvcm0gIT09ICdub25lJyB8fCBjc3MucGVyc3BlY3RpdmUgIT09ICdub25lJyB8fCBjc3MuY29udGFpbiA9PT0gJ3BhaW50JyB8fCBbJ3RyYW5zZm9ybScsICdwZXJzcGVjdGl2ZSddLmluZGV4T2YoY3NzLndpbGxDaGFuZ2UpICE9PSAtMSB8fCBpc0ZpcmVmb3ggJiYgY3NzLndpbGxDaGFuZ2UgPT09ICdmaWx0ZXInIHx8IGlzRmlyZWZveCAmJiBjc3MuZmlsdGVyICYmIGNzcy5maWx0ZXIgIT09ICdub25lJykge1xuICAgICAgICByZXR1cm4gY3VycmVudE5vZGU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjdXJyZW50Tm9kZSA9IGN1cnJlbnROb2RlLnBhcmVudE5vZGU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH0gLy8gR2V0cyB0aGUgY2xvc2VzdCBhbmNlc3RvciBwb3NpdGlvbmVkIGVsZW1lbnQuIEhhbmRsZXMgc29tZSBlZGdlIGNhc2VzLFxuICAvLyBzdWNoIGFzIHRhYmxlIGFuY2VzdG9ycyBhbmQgY3Jvc3MgYnJvd3NlciBidWdzLlxuXG5cbiAgZnVuY3Rpb24gZ2V0T2Zmc2V0UGFyZW50KGVsZW1lbnQpIHtcbiAgICB2YXIgd2luZG93ID0gZ2V0V2luZG93KGVsZW1lbnQpO1xuICAgIHZhciBvZmZzZXRQYXJlbnQgPSBnZXRUcnVlT2Zmc2V0UGFyZW50KGVsZW1lbnQpO1xuXG4gICAgd2hpbGUgKG9mZnNldFBhcmVudCAmJiBpc1RhYmxlRWxlbWVudChvZmZzZXRQYXJlbnQpICYmIGdldENvbXB1dGVkU3R5bGUkMShvZmZzZXRQYXJlbnQpLnBvc2l0aW9uID09PSAnc3RhdGljJykge1xuICAgICAgb2Zmc2V0UGFyZW50ID0gZ2V0VHJ1ZU9mZnNldFBhcmVudChvZmZzZXRQYXJlbnQpO1xuICAgIH1cblxuICAgIGlmIChvZmZzZXRQYXJlbnQgJiYgKGdldE5vZGVOYW1lKG9mZnNldFBhcmVudCkgPT09ICdodG1sJyB8fCBnZXROb2RlTmFtZShvZmZzZXRQYXJlbnQpID09PSAnYm9keScgJiYgZ2V0Q29tcHV0ZWRTdHlsZSQxKG9mZnNldFBhcmVudCkucG9zaXRpb24gPT09ICdzdGF0aWMnKSkge1xuICAgICAgcmV0dXJuIHdpbmRvdztcbiAgICB9XG5cbiAgICByZXR1cm4gb2Zmc2V0UGFyZW50IHx8IGdldENvbnRhaW5pbmdCbG9jayhlbGVtZW50KSB8fCB3aW5kb3c7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRNYWluQXhpc0Zyb21QbGFjZW1lbnQocGxhY2VtZW50KSB7XG4gICAgcmV0dXJuIFsndG9wJywgJ2JvdHRvbSddLmluZGV4T2YocGxhY2VtZW50KSA+PSAwID8gJ3gnIDogJ3knO1xuICB9XG5cbiAgdmFyIG1heCA9IE1hdGgubWF4O1xuICB2YXIgbWluID0gTWF0aC5taW47XG4gIHZhciByb3VuZCA9IE1hdGgucm91bmQ7XG5cbiAgZnVuY3Rpb24gd2l0aGluKG1pbiQxLCB2YWx1ZSwgbWF4JDEpIHtcbiAgICByZXR1cm4gbWF4KG1pbiQxLCBtaW4odmFsdWUsIG1heCQxKSk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRGcmVzaFNpZGVPYmplY3QoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRvcDogMCxcbiAgICAgIHJpZ2h0OiAwLFxuICAgICAgYm90dG9tOiAwLFxuICAgICAgbGVmdDogMFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBtZXJnZVBhZGRpbmdPYmplY3QocGFkZGluZ09iamVjdCkge1xuICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCBnZXRGcmVzaFNpZGVPYmplY3QoKSwgcGFkZGluZ09iamVjdCk7XG4gIH1cblxuICBmdW5jdGlvbiBleHBhbmRUb0hhc2hNYXAodmFsdWUsIGtleXMpIHtcbiAgICByZXR1cm4ga2V5cy5yZWR1Y2UoZnVuY3Rpb24gKGhhc2hNYXAsIGtleSkge1xuICAgICAgaGFzaE1hcFtrZXldID0gdmFsdWU7XG4gICAgICByZXR1cm4gaGFzaE1hcDtcbiAgICB9LCB7fSk7XG4gIH1cblxuICB2YXIgdG9QYWRkaW5nT2JqZWN0ID0gZnVuY3Rpb24gdG9QYWRkaW5nT2JqZWN0KHBhZGRpbmcsIHN0YXRlKSB7XG4gICAgcGFkZGluZyA9IHR5cGVvZiBwYWRkaW5nID09PSAnZnVuY3Rpb24nID8gcGFkZGluZyhPYmplY3QuYXNzaWduKHt9LCBzdGF0ZS5yZWN0cywge1xuICAgICAgcGxhY2VtZW50OiBzdGF0ZS5wbGFjZW1lbnRcbiAgICB9KSkgOiBwYWRkaW5nO1xuICAgIHJldHVybiBtZXJnZVBhZGRpbmdPYmplY3QodHlwZW9mIHBhZGRpbmcgIT09ICdudW1iZXInID8gcGFkZGluZyA6IGV4cGFuZFRvSGFzaE1hcChwYWRkaW5nLCBiYXNlUGxhY2VtZW50cykpO1xuICB9O1xuXG4gIGZ1bmN0aW9uIGFycm93KF9yZWYpIHtcbiAgICB2YXIgX3N0YXRlJG1vZGlmaWVyc0RhdGEkO1xuXG4gICAgdmFyIHN0YXRlID0gX3JlZi5zdGF0ZSxcbiAgICAgICAgbmFtZSA9IF9yZWYubmFtZSxcbiAgICAgICAgb3B0aW9ucyA9IF9yZWYub3B0aW9ucztcbiAgICB2YXIgYXJyb3dFbGVtZW50ID0gc3RhdGUuZWxlbWVudHMuYXJyb3c7XG4gICAgdmFyIHBvcHBlck9mZnNldHMgPSBzdGF0ZS5tb2RpZmllcnNEYXRhLnBvcHBlck9mZnNldHM7XG4gICAgdmFyIGJhc2VQbGFjZW1lbnQgPSBnZXRCYXNlUGxhY2VtZW50KHN0YXRlLnBsYWNlbWVudCk7XG4gICAgdmFyIGF4aXMgPSBnZXRNYWluQXhpc0Zyb21QbGFjZW1lbnQoYmFzZVBsYWNlbWVudCk7XG4gICAgdmFyIGlzVmVydGljYWwgPSBbbGVmdCwgcmlnaHRdLmluZGV4T2YoYmFzZVBsYWNlbWVudCkgPj0gMDtcbiAgICB2YXIgbGVuID0gaXNWZXJ0aWNhbCA/ICdoZWlnaHQnIDogJ3dpZHRoJztcblxuICAgIGlmICghYXJyb3dFbGVtZW50IHx8ICFwb3BwZXJPZmZzZXRzKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHBhZGRpbmdPYmplY3QgPSB0b1BhZGRpbmdPYmplY3Qob3B0aW9ucy5wYWRkaW5nLCBzdGF0ZSk7XG4gICAgdmFyIGFycm93UmVjdCA9IGdldExheW91dFJlY3QoYXJyb3dFbGVtZW50KTtcbiAgICB2YXIgbWluUHJvcCA9IGF4aXMgPT09ICd5JyA/IHRvcCA6IGxlZnQ7XG4gICAgdmFyIG1heFByb3AgPSBheGlzID09PSAneScgPyBib3R0b20gOiByaWdodDtcbiAgICB2YXIgZW5kRGlmZiA9IHN0YXRlLnJlY3RzLnJlZmVyZW5jZVtsZW5dICsgc3RhdGUucmVjdHMucmVmZXJlbmNlW2F4aXNdIC0gcG9wcGVyT2Zmc2V0c1theGlzXSAtIHN0YXRlLnJlY3RzLnBvcHBlcltsZW5dO1xuICAgIHZhciBzdGFydERpZmYgPSBwb3BwZXJPZmZzZXRzW2F4aXNdIC0gc3RhdGUucmVjdHMucmVmZXJlbmNlW2F4aXNdO1xuICAgIHZhciBhcnJvd09mZnNldFBhcmVudCA9IGdldE9mZnNldFBhcmVudChhcnJvd0VsZW1lbnQpO1xuICAgIHZhciBjbGllbnRTaXplID0gYXJyb3dPZmZzZXRQYXJlbnQgPyBheGlzID09PSAneScgPyBhcnJvd09mZnNldFBhcmVudC5jbGllbnRIZWlnaHQgfHwgMCA6IGFycm93T2Zmc2V0UGFyZW50LmNsaWVudFdpZHRoIHx8IDAgOiAwO1xuICAgIHZhciBjZW50ZXJUb1JlZmVyZW5jZSA9IGVuZERpZmYgLyAyIC0gc3RhcnREaWZmIC8gMjsgLy8gTWFrZSBzdXJlIHRoZSBhcnJvdyBkb2Vzbid0IG92ZXJmbG93IHRoZSBwb3BwZXIgaWYgdGhlIGNlbnRlciBwb2ludCBpc1xuICAgIC8vIG91dHNpZGUgb2YgdGhlIHBvcHBlciBib3VuZHNcblxuICAgIHZhciBtaW4gPSBwYWRkaW5nT2JqZWN0W21pblByb3BdO1xuICAgIHZhciBtYXggPSBjbGllbnRTaXplIC0gYXJyb3dSZWN0W2xlbl0gLSBwYWRkaW5nT2JqZWN0W21heFByb3BdO1xuICAgIHZhciBjZW50ZXIgPSBjbGllbnRTaXplIC8gMiAtIGFycm93UmVjdFtsZW5dIC8gMiArIGNlbnRlclRvUmVmZXJlbmNlO1xuICAgIHZhciBvZmZzZXQgPSB3aXRoaW4obWluLCBjZW50ZXIsIG1heCk7IC8vIFByZXZlbnRzIGJyZWFraW5nIHN5bnRheCBoaWdobGlnaHRpbmcuLi5cblxuICAgIHZhciBheGlzUHJvcCA9IGF4aXM7XG4gICAgc3RhdGUubW9kaWZpZXJzRGF0YVtuYW1lXSA9IChfc3RhdGUkbW9kaWZpZXJzRGF0YSQgPSB7fSwgX3N0YXRlJG1vZGlmaWVyc0RhdGEkW2F4aXNQcm9wXSA9IG9mZnNldCwgX3N0YXRlJG1vZGlmaWVyc0RhdGEkLmNlbnRlck9mZnNldCA9IG9mZnNldCAtIGNlbnRlciwgX3N0YXRlJG1vZGlmaWVyc0RhdGEkKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGVmZmVjdCQxKF9yZWYyKSB7XG4gICAgdmFyIHN0YXRlID0gX3JlZjIuc3RhdGUsXG4gICAgICAgIG9wdGlvbnMgPSBfcmVmMi5vcHRpb25zO1xuICAgIHZhciBfb3B0aW9ucyRlbGVtZW50ID0gb3B0aW9ucy5lbGVtZW50LFxuICAgICAgICBhcnJvd0VsZW1lbnQgPSBfb3B0aW9ucyRlbGVtZW50ID09PSB2b2lkIDAgPyAnW2RhdGEtcG9wcGVyLWFycm93XScgOiBfb3B0aW9ucyRlbGVtZW50O1xuXG4gICAgaWYgKGFycm93RWxlbWVudCA9PSBudWxsKSB7XG4gICAgICByZXR1cm47XG4gICAgfSAvLyBDU1Mgc2VsZWN0b3JcblxuXG4gICAgaWYgKHR5cGVvZiBhcnJvd0VsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICBhcnJvd0VsZW1lbnQgPSBzdGF0ZS5lbGVtZW50cy5wb3BwZXIucXVlcnlTZWxlY3RvcihhcnJvd0VsZW1lbnQpO1xuXG4gICAgICBpZiAoIWFycm93RWxlbWVudCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFjb250YWlucyhzdGF0ZS5lbGVtZW50cy5wb3BwZXIsIGFycm93RWxlbWVudCkpIHtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHN0YXRlLmVsZW1lbnRzLmFycm93ID0gYXJyb3dFbGVtZW50O1xuICB9IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tdW51c2VkLW1vZHVsZXNcblxuXG4gIGNvbnN0IGFycm93JDEgPSB7XG4gICAgbmFtZTogJ2Fycm93JyxcbiAgICBlbmFibGVkOiB0cnVlLFxuICAgIHBoYXNlOiAnbWFpbicsXG4gICAgZm46IGFycm93LFxuICAgIGVmZmVjdDogZWZmZWN0JDEsXG4gICAgcmVxdWlyZXM6IFsncG9wcGVyT2Zmc2V0cyddLFxuICAgIHJlcXVpcmVzSWZFeGlzdHM6IFsncHJldmVudE92ZXJmbG93J11cbiAgfTtcblxuICBmdW5jdGlvbiBnZXRWYXJpYXRpb24ocGxhY2VtZW50KSB7XG4gICAgcmV0dXJuIHBsYWNlbWVudC5zcGxpdCgnLScpWzFdO1xuICB9XG5cbiAgdmFyIHVuc2V0U2lkZXMgPSB7XG4gICAgdG9wOiAnYXV0bycsXG4gICAgcmlnaHQ6ICdhdXRvJyxcbiAgICBib3R0b206ICdhdXRvJyxcbiAgICBsZWZ0OiAnYXV0bydcbiAgfTsgLy8gUm91bmQgdGhlIG9mZnNldHMgdG8gdGhlIG5lYXJlc3Qgc3VpdGFibGUgc3VicGl4ZWwgYmFzZWQgb24gdGhlIERQUi5cbiAgLy8gWm9vbWluZyBjYW4gY2hhbmdlIHRoZSBEUFIsIGJ1dCBpdCBzZWVtcyB0byByZXBvcnQgYSB2YWx1ZSB0aGF0IHdpbGxcbiAgLy8gY2xlYW5seSBkaXZpZGUgdGhlIHZhbHVlcyBpbnRvIHRoZSBhcHByb3ByaWF0ZSBzdWJwaXhlbHMuXG5cbiAgZnVuY3Rpb24gcm91bmRPZmZzZXRzQnlEUFIoX3JlZikge1xuICAgIHZhciB4ID0gX3JlZi54LFxuICAgICAgICB5ID0gX3JlZi55O1xuICAgIHZhciB3aW4gPSB3aW5kb3c7XG4gICAgdmFyIGRwciA9IHdpbi5kZXZpY2VQaXhlbFJhdGlvIHx8IDE7XG4gICAgcmV0dXJuIHtcbiAgICAgIHg6IHJvdW5kKHJvdW5kKHggKiBkcHIpIC8gZHByKSB8fCAwLFxuICAgICAgeTogcm91bmQocm91bmQoeSAqIGRwcikgLyBkcHIpIHx8IDBcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gbWFwVG9TdHlsZXMoX3JlZjIpIHtcbiAgICB2YXIgX09iamVjdCRhc3NpZ24yO1xuXG4gICAgdmFyIHBvcHBlciA9IF9yZWYyLnBvcHBlcixcbiAgICAgICAgcG9wcGVyUmVjdCA9IF9yZWYyLnBvcHBlclJlY3QsXG4gICAgICAgIHBsYWNlbWVudCA9IF9yZWYyLnBsYWNlbWVudCxcbiAgICAgICAgdmFyaWF0aW9uID0gX3JlZjIudmFyaWF0aW9uLFxuICAgICAgICBvZmZzZXRzID0gX3JlZjIub2Zmc2V0cyxcbiAgICAgICAgcG9zaXRpb24gPSBfcmVmMi5wb3NpdGlvbixcbiAgICAgICAgZ3B1QWNjZWxlcmF0aW9uID0gX3JlZjIuZ3B1QWNjZWxlcmF0aW9uLFxuICAgICAgICBhZGFwdGl2ZSA9IF9yZWYyLmFkYXB0aXZlLFxuICAgICAgICByb3VuZE9mZnNldHMgPSBfcmVmMi5yb3VuZE9mZnNldHM7XG5cbiAgICB2YXIgX3JlZjMgPSByb3VuZE9mZnNldHMgPT09IHRydWUgPyByb3VuZE9mZnNldHNCeURQUihvZmZzZXRzKSA6IHR5cGVvZiByb3VuZE9mZnNldHMgPT09ICdmdW5jdGlvbicgPyByb3VuZE9mZnNldHMob2Zmc2V0cykgOiBvZmZzZXRzLFxuICAgICAgICBfcmVmMyR4ID0gX3JlZjMueCxcbiAgICAgICAgeCA9IF9yZWYzJHggPT09IHZvaWQgMCA/IDAgOiBfcmVmMyR4LFxuICAgICAgICBfcmVmMyR5ID0gX3JlZjMueSxcbiAgICAgICAgeSA9IF9yZWYzJHkgPT09IHZvaWQgMCA/IDAgOiBfcmVmMyR5O1xuXG4gICAgdmFyIGhhc1ggPSBvZmZzZXRzLmhhc093blByb3BlcnR5KCd4Jyk7XG4gICAgdmFyIGhhc1kgPSBvZmZzZXRzLmhhc093blByb3BlcnR5KCd5Jyk7XG4gICAgdmFyIHNpZGVYID0gbGVmdDtcbiAgICB2YXIgc2lkZVkgPSB0b3A7XG4gICAgdmFyIHdpbiA9IHdpbmRvdztcblxuICAgIGlmIChhZGFwdGl2ZSkge1xuICAgICAgdmFyIG9mZnNldFBhcmVudCA9IGdldE9mZnNldFBhcmVudChwb3BwZXIpO1xuICAgICAgdmFyIGhlaWdodFByb3AgPSAnY2xpZW50SGVpZ2h0JztcbiAgICAgIHZhciB3aWR0aFByb3AgPSAnY2xpZW50V2lkdGgnO1xuXG4gICAgICBpZiAob2Zmc2V0UGFyZW50ID09PSBnZXRXaW5kb3cocG9wcGVyKSkge1xuICAgICAgICBvZmZzZXRQYXJlbnQgPSBnZXREb2N1bWVudEVsZW1lbnQocG9wcGVyKTtcblxuICAgICAgICBpZiAoZ2V0Q29tcHV0ZWRTdHlsZSQxKG9mZnNldFBhcmVudCkucG9zaXRpb24gIT09ICdzdGF0aWMnICYmIHBvc2l0aW9uID09PSAnYWJzb2x1dGUnKSB7XG4gICAgICAgICAgaGVpZ2h0UHJvcCA9ICdzY3JvbGxIZWlnaHQnO1xuICAgICAgICAgIHdpZHRoUHJvcCA9ICdzY3JvbGxXaWR0aCc7XG4gICAgICAgIH1cbiAgICAgIH0gLy8gJEZsb3dGaXhNZVtpbmNvbXBhdGlibGUtY2FzdF06IGZvcmNlIHR5cGUgcmVmaW5lbWVudCwgd2UgY29tcGFyZSBvZmZzZXRQYXJlbnQgd2l0aCB3aW5kb3cgYWJvdmUsIGJ1dCBGbG93IGRvZXNuJ3QgZGV0ZWN0IGl0XG5cblxuICAgICAgb2Zmc2V0UGFyZW50ID0gb2Zmc2V0UGFyZW50O1xuXG4gICAgICBpZiAocGxhY2VtZW50ID09PSB0b3AgfHwgKHBsYWNlbWVudCA9PT0gbGVmdCB8fCBwbGFjZW1lbnQgPT09IHJpZ2h0KSAmJiB2YXJpYXRpb24gPT09IGVuZCkge1xuICAgICAgICBzaWRlWSA9IGJvdHRvbTsgLy8gJEZsb3dGaXhNZVtwcm9wLW1pc3NpbmddXG5cbiAgICAgICAgeSAtPSBvZmZzZXRQYXJlbnRbaGVpZ2h0UHJvcF0gLSBwb3BwZXJSZWN0LmhlaWdodDtcbiAgICAgICAgeSAqPSBncHVBY2NlbGVyYXRpb24gPyAxIDogLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChwbGFjZW1lbnQgPT09IGxlZnQgfHwgKHBsYWNlbWVudCA9PT0gdG9wIHx8IHBsYWNlbWVudCA9PT0gYm90dG9tKSAmJiB2YXJpYXRpb24gPT09IGVuZCkge1xuICAgICAgICBzaWRlWCA9IHJpZ2h0OyAvLyAkRmxvd0ZpeE1lW3Byb3AtbWlzc2luZ11cblxuICAgICAgICB4IC09IG9mZnNldFBhcmVudFt3aWR0aFByb3BdIC0gcG9wcGVyUmVjdC53aWR0aDtcbiAgICAgICAgeCAqPSBncHVBY2NlbGVyYXRpb24gPyAxIDogLTE7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGNvbW1vblN0eWxlcyA9IE9iamVjdC5hc3NpZ24oe1xuICAgICAgcG9zaXRpb246IHBvc2l0aW9uXG4gICAgfSwgYWRhcHRpdmUgJiYgdW5zZXRTaWRlcyk7XG5cbiAgICBpZiAoZ3B1QWNjZWxlcmF0aW9uKSB7XG4gICAgICB2YXIgX09iamVjdCRhc3NpZ247XG5cbiAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCBjb21tb25TdHlsZXMsIChfT2JqZWN0JGFzc2lnbiA9IHt9LCBfT2JqZWN0JGFzc2lnbltzaWRlWV0gPSBoYXNZID8gJzAnIDogJycsIF9PYmplY3QkYXNzaWduW3NpZGVYXSA9IGhhc1ggPyAnMCcgOiAnJywgX09iamVjdCRhc3NpZ24udHJhbnNmb3JtID0gKHdpbi5kZXZpY2VQaXhlbFJhdGlvIHx8IDEpIDw9IDEgPyBcInRyYW5zbGF0ZShcIiArIHggKyBcInB4LCBcIiArIHkgKyBcInB4KVwiIDogXCJ0cmFuc2xhdGUzZChcIiArIHggKyBcInB4LCBcIiArIHkgKyBcInB4LCAwKVwiLCBfT2JqZWN0JGFzc2lnbikpO1xuICAgIH1cblxuICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCBjb21tb25TdHlsZXMsIChfT2JqZWN0JGFzc2lnbjIgPSB7fSwgX09iamVjdCRhc3NpZ24yW3NpZGVZXSA9IGhhc1kgPyB5ICsgXCJweFwiIDogJycsIF9PYmplY3QkYXNzaWduMltzaWRlWF0gPSBoYXNYID8geCArIFwicHhcIiA6ICcnLCBfT2JqZWN0JGFzc2lnbjIudHJhbnNmb3JtID0gJycsIF9PYmplY3QkYXNzaWduMikpO1xuICB9XG5cbiAgZnVuY3Rpb24gY29tcHV0ZVN0eWxlcyhfcmVmNCkge1xuICAgIHZhciBzdGF0ZSA9IF9yZWY0LnN0YXRlLFxuICAgICAgICBvcHRpb25zID0gX3JlZjQub3B0aW9ucztcbiAgICB2YXIgX29wdGlvbnMkZ3B1QWNjZWxlcmF0ID0gb3B0aW9ucy5ncHVBY2NlbGVyYXRpb24sXG4gICAgICAgIGdwdUFjY2VsZXJhdGlvbiA9IF9vcHRpb25zJGdwdUFjY2VsZXJhdCA9PT0gdm9pZCAwID8gdHJ1ZSA6IF9vcHRpb25zJGdwdUFjY2VsZXJhdCxcbiAgICAgICAgX29wdGlvbnMkYWRhcHRpdmUgPSBvcHRpb25zLmFkYXB0aXZlLFxuICAgICAgICBhZGFwdGl2ZSA9IF9vcHRpb25zJGFkYXB0aXZlID09PSB2b2lkIDAgPyB0cnVlIDogX29wdGlvbnMkYWRhcHRpdmUsXG4gICAgICAgIF9vcHRpb25zJHJvdW5kT2Zmc2V0cyA9IG9wdGlvbnMucm91bmRPZmZzZXRzLFxuICAgICAgICByb3VuZE9mZnNldHMgPSBfb3B0aW9ucyRyb3VuZE9mZnNldHMgPT09IHZvaWQgMCA/IHRydWUgOiBfb3B0aW9ucyRyb3VuZE9mZnNldHM7XG5cbiAgICB2YXIgY29tbW9uU3R5bGVzID0ge1xuICAgICAgcGxhY2VtZW50OiBnZXRCYXNlUGxhY2VtZW50KHN0YXRlLnBsYWNlbWVudCksXG4gICAgICB2YXJpYXRpb246IGdldFZhcmlhdGlvbihzdGF0ZS5wbGFjZW1lbnQpLFxuICAgICAgcG9wcGVyOiBzdGF0ZS5lbGVtZW50cy5wb3BwZXIsXG4gICAgICBwb3BwZXJSZWN0OiBzdGF0ZS5yZWN0cy5wb3BwZXIsXG4gICAgICBncHVBY2NlbGVyYXRpb246IGdwdUFjY2VsZXJhdGlvblxuICAgIH07XG5cbiAgICBpZiAoc3RhdGUubW9kaWZpZXJzRGF0YS5wb3BwZXJPZmZzZXRzICE9IG51bGwpIHtcbiAgICAgIHN0YXRlLnN0eWxlcy5wb3BwZXIgPSBPYmplY3QuYXNzaWduKHt9LCBzdGF0ZS5zdHlsZXMucG9wcGVyLCBtYXBUb1N0eWxlcyhPYmplY3QuYXNzaWduKHt9LCBjb21tb25TdHlsZXMsIHtcbiAgICAgICAgb2Zmc2V0czogc3RhdGUubW9kaWZpZXJzRGF0YS5wb3BwZXJPZmZzZXRzLFxuICAgICAgICBwb3NpdGlvbjogc3RhdGUub3B0aW9ucy5zdHJhdGVneSxcbiAgICAgICAgYWRhcHRpdmU6IGFkYXB0aXZlLFxuICAgICAgICByb3VuZE9mZnNldHM6IHJvdW5kT2Zmc2V0c1xuICAgICAgfSkpKTtcbiAgICB9XG5cbiAgICBpZiAoc3RhdGUubW9kaWZpZXJzRGF0YS5hcnJvdyAhPSBudWxsKSB7XG4gICAgICBzdGF0ZS5zdHlsZXMuYXJyb3cgPSBPYmplY3QuYXNzaWduKHt9LCBzdGF0ZS5zdHlsZXMuYXJyb3csIG1hcFRvU3R5bGVzKE9iamVjdC5hc3NpZ24oe30sIGNvbW1vblN0eWxlcywge1xuICAgICAgICBvZmZzZXRzOiBzdGF0ZS5tb2RpZmllcnNEYXRhLmFycm93LFxuICAgICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgICAgYWRhcHRpdmU6IGZhbHNlLFxuICAgICAgICByb3VuZE9mZnNldHM6IHJvdW5kT2Zmc2V0c1xuICAgICAgfSkpKTtcbiAgICB9XG5cbiAgICBzdGF0ZS5hdHRyaWJ1dGVzLnBvcHBlciA9IE9iamVjdC5hc3NpZ24oe30sIHN0YXRlLmF0dHJpYnV0ZXMucG9wcGVyLCB7XG4gICAgICAnZGF0YS1wb3BwZXItcGxhY2VtZW50Jzogc3RhdGUucGxhY2VtZW50XG4gICAgfSk7XG4gIH0gLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby11bnVzZWQtbW9kdWxlc1xuXG5cbiAgY29uc3QgY29tcHV0ZVN0eWxlcyQxID0ge1xuICAgIG5hbWU6ICdjb21wdXRlU3R5bGVzJyxcbiAgICBlbmFibGVkOiB0cnVlLFxuICAgIHBoYXNlOiAnYmVmb3JlV3JpdGUnLFxuICAgIGZuOiBjb21wdXRlU3R5bGVzLFxuICAgIGRhdGE6IHt9XG4gIH07XG5cbiAgdmFyIHBhc3NpdmUgPSB7XG4gICAgcGFzc2l2ZTogdHJ1ZVxuICB9O1xuXG4gIGZ1bmN0aW9uIGVmZmVjdChfcmVmKSB7XG4gICAgdmFyIHN0YXRlID0gX3JlZi5zdGF0ZSxcbiAgICAgICAgaW5zdGFuY2UgPSBfcmVmLmluc3RhbmNlLFxuICAgICAgICBvcHRpb25zID0gX3JlZi5vcHRpb25zO1xuICAgIHZhciBfb3B0aW9ucyRzY3JvbGwgPSBvcHRpb25zLnNjcm9sbCxcbiAgICAgICAgc2Nyb2xsID0gX29wdGlvbnMkc2Nyb2xsID09PSB2b2lkIDAgPyB0cnVlIDogX29wdGlvbnMkc2Nyb2xsLFxuICAgICAgICBfb3B0aW9ucyRyZXNpemUgPSBvcHRpb25zLnJlc2l6ZSxcbiAgICAgICAgcmVzaXplID0gX29wdGlvbnMkcmVzaXplID09PSB2b2lkIDAgPyB0cnVlIDogX29wdGlvbnMkcmVzaXplO1xuICAgIHZhciB3aW5kb3cgPSBnZXRXaW5kb3coc3RhdGUuZWxlbWVudHMucG9wcGVyKTtcbiAgICB2YXIgc2Nyb2xsUGFyZW50cyA9IFtdLmNvbmNhdChzdGF0ZS5zY3JvbGxQYXJlbnRzLnJlZmVyZW5jZSwgc3RhdGUuc2Nyb2xsUGFyZW50cy5wb3BwZXIpO1xuXG4gICAgaWYgKHNjcm9sbCkge1xuICAgICAgc2Nyb2xsUGFyZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChzY3JvbGxQYXJlbnQpIHtcbiAgICAgICAgc2Nyb2xsUGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIGluc3RhbmNlLnVwZGF0ZSwgcGFzc2l2ZSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAocmVzaXplKSB7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgaW5zdGFuY2UudXBkYXRlLCBwYXNzaXZlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKHNjcm9sbCkge1xuICAgICAgICBzY3JvbGxQYXJlbnRzLmZvckVhY2goZnVuY3Rpb24gKHNjcm9sbFBhcmVudCkge1xuICAgICAgICAgIHNjcm9sbFBhcmVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBpbnN0YW5jZS51cGRhdGUsIHBhc3NpdmUpO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKHJlc2l6ZSkge1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgaW5zdGFuY2UudXBkYXRlLCBwYXNzaXZlKTtcbiAgICAgIH1cbiAgICB9O1xuICB9IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tdW51c2VkLW1vZHVsZXNcblxuXG4gIGNvbnN0IGV2ZW50TGlzdGVuZXJzID0ge1xuICAgIG5hbWU6ICdldmVudExpc3RlbmVycycsXG4gICAgZW5hYmxlZDogdHJ1ZSxcbiAgICBwaGFzZTogJ3dyaXRlJyxcbiAgICBmbjogZnVuY3Rpb24gZm4oKSB7fSxcbiAgICBlZmZlY3Q6IGVmZmVjdCxcbiAgICBkYXRhOiB7fVxuICB9O1xuXG4gIHZhciBoYXNoJDEgPSB7XG4gICAgbGVmdDogJ3JpZ2h0JyxcbiAgICByaWdodDogJ2xlZnQnLFxuICAgIGJvdHRvbTogJ3RvcCcsXG4gICAgdG9wOiAnYm90dG9tJ1xuICB9O1xuICBmdW5jdGlvbiBnZXRPcHBvc2l0ZVBsYWNlbWVudChwbGFjZW1lbnQpIHtcbiAgICByZXR1cm4gcGxhY2VtZW50LnJlcGxhY2UoL2xlZnR8cmlnaHR8Ym90dG9tfHRvcC9nLCBmdW5jdGlvbiAobWF0Y2hlZCkge1xuICAgICAgcmV0dXJuIGhhc2gkMVttYXRjaGVkXTtcbiAgICB9KTtcbiAgfVxuXG4gIHZhciBoYXNoID0ge1xuICAgIHN0YXJ0OiAnZW5kJyxcbiAgICBlbmQ6ICdzdGFydCdcbiAgfTtcbiAgZnVuY3Rpb24gZ2V0T3Bwb3NpdGVWYXJpYXRpb25QbGFjZW1lbnQocGxhY2VtZW50KSB7XG4gICAgcmV0dXJuIHBsYWNlbWVudC5yZXBsYWNlKC9zdGFydHxlbmQvZywgZnVuY3Rpb24gKG1hdGNoZWQpIHtcbiAgICAgIHJldHVybiBoYXNoW21hdGNoZWRdO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0V2luZG93U2Nyb2xsKG5vZGUpIHtcbiAgICB2YXIgd2luID0gZ2V0V2luZG93KG5vZGUpO1xuICAgIHZhciBzY3JvbGxMZWZ0ID0gd2luLnBhZ2VYT2Zmc2V0O1xuICAgIHZhciBzY3JvbGxUb3AgPSB3aW4ucGFnZVlPZmZzZXQ7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNjcm9sbExlZnQ6IHNjcm9sbExlZnQsXG4gICAgICBzY3JvbGxUb3A6IHNjcm9sbFRvcFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBnZXRXaW5kb3dTY3JvbGxCYXJYKGVsZW1lbnQpIHtcbiAgICAvLyBJZiA8aHRtbD4gaGFzIGEgQ1NTIHdpZHRoIGdyZWF0ZXIgdGhhbiB0aGUgdmlld3BvcnQsIHRoZW4gdGhpcyB3aWxsIGJlXG4gICAgLy8gaW5jb3JyZWN0IGZvciBSVEwuXG4gICAgLy8gUG9wcGVyIDEgaXMgYnJva2VuIGluIHRoaXMgY2FzZSBhbmQgbmV2ZXIgaGFkIGEgYnVnIHJlcG9ydCBzbyBsZXQncyBhc3N1bWVcbiAgICAvLyBpdCdzIG5vdCBhbiBpc3N1ZS4gSSBkb24ndCB0aGluayBhbnlvbmUgZXZlciBzcGVjaWZpZXMgd2lkdGggb24gPGh0bWw+XG4gICAgLy8gYW55d2F5LlxuICAgIC8vIEJyb3dzZXJzIHdoZXJlIHRoZSBsZWZ0IHNjcm9sbGJhciBkb2Vzbid0IGNhdXNlIGFuIGlzc3VlIHJlcG9ydCBgMGAgZm9yXG4gICAgLy8gdGhpcyAoZS5nLiBFZGdlIDIwMTksIElFMTEsIFNhZmFyaSlcbiAgICByZXR1cm4gZ2V0Qm91bmRpbmdDbGllbnRSZWN0KGdldERvY3VtZW50RWxlbWVudChlbGVtZW50KSkubGVmdCArIGdldFdpbmRvd1Njcm9sbChlbGVtZW50KS5zY3JvbGxMZWZ0O1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0Vmlld3BvcnRSZWN0KGVsZW1lbnQpIHtcbiAgICB2YXIgd2luID0gZ2V0V2luZG93KGVsZW1lbnQpO1xuICAgIHZhciBodG1sID0gZ2V0RG9jdW1lbnRFbGVtZW50KGVsZW1lbnQpO1xuICAgIHZhciB2aXN1YWxWaWV3cG9ydCA9IHdpbi52aXN1YWxWaWV3cG9ydDtcbiAgICB2YXIgd2lkdGggPSBodG1sLmNsaWVudFdpZHRoO1xuICAgIHZhciBoZWlnaHQgPSBodG1sLmNsaWVudEhlaWdodDtcbiAgICB2YXIgeCA9IDA7XG4gICAgdmFyIHkgPSAwOyAvLyBOQjogVGhpcyBpc24ndCBzdXBwb3J0ZWQgb24gaU9TIDw9IDEyLiBJZiB0aGUga2V5Ym9hcmQgaXMgb3BlbiwgdGhlIHBvcHBlclxuICAgIC8vIGNhbiBiZSBvYnNjdXJlZCB1bmRlcm5lYXRoIGl0LlxuICAgIC8vIEFsc28sIGBodG1sLmNsaWVudEhlaWdodGAgYWRkcyB0aGUgYm90dG9tIGJhciBoZWlnaHQgaW4gU2FmYXJpIGlPUywgZXZlblxuICAgIC8vIGlmIGl0IGlzbid0IG9wZW4sIHNvIGlmIHRoaXMgaXNuJ3QgYXZhaWxhYmxlLCB0aGUgcG9wcGVyIHdpbGwgYmUgZGV0ZWN0ZWRcbiAgICAvLyB0byBvdmVyZmxvdyB0aGUgYm90dG9tIG9mIHRoZSBzY3JlZW4gdG9vIGVhcmx5LlxuXG4gICAgaWYgKHZpc3VhbFZpZXdwb3J0KSB7XG4gICAgICB3aWR0aCA9IHZpc3VhbFZpZXdwb3J0LndpZHRoO1xuICAgICAgaGVpZ2h0ID0gdmlzdWFsVmlld3BvcnQuaGVpZ2h0OyAvLyBVc2VzIExheW91dCBWaWV3cG9ydCAobGlrZSBDaHJvbWU7IFNhZmFyaSBkb2VzIG5vdCBjdXJyZW50bHkpXG4gICAgICAvLyBJbiBDaHJvbWUsIGl0IHJldHVybnMgYSB2YWx1ZSB2ZXJ5IGNsb3NlIHRvIDAgKCsvLSkgYnV0IGNvbnRhaW5zIHJvdW5kaW5nXG4gICAgICAvLyBlcnJvcnMgZHVlIHRvIGZsb2F0aW5nIHBvaW50IG51bWJlcnMsIHNvIHdlIG5lZWQgdG8gY2hlY2sgcHJlY2lzaW9uLlxuICAgICAgLy8gU2FmYXJpIHJldHVybnMgYSBudW1iZXIgPD0gMCwgdXN1YWxseSA8IC0xIHdoZW4gcGluY2gtem9vbWVkXG4gICAgICAvLyBGZWF0dXJlIGRldGVjdGlvbiBmYWlscyBpbiBtb2JpbGUgZW11bGF0aW9uIG1vZGUgaW4gQ2hyb21lLlxuICAgICAgLy8gTWF0aC5hYnMod2luLmlubmVyV2lkdGggLyB2aXN1YWxWaWV3cG9ydC5zY2FsZSAtIHZpc3VhbFZpZXdwb3J0LndpZHRoKSA8XG4gICAgICAvLyAwLjAwMVxuICAgICAgLy8gRmFsbGJhY2sgaGVyZTogXCJOb3QgU2FmYXJpXCIgdXNlckFnZW50XG5cbiAgICAgIGlmICghL14oKD8hY2hyb21lfGFuZHJvaWQpLikqc2FmYXJpL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KSkge1xuICAgICAgICB4ID0gdmlzdWFsVmlld3BvcnQub2Zmc2V0TGVmdDtcbiAgICAgICAgeSA9IHZpc3VhbFZpZXdwb3J0Lm9mZnNldFRvcDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgd2lkdGg6IHdpZHRoLFxuICAgICAgaGVpZ2h0OiBoZWlnaHQsXG4gICAgICB4OiB4ICsgZ2V0V2luZG93U2Nyb2xsQmFyWChlbGVtZW50KSxcbiAgICAgIHk6IHlcbiAgICB9O1xuICB9XG5cbiAgLy8gb2YgdGhlIGA8aHRtbD5gIGFuZCBgPGJvZHk+YCByZWN0IGJvdW5kcyBpZiBob3Jpem9udGFsbHkgc2Nyb2xsYWJsZVxuXG4gIGZ1bmN0aW9uIGdldERvY3VtZW50UmVjdChlbGVtZW50KSB7XG4gICAgdmFyIF9lbGVtZW50JG93bmVyRG9jdW1lbjtcblxuICAgIHZhciBodG1sID0gZ2V0RG9jdW1lbnRFbGVtZW50KGVsZW1lbnQpO1xuICAgIHZhciB3aW5TY3JvbGwgPSBnZXRXaW5kb3dTY3JvbGwoZWxlbWVudCk7XG4gICAgdmFyIGJvZHkgPSAoX2VsZW1lbnQkb3duZXJEb2N1bWVuID0gZWxlbWVudC5vd25lckRvY3VtZW50KSA9PSBudWxsID8gdm9pZCAwIDogX2VsZW1lbnQkb3duZXJEb2N1bWVuLmJvZHk7XG4gICAgdmFyIHdpZHRoID0gbWF4KGh0bWwuc2Nyb2xsV2lkdGgsIGh0bWwuY2xpZW50V2lkdGgsIGJvZHkgPyBib2R5LnNjcm9sbFdpZHRoIDogMCwgYm9keSA/IGJvZHkuY2xpZW50V2lkdGggOiAwKTtcbiAgICB2YXIgaGVpZ2h0ID0gbWF4KGh0bWwuc2Nyb2xsSGVpZ2h0LCBodG1sLmNsaWVudEhlaWdodCwgYm9keSA/IGJvZHkuc2Nyb2xsSGVpZ2h0IDogMCwgYm9keSA/IGJvZHkuY2xpZW50SGVpZ2h0IDogMCk7XG4gICAgdmFyIHggPSAtd2luU2Nyb2xsLnNjcm9sbExlZnQgKyBnZXRXaW5kb3dTY3JvbGxCYXJYKGVsZW1lbnQpO1xuICAgIHZhciB5ID0gLXdpblNjcm9sbC5zY3JvbGxUb3A7XG5cbiAgICBpZiAoZ2V0Q29tcHV0ZWRTdHlsZSQxKGJvZHkgfHwgaHRtbCkuZGlyZWN0aW9uID09PSAncnRsJykge1xuICAgICAgeCArPSBtYXgoaHRtbC5jbGllbnRXaWR0aCwgYm9keSA/IGJvZHkuY2xpZW50V2lkdGggOiAwKSAtIHdpZHRoO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICB3aWR0aDogd2lkdGgsXG4gICAgICBoZWlnaHQ6IGhlaWdodCxcbiAgICAgIHg6IHgsXG4gICAgICB5OiB5XG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzU2Nyb2xsUGFyZW50KGVsZW1lbnQpIHtcbiAgICAvLyBGaXJlZm94IHdhbnRzIHVzIHRvIGNoZWNrIGAteGAgYW5kIGAteWAgdmFyaWF0aW9ucyBhcyB3ZWxsXG4gICAgdmFyIF9nZXRDb21wdXRlZFN0eWxlID0gZ2V0Q29tcHV0ZWRTdHlsZSQxKGVsZW1lbnQpLFxuICAgICAgICBvdmVyZmxvdyA9IF9nZXRDb21wdXRlZFN0eWxlLm92ZXJmbG93LFxuICAgICAgICBvdmVyZmxvd1ggPSBfZ2V0Q29tcHV0ZWRTdHlsZS5vdmVyZmxvd1gsXG4gICAgICAgIG92ZXJmbG93WSA9IF9nZXRDb21wdXRlZFN0eWxlLm92ZXJmbG93WTtcblxuICAgIHJldHVybiAvYXV0b3xzY3JvbGx8b3ZlcmxheXxoaWRkZW4vLnRlc3Qob3ZlcmZsb3cgKyBvdmVyZmxvd1kgKyBvdmVyZmxvd1gpO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0U2Nyb2xsUGFyZW50KG5vZGUpIHtcbiAgICBpZiAoWydodG1sJywgJ2JvZHknLCAnI2RvY3VtZW50J10uaW5kZXhPZihnZXROb2RlTmFtZShub2RlKSkgPj0gMCkge1xuICAgICAgLy8gJEZsb3dGaXhNZVtpbmNvbXBhdGlibGUtcmV0dXJuXTogYXNzdW1lIGJvZHkgaXMgYWx3YXlzIGF2YWlsYWJsZVxuICAgICAgcmV0dXJuIG5vZGUub3duZXJEb2N1bWVudC5ib2R5O1xuICAgIH1cblxuICAgIGlmIChpc0hUTUxFbGVtZW50KG5vZGUpICYmIGlzU2Nyb2xsUGFyZW50KG5vZGUpKSB7XG4gICAgICByZXR1cm4gbm9kZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZ2V0U2Nyb2xsUGFyZW50KGdldFBhcmVudE5vZGUobm9kZSkpO1xuICB9XG5cbiAgLypcbiAgZ2l2ZW4gYSBET00gZWxlbWVudCwgcmV0dXJuIHRoZSBsaXN0IG9mIGFsbCBzY3JvbGwgcGFyZW50cywgdXAgdGhlIGxpc3Qgb2YgYW5jZXNvcnNcbiAgdW50aWwgd2UgZ2V0IHRvIHRoZSB0b3Agd2luZG93IG9iamVjdC4gVGhpcyBsaXN0IGlzIHdoYXQgd2UgYXR0YWNoIHNjcm9sbCBsaXN0ZW5lcnNcbiAgdG8sIGJlY2F1c2UgaWYgYW55IG9mIHRoZXNlIHBhcmVudCBlbGVtZW50cyBzY3JvbGwsIHdlJ2xsIG5lZWQgdG8gcmUtY2FsY3VsYXRlIHRoZVxuICByZWZlcmVuY2UgZWxlbWVudCdzIHBvc2l0aW9uLlxuICAqL1xuXG4gIGZ1bmN0aW9uIGxpc3RTY3JvbGxQYXJlbnRzKGVsZW1lbnQsIGxpc3QpIHtcbiAgICB2YXIgX2VsZW1lbnQkb3duZXJEb2N1bWVuO1xuXG4gICAgaWYgKGxpc3QgPT09IHZvaWQgMCkge1xuICAgICAgbGlzdCA9IFtdO1xuICAgIH1cblxuICAgIHZhciBzY3JvbGxQYXJlbnQgPSBnZXRTY3JvbGxQYXJlbnQoZWxlbWVudCk7XG4gICAgdmFyIGlzQm9keSA9IHNjcm9sbFBhcmVudCA9PT0gKChfZWxlbWVudCRvd25lckRvY3VtZW4gPSBlbGVtZW50Lm93bmVyRG9jdW1lbnQpID09IG51bGwgPyB2b2lkIDAgOiBfZWxlbWVudCRvd25lckRvY3VtZW4uYm9keSk7XG4gICAgdmFyIHdpbiA9IGdldFdpbmRvdyhzY3JvbGxQYXJlbnQpO1xuICAgIHZhciB0YXJnZXQgPSBpc0JvZHkgPyBbd2luXS5jb25jYXQod2luLnZpc3VhbFZpZXdwb3J0IHx8IFtdLCBpc1Njcm9sbFBhcmVudChzY3JvbGxQYXJlbnQpID8gc2Nyb2xsUGFyZW50IDogW10pIDogc2Nyb2xsUGFyZW50O1xuICAgIHZhciB1cGRhdGVkTGlzdCA9IGxpc3QuY29uY2F0KHRhcmdldCk7XG4gICAgcmV0dXJuIGlzQm9keSA/IHVwZGF0ZWRMaXN0IDogLy8gJEZsb3dGaXhNZVtpbmNvbXBhdGlibGUtY2FsbF06IGlzQm9keSB0ZWxscyB1cyB0YXJnZXQgd2lsbCBiZSBhbiBIVE1MRWxlbWVudCBoZXJlXG4gICAgdXBkYXRlZExpc3QuY29uY2F0KGxpc3RTY3JvbGxQYXJlbnRzKGdldFBhcmVudE5vZGUodGFyZ2V0KSkpO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVjdFRvQ2xpZW50UmVjdChyZWN0KSB7XG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIHJlY3QsIHtcbiAgICAgIGxlZnQ6IHJlY3QueCxcbiAgICAgIHRvcDogcmVjdC55LFxuICAgICAgcmlnaHQ6IHJlY3QueCArIHJlY3Qud2lkdGgsXG4gICAgICBib3R0b206IHJlY3QueSArIHJlY3QuaGVpZ2h0XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRJbm5lckJvdW5kaW5nQ2xpZW50UmVjdChlbGVtZW50KSB7XG4gICAgdmFyIHJlY3QgPSBnZXRCb3VuZGluZ0NsaWVudFJlY3QoZWxlbWVudCk7XG4gICAgcmVjdC50b3AgPSByZWN0LnRvcCArIGVsZW1lbnQuY2xpZW50VG9wO1xuICAgIHJlY3QubGVmdCA9IHJlY3QubGVmdCArIGVsZW1lbnQuY2xpZW50TGVmdDtcbiAgICByZWN0LmJvdHRvbSA9IHJlY3QudG9wICsgZWxlbWVudC5jbGllbnRIZWlnaHQ7XG4gICAgcmVjdC5yaWdodCA9IHJlY3QubGVmdCArIGVsZW1lbnQuY2xpZW50V2lkdGg7XG4gICAgcmVjdC53aWR0aCA9IGVsZW1lbnQuY2xpZW50V2lkdGg7XG4gICAgcmVjdC5oZWlnaHQgPSBlbGVtZW50LmNsaWVudEhlaWdodDtcbiAgICByZWN0LnggPSByZWN0LmxlZnQ7XG4gICAgcmVjdC55ID0gcmVjdC50b3A7XG4gICAgcmV0dXJuIHJlY3Q7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRDbGllbnRSZWN0RnJvbU1peGVkVHlwZShlbGVtZW50LCBjbGlwcGluZ1BhcmVudCkge1xuICAgIHJldHVybiBjbGlwcGluZ1BhcmVudCA9PT0gdmlld3BvcnQgPyByZWN0VG9DbGllbnRSZWN0KGdldFZpZXdwb3J0UmVjdChlbGVtZW50KSkgOiBpc0hUTUxFbGVtZW50KGNsaXBwaW5nUGFyZW50KSA/IGdldElubmVyQm91bmRpbmdDbGllbnRSZWN0KGNsaXBwaW5nUGFyZW50KSA6IHJlY3RUb0NsaWVudFJlY3QoZ2V0RG9jdW1lbnRSZWN0KGdldERvY3VtZW50RWxlbWVudChlbGVtZW50KSkpO1xuICB9IC8vIEEgXCJjbGlwcGluZyBwYXJlbnRcIiBpcyBhbiBvdmVyZmxvd2FibGUgY29udGFpbmVyIHdpdGggdGhlIGNoYXJhY3RlcmlzdGljIG9mXG4gIC8vIGNsaXBwaW5nIChvciBoaWRpbmcpIG92ZXJmbG93aW5nIGVsZW1lbnRzIHdpdGggYSBwb3NpdGlvbiBkaWZmZXJlbnQgZnJvbVxuICAvLyBgaW5pdGlhbGBcblxuXG4gIGZ1bmN0aW9uIGdldENsaXBwaW5nUGFyZW50cyhlbGVtZW50KSB7XG4gICAgdmFyIGNsaXBwaW5nUGFyZW50cyA9IGxpc3RTY3JvbGxQYXJlbnRzKGdldFBhcmVudE5vZGUoZWxlbWVudCkpO1xuICAgIHZhciBjYW5Fc2NhcGVDbGlwcGluZyA9IFsnYWJzb2x1dGUnLCAnZml4ZWQnXS5pbmRleE9mKGdldENvbXB1dGVkU3R5bGUkMShlbGVtZW50KS5wb3NpdGlvbikgPj0gMDtcbiAgICB2YXIgY2xpcHBlckVsZW1lbnQgPSBjYW5Fc2NhcGVDbGlwcGluZyAmJiBpc0hUTUxFbGVtZW50KGVsZW1lbnQpID8gZ2V0T2Zmc2V0UGFyZW50KGVsZW1lbnQpIDogZWxlbWVudDtcblxuICAgIGlmICghaXNFbGVtZW50KGNsaXBwZXJFbGVtZW50KSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH0gLy8gJEZsb3dGaXhNZVtpbmNvbXBhdGlibGUtcmV0dXJuXTogaHR0cHM6Ly9naXRodWIuY29tL2ZhY2Vib29rL2Zsb3cvaXNzdWVzLzE0MTRcblxuXG4gICAgcmV0dXJuIGNsaXBwaW5nUGFyZW50cy5maWx0ZXIoZnVuY3Rpb24gKGNsaXBwaW5nUGFyZW50KSB7XG4gICAgICByZXR1cm4gaXNFbGVtZW50KGNsaXBwaW5nUGFyZW50KSAmJiBjb250YWlucyhjbGlwcGluZ1BhcmVudCwgY2xpcHBlckVsZW1lbnQpICYmIGdldE5vZGVOYW1lKGNsaXBwaW5nUGFyZW50KSAhPT0gJ2JvZHknO1xuICAgIH0pO1xuICB9IC8vIEdldHMgdGhlIG1heGltdW0gYXJlYSB0aGF0IHRoZSBlbGVtZW50IGlzIHZpc2libGUgaW4gZHVlIHRvIGFueSBudW1iZXIgb2ZcbiAgLy8gY2xpcHBpbmcgcGFyZW50c1xuXG5cbiAgZnVuY3Rpb24gZ2V0Q2xpcHBpbmdSZWN0KGVsZW1lbnQsIGJvdW5kYXJ5LCByb290Qm91bmRhcnkpIHtcbiAgICB2YXIgbWFpbkNsaXBwaW5nUGFyZW50cyA9IGJvdW5kYXJ5ID09PSAnY2xpcHBpbmdQYXJlbnRzJyA/IGdldENsaXBwaW5nUGFyZW50cyhlbGVtZW50KSA6IFtdLmNvbmNhdChib3VuZGFyeSk7XG4gICAgdmFyIGNsaXBwaW5nUGFyZW50cyA9IFtdLmNvbmNhdChtYWluQ2xpcHBpbmdQYXJlbnRzLCBbcm9vdEJvdW5kYXJ5XSk7XG4gICAgdmFyIGZpcnN0Q2xpcHBpbmdQYXJlbnQgPSBjbGlwcGluZ1BhcmVudHNbMF07XG4gICAgdmFyIGNsaXBwaW5nUmVjdCA9IGNsaXBwaW5nUGFyZW50cy5yZWR1Y2UoZnVuY3Rpb24gKGFjY1JlY3QsIGNsaXBwaW5nUGFyZW50KSB7XG4gICAgICB2YXIgcmVjdCA9IGdldENsaWVudFJlY3RGcm9tTWl4ZWRUeXBlKGVsZW1lbnQsIGNsaXBwaW5nUGFyZW50KTtcbiAgICAgIGFjY1JlY3QudG9wID0gbWF4KHJlY3QudG9wLCBhY2NSZWN0LnRvcCk7XG4gICAgICBhY2NSZWN0LnJpZ2h0ID0gbWluKHJlY3QucmlnaHQsIGFjY1JlY3QucmlnaHQpO1xuICAgICAgYWNjUmVjdC5ib3R0b20gPSBtaW4ocmVjdC5ib3R0b20sIGFjY1JlY3QuYm90dG9tKTtcbiAgICAgIGFjY1JlY3QubGVmdCA9IG1heChyZWN0LmxlZnQsIGFjY1JlY3QubGVmdCk7XG4gICAgICByZXR1cm4gYWNjUmVjdDtcbiAgICB9LCBnZXRDbGllbnRSZWN0RnJvbU1peGVkVHlwZShlbGVtZW50LCBmaXJzdENsaXBwaW5nUGFyZW50KSk7XG4gICAgY2xpcHBpbmdSZWN0LndpZHRoID0gY2xpcHBpbmdSZWN0LnJpZ2h0IC0gY2xpcHBpbmdSZWN0LmxlZnQ7XG4gICAgY2xpcHBpbmdSZWN0LmhlaWdodCA9IGNsaXBwaW5nUmVjdC5ib3R0b20gLSBjbGlwcGluZ1JlY3QudG9wO1xuICAgIGNsaXBwaW5nUmVjdC54ID0gY2xpcHBpbmdSZWN0LmxlZnQ7XG4gICAgY2xpcHBpbmdSZWN0LnkgPSBjbGlwcGluZ1JlY3QudG9wO1xuICAgIHJldHVybiBjbGlwcGluZ1JlY3Q7XG4gIH1cblxuICBmdW5jdGlvbiBjb21wdXRlT2Zmc2V0cyhfcmVmKSB7XG4gICAgdmFyIHJlZmVyZW5jZSA9IF9yZWYucmVmZXJlbmNlLFxuICAgICAgICBlbGVtZW50ID0gX3JlZi5lbGVtZW50LFxuICAgICAgICBwbGFjZW1lbnQgPSBfcmVmLnBsYWNlbWVudDtcbiAgICB2YXIgYmFzZVBsYWNlbWVudCA9IHBsYWNlbWVudCA/IGdldEJhc2VQbGFjZW1lbnQocGxhY2VtZW50KSA6IG51bGw7XG4gICAgdmFyIHZhcmlhdGlvbiA9IHBsYWNlbWVudCA/IGdldFZhcmlhdGlvbihwbGFjZW1lbnQpIDogbnVsbDtcbiAgICB2YXIgY29tbW9uWCA9IHJlZmVyZW5jZS54ICsgcmVmZXJlbmNlLndpZHRoIC8gMiAtIGVsZW1lbnQud2lkdGggLyAyO1xuICAgIHZhciBjb21tb25ZID0gcmVmZXJlbmNlLnkgKyByZWZlcmVuY2UuaGVpZ2h0IC8gMiAtIGVsZW1lbnQuaGVpZ2h0IC8gMjtcbiAgICB2YXIgb2Zmc2V0cztcblxuICAgIHN3aXRjaCAoYmFzZVBsYWNlbWVudCkge1xuICAgICAgY2FzZSB0b3A6XG4gICAgICAgIG9mZnNldHMgPSB7XG4gICAgICAgICAgeDogY29tbW9uWCxcbiAgICAgICAgICB5OiByZWZlcmVuY2UueSAtIGVsZW1lbnQuaGVpZ2h0XG4gICAgICAgIH07XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIGJvdHRvbTpcbiAgICAgICAgb2Zmc2V0cyA9IHtcbiAgICAgICAgICB4OiBjb21tb25YLFxuICAgICAgICAgIHk6IHJlZmVyZW5jZS55ICsgcmVmZXJlbmNlLmhlaWdodFxuICAgICAgICB9O1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSByaWdodDpcbiAgICAgICAgb2Zmc2V0cyA9IHtcbiAgICAgICAgICB4OiByZWZlcmVuY2UueCArIHJlZmVyZW5jZS53aWR0aCxcbiAgICAgICAgICB5OiBjb21tb25ZXG4gICAgICAgIH07XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIGxlZnQ6XG4gICAgICAgIG9mZnNldHMgPSB7XG4gICAgICAgICAgeDogcmVmZXJlbmNlLnggLSBlbGVtZW50LndpZHRoLFxuICAgICAgICAgIHk6IGNvbW1vbllcbiAgICAgICAgfTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIG9mZnNldHMgPSB7XG4gICAgICAgICAgeDogcmVmZXJlbmNlLngsXG4gICAgICAgICAgeTogcmVmZXJlbmNlLnlcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICB2YXIgbWFpbkF4aXMgPSBiYXNlUGxhY2VtZW50ID8gZ2V0TWFpbkF4aXNGcm9tUGxhY2VtZW50KGJhc2VQbGFjZW1lbnQpIDogbnVsbDtcblxuICAgIGlmIChtYWluQXhpcyAhPSBudWxsKSB7XG4gICAgICB2YXIgbGVuID0gbWFpbkF4aXMgPT09ICd5JyA/ICdoZWlnaHQnIDogJ3dpZHRoJztcblxuICAgICAgc3dpdGNoICh2YXJpYXRpb24pIHtcbiAgICAgICAgY2FzZSBzdGFydDpcbiAgICAgICAgICBvZmZzZXRzW21haW5BeGlzXSA9IG9mZnNldHNbbWFpbkF4aXNdIC0gKHJlZmVyZW5jZVtsZW5dIC8gMiAtIGVsZW1lbnRbbGVuXSAvIDIpO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgZW5kOlxuICAgICAgICAgIG9mZnNldHNbbWFpbkF4aXNdID0gb2Zmc2V0c1ttYWluQXhpc10gKyAocmVmZXJlbmNlW2xlbl0gLyAyIC0gZWxlbWVudFtsZW5dIC8gMik7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG9mZnNldHM7XG4gIH1cblxuICBmdW5jdGlvbiBkZXRlY3RPdmVyZmxvdyhzdGF0ZSwgb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHtcbiAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICB9XG5cbiAgICB2YXIgX29wdGlvbnMgPSBvcHRpb25zLFxuICAgICAgICBfb3B0aW9ucyRwbGFjZW1lbnQgPSBfb3B0aW9ucy5wbGFjZW1lbnQsXG4gICAgICAgIHBsYWNlbWVudCA9IF9vcHRpb25zJHBsYWNlbWVudCA9PT0gdm9pZCAwID8gc3RhdGUucGxhY2VtZW50IDogX29wdGlvbnMkcGxhY2VtZW50LFxuICAgICAgICBfb3B0aW9ucyRib3VuZGFyeSA9IF9vcHRpb25zLmJvdW5kYXJ5LFxuICAgICAgICBib3VuZGFyeSA9IF9vcHRpb25zJGJvdW5kYXJ5ID09PSB2b2lkIDAgPyBjbGlwcGluZ1BhcmVudHMgOiBfb3B0aW9ucyRib3VuZGFyeSxcbiAgICAgICAgX29wdGlvbnMkcm9vdEJvdW5kYXJ5ID0gX29wdGlvbnMucm9vdEJvdW5kYXJ5LFxuICAgICAgICByb290Qm91bmRhcnkgPSBfb3B0aW9ucyRyb290Qm91bmRhcnkgPT09IHZvaWQgMCA/IHZpZXdwb3J0IDogX29wdGlvbnMkcm9vdEJvdW5kYXJ5LFxuICAgICAgICBfb3B0aW9ucyRlbGVtZW50Q29udGUgPSBfb3B0aW9ucy5lbGVtZW50Q29udGV4dCxcbiAgICAgICAgZWxlbWVudENvbnRleHQgPSBfb3B0aW9ucyRlbGVtZW50Q29udGUgPT09IHZvaWQgMCA/IHBvcHBlciA6IF9vcHRpb25zJGVsZW1lbnRDb250ZSxcbiAgICAgICAgX29wdGlvbnMkYWx0Qm91bmRhcnkgPSBfb3B0aW9ucy5hbHRCb3VuZGFyeSxcbiAgICAgICAgYWx0Qm91bmRhcnkgPSBfb3B0aW9ucyRhbHRCb3VuZGFyeSA9PT0gdm9pZCAwID8gZmFsc2UgOiBfb3B0aW9ucyRhbHRCb3VuZGFyeSxcbiAgICAgICAgX29wdGlvbnMkcGFkZGluZyA9IF9vcHRpb25zLnBhZGRpbmcsXG4gICAgICAgIHBhZGRpbmcgPSBfb3B0aW9ucyRwYWRkaW5nID09PSB2b2lkIDAgPyAwIDogX29wdGlvbnMkcGFkZGluZztcbiAgICB2YXIgcGFkZGluZ09iamVjdCA9IG1lcmdlUGFkZGluZ09iamVjdCh0eXBlb2YgcGFkZGluZyAhPT0gJ251bWJlcicgPyBwYWRkaW5nIDogZXhwYW5kVG9IYXNoTWFwKHBhZGRpbmcsIGJhc2VQbGFjZW1lbnRzKSk7XG4gICAgdmFyIGFsdENvbnRleHQgPSBlbGVtZW50Q29udGV4dCA9PT0gcG9wcGVyID8gcmVmZXJlbmNlIDogcG9wcGVyO1xuICAgIHZhciBwb3BwZXJSZWN0ID0gc3RhdGUucmVjdHMucG9wcGVyO1xuICAgIHZhciBlbGVtZW50ID0gc3RhdGUuZWxlbWVudHNbYWx0Qm91bmRhcnkgPyBhbHRDb250ZXh0IDogZWxlbWVudENvbnRleHRdO1xuICAgIHZhciBjbGlwcGluZ0NsaWVudFJlY3QgPSBnZXRDbGlwcGluZ1JlY3QoaXNFbGVtZW50KGVsZW1lbnQpID8gZWxlbWVudCA6IGVsZW1lbnQuY29udGV4dEVsZW1lbnQgfHwgZ2V0RG9jdW1lbnRFbGVtZW50KHN0YXRlLmVsZW1lbnRzLnBvcHBlciksIGJvdW5kYXJ5LCByb290Qm91bmRhcnkpO1xuICAgIHZhciByZWZlcmVuY2VDbGllbnRSZWN0ID0gZ2V0Qm91bmRpbmdDbGllbnRSZWN0KHN0YXRlLmVsZW1lbnRzLnJlZmVyZW5jZSk7XG4gICAgdmFyIHBvcHBlck9mZnNldHMgPSBjb21wdXRlT2Zmc2V0cyh7XG4gICAgICByZWZlcmVuY2U6IHJlZmVyZW5jZUNsaWVudFJlY3QsXG4gICAgICBlbGVtZW50OiBwb3BwZXJSZWN0LFxuICAgICAgc3RyYXRlZ3k6ICdhYnNvbHV0ZScsXG4gICAgICBwbGFjZW1lbnQ6IHBsYWNlbWVudFxuICAgIH0pO1xuICAgIHZhciBwb3BwZXJDbGllbnRSZWN0ID0gcmVjdFRvQ2xpZW50UmVjdChPYmplY3QuYXNzaWduKHt9LCBwb3BwZXJSZWN0LCBwb3BwZXJPZmZzZXRzKSk7XG4gICAgdmFyIGVsZW1lbnRDbGllbnRSZWN0ID0gZWxlbWVudENvbnRleHQgPT09IHBvcHBlciA/IHBvcHBlckNsaWVudFJlY3QgOiByZWZlcmVuY2VDbGllbnRSZWN0OyAvLyBwb3NpdGl2ZSA9IG92ZXJmbG93aW5nIHRoZSBjbGlwcGluZyByZWN0XG4gICAgLy8gMCBvciBuZWdhdGl2ZSA9IHdpdGhpbiB0aGUgY2xpcHBpbmcgcmVjdFxuXG4gICAgdmFyIG92ZXJmbG93T2Zmc2V0cyA9IHtcbiAgICAgIHRvcDogY2xpcHBpbmdDbGllbnRSZWN0LnRvcCAtIGVsZW1lbnRDbGllbnRSZWN0LnRvcCArIHBhZGRpbmdPYmplY3QudG9wLFxuICAgICAgYm90dG9tOiBlbGVtZW50Q2xpZW50UmVjdC5ib3R0b20gLSBjbGlwcGluZ0NsaWVudFJlY3QuYm90dG9tICsgcGFkZGluZ09iamVjdC5ib3R0b20sXG4gICAgICBsZWZ0OiBjbGlwcGluZ0NsaWVudFJlY3QubGVmdCAtIGVsZW1lbnRDbGllbnRSZWN0LmxlZnQgKyBwYWRkaW5nT2JqZWN0LmxlZnQsXG4gICAgICByaWdodDogZWxlbWVudENsaWVudFJlY3QucmlnaHQgLSBjbGlwcGluZ0NsaWVudFJlY3QucmlnaHQgKyBwYWRkaW5nT2JqZWN0LnJpZ2h0XG4gICAgfTtcbiAgICB2YXIgb2Zmc2V0RGF0YSA9IHN0YXRlLm1vZGlmaWVyc0RhdGEub2Zmc2V0OyAvLyBPZmZzZXRzIGNhbiBiZSBhcHBsaWVkIG9ubHkgdG8gdGhlIHBvcHBlciBlbGVtZW50XG5cbiAgICBpZiAoZWxlbWVudENvbnRleHQgPT09IHBvcHBlciAmJiBvZmZzZXREYXRhKSB7XG4gICAgICB2YXIgb2Zmc2V0ID0gb2Zmc2V0RGF0YVtwbGFjZW1lbnRdO1xuICAgICAgT2JqZWN0LmtleXMob3ZlcmZsb3dPZmZzZXRzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgdmFyIG11bHRpcGx5ID0gW3JpZ2h0LCBib3R0b21dLmluZGV4T2Yoa2V5KSA+PSAwID8gMSA6IC0xO1xuICAgICAgICB2YXIgYXhpcyA9IFt0b3AsIGJvdHRvbV0uaW5kZXhPZihrZXkpID49IDAgPyAneScgOiAneCc7XG4gICAgICAgIG92ZXJmbG93T2Zmc2V0c1trZXldICs9IG9mZnNldFtheGlzXSAqIG11bHRpcGx5O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG92ZXJmbG93T2Zmc2V0cztcbiAgfVxuXG4gIGZ1bmN0aW9uIGNvbXB1dGVBdXRvUGxhY2VtZW50KHN0YXRlLCBvcHRpb25zKSB7XG4gICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkge1xuICAgICAgb3B0aW9ucyA9IHt9O1xuICAgIH1cblxuICAgIHZhciBfb3B0aW9ucyA9IG9wdGlvbnMsXG4gICAgICAgIHBsYWNlbWVudCA9IF9vcHRpb25zLnBsYWNlbWVudCxcbiAgICAgICAgYm91bmRhcnkgPSBfb3B0aW9ucy5ib3VuZGFyeSxcbiAgICAgICAgcm9vdEJvdW5kYXJ5ID0gX29wdGlvbnMucm9vdEJvdW5kYXJ5LFxuICAgICAgICBwYWRkaW5nID0gX29wdGlvbnMucGFkZGluZyxcbiAgICAgICAgZmxpcFZhcmlhdGlvbnMgPSBfb3B0aW9ucy5mbGlwVmFyaWF0aW9ucyxcbiAgICAgICAgX29wdGlvbnMkYWxsb3dlZEF1dG9QID0gX29wdGlvbnMuYWxsb3dlZEF1dG9QbGFjZW1lbnRzLFxuICAgICAgICBhbGxvd2VkQXV0b1BsYWNlbWVudHMgPSBfb3B0aW9ucyRhbGxvd2VkQXV0b1AgPT09IHZvaWQgMCA/IHBsYWNlbWVudHMgOiBfb3B0aW9ucyRhbGxvd2VkQXV0b1A7XG4gICAgdmFyIHZhcmlhdGlvbiA9IGdldFZhcmlhdGlvbihwbGFjZW1lbnQpO1xuICAgIHZhciBwbGFjZW1lbnRzJDEgPSB2YXJpYXRpb24gPyBmbGlwVmFyaWF0aW9ucyA/IHZhcmlhdGlvblBsYWNlbWVudHMgOiB2YXJpYXRpb25QbGFjZW1lbnRzLmZpbHRlcihmdW5jdGlvbiAocGxhY2VtZW50KSB7XG4gICAgICByZXR1cm4gZ2V0VmFyaWF0aW9uKHBsYWNlbWVudCkgPT09IHZhcmlhdGlvbjtcbiAgICB9KSA6IGJhc2VQbGFjZW1lbnRzO1xuICAgIHZhciBhbGxvd2VkUGxhY2VtZW50cyA9IHBsYWNlbWVudHMkMS5maWx0ZXIoZnVuY3Rpb24gKHBsYWNlbWVudCkge1xuICAgICAgcmV0dXJuIGFsbG93ZWRBdXRvUGxhY2VtZW50cy5pbmRleE9mKHBsYWNlbWVudCkgPj0gMDtcbiAgICB9KTtcblxuICAgIGlmIChhbGxvd2VkUGxhY2VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgIGFsbG93ZWRQbGFjZW1lbnRzID0gcGxhY2VtZW50cyQxO1xuICAgIH0gLy8gJEZsb3dGaXhNZVtpbmNvbXBhdGlibGUtdHlwZV06IEZsb3cgc2VlbXMgdG8gaGF2ZSBwcm9ibGVtcyB3aXRoIHR3byBhcnJheSB1bmlvbnMuLi5cblxuXG4gICAgdmFyIG92ZXJmbG93cyA9IGFsbG93ZWRQbGFjZW1lbnRzLnJlZHVjZShmdW5jdGlvbiAoYWNjLCBwbGFjZW1lbnQpIHtcbiAgICAgIGFjY1twbGFjZW1lbnRdID0gZGV0ZWN0T3ZlcmZsb3coc3RhdGUsIHtcbiAgICAgICAgcGxhY2VtZW50OiBwbGFjZW1lbnQsXG4gICAgICAgIGJvdW5kYXJ5OiBib3VuZGFyeSxcbiAgICAgICAgcm9vdEJvdW5kYXJ5OiByb290Qm91bmRhcnksXG4gICAgICAgIHBhZGRpbmc6IHBhZGRpbmdcbiAgICAgIH0pW2dldEJhc2VQbGFjZW1lbnQocGxhY2VtZW50KV07XG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sIHt9KTtcbiAgICByZXR1cm4gT2JqZWN0LmtleXMob3ZlcmZsb3dzKS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICByZXR1cm4gb3ZlcmZsb3dzW2FdIC0gb3ZlcmZsb3dzW2JdO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0RXhwYW5kZWRGYWxsYmFja1BsYWNlbWVudHMocGxhY2VtZW50KSB7XG4gICAgaWYgKGdldEJhc2VQbGFjZW1lbnQocGxhY2VtZW50KSA9PT0gYXV0bykge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHZhciBvcHBvc2l0ZVBsYWNlbWVudCA9IGdldE9wcG9zaXRlUGxhY2VtZW50KHBsYWNlbWVudCk7XG4gICAgcmV0dXJuIFtnZXRPcHBvc2l0ZVZhcmlhdGlvblBsYWNlbWVudChwbGFjZW1lbnQpLCBvcHBvc2l0ZVBsYWNlbWVudCwgZ2V0T3Bwb3NpdGVWYXJpYXRpb25QbGFjZW1lbnQob3Bwb3NpdGVQbGFjZW1lbnQpXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZsaXAoX3JlZikge1xuICAgIHZhciBzdGF0ZSA9IF9yZWYuc3RhdGUsXG4gICAgICAgIG9wdGlvbnMgPSBfcmVmLm9wdGlvbnMsXG4gICAgICAgIG5hbWUgPSBfcmVmLm5hbWU7XG5cbiAgICBpZiAoc3RhdGUubW9kaWZpZXJzRGF0YVtuYW1lXS5fc2tpcCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBfb3B0aW9ucyRtYWluQXhpcyA9IG9wdGlvbnMubWFpbkF4aXMsXG4gICAgICAgIGNoZWNrTWFpbkF4aXMgPSBfb3B0aW9ucyRtYWluQXhpcyA9PT0gdm9pZCAwID8gdHJ1ZSA6IF9vcHRpb25zJG1haW5BeGlzLFxuICAgICAgICBfb3B0aW9ucyRhbHRBeGlzID0gb3B0aW9ucy5hbHRBeGlzLFxuICAgICAgICBjaGVja0FsdEF4aXMgPSBfb3B0aW9ucyRhbHRBeGlzID09PSB2b2lkIDAgPyB0cnVlIDogX29wdGlvbnMkYWx0QXhpcyxcbiAgICAgICAgc3BlY2lmaWVkRmFsbGJhY2tQbGFjZW1lbnRzID0gb3B0aW9ucy5mYWxsYmFja1BsYWNlbWVudHMsXG4gICAgICAgIHBhZGRpbmcgPSBvcHRpb25zLnBhZGRpbmcsXG4gICAgICAgIGJvdW5kYXJ5ID0gb3B0aW9ucy5ib3VuZGFyeSxcbiAgICAgICAgcm9vdEJvdW5kYXJ5ID0gb3B0aW9ucy5yb290Qm91bmRhcnksXG4gICAgICAgIGFsdEJvdW5kYXJ5ID0gb3B0aW9ucy5hbHRCb3VuZGFyeSxcbiAgICAgICAgX29wdGlvbnMkZmxpcFZhcmlhdGlvID0gb3B0aW9ucy5mbGlwVmFyaWF0aW9ucyxcbiAgICAgICAgZmxpcFZhcmlhdGlvbnMgPSBfb3B0aW9ucyRmbGlwVmFyaWF0aW8gPT09IHZvaWQgMCA/IHRydWUgOiBfb3B0aW9ucyRmbGlwVmFyaWF0aW8sXG4gICAgICAgIGFsbG93ZWRBdXRvUGxhY2VtZW50cyA9IG9wdGlvbnMuYWxsb3dlZEF1dG9QbGFjZW1lbnRzO1xuICAgIHZhciBwcmVmZXJyZWRQbGFjZW1lbnQgPSBzdGF0ZS5vcHRpb25zLnBsYWNlbWVudDtcbiAgICB2YXIgYmFzZVBsYWNlbWVudCA9IGdldEJhc2VQbGFjZW1lbnQocHJlZmVycmVkUGxhY2VtZW50KTtcbiAgICB2YXIgaXNCYXNlUGxhY2VtZW50ID0gYmFzZVBsYWNlbWVudCA9PT0gcHJlZmVycmVkUGxhY2VtZW50O1xuICAgIHZhciBmYWxsYmFja1BsYWNlbWVudHMgPSBzcGVjaWZpZWRGYWxsYmFja1BsYWNlbWVudHMgfHwgKGlzQmFzZVBsYWNlbWVudCB8fCAhZmxpcFZhcmlhdGlvbnMgPyBbZ2V0T3Bwb3NpdGVQbGFjZW1lbnQocHJlZmVycmVkUGxhY2VtZW50KV0gOiBnZXRFeHBhbmRlZEZhbGxiYWNrUGxhY2VtZW50cyhwcmVmZXJyZWRQbGFjZW1lbnQpKTtcbiAgICB2YXIgcGxhY2VtZW50cyA9IFtwcmVmZXJyZWRQbGFjZW1lbnRdLmNvbmNhdChmYWxsYmFja1BsYWNlbWVudHMpLnJlZHVjZShmdW5jdGlvbiAoYWNjLCBwbGFjZW1lbnQpIHtcbiAgICAgIHJldHVybiBhY2MuY29uY2F0KGdldEJhc2VQbGFjZW1lbnQocGxhY2VtZW50KSA9PT0gYXV0byA/IGNvbXB1dGVBdXRvUGxhY2VtZW50KHN0YXRlLCB7XG4gICAgICAgIHBsYWNlbWVudDogcGxhY2VtZW50LFxuICAgICAgICBib3VuZGFyeTogYm91bmRhcnksXG4gICAgICAgIHJvb3RCb3VuZGFyeTogcm9vdEJvdW5kYXJ5LFxuICAgICAgICBwYWRkaW5nOiBwYWRkaW5nLFxuICAgICAgICBmbGlwVmFyaWF0aW9uczogZmxpcFZhcmlhdGlvbnMsXG4gICAgICAgIGFsbG93ZWRBdXRvUGxhY2VtZW50czogYWxsb3dlZEF1dG9QbGFjZW1lbnRzXG4gICAgICB9KSA6IHBsYWNlbWVudCk7XG4gICAgfSwgW10pO1xuICAgIHZhciByZWZlcmVuY2VSZWN0ID0gc3RhdGUucmVjdHMucmVmZXJlbmNlO1xuICAgIHZhciBwb3BwZXJSZWN0ID0gc3RhdGUucmVjdHMucG9wcGVyO1xuICAgIHZhciBjaGVja3NNYXAgPSBuZXcgTWFwKCk7XG4gICAgdmFyIG1ha2VGYWxsYmFja0NoZWNrcyA9IHRydWU7XG4gICAgdmFyIGZpcnN0Rml0dGluZ1BsYWNlbWVudCA9IHBsYWNlbWVudHNbMF07XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBsYWNlbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBwbGFjZW1lbnQgPSBwbGFjZW1lbnRzW2ldO1xuXG4gICAgICB2YXIgX2Jhc2VQbGFjZW1lbnQgPSBnZXRCYXNlUGxhY2VtZW50KHBsYWNlbWVudCk7XG5cbiAgICAgIHZhciBpc1N0YXJ0VmFyaWF0aW9uID0gZ2V0VmFyaWF0aW9uKHBsYWNlbWVudCkgPT09IHN0YXJ0O1xuICAgICAgdmFyIGlzVmVydGljYWwgPSBbdG9wLCBib3R0b21dLmluZGV4T2YoX2Jhc2VQbGFjZW1lbnQpID49IDA7XG4gICAgICB2YXIgbGVuID0gaXNWZXJ0aWNhbCA/ICd3aWR0aCcgOiAnaGVpZ2h0JztcbiAgICAgIHZhciBvdmVyZmxvdyA9IGRldGVjdE92ZXJmbG93KHN0YXRlLCB7XG4gICAgICAgIHBsYWNlbWVudDogcGxhY2VtZW50LFxuICAgICAgICBib3VuZGFyeTogYm91bmRhcnksXG4gICAgICAgIHJvb3RCb3VuZGFyeTogcm9vdEJvdW5kYXJ5LFxuICAgICAgICBhbHRCb3VuZGFyeTogYWx0Qm91bmRhcnksXG4gICAgICAgIHBhZGRpbmc6IHBhZGRpbmdcbiAgICAgIH0pO1xuICAgICAgdmFyIG1haW5WYXJpYXRpb25TaWRlID0gaXNWZXJ0aWNhbCA/IGlzU3RhcnRWYXJpYXRpb24gPyByaWdodCA6IGxlZnQgOiBpc1N0YXJ0VmFyaWF0aW9uID8gYm90dG9tIDogdG9wO1xuXG4gICAgICBpZiAocmVmZXJlbmNlUmVjdFtsZW5dID4gcG9wcGVyUmVjdFtsZW5dKSB7XG4gICAgICAgIG1haW5WYXJpYXRpb25TaWRlID0gZ2V0T3Bwb3NpdGVQbGFjZW1lbnQobWFpblZhcmlhdGlvblNpZGUpO1xuICAgICAgfVxuXG4gICAgICB2YXIgYWx0VmFyaWF0aW9uU2lkZSA9IGdldE9wcG9zaXRlUGxhY2VtZW50KG1haW5WYXJpYXRpb25TaWRlKTtcbiAgICAgIHZhciBjaGVja3MgPSBbXTtcblxuICAgICAgaWYgKGNoZWNrTWFpbkF4aXMpIHtcbiAgICAgICAgY2hlY2tzLnB1c2gob3ZlcmZsb3dbX2Jhc2VQbGFjZW1lbnRdIDw9IDApO1xuICAgICAgfVxuXG4gICAgICBpZiAoY2hlY2tBbHRBeGlzKSB7XG4gICAgICAgIGNoZWNrcy5wdXNoKG92ZXJmbG93W21haW5WYXJpYXRpb25TaWRlXSA8PSAwLCBvdmVyZmxvd1thbHRWYXJpYXRpb25TaWRlXSA8PSAwKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNoZWNrcy5ldmVyeShmdW5jdGlvbiAoY2hlY2spIHtcbiAgICAgICAgcmV0dXJuIGNoZWNrO1xuICAgICAgfSkpIHtcbiAgICAgICAgZmlyc3RGaXR0aW5nUGxhY2VtZW50ID0gcGxhY2VtZW50O1xuICAgICAgICBtYWtlRmFsbGJhY2tDaGVja3MgPSBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIGNoZWNrc01hcC5zZXQocGxhY2VtZW50LCBjaGVja3MpO1xuICAgIH1cblxuICAgIGlmIChtYWtlRmFsbGJhY2tDaGVja3MpIHtcbiAgICAgIC8vIGAyYCBtYXkgYmUgZGVzaXJlZCBpbiBzb21lIGNhc2VzIOKAkyByZXNlYXJjaCBsYXRlclxuICAgICAgdmFyIG51bWJlck9mQ2hlY2tzID0gZmxpcFZhcmlhdGlvbnMgPyAzIDogMTtcblxuICAgICAgdmFyIF9sb29wID0gZnVuY3Rpb24gX2xvb3AoX2kpIHtcbiAgICAgICAgdmFyIGZpdHRpbmdQbGFjZW1lbnQgPSBwbGFjZW1lbnRzLmZpbmQoZnVuY3Rpb24gKHBsYWNlbWVudCkge1xuICAgICAgICAgIHZhciBjaGVja3MgPSBjaGVja3NNYXAuZ2V0KHBsYWNlbWVudCk7XG5cbiAgICAgICAgICBpZiAoY2hlY2tzKSB7XG4gICAgICAgICAgICByZXR1cm4gY2hlY2tzLnNsaWNlKDAsIF9pKS5ldmVyeShmdW5jdGlvbiAoY2hlY2spIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGNoZWNrO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoZml0dGluZ1BsYWNlbWVudCkge1xuICAgICAgICAgIGZpcnN0Rml0dGluZ1BsYWNlbWVudCA9IGZpdHRpbmdQbGFjZW1lbnQ7XG4gICAgICAgICAgcmV0dXJuIFwiYnJlYWtcIjtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgZm9yICh2YXIgX2kgPSBudW1iZXJPZkNoZWNrczsgX2kgPiAwOyBfaS0tKSB7XG4gICAgICAgIHZhciBfcmV0ID0gX2xvb3AoX2kpO1xuXG4gICAgICAgIGlmIChfcmV0ID09PSBcImJyZWFrXCIpIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzdGF0ZS5wbGFjZW1lbnQgIT09IGZpcnN0Rml0dGluZ1BsYWNlbWVudCkge1xuICAgICAgc3RhdGUubW9kaWZpZXJzRGF0YVtuYW1lXS5fc2tpcCA9IHRydWU7XG4gICAgICBzdGF0ZS5wbGFjZW1lbnQgPSBmaXJzdEZpdHRpbmdQbGFjZW1lbnQ7XG4gICAgICBzdGF0ZS5yZXNldCA9IHRydWU7XG4gICAgfVxuICB9IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tdW51c2VkLW1vZHVsZXNcblxuXG4gIGNvbnN0IGZsaXAkMSA9IHtcbiAgICBuYW1lOiAnZmxpcCcsXG4gICAgZW5hYmxlZDogdHJ1ZSxcbiAgICBwaGFzZTogJ21haW4nLFxuICAgIGZuOiBmbGlwLFxuICAgIHJlcXVpcmVzSWZFeGlzdHM6IFsnb2Zmc2V0J10sXG4gICAgZGF0YToge1xuICAgICAgX3NraXA6IGZhbHNlXG4gICAgfVxuICB9O1xuXG4gIGZ1bmN0aW9uIGdldFNpZGVPZmZzZXRzKG92ZXJmbG93LCByZWN0LCBwcmV2ZW50ZWRPZmZzZXRzKSB7XG4gICAgaWYgKHByZXZlbnRlZE9mZnNldHMgPT09IHZvaWQgMCkge1xuICAgICAgcHJldmVudGVkT2Zmc2V0cyA9IHtcbiAgICAgICAgeDogMCxcbiAgICAgICAgeTogMFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdG9wOiBvdmVyZmxvdy50b3AgLSByZWN0LmhlaWdodCAtIHByZXZlbnRlZE9mZnNldHMueSxcbiAgICAgIHJpZ2h0OiBvdmVyZmxvdy5yaWdodCAtIHJlY3Qud2lkdGggKyBwcmV2ZW50ZWRPZmZzZXRzLngsXG4gICAgICBib3R0b206IG92ZXJmbG93LmJvdHRvbSAtIHJlY3QuaGVpZ2h0ICsgcHJldmVudGVkT2Zmc2V0cy55LFxuICAgICAgbGVmdDogb3ZlcmZsb3cubGVmdCAtIHJlY3Qud2lkdGggLSBwcmV2ZW50ZWRPZmZzZXRzLnhcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gaXNBbnlTaWRlRnVsbHlDbGlwcGVkKG92ZXJmbG93KSB7XG4gICAgcmV0dXJuIFt0b3AsIHJpZ2h0LCBib3R0b20sIGxlZnRdLnNvbWUoZnVuY3Rpb24gKHNpZGUpIHtcbiAgICAgIHJldHVybiBvdmVyZmxvd1tzaWRlXSA+PSAwO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gaGlkZShfcmVmKSB7XG4gICAgdmFyIHN0YXRlID0gX3JlZi5zdGF0ZSxcbiAgICAgICAgbmFtZSA9IF9yZWYubmFtZTtcbiAgICB2YXIgcmVmZXJlbmNlUmVjdCA9IHN0YXRlLnJlY3RzLnJlZmVyZW5jZTtcbiAgICB2YXIgcG9wcGVyUmVjdCA9IHN0YXRlLnJlY3RzLnBvcHBlcjtcbiAgICB2YXIgcHJldmVudGVkT2Zmc2V0cyA9IHN0YXRlLm1vZGlmaWVyc0RhdGEucHJldmVudE92ZXJmbG93O1xuICAgIHZhciByZWZlcmVuY2VPdmVyZmxvdyA9IGRldGVjdE92ZXJmbG93KHN0YXRlLCB7XG4gICAgICBlbGVtZW50Q29udGV4dDogJ3JlZmVyZW5jZSdcbiAgICB9KTtcbiAgICB2YXIgcG9wcGVyQWx0T3ZlcmZsb3cgPSBkZXRlY3RPdmVyZmxvdyhzdGF0ZSwge1xuICAgICAgYWx0Qm91bmRhcnk6IHRydWVcbiAgICB9KTtcbiAgICB2YXIgcmVmZXJlbmNlQ2xpcHBpbmdPZmZzZXRzID0gZ2V0U2lkZU9mZnNldHMocmVmZXJlbmNlT3ZlcmZsb3csIHJlZmVyZW5jZVJlY3QpO1xuICAgIHZhciBwb3BwZXJFc2NhcGVPZmZzZXRzID0gZ2V0U2lkZU9mZnNldHMocG9wcGVyQWx0T3ZlcmZsb3csIHBvcHBlclJlY3QsIHByZXZlbnRlZE9mZnNldHMpO1xuICAgIHZhciBpc1JlZmVyZW5jZUhpZGRlbiA9IGlzQW55U2lkZUZ1bGx5Q2xpcHBlZChyZWZlcmVuY2VDbGlwcGluZ09mZnNldHMpO1xuICAgIHZhciBoYXNQb3BwZXJFc2NhcGVkID0gaXNBbnlTaWRlRnVsbHlDbGlwcGVkKHBvcHBlckVzY2FwZU9mZnNldHMpO1xuICAgIHN0YXRlLm1vZGlmaWVyc0RhdGFbbmFtZV0gPSB7XG4gICAgICByZWZlcmVuY2VDbGlwcGluZ09mZnNldHM6IHJlZmVyZW5jZUNsaXBwaW5nT2Zmc2V0cyxcbiAgICAgIHBvcHBlckVzY2FwZU9mZnNldHM6IHBvcHBlckVzY2FwZU9mZnNldHMsXG4gICAgICBpc1JlZmVyZW5jZUhpZGRlbjogaXNSZWZlcmVuY2VIaWRkZW4sXG4gICAgICBoYXNQb3BwZXJFc2NhcGVkOiBoYXNQb3BwZXJFc2NhcGVkXG4gICAgfTtcbiAgICBzdGF0ZS5hdHRyaWJ1dGVzLnBvcHBlciA9IE9iamVjdC5hc3NpZ24oe30sIHN0YXRlLmF0dHJpYnV0ZXMucG9wcGVyLCB7XG4gICAgICAnZGF0YS1wb3BwZXItcmVmZXJlbmNlLWhpZGRlbic6IGlzUmVmZXJlbmNlSGlkZGVuLFxuICAgICAgJ2RhdGEtcG9wcGVyLWVzY2FwZWQnOiBoYXNQb3BwZXJFc2NhcGVkXG4gICAgfSk7XG4gIH0gLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby11bnVzZWQtbW9kdWxlc1xuXG5cbiAgY29uc3QgaGlkZSQxID0ge1xuICAgIG5hbWU6ICdoaWRlJyxcbiAgICBlbmFibGVkOiB0cnVlLFxuICAgIHBoYXNlOiAnbWFpbicsXG4gICAgcmVxdWlyZXNJZkV4aXN0czogWydwcmV2ZW50T3ZlcmZsb3cnXSxcbiAgICBmbjogaGlkZVxuICB9O1xuXG4gIGZ1bmN0aW9uIGRpc3RhbmNlQW5kU2tpZGRpbmdUb1hZKHBsYWNlbWVudCwgcmVjdHMsIG9mZnNldCkge1xuICAgIHZhciBiYXNlUGxhY2VtZW50ID0gZ2V0QmFzZVBsYWNlbWVudChwbGFjZW1lbnQpO1xuICAgIHZhciBpbnZlcnREaXN0YW5jZSA9IFtsZWZ0LCB0b3BdLmluZGV4T2YoYmFzZVBsYWNlbWVudCkgPj0gMCA/IC0xIDogMTtcblxuICAgIHZhciBfcmVmID0gdHlwZW9mIG9mZnNldCA9PT0gJ2Z1bmN0aW9uJyA/IG9mZnNldChPYmplY3QuYXNzaWduKHt9LCByZWN0cywge1xuICAgICAgcGxhY2VtZW50OiBwbGFjZW1lbnRcbiAgICB9KSkgOiBvZmZzZXQsXG4gICAgICAgIHNraWRkaW5nID0gX3JlZlswXSxcbiAgICAgICAgZGlzdGFuY2UgPSBfcmVmWzFdO1xuXG4gICAgc2tpZGRpbmcgPSBza2lkZGluZyB8fCAwO1xuICAgIGRpc3RhbmNlID0gKGRpc3RhbmNlIHx8IDApICogaW52ZXJ0RGlzdGFuY2U7XG4gICAgcmV0dXJuIFtsZWZ0LCByaWdodF0uaW5kZXhPZihiYXNlUGxhY2VtZW50KSA+PSAwID8ge1xuICAgICAgeDogZGlzdGFuY2UsXG4gICAgICB5OiBza2lkZGluZ1xuICAgIH0gOiB7XG4gICAgICB4OiBza2lkZGluZyxcbiAgICAgIHk6IGRpc3RhbmNlXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG9mZnNldChfcmVmMikge1xuICAgIHZhciBzdGF0ZSA9IF9yZWYyLnN0YXRlLFxuICAgICAgICBvcHRpb25zID0gX3JlZjIub3B0aW9ucyxcbiAgICAgICAgbmFtZSA9IF9yZWYyLm5hbWU7XG4gICAgdmFyIF9vcHRpb25zJG9mZnNldCA9IG9wdGlvbnMub2Zmc2V0LFxuICAgICAgICBvZmZzZXQgPSBfb3B0aW9ucyRvZmZzZXQgPT09IHZvaWQgMCA/IFswLCAwXSA6IF9vcHRpb25zJG9mZnNldDtcbiAgICB2YXIgZGF0YSA9IHBsYWNlbWVudHMucmVkdWNlKGZ1bmN0aW9uIChhY2MsIHBsYWNlbWVudCkge1xuICAgICAgYWNjW3BsYWNlbWVudF0gPSBkaXN0YW5jZUFuZFNraWRkaW5nVG9YWShwbGFjZW1lbnQsIHN0YXRlLnJlY3RzLCBvZmZzZXQpO1xuICAgICAgcmV0dXJuIGFjYztcbiAgICB9LCB7fSk7XG4gICAgdmFyIF9kYXRhJHN0YXRlJHBsYWNlbWVudCA9IGRhdGFbc3RhdGUucGxhY2VtZW50XSxcbiAgICAgICAgeCA9IF9kYXRhJHN0YXRlJHBsYWNlbWVudC54LFxuICAgICAgICB5ID0gX2RhdGEkc3RhdGUkcGxhY2VtZW50Lnk7XG5cbiAgICBpZiAoc3RhdGUubW9kaWZpZXJzRGF0YS5wb3BwZXJPZmZzZXRzICE9IG51bGwpIHtcbiAgICAgIHN0YXRlLm1vZGlmaWVyc0RhdGEucG9wcGVyT2Zmc2V0cy54ICs9IHg7XG4gICAgICBzdGF0ZS5tb2RpZmllcnNEYXRhLnBvcHBlck9mZnNldHMueSArPSB5O1xuICAgIH1cblxuICAgIHN0YXRlLm1vZGlmaWVyc0RhdGFbbmFtZV0gPSBkYXRhO1xuICB9IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tdW51c2VkLW1vZHVsZXNcblxuXG4gIGNvbnN0IG9mZnNldCQxID0ge1xuICAgIG5hbWU6ICdvZmZzZXQnLFxuICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgcGhhc2U6ICdtYWluJyxcbiAgICByZXF1aXJlczogWydwb3BwZXJPZmZzZXRzJ10sXG4gICAgZm46IG9mZnNldFxuICB9O1xuXG4gIGZ1bmN0aW9uIHBvcHBlck9mZnNldHMoX3JlZikge1xuICAgIHZhciBzdGF0ZSA9IF9yZWYuc3RhdGUsXG4gICAgICAgIG5hbWUgPSBfcmVmLm5hbWU7XG4gICAgLy8gT2Zmc2V0cyBhcmUgdGhlIGFjdHVhbCBwb3NpdGlvbiB0aGUgcG9wcGVyIG5lZWRzIHRvIGhhdmUgdG8gYmVcbiAgICAvLyBwcm9wZXJseSBwb3NpdGlvbmVkIG5lYXIgaXRzIHJlZmVyZW5jZSBlbGVtZW50XG4gICAgLy8gVGhpcyBpcyB0aGUgbW9zdCBiYXNpYyBwbGFjZW1lbnQsIGFuZCB3aWxsIGJlIGFkanVzdGVkIGJ5XG4gICAgLy8gdGhlIG1vZGlmaWVycyBpbiB0aGUgbmV4dCBzdGVwXG4gICAgc3RhdGUubW9kaWZpZXJzRGF0YVtuYW1lXSA9IGNvbXB1dGVPZmZzZXRzKHtcbiAgICAgIHJlZmVyZW5jZTogc3RhdGUucmVjdHMucmVmZXJlbmNlLFxuICAgICAgZWxlbWVudDogc3RhdGUucmVjdHMucG9wcGVyLFxuICAgICAgc3RyYXRlZ3k6ICdhYnNvbHV0ZScsXG4gICAgICBwbGFjZW1lbnQ6IHN0YXRlLnBsYWNlbWVudFxuICAgIH0pO1xuICB9IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tdW51c2VkLW1vZHVsZXNcblxuXG4gIGNvbnN0IHBvcHBlck9mZnNldHMkMSA9IHtcbiAgICBuYW1lOiAncG9wcGVyT2Zmc2V0cycsXG4gICAgZW5hYmxlZDogdHJ1ZSxcbiAgICBwaGFzZTogJ3JlYWQnLFxuICAgIGZuOiBwb3BwZXJPZmZzZXRzLFxuICAgIGRhdGE6IHt9XG4gIH07XG5cbiAgZnVuY3Rpb24gZ2V0QWx0QXhpcyhheGlzKSB7XG4gICAgcmV0dXJuIGF4aXMgPT09ICd4JyA/ICd5JyA6ICd4JztcbiAgfVxuXG4gIGZ1bmN0aW9uIHByZXZlbnRPdmVyZmxvdyhfcmVmKSB7XG4gICAgdmFyIHN0YXRlID0gX3JlZi5zdGF0ZSxcbiAgICAgICAgb3B0aW9ucyA9IF9yZWYub3B0aW9ucyxcbiAgICAgICAgbmFtZSA9IF9yZWYubmFtZTtcbiAgICB2YXIgX29wdGlvbnMkbWFpbkF4aXMgPSBvcHRpb25zLm1haW5BeGlzLFxuICAgICAgICBjaGVja01haW5BeGlzID0gX29wdGlvbnMkbWFpbkF4aXMgPT09IHZvaWQgMCA/IHRydWUgOiBfb3B0aW9ucyRtYWluQXhpcyxcbiAgICAgICAgX29wdGlvbnMkYWx0QXhpcyA9IG9wdGlvbnMuYWx0QXhpcyxcbiAgICAgICAgY2hlY2tBbHRBeGlzID0gX29wdGlvbnMkYWx0QXhpcyA9PT0gdm9pZCAwID8gZmFsc2UgOiBfb3B0aW9ucyRhbHRBeGlzLFxuICAgICAgICBib3VuZGFyeSA9IG9wdGlvbnMuYm91bmRhcnksXG4gICAgICAgIHJvb3RCb3VuZGFyeSA9IG9wdGlvbnMucm9vdEJvdW5kYXJ5LFxuICAgICAgICBhbHRCb3VuZGFyeSA9IG9wdGlvbnMuYWx0Qm91bmRhcnksXG4gICAgICAgIHBhZGRpbmcgPSBvcHRpb25zLnBhZGRpbmcsXG4gICAgICAgIF9vcHRpb25zJHRldGhlciA9IG9wdGlvbnMudGV0aGVyLFxuICAgICAgICB0ZXRoZXIgPSBfb3B0aW9ucyR0ZXRoZXIgPT09IHZvaWQgMCA/IHRydWUgOiBfb3B0aW9ucyR0ZXRoZXIsXG4gICAgICAgIF9vcHRpb25zJHRldGhlck9mZnNldCA9IG9wdGlvbnMudGV0aGVyT2Zmc2V0LFxuICAgICAgICB0ZXRoZXJPZmZzZXQgPSBfb3B0aW9ucyR0ZXRoZXJPZmZzZXQgPT09IHZvaWQgMCA/IDAgOiBfb3B0aW9ucyR0ZXRoZXJPZmZzZXQ7XG4gICAgdmFyIG92ZXJmbG93ID0gZGV0ZWN0T3ZlcmZsb3coc3RhdGUsIHtcbiAgICAgIGJvdW5kYXJ5OiBib3VuZGFyeSxcbiAgICAgIHJvb3RCb3VuZGFyeTogcm9vdEJvdW5kYXJ5LFxuICAgICAgcGFkZGluZzogcGFkZGluZyxcbiAgICAgIGFsdEJvdW5kYXJ5OiBhbHRCb3VuZGFyeVxuICAgIH0pO1xuICAgIHZhciBiYXNlUGxhY2VtZW50ID0gZ2V0QmFzZVBsYWNlbWVudChzdGF0ZS5wbGFjZW1lbnQpO1xuICAgIHZhciB2YXJpYXRpb24gPSBnZXRWYXJpYXRpb24oc3RhdGUucGxhY2VtZW50KTtcbiAgICB2YXIgaXNCYXNlUGxhY2VtZW50ID0gIXZhcmlhdGlvbjtcbiAgICB2YXIgbWFpbkF4aXMgPSBnZXRNYWluQXhpc0Zyb21QbGFjZW1lbnQoYmFzZVBsYWNlbWVudCk7XG4gICAgdmFyIGFsdEF4aXMgPSBnZXRBbHRBeGlzKG1haW5BeGlzKTtcbiAgICB2YXIgcG9wcGVyT2Zmc2V0cyA9IHN0YXRlLm1vZGlmaWVyc0RhdGEucG9wcGVyT2Zmc2V0cztcbiAgICB2YXIgcmVmZXJlbmNlUmVjdCA9IHN0YXRlLnJlY3RzLnJlZmVyZW5jZTtcbiAgICB2YXIgcG9wcGVyUmVjdCA9IHN0YXRlLnJlY3RzLnBvcHBlcjtcbiAgICB2YXIgdGV0aGVyT2Zmc2V0VmFsdWUgPSB0eXBlb2YgdGV0aGVyT2Zmc2V0ID09PSAnZnVuY3Rpb24nID8gdGV0aGVyT2Zmc2V0KE9iamVjdC5hc3NpZ24oe30sIHN0YXRlLnJlY3RzLCB7XG4gICAgICBwbGFjZW1lbnQ6IHN0YXRlLnBsYWNlbWVudFxuICAgIH0pKSA6IHRldGhlck9mZnNldDtcbiAgICB2YXIgZGF0YSA9IHtcbiAgICAgIHg6IDAsXG4gICAgICB5OiAwXG4gICAgfTtcblxuICAgIGlmICghcG9wcGVyT2Zmc2V0cykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjaGVja01haW5BeGlzIHx8IGNoZWNrQWx0QXhpcykge1xuICAgICAgdmFyIG1haW5TaWRlID0gbWFpbkF4aXMgPT09ICd5JyA/IHRvcCA6IGxlZnQ7XG4gICAgICB2YXIgYWx0U2lkZSA9IG1haW5BeGlzID09PSAneScgPyBib3R0b20gOiByaWdodDtcbiAgICAgIHZhciBsZW4gPSBtYWluQXhpcyA9PT0gJ3knID8gJ2hlaWdodCcgOiAnd2lkdGgnO1xuICAgICAgdmFyIG9mZnNldCA9IHBvcHBlck9mZnNldHNbbWFpbkF4aXNdO1xuICAgICAgdmFyIG1pbiQxID0gcG9wcGVyT2Zmc2V0c1ttYWluQXhpc10gKyBvdmVyZmxvd1ttYWluU2lkZV07XG4gICAgICB2YXIgbWF4JDEgPSBwb3BwZXJPZmZzZXRzW21haW5BeGlzXSAtIG92ZXJmbG93W2FsdFNpZGVdO1xuICAgICAgdmFyIGFkZGl0aXZlID0gdGV0aGVyID8gLXBvcHBlclJlY3RbbGVuXSAvIDIgOiAwO1xuICAgICAgdmFyIG1pbkxlbiA9IHZhcmlhdGlvbiA9PT0gc3RhcnQgPyByZWZlcmVuY2VSZWN0W2xlbl0gOiBwb3BwZXJSZWN0W2xlbl07XG4gICAgICB2YXIgbWF4TGVuID0gdmFyaWF0aW9uID09PSBzdGFydCA/IC1wb3BwZXJSZWN0W2xlbl0gOiAtcmVmZXJlbmNlUmVjdFtsZW5dOyAvLyBXZSBuZWVkIHRvIGluY2x1ZGUgdGhlIGFycm93IGluIHRoZSBjYWxjdWxhdGlvbiBzbyB0aGUgYXJyb3cgZG9lc24ndCBnb1xuICAgICAgLy8gb3V0c2lkZSB0aGUgcmVmZXJlbmNlIGJvdW5kc1xuXG4gICAgICB2YXIgYXJyb3dFbGVtZW50ID0gc3RhdGUuZWxlbWVudHMuYXJyb3c7XG4gICAgICB2YXIgYXJyb3dSZWN0ID0gdGV0aGVyICYmIGFycm93RWxlbWVudCA/IGdldExheW91dFJlY3QoYXJyb3dFbGVtZW50KSA6IHtcbiAgICAgICAgd2lkdGg6IDAsXG4gICAgICAgIGhlaWdodDogMFxuICAgICAgfTtcbiAgICAgIHZhciBhcnJvd1BhZGRpbmdPYmplY3QgPSBzdGF0ZS5tb2RpZmllcnNEYXRhWydhcnJvdyNwZXJzaXN0ZW50J10gPyBzdGF0ZS5tb2RpZmllcnNEYXRhWydhcnJvdyNwZXJzaXN0ZW50J10ucGFkZGluZyA6IGdldEZyZXNoU2lkZU9iamVjdCgpO1xuICAgICAgdmFyIGFycm93UGFkZGluZ01pbiA9IGFycm93UGFkZGluZ09iamVjdFttYWluU2lkZV07XG4gICAgICB2YXIgYXJyb3dQYWRkaW5nTWF4ID0gYXJyb3dQYWRkaW5nT2JqZWN0W2FsdFNpZGVdOyAvLyBJZiB0aGUgcmVmZXJlbmNlIGxlbmd0aCBpcyBzbWFsbGVyIHRoYW4gdGhlIGFycm93IGxlbmd0aCwgd2UgZG9uJ3Qgd2FudFxuICAgICAgLy8gdG8gaW5jbHVkZSBpdHMgZnVsbCBzaXplIGluIHRoZSBjYWxjdWxhdGlvbi4gSWYgdGhlIHJlZmVyZW5jZSBpcyBzbWFsbFxuICAgICAgLy8gYW5kIG5lYXIgdGhlIGVkZ2Ugb2YgYSBib3VuZGFyeSwgdGhlIHBvcHBlciBjYW4gb3ZlcmZsb3cgZXZlbiBpZiB0aGVcbiAgICAgIC8vIHJlZmVyZW5jZSBpcyBub3Qgb3ZlcmZsb3dpbmcgYXMgd2VsbCAoZS5nLiB2aXJ0dWFsIGVsZW1lbnRzIHdpdGggbm9cbiAgICAgIC8vIHdpZHRoIG9yIGhlaWdodClcblxuICAgICAgdmFyIGFycm93TGVuID0gd2l0aGluKDAsIHJlZmVyZW5jZVJlY3RbbGVuXSwgYXJyb3dSZWN0W2xlbl0pO1xuICAgICAgdmFyIG1pbk9mZnNldCA9IGlzQmFzZVBsYWNlbWVudCA/IHJlZmVyZW5jZVJlY3RbbGVuXSAvIDIgLSBhZGRpdGl2ZSAtIGFycm93TGVuIC0gYXJyb3dQYWRkaW5nTWluIC0gdGV0aGVyT2Zmc2V0VmFsdWUgOiBtaW5MZW4gLSBhcnJvd0xlbiAtIGFycm93UGFkZGluZ01pbiAtIHRldGhlck9mZnNldFZhbHVlO1xuICAgICAgdmFyIG1heE9mZnNldCA9IGlzQmFzZVBsYWNlbWVudCA/IC1yZWZlcmVuY2VSZWN0W2xlbl0gLyAyICsgYWRkaXRpdmUgKyBhcnJvd0xlbiArIGFycm93UGFkZGluZ01heCArIHRldGhlck9mZnNldFZhbHVlIDogbWF4TGVuICsgYXJyb3dMZW4gKyBhcnJvd1BhZGRpbmdNYXggKyB0ZXRoZXJPZmZzZXRWYWx1ZTtcbiAgICAgIHZhciBhcnJvd09mZnNldFBhcmVudCA9IHN0YXRlLmVsZW1lbnRzLmFycm93ICYmIGdldE9mZnNldFBhcmVudChzdGF0ZS5lbGVtZW50cy5hcnJvdyk7XG4gICAgICB2YXIgY2xpZW50T2Zmc2V0ID0gYXJyb3dPZmZzZXRQYXJlbnQgPyBtYWluQXhpcyA9PT0gJ3knID8gYXJyb3dPZmZzZXRQYXJlbnQuY2xpZW50VG9wIHx8IDAgOiBhcnJvd09mZnNldFBhcmVudC5jbGllbnRMZWZ0IHx8IDAgOiAwO1xuICAgICAgdmFyIG9mZnNldE1vZGlmaWVyVmFsdWUgPSBzdGF0ZS5tb2RpZmllcnNEYXRhLm9mZnNldCA/IHN0YXRlLm1vZGlmaWVyc0RhdGEub2Zmc2V0W3N0YXRlLnBsYWNlbWVudF1bbWFpbkF4aXNdIDogMDtcbiAgICAgIHZhciB0ZXRoZXJNaW4gPSBwb3BwZXJPZmZzZXRzW21haW5BeGlzXSArIG1pbk9mZnNldCAtIG9mZnNldE1vZGlmaWVyVmFsdWUgLSBjbGllbnRPZmZzZXQ7XG4gICAgICB2YXIgdGV0aGVyTWF4ID0gcG9wcGVyT2Zmc2V0c1ttYWluQXhpc10gKyBtYXhPZmZzZXQgLSBvZmZzZXRNb2RpZmllclZhbHVlO1xuXG4gICAgICBpZiAoY2hlY2tNYWluQXhpcykge1xuICAgICAgICB2YXIgcHJldmVudGVkT2Zmc2V0ID0gd2l0aGluKHRldGhlciA/IG1pbihtaW4kMSwgdGV0aGVyTWluKSA6IG1pbiQxLCBvZmZzZXQsIHRldGhlciA/IG1heChtYXgkMSwgdGV0aGVyTWF4KSA6IG1heCQxKTtcbiAgICAgICAgcG9wcGVyT2Zmc2V0c1ttYWluQXhpc10gPSBwcmV2ZW50ZWRPZmZzZXQ7XG4gICAgICAgIGRhdGFbbWFpbkF4aXNdID0gcHJldmVudGVkT2Zmc2V0IC0gb2Zmc2V0O1xuICAgICAgfVxuXG4gICAgICBpZiAoY2hlY2tBbHRBeGlzKSB7XG4gICAgICAgIHZhciBfbWFpblNpZGUgPSBtYWluQXhpcyA9PT0gJ3gnID8gdG9wIDogbGVmdDtcblxuICAgICAgICB2YXIgX2FsdFNpZGUgPSBtYWluQXhpcyA9PT0gJ3gnID8gYm90dG9tIDogcmlnaHQ7XG5cbiAgICAgICAgdmFyIF9vZmZzZXQgPSBwb3BwZXJPZmZzZXRzW2FsdEF4aXNdO1xuXG4gICAgICAgIHZhciBfbWluID0gX29mZnNldCArIG92ZXJmbG93W19tYWluU2lkZV07XG5cbiAgICAgICAgdmFyIF9tYXggPSBfb2Zmc2V0IC0gb3ZlcmZsb3dbX2FsdFNpZGVdO1xuXG4gICAgICAgIHZhciBfcHJldmVudGVkT2Zmc2V0ID0gd2l0aGluKHRldGhlciA/IG1pbihfbWluLCB0ZXRoZXJNaW4pIDogX21pbiwgX29mZnNldCwgdGV0aGVyID8gbWF4KF9tYXgsIHRldGhlck1heCkgOiBfbWF4KTtcblxuICAgICAgICBwb3BwZXJPZmZzZXRzW2FsdEF4aXNdID0gX3ByZXZlbnRlZE9mZnNldDtcbiAgICAgICAgZGF0YVthbHRBeGlzXSA9IF9wcmV2ZW50ZWRPZmZzZXQgLSBfb2Zmc2V0O1xuICAgICAgfVxuICAgIH1cblxuICAgIHN0YXRlLm1vZGlmaWVyc0RhdGFbbmFtZV0gPSBkYXRhO1xuICB9IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tdW51c2VkLW1vZHVsZXNcblxuXG4gIGNvbnN0IHByZXZlbnRPdmVyZmxvdyQxID0ge1xuICAgIG5hbWU6ICdwcmV2ZW50T3ZlcmZsb3cnLFxuICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgcGhhc2U6ICdtYWluJyxcbiAgICBmbjogcHJldmVudE92ZXJmbG93LFxuICAgIHJlcXVpcmVzSWZFeGlzdHM6IFsnb2Zmc2V0J11cbiAgfTtcblxuICBmdW5jdGlvbiBnZXRIVE1MRWxlbWVudFNjcm9sbChlbGVtZW50KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNjcm9sbExlZnQ6IGVsZW1lbnQuc2Nyb2xsTGVmdCxcbiAgICAgIHNjcm9sbFRvcDogZWxlbWVudC5zY3JvbGxUb3BcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0Tm9kZVNjcm9sbChub2RlKSB7XG4gICAgaWYgKG5vZGUgPT09IGdldFdpbmRvdyhub2RlKSB8fCAhaXNIVE1MRWxlbWVudChub2RlKSkge1xuICAgICAgcmV0dXJuIGdldFdpbmRvd1Njcm9sbChub2RlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGdldEhUTUxFbGVtZW50U2Nyb2xsKG5vZGUpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGlzRWxlbWVudFNjYWxlZChlbGVtZW50KSB7XG4gICAgdmFyIHJlY3QgPSBlbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHZhciBzY2FsZVggPSByZWN0LndpZHRoIC8gZWxlbWVudC5vZmZzZXRXaWR0aCB8fCAxO1xuICAgIHZhciBzY2FsZVkgPSByZWN0LmhlaWdodCAvIGVsZW1lbnQub2Zmc2V0SGVpZ2h0IHx8IDE7XG4gICAgcmV0dXJuIHNjYWxlWCAhPT0gMSB8fCBzY2FsZVkgIT09IDE7XG4gIH0gLy8gUmV0dXJucyB0aGUgY29tcG9zaXRlIHJlY3Qgb2YgYW4gZWxlbWVudCByZWxhdGl2ZSB0byBpdHMgb2Zmc2V0UGFyZW50LlxuICAvLyBDb21wb3NpdGUgbWVhbnMgaXQgdGFrZXMgaW50byBhY2NvdW50IHRyYW5zZm9ybXMgYXMgd2VsbCBhcyBsYXlvdXQuXG5cblxuICBmdW5jdGlvbiBnZXRDb21wb3NpdGVSZWN0KGVsZW1lbnRPclZpcnR1YWxFbGVtZW50LCBvZmZzZXRQYXJlbnQsIGlzRml4ZWQpIHtcbiAgICBpZiAoaXNGaXhlZCA9PT0gdm9pZCAwKSB7XG4gICAgICBpc0ZpeGVkID0gZmFsc2U7XG4gICAgfVxuXG4gICAgdmFyIGlzT2Zmc2V0UGFyZW50QW5FbGVtZW50ID0gaXNIVE1MRWxlbWVudChvZmZzZXRQYXJlbnQpO1xuICAgIGlzSFRNTEVsZW1lbnQob2Zmc2V0UGFyZW50KSAmJiBpc0VsZW1lbnRTY2FsZWQob2Zmc2V0UGFyZW50KTtcbiAgICB2YXIgZG9jdW1lbnRFbGVtZW50ID0gZ2V0RG9jdW1lbnRFbGVtZW50KG9mZnNldFBhcmVudCk7XG4gICAgdmFyIHJlY3QgPSBnZXRCb3VuZGluZ0NsaWVudFJlY3QoZWxlbWVudE9yVmlydHVhbEVsZW1lbnQpO1xuICAgIHZhciBzY3JvbGwgPSB7XG4gICAgICBzY3JvbGxMZWZ0OiAwLFxuICAgICAgc2Nyb2xsVG9wOiAwXG4gICAgfTtcbiAgICB2YXIgb2Zmc2V0cyA9IHtcbiAgICAgIHg6IDAsXG4gICAgICB5OiAwXG4gICAgfTtcblxuICAgIGlmIChpc09mZnNldFBhcmVudEFuRWxlbWVudCB8fCAhaXNPZmZzZXRQYXJlbnRBbkVsZW1lbnQgJiYgIWlzRml4ZWQpIHtcbiAgICAgIGlmIChnZXROb2RlTmFtZShvZmZzZXRQYXJlbnQpICE9PSAnYm9keScgfHwgLy8gaHR0cHM6Ly9naXRodWIuY29tL3BvcHBlcmpzL3BvcHBlci1jb3JlL2lzc3Vlcy8xMDc4XG4gICAgICBpc1Njcm9sbFBhcmVudChkb2N1bWVudEVsZW1lbnQpKSB7XG4gICAgICAgIHNjcm9sbCA9IGdldE5vZGVTY3JvbGwob2Zmc2V0UGFyZW50KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzSFRNTEVsZW1lbnQob2Zmc2V0UGFyZW50KSkge1xuICAgICAgICBvZmZzZXRzID0gZ2V0Qm91bmRpbmdDbGllbnRSZWN0KG9mZnNldFBhcmVudCk7XG4gICAgICAgIG9mZnNldHMueCArPSBvZmZzZXRQYXJlbnQuY2xpZW50TGVmdDtcbiAgICAgICAgb2Zmc2V0cy55ICs9IG9mZnNldFBhcmVudC5jbGllbnRUb3A7XG4gICAgICB9IGVsc2UgaWYgKGRvY3VtZW50RWxlbWVudCkge1xuICAgICAgICBvZmZzZXRzLnggPSBnZXRXaW5kb3dTY3JvbGxCYXJYKGRvY3VtZW50RWxlbWVudCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHg6IHJlY3QubGVmdCArIHNjcm9sbC5zY3JvbGxMZWZ0IC0gb2Zmc2V0cy54LFxuICAgICAgeTogcmVjdC50b3AgKyBzY3JvbGwuc2Nyb2xsVG9wIC0gb2Zmc2V0cy55LFxuICAgICAgd2lkdGg6IHJlY3Qud2lkdGgsXG4gICAgICBoZWlnaHQ6IHJlY3QuaGVpZ2h0XG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG9yZGVyKG1vZGlmaWVycykge1xuICAgIHZhciBtYXAgPSBuZXcgTWFwKCk7XG4gICAgdmFyIHZpc2l0ZWQgPSBuZXcgU2V0KCk7XG4gICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgIG1vZGlmaWVycy5mb3JFYWNoKGZ1bmN0aW9uIChtb2RpZmllcikge1xuICAgICAgbWFwLnNldChtb2RpZmllci5uYW1lLCBtb2RpZmllcik7XG4gICAgfSk7IC8vIE9uIHZpc2l0aW5nIG9iamVjdCwgY2hlY2sgZm9yIGl0cyBkZXBlbmRlbmNpZXMgYW5kIHZpc2l0IHRoZW0gcmVjdXJzaXZlbHlcblxuICAgIGZ1bmN0aW9uIHNvcnQobW9kaWZpZXIpIHtcbiAgICAgIHZpc2l0ZWQuYWRkKG1vZGlmaWVyLm5hbWUpO1xuICAgICAgdmFyIHJlcXVpcmVzID0gW10uY29uY2F0KG1vZGlmaWVyLnJlcXVpcmVzIHx8IFtdLCBtb2RpZmllci5yZXF1aXJlc0lmRXhpc3RzIHx8IFtdKTtcbiAgICAgIHJlcXVpcmVzLmZvckVhY2goZnVuY3Rpb24gKGRlcCkge1xuICAgICAgICBpZiAoIXZpc2l0ZWQuaGFzKGRlcCkpIHtcbiAgICAgICAgICB2YXIgZGVwTW9kaWZpZXIgPSBtYXAuZ2V0KGRlcCk7XG5cbiAgICAgICAgICBpZiAoZGVwTW9kaWZpZXIpIHtcbiAgICAgICAgICAgIHNvcnQoZGVwTW9kaWZpZXIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXN1bHQucHVzaChtb2RpZmllcik7XG4gICAgfVxuXG4gICAgbW9kaWZpZXJzLmZvckVhY2goZnVuY3Rpb24gKG1vZGlmaWVyKSB7XG4gICAgICBpZiAoIXZpc2l0ZWQuaGFzKG1vZGlmaWVyLm5hbWUpKSB7XG4gICAgICAgIC8vIGNoZWNrIGZvciB2aXNpdGVkIG9iamVjdFxuICAgICAgICBzb3J0KG1vZGlmaWVyKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gb3JkZXJNb2RpZmllcnMobW9kaWZpZXJzKSB7XG4gICAgLy8gb3JkZXIgYmFzZWQgb24gZGVwZW5kZW5jaWVzXG4gICAgdmFyIG9yZGVyZWRNb2RpZmllcnMgPSBvcmRlcihtb2RpZmllcnMpOyAvLyBvcmRlciBiYXNlZCBvbiBwaGFzZVxuXG4gICAgcmV0dXJuIG1vZGlmaWVyUGhhc2VzLnJlZHVjZShmdW5jdGlvbiAoYWNjLCBwaGFzZSkge1xuICAgICAgcmV0dXJuIGFjYy5jb25jYXQob3JkZXJlZE1vZGlmaWVycy5maWx0ZXIoZnVuY3Rpb24gKG1vZGlmaWVyKSB7XG4gICAgICAgIHJldHVybiBtb2RpZmllci5waGFzZSA9PT0gcGhhc2U7XG4gICAgICB9KSk7XG4gICAgfSwgW10pO1xuICB9XG5cbiAgZnVuY3Rpb24gZGVib3VuY2UoZm4pIHtcbiAgICB2YXIgcGVuZGluZztcbiAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKCFwZW5kaW5nKSB7XG4gICAgICAgIHBlbmRpbmcgPSBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgICAgICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcGVuZGluZyA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHJlc29sdmUoZm4oKSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcGVuZGluZztcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gbWVyZ2VCeU5hbWUobW9kaWZpZXJzKSB7XG4gICAgdmFyIG1lcmdlZCA9IG1vZGlmaWVycy5yZWR1Y2UoZnVuY3Rpb24gKG1lcmdlZCwgY3VycmVudCkge1xuICAgICAgdmFyIGV4aXN0aW5nID0gbWVyZ2VkW2N1cnJlbnQubmFtZV07XG4gICAgICBtZXJnZWRbY3VycmVudC5uYW1lXSA9IGV4aXN0aW5nID8gT2JqZWN0LmFzc2lnbih7fSwgZXhpc3RpbmcsIGN1cnJlbnQsIHtcbiAgICAgICAgb3B0aW9uczogT2JqZWN0LmFzc2lnbih7fSwgZXhpc3Rpbmcub3B0aW9ucywgY3VycmVudC5vcHRpb25zKSxcbiAgICAgICAgZGF0YTogT2JqZWN0LmFzc2lnbih7fSwgZXhpc3RpbmcuZGF0YSwgY3VycmVudC5kYXRhKVxuICAgICAgfSkgOiBjdXJyZW50O1xuICAgICAgcmV0dXJuIG1lcmdlZDtcbiAgICB9LCB7fSk7IC8vIElFMTEgZG9lcyBub3Qgc3VwcG9ydCBPYmplY3QudmFsdWVzXG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMobWVyZ2VkKS5tYXAoZnVuY3Rpb24gKGtleSkge1xuICAgICAgcmV0dXJuIG1lcmdlZFtrZXldO1xuICAgIH0pO1xuICB9XG5cbiAgdmFyIERFRkFVTFRfT1BUSU9OUyA9IHtcbiAgICBwbGFjZW1lbnQ6ICdib3R0b20nLFxuICAgIG1vZGlmaWVyczogW10sXG4gICAgc3RyYXRlZ3k6ICdhYnNvbHV0ZSdcbiAgfTtcblxuICBmdW5jdGlvbiBhcmVWYWxpZEVsZW1lbnRzKCkge1xuICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykge1xuICAgICAgYXJnc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTtcbiAgICB9XG5cbiAgICByZXR1cm4gIWFyZ3Muc29tZShmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgICAgcmV0dXJuICEoZWxlbWVudCAmJiB0eXBlb2YgZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QgPT09ICdmdW5jdGlvbicpO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gcG9wcGVyR2VuZXJhdG9yKGdlbmVyYXRvck9wdGlvbnMpIHtcbiAgICBpZiAoZ2VuZXJhdG9yT3B0aW9ucyA9PT0gdm9pZCAwKSB7XG4gICAgICBnZW5lcmF0b3JPcHRpb25zID0ge307XG4gICAgfVxuXG4gICAgdmFyIF9nZW5lcmF0b3JPcHRpb25zID0gZ2VuZXJhdG9yT3B0aW9ucyxcbiAgICAgICAgX2dlbmVyYXRvck9wdGlvbnMkZGVmID0gX2dlbmVyYXRvck9wdGlvbnMuZGVmYXVsdE1vZGlmaWVycyxcbiAgICAgICAgZGVmYXVsdE1vZGlmaWVycyA9IF9nZW5lcmF0b3JPcHRpb25zJGRlZiA9PT0gdm9pZCAwID8gW10gOiBfZ2VuZXJhdG9yT3B0aW9ucyRkZWYsXG4gICAgICAgIF9nZW5lcmF0b3JPcHRpb25zJGRlZjIgPSBfZ2VuZXJhdG9yT3B0aW9ucy5kZWZhdWx0T3B0aW9ucyxcbiAgICAgICAgZGVmYXVsdE9wdGlvbnMgPSBfZ2VuZXJhdG9yT3B0aW9ucyRkZWYyID09PSB2b2lkIDAgPyBERUZBVUxUX09QVElPTlMgOiBfZ2VuZXJhdG9yT3B0aW9ucyRkZWYyO1xuICAgIHJldHVybiBmdW5jdGlvbiBjcmVhdGVQb3BwZXIocmVmZXJlbmNlLCBwb3BwZXIsIG9wdGlvbnMpIHtcbiAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHtcbiAgICAgICAgb3B0aW9ucyA9IGRlZmF1bHRPcHRpb25zO1xuICAgICAgfVxuXG4gICAgICB2YXIgc3RhdGUgPSB7XG4gICAgICAgIHBsYWNlbWVudDogJ2JvdHRvbScsXG4gICAgICAgIG9yZGVyZWRNb2RpZmllcnM6IFtdLFxuICAgICAgICBvcHRpb25zOiBPYmplY3QuYXNzaWduKHt9LCBERUZBVUxUX09QVElPTlMsIGRlZmF1bHRPcHRpb25zKSxcbiAgICAgICAgbW9kaWZpZXJzRGF0YToge30sXG4gICAgICAgIGVsZW1lbnRzOiB7XG4gICAgICAgICAgcmVmZXJlbmNlOiByZWZlcmVuY2UsXG4gICAgICAgICAgcG9wcGVyOiBwb3BwZXJcbiAgICAgICAgfSxcbiAgICAgICAgYXR0cmlidXRlczoge30sXG4gICAgICAgIHN0eWxlczoge31cbiAgICAgIH07XG4gICAgICB2YXIgZWZmZWN0Q2xlYW51cEZucyA9IFtdO1xuICAgICAgdmFyIGlzRGVzdHJveWVkID0gZmFsc2U7XG4gICAgICB2YXIgaW5zdGFuY2UgPSB7XG4gICAgICAgIHN0YXRlOiBzdGF0ZSxcbiAgICAgICAgc2V0T3B0aW9uczogZnVuY3Rpb24gc2V0T3B0aW9ucyhzZXRPcHRpb25zQWN0aW9uKSB7XG4gICAgICAgICAgdmFyIG9wdGlvbnMgPSB0eXBlb2Ygc2V0T3B0aW9uc0FjdGlvbiA9PT0gJ2Z1bmN0aW9uJyA/IHNldE9wdGlvbnNBY3Rpb24oc3RhdGUub3B0aW9ucykgOiBzZXRPcHRpb25zQWN0aW9uO1xuICAgICAgICAgIGNsZWFudXBNb2RpZmllckVmZmVjdHMoKTtcbiAgICAgICAgICBzdGF0ZS5vcHRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgZGVmYXVsdE9wdGlvbnMsIHN0YXRlLm9wdGlvbnMsIG9wdGlvbnMpO1xuICAgICAgICAgIHN0YXRlLnNjcm9sbFBhcmVudHMgPSB7XG4gICAgICAgICAgICByZWZlcmVuY2U6IGlzRWxlbWVudChyZWZlcmVuY2UpID8gbGlzdFNjcm9sbFBhcmVudHMocmVmZXJlbmNlKSA6IHJlZmVyZW5jZS5jb250ZXh0RWxlbWVudCA/IGxpc3RTY3JvbGxQYXJlbnRzKHJlZmVyZW5jZS5jb250ZXh0RWxlbWVudCkgOiBbXSxcbiAgICAgICAgICAgIHBvcHBlcjogbGlzdFNjcm9sbFBhcmVudHMocG9wcGVyKVxuICAgICAgICAgIH07IC8vIE9yZGVycyB0aGUgbW9kaWZpZXJzIGJhc2VkIG9uIHRoZWlyIGRlcGVuZGVuY2llcyBhbmQgYHBoYXNlYFxuICAgICAgICAgIC8vIHByb3BlcnRpZXNcblxuICAgICAgICAgIHZhciBvcmRlcmVkTW9kaWZpZXJzID0gb3JkZXJNb2RpZmllcnMobWVyZ2VCeU5hbWUoW10uY29uY2F0KGRlZmF1bHRNb2RpZmllcnMsIHN0YXRlLm9wdGlvbnMubW9kaWZpZXJzKSkpOyAvLyBTdHJpcCBvdXQgZGlzYWJsZWQgbW9kaWZpZXJzXG5cbiAgICAgICAgICBzdGF0ZS5vcmRlcmVkTW9kaWZpZXJzID0gb3JkZXJlZE1vZGlmaWVycy5maWx0ZXIoZnVuY3Rpb24gKG0pIHtcbiAgICAgICAgICAgIHJldHVybiBtLmVuYWJsZWQ7XG4gICAgICAgICAgfSk7IC8vIFZhbGlkYXRlIHRoZSBwcm92aWRlZCBtb2RpZmllcnMgc28gdGhhdCB0aGUgY29uc3VtZXIgd2lsbCBnZXQgd2FybmVkXG5cbiAgICAgICAgICBydW5Nb2RpZmllckVmZmVjdHMoKTtcbiAgICAgICAgICByZXR1cm4gaW5zdGFuY2UudXBkYXRlKCk7XG4gICAgICAgIH0sXG4gICAgICAgIC8vIFN5bmMgdXBkYXRlIOKAkyBpdCB3aWxsIGFsd2F5cyBiZSBleGVjdXRlZCwgZXZlbiBpZiBub3QgbmVjZXNzYXJ5LiBUaGlzXG4gICAgICAgIC8vIGlzIHVzZWZ1bCBmb3IgbG93IGZyZXF1ZW5jeSB1cGRhdGVzIHdoZXJlIHN5bmMgYmVoYXZpb3Igc2ltcGxpZmllcyB0aGVcbiAgICAgICAgLy8gbG9naWMuXG4gICAgICAgIC8vIEZvciBoaWdoIGZyZXF1ZW5jeSB1cGRhdGVzIChlLmcuIGByZXNpemVgIGFuZCBgc2Nyb2xsYCBldmVudHMpLCBhbHdheXNcbiAgICAgICAgLy8gcHJlZmVyIHRoZSBhc3luYyBQb3BwZXIjdXBkYXRlIG1ldGhvZFxuICAgICAgICBmb3JjZVVwZGF0ZTogZnVuY3Rpb24gZm9yY2VVcGRhdGUoKSB7XG4gICAgICAgICAgaWYgKGlzRGVzdHJveWVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIF9zdGF0ZSRlbGVtZW50cyA9IHN0YXRlLmVsZW1lbnRzLFxuICAgICAgICAgICAgICByZWZlcmVuY2UgPSBfc3RhdGUkZWxlbWVudHMucmVmZXJlbmNlLFxuICAgICAgICAgICAgICBwb3BwZXIgPSBfc3RhdGUkZWxlbWVudHMucG9wcGVyOyAvLyBEb24ndCBwcm9jZWVkIGlmIGByZWZlcmVuY2VgIG9yIGBwb3BwZXJgIGFyZSBub3QgdmFsaWQgZWxlbWVudHNcbiAgICAgICAgICAvLyBhbnltb3JlXG5cbiAgICAgICAgICBpZiAoIWFyZVZhbGlkRWxlbWVudHMocmVmZXJlbmNlLCBwb3BwZXIpKSB7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9IC8vIFN0b3JlIHRoZSByZWZlcmVuY2UgYW5kIHBvcHBlciByZWN0cyB0byBiZSByZWFkIGJ5IG1vZGlmaWVyc1xuXG5cbiAgICAgICAgICBzdGF0ZS5yZWN0cyA9IHtcbiAgICAgICAgICAgIHJlZmVyZW5jZTogZ2V0Q29tcG9zaXRlUmVjdChyZWZlcmVuY2UsIGdldE9mZnNldFBhcmVudChwb3BwZXIpLCBzdGF0ZS5vcHRpb25zLnN0cmF0ZWd5ID09PSAnZml4ZWQnKSxcbiAgICAgICAgICAgIHBvcHBlcjogZ2V0TGF5b3V0UmVjdChwb3BwZXIpXG4gICAgICAgICAgfTsgLy8gTW9kaWZpZXJzIGhhdmUgdGhlIGFiaWxpdHkgdG8gcmVzZXQgdGhlIGN1cnJlbnQgdXBkYXRlIGN5Y2xlLiBUaGVcbiAgICAgICAgICAvLyBtb3N0IGNvbW1vbiB1c2UgY2FzZSBmb3IgdGhpcyBpcyB0aGUgYGZsaXBgIG1vZGlmaWVyIGNoYW5naW5nIHRoZVxuICAgICAgICAgIC8vIHBsYWNlbWVudCwgd2hpY2ggdGhlbiBuZWVkcyB0byByZS1ydW4gYWxsIHRoZSBtb2RpZmllcnMsIGJlY2F1c2UgdGhlXG4gICAgICAgICAgLy8gbG9naWMgd2FzIHByZXZpb3VzbHkgcmFuIGZvciB0aGUgcHJldmlvdXMgcGxhY2VtZW50IGFuZCBpcyB0aGVyZWZvcmVcbiAgICAgICAgICAvLyBzdGFsZS9pbmNvcnJlY3RcblxuICAgICAgICAgIHN0YXRlLnJlc2V0ID0gZmFsc2U7XG4gICAgICAgICAgc3RhdGUucGxhY2VtZW50ID0gc3RhdGUub3B0aW9ucy5wbGFjZW1lbnQ7IC8vIE9uIGVhY2ggdXBkYXRlIGN5Y2xlLCB0aGUgYG1vZGlmaWVyc0RhdGFgIHByb3BlcnR5IGZvciBlYWNoIG1vZGlmaWVyXG4gICAgICAgICAgLy8gaXMgZmlsbGVkIHdpdGggdGhlIGluaXRpYWwgZGF0YSBzcGVjaWZpZWQgYnkgdGhlIG1vZGlmaWVyLiBUaGlzIG1lYW5zXG4gICAgICAgICAgLy8gaXQgZG9lc24ndCBwZXJzaXN0IGFuZCBpcyBmcmVzaCBvbiBlYWNoIHVwZGF0ZS5cbiAgICAgICAgICAvLyBUbyBlbnN1cmUgcGVyc2lzdGVudCBkYXRhLCB1c2UgYCR7bmFtZX0jcGVyc2lzdGVudGBcblxuICAgICAgICAgIHN0YXRlLm9yZGVyZWRNb2RpZmllcnMuZm9yRWFjaChmdW5jdGlvbiAobW9kaWZpZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBzdGF0ZS5tb2RpZmllcnNEYXRhW21vZGlmaWVyLm5hbWVdID0gT2JqZWN0LmFzc2lnbih7fSwgbW9kaWZpZXIuZGF0YSk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgc3RhdGUub3JkZXJlZE1vZGlmaWVycy5sZW5ndGg7IGluZGV4KyspIHtcblxuICAgICAgICAgICAgaWYgKHN0YXRlLnJlc2V0ID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgIHN0YXRlLnJlc2V0ID0gZmFsc2U7XG4gICAgICAgICAgICAgIGluZGV4ID0gLTE7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgX3N0YXRlJG9yZGVyZWRNb2RpZmllID0gc3RhdGUub3JkZXJlZE1vZGlmaWVyc1tpbmRleF0sXG4gICAgICAgICAgICAgICAgZm4gPSBfc3RhdGUkb3JkZXJlZE1vZGlmaWUuZm4sXG4gICAgICAgICAgICAgICAgX3N0YXRlJG9yZGVyZWRNb2RpZmllMiA9IF9zdGF0ZSRvcmRlcmVkTW9kaWZpZS5vcHRpb25zLFxuICAgICAgICAgICAgICAgIF9vcHRpb25zID0gX3N0YXRlJG9yZGVyZWRNb2RpZmllMiA9PT0gdm9pZCAwID8ge30gOiBfc3RhdGUkb3JkZXJlZE1vZGlmaWUyLFxuICAgICAgICAgICAgICAgIG5hbWUgPSBfc3RhdGUkb3JkZXJlZE1vZGlmaWUubmFtZTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBmbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICBzdGF0ZSA9IGZuKHtcbiAgICAgICAgICAgICAgICBzdGF0ZTogc3RhdGUsXG4gICAgICAgICAgICAgICAgb3B0aW9uczogX29wdGlvbnMsXG4gICAgICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgICBpbnN0YW5jZTogaW5zdGFuY2VcbiAgICAgICAgICAgICAgfSkgfHwgc3RhdGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICAvLyBBc3luYyBhbmQgb3B0aW1pc3RpY2FsbHkgb3B0aW1pemVkIHVwZGF0ZSDigJMgaXQgd2lsbCBub3QgYmUgZXhlY3V0ZWQgaWZcbiAgICAgICAgLy8gbm90IG5lY2Vzc2FyeSAoZGVib3VuY2VkIHRvIHJ1biBhdCBtb3N0IG9uY2UtcGVyLXRpY2spXG4gICAgICAgIHVwZGF0ZTogZGVib3VuY2UoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgICAgICAgICAgaW5zdGFuY2UuZm9yY2VVcGRhdGUoKTtcbiAgICAgICAgICAgIHJlc29sdmUoc3RhdGUpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KSxcbiAgICAgICAgZGVzdHJveTogZnVuY3Rpb24gZGVzdHJveSgpIHtcbiAgICAgICAgICBjbGVhbnVwTW9kaWZpZXJFZmZlY3RzKCk7XG4gICAgICAgICAgaXNEZXN0cm95ZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBpZiAoIWFyZVZhbGlkRWxlbWVudHMocmVmZXJlbmNlLCBwb3BwZXIpKSB7XG5cbiAgICAgICAgcmV0dXJuIGluc3RhbmNlO1xuICAgICAgfVxuXG4gICAgICBpbnN0YW5jZS5zZXRPcHRpb25zKG9wdGlvbnMpLnRoZW4oZnVuY3Rpb24gKHN0YXRlKSB7XG4gICAgICAgIGlmICghaXNEZXN0cm95ZWQgJiYgb3B0aW9ucy5vbkZpcnN0VXBkYXRlKSB7XG4gICAgICAgICAgb3B0aW9ucy5vbkZpcnN0VXBkYXRlKHN0YXRlKTtcbiAgICAgICAgfVxuICAgICAgfSk7IC8vIE1vZGlmaWVycyBoYXZlIHRoZSBhYmlsaXR5IHRvIGV4ZWN1dGUgYXJiaXRyYXJ5IGNvZGUgYmVmb3JlIHRoZSBmaXJzdFxuICAgICAgLy8gdXBkYXRlIGN5Y2xlIHJ1bnMuIFRoZXkgd2lsbCBiZSBleGVjdXRlZCBpbiB0aGUgc2FtZSBvcmRlciBhcyB0aGUgdXBkYXRlXG4gICAgICAvLyBjeWNsZS4gVGhpcyBpcyB1c2VmdWwgd2hlbiBhIG1vZGlmaWVyIGFkZHMgc29tZSBwZXJzaXN0ZW50IGRhdGEgdGhhdFxuICAgICAgLy8gb3RoZXIgbW9kaWZpZXJzIG5lZWQgdG8gdXNlLCBidXQgdGhlIG1vZGlmaWVyIGlzIHJ1biBhZnRlciB0aGUgZGVwZW5kZW50XG4gICAgICAvLyBvbmUuXG5cbiAgICAgIGZ1bmN0aW9uIHJ1bk1vZGlmaWVyRWZmZWN0cygpIHtcbiAgICAgICAgc3RhdGUub3JkZXJlZE1vZGlmaWVycy5mb3JFYWNoKGZ1bmN0aW9uIChfcmVmMykge1xuICAgICAgICAgIHZhciBuYW1lID0gX3JlZjMubmFtZSxcbiAgICAgICAgICAgICAgX3JlZjMkb3B0aW9ucyA9IF9yZWYzLm9wdGlvbnMsXG4gICAgICAgICAgICAgIG9wdGlvbnMgPSBfcmVmMyRvcHRpb25zID09PSB2b2lkIDAgPyB7fSA6IF9yZWYzJG9wdGlvbnMsXG4gICAgICAgICAgICAgIGVmZmVjdCA9IF9yZWYzLmVmZmVjdDtcblxuICAgICAgICAgIGlmICh0eXBlb2YgZWZmZWN0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB2YXIgY2xlYW51cEZuID0gZWZmZWN0KHtcbiAgICAgICAgICAgICAgc3RhdGU6IHN0YXRlLFxuICAgICAgICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICAgICAgICBpbnN0YW5jZTogaW5zdGFuY2UsXG4gICAgICAgICAgICAgIG9wdGlvbnM6IG9wdGlvbnNcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB2YXIgbm9vcEZuID0gZnVuY3Rpb24gbm9vcEZuKCkge307XG5cbiAgICAgICAgICAgIGVmZmVjdENsZWFudXBGbnMucHVzaChjbGVhbnVwRm4gfHwgbm9vcEZuKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBjbGVhbnVwTW9kaWZpZXJFZmZlY3RzKCkge1xuICAgICAgICBlZmZlY3RDbGVhbnVwRm5zLmZvckVhY2goZnVuY3Rpb24gKGZuKSB7XG4gICAgICAgICAgcmV0dXJuIGZuKCk7XG4gICAgICAgIH0pO1xuICAgICAgICBlZmZlY3RDbGVhbnVwRm5zID0gW107XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBpbnN0YW5jZTtcbiAgICB9O1xuICB9XG4gIHZhciBjcmVhdGVQb3BwZXIkMiA9IC8qI19fUFVSRV9fKi9wb3BwZXJHZW5lcmF0b3IoKTsgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby11bnVzZWQtbW9kdWxlc1xuXG4gIHZhciBkZWZhdWx0TW9kaWZpZXJzJDEgPSBbZXZlbnRMaXN0ZW5lcnMsIHBvcHBlck9mZnNldHMkMSwgY29tcHV0ZVN0eWxlcyQxLCBhcHBseVN0eWxlcyQxXTtcbiAgdmFyIGNyZWF0ZVBvcHBlciQxID0gLyojX19QVVJFX18qL3BvcHBlckdlbmVyYXRvcih7XG4gICAgZGVmYXVsdE1vZGlmaWVyczogZGVmYXVsdE1vZGlmaWVycyQxXG4gIH0pOyAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLXVudXNlZC1tb2R1bGVzXG5cbiAgdmFyIGRlZmF1bHRNb2RpZmllcnMgPSBbZXZlbnRMaXN0ZW5lcnMsIHBvcHBlck9mZnNldHMkMSwgY29tcHV0ZVN0eWxlcyQxLCBhcHBseVN0eWxlcyQxLCBvZmZzZXQkMSwgZmxpcCQxLCBwcmV2ZW50T3ZlcmZsb3ckMSwgYXJyb3ckMSwgaGlkZSQxXTtcbiAgdmFyIGNyZWF0ZVBvcHBlciA9IC8qI19fUFVSRV9fKi9wb3BwZXJHZW5lcmF0b3Ioe1xuICAgIGRlZmF1bHRNb2RpZmllcnM6IGRlZmF1bHRNb2RpZmllcnNcbiAgfSk7IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tdW51c2VkLW1vZHVsZXNcblxuICBjb25zdCBQb3BwZXIgPSAvKiNfX1BVUkVfXyovT2JqZWN0LmZyZWV6ZSh7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIHBvcHBlckdlbmVyYXRvcixcbiAgICBkZXRlY3RPdmVyZmxvdyxcbiAgICBjcmVhdGVQb3BwZXJCYXNlOiBjcmVhdGVQb3BwZXIkMixcbiAgICBjcmVhdGVQb3BwZXIsXG4gICAgY3JlYXRlUG9wcGVyTGl0ZTogY3JlYXRlUG9wcGVyJDEsXG4gICAgdG9wLFxuICAgIGJvdHRvbSxcbiAgICByaWdodCxcbiAgICBsZWZ0LFxuICAgIGF1dG8sXG4gICAgYmFzZVBsYWNlbWVudHMsXG4gICAgc3RhcnQsXG4gICAgZW5kLFxuICAgIGNsaXBwaW5nUGFyZW50cyxcbiAgICB2aWV3cG9ydCxcbiAgICBwb3BwZXIsXG4gICAgcmVmZXJlbmNlLFxuICAgIHZhcmlhdGlvblBsYWNlbWVudHMsXG4gICAgcGxhY2VtZW50cyxcbiAgICBiZWZvcmVSZWFkLFxuICAgIHJlYWQsXG4gICAgYWZ0ZXJSZWFkLFxuICAgIGJlZm9yZU1haW4sXG4gICAgbWFpbixcbiAgICBhZnRlck1haW4sXG4gICAgYmVmb3JlV3JpdGUsXG4gICAgd3JpdGUsXG4gICAgYWZ0ZXJXcml0ZSxcbiAgICBtb2RpZmllclBoYXNlcyxcbiAgICBhcHBseVN0eWxlczogYXBwbHlTdHlsZXMkMSxcbiAgICBhcnJvdzogYXJyb3ckMSxcbiAgICBjb21wdXRlU3R5bGVzOiBjb21wdXRlU3R5bGVzJDEsXG4gICAgZXZlbnRMaXN0ZW5lcnMsXG4gICAgZmxpcDogZmxpcCQxLFxuICAgIGhpZGU6IGhpZGUkMSxcbiAgICBvZmZzZXQ6IG9mZnNldCQxLFxuICAgIHBvcHBlck9mZnNldHM6IHBvcHBlck9mZnNldHMkMSxcbiAgICBwcmV2ZW50T3ZlcmZsb3c6IHByZXZlbnRPdmVyZmxvdyQxXG4gIH0pO1xuXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBCb290c3RyYXAgKHY1LjEuMyk6IGRyb3Bkb3duLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDb25zdGFudHNcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIGNvbnN0IE5BTUUkOSA9ICdkcm9wZG93bic7XG4gIGNvbnN0IERBVEFfS0VZJDggPSAnYnMuZHJvcGRvd24nO1xuICBjb25zdCBFVkVOVF9LRVkkOCA9IGAuJHtEQVRBX0tFWSQ4fWA7XG4gIGNvbnN0IERBVEFfQVBJX0tFWSQ0ID0gJy5kYXRhLWFwaSc7XG4gIGNvbnN0IEVTQ0FQRV9LRVkkMiA9ICdFc2NhcGUnO1xuICBjb25zdCBTUEFDRV9LRVkgPSAnU3BhY2UnO1xuICBjb25zdCBUQUJfS0VZJDEgPSAnVGFiJztcbiAgY29uc3QgQVJST1dfVVBfS0VZID0gJ0Fycm93VXAnO1xuICBjb25zdCBBUlJPV19ET1dOX0tFWSA9ICdBcnJvd0Rvd24nO1xuICBjb25zdCBSSUdIVF9NT1VTRV9CVVRUT04gPSAyOyAvLyBNb3VzZUV2ZW50LmJ1dHRvbiB2YWx1ZSBmb3IgdGhlIHNlY29uZGFyeSBidXR0b24sIHVzdWFsbHkgdGhlIHJpZ2h0IGJ1dHRvblxuXG4gIGNvbnN0IFJFR0VYUF9LRVlET1dOID0gbmV3IFJlZ0V4cChgJHtBUlJPV19VUF9LRVl9fCR7QVJST1dfRE9XTl9LRVl9fCR7RVNDQVBFX0tFWSQyfWApO1xuICBjb25zdCBFVkVOVF9ISURFJDQgPSBgaGlkZSR7RVZFTlRfS0VZJDh9YDtcbiAgY29uc3QgRVZFTlRfSElEREVOJDQgPSBgaGlkZGVuJHtFVkVOVF9LRVkkOH1gO1xuICBjb25zdCBFVkVOVF9TSE9XJDQgPSBgc2hvdyR7RVZFTlRfS0VZJDh9YDtcbiAgY29uc3QgRVZFTlRfU0hPV04kNCA9IGBzaG93biR7RVZFTlRfS0VZJDh9YDtcbiAgY29uc3QgRVZFTlRfQ0xJQ0tfREFUQV9BUEkkMyA9IGBjbGljayR7RVZFTlRfS0VZJDh9JHtEQVRBX0FQSV9LRVkkNH1gO1xuICBjb25zdCBFVkVOVF9LRVlET1dOX0RBVEFfQVBJID0gYGtleWRvd24ke0VWRU5UX0tFWSQ4fSR7REFUQV9BUElfS0VZJDR9YDtcbiAgY29uc3QgRVZFTlRfS0VZVVBfREFUQV9BUEkgPSBga2V5dXAke0VWRU5UX0tFWSQ4fSR7REFUQV9BUElfS0VZJDR9YDtcbiAgY29uc3QgQ0xBU1NfTkFNRV9TSE9XJDYgPSAnc2hvdyc7XG4gIGNvbnN0IENMQVNTX05BTUVfRFJPUFVQID0gJ2Ryb3B1cCc7XG4gIGNvbnN0IENMQVNTX05BTUVfRFJPUEVORCA9ICdkcm9wZW5kJztcbiAgY29uc3QgQ0xBU1NfTkFNRV9EUk9QU1RBUlQgPSAnZHJvcHN0YXJ0JztcbiAgY29uc3QgQ0xBU1NfTkFNRV9OQVZCQVIgPSAnbmF2YmFyJztcbiAgY29uc3QgU0VMRUNUT1JfREFUQV9UT0dHTEUkMyA9ICdbZGF0YS1icy10b2dnbGU9XCJkcm9wZG93blwiXSc7XG4gIGNvbnN0IFNFTEVDVE9SX01FTlUgPSAnLmRyb3Bkb3duLW1lbnUnO1xuICBjb25zdCBTRUxFQ1RPUl9OQVZCQVJfTkFWID0gJy5uYXZiYXItbmF2JztcbiAgY29uc3QgU0VMRUNUT1JfVklTSUJMRV9JVEVNUyA9ICcuZHJvcGRvd24tbWVudSAuZHJvcGRvd24taXRlbTpub3QoLmRpc2FibGVkKTpub3QoOmRpc2FibGVkKSc7XG4gIGNvbnN0IFBMQUNFTUVOVF9UT1AgPSBpc1JUTCgpID8gJ3RvcC1lbmQnIDogJ3RvcC1zdGFydCc7XG4gIGNvbnN0IFBMQUNFTUVOVF9UT1BFTkQgPSBpc1JUTCgpID8gJ3RvcC1zdGFydCcgOiAndG9wLWVuZCc7XG4gIGNvbnN0IFBMQUNFTUVOVF9CT1RUT00gPSBpc1JUTCgpID8gJ2JvdHRvbS1lbmQnIDogJ2JvdHRvbS1zdGFydCc7XG4gIGNvbnN0IFBMQUNFTUVOVF9CT1RUT01FTkQgPSBpc1JUTCgpID8gJ2JvdHRvbS1zdGFydCcgOiAnYm90dG9tLWVuZCc7XG4gIGNvbnN0IFBMQUNFTUVOVF9SSUdIVCA9IGlzUlRMKCkgPyAnbGVmdC1zdGFydCcgOiAncmlnaHQtc3RhcnQnO1xuICBjb25zdCBQTEFDRU1FTlRfTEVGVCA9IGlzUlRMKCkgPyAncmlnaHQtc3RhcnQnIDogJ2xlZnQtc3RhcnQnO1xuICBjb25zdCBEZWZhdWx0JDggPSB7XG4gICAgb2Zmc2V0OiBbMCwgMl0sXG4gICAgYm91bmRhcnk6ICdjbGlwcGluZ1BhcmVudHMnLFxuICAgIHJlZmVyZW5jZTogJ3RvZ2dsZScsXG4gICAgZGlzcGxheTogJ2R5bmFtaWMnLFxuICAgIHBvcHBlckNvbmZpZzogbnVsbCxcbiAgICBhdXRvQ2xvc2U6IHRydWVcbiAgfTtcbiAgY29uc3QgRGVmYXVsdFR5cGUkOCA9IHtcbiAgICBvZmZzZXQ6ICcoYXJyYXl8c3RyaW5nfGZ1bmN0aW9uKScsXG4gICAgYm91bmRhcnk6ICcoc3RyaW5nfGVsZW1lbnQpJyxcbiAgICByZWZlcmVuY2U6ICcoc3RyaW5nfGVsZW1lbnR8b2JqZWN0KScsXG4gICAgZGlzcGxheTogJ3N0cmluZycsXG4gICAgcG9wcGVyQ29uZmlnOiAnKG51bGx8b2JqZWN0fGZ1bmN0aW9uKScsXG4gICAgYXV0b0Nsb3NlOiAnKGJvb2xlYW58c3RyaW5nKSdcbiAgfTtcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICBjbGFzcyBEcm9wZG93biBleHRlbmRzIEJhc2VDb21wb25lbnQge1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQsIGNvbmZpZykge1xuICAgICAgc3VwZXIoZWxlbWVudCk7XG4gICAgICB0aGlzLl9wb3BwZXIgPSBudWxsO1xuICAgICAgdGhpcy5fY29uZmlnID0gdGhpcy5fZ2V0Q29uZmlnKGNvbmZpZyk7XG4gICAgICB0aGlzLl9tZW51ID0gdGhpcy5fZ2V0TWVudUVsZW1lbnQoKTtcbiAgICAgIHRoaXMuX2luTmF2YmFyID0gdGhpcy5fZGV0ZWN0TmF2YmFyKCk7XG4gICAgfSAvLyBHZXR0ZXJzXG5cblxuICAgIHN0YXRpYyBnZXQgRGVmYXVsdCgpIHtcbiAgICAgIHJldHVybiBEZWZhdWx0JDg7XG4gICAgfVxuXG4gICAgc3RhdGljIGdldCBEZWZhdWx0VHlwZSgpIHtcbiAgICAgIHJldHVybiBEZWZhdWx0VHlwZSQ4O1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXQgTkFNRSgpIHtcbiAgICAgIHJldHVybiBOQU1FJDk7XG4gICAgfSAvLyBQdWJsaWNcblxuXG4gICAgdG9nZ2xlKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2lzU2hvd24oKSA/IHRoaXMuaGlkZSgpIDogdGhpcy5zaG93KCk7XG4gICAgfVxuXG4gICAgc2hvdygpIHtcbiAgICAgIGlmIChpc0Rpc2FibGVkKHRoaXMuX2VsZW1lbnQpIHx8IHRoaXMuX2lzU2hvd24odGhpcy5fbWVudSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCByZWxhdGVkVGFyZ2V0ID0ge1xuICAgICAgICByZWxhdGVkVGFyZ2V0OiB0aGlzLl9lbGVtZW50XG4gICAgICB9O1xuICAgICAgY29uc3Qgc2hvd0V2ZW50ID0gRXZlbnRIYW5kbGVyLnRyaWdnZXIodGhpcy5fZWxlbWVudCwgRVZFTlRfU0hPVyQ0LCByZWxhdGVkVGFyZ2V0KTtcblxuICAgICAgaWYgKHNob3dFdmVudC5kZWZhdWx0UHJldmVudGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcGFyZW50ID0gRHJvcGRvd24uZ2V0UGFyZW50RnJvbUVsZW1lbnQodGhpcy5fZWxlbWVudCk7IC8vIFRvdGFsbHkgZGlzYWJsZSBQb3BwZXIgZm9yIERyb3Bkb3ducyBpbiBOYXZiYXJcblxuICAgICAgaWYgKHRoaXMuX2luTmF2YmFyKSB7XG4gICAgICAgIE1hbmlwdWxhdG9yLnNldERhdGFBdHRyaWJ1dGUodGhpcy5fbWVudSwgJ3BvcHBlcicsICdub25lJyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9jcmVhdGVQb3BwZXIocGFyZW50KTtcbiAgICAgIH0gLy8gSWYgdGhpcyBpcyBhIHRvdWNoLWVuYWJsZWQgZGV2aWNlIHdlIGFkZCBleHRyYVxuICAgICAgLy8gZW1wdHkgbW91c2VvdmVyIGxpc3RlbmVycyB0byB0aGUgYm9keSdzIGltbWVkaWF0ZSBjaGlsZHJlbjtcbiAgICAgIC8vIG9ubHkgbmVlZGVkIGJlY2F1c2Ugb2YgYnJva2VuIGV2ZW50IGRlbGVnYXRpb24gb24gaU9TXG4gICAgICAvLyBodHRwczovL3d3dy5xdWlya3Ntb2RlLm9yZy9ibG9nL2FyY2hpdmVzLzIwMTQvMDIvbW91c2VfZXZlbnRfYnViLmh0bWxcblxuXG4gICAgICBpZiAoJ29udG91Y2hzdGFydCcgaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50ICYmICFwYXJlbnQuY2xvc2VzdChTRUxFQ1RPUl9OQVZCQVJfTkFWKSkge1xuICAgICAgICBbXS5jb25jYXQoLi4uZG9jdW1lbnQuYm9keS5jaGlsZHJlbikuZm9yRWFjaChlbGVtID0+IEV2ZW50SGFuZGxlci5vbihlbGVtLCAnbW91c2VvdmVyJywgbm9vcCkpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9lbGVtZW50LmZvY3VzKCk7XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQuc2V0QXR0cmlidXRlKCdhcmlhLWV4cGFuZGVkJywgdHJ1ZSk7XG5cbiAgICAgIHRoaXMuX21lbnUuY2xhc3NMaXN0LmFkZChDTEFTU19OQU1FX1NIT1ckNik7XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmFkZChDTEFTU19OQU1FX1NIT1ckNik7XG5cbiAgICAgIEV2ZW50SGFuZGxlci50cmlnZ2VyKHRoaXMuX2VsZW1lbnQsIEVWRU5UX1NIT1dOJDQsIHJlbGF0ZWRUYXJnZXQpO1xuICAgIH1cblxuICAgIGhpZGUoKSB7XG4gICAgICBpZiAoaXNEaXNhYmxlZCh0aGlzLl9lbGVtZW50KSB8fCAhdGhpcy5faXNTaG93bih0aGlzLl9tZW51KSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlbGF0ZWRUYXJnZXQgPSB7XG4gICAgICAgIHJlbGF0ZWRUYXJnZXQ6IHRoaXMuX2VsZW1lbnRcbiAgICAgIH07XG5cbiAgICAgIHRoaXMuX2NvbXBsZXRlSGlkZShyZWxhdGVkVGFyZ2V0KTtcbiAgICB9XG5cbiAgICBkaXNwb3NlKCkge1xuICAgICAgaWYgKHRoaXMuX3BvcHBlcikge1xuICAgICAgICB0aGlzLl9wb3BwZXIuZGVzdHJveSgpO1xuICAgICAgfVxuXG4gICAgICBzdXBlci5kaXNwb3NlKCk7XG4gICAgfVxuXG4gICAgdXBkYXRlKCkge1xuICAgICAgdGhpcy5faW5OYXZiYXIgPSB0aGlzLl9kZXRlY3ROYXZiYXIoKTtcblxuICAgICAgaWYgKHRoaXMuX3BvcHBlcikge1xuICAgICAgICB0aGlzLl9wb3BwZXIudXBkYXRlKCk7XG4gICAgICB9XG4gICAgfSAvLyBQcml2YXRlXG5cblxuICAgIF9jb21wbGV0ZUhpZGUocmVsYXRlZFRhcmdldCkge1xuICAgICAgY29uc3QgaGlkZUV2ZW50ID0gRXZlbnRIYW5kbGVyLnRyaWdnZXIodGhpcy5fZWxlbWVudCwgRVZFTlRfSElERSQ0LCByZWxhdGVkVGFyZ2V0KTtcblxuICAgICAgaWYgKGhpZGVFdmVudC5kZWZhdWx0UHJldmVudGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gLy8gSWYgdGhpcyBpcyBhIHRvdWNoLWVuYWJsZWQgZGV2aWNlIHdlIHJlbW92ZSB0aGUgZXh0cmFcbiAgICAgIC8vIGVtcHR5IG1vdXNlb3ZlciBsaXN0ZW5lcnMgd2UgYWRkZWQgZm9yIGlPUyBzdXBwb3J0XG5cblxuICAgICAgaWYgKCdvbnRvdWNoc3RhcnQnIGluIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkge1xuICAgICAgICBbXS5jb25jYXQoLi4uZG9jdW1lbnQuYm9keS5jaGlsZHJlbikuZm9yRWFjaChlbGVtID0+IEV2ZW50SGFuZGxlci5vZmYoZWxlbSwgJ21vdXNlb3ZlcicsIG5vb3ApKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX3BvcHBlcikge1xuICAgICAgICB0aGlzLl9wb3BwZXIuZGVzdHJveSgpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9tZW51LmNsYXNzTGlzdC5yZW1vdmUoQ0xBU1NfTkFNRV9TSE9XJDYpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoQ0xBU1NfTkFNRV9TSE9XJDYpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsICdmYWxzZScpO1xuXG4gICAgICBNYW5pcHVsYXRvci5yZW1vdmVEYXRhQXR0cmlidXRlKHRoaXMuX21lbnUsICdwb3BwZXInKTtcbiAgICAgIEV2ZW50SGFuZGxlci50cmlnZ2VyKHRoaXMuX2VsZW1lbnQsIEVWRU5UX0hJRERFTiQ0LCByZWxhdGVkVGFyZ2V0KTtcbiAgICB9XG5cbiAgICBfZ2V0Q29uZmlnKGNvbmZpZykge1xuICAgICAgY29uZmlnID0geyAuLi50aGlzLmNvbnN0cnVjdG9yLkRlZmF1bHQsXG4gICAgICAgIC4uLk1hbmlwdWxhdG9yLmdldERhdGFBdHRyaWJ1dGVzKHRoaXMuX2VsZW1lbnQpLFxuICAgICAgICAuLi5jb25maWdcbiAgICAgIH07XG4gICAgICB0eXBlQ2hlY2tDb25maWcoTkFNRSQ5LCBjb25maWcsIHRoaXMuY29uc3RydWN0b3IuRGVmYXVsdFR5cGUpO1xuXG4gICAgICBpZiAodHlwZW9mIGNvbmZpZy5yZWZlcmVuY2UgPT09ICdvYmplY3QnICYmICFpc0VsZW1lbnQkMShjb25maWcucmVmZXJlbmNlKSAmJiB0eXBlb2YgY29uZmlnLnJlZmVyZW5jZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgLy8gUG9wcGVyIHZpcnR1YWwgZWxlbWVudHMgcmVxdWlyZSBhIGdldEJvdW5kaW5nQ2xpZW50UmVjdCBtZXRob2RcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgJHtOQU1FJDkudG9VcHBlckNhc2UoKX06IE9wdGlvbiBcInJlZmVyZW5jZVwiIHByb3ZpZGVkIHR5cGUgXCJvYmplY3RcIiB3aXRob3V0IGEgcmVxdWlyZWQgXCJnZXRCb3VuZGluZ0NsaWVudFJlY3RcIiBtZXRob2QuYCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjb25maWc7XG4gICAgfVxuXG4gICAgX2NyZWF0ZVBvcHBlcihwYXJlbnQpIHtcbiAgICAgIGlmICh0eXBlb2YgUG9wcGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdCb290c3RyYXBcXCdzIGRyb3Bkb3ducyByZXF1aXJlIFBvcHBlciAoaHR0cHM6Ly9wb3BwZXIuanMub3JnKScpO1xuICAgICAgfVxuXG4gICAgICBsZXQgcmVmZXJlbmNlRWxlbWVudCA9IHRoaXMuX2VsZW1lbnQ7XG5cbiAgICAgIGlmICh0aGlzLl9jb25maWcucmVmZXJlbmNlID09PSAncGFyZW50Jykge1xuICAgICAgICByZWZlcmVuY2VFbGVtZW50ID0gcGFyZW50O1xuICAgICAgfSBlbHNlIGlmIChpc0VsZW1lbnQkMSh0aGlzLl9jb25maWcucmVmZXJlbmNlKSkge1xuICAgICAgICByZWZlcmVuY2VFbGVtZW50ID0gZ2V0RWxlbWVudCh0aGlzLl9jb25maWcucmVmZXJlbmNlKTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMuX2NvbmZpZy5yZWZlcmVuY2UgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIHJlZmVyZW5jZUVsZW1lbnQgPSB0aGlzLl9jb25maWcucmVmZXJlbmNlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwb3BwZXJDb25maWcgPSB0aGlzLl9nZXRQb3BwZXJDb25maWcoKTtcblxuICAgICAgY29uc3QgaXNEaXNwbGF5U3RhdGljID0gcG9wcGVyQ29uZmlnLm1vZGlmaWVycy5maW5kKG1vZGlmaWVyID0+IG1vZGlmaWVyLm5hbWUgPT09ICdhcHBseVN0eWxlcycgJiYgbW9kaWZpZXIuZW5hYmxlZCA9PT0gZmFsc2UpO1xuICAgICAgdGhpcy5fcG9wcGVyID0gY3JlYXRlUG9wcGVyKHJlZmVyZW5jZUVsZW1lbnQsIHRoaXMuX21lbnUsIHBvcHBlckNvbmZpZyk7XG5cbiAgICAgIGlmIChpc0Rpc3BsYXlTdGF0aWMpIHtcbiAgICAgICAgTWFuaXB1bGF0b3Iuc2V0RGF0YUF0dHJpYnV0ZSh0aGlzLl9tZW51LCAncG9wcGVyJywgJ3N0YXRpYycpO1xuICAgICAgfVxuICAgIH1cblxuICAgIF9pc1Nob3duKGVsZW1lbnQgPSB0aGlzLl9lbGVtZW50KSB7XG4gICAgICByZXR1cm4gZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoQ0xBU1NfTkFNRV9TSE9XJDYpO1xuICAgIH1cblxuICAgIF9nZXRNZW51RWxlbWVudCgpIHtcbiAgICAgIHJldHVybiBTZWxlY3RvckVuZ2luZS5uZXh0KHRoaXMuX2VsZW1lbnQsIFNFTEVDVE9SX01FTlUpWzBdO1xuICAgIH1cblxuICAgIF9nZXRQbGFjZW1lbnQoKSB7XG4gICAgICBjb25zdCBwYXJlbnREcm9wZG93biA9IHRoaXMuX2VsZW1lbnQucGFyZW50Tm9kZTtcblxuICAgICAgaWYgKHBhcmVudERyb3Bkb3duLmNsYXNzTGlzdC5jb250YWlucyhDTEFTU19OQU1FX0RST1BFTkQpKSB7XG4gICAgICAgIHJldHVybiBQTEFDRU1FTlRfUklHSFQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJlbnREcm9wZG93bi5jbGFzc0xpc3QuY29udGFpbnMoQ0xBU1NfTkFNRV9EUk9QU1RBUlQpKSB7XG4gICAgICAgIHJldHVybiBQTEFDRU1FTlRfTEVGVDtcbiAgICAgIH0gLy8gV2UgbmVlZCB0byB0cmltIHRoZSB2YWx1ZSBiZWNhdXNlIGN1c3RvbSBwcm9wZXJ0aWVzIGNhbiBhbHNvIGluY2x1ZGUgc3BhY2VzXG5cblxuICAgICAgY29uc3QgaXNFbmQgPSBnZXRDb21wdXRlZFN0eWxlKHRoaXMuX21lbnUpLmdldFByb3BlcnR5VmFsdWUoJy0tYnMtcG9zaXRpb24nKS50cmltKCkgPT09ICdlbmQnO1xuXG4gICAgICBpZiAocGFyZW50RHJvcGRvd24uY2xhc3NMaXN0LmNvbnRhaW5zKENMQVNTX05BTUVfRFJPUFVQKSkge1xuICAgICAgICByZXR1cm4gaXNFbmQgPyBQTEFDRU1FTlRfVE9QRU5EIDogUExBQ0VNRU5UX1RPUDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGlzRW5kID8gUExBQ0VNRU5UX0JPVFRPTUVORCA6IFBMQUNFTUVOVF9CT1RUT007XG4gICAgfVxuXG4gICAgX2RldGVjdE5hdmJhcigpIHtcbiAgICAgIHJldHVybiB0aGlzLl9lbGVtZW50LmNsb3Nlc3QoYC4ke0NMQVNTX05BTUVfTkFWQkFSfWApICE9PSBudWxsO1xuICAgIH1cblxuICAgIF9nZXRPZmZzZXQoKSB7XG4gICAgICBjb25zdCB7XG4gICAgICAgIG9mZnNldFxuICAgICAgfSA9IHRoaXMuX2NvbmZpZztcblxuICAgICAgaWYgKHR5cGVvZiBvZmZzZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBvZmZzZXQuc3BsaXQoJywnKS5tYXAodmFsID0+IE51bWJlci5wYXJzZUludCh2YWwsIDEwKSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBwb3BwZXJEYXRhID0+IG9mZnNldChwb3BwZXJEYXRhLCB0aGlzLl9lbGVtZW50KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG9mZnNldDtcbiAgICB9XG5cbiAgICBfZ2V0UG9wcGVyQ29uZmlnKCkge1xuICAgICAgY29uc3QgZGVmYXVsdEJzUG9wcGVyQ29uZmlnID0ge1xuICAgICAgICBwbGFjZW1lbnQ6IHRoaXMuX2dldFBsYWNlbWVudCgpLFxuICAgICAgICBtb2RpZmllcnM6IFt7XG4gICAgICAgICAgbmFtZTogJ3ByZXZlbnRPdmVyZmxvdycsXG4gICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgYm91bmRhcnk6IHRoaXMuX2NvbmZpZy5ib3VuZGFyeVxuICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgIG5hbWU6ICdvZmZzZXQnLFxuICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgIG9mZnNldDogdGhpcy5fZ2V0T2Zmc2V0KClcbiAgICAgICAgICB9XG4gICAgICAgIH1dXG4gICAgICB9OyAvLyBEaXNhYmxlIFBvcHBlciBpZiB3ZSBoYXZlIGEgc3RhdGljIGRpc3BsYXlcblxuICAgICAgaWYgKHRoaXMuX2NvbmZpZy5kaXNwbGF5ID09PSAnc3RhdGljJykge1xuICAgICAgICBkZWZhdWx0QnNQb3BwZXJDb25maWcubW9kaWZpZXJzID0gW3tcbiAgICAgICAgICBuYW1lOiAnYXBwbHlTdHlsZXMnLFxuICAgICAgICAgIGVuYWJsZWQ6IGZhbHNlXG4gICAgICAgIH1dO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4geyAuLi5kZWZhdWx0QnNQb3BwZXJDb25maWcsXG4gICAgICAgIC4uLih0eXBlb2YgdGhpcy5fY29uZmlnLnBvcHBlckNvbmZpZyA9PT0gJ2Z1bmN0aW9uJyA/IHRoaXMuX2NvbmZpZy5wb3BwZXJDb25maWcoZGVmYXVsdEJzUG9wcGVyQ29uZmlnKSA6IHRoaXMuX2NvbmZpZy5wb3BwZXJDb25maWcpXG4gICAgICB9O1xuICAgIH1cblxuICAgIF9zZWxlY3RNZW51SXRlbSh7XG4gICAgICBrZXksXG4gICAgICB0YXJnZXRcbiAgICB9KSB7XG4gICAgICBjb25zdCBpdGVtcyA9IFNlbGVjdG9yRW5naW5lLmZpbmQoU0VMRUNUT1JfVklTSUJMRV9JVEVNUywgdGhpcy5fbWVudSkuZmlsdGVyKGlzVmlzaWJsZSk7XG5cbiAgICAgIGlmICghaXRlbXMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gLy8gaWYgdGFyZ2V0IGlzbid0IGluY2x1ZGVkIGluIGl0ZW1zIChlLmcuIHdoZW4gZXhwYW5kaW5nIHRoZSBkcm9wZG93bilcbiAgICAgIC8vIGFsbG93IGN5Y2xpbmcgdG8gZ2V0IHRoZSBsYXN0IGl0ZW0gaW4gY2FzZSBrZXkgZXF1YWxzIEFSUk9XX1VQX0tFWVxuXG5cbiAgICAgIGdldE5leHRBY3RpdmVFbGVtZW50KGl0ZW1zLCB0YXJnZXQsIGtleSA9PT0gQVJST1dfRE9XTl9LRVksICFpdGVtcy5pbmNsdWRlcyh0YXJnZXQpKS5mb2N1cygpO1xuICAgIH0gLy8gU3RhdGljXG5cblxuICAgIHN0YXRpYyBqUXVlcnlJbnRlcmZhY2UoY29uZmlnKSB7XG4gICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IERyb3Bkb3duLmdldE9yQ3JlYXRlSW5zdGFuY2UodGhpcywgY29uZmlnKTtcblxuICAgICAgICBpZiAodHlwZW9mIGNvbmZpZyAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGRhdGFbY29uZmlnXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBObyBtZXRob2QgbmFtZWQgXCIke2NvbmZpZ31cImApO1xuICAgICAgICB9XG5cbiAgICAgICAgZGF0YVtjb25maWddKCk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY2xlYXJNZW51cyhldmVudCkge1xuICAgICAgaWYgKGV2ZW50ICYmIChldmVudC5idXR0b24gPT09IFJJR0hUX01PVVNFX0JVVFRPTiB8fCBldmVudC50eXBlID09PSAna2V5dXAnICYmIGV2ZW50LmtleSAhPT0gVEFCX0tFWSQxKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRvZ2dsZXMgPSBTZWxlY3RvckVuZ2luZS5maW5kKFNFTEVDVE9SX0RBVEFfVE9HR0xFJDMpO1xuXG4gICAgICBmb3IgKGxldCBpID0gMCwgbGVuID0gdG9nZ2xlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBjb25zdCBjb250ZXh0ID0gRHJvcGRvd24uZ2V0SW5zdGFuY2UodG9nZ2xlc1tpXSk7XG5cbiAgICAgICAgaWYgKCFjb250ZXh0IHx8IGNvbnRleHQuX2NvbmZpZy5hdXRvQ2xvc2UgPT09IGZhbHNlKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWNvbnRleHQuX2lzU2hvd24oKSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVsYXRlZFRhcmdldCA9IHtcbiAgICAgICAgICByZWxhdGVkVGFyZ2V0OiBjb250ZXh0Ll9lbGVtZW50XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgY29uc3QgY29tcG9zZWRQYXRoID0gZXZlbnQuY29tcG9zZWRQYXRoKCk7XG4gICAgICAgICAgY29uc3QgaXNNZW51VGFyZ2V0ID0gY29tcG9zZWRQYXRoLmluY2x1ZGVzKGNvbnRleHQuX21lbnUpO1xuXG4gICAgICAgICAgaWYgKGNvbXBvc2VkUGF0aC5pbmNsdWRlcyhjb250ZXh0Ll9lbGVtZW50KSB8fCBjb250ZXh0Ll9jb25maWcuYXV0b0Nsb3NlID09PSAnaW5zaWRlJyAmJiAhaXNNZW51VGFyZ2V0IHx8IGNvbnRleHQuX2NvbmZpZy5hdXRvQ2xvc2UgPT09ICdvdXRzaWRlJyAmJiBpc01lbnVUYXJnZXQpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH0gLy8gVGFiIG5hdmlnYXRpb24gdGhyb3VnaCB0aGUgZHJvcGRvd24gbWVudSBvciBldmVudHMgZnJvbSBjb250YWluZWQgaW5wdXRzIHNob3VsZG4ndCBjbG9zZSB0aGUgbWVudVxuXG5cbiAgICAgICAgICBpZiAoY29udGV4dC5fbWVudS5jb250YWlucyhldmVudC50YXJnZXQpICYmIChldmVudC50eXBlID09PSAna2V5dXAnICYmIGV2ZW50LmtleSA9PT0gVEFCX0tFWSQxIHx8IC9pbnB1dHxzZWxlY3R8b3B0aW9ufHRleHRhcmVhfGZvcm0vaS50ZXN0KGV2ZW50LnRhcmdldC50YWdOYW1lKSkpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChldmVudC50eXBlID09PSAnY2xpY2snKSB7XG4gICAgICAgICAgICByZWxhdGVkVGFyZ2V0LmNsaWNrRXZlbnQgPSBldmVudDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb250ZXh0Ll9jb21wbGV0ZUhpZGUocmVsYXRlZFRhcmdldCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIGdldFBhcmVudEZyb21FbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgIHJldHVybiBnZXRFbGVtZW50RnJvbVNlbGVjdG9yKGVsZW1lbnQpIHx8IGVsZW1lbnQucGFyZW50Tm9kZTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZGF0YUFwaUtleWRvd25IYW5kbGVyKGV2ZW50KSB7XG4gICAgICAvLyBJZiBub3QgaW5wdXQvdGV4dGFyZWE6XG4gICAgICAvLyAgLSBBbmQgbm90IGEga2V5IGluIFJFR0VYUF9LRVlET1dOID0+IG5vdCBhIGRyb3Bkb3duIGNvbW1hbmRcbiAgICAgIC8vIElmIGlucHV0L3RleHRhcmVhOlxuICAgICAgLy8gIC0gSWYgc3BhY2Uga2V5ID0+IG5vdCBhIGRyb3Bkb3duIGNvbW1hbmRcbiAgICAgIC8vICAtIElmIGtleSBpcyBvdGhlciB0aGFuIGVzY2FwZVxuICAgICAgLy8gICAgLSBJZiBrZXkgaXMgbm90IHVwIG9yIGRvd24gPT4gbm90IGEgZHJvcGRvd24gY29tbWFuZFxuICAgICAgLy8gICAgLSBJZiB0cmlnZ2VyIGluc2lkZSB0aGUgbWVudSA9PiBub3QgYSBkcm9wZG93biBjb21tYW5kXG4gICAgICBpZiAoL2lucHV0fHRleHRhcmVhL2kudGVzdChldmVudC50YXJnZXQudGFnTmFtZSkgPyBldmVudC5rZXkgPT09IFNQQUNFX0tFWSB8fCBldmVudC5rZXkgIT09IEVTQ0FQRV9LRVkkMiAmJiAoZXZlbnQua2V5ICE9PSBBUlJPV19ET1dOX0tFWSAmJiBldmVudC5rZXkgIT09IEFSUk9XX1VQX0tFWSB8fCBldmVudC50YXJnZXQuY2xvc2VzdChTRUxFQ1RPUl9NRU5VKSkgOiAhUkVHRVhQX0tFWURPV04udGVzdChldmVudC5rZXkpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgaXNBY3RpdmUgPSB0aGlzLmNsYXNzTGlzdC5jb250YWlucyhDTEFTU19OQU1FX1NIT1ckNik7XG5cbiAgICAgIGlmICghaXNBY3RpdmUgJiYgZXZlbnQua2V5ID09PSBFU0NBUEVfS0VZJDIpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgIGlmIChpc0Rpc2FibGVkKHRoaXMpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZ2V0VG9nZ2xlQnV0dG9uID0gdGhpcy5tYXRjaGVzKFNFTEVDVE9SX0RBVEFfVE9HR0xFJDMpID8gdGhpcyA6IFNlbGVjdG9yRW5naW5lLnByZXYodGhpcywgU0VMRUNUT1JfREFUQV9UT0dHTEUkMylbMF07XG4gICAgICBjb25zdCBpbnN0YW5jZSA9IERyb3Bkb3duLmdldE9yQ3JlYXRlSW5zdGFuY2UoZ2V0VG9nZ2xlQnV0dG9uKTtcblxuICAgICAgaWYgKGV2ZW50LmtleSA9PT0gRVNDQVBFX0tFWSQyKSB7XG4gICAgICAgIGluc3RhbmNlLmhpZGUoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoZXZlbnQua2V5ID09PSBBUlJPV19VUF9LRVkgfHwgZXZlbnQua2V5ID09PSBBUlJPV19ET1dOX0tFWSkge1xuICAgICAgICBpZiAoIWlzQWN0aXZlKSB7XG4gICAgICAgICAgaW5zdGFuY2Uuc2hvdygpO1xuICAgICAgICB9XG5cbiAgICAgICAgaW5zdGFuY2UuX3NlbGVjdE1lbnVJdGVtKGV2ZW50KTtcblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICghaXNBY3RpdmUgfHwgZXZlbnQua2V5ID09PSBTUEFDRV9LRVkpIHtcbiAgICAgICAgRHJvcGRvd24uY2xlYXJNZW51cygpO1xuICAgICAgfVxuICAgIH1cblxuICB9XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogRGF0YSBBcGkgaW1wbGVtZW50YXRpb25cbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG5cbiAgRXZlbnRIYW5kbGVyLm9uKGRvY3VtZW50LCBFVkVOVF9LRVlET1dOX0RBVEFfQVBJLCBTRUxFQ1RPUl9EQVRBX1RPR0dMRSQzLCBEcm9wZG93bi5kYXRhQXBpS2V5ZG93bkhhbmRsZXIpO1xuICBFdmVudEhhbmRsZXIub24oZG9jdW1lbnQsIEVWRU5UX0tFWURPV05fREFUQV9BUEksIFNFTEVDVE9SX01FTlUsIERyb3Bkb3duLmRhdGFBcGlLZXlkb3duSGFuZGxlcik7XG4gIEV2ZW50SGFuZGxlci5vbihkb2N1bWVudCwgRVZFTlRfQ0xJQ0tfREFUQV9BUEkkMywgRHJvcGRvd24uY2xlYXJNZW51cyk7XG4gIEV2ZW50SGFuZGxlci5vbihkb2N1bWVudCwgRVZFTlRfS0VZVVBfREFUQV9BUEksIERyb3Bkb3duLmNsZWFyTWVudXMpO1xuICBFdmVudEhhbmRsZXIub24oZG9jdW1lbnQsIEVWRU5UX0NMSUNLX0RBVEFfQVBJJDMsIFNFTEVDVE9SX0RBVEFfVE9HR0xFJDMsIGZ1bmN0aW9uIChldmVudCkge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgRHJvcGRvd24uZ2V0T3JDcmVhdGVJbnN0YW5jZSh0aGlzKS50b2dnbGUoKTtcbiAgfSk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogalF1ZXJ5XG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBhZGQgLkRyb3Bkb3duIHRvIGpRdWVyeSBvbmx5IGlmIGpRdWVyeSBpcyBwcmVzZW50XG4gICAqL1xuXG4gIGRlZmluZUpRdWVyeVBsdWdpbihEcm9wZG93bik7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjUuMS4zKTogdXRpbC9zY3JvbGxCYXIuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYWluL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuICBjb25zdCBTRUxFQ1RPUl9GSVhFRF9DT05URU5UID0gJy5maXhlZC10b3AsIC5maXhlZC1ib3R0b20sIC5pcy1maXhlZCwgLnN0aWNreS10b3AnO1xuICBjb25zdCBTRUxFQ1RPUl9TVElDS1lfQ09OVEVOVCA9ICcuc3RpY2t5LXRvcCc7XG5cbiAgY2xhc3MgU2Nyb2xsQmFySGVscGVyIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgIHRoaXMuX2VsZW1lbnQgPSBkb2N1bWVudC5ib2R5O1xuICAgIH1cblxuICAgIGdldFdpZHRoKCkge1xuICAgICAgLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1dpbmRvdy9pbm5lcldpZHRoI3VzYWdlX25vdGVzXG4gICAgICBjb25zdCBkb2N1bWVudFdpZHRoID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudFdpZHRoO1xuICAgICAgcmV0dXJuIE1hdGguYWJzKHdpbmRvdy5pbm5lcldpZHRoIC0gZG9jdW1lbnRXaWR0aCk7XG4gICAgfVxuXG4gICAgaGlkZSgpIHtcbiAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy5nZXRXaWR0aCgpO1xuXG4gICAgICB0aGlzLl9kaXNhYmxlT3ZlckZsb3coKTsgLy8gZ2l2ZSBwYWRkaW5nIHRvIGVsZW1lbnQgdG8gYmFsYW5jZSB0aGUgaGlkZGVuIHNjcm9sbGJhciB3aWR0aFxuXG5cbiAgICAgIHRoaXMuX3NldEVsZW1lbnRBdHRyaWJ1dGVzKHRoaXMuX2VsZW1lbnQsICdwYWRkaW5nUmlnaHQnLCBjYWxjdWxhdGVkVmFsdWUgPT4gY2FsY3VsYXRlZFZhbHVlICsgd2lkdGgpOyAvLyB0cmljazogV2UgYWRqdXN0IHBvc2l0aXZlIHBhZGRpbmdSaWdodCBhbmQgbmVnYXRpdmUgbWFyZ2luUmlnaHQgdG8gc3RpY2t5LXRvcCBlbGVtZW50cyB0byBrZWVwIHNob3dpbmcgZnVsbHdpZHRoXG5cblxuICAgICAgdGhpcy5fc2V0RWxlbWVudEF0dHJpYnV0ZXMoU0VMRUNUT1JfRklYRURfQ09OVEVOVCwgJ3BhZGRpbmdSaWdodCcsIGNhbGN1bGF0ZWRWYWx1ZSA9PiBjYWxjdWxhdGVkVmFsdWUgKyB3aWR0aCk7XG5cbiAgICAgIHRoaXMuX3NldEVsZW1lbnRBdHRyaWJ1dGVzKFNFTEVDVE9SX1NUSUNLWV9DT05URU5ULCAnbWFyZ2luUmlnaHQnLCBjYWxjdWxhdGVkVmFsdWUgPT4gY2FsY3VsYXRlZFZhbHVlIC0gd2lkdGgpO1xuICAgIH1cblxuICAgIF9kaXNhYmxlT3ZlckZsb3coKSB7XG4gICAgICB0aGlzLl9zYXZlSW5pdGlhbEF0dHJpYnV0ZSh0aGlzLl9lbGVtZW50LCAnb3ZlcmZsb3cnKTtcblxuICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZS5vdmVyZmxvdyA9ICdoaWRkZW4nO1xuICAgIH1cblxuICAgIF9zZXRFbGVtZW50QXR0cmlidXRlcyhzZWxlY3Rvciwgc3R5bGVQcm9wLCBjYWxsYmFjaykge1xuICAgICAgY29uc3Qgc2Nyb2xsYmFyV2lkdGggPSB0aGlzLmdldFdpZHRoKCk7XG5cbiAgICAgIGNvbnN0IG1hbmlwdWxhdGlvbkNhbGxCYWNrID0gZWxlbWVudCA9PiB7XG4gICAgICAgIGlmIChlbGVtZW50ICE9PSB0aGlzLl9lbGVtZW50ICYmIHdpbmRvdy5pbm5lcldpZHRoID4gZWxlbWVudC5jbGllbnRXaWR0aCArIHNjcm9sbGJhcldpZHRoKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fc2F2ZUluaXRpYWxBdHRyaWJ1dGUoZWxlbWVudCwgc3R5bGVQcm9wKTtcblxuICAgICAgICBjb25zdCBjYWxjdWxhdGVkVmFsdWUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50KVtzdHlsZVByb3BdO1xuICAgICAgICBlbGVtZW50LnN0eWxlW3N0eWxlUHJvcF0gPSBgJHtjYWxsYmFjayhOdW1iZXIucGFyc2VGbG9hdChjYWxjdWxhdGVkVmFsdWUpKX1weGA7XG4gICAgICB9O1xuXG4gICAgICB0aGlzLl9hcHBseU1hbmlwdWxhdGlvbkNhbGxiYWNrKHNlbGVjdG9yLCBtYW5pcHVsYXRpb25DYWxsQmFjayk7XG4gICAgfVxuXG4gICAgcmVzZXQoKSB7XG4gICAgICB0aGlzLl9yZXNldEVsZW1lbnRBdHRyaWJ1dGVzKHRoaXMuX2VsZW1lbnQsICdvdmVyZmxvdycpO1xuXG4gICAgICB0aGlzLl9yZXNldEVsZW1lbnRBdHRyaWJ1dGVzKHRoaXMuX2VsZW1lbnQsICdwYWRkaW5nUmlnaHQnKTtcblxuICAgICAgdGhpcy5fcmVzZXRFbGVtZW50QXR0cmlidXRlcyhTRUxFQ1RPUl9GSVhFRF9DT05URU5ULCAncGFkZGluZ1JpZ2h0Jyk7XG5cbiAgICAgIHRoaXMuX3Jlc2V0RWxlbWVudEF0dHJpYnV0ZXMoU0VMRUNUT1JfU1RJQ0tZX0NPTlRFTlQsICdtYXJnaW5SaWdodCcpO1xuICAgIH1cblxuICAgIF9zYXZlSW5pdGlhbEF0dHJpYnV0ZShlbGVtZW50LCBzdHlsZVByb3ApIHtcbiAgICAgIGNvbnN0IGFjdHVhbFZhbHVlID0gZWxlbWVudC5zdHlsZVtzdHlsZVByb3BdO1xuXG4gICAgICBpZiAoYWN0dWFsVmFsdWUpIHtcbiAgICAgICAgTWFuaXB1bGF0b3Iuc2V0RGF0YUF0dHJpYnV0ZShlbGVtZW50LCBzdHlsZVByb3AsIGFjdHVhbFZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBfcmVzZXRFbGVtZW50QXR0cmlidXRlcyhzZWxlY3Rvciwgc3R5bGVQcm9wKSB7XG4gICAgICBjb25zdCBtYW5pcHVsYXRpb25DYWxsQmFjayA9IGVsZW1lbnQgPT4ge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IE1hbmlwdWxhdG9yLmdldERhdGFBdHRyaWJ1dGUoZWxlbWVudCwgc3R5bGVQcm9wKTtcblxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIGVsZW1lbnQuc3R5bGUucmVtb3ZlUHJvcGVydHkoc3R5bGVQcm9wKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBNYW5pcHVsYXRvci5yZW1vdmVEYXRhQXR0cmlidXRlKGVsZW1lbnQsIHN0eWxlUHJvcCk7XG4gICAgICAgICAgZWxlbWVudC5zdHlsZVtzdHlsZVByb3BdID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIHRoaXMuX2FwcGx5TWFuaXB1bGF0aW9uQ2FsbGJhY2soc2VsZWN0b3IsIG1hbmlwdWxhdGlvbkNhbGxCYWNrKTtcbiAgICB9XG5cbiAgICBfYXBwbHlNYW5pcHVsYXRpb25DYWxsYmFjayhzZWxlY3RvciwgY2FsbEJhY2spIHtcbiAgICAgIGlmIChpc0VsZW1lbnQkMShzZWxlY3RvcikpIHtcbiAgICAgICAgY2FsbEJhY2soc2VsZWN0b3IpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgU2VsZWN0b3JFbmdpbmUuZmluZChzZWxlY3RvciwgdGhpcy5fZWxlbWVudCkuZm9yRWFjaChjYWxsQmFjayk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaXNPdmVyZmxvd2luZygpIHtcbiAgICAgIHJldHVybiB0aGlzLmdldFdpZHRoKCkgPiAwO1xuICAgIH1cblxuICB9XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjUuMS4zKTogdXRpbC9iYWNrZHJvcC5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIGNvbnN0IERlZmF1bHQkNyA9IHtcbiAgICBjbGFzc05hbWU6ICdtb2RhbC1iYWNrZHJvcCcsXG4gICAgaXNWaXNpYmxlOiB0cnVlLFxuICAgIC8vIGlmIGZhbHNlLCB3ZSB1c2UgdGhlIGJhY2tkcm9wIGhlbHBlciB3aXRob3V0IGFkZGluZyBhbnkgZWxlbWVudCB0byB0aGUgZG9tXG4gICAgaXNBbmltYXRlZDogZmFsc2UsXG4gICAgcm9vdEVsZW1lbnQ6ICdib2R5JyxcbiAgICAvLyBnaXZlIHRoZSBjaG9pY2UgdG8gcGxhY2UgYmFja2Ryb3AgdW5kZXIgZGlmZmVyZW50IGVsZW1lbnRzXG4gICAgY2xpY2tDYWxsYmFjazogbnVsbFxuICB9O1xuICBjb25zdCBEZWZhdWx0VHlwZSQ3ID0ge1xuICAgIGNsYXNzTmFtZTogJ3N0cmluZycsXG4gICAgaXNWaXNpYmxlOiAnYm9vbGVhbicsXG4gICAgaXNBbmltYXRlZDogJ2Jvb2xlYW4nLFxuICAgIHJvb3RFbGVtZW50OiAnKGVsZW1lbnR8c3RyaW5nKScsXG4gICAgY2xpY2tDYWxsYmFjazogJyhmdW5jdGlvbnxudWxsKSdcbiAgfTtcbiAgY29uc3QgTkFNRSQ4ID0gJ2JhY2tkcm9wJztcbiAgY29uc3QgQ0xBU1NfTkFNRV9GQURFJDQgPSAnZmFkZSc7XG4gIGNvbnN0IENMQVNTX05BTUVfU0hPVyQ1ID0gJ3Nob3cnO1xuICBjb25zdCBFVkVOVF9NT1VTRURPV04gPSBgbW91c2Vkb3duLmJzLiR7TkFNRSQ4fWA7XG5cbiAgY2xhc3MgQmFja2Ryb3Age1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZykge1xuICAgICAgdGhpcy5fY29uZmlnID0gdGhpcy5fZ2V0Q29uZmlnKGNvbmZpZyk7XG4gICAgICB0aGlzLl9pc0FwcGVuZGVkID0gZmFsc2U7XG4gICAgICB0aGlzLl9lbGVtZW50ID0gbnVsbDtcbiAgICB9XG5cbiAgICBzaG93KGNhbGxiYWNrKSB7XG4gICAgICBpZiAoIXRoaXMuX2NvbmZpZy5pc1Zpc2libGUpIHtcbiAgICAgICAgZXhlY3V0ZShjYWxsYmFjayk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fYXBwZW5kKCk7XG5cbiAgICAgIGlmICh0aGlzLl9jb25maWcuaXNBbmltYXRlZCkge1xuICAgICAgICByZWZsb3codGhpcy5fZ2V0RWxlbWVudCgpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fZ2V0RWxlbWVudCgpLmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9TSE9XJDUpO1xuXG4gICAgICB0aGlzLl9lbXVsYXRlQW5pbWF0aW9uKCgpID0+IHtcbiAgICAgICAgZXhlY3V0ZShjYWxsYmFjayk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBoaWRlKGNhbGxiYWNrKSB7XG4gICAgICBpZiAoIXRoaXMuX2NvbmZpZy5pc1Zpc2libGUpIHtcbiAgICAgICAgZXhlY3V0ZShjYWxsYmFjayk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fZ2V0RWxlbWVudCgpLmNsYXNzTGlzdC5yZW1vdmUoQ0xBU1NfTkFNRV9TSE9XJDUpO1xuXG4gICAgICB0aGlzLl9lbXVsYXRlQW5pbWF0aW9uKCgpID0+IHtcbiAgICAgICAgdGhpcy5kaXNwb3NlKCk7XG4gICAgICAgIGV4ZWN1dGUoY2FsbGJhY2spO1xuICAgICAgfSk7XG4gICAgfSAvLyBQcml2YXRlXG5cblxuICAgIF9nZXRFbGVtZW50KCkge1xuICAgICAgaWYgKCF0aGlzLl9lbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IGJhY2tkcm9wID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIGJhY2tkcm9wLmNsYXNzTmFtZSA9IHRoaXMuX2NvbmZpZy5jbGFzc05hbWU7XG5cbiAgICAgICAgaWYgKHRoaXMuX2NvbmZpZy5pc0FuaW1hdGVkKSB7XG4gICAgICAgICAgYmFja2Ryb3AuY2xhc3NMaXN0LmFkZChDTEFTU19OQU1FX0ZBREUkNCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9lbGVtZW50ID0gYmFja2Ryb3A7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLl9lbGVtZW50O1xuICAgIH1cblxuICAgIF9nZXRDb25maWcoY29uZmlnKSB7XG4gICAgICBjb25maWcgPSB7IC4uLkRlZmF1bHQkNyxcbiAgICAgICAgLi4uKHR5cGVvZiBjb25maWcgPT09ICdvYmplY3QnID8gY29uZmlnIDoge30pXG4gICAgICB9OyAvLyB1c2UgZ2V0RWxlbWVudCgpIHdpdGggdGhlIGRlZmF1bHQgXCJib2R5XCIgdG8gZ2V0IGEgZnJlc2ggRWxlbWVudCBvbiBlYWNoIGluc3RhbnRpYXRpb25cblxuICAgICAgY29uZmlnLnJvb3RFbGVtZW50ID0gZ2V0RWxlbWVudChjb25maWcucm9vdEVsZW1lbnQpO1xuICAgICAgdHlwZUNoZWNrQ29uZmlnKE5BTUUkOCwgY29uZmlnLCBEZWZhdWx0VHlwZSQ3KTtcbiAgICAgIHJldHVybiBjb25maWc7XG4gICAgfVxuXG4gICAgX2FwcGVuZCgpIHtcbiAgICAgIGlmICh0aGlzLl9pc0FwcGVuZGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fY29uZmlnLnJvb3RFbGVtZW50LmFwcGVuZCh0aGlzLl9nZXRFbGVtZW50KCkpO1xuXG4gICAgICBFdmVudEhhbmRsZXIub24odGhpcy5fZ2V0RWxlbWVudCgpLCBFVkVOVF9NT1VTRURPV04sICgpID0+IHtcbiAgICAgICAgZXhlY3V0ZSh0aGlzLl9jb25maWcuY2xpY2tDYWxsYmFjayk7XG4gICAgICB9KTtcbiAgICAgIHRoaXMuX2lzQXBwZW5kZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGRpc3Bvc2UoKSB7XG4gICAgICBpZiAoIXRoaXMuX2lzQXBwZW5kZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBFdmVudEhhbmRsZXIub2ZmKHRoaXMuX2VsZW1lbnQsIEVWRU5UX01PVVNFRE9XTik7XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQucmVtb3ZlKCk7XG5cbiAgICAgIHRoaXMuX2lzQXBwZW5kZWQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBfZW11bGF0ZUFuaW1hdGlvbihjYWxsYmFjaykge1xuICAgICAgZXhlY3V0ZUFmdGVyVHJhbnNpdGlvbihjYWxsYmFjaywgdGhpcy5fZ2V0RWxlbWVudCgpLCB0aGlzLl9jb25maWcuaXNBbmltYXRlZCk7XG4gICAgfVxuXG4gIH1cblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NS4xLjMpOiB1dGlsL2ZvY3VzdHJhcC5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIGNvbnN0IERlZmF1bHQkNiA9IHtcbiAgICB0cmFwRWxlbWVudDogbnVsbCxcbiAgICAvLyBUaGUgZWxlbWVudCB0byB0cmFwIGZvY3VzIGluc2lkZSBvZlxuICAgIGF1dG9mb2N1czogdHJ1ZVxuICB9O1xuICBjb25zdCBEZWZhdWx0VHlwZSQ2ID0ge1xuICAgIHRyYXBFbGVtZW50OiAnZWxlbWVudCcsXG4gICAgYXV0b2ZvY3VzOiAnYm9vbGVhbidcbiAgfTtcbiAgY29uc3QgTkFNRSQ3ID0gJ2ZvY3VzdHJhcCc7XG4gIGNvbnN0IERBVEFfS0VZJDcgPSAnYnMuZm9jdXN0cmFwJztcbiAgY29uc3QgRVZFTlRfS0VZJDcgPSBgLiR7REFUQV9LRVkkN31gO1xuICBjb25zdCBFVkVOVF9GT0NVU0lOJDEgPSBgZm9jdXNpbiR7RVZFTlRfS0VZJDd9YDtcbiAgY29uc3QgRVZFTlRfS0VZRE9XTl9UQUIgPSBga2V5ZG93bi50YWIke0VWRU5UX0tFWSQ3fWA7XG4gIGNvbnN0IFRBQl9LRVkgPSAnVGFiJztcbiAgY29uc3QgVEFCX05BVl9GT1JXQVJEID0gJ2ZvcndhcmQnO1xuICBjb25zdCBUQUJfTkFWX0JBQ0tXQVJEID0gJ2JhY2t3YXJkJztcblxuICBjbGFzcyBGb2N1c1RyYXAge1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZykge1xuICAgICAgdGhpcy5fY29uZmlnID0gdGhpcy5fZ2V0Q29uZmlnKGNvbmZpZyk7XG4gICAgICB0aGlzLl9pc0FjdGl2ZSA9IGZhbHNlO1xuICAgICAgdGhpcy5fbGFzdFRhYk5hdkRpcmVjdGlvbiA9IG51bGw7XG4gICAgfVxuXG4gICAgYWN0aXZhdGUoKSB7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHRyYXBFbGVtZW50LFxuICAgICAgICBhdXRvZm9jdXNcbiAgICAgIH0gPSB0aGlzLl9jb25maWc7XG5cbiAgICAgIGlmICh0aGlzLl9pc0FjdGl2ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmIChhdXRvZm9jdXMpIHtcbiAgICAgICAgdHJhcEVsZW1lbnQuZm9jdXMoKTtcbiAgICAgIH1cblxuICAgICAgRXZlbnRIYW5kbGVyLm9mZihkb2N1bWVudCwgRVZFTlRfS0VZJDcpOyAvLyBndWFyZCBhZ2FpbnN0IGluZmluaXRlIGZvY3VzIGxvb3BcblxuICAgICAgRXZlbnRIYW5kbGVyLm9uKGRvY3VtZW50LCBFVkVOVF9GT0NVU0lOJDEsIGV2ZW50ID0+IHRoaXMuX2hhbmRsZUZvY3VzaW4oZXZlbnQpKTtcbiAgICAgIEV2ZW50SGFuZGxlci5vbihkb2N1bWVudCwgRVZFTlRfS0VZRE9XTl9UQUIsIGV2ZW50ID0+IHRoaXMuX2hhbmRsZUtleWRvd24oZXZlbnQpKTtcbiAgICAgIHRoaXMuX2lzQWN0aXZlID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBkZWFjdGl2YXRlKCkge1xuICAgICAgaWYgKCF0aGlzLl9pc0FjdGl2ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2lzQWN0aXZlID0gZmFsc2U7XG4gICAgICBFdmVudEhhbmRsZXIub2ZmKGRvY3VtZW50LCBFVkVOVF9LRVkkNyk7XG4gICAgfSAvLyBQcml2YXRlXG5cblxuICAgIF9oYW5kbGVGb2N1c2luKGV2ZW50KSB7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHRhcmdldFxuICAgICAgfSA9IGV2ZW50O1xuICAgICAgY29uc3Qge1xuICAgICAgICB0cmFwRWxlbWVudFxuICAgICAgfSA9IHRoaXMuX2NvbmZpZztcblxuICAgICAgaWYgKHRhcmdldCA9PT0gZG9jdW1lbnQgfHwgdGFyZ2V0ID09PSB0cmFwRWxlbWVudCB8fCB0cmFwRWxlbWVudC5jb250YWlucyh0YXJnZXQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZWxlbWVudHMgPSBTZWxlY3RvckVuZ2luZS5mb2N1c2FibGVDaGlsZHJlbih0cmFwRWxlbWVudCk7XG5cbiAgICAgIGlmIChlbGVtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdHJhcEVsZW1lbnQuZm9jdXMoKTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5fbGFzdFRhYk5hdkRpcmVjdGlvbiA9PT0gVEFCX05BVl9CQUNLV0FSRCkge1xuICAgICAgICBlbGVtZW50c1tlbGVtZW50cy5sZW5ndGggLSAxXS5mb2N1cygpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZWxlbWVudHNbMF0uZm9jdXMoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBfaGFuZGxlS2V5ZG93bihldmVudCkge1xuICAgICAgaWYgKGV2ZW50LmtleSAhPT0gVEFCX0tFWSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2xhc3RUYWJOYXZEaXJlY3Rpb24gPSBldmVudC5zaGlmdEtleSA/IFRBQl9OQVZfQkFDS1dBUkQgOiBUQUJfTkFWX0ZPUldBUkQ7XG4gICAgfVxuXG4gICAgX2dldENvbmZpZyhjb25maWcpIHtcbiAgICAgIGNvbmZpZyA9IHsgLi4uRGVmYXVsdCQ2LFxuICAgICAgICAuLi4odHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcgPyBjb25maWcgOiB7fSlcbiAgICAgIH07XG4gICAgICB0eXBlQ2hlY2tDb25maWcoTkFNRSQ3LCBjb25maWcsIERlZmF1bHRUeXBlJDYpO1xuICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICB9XG5cbiAgfVxuXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBCb290c3RyYXAgKHY1LjEuMyk6IG1vZGFsLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDb25zdGFudHNcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIGNvbnN0IE5BTUUkNiA9ICdtb2RhbCc7XG4gIGNvbnN0IERBVEFfS0VZJDYgPSAnYnMubW9kYWwnO1xuICBjb25zdCBFVkVOVF9LRVkkNiA9IGAuJHtEQVRBX0tFWSQ2fWA7XG4gIGNvbnN0IERBVEFfQVBJX0tFWSQzID0gJy5kYXRhLWFwaSc7XG4gIGNvbnN0IEVTQ0FQRV9LRVkkMSA9ICdFc2NhcGUnO1xuICBjb25zdCBEZWZhdWx0JDUgPSB7XG4gICAgYmFja2Ryb3A6IHRydWUsXG4gICAga2V5Ym9hcmQ6IHRydWUsXG4gICAgZm9jdXM6IHRydWVcbiAgfTtcbiAgY29uc3QgRGVmYXVsdFR5cGUkNSA9IHtcbiAgICBiYWNrZHJvcDogJyhib29sZWFufHN0cmluZyknLFxuICAgIGtleWJvYXJkOiAnYm9vbGVhbicsXG4gICAgZm9jdXM6ICdib29sZWFuJ1xuICB9O1xuICBjb25zdCBFVkVOVF9ISURFJDMgPSBgaGlkZSR7RVZFTlRfS0VZJDZ9YDtcbiAgY29uc3QgRVZFTlRfSElERV9QUkVWRU5URUQgPSBgaGlkZVByZXZlbnRlZCR7RVZFTlRfS0VZJDZ9YDtcbiAgY29uc3QgRVZFTlRfSElEREVOJDMgPSBgaGlkZGVuJHtFVkVOVF9LRVkkNn1gO1xuICBjb25zdCBFVkVOVF9TSE9XJDMgPSBgc2hvdyR7RVZFTlRfS0VZJDZ9YDtcbiAgY29uc3QgRVZFTlRfU0hPV04kMyA9IGBzaG93biR7RVZFTlRfS0VZJDZ9YDtcbiAgY29uc3QgRVZFTlRfUkVTSVpFID0gYHJlc2l6ZSR7RVZFTlRfS0VZJDZ9YDtcbiAgY29uc3QgRVZFTlRfQ0xJQ0tfRElTTUlTUyA9IGBjbGljay5kaXNtaXNzJHtFVkVOVF9LRVkkNn1gO1xuICBjb25zdCBFVkVOVF9LRVlET1dOX0RJU01JU1MkMSA9IGBrZXlkb3duLmRpc21pc3Mke0VWRU5UX0tFWSQ2fWA7XG4gIGNvbnN0IEVWRU5UX01PVVNFVVBfRElTTUlTUyA9IGBtb3VzZXVwLmRpc21pc3Mke0VWRU5UX0tFWSQ2fWA7XG4gIGNvbnN0IEVWRU5UX01PVVNFRE9XTl9ESVNNSVNTID0gYG1vdXNlZG93bi5kaXNtaXNzJHtFVkVOVF9LRVkkNn1gO1xuICBjb25zdCBFVkVOVF9DTElDS19EQVRBX0FQSSQyID0gYGNsaWNrJHtFVkVOVF9LRVkkNn0ke0RBVEFfQVBJX0tFWSQzfWA7XG4gIGNvbnN0IENMQVNTX05BTUVfT1BFTiA9ICdtb2RhbC1vcGVuJztcbiAgY29uc3QgQ0xBU1NfTkFNRV9GQURFJDMgPSAnZmFkZSc7XG4gIGNvbnN0IENMQVNTX05BTUVfU0hPVyQ0ID0gJ3Nob3cnO1xuICBjb25zdCBDTEFTU19OQU1FX1NUQVRJQyA9ICdtb2RhbC1zdGF0aWMnO1xuICBjb25zdCBPUEVOX1NFTEVDVE9SJDEgPSAnLm1vZGFsLnNob3cnO1xuICBjb25zdCBTRUxFQ1RPUl9ESUFMT0cgPSAnLm1vZGFsLWRpYWxvZyc7XG4gIGNvbnN0IFNFTEVDVE9SX01PREFMX0JPRFkgPSAnLm1vZGFsLWJvZHknO1xuICBjb25zdCBTRUxFQ1RPUl9EQVRBX1RPR0dMRSQyID0gJ1tkYXRhLWJzLXRvZ2dsZT1cIm1vZGFsXCJdJztcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICBjbGFzcyBNb2RhbCBleHRlbmRzIEJhc2VDb21wb25lbnQge1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQsIGNvbmZpZykge1xuICAgICAgc3VwZXIoZWxlbWVudCk7XG4gICAgICB0aGlzLl9jb25maWcgPSB0aGlzLl9nZXRDb25maWcoY29uZmlnKTtcbiAgICAgIHRoaXMuX2RpYWxvZyA9IFNlbGVjdG9yRW5naW5lLmZpbmRPbmUoU0VMRUNUT1JfRElBTE9HLCB0aGlzLl9lbGVtZW50KTtcbiAgICAgIHRoaXMuX2JhY2tkcm9wID0gdGhpcy5faW5pdGlhbGl6ZUJhY2tEcm9wKCk7XG4gICAgICB0aGlzLl9mb2N1c3RyYXAgPSB0aGlzLl9pbml0aWFsaXplRm9jdXNUcmFwKCk7XG4gICAgICB0aGlzLl9pc1Nob3duID0gZmFsc2U7XG4gICAgICB0aGlzLl9pZ25vcmVCYWNrZHJvcENsaWNrID0gZmFsc2U7XG4gICAgICB0aGlzLl9pc1RyYW5zaXRpb25pbmcgPSBmYWxzZTtcbiAgICAgIHRoaXMuX3Njcm9sbEJhciA9IG5ldyBTY3JvbGxCYXJIZWxwZXIoKTtcbiAgICB9IC8vIEdldHRlcnNcblxuXG4gICAgc3RhdGljIGdldCBEZWZhdWx0KCkge1xuICAgICAgcmV0dXJuIERlZmF1bHQkNTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZ2V0IE5BTUUoKSB7XG4gICAgICByZXR1cm4gTkFNRSQ2O1xuICAgIH0gLy8gUHVibGljXG5cblxuICAgIHRvZ2dsZShyZWxhdGVkVGFyZ2V0KSB7XG4gICAgICByZXR1cm4gdGhpcy5faXNTaG93biA/IHRoaXMuaGlkZSgpIDogdGhpcy5zaG93KHJlbGF0ZWRUYXJnZXQpO1xuICAgIH1cblxuICAgIHNob3cocmVsYXRlZFRhcmdldCkge1xuICAgICAgaWYgKHRoaXMuX2lzU2hvd24gfHwgdGhpcy5faXNUcmFuc2l0aW9uaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc2hvd0V2ZW50ID0gRXZlbnRIYW5kbGVyLnRyaWdnZXIodGhpcy5fZWxlbWVudCwgRVZFTlRfU0hPVyQzLCB7XG4gICAgICAgIHJlbGF0ZWRUYXJnZXRcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoc2hvd0V2ZW50LmRlZmF1bHRQcmV2ZW50ZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9pc1Nob3duID0gdHJ1ZTtcblxuICAgICAgaWYgKHRoaXMuX2lzQW5pbWF0ZWQoKSkge1xuICAgICAgICB0aGlzLl9pc1RyYW5zaXRpb25pbmcgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9zY3JvbGxCYXIuaGlkZSgpO1xuXG4gICAgICBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9PUEVOKTtcblxuICAgICAgdGhpcy5fYWRqdXN0RGlhbG9nKCk7XG5cbiAgICAgIHRoaXMuX3NldEVzY2FwZUV2ZW50KCk7XG5cbiAgICAgIHRoaXMuX3NldFJlc2l6ZUV2ZW50KCk7XG5cbiAgICAgIEV2ZW50SGFuZGxlci5vbih0aGlzLl9kaWFsb2csIEVWRU5UX01PVVNFRE9XTl9ESVNNSVNTLCAoKSA9PiB7XG4gICAgICAgIEV2ZW50SGFuZGxlci5vbmUodGhpcy5fZWxlbWVudCwgRVZFTlRfTU9VU0VVUF9ESVNNSVNTLCBldmVudCA9PiB7XG4gICAgICAgICAgaWYgKGV2ZW50LnRhcmdldCA9PT0gdGhpcy5fZWxlbWVudCkge1xuICAgICAgICAgICAgdGhpcy5faWdub3JlQmFja2Ryb3BDbGljayA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLl9zaG93QmFja2Ryb3AoKCkgPT4gdGhpcy5fc2hvd0VsZW1lbnQocmVsYXRlZFRhcmdldCkpO1xuICAgIH1cblxuICAgIGhpZGUoKSB7XG4gICAgICBpZiAoIXRoaXMuX2lzU2hvd24gfHwgdGhpcy5faXNUcmFuc2l0aW9uaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgaGlkZUV2ZW50ID0gRXZlbnRIYW5kbGVyLnRyaWdnZXIodGhpcy5fZWxlbWVudCwgRVZFTlRfSElERSQzKTtcblxuICAgICAgaWYgKGhpZGVFdmVudC5kZWZhdWx0UHJldmVudGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5faXNTaG93biA9IGZhbHNlO1xuXG4gICAgICBjb25zdCBpc0FuaW1hdGVkID0gdGhpcy5faXNBbmltYXRlZCgpO1xuXG4gICAgICBpZiAoaXNBbmltYXRlZCkge1xuICAgICAgICB0aGlzLl9pc1RyYW5zaXRpb25pbmcgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9zZXRFc2NhcGVFdmVudCgpO1xuXG4gICAgICB0aGlzLl9zZXRSZXNpemVFdmVudCgpO1xuXG4gICAgICB0aGlzLl9mb2N1c3RyYXAuZGVhY3RpdmF0ZSgpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoQ0xBU1NfTkFNRV9TSE9XJDQpO1xuXG4gICAgICBFdmVudEhhbmRsZXIub2ZmKHRoaXMuX2VsZW1lbnQsIEVWRU5UX0NMSUNLX0RJU01JU1MpO1xuICAgICAgRXZlbnRIYW5kbGVyLm9mZih0aGlzLl9kaWFsb2csIEVWRU5UX01PVVNFRE9XTl9ESVNNSVNTKTtcblxuICAgICAgdGhpcy5fcXVldWVDYWxsYmFjaygoKSA9PiB0aGlzLl9oaWRlTW9kYWwoKSwgdGhpcy5fZWxlbWVudCwgaXNBbmltYXRlZCk7XG4gICAgfVxuXG4gICAgZGlzcG9zZSgpIHtcbiAgICAgIFt3aW5kb3csIHRoaXMuX2RpYWxvZ10uZm9yRWFjaChodG1sRWxlbWVudCA9PiBFdmVudEhhbmRsZXIub2ZmKGh0bWxFbGVtZW50LCBFVkVOVF9LRVkkNikpO1xuXG4gICAgICB0aGlzLl9iYWNrZHJvcC5kaXNwb3NlKCk7XG5cbiAgICAgIHRoaXMuX2ZvY3VzdHJhcC5kZWFjdGl2YXRlKCk7XG5cbiAgICAgIHN1cGVyLmRpc3Bvc2UoKTtcbiAgICB9XG5cbiAgICBoYW5kbGVVcGRhdGUoKSB7XG4gICAgICB0aGlzLl9hZGp1c3REaWFsb2coKTtcbiAgICB9IC8vIFByaXZhdGVcblxuXG4gICAgX2luaXRpYWxpemVCYWNrRHJvcCgpIHtcbiAgICAgIHJldHVybiBuZXcgQmFja2Ryb3Aoe1xuICAgICAgICBpc1Zpc2libGU6IEJvb2xlYW4odGhpcy5fY29uZmlnLmJhY2tkcm9wKSxcbiAgICAgICAgLy8gJ3N0YXRpYycgb3B0aW9uIHdpbGwgYmUgdHJhbnNsYXRlZCB0byB0cnVlLCBhbmQgYm9vbGVhbnMgd2lsbCBrZWVwIHRoZWlyIHZhbHVlXG4gICAgICAgIGlzQW5pbWF0ZWQ6IHRoaXMuX2lzQW5pbWF0ZWQoKVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgX2luaXRpYWxpemVGb2N1c1RyYXAoKSB7XG4gICAgICByZXR1cm4gbmV3IEZvY3VzVHJhcCh7XG4gICAgICAgIHRyYXBFbGVtZW50OiB0aGlzLl9lbGVtZW50XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBfZ2V0Q29uZmlnKGNvbmZpZykge1xuICAgICAgY29uZmlnID0geyAuLi5EZWZhdWx0JDUsXG4gICAgICAgIC4uLk1hbmlwdWxhdG9yLmdldERhdGFBdHRyaWJ1dGVzKHRoaXMuX2VsZW1lbnQpLFxuICAgICAgICAuLi4odHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcgPyBjb25maWcgOiB7fSlcbiAgICAgIH07XG4gICAgICB0eXBlQ2hlY2tDb25maWcoTkFNRSQ2LCBjb25maWcsIERlZmF1bHRUeXBlJDUpO1xuICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICB9XG5cbiAgICBfc2hvd0VsZW1lbnQocmVsYXRlZFRhcmdldCkge1xuICAgICAgY29uc3QgaXNBbmltYXRlZCA9IHRoaXMuX2lzQW5pbWF0ZWQoKTtcblxuICAgICAgY29uc3QgbW9kYWxCb2R5ID0gU2VsZWN0b3JFbmdpbmUuZmluZE9uZShTRUxFQ1RPUl9NT0RBTF9CT0RZLCB0aGlzLl9kaWFsb2cpO1xuXG4gICAgICBpZiAoIXRoaXMuX2VsZW1lbnQucGFyZW50Tm9kZSB8fCB0aGlzLl9lbGVtZW50LnBhcmVudE5vZGUubm9kZVR5cGUgIT09IE5vZGUuRUxFTUVOVF9OT0RFKSB7XG4gICAgICAgIC8vIERvbid0IG1vdmUgbW9kYWwncyBET00gcG9zaXRpb25cbiAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmQodGhpcy5fZWxlbWVudCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQucmVtb3ZlQXR0cmlidXRlKCdhcmlhLWhpZGRlbicpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1tb2RhbCcsIHRydWUpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LnNldEF0dHJpYnV0ZSgncm9sZScsICdkaWFsb2cnKTtcblxuICAgICAgdGhpcy5fZWxlbWVudC5zY3JvbGxUb3AgPSAwO1xuXG4gICAgICBpZiAobW9kYWxCb2R5KSB7XG4gICAgICAgIG1vZGFsQm9keS5zY3JvbGxUb3AgPSAwO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNBbmltYXRlZCkge1xuICAgICAgICByZWZsb3codGhpcy5fZWxlbWVudCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmFkZChDTEFTU19OQU1FX1NIT1ckNCk7XG5cbiAgICAgIGNvbnN0IHRyYW5zaXRpb25Db21wbGV0ZSA9ICgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuX2NvbmZpZy5mb2N1cykge1xuICAgICAgICAgIHRoaXMuX2ZvY3VzdHJhcC5hY3RpdmF0ZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5faXNUcmFuc2l0aW9uaW5nID0gZmFsc2U7XG4gICAgICAgIEV2ZW50SGFuZGxlci50cmlnZ2VyKHRoaXMuX2VsZW1lbnQsIEVWRU5UX1NIT1dOJDMsIHtcbiAgICAgICAgICByZWxhdGVkVGFyZ2V0XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgdGhpcy5fcXVldWVDYWxsYmFjayh0cmFuc2l0aW9uQ29tcGxldGUsIHRoaXMuX2RpYWxvZywgaXNBbmltYXRlZCk7XG4gICAgfVxuXG4gICAgX3NldEVzY2FwZUV2ZW50KCkge1xuICAgICAgaWYgKHRoaXMuX2lzU2hvd24pIHtcbiAgICAgICAgRXZlbnRIYW5kbGVyLm9uKHRoaXMuX2VsZW1lbnQsIEVWRU5UX0tFWURPV05fRElTTUlTUyQxLCBldmVudCA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMuX2NvbmZpZy5rZXlib2FyZCAmJiBldmVudC5rZXkgPT09IEVTQ0FQRV9LRVkkMSkge1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuX2NvbmZpZy5rZXlib2FyZCAmJiBldmVudC5rZXkgPT09IEVTQ0FQRV9LRVkkMSkge1xuICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckJhY2tkcm9wVHJhbnNpdGlvbigpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBFdmVudEhhbmRsZXIub2ZmKHRoaXMuX2VsZW1lbnQsIEVWRU5UX0tFWURPV05fRElTTUlTUyQxKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBfc2V0UmVzaXplRXZlbnQoKSB7XG4gICAgICBpZiAodGhpcy5faXNTaG93bikge1xuICAgICAgICBFdmVudEhhbmRsZXIub24od2luZG93LCBFVkVOVF9SRVNJWkUsICgpID0+IHRoaXMuX2FkanVzdERpYWxvZygpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIEV2ZW50SGFuZGxlci5vZmYod2luZG93LCBFVkVOVF9SRVNJWkUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIF9oaWRlTW9kYWwoKSB7XG4gICAgICB0aGlzLl9lbGVtZW50LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQuc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsIHRydWUpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1tb2RhbCcpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgncm9sZScpO1xuXG4gICAgICB0aGlzLl9pc1RyYW5zaXRpb25pbmcgPSBmYWxzZTtcblxuICAgICAgdGhpcy5fYmFja2Ryb3AuaGlkZSgoKSA9PiB7XG4gICAgICAgIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LnJlbW92ZShDTEFTU19OQU1FX09QRU4pO1xuXG4gICAgICAgIHRoaXMuX3Jlc2V0QWRqdXN0bWVudHMoKTtcblxuICAgICAgICB0aGlzLl9zY3JvbGxCYXIucmVzZXQoKTtcblxuICAgICAgICBFdmVudEhhbmRsZXIudHJpZ2dlcih0aGlzLl9lbGVtZW50LCBFVkVOVF9ISURERU4kMyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBfc2hvd0JhY2tkcm9wKGNhbGxiYWNrKSB7XG4gICAgICBFdmVudEhhbmRsZXIub24odGhpcy5fZWxlbWVudCwgRVZFTlRfQ0xJQ0tfRElTTUlTUywgZXZlbnQgPT4ge1xuICAgICAgICBpZiAodGhpcy5faWdub3JlQmFja2Ryb3BDbGljaykge1xuICAgICAgICAgIHRoaXMuX2lnbm9yZUJhY2tkcm9wQ2xpY2sgPSBmYWxzZTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQudGFyZ2V0ICE9PSBldmVudC5jdXJyZW50VGFyZ2V0KSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX2NvbmZpZy5iYWNrZHJvcCA9PT0gdHJ1ZSkge1xuICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX2NvbmZpZy5iYWNrZHJvcCA9PT0gJ3N0YXRpYycpIHtcbiAgICAgICAgICB0aGlzLl90cmlnZ2VyQmFja2Ryb3BUcmFuc2l0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLl9iYWNrZHJvcC5zaG93KGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICBfaXNBbmltYXRlZCgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhDTEFTU19OQU1FX0ZBREUkMyk7XG4gICAgfVxuXG4gICAgX3RyaWdnZXJCYWNrZHJvcFRyYW5zaXRpb24oKSB7XG4gICAgICBjb25zdCBoaWRlRXZlbnQgPSBFdmVudEhhbmRsZXIudHJpZ2dlcih0aGlzLl9lbGVtZW50LCBFVkVOVF9ISURFX1BSRVZFTlRFRCk7XG5cbiAgICAgIGlmIChoaWRlRXZlbnQuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHtcbiAgICAgICAgY2xhc3NMaXN0LFxuICAgICAgICBzY3JvbGxIZWlnaHQsXG4gICAgICAgIHN0eWxlXG4gICAgICB9ID0gdGhpcy5fZWxlbWVudDtcbiAgICAgIGNvbnN0IGlzTW9kYWxPdmVyZmxvd2luZyA9IHNjcm9sbEhlaWdodCA+IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQ7IC8vIHJldHVybiBpZiB0aGUgZm9sbG93aW5nIGJhY2tncm91bmQgdHJhbnNpdGlvbiBoYXNuJ3QgeWV0IGNvbXBsZXRlZFxuXG4gICAgICBpZiAoIWlzTW9kYWxPdmVyZmxvd2luZyAmJiBzdHlsZS5vdmVyZmxvd1kgPT09ICdoaWRkZW4nIHx8IGNsYXNzTGlzdC5jb250YWlucyhDTEFTU19OQU1FX1NUQVRJQykpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWlzTW9kYWxPdmVyZmxvd2luZykge1xuICAgICAgICBzdHlsZS5vdmVyZmxvd1kgPSAnaGlkZGVuJztcbiAgICAgIH1cblxuICAgICAgY2xhc3NMaXN0LmFkZChDTEFTU19OQU1FX1NUQVRJQyk7XG5cbiAgICAgIHRoaXMuX3F1ZXVlQ2FsbGJhY2soKCkgPT4ge1xuICAgICAgICBjbGFzc0xpc3QucmVtb3ZlKENMQVNTX05BTUVfU1RBVElDKTtcblxuICAgICAgICBpZiAoIWlzTW9kYWxPdmVyZmxvd2luZykge1xuICAgICAgICAgIHRoaXMuX3F1ZXVlQ2FsbGJhY2soKCkgPT4ge1xuICAgICAgICAgICAgc3R5bGUub3ZlcmZsb3dZID0gJyc7XG4gICAgICAgICAgfSwgdGhpcy5fZGlhbG9nKTtcbiAgICAgICAgfVxuICAgICAgfSwgdGhpcy5fZGlhbG9nKTtcblxuICAgICAgdGhpcy5fZWxlbWVudC5mb2N1cygpO1xuICAgIH0gLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIHRoZSBmb2xsb3dpbmcgbWV0aG9kcyBhcmUgdXNlZCB0byBoYW5kbGUgb3ZlcmZsb3dpbmcgbW9kYWxzXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cbiAgICBfYWRqdXN0RGlhbG9nKCkge1xuICAgICAgY29uc3QgaXNNb2RhbE92ZXJmbG93aW5nID0gdGhpcy5fZWxlbWVudC5zY3JvbGxIZWlnaHQgPiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuXG4gICAgICBjb25zdCBzY3JvbGxiYXJXaWR0aCA9IHRoaXMuX3Njcm9sbEJhci5nZXRXaWR0aCgpO1xuXG4gICAgICBjb25zdCBpc0JvZHlPdmVyZmxvd2luZyA9IHNjcm9sbGJhcldpZHRoID4gMDtcblxuICAgICAgaWYgKCFpc0JvZHlPdmVyZmxvd2luZyAmJiBpc01vZGFsT3ZlcmZsb3dpbmcgJiYgIWlzUlRMKCkgfHwgaXNCb2R5T3ZlcmZsb3dpbmcgJiYgIWlzTW9kYWxPdmVyZmxvd2luZyAmJiBpc1JUTCgpKSB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGUucGFkZGluZ0xlZnQgPSBgJHtzY3JvbGxiYXJXaWR0aH1weGA7XG4gICAgICB9XG5cbiAgICAgIGlmIChpc0JvZHlPdmVyZmxvd2luZyAmJiAhaXNNb2RhbE92ZXJmbG93aW5nICYmICFpc1JUTCgpIHx8ICFpc0JvZHlPdmVyZmxvd2luZyAmJiBpc01vZGFsT3ZlcmZsb3dpbmcgJiYgaXNSVEwoKSkge1xuICAgICAgICB0aGlzLl9lbGVtZW50LnN0eWxlLnBhZGRpbmdSaWdodCA9IGAke3Njcm9sbGJhcldpZHRofXB4YDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBfcmVzZXRBZGp1c3RtZW50cygpIHtcbiAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGUucGFkZGluZ0xlZnQgPSAnJztcbiAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGUucGFkZGluZ1JpZ2h0ID0gJyc7XG4gICAgfSAvLyBTdGF0aWNcblxuXG4gICAgc3RhdGljIGpRdWVyeUludGVyZmFjZShjb25maWcsIHJlbGF0ZWRUYXJnZXQpIHtcbiAgICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBkYXRhID0gTW9kYWwuZ2V0T3JDcmVhdGVJbnN0YW5jZSh0aGlzLCBjb25maWcpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgY29uZmlnICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgZGF0YVtjb25maWddID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYE5vIG1ldGhvZCBuYW1lZCBcIiR7Y29uZmlnfVwiYCk7XG4gICAgICAgIH1cblxuICAgICAgICBkYXRhW2NvbmZpZ10ocmVsYXRlZFRhcmdldCk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgfVxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIERhdGEgQXBpIGltcGxlbWVudGF0aW9uXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuXG4gIEV2ZW50SGFuZGxlci5vbihkb2N1bWVudCwgRVZFTlRfQ0xJQ0tfREFUQV9BUEkkMiwgU0VMRUNUT1JfREFUQV9UT0dHTEUkMiwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgY29uc3QgdGFyZ2V0ID0gZ2V0RWxlbWVudEZyb21TZWxlY3Rvcih0aGlzKTtcblxuICAgIGlmIChbJ0EnLCAnQVJFQSddLmluY2x1ZGVzKHRoaXMudGFnTmFtZSkpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuXG4gICAgRXZlbnRIYW5kbGVyLm9uZSh0YXJnZXQsIEVWRU5UX1NIT1ckMywgc2hvd0V2ZW50ID0+IHtcbiAgICAgIGlmIChzaG93RXZlbnQuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICAvLyBvbmx5IHJlZ2lzdGVyIGZvY3VzIHJlc3RvcmVyIGlmIG1vZGFsIHdpbGwgYWN0dWFsbHkgZ2V0IHNob3duXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgRXZlbnRIYW5kbGVyLm9uZSh0YXJnZXQsIEVWRU5UX0hJRERFTiQzLCAoKSA9PiB7XG4gICAgICAgIGlmIChpc1Zpc2libGUodGhpcykpIHtcbiAgICAgICAgICB0aGlzLmZvY3VzKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pOyAvLyBhdm9pZCBjb25mbGljdCB3aGVuIGNsaWNraW5nIG1vZGRhbCB0b2dnbGVyIHdoaWxlIGFub3RoZXIgb25lIGlzIG9wZW5cblxuICAgIGNvbnN0IGFsbFJlYWR5T3BlbiA9IFNlbGVjdG9yRW5naW5lLmZpbmRPbmUoT1BFTl9TRUxFQ1RPUiQxKTtcblxuICAgIGlmIChhbGxSZWFkeU9wZW4pIHtcbiAgICAgIE1vZGFsLmdldEluc3RhbmNlKGFsbFJlYWR5T3BlbikuaGlkZSgpO1xuICAgIH1cblxuICAgIGNvbnN0IGRhdGEgPSBNb2RhbC5nZXRPckNyZWF0ZUluc3RhbmNlKHRhcmdldCk7XG4gICAgZGF0YS50b2dnbGUodGhpcyk7XG4gIH0pO1xuICBlbmFibGVEaXNtaXNzVHJpZ2dlcihNb2RhbCk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogalF1ZXJ5XG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBhZGQgLk1vZGFsIHRvIGpRdWVyeSBvbmx5IGlmIGpRdWVyeSBpcyBwcmVzZW50XG4gICAqL1xuXG4gIGRlZmluZUpRdWVyeVBsdWdpbihNb2RhbCk7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjUuMS4zKTogb2ZmY2FudmFzLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDb25zdGFudHNcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIGNvbnN0IE5BTUUkNSA9ICdvZmZjYW52YXMnO1xuICBjb25zdCBEQVRBX0tFWSQ1ID0gJ2JzLm9mZmNhbnZhcyc7XG4gIGNvbnN0IEVWRU5UX0tFWSQ1ID0gYC4ke0RBVEFfS0VZJDV9YDtcbiAgY29uc3QgREFUQV9BUElfS0VZJDIgPSAnLmRhdGEtYXBpJztcbiAgY29uc3QgRVZFTlRfTE9BRF9EQVRBX0FQSSQxID0gYGxvYWQke0VWRU5UX0tFWSQ1fSR7REFUQV9BUElfS0VZJDJ9YDtcbiAgY29uc3QgRVNDQVBFX0tFWSA9ICdFc2NhcGUnO1xuICBjb25zdCBEZWZhdWx0JDQgPSB7XG4gICAgYmFja2Ryb3A6IHRydWUsXG4gICAga2V5Ym9hcmQ6IHRydWUsXG4gICAgc2Nyb2xsOiBmYWxzZVxuICB9O1xuICBjb25zdCBEZWZhdWx0VHlwZSQ0ID0ge1xuICAgIGJhY2tkcm9wOiAnYm9vbGVhbicsXG4gICAga2V5Ym9hcmQ6ICdib29sZWFuJyxcbiAgICBzY3JvbGw6ICdib29sZWFuJ1xuICB9O1xuICBjb25zdCBDTEFTU19OQU1FX1NIT1ckMyA9ICdzaG93JztcbiAgY29uc3QgQ0xBU1NfTkFNRV9CQUNLRFJPUCA9ICdvZmZjYW52YXMtYmFja2Ryb3AnO1xuICBjb25zdCBPUEVOX1NFTEVDVE9SID0gJy5vZmZjYW52YXMuc2hvdyc7XG4gIGNvbnN0IEVWRU5UX1NIT1ckMiA9IGBzaG93JHtFVkVOVF9LRVkkNX1gO1xuICBjb25zdCBFVkVOVF9TSE9XTiQyID0gYHNob3duJHtFVkVOVF9LRVkkNX1gO1xuICBjb25zdCBFVkVOVF9ISURFJDIgPSBgaGlkZSR7RVZFTlRfS0VZJDV9YDtcbiAgY29uc3QgRVZFTlRfSElEREVOJDIgPSBgaGlkZGVuJHtFVkVOVF9LRVkkNX1gO1xuICBjb25zdCBFVkVOVF9DTElDS19EQVRBX0FQSSQxID0gYGNsaWNrJHtFVkVOVF9LRVkkNX0ke0RBVEFfQVBJX0tFWSQyfWA7XG4gIGNvbnN0IEVWRU5UX0tFWURPV05fRElTTUlTUyA9IGBrZXlkb3duLmRpc21pc3Mke0VWRU5UX0tFWSQ1fWA7XG4gIGNvbnN0IFNFTEVDVE9SX0RBVEFfVE9HR0xFJDEgPSAnW2RhdGEtYnMtdG9nZ2xlPVwib2ZmY2FudmFzXCJdJztcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICBjbGFzcyBPZmZjYW52YXMgZXh0ZW5kcyBCYXNlQ29tcG9uZW50IHtcbiAgICBjb25zdHJ1Y3RvcihlbGVtZW50LCBjb25maWcpIHtcbiAgICAgIHN1cGVyKGVsZW1lbnQpO1xuICAgICAgdGhpcy5fY29uZmlnID0gdGhpcy5fZ2V0Q29uZmlnKGNvbmZpZyk7XG4gICAgICB0aGlzLl9pc1Nob3duID0gZmFsc2U7XG4gICAgICB0aGlzLl9iYWNrZHJvcCA9IHRoaXMuX2luaXRpYWxpemVCYWNrRHJvcCgpO1xuICAgICAgdGhpcy5fZm9jdXN0cmFwID0gdGhpcy5faW5pdGlhbGl6ZUZvY3VzVHJhcCgpO1xuXG4gICAgICB0aGlzLl9hZGRFdmVudExpc3RlbmVycygpO1xuICAgIH0gLy8gR2V0dGVyc1xuXG5cbiAgICBzdGF0aWMgZ2V0IE5BTUUoKSB7XG4gICAgICByZXR1cm4gTkFNRSQ1O1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXQgRGVmYXVsdCgpIHtcbiAgICAgIHJldHVybiBEZWZhdWx0JDQ7XG4gICAgfSAvLyBQdWJsaWNcblxuXG4gICAgdG9nZ2xlKHJlbGF0ZWRUYXJnZXQpIHtcbiAgICAgIHJldHVybiB0aGlzLl9pc1Nob3duID8gdGhpcy5oaWRlKCkgOiB0aGlzLnNob3cocmVsYXRlZFRhcmdldCk7XG4gICAgfVxuXG4gICAgc2hvdyhyZWxhdGVkVGFyZ2V0KSB7XG4gICAgICBpZiAodGhpcy5faXNTaG93bikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNob3dFdmVudCA9IEV2ZW50SGFuZGxlci50cmlnZ2VyKHRoaXMuX2VsZW1lbnQsIEVWRU5UX1NIT1ckMiwge1xuICAgICAgICByZWxhdGVkVGFyZ2V0XG4gICAgICB9KTtcblxuICAgICAgaWYgKHNob3dFdmVudC5kZWZhdWx0UHJldmVudGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5faXNTaG93biA9IHRydWU7XG4gICAgICB0aGlzLl9lbGVtZW50LnN0eWxlLnZpc2liaWxpdHkgPSAndmlzaWJsZSc7XG5cbiAgICAgIHRoaXMuX2JhY2tkcm9wLnNob3coKTtcblxuICAgICAgaWYgKCF0aGlzLl9jb25maWcuc2Nyb2xsKSB7XG4gICAgICAgIG5ldyBTY3JvbGxCYXJIZWxwZXIoKS5oaWRlKCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQucmVtb3ZlQXR0cmlidXRlKCdhcmlhLWhpZGRlbicpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1tb2RhbCcsIHRydWUpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LnNldEF0dHJpYnV0ZSgncm9sZScsICdkaWFsb2cnKTtcblxuICAgICAgdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuYWRkKENMQVNTX05BTUVfU0hPVyQzKTtcblxuICAgICAgY29uc3QgY29tcGxldGVDYWxsQmFjayA9ICgpID0+IHtcbiAgICAgICAgaWYgKCF0aGlzLl9jb25maWcuc2Nyb2xsKSB7XG4gICAgICAgICAgdGhpcy5fZm9jdXN0cmFwLmFjdGl2YXRlKCk7XG4gICAgICAgIH1cblxuICAgICAgICBFdmVudEhhbmRsZXIudHJpZ2dlcih0aGlzLl9lbGVtZW50LCBFVkVOVF9TSE9XTiQyLCB7XG4gICAgICAgICAgcmVsYXRlZFRhcmdldFxuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIHRoaXMuX3F1ZXVlQ2FsbGJhY2soY29tcGxldGVDYWxsQmFjaywgdGhpcy5fZWxlbWVudCwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgaGlkZSgpIHtcbiAgICAgIGlmICghdGhpcy5faXNTaG93bikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGhpZGVFdmVudCA9IEV2ZW50SGFuZGxlci50cmlnZ2VyKHRoaXMuX2VsZW1lbnQsIEVWRU5UX0hJREUkMik7XG5cbiAgICAgIGlmIChoaWRlRXZlbnQuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2ZvY3VzdHJhcC5kZWFjdGl2YXRlKCk7XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQuYmx1cigpO1xuXG4gICAgICB0aGlzLl9pc1Nob3duID0gZmFsc2U7XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShDTEFTU19OQU1FX1NIT1ckMyk7XG5cbiAgICAgIHRoaXMuX2JhY2tkcm9wLmhpZGUoKTtcblxuICAgICAgY29uc3QgY29tcGxldGVDYWxsYmFjayA9ICgpID0+IHtcbiAgICAgICAgdGhpcy5fZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJywgdHJ1ZSk7XG5cbiAgICAgICAgdGhpcy5fZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoJ2FyaWEtbW9kYWwnKTtcblxuICAgICAgICB0aGlzLl9lbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgncm9sZScpO1xuXG4gICAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGUudmlzaWJpbGl0eSA9ICdoaWRkZW4nO1xuXG4gICAgICAgIGlmICghdGhpcy5fY29uZmlnLnNjcm9sbCkge1xuICAgICAgICAgIG5ldyBTY3JvbGxCYXJIZWxwZXIoKS5yZXNldCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgRXZlbnRIYW5kbGVyLnRyaWdnZXIodGhpcy5fZWxlbWVudCwgRVZFTlRfSElEREVOJDIpO1xuICAgICAgfTtcblxuICAgICAgdGhpcy5fcXVldWVDYWxsYmFjayhjb21wbGV0ZUNhbGxiYWNrLCB0aGlzLl9lbGVtZW50LCB0cnVlKTtcbiAgICB9XG5cbiAgICBkaXNwb3NlKCkge1xuICAgICAgdGhpcy5fYmFja2Ryb3AuZGlzcG9zZSgpO1xuXG4gICAgICB0aGlzLl9mb2N1c3RyYXAuZGVhY3RpdmF0ZSgpO1xuXG4gICAgICBzdXBlci5kaXNwb3NlKCk7XG4gICAgfSAvLyBQcml2YXRlXG5cblxuICAgIF9nZXRDb25maWcoY29uZmlnKSB7XG4gICAgICBjb25maWcgPSB7IC4uLkRlZmF1bHQkNCxcbiAgICAgICAgLi4uTWFuaXB1bGF0b3IuZ2V0RGF0YUF0dHJpYnV0ZXModGhpcy5fZWxlbWVudCksXG4gICAgICAgIC4uLih0eXBlb2YgY29uZmlnID09PSAnb2JqZWN0JyA/IGNvbmZpZyA6IHt9KVxuICAgICAgfTtcbiAgICAgIHR5cGVDaGVja0NvbmZpZyhOQU1FJDUsIGNvbmZpZywgRGVmYXVsdFR5cGUkNCk7XG4gICAgICByZXR1cm4gY29uZmlnO1xuICAgIH1cblxuICAgIF9pbml0aWFsaXplQmFja0Ryb3AoKSB7XG4gICAgICByZXR1cm4gbmV3IEJhY2tkcm9wKHtcbiAgICAgICAgY2xhc3NOYW1lOiBDTEFTU19OQU1FX0JBQ0tEUk9QLFxuICAgICAgICBpc1Zpc2libGU6IHRoaXMuX2NvbmZpZy5iYWNrZHJvcCxcbiAgICAgICAgaXNBbmltYXRlZDogdHJ1ZSxcbiAgICAgICAgcm9vdEVsZW1lbnQ6IHRoaXMuX2VsZW1lbnQucGFyZW50Tm9kZSxcbiAgICAgICAgY2xpY2tDYWxsYmFjazogKCkgPT4gdGhpcy5oaWRlKClcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIF9pbml0aWFsaXplRm9jdXNUcmFwKCkge1xuICAgICAgcmV0dXJuIG5ldyBGb2N1c1RyYXAoe1xuICAgICAgICB0cmFwRWxlbWVudDogdGhpcy5fZWxlbWVudFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgX2FkZEV2ZW50TGlzdGVuZXJzKCkge1xuICAgICAgRXZlbnRIYW5kbGVyLm9uKHRoaXMuX2VsZW1lbnQsIEVWRU5UX0tFWURPV05fRElTTUlTUywgZXZlbnQgPT4ge1xuICAgICAgICBpZiAodGhpcy5fY29uZmlnLmtleWJvYXJkICYmIGV2ZW50LmtleSA9PT0gRVNDQVBFX0tFWSkge1xuICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9IC8vIFN0YXRpY1xuXG5cbiAgICBzdGF0aWMgalF1ZXJ5SW50ZXJmYWNlKGNvbmZpZykge1xuICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBPZmZjYW52YXMuZ2V0T3JDcmVhdGVJbnN0YW5jZSh0aGlzLCBjb25maWcpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgY29uZmlnICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkYXRhW2NvbmZpZ10gPT09IHVuZGVmaW5lZCB8fCBjb25maWcuc3RhcnRzV2l0aCgnXycpIHx8IGNvbmZpZyA9PT0gJ2NvbnN0cnVjdG9yJykge1xuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYE5vIG1ldGhvZCBuYW1lZCBcIiR7Y29uZmlnfVwiYCk7XG4gICAgICAgIH1cblxuICAgICAgICBkYXRhW2NvbmZpZ10odGhpcyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgfVxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIERhdGEgQXBpIGltcGxlbWVudGF0aW9uXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuXG4gIEV2ZW50SGFuZGxlci5vbihkb2N1bWVudCwgRVZFTlRfQ0xJQ0tfREFUQV9BUEkkMSwgU0VMRUNUT1JfREFUQV9UT0dHTEUkMSwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgY29uc3QgdGFyZ2V0ID0gZ2V0RWxlbWVudEZyb21TZWxlY3Rvcih0aGlzKTtcblxuICAgIGlmIChbJ0EnLCAnQVJFQSddLmluY2x1ZGVzKHRoaXMudGFnTmFtZSkpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuXG4gICAgaWYgKGlzRGlzYWJsZWQodGhpcykpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBFdmVudEhhbmRsZXIub25lKHRhcmdldCwgRVZFTlRfSElEREVOJDIsICgpID0+IHtcbiAgICAgIC8vIGZvY3VzIG9uIHRyaWdnZXIgd2hlbiBpdCBpcyBjbG9zZWRcbiAgICAgIGlmIChpc1Zpc2libGUodGhpcykpIHtcbiAgICAgICAgdGhpcy5mb2N1cygpO1xuICAgICAgfVxuICAgIH0pOyAvLyBhdm9pZCBjb25mbGljdCB3aGVuIGNsaWNraW5nIGEgdG9nZ2xlciBvZiBhbiBvZmZjYW52YXMsIHdoaWxlIGFub3RoZXIgaXMgb3BlblxuXG4gICAgY29uc3QgYWxsUmVhZHlPcGVuID0gU2VsZWN0b3JFbmdpbmUuZmluZE9uZShPUEVOX1NFTEVDVE9SKTtcblxuICAgIGlmIChhbGxSZWFkeU9wZW4gJiYgYWxsUmVhZHlPcGVuICE9PSB0YXJnZXQpIHtcbiAgICAgIE9mZmNhbnZhcy5nZXRJbnN0YW5jZShhbGxSZWFkeU9wZW4pLmhpZGUoKTtcbiAgICB9XG5cbiAgICBjb25zdCBkYXRhID0gT2ZmY2FudmFzLmdldE9yQ3JlYXRlSW5zdGFuY2UodGFyZ2V0KTtcbiAgICBkYXRhLnRvZ2dsZSh0aGlzKTtcbiAgfSk7XG4gIEV2ZW50SGFuZGxlci5vbih3aW5kb3csIEVWRU5UX0xPQURfREFUQV9BUEkkMSwgKCkgPT4gU2VsZWN0b3JFbmdpbmUuZmluZChPUEVOX1NFTEVDVE9SKS5mb3JFYWNoKGVsID0+IE9mZmNhbnZhcy5nZXRPckNyZWF0ZUluc3RhbmNlKGVsKS5zaG93KCkpKTtcbiAgZW5hYmxlRGlzbWlzc1RyaWdnZXIoT2ZmY2FudmFzKTtcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBqUXVlcnlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIGRlZmluZUpRdWVyeVBsdWdpbihPZmZjYW52YXMpO1xuXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBCb290c3RyYXAgKHY1LjEuMyk6IHV0aWwvc2FuaXRpemVyLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cbiAgY29uc3QgdXJpQXR0cmlidXRlcyA9IG5ldyBTZXQoWydiYWNrZ3JvdW5kJywgJ2NpdGUnLCAnaHJlZicsICdpdGVtdHlwZScsICdsb25nZGVzYycsICdwb3N0ZXInLCAnc3JjJywgJ3hsaW5rOmhyZWYnXSk7XG4gIGNvbnN0IEFSSUFfQVRUUklCVVRFX1BBVFRFUk4gPSAvXmFyaWEtW1xcdy1dKiQvaTtcbiAgLyoqXG4gICAqIEEgcGF0dGVybiB0aGF0IHJlY29nbml6ZXMgYSBjb21tb25seSB1c2VmdWwgc3Vic2V0IG9mIFVSTHMgdGhhdCBhcmUgc2FmZS5cbiAgICpcbiAgICogU2hvdXRvdXQgdG8gQW5ndWxhciBodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9hbmd1bGFyL2Jsb2IvMTIuMi54L3BhY2thZ2VzL2NvcmUvc3JjL3Nhbml0aXphdGlvbi91cmxfc2FuaXRpemVyLnRzXG4gICAqL1xuXG4gIGNvbnN0IFNBRkVfVVJMX1BBVFRFUk4gPSAvXig/Oig/Omh0dHBzP3xtYWlsdG98ZnRwfHRlbHxmaWxlfHNtcyk6fFteIyYvOj9dKig/OlsjLz9dfCQpKS9pO1xuICAvKipcbiAgICogQSBwYXR0ZXJuIHRoYXQgbWF0Y2hlcyBzYWZlIGRhdGEgVVJMcy4gT25seSBtYXRjaGVzIGltYWdlLCB2aWRlbyBhbmQgYXVkaW8gdHlwZXMuXG4gICAqXG4gICAqIFNob3V0b3V0IHRvIEFuZ3VsYXIgaHR0cHM6Ly9naXRodWIuY29tL2FuZ3VsYXIvYW5ndWxhci9ibG9iLzEyLjIueC9wYWNrYWdlcy9jb3JlL3NyYy9zYW5pdGl6YXRpb24vdXJsX3Nhbml0aXplci50c1xuICAgKi9cblxuICBjb25zdCBEQVRBX1VSTF9QQVRURVJOID0gL15kYXRhOig/OmltYWdlXFwvKD86Ym1wfGdpZnxqcGVnfGpwZ3xwbmd8dGlmZnx3ZWJwKXx2aWRlb1xcLyg/Om1wZWd8bXA0fG9nZ3x3ZWJtKXxhdWRpb1xcLyg/Om1wM3xvZ2F8b2dnfG9wdXMpKTtiYXNlNjQsW1xcZCsvYS16XSs9KiQvaTtcblxuICBjb25zdCBhbGxvd2VkQXR0cmlidXRlID0gKGF0dHJpYnV0ZSwgYWxsb3dlZEF0dHJpYnV0ZUxpc3QpID0+IHtcbiAgICBjb25zdCBhdHRyaWJ1dGVOYW1lID0gYXR0cmlidXRlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7XG5cbiAgICBpZiAoYWxsb3dlZEF0dHJpYnV0ZUxpc3QuaW5jbHVkZXMoYXR0cmlidXRlTmFtZSkpIHtcbiAgICAgIGlmICh1cmlBdHRyaWJ1dGVzLmhhcyhhdHRyaWJ1dGVOYW1lKSkge1xuICAgICAgICByZXR1cm4gQm9vbGVhbihTQUZFX1VSTF9QQVRURVJOLnRlc3QoYXR0cmlidXRlLm5vZGVWYWx1ZSkgfHwgREFUQV9VUkxfUEFUVEVSTi50ZXN0KGF0dHJpYnV0ZS5ub2RlVmFsdWUpKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgY29uc3QgcmVnRXhwID0gYWxsb3dlZEF0dHJpYnV0ZUxpc3QuZmlsdGVyKGF0dHJpYnV0ZVJlZ2V4ID0+IGF0dHJpYnV0ZVJlZ2V4IGluc3RhbmNlb2YgUmVnRXhwKTsgLy8gQ2hlY2sgaWYgYSByZWd1bGFyIGV4cHJlc3Npb24gdmFsaWRhdGVzIHRoZSBhdHRyaWJ1dGUuXG5cbiAgICBmb3IgKGxldCBpID0gMCwgbGVuID0gcmVnRXhwLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBpZiAocmVnRXhwW2ldLnRlc3QoYXR0cmlidXRlTmFtZSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xuXG4gIGNvbnN0IERlZmF1bHRBbGxvd2xpc3QgPSB7XG4gICAgLy8gR2xvYmFsIGF0dHJpYnV0ZXMgYWxsb3dlZCBvbiBhbnkgc3VwcGxpZWQgZWxlbWVudCBiZWxvdy5cbiAgICAnKic6IFsnY2xhc3MnLCAnZGlyJywgJ2lkJywgJ2xhbmcnLCAncm9sZScsIEFSSUFfQVRUUklCVVRFX1BBVFRFUk5dLFxuICAgIGE6IFsndGFyZ2V0JywgJ2hyZWYnLCAndGl0bGUnLCAncmVsJ10sXG4gICAgYXJlYTogW10sXG4gICAgYjogW10sXG4gICAgYnI6IFtdLFxuICAgIGNvbDogW10sXG4gICAgY29kZTogW10sXG4gICAgZGl2OiBbXSxcbiAgICBlbTogW10sXG4gICAgaHI6IFtdLFxuICAgIGgxOiBbXSxcbiAgICBoMjogW10sXG4gICAgaDM6IFtdLFxuICAgIGg0OiBbXSxcbiAgICBoNTogW10sXG4gICAgaDY6IFtdLFxuICAgIGk6IFtdLFxuICAgIGltZzogWydzcmMnLCAnc3Jjc2V0JywgJ2FsdCcsICd0aXRsZScsICd3aWR0aCcsICdoZWlnaHQnXSxcbiAgICBsaTogW10sXG4gICAgb2w6IFtdLFxuICAgIHA6IFtdLFxuICAgIHByZTogW10sXG4gICAgczogW10sXG4gICAgc21hbGw6IFtdLFxuICAgIHNwYW46IFtdLFxuICAgIHN1YjogW10sXG4gICAgc3VwOiBbXSxcbiAgICBzdHJvbmc6IFtdLFxuICAgIHU6IFtdLFxuICAgIHVsOiBbXVxuICB9O1xuICBmdW5jdGlvbiBzYW5pdGl6ZUh0bWwodW5zYWZlSHRtbCwgYWxsb3dMaXN0LCBzYW5pdGl6ZUZuKSB7XG4gICAgaWYgKCF1bnNhZmVIdG1sLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHVuc2FmZUh0bWw7XG4gICAgfVxuXG4gICAgaWYgKHNhbml0aXplRm4gJiYgdHlwZW9mIHNhbml0aXplRm4gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiBzYW5pdGl6ZUZuKHVuc2FmZUh0bWwpO1xuICAgIH1cblxuICAgIGNvbnN0IGRvbVBhcnNlciA9IG5ldyB3aW5kb3cuRE9NUGFyc2VyKCk7XG4gICAgY29uc3QgY3JlYXRlZERvY3VtZW50ID0gZG9tUGFyc2VyLnBhcnNlRnJvbVN0cmluZyh1bnNhZmVIdG1sLCAndGV4dC9odG1sJyk7XG4gICAgY29uc3QgZWxlbWVudHMgPSBbXS5jb25jYXQoLi4uY3JlYXRlZERvY3VtZW50LmJvZHkucXVlcnlTZWxlY3RvckFsbCgnKicpKTtcblxuICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSBlbGVtZW50cy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgY29uc3QgZWxlbWVudCA9IGVsZW1lbnRzW2ldO1xuICAgICAgY29uc3QgZWxlbWVudE5hbWUgPSBlbGVtZW50Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAgIGlmICghT2JqZWN0LmtleXMoYWxsb3dMaXN0KS5pbmNsdWRlcyhlbGVtZW50TmFtZSkpIHtcbiAgICAgICAgZWxlbWVudC5yZW1vdmUoKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGF0dHJpYnV0ZUxpc3QgPSBbXS5jb25jYXQoLi4uZWxlbWVudC5hdHRyaWJ1dGVzKTtcbiAgICAgIGNvbnN0IGFsbG93ZWRBdHRyaWJ1dGVzID0gW10uY29uY2F0KGFsbG93TGlzdFsnKiddIHx8IFtdLCBhbGxvd0xpc3RbZWxlbWVudE5hbWVdIHx8IFtdKTtcbiAgICAgIGF0dHJpYnV0ZUxpc3QuZm9yRWFjaChhdHRyaWJ1dGUgPT4ge1xuICAgICAgICBpZiAoIWFsbG93ZWRBdHRyaWJ1dGUoYXR0cmlidXRlLCBhbGxvd2VkQXR0cmlidXRlcykpIHtcbiAgICAgICAgICBlbGVtZW50LnJlbW92ZUF0dHJpYnV0ZShhdHRyaWJ1dGUubm9kZU5hbWUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gY3JlYXRlZERvY3VtZW50LmJvZHkuaW5uZXJIVE1MO1xuICB9XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjUuMS4zKTogdG9vbHRpcC5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQ29uc3RhbnRzXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICBjb25zdCBOQU1FJDQgPSAndG9vbHRpcCc7XG4gIGNvbnN0IERBVEFfS0VZJDQgPSAnYnMudG9vbHRpcCc7XG4gIGNvbnN0IEVWRU5UX0tFWSQ0ID0gYC4ke0RBVEFfS0VZJDR9YDtcbiAgY29uc3QgQ0xBU1NfUFJFRklYJDEgPSAnYnMtdG9vbHRpcCc7XG4gIGNvbnN0IERJU0FMTE9XRURfQVRUUklCVVRFUyA9IG5ldyBTZXQoWydzYW5pdGl6ZScsICdhbGxvd0xpc3QnLCAnc2FuaXRpemVGbiddKTtcbiAgY29uc3QgRGVmYXVsdFR5cGUkMyA9IHtcbiAgICBhbmltYXRpb246ICdib29sZWFuJyxcbiAgICB0ZW1wbGF0ZTogJ3N0cmluZycsXG4gICAgdGl0bGU6ICcoc3RyaW5nfGVsZW1lbnR8ZnVuY3Rpb24pJyxcbiAgICB0cmlnZ2VyOiAnc3RyaW5nJyxcbiAgICBkZWxheTogJyhudW1iZXJ8b2JqZWN0KScsXG4gICAgaHRtbDogJ2Jvb2xlYW4nLFxuICAgIHNlbGVjdG9yOiAnKHN0cmluZ3xib29sZWFuKScsXG4gICAgcGxhY2VtZW50OiAnKHN0cmluZ3xmdW5jdGlvbiknLFxuICAgIG9mZnNldDogJyhhcnJheXxzdHJpbmd8ZnVuY3Rpb24pJyxcbiAgICBjb250YWluZXI6ICcoc3RyaW5nfGVsZW1lbnR8Ym9vbGVhbiknLFxuICAgIGZhbGxiYWNrUGxhY2VtZW50czogJ2FycmF5JyxcbiAgICBib3VuZGFyeTogJyhzdHJpbmd8ZWxlbWVudCknLFxuICAgIGN1c3RvbUNsYXNzOiAnKHN0cmluZ3xmdW5jdGlvbiknLFxuICAgIHNhbml0aXplOiAnYm9vbGVhbicsXG4gICAgc2FuaXRpemVGbjogJyhudWxsfGZ1bmN0aW9uKScsXG4gICAgYWxsb3dMaXN0OiAnb2JqZWN0JyxcbiAgICBwb3BwZXJDb25maWc6ICcobnVsbHxvYmplY3R8ZnVuY3Rpb24pJ1xuICB9O1xuICBjb25zdCBBdHRhY2htZW50TWFwID0ge1xuICAgIEFVVE86ICdhdXRvJyxcbiAgICBUT1A6ICd0b3AnLFxuICAgIFJJR0hUOiBpc1JUTCgpID8gJ2xlZnQnIDogJ3JpZ2h0JyxcbiAgICBCT1RUT006ICdib3R0b20nLFxuICAgIExFRlQ6IGlzUlRMKCkgPyAncmlnaHQnIDogJ2xlZnQnXG4gIH07XG4gIGNvbnN0IERlZmF1bHQkMyA9IHtcbiAgICBhbmltYXRpb246IHRydWUsXG4gICAgdGVtcGxhdGU6ICc8ZGl2IGNsYXNzPVwidG9vbHRpcFwiIHJvbGU9XCJ0b29sdGlwXCI+JyArICc8ZGl2IGNsYXNzPVwidG9vbHRpcC1hcnJvd1wiPjwvZGl2PicgKyAnPGRpdiBjbGFzcz1cInRvb2x0aXAtaW5uZXJcIj48L2Rpdj4nICsgJzwvZGl2PicsXG4gICAgdHJpZ2dlcjogJ2hvdmVyIGZvY3VzJyxcbiAgICB0aXRsZTogJycsXG4gICAgZGVsYXk6IDAsXG4gICAgaHRtbDogZmFsc2UsXG4gICAgc2VsZWN0b3I6IGZhbHNlLFxuICAgIHBsYWNlbWVudDogJ3RvcCcsXG4gICAgb2Zmc2V0OiBbMCwgMF0sXG4gICAgY29udGFpbmVyOiBmYWxzZSxcbiAgICBmYWxsYmFja1BsYWNlbWVudHM6IFsndG9wJywgJ3JpZ2h0JywgJ2JvdHRvbScsICdsZWZ0J10sXG4gICAgYm91bmRhcnk6ICdjbGlwcGluZ1BhcmVudHMnLFxuICAgIGN1c3RvbUNsYXNzOiAnJyxcbiAgICBzYW5pdGl6ZTogdHJ1ZSxcbiAgICBzYW5pdGl6ZUZuOiBudWxsLFxuICAgIGFsbG93TGlzdDogRGVmYXVsdEFsbG93bGlzdCxcbiAgICBwb3BwZXJDb25maWc6IG51bGxcbiAgfTtcbiAgY29uc3QgRXZlbnQkMiA9IHtcbiAgICBISURFOiBgaGlkZSR7RVZFTlRfS0VZJDR9YCxcbiAgICBISURERU46IGBoaWRkZW4ke0VWRU5UX0tFWSQ0fWAsXG4gICAgU0hPVzogYHNob3cke0VWRU5UX0tFWSQ0fWAsXG4gICAgU0hPV046IGBzaG93biR7RVZFTlRfS0VZJDR9YCxcbiAgICBJTlNFUlRFRDogYGluc2VydGVkJHtFVkVOVF9LRVkkNH1gLFxuICAgIENMSUNLOiBgY2xpY2ske0VWRU5UX0tFWSQ0fWAsXG4gICAgRk9DVVNJTjogYGZvY3VzaW4ke0VWRU5UX0tFWSQ0fWAsXG4gICAgRk9DVVNPVVQ6IGBmb2N1c291dCR7RVZFTlRfS0VZJDR9YCxcbiAgICBNT1VTRUVOVEVSOiBgbW91c2VlbnRlciR7RVZFTlRfS0VZJDR9YCxcbiAgICBNT1VTRUxFQVZFOiBgbW91c2VsZWF2ZSR7RVZFTlRfS0VZJDR9YFxuICB9O1xuICBjb25zdCBDTEFTU19OQU1FX0ZBREUkMiA9ICdmYWRlJztcbiAgY29uc3QgQ0xBU1NfTkFNRV9NT0RBTCA9ICdtb2RhbCc7XG4gIGNvbnN0IENMQVNTX05BTUVfU0hPVyQyID0gJ3Nob3cnO1xuICBjb25zdCBIT1ZFUl9TVEFURV9TSE9XID0gJ3Nob3cnO1xuICBjb25zdCBIT1ZFUl9TVEFURV9PVVQgPSAnb3V0JztcbiAgY29uc3QgU0VMRUNUT1JfVE9PTFRJUF9JTk5FUiA9ICcudG9vbHRpcC1pbm5lcic7XG4gIGNvbnN0IFNFTEVDVE9SX01PREFMID0gYC4ke0NMQVNTX05BTUVfTU9EQUx9YDtcbiAgY29uc3QgRVZFTlRfTU9EQUxfSElERSA9ICdoaWRlLmJzLm1vZGFsJztcbiAgY29uc3QgVFJJR0dFUl9IT1ZFUiA9ICdob3Zlcic7XG4gIGNvbnN0IFRSSUdHRVJfRk9DVVMgPSAnZm9jdXMnO1xuICBjb25zdCBUUklHR0VSX0NMSUNLID0gJ2NsaWNrJztcbiAgY29uc3QgVFJJR0dFUl9NQU5VQUwgPSAnbWFudWFsJztcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICBjbGFzcyBUb29sdGlwIGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoZWxlbWVudCwgY29uZmlnKSB7XG4gICAgICBpZiAodHlwZW9mIFBvcHBlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQm9vdHN0cmFwXFwncyB0b29sdGlwcyByZXF1aXJlIFBvcHBlciAoaHR0cHM6Ly9wb3BwZXIuanMub3JnKScpO1xuICAgICAgfVxuXG4gICAgICBzdXBlcihlbGVtZW50KTsgLy8gcHJpdmF0ZVxuXG4gICAgICB0aGlzLl9pc0VuYWJsZWQgPSB0cnVlO1xuICAgICAgdGhpcy5fdGltZW91dCA9IDA7XG4gICAgICB0aGlzLl9ob3ZlclN0YXRlID0gJyc7XG4gICAgICB0aGlzLl9hY3RpdmVUcmlnZ2VyID0ge307XG4gICAgICB0aGlzLl9wb3BwZXIgPSBudWxsOyAvLyBQcm90ZWN0ZWRcblxuICAgICAgdGhpcy5fY29uZmlnID0gdGhpcy5fZ2V0Q29uZmlnKGNvbmZpZyk7XG4gICAgICB0aGlzLnRpcCA9IG51bGw7XG5cbiAgICAgIHRoaXMuX3NldExpc3RlbmVycygpO1xuICAgIH0gLy8gR2V0dGVyc1xuXG5cbiAgICBzdGF0aWMgZ2V0IERlZmF1bHQoKSB7XG4gICAgICByZXR1cm4gRGVmYXVsdCQzO1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXQgTkFNRSgpIHtcbiAgICAgIHJldHVybiBOQU1FJDQ7XG4gICAgfVxuXG4gICAgc3RhdGljIGdldCBFdmVudCgpIHtcbiAgICAgIHJldHVybiBFdmVudCQyO1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXQgRGVmYXVsdFR5cGUoKSB7XG4gICAgICByZXR1cm4gRGVmYXVsdFR5cGUkMztcbiAgICB9IC8vIFB1YmxpY1xuXG5cbiAgICBlbmFibGUoKSB7XG4gICAgICB0aGlzLl9pc0VuYWJsZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGRpc2FibGUoKSB7XG4gICAgICB0aGlzLl9pc0VuYWJsZWQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICB0b2dnbGVFbmFibGVkKCkge1xuICAgICAgdGhpcy5faXNFbmFibGVkID0gIXRoaXMuX2lzRW5hYmxlZDtcbiAgICB9XG5cbiAgICB0b2dnbGUoZXZlbnQpIHtcbiAgICAgIGlmICghdGhpcy5faXNFbmFibGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLl9pbml0aWFsaXplT25EZWxlZ2F0ZWRUYXJnZXQoZXZlbnQpO1xuXG4gICAgICAgIGNvbnRleHQuX2FjdGl2ZVRyaWdnZXIuY2xpY2sgPSAhY29udGV4dC5fYWN0aXZlVHJpZ2dlci5jbGljaztcblxuICAgICAgICBpZiAoY29udGV4dC5faXNXaXRoQWN0aXZlVHJpZ2dlcigpKSB7XG4gICAgICAgICAgY29udGV4dC5fZW50ZXIobnVsbCwgY29udGV4dCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29udGV4dC5fbGVhdmUobnVsbCwgY29udGV4dCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICh0aGlzLmdldFRpcEVsZW1lbnQoKS5jbGFzc0xpc3QuY29udGFpbnMoQ0xBU1NfTkFNRV9TSE9XJDIpKSB7XG4gICAgICAgICAgdGhpcy5fbGVhdmUobnVsbCwgdGhpcyk7XG5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9lbnRlcihudWxsLCB0aGlzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBkaXNwb3NlKCkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuX3RpbWVvdXQpO1xuICAgICAgRXZlbnRIYW5kbGVyLm9mZih0aGlzLl9lbGVtZW50LmNsb3Nlc3QoU0VMRUNUT1JfTU9EQUwpLCBFVkVOVF9NT0RBTF9ISURFLCB0aGlzLl9oaWRlTW9kYWxIYW5kbGVyKTtcblxuICAgICAgaWYgKHRoaXMudGlwKSB7XG4gICAgICAgIHRoaXMudGlwLnJlbW92ZSgpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9kaXNwb3NlUG9wcGVyKCk7XG5cbiAgICAgIHN1cGVyLmRpc3Bvc2UoKTtcbiAgICB9XG5cbiAgICBzaG93KCkge1xuICAgICAgaWYgKHRoaXMuX2VsZW1lbnQuc3R5bGUuZGlzcGxheSA9PT0gJ25vbmUnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignUGxlYXNlIHVzZSBzaG93IG9uIHZpc2libGUgZWxlbWVudHMnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCEodGhpcy5pc1dpdGhDb250ZW50KCkgJiYgdGhpcy5faXNFbmFibGVkKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNob3dFdmVudCA9IEV2ZW50SGFuZGxlci50cmlnZ2VyKHRoaXMuX2VsZW1lbnQsIHRoaXMuY29uc3RydWN0b3IuRXZlbnQuU0hPVyk7XG4gICAgICBjb25zdCBzaGFkb3dSb290ID0gZmluZFNoYWRvd1Jvb3QodGhpcy5fZWxlbWVudCk7XG4gICAgICBjb25zdCBpc0luVGhlRG9tID0gc2hhZG93Um9vdCA9PT0gbnVsbCA/IHRoaXMuX2VsZW1lbnQub3duZXJEb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY29udGFpbnModGhpcy5fZWxlbWVudCkgOiBzaGFkb3dSb290LmNvbnRhaW5zKHRoaXMuX2VsZW1lbnQpO1xuXG4gICAgICBpZiAoc2hvd0V2ZW50LmRlZmF1bHRQcmV2ZW50ZWQgfHwgIWlzSW5UaGVEb20pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSAvLyBBIHRyaWNrIHRvIHJlY3JlYXRlIGEgdG9vbHRpcCBpbiBjYXNlIGEgbmV3IHRpdGxlIGlzIGdpdmVuIGJ5IHVzaW5nIHRoZSBOT1QgZG9jdW1lbnRlZCBgZGF0YS1icy1vcmlnaW5hbC10aXRsZWBcbiAgICAgIC8vIFRoaXMgd2lsbCBiZSByZW1vdmVkIGxhdGVyIGluIGZhdm9yIG9mIGEgYHNldENvbnRlbnRgIG1ldGhvZFxuXG5cbiAgICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yLk5BTUUgPT09ICd0b29sdGlwJyAmJiB0aGlzLnRpcCAmJiB0aGlzLmdldFRpdGxlKCkgIT09IHRoaXMudGlwLnF1ZXJ5U2VsZWN0b3IoU0VMRUNUT1JfVE9PTFRJUF9JTk5FUikuaW5uZXJIVE1MKSB7XG4gICAgICAgIHRoaXMuX2Rpc3Bvc2VQb3BwZXIoKTtcblxuICAgICAgICB0aGlzLnRpcC5yZW1vdmUoKTtcbiAgICAgICAgdGhpcy50aXAgPSBudWxsO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB0aXAgPSB0aGlzLmdldFRpcEVsZW1lbnQoKTtcbiAgICAgIGNvbnN0IHRpcElkID0gZ2V0VUlEKHRoaXMuY29uc3RydWN0b3IuTkFNRSk7XG4gICAgICB0aXAuc2V0QXR0cmlidXRlKCdpZCcsIHRpcElkKTtcblxuICAgICAgdGhpcy5fZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2FyaWEtZGVzY3JpYmVkYnknLCB0aXBJZCk7XG5cbiAgICAgIGlmICh0aGlzLl9jb25maWcuYW5pbWF0aW9uKSB7XG4gICAgICAgIHRpcC5jbGFzc0xpc3QuYWRkKENMQVNTX05BTUVfRkFERSQyKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcGxhY2VtZW50ID0gdHlwZW9mIHRoaXMuX2NvbmZpZy5wbGFjZW1lbnQgPT09ICdmdW5jdGlvbicgPyB0aGlzLl9jb25maWcucGxhY2VtZW50LmNhbGwodGhpcywgdGlwLCB0aGlzLl9lbGVtZW50KSA6IHRoaXMuX2NvbmZpZy5wbGFjZW1lbnQ7XG5cbiAgICAgIGNvbnN0IGF0dGFjaG1lbnQgPSB0aGlzLl9nZXRBdHRhY2htZW50KHBsYWNlbWVudCk7XG5cbiAgICAgIHRoaXMuX2FkZEF0dGFjaG1lbnRDbGFzcyhhdHRhY2htZW50KTtcblxuICAgICAgY29uc3Qge1xuICAgICAgICBjb250YWluZXJcbiAgICAgIH0gPSB0aGlzLl9jb25maWc7XG4gICAgICBEYXRhLnNldCh0aXAsIHRoaXMuY29uc3RydWN0b3IuREFUQV9LRVksIHRoaXMpO1xuXG4gICAgICBpZiAoIXRoaXMuX2VsZW1lbnQub3duZXJEb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY29udGFpbnModGhpcy50aXApKSB7XG4gICAgICAgIGNvbnRhaW5lci5hcHBlbmQodGlwKTtcbiAgICAgICAgRXZlbnRIYW5kbGVyLnRyaWdnZXIodGhpcy5fZWxlbWVudCwgdGhpcy5jb25zdHJ1Y3Rvci5FdmVudC5JTlNFUlRFRCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9wb3BwZXIpIHtcbiAgICAgICAgdGhpcy5fcG9wcGVyLnVwZGF0ZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fcG9wcGVyID0gY3JlYXRlUG9wcGVyKHRoaXMuX2VsZW1lbnQsIHRpcCwgdGhpcy5fZ2V0UG9wcGVyQ29uZmlnKGF0dGFjaG1lbnQpKTtcbiAgICAgIH1cblxuICAgICAgdGlwLmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9TSE9XJDIpO1xuXG4gICAgICBjb25zdCBjdXN0b21DbGFzcyA9IHRoaXMuX3Jlc29sdmVQb3NzaWJsZUZ1bmN0aW9uKHRoaXMuX2NvbmZpZy5jdXN0b21DbGFzcyk7XG5cbiAgICAgIGlmIChjdXN0b21DbGFzcykge1xuICAgICAgICB0aXAuY2xhc3NMaXN0LmFkZCguLi5jdXN0b21DbGFzcy5zcGxpdCgnICcpKTtcbiAgICAgIH0gLy8gSWYgdGhpcyBpcyBhIHRvdWNoLWVuYWJsZWQgZGV2aWNlIHdlIGFkZCBleHRyYVxuICAgICAgLy8gZW1wdHkgbW91c2VvdmVyIGxpc3RlbmVycyB0byB0aGUgYm9keSdzIGltbWVkaWF0ZSBjaGlsZHJlbjtcbiAgICAgIC8vIG9ubHkgbmVlZGVkIGJlY2F1c2Ugb2YgYnJva2VuIGV2ZW50IGRlbGVnYXRpb24gb24gaU9TXG4gICAgICAvLyBodHRwczovL3d3dy5xdWlya3Ntb2RlLm9yZy9ibG9nL2FyY2hpdmVzLzIwMTQvMDIvbW91c2VfZXZlbnRfYnViLmh0bWxcblxuXG4gICAgICBpZiAoJ29udG91Y2hzdGFydCcgaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSB7XG4gICAgICAgIFtdLmNvbmNhdCguLi5kb2N1bWVudC5ib2R5LmNoaWxkcmVuKS5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgIEV2ZW50SGFuZGxlci5vbihlbGVtZW50LCAnbW91c2VvdmVyJywgbm9vcCk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjb21wbGV0ZSA9ICgpID0+IHtcbiAgICAgICAgY29uc3QgcHJldkhvdmVyU3RhdGUgPSB0aGlzLl9ob3ZlclN0YXRlO1xuICAgICAgICB0aGlzLl9ob3ZlclN0YXRlID0gbnVsbDtcbiAgICAgICAgRXZlbnRIYW5kbGVyLnRyaWdnZXIodGhpcy5fZWxlbWVudCwgdGhpcy5jb25zdHJ1Y3Rvci5FdmVudC5TSE9XTik7XG5cbiAgICAgICAgaWYgKHByZXZIb3ZlclN0YXRlID09PSBIT1ZFUl9TVEFURV9PVVQpIHtcbiAgICAgICAgICB0aGlzLl9sZWF2ZShudWxsLCB0aGlzKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgY29uc3QgaXNBbmltYXRlZCA9IHRoaXMudGlwLmNsYXNzTGlzdC5jb250YWlucyhDTEFTU19OQU1FX0ZBREUkMik7XG5cbiAgICAgIHRoaXMuX3F1ZXVlQ2FsbGJhY2soY29tcGxldGUsIHRoaXMudGlwLCBpc0FuaW1hdGVkKTtcbiAgICB9XG5cbiAgICBoaWRlKCkge1xuICAgICAgaWYgKCF0aGlzLl9wb3BwZXIpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB0aXAgPSB0aGlzLmdldFRpcEVsZW1lbnQoKTtcblxuICAgICAgY29uc3QgY29tcGxldGUgPSAoKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLl9pc1dpdGhBY3RpdmVUcmlnZ2VyKCkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5faG92ZXJTdGF0ZSAhPT0gSE9WRVJfU1RBVEVfU0hPVykge1xuICAgICAgICAgIHRpcC5yZW1vdmUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2NsZWFuVGlwQ2xhc3MoKTtcblxuICAgICAgICB0aGlzLl9lbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1kZXNjcmliZWRieScpO1xuXG4gICAgICAgIEV2ZW50SGFuZGxlci50cmlnZ2VyKHRoaXMuX2VsZW1lbnQsIHRoaXMuY29uc3RydWN0b3IuRXZlbnQuSElEREVOKTtcblxuICAgICAgICB0aGlzLl9kaXNwb3NlUG9wcGVyKCk7XG4gICAgICB9O1xuXG4gICAgICBjb25zdCBoaWRlRXZlbnQgPSBFdmVudEhhbmRsZXIudHJpZ2dlcih0aGlzLl9lbGVtZW50LCB0aGlzLmNvbnN0cnVjdG9yLkV2ZW50LkhJREUpO1xuXG4gICAgICBpZiAoaGlkZUV2ZW50LmRlZmF1bHRQcmV2ZW50ZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aXAuY2xhc3NMaXN0LnJlbW92ZShDTEFTU19OQU1FX1NIT1ckMik7IC8vIElmIHRoaXMgaXMgYSB0b3VjaC1lbmFibGVkIGRldmljZSB3ZSByZW1vdmUgdGhlIGV4dHJhXG4gICAgICAvLyBlbXB0eSBtb3VzZW92ZXIgbGlzdGVuZXJzIHdlIGFkZGVkIGZvciBpT1Mgc3VwcG9ydFxuXG4gICAgICBpZiAoJ29udG91Y2hzdGFydCcgaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSB7XG4gICAgICAgIFtdLmNvbmNhdCguLi5kb2N1bWVudC5ib2R5LmNoaWxkcmVuKS5mb3JFYWNoKGVsZW1lbnQgPT4gRXZlbnRIYW5kbGVyLm9mZihlbGVtZW50LCAnbW91c2VvdmVyJywgbm9vcCkpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9hY3RpdmVUcmlnZ2VyW1RSSUdHRVJfQ0xJQ0tdID0gZmFsc2U7XG4gICAgICB0aGlzLl9hY3RpdmVUcmlnZ2VyW1RSSUdHRVJfRk9DVVNdID0gZmFsc2U7XG4gICAgICB0aGlzLl9hY3RpdmVUcmlnZ2VyW1RSSUdHRVJfSE9WRVJdID0gZmFsc2U7XG4gICAgICBjb25zdCBpc0FuaW1hdGVkID0gdGhpcy50aXAuY2xhc3NMaXN0LmNvbnRhaW5zKENMQVNTX05BTUVfRkFERSQyKTtcblxuICAgICAgdGhpcy5fcXVldWVDYWxsYmFjayhjb21wbGV0ZSwgdGhpcy50aXAsIGlzQW5pbWF0ZWQpO1xuXG4gICAgICB0aGlzLl9ob3ZlclN0YXRlID0gJyc7XG4gICAgfVxuXG4gICAgdXBkYXRlKCkge1xuICAgICAgaWYgKHRoaXMuX3BvcHBlciAhPT0gbnVsbCkge1xuICAgICAgICB0aGlzLl9wb3BwZXIudXBkYXRlKCk7XG4gICAgICB9XG4gICAgfSAvLyBQcm90ZWN0ZWRcblxuXG4gICAgaXNXaXRoQ29udGVudCgpIHtcbiAgICAgIHJldHVybiBCb29sZWFuKHRoaXMuZ2V0VGl0bGUoKSk7XG4gICAgfVxuXG4gICAgZ2V0VGlwRWxlbWVudCgpIHtcbiAgICAgIGlmICh0aGlzLnRpcCkge1xuICAgICAgICByZXR1cm4gdGhpcy50aXA7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gdGhpcy5fY29uZmlnLnRlbXBsYXRlO1xuICAgICAgY29uc3QgdGlwID0gZWxlbWVudC5jaGlsZHJlblswXTtcbiAgICAgIHRoaXMuc2V0Q29udGVudCh0aXApO1xuICAgICAgdGlwLmNsYXNzTGlzdC5yZW1vdmUoQ0xBU1NfTkFNRV9GQURFJDIsIENMQVNTX05BTUVfU0hPVyQyKTtcbiAgICAgIHRoaXMudGlwID0gdGlwO1xuICAgICAgcmV0dXJuIHRoaXMudGlwO1xuICAgIH1cblxuICAgIHNldENvbnRlbnQodGlwKSB7XG4gICAgICB0aGlzLl9zYW5pdGl6ZUFuZFNldENvbnRlbnQodGlwLCB0aGlzLmdldFRpdGxlKCksIFNFTEVDVE9SX1RPT0xUSVBfSU5ORVIpO1xuICAgIH1cblxuICAgIF9zYW5pdGl6ZUFuZFNldENvbnRlbnQodGVtcGxhdGUsIGNvbnRlbnQsIHNlbGVjdG9yKSB7XG4gICAgICBjb25zdCB0ZW1wbGF0ZUVsZW1lbnQgPSBTZWxlY3RvckVuZ2luZS5maW5kT25lKHNlbGVjdG9yLCB0ZW1wbGF0ZSk7XG5cbiAgICAgIGlmICghY29udGVudCAmJiB0ZW1wbGF0ZUVsZW1lbnQpIHtcbiAgICAgICAgdGVtcGxhdGVFbGVtZW50LnJlbW92ZSgpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IC8vIHdlIHVzZSBhcHBlbmQgZm9yIGh0bWwgb2JqZWN0cyB0byBtYWludGFpbiBqcyBldmVudHNcblxuXG4gICAgICB0aGlzLnNldEVsZW1lbnRDb250ZW50KHRlbXBsYXRlRWxlbWVudCwgY29udGVudCk7XG4gICAgfVxuXG4gICAgc2V0RWxlbWVudENvbnRlbnQoZWxlbWVudCwgY29udGVudCkge1xuICAgICAgaWYgKGVsZW1lbnQgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNFbGVtZW50JDEoY29udGVudCkpIHtcbiAgICAgICAgY29udGVudCA9IGdldEVsZW1lbnQoY29udGVudCk7IC8vIGNvbnRlbnQgaXMgYSBET00gbm9kZSBvciBhIGpRdWVyeVxuXG4gICAgICAgIGlmICh0aGlzLl9jb25maWcuaHRtbCkge1xuICAgICAgICAgIGlmIChjb250ZW50LnBhcmVudE5vZGUgIT09IGVsZW1lbnQpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gJyc7XG4gICAgICAgICAgICBlbGVtZW50LmFwcGVuZChjb250ZW50KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZWxlbWVudC50ZXh0Q29udGVudCA9IGNvbnRlbnQudGV4dENvbnRlbnQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9jb25maWcuaHRtbCkge1xuICAgICAgICBpZiAodGhpcy5fY29uZmlnLnNhbml0aXplKSB7XG4gICAgICAgICAgY29udGVudCA9IHNhbml0aXplSHRtbChjb250ZW50LCB0aGlzLl9jb25maWcuYWxsb3dMaXN0LCB0aGlzLl9jb25maWcuc2FuaXRpemVGbik7XG4gICAgICAgIH1cblxuICAgICAgICBlbGVtZW50LmlubmVySFRNTCA9IGNvbnRlbnQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlbGVtZW50LnRleHRDb250ZW50ID0gY29udGVudDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBnZXRUaXRsZSgpIHtcbiAgICAgIGNvbnN0IHRpdGxlID0gdGhpcy5fZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2RhdGEtYnMtb3JpZ2luYWwtdGl0bGUnKSB8fCB0aGlzLl9jb25maWcudGl0bGU7XG5cbiAgICAgIHJldHVybiB0aGlzLl9yZXNvbHZlUG9zc2libGVGdW5jdGlvbih0aXRsZSk7XG4gICAgfVxuXG4gICAgdXBkYXRlQXR0YWNobWVudChhdHRhY2htZW50KSB7XG4gICAgICBpZiAoYXR0YWNobWVudCA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICByZXR1cm4gJ2VuZCc7XG4gICAgICB9XG5cbiAgICAgIGlmIChhdHRhY2htZW50ID09PSAnbGVmdCcpIHtcbiAgICAgICAgcmV0dXJuICdzdGFydCc7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBhdHRhY2htZW50O1xuICAgIH0gLy8gUHJpdmF0ZVxuXG5cbiAgICBfaW5pdGlhbGl6ZU9uRGVsZWdhdGVkVGFyZ2V0KGV2ZW50LCBjb250ZXh0KSB7XG4gICAgICByZXR1cm4gY29udGV4dCB8fCB0aGlzLmNvbnN0cnVjdG9yLmdldE9yQ3JlYXRlSW5zdGFuY2UoZXZlbnQuZGVsZWdhdGVUYXJnZXQsIHRoaXMuX2dldERlbGVnYXRlQ29uZmlnKCkpO1xuICAgIH1cblxuICAgIF9nZXRPZmZzZXQoKSB7XG4gICAgICBjb25zdCB7XG4gICAgICAgIG9mZnNldFxuICAgICAgfSA9IHRoaXMuX2NvbmZpZztcblxuICAgICAgaWYgKHR5cGVvZiBvZmZzZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBvZmZzZXQuc3BsaXQoJywnKS5tYXAodmFsID0+IE51bWJlci5wYXJzZUludCh2YWwsIDEwKSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBwb3BwZXJEYXRhID0+IG9mZnNldChwb3BwZXJEYXRhLCB0aGlzLl9lbGVtZW50KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG9mZnNldDtcbiAgICB9XG5cbiAgICBfcmVzb2x2ZVBvc3NpYmxlRnVuY3Rpb24oY29udGVudCkge1xuICAgICAgcmV0dXJuIHR5cGVvZiBjb250ZW50ID09PSAnZnVuY3Rpb24nID8gY29udGVudC5jYWxsKHRoaXMuX2VsZW1lbnQpIDogY29udGVudDtcbiAgICB9XG5cbiAgICBfZ2V0UG9wcGVyQ29uZmlnKGF0dGFjaG1lbnQpIHtcbiAgICAgIGNvbnN0IGRlZmF1bHRCc1BvcHBlckNvbmZpZyA9IHtcbiAgICAgICAgcGxhY2VtZW50OiBhdHRhY2htZW50LFxuICAgICAgICBtb2RpZmllcnM6IFt7XG4gICAgICAgICAgbmFtZTogJ2ZsaXAnLFxuICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgIGZhbGxiYWNrUGxhY2VtZW50czogdGhpcy5fY29uZmlnLmZhbGxiYWNrUGxhY2VtZW50c1xuICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgIG5hbWU6ICdvZmZzZXQnLFxuICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgIG9mZnNldDogdGhpcy5fZ2V0T2Zmc2V0KClcbiAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICBuYW1lOiAncHJldmVudE92ZXJmbG93JyxcbiAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICBib3VuZGFyeTogdGhpcy5fY29uZmlnLmJvdW5kYXJ5XG4gICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgbmFtZTogJ2Fycm93JyxcbiAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICBlbGVtZW50OiBgLiR7dGhpcy5jb25zdHJ1Y3Rvci5OQU1FfS1hcnJvd2BcbiAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICBuYW1lOiAnb25DaGFuZ2UnLFxuICAgICAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgICAgICAgcGhhc2U6ICdhZnRlcldyaXRlJyxcbiAgICAgICAgICBmbjogZGF0YSA9PiB0aGlzLl9oYW5kbGVQb3BwZXJQbGFjZW1lbnRDaGFuZ2UoZGF0YSlcbiAgICAgICAgfV0sXG4gICAgICAgIG9uRmlyc3RVcGRhdGU6IGRhdGEgPT4ge1xuICAgICAgICAgIGlmIChkYXRhLm9wdGlvbnMucGxhY2VtZW50ICE9PSBkYXRhLnBsYWNlbWVudCkge1xuICAgICAgICAgICAgdGhpcy5faGFuZGxlUG9wcGVyUGxhY2VtZW50Q2hhbmdlKGRhdGEpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIHJldHVybiB7IC4uLmRlZmF1bHRCc1BvcHBlckNvbmZpZyxcbiAgICAgICAgLi4uKHR5cGVvZiB0aGlzLl9jb25maWcucG9wcGVyQ29uZmlnID09PSAnZnVuY3Rpb24nID8gdGhpcy5fY29uZmlnLnBvcHBlckNvbmZpZyhkZWZhdWx0QnNQb3BwZXJDb25maWcpIDogdGhpcy5fY29uZmlnLnBvcHBlckNvbmZpZylcbiAgICAgIH07XG4gICAgfVxuXG4gICAgX2FkZEF0dGFjaG1lbnRDbGFzcyhhdHRhY2htZW50KSB7XG4gICAgICB0aGlzLmdldFRpcEVsZW1lbnQoKS5jbGFzc0xpc3QuYWRkKGAke3RoaXMuX2dldEJhc2ljQ2xhc3NQcmVmaXgoKX0tJHt0aGlzLnVwZGF0ZUF0dGFjaG1lbnQoYXR0YWNobWVudCl9YCk7XG4gICAgfVxuXG4gICAgX2dldEF0dGFjaG1lbnQocGxhY2VtZW50KSB7XG4gICAgICByZXR1cm4gQXR0YWNobWVudE1hcFtwbGFjZW1lbnQudG9VcHBlckNhc2UoKV07XG4gICAgfVxuXG4gICAgX3NldExpc3RlbmVycygpIHtcbiAgICAgIGNvbnN0IHRyaWdnZXJzID0gdGhpcy5fY29uZmlnLnRyaWdnZXIuc3BsaXQoJyAnKTtcblxuICAgICAgdHJpZ2dlcnMuZm9yRWFjaCh0cmlnZ2VyID0+IHtcbiAgICAgICAgaWYgKHRyaWdnZXIgPT09ICdjbGljaycpIHtcbiAgICAgICAgICBFdmVudEhhbmRsZXIub24odGhpcy5fZWxlbWVudCwgdGhpcy5jb25zdHJ1Y3Rvci5FdmVudC5DTElDSywgdGhpcy5fY29uZmlnLnNlbGVjdG9yLCBldmVudCA9PiB0aGlzLnRvZ2dsZShldmVudCkpO1xuICAgICAgICB9IGVsc2UgaWYgKHRyaWdnZXIgIT09IFRSSUdHRVJfTUFOVUFMKSB7XG4gICAgICAgICAgY29uc3QgZXZlbnRJbiA9IHRyaWdnZXIgPT09IFRSSUdHRVJfSE9WRVIgPyB0aGlzLmNvbnN0cnVjdG9yLkV2ZW50Lk1PVVNFRU5URVIgOiB0aGlzLmNvbnN0cnVjdG9yLkV2ZW50LkZPQ1VTSU47XG4gICAgICAgICAgY29uc3QgZXZlbnRPdXQgPSB0cmlnZ2VyID09PSBUUklHR0VSX0hPVkVSID8gdGhpcy5jb25zdHJ1Y3Rvci5FdmVudC5NT1VTRUxFQVZFIDogdGhpcy5jb25zdHJ1Y3Rvci5FdmVudC5GT0NVU09VVDtcbiAgICAgICAgICBFdmVudEhhbmRsZXIub24odGhpcy5fZWxlbWVudCwgZXZlbnRJbiwgdGhpcy5fY29uZmlnLnNlbGVjdG9yLCBldmVudCA9PiB0aGlzLl9lbnRlcihldmVudCkpO1xuICAgICAgICAgIEV2ZW50SGFuZGxlci5vbih0aGlzLl9lbGVtZW50LCBldmVudE91dCwgdGhpcy5fY29uZmlnLnNlbGVjdG9yLCBldmVudCA9PiB0aGlzLl9sZWF2ZShldmVudCkpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgdGhpcy5faGlkZU1vZGFsSGFuZGxlciA9ICgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuX2VsZW1lbnQpIHtcbiAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgRXZlbnRIYW5kbGVyLm9uKHRoaXMuX2VsZW1lbnQuY2xvc2VzdChTRUxFQ1RPUl9NT0RBTCksIEVWRU5UX01PREFMX0hJREUsIHRoaXMuX2hpZGVNb2RhbEhhbmRsZXIpO1xuXG4gICAgICBpZiAodGhpcy5fY29uZmlnLnNlbGVjdG9yKSB7XG4gICAgICAgIHRoaXMuX2NvbmZpZyA9IHsgLi4udGhpcy5fY29uZmlnLFxuICAgICAgICAgIHRyaWdnZXI6ICdtYW51YWwnLFxuICAgICAgICAgIHNlbGVjdG9yOiAnJ1xuICAgICAgICB9O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fZml4VGl0bGUoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBfZml4VGl0bGUoKSB7XG4gICAgICBjb25zdCB0aXRsZSA9IHRoaXMuX2VsZW1lbnQuZ2V0QXR0cmlidXRlKCd0aXRsZScpO1xuXG4gICAgICBjb25zdCBvcmlnaW5hbFRpdGxlVHlwZSA9IHR5cGVvZiB0aGlzLl9lbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS1icy1vcmlnaW5hbC10aXRsZScpO1xuXG4gICAgICBpZiAodGl0bGUgfHwgb3JpZ2luYWxUaXRsZVR5cGUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQuc2V0QXR0cmlidXRlKCdkYXRhLWJzLW9yaWdpbmFsLXRpdGxlJywgdGl0bGUgfHwgJycpO1xuXG4gICAgICAgIGlmICh0aXRsZSAmJiAhdGhpcy5fZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnKSAmJiAhdGhpcy5fZWxlbWVudC50ZXh0Q29udGVudCkge1xuICAgICAgICAgIHRoaXMuX2VsZW1lbnQuc2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsJywgdGl0bGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ3RpdGxlJywgJycpO1xuICAgICAgfVxuICAgIH1cblxuICAgIF9lbnRlcihldmVudCwgY29udGV4dCkge1xuICAgICAgY29udGV4dCA9IHRoaXMuX2luaXRpYWxpemVPbkRlbGVnYXRlZFRhcmdldChldmVudCwgY29udGV4dCk7XG5cbiAgICAgIGlmIChldmVudCkge1xuICAgICAgICBjb250ZXh0Ll9hY3RpdmVUcmlnZ2VyW2V2ZW50LnR5cGUgPT09ICdmb2N1c2luJyA/IFRSSUdHRVJfRk9DVVMgOiBUUklHR0VSX0hPVkVSXSA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChjb250ZXh0LmdldFRpcEVsZW1lbnQoKS5jbGFzc0xpc3QuY29udGFpbnMoQ0xBU1NfTkFNRV9TSE9XJDIpIHx8IGNvbnRleHQuX2hvdmVyU3RhdGUgPT09IEhPVkVSX1NUQVRFX1NIT1cpIHtcbiAgICAgICAgY29udGV4dC5faG92ZXJTdGF0ZSA9IEhPVkVSX1NUQVRFX1NIT1c7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY2xlYXJUaW1lb3V0KGNvbnRleHQuX3RpbWVvdXQpO1xuICAgICAgY29udGV4dC5faG92ZXJTdGF0ZSA9IEhPVkVSX1NUQVRFX1NIT1c7XG5cbiAgICAgIGlmICghY29udGV4dC5fY29uZmlnLmRlbGF5IHx8ICFjb250ZXh0Ll9jb25maWcuZGVsYXkuc2hvdykge1xuICAgICAgICBjb250ZXh0LnNob3coKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb250ZXh0Ll90aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIGlmIChjb250ZXh0Ll9ob3ZlclN0YXRlID09PSBIT1ZFUl9TVEFURV9TSE9XKSB7XG4gICAgICAgICAgY29udGV4dC5zaG93KCk7XG4gICAgICAgIH1cbiAgICAgIH0sIGNvbnRleHQuX2NvbmZpZy5kZWxheS5zaG93KTtcbiAgICB9XG5cbiAgICBfbGVhdmUoZXZlbnQsIGNvbnRleHQpIHtcbiAgICAgIGNvbnRleHQgPSB0aGlzLl9pbml0aWFsaXplT25EZWxlZ2F0ZWRUYXJnZXQoZXZlbnQsIGNvbnRleHQpO1xuXG4gICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgY29udGV4dC5fYWN0aXZlVHJpZ2dlcltldmVudC50eXBlID09PSAnZm9jdXNvdXQnID8gVFJJR0dFUl9GT0NVUyA6IFRSSUdHRVJfSE9WRVJdID0gY29udGV4dC5fZWxlbWVudC5jb250YWlucyhldmVudC5yZWxhdGVkVGFyZ2V0KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNvbnRleHQuX2lzV2l0aEFjdGl2ZVRyaWdnZXIoKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNsZWFyVGltZW91dChjb250ZXh0Ll90aW1lb3V0KTtcbiAgICAgIGNvbnRleHQuX2hvdmVyU3RhdGUgPSBIT1ZFUl9TVEFURV9PVVQ7XG5cbiAgICAgIGlmICghY29udGV4dC5fY29uZmlnLmRlbGF5IHx8ICFjb250ZXh0Ll9jb25maWcuZGVsYXkuaGlkZSkge1xuICAgICAgICBjb250ZXh0LmhpZGUoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb250ZXh0Ll90aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIGlmIChjb250ZXh0Ll9ob3ZlclN0YXRlID09PSBIT1ZFUl9TVEFURV9PVVQpIHtcbiAgICAgICAgICBjb250ZXh0LmhpZGUoKTtcbiAgICAgICAgfVxuICAgICAgfSwgY29udGV4dC5fY29uZmlnLmRlbGF5LmhpZGUpO1xuICAgIH1cblxuICAgIF9pc1dpdGhBY3RpdmVUcmlnZ2VyKCkge1xuICAgICAgZm9yIChjb25zdCB0cmlnZ2VyIGluIHRoaXMuX2FjdGl2ZVRyaWdnZXIpIHtcbiAgICAgICAgaWYgKHRoaXMuX2FjdGl2ZVRyaWdnZXJbdHJpZ2dlcl0pIHtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgX2dldENvbmZpZyhjb25maWcpIHtcbiAgICAgIGNvbnN0IGRhdGFBdHRyaWJ1dGVzID0gTWFuaXB1bGF0b3IuZ2V0RGF0YUF0dHJpYnV0ZXModGhpcy5fZWxlbWVudCk7XG4gICAgICBPYmplY3Qua2V5cyhkYXRhQXR0cmlidXRlcykuZm9yRWFjaChkYXRhQXR0ciA9PiB7XG4gICAgICAgIGlmIChESVNBTExPV0VEX0FUVFJJQlVURVMuaGFzKGRhdGFBdHRyKSkge1xuICAgICAgICAgIGRlbGV0ZSBkYXRhQXR0cmlidXRlc1tkYXRhQXR0cl07XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgY29uZmlnID0geyAuLi50aGlzLmNvbnN0cnVjdG9yLkRlZmF1bHQsXG4gICAgICAgIC4uLmRhdGFBdHRyaWJ1dGVzLFxuICAgICAgICAuLi4odHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcgJiYgY29uZmlnID8gY29uZmlnIDoge30pXG4gICAgICB9O1xuICAgICAgY29uZmlnLmNvbnRhaW5lciA9IGNvbmZpZy5jb250YWluZXIgPT09IGZhbHNlID8gZG9jdW1lbnQuYm9keSA6IGdldEVsZW1lbnQoY29uZmlnLmNvbnRhaW5lcik7XG5cbiAgICAgIGlmICh0eXBlb2YgY29uZmlnLmRlbGF5ID09PSAnbnVtYmVyJykge1xuICAgICAgICBjb25maWcuZGVsYXkgPSB7XG4gICAgICAgICAgc2hvdzogY29uZmlnLmRlbGF5LFxuICAgICAgICAgIGhpZGU6IGNvbmZpZy5kZWxheVxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIGNvbmZpZy50aXRsZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgY29uZmlnLnRpdGxlID0gY29uZmlnLnRpdGxlLnRvU3RyaW5nKCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgY29uZmlnLmNvbnRlbnQgPT09ICdudW1iZXInKSB7XG4gICAgICAgIGNvbmZpZy5jb250ZW50ID0gY29uZmlnLmNvbnRlbnQudG9TdHJpbmcoKTtcbiAgICAgIH1cblxuICAgICAgdHlwZUNoZWNrQ29uZmlnKE5BTUUkNCwgY29uZmlnLCB0aGlzLmNvbnN0cnVjdG9yLkRlZmF1bHRUeXBlKTtcblxuICAgICAgaWYgKGNvbmZpZy5zYW5pdGl6ZSkge1xuICAgICAgICBjb25maWcudGVtcGxhdGUgPSBzYW5pdGl6ZUh0bWwoY29uZmlnLnRlbXBsYXRlLCBjb25maWcuYWxsb3dMaXN0LCBjb25maWcuc2FuaXRpemVGbik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjb25maWc7XG4gICAgfVxuXG4gICAgX2dldERlbGVnYXRlQ29uZmlnKCkge1xuICAgICAgY29uc3QgY29uZmlnID0ge307XG5cbiAgICAgIGZvciAoY29uc3Qga2V5IGluIHRoaXMuX2NvbmZpZykge1xuICAgICAgICBpZiAodGhpcy5jb25zdHJ1Y3Rvci5EZWZhdWx0W2tleV0gIT09IHRoaXMuX2NvbmZpZ1trZXldKSB7XG4gICAgICAgICAgY29uZmlnW2tleV0gPSB0aGlzLl9jb25maWdba2V5XTtcbiAgICAgICAgfVxuICAgICAgfSAvLyBJbiB0aGUgZnV0dXJlIGNhbiBiZSByZXBsYWNlZCB3aXRoOlxuICAgICAgLy8gY29uc3Qga2V5c1dpdGhEaWZmZXJlbnRWYWx1ZXMgPSBPYmplY3QuZW50cmllcyh0aGlzLl9jb25maWcpLmZpbHRlcihlbnRyeSA9PiB0aGlzLmNvbnN0cnVjdG9yLkRlZmF1bHRbZW50cnlbMF1dICE9PSB0aGlzLl9jb25maWdbZW50cnlbMF1dKVxuICAgICAgLy8gYE9iamVjdC5mcm9tRW50cmllcyhrZXlzV2l0aERpZmZlcmVudFZhbHVlcylgXG5cblxuICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICB9XG5cbiAgICBfY2xlYW5UaXBDbGFzcygpIHtcbiAgICAgIGNvbnN0IHRpcCA9IHRoaXMuZ2V0VGlwRWxlbWVudCgpO1xuICAgICAgY29uc3QgYmFzaWNDbGFzc1ByZWZpeFJlZ2V4ID0gbmV3IFJlZ0V4cChgKF58XFxcXHMpJHt0aGlzLl9nZXRCYXNpY0NsYXNzUHJlZml4KCl9XFxcXFMrYCwgJ2cnKTtcbiAgICAgIGNvbnN0IHRhYkNsYXNzID0gdGlwLmdldEF0dHJpYnV0ZSgnY2xhc3MnKS5tYXRjaChiYXNpY0NsYXNzUHJlZml4UmVnZXgpO1xuXG4gICAgICBpZiAodGFiQ2xhc3MgIT09IG51bGwgJiYgdGFiQ2xhc3MubGVuZ3RoID4gMCkge1xuICAgICAgICB0YWJDbGFzcy5tYXAodG9rZW4gPT4gdG9rZW4udHJpbSgpKS5mb3JFYWNoKHRDbGFzcyA9PiB0aXAuY2xhc3NMaXN0LnJlbW92ZSh0Q2xhc3MpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBfZ2V0QmFzaWNDbGFzc1ByZWZpeCgpIHtcbiAgICAgIHJldHVybiBDTEFTU19QUkVGSVgkMTtcbiAgICB9XG5cbiAgICBfaGFuZGxlUG9wcGVyUGxhY2VtZW50Q2hhbmdlKHBvcHBlckRhdGEpIHtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgc3RhdGVcbiAgICAgIH0gPSBwb3BwZXJEYXRhO1xuXG4gICAgICBpZiAoIXN0YXRlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy50aXAgPSBzdGF0ZS5lbGVtZW50cy5wb3BwZXI7XG5cbiAgICAgIHRoaXMuX2NsZWFuVGlwQ2xhc3MoKTtcblxuICAgICAgdGhpcy5fYWRkQXR0YWNobWVudENsYXNzKHRoaXMuX2dldEF0dGFjaG1lbnQoc3RhdGUucGxhY2VtZW50KSk7XG4gICAgfVxuXG4gICAgX2Rpc3Bvc2VQb3BwZXIoKSB7XG4gICAgICBpZiAodGhpcy5fcG9wcGVyKSB7XG4gICAgICAgIHRoaXMuX3BvcHBlci5kZXN0cm95KCk7XG5cbiAgICAgICAgdGhpcy5fcG9wcGVyID0gbnVsbDtcbiAgICAgIH1cbiAgICB9IC8vIFN0YXRpY1xuXG5cbiAgICBzdGF0aWMgalF1ZXJ5SW50ZXJmYWNlKGNvbmZpZykge1xuICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBUb29sdGlwLmdldE9yQ3JlYXRlSW5zdGFuY2UodGhpcywgY29uZmlnKTtcblxuICAgICAgICBpZiAodHlwZW9mIGNvbmZpZyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGRhdGFbY29uZmlnXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYE5vIG1ldGhvZCBuYW1lZCBcIiR7Y29uZmlnfVwiYCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZGF0YVtjb25maWddKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICB9XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogalF1ZXJ5XG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBhZGQgLlRvb2x0aXAgdG8galF1ZXJ5IG9ubHkgaWYgalF1ZXJ5IGlzIHByZXNlbnRcbiAgICovXG5cblxuICBkZWZpbmVKUXVlcnlQbHVnaW4oVG9vbHRpcCk7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjUuMS4zKTogcG9wb3Zlci5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQ29uc3RhbnRzXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICBjb25zdCBOQU1FJDMgPSAncG9wb3Zlcic7XG4gIGNvbnN0IERBVEFfS0VZJDMgPSAnYnMucG9wb3Zlcic7XG4gIGNvbnN0IEVWRU5UX0tFWSQzID0gYC4ke0RBVEFfS0VZJDN9YDtcbiAgY29uc3QgQ0xBU1NfUFJFRklYID0gJ2JzLXBvcG92ZXInO1xuICBjb25zdCBEZWZhdWx0JDIgPSB7IC4uLlRvb2x0aXAuRGVmYXVsdCxcbiAgICBwbGFjZW1lbnQ6ICdyaWdodCcsXG4gICAgb2Zmc2V0OiBbMCwgOF0sXG4gICAgdHJpZ2dlcjogJ2NsaWNrJyxcbiAgICBjb250ZW50OiAnJyxcbiAgICB0ZW1wbGF0ZTogJzxkaXYgY2xhc3M9XCJwb3BvdmVyXCIgcm9sZT1cInRvb2x0aXBcIj4nICsgJzxkaXYgY2xhc3M9XCJwb3BvdmVyLWFycm93XCI+PC9kaXY+JyArICc8aDMgY2xhc3M9XCJwb3BvdmVyLWhlYWRlclwiPjwvaDM+JyArICc8ZGl2IGNsYXNzPVwicG9wb3Zlci1ib2R5XCI+PC9kaXY+JyArICc8L2Rpdj4nXG4gIH07XG4gIGNvbnN0IERlZmF1bHRUeXBlJDIgPSB7IC4uLlRvb2x0aXAuRGVmYXVsdFR5cGUsXG4gICAgY29udGVudDogJyhzdHJpbmd8ZWxlbWVudHxmdW5jdGlvbiknXG4gIH07XG4gIGNvbnN0IEV2ZW50JDEgPSB7XG4gICAgSElERTogYGhpZGUke0VWRU5UX0tFWSQzfWAsXG4gICAgSElEREVOOiBgaGlkZGVuJHtFVkVOVF9LRVkkM31gLFxuICAgIFNIT1c6IGBzaG93JHtFVkVOVF9LRVkkM31gLFxuICAgIFNIT1dOOiBgc2hvd24ke0VWRU5UX0tFWSQzfWAsXG4gICAgSU5TRVJURUQ6IGBpbnNlcnRlZCR7RVZFTlRfS0VZJDN9YCxcbiAgICBDTElDSzogYGNsaWNrJHtFVkVOVF9LRVkkM31gLFxuICAgIEZPQ1VTSU46IGBmb2N1c2luJHtFVkVOVF9LRVkkM31gLFxuICAgIEZPQ1VTT1VUOiBgZm9jdXNvdXQke0VWRU5UX0tFWSQzfWAsXG4gICAgTU9VU0VFTlRFUjogYG1vdXNlZW50ZXIke0VWRU5UX0tFWSQzfWAsXG4gICAgTU9VU0VMRUFWRTogYG1vdXNlbGVhdmUke0VWRU5UX0tFWSQzfWBcbiAgfTtcbiAgY29uc3QgU0VMRUNUT1JfVElUTEUgPSAnLnBvcG92ZXItaGVhZGVyJztcbiAgY29uc3QgU0VMRUNUT1JfQ09OVEVOVCA9ICcucG9wb3Zlci1ib2R5JztcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICBjbGFzcyBQb3BvdmVyIGV4dGVuZHMgVG9vbHRpcCB7XG4gICAgLy8gR2V0dGVyc1xuICAgIHN0YXRpYyBnZXQgRGVmYXVsdCgpIHtcbiAgICAgIHJldHVybiBEZWZhdWx0JDI7XG4gICAgfVxuXG4gICAgc3RhdGljIGdldCBOQU1FKCkge1xuICAgICAgcmV0dXJuIE5BTUUkMztcbiAgICB9XG5cbiAgICBzdGF0aWMgZ2V0IEV2ZW50KCkge1xuICAgICAgcmV0dXJuIEV2ZW50JDE7XG4gICAgfVxuXG4gICAgc3RhdGljIGdldCBEZWZhdWx0VHlwZSgpIHtcbiAgICAgIHJldHVybiBEZWZhdWx0VHlwZSQyO1xuICAgIH0gLy8gT3ZlcnJpZGVzXG5cblxuICAgIGlzV2l0aENvbnRlbnQoKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRUaXRsZSgpIHx8IHRoaXMuX2dldENvbnRlbnQoKTtcbiAgICB9XG5cbiAgICBzZXRDb250ZW50KHRpcCkge1xuICAgICAgdGhpcy5fc2FuaXRpemVBbmRTZXRDb250ZW50KHRpcCwgdGhpcy5nZXRUaXRsZSgpLCBTRUxFQ1RPUl9USVRMRSk7XG5cbiAgICAgIHRoaXMuX3Nhbml0aXplQW5kU2V0Q29udGVudCh0aXAsIHRoaXMuX2dldENvbnRlbnQoKSwgU0VMRUNUT1JfQ09OVEVOVCk7XG4gICAgfSAvLyBQcml2YXRlXG5cblxuICAgIF9nZXRDb250ZW50KCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3Jlc29sdmVQb3NzaWJsZUZ1bmN0aW9uKHRoaXMuX2NvbmZpZy5jb250ZW50KTtcbiAgICB9XG5cbiAgICBfZ2V0QmFzaWNDbGFzc1ByZWZpeCgpIHtcbiAgICAgIHJldHVybiBDTEFTU19QUkVGSVg7XG4gICAgfSAvLyBTdGF0aWNcblxuXG4gICAgc3RhdGljIGpRdWVyeUludGVyZmFjZShjb25maWcpIHtcbiAgICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBkYXRhID0gUG9wb3Zlci5nZXRPckNyZWF0ZUluc3RhbmNlKHRoaXMsIGNvbmZpZyk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2NvbmZpZ10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBObyBtZXRob2QgbmFtZWQgXCIke2NvbmZpZ31cImApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGRhdGFbY29uZmlnXSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgfVxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIGpRdWVyeVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogYWRkIC5Qb3BvdmVyIHRvIGpRdWVyeSBvbmx5IGlmIGpRdWVyeSBpcyBwcmVzZW50XG4gICAqL1xuXG5cbiAgZGVmaW5lSlF1ZXJ5UGx1Z2luKFBvcG92ZXIpO1xuXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBCb290c3RyYXAgKHY1LjEuMyk6IHNjcm9sbHNweS5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQ29uc3RhbnRzXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICBjb25zdCBOQU1FJDIgPSAnc2Nyb2xsc3B5JztcbiAgY29uc3QgREFUQV9LRVkkMiA9ICdicy5zY3JvbGxzcHknO1xuICBjb25zdCBFVkVOVF9LRVkkMiA9IGAuJHtEQVRBX0tFWSQyfWA7XG4gIGNvbnN0IERBVEFfQVBJX0tFWSQxID0gJy5kYXRhLWFwaSc7XG4gIGNvbnN0IERlZmF1bHQkMSA9IHtcbiAgICBvZmZzZXQ6IDEwLFxuICAgIG1ldGhvZDogJ2F1dG8nLFxuICAgIHRhcmdldDogJydcbiAgfTtcbiAgY29uc3QgRGVmYXVsdFR5cGUkMSA9IHtcbiAgICBvZmZzZXQ6ICdudW1iZXInLFxuICAgIG1ldGhvZDogJ3N0cmluZycsXG4gICAgdGFyZ2V0OiAnKHN0cmluZ3xlbGVtZW50KSdcbiAgfTtcbiAgY29uc3QgRVZFTlRfQUNUSVZBVEUgPSBgYWN0aXZhdGUke0VWRU5UX0tFWSQyfWA7XG4gIGNvbnN0IEVWRU5UX1NDUk9MTCA9IGBzY3JvbGwke0VWRU5UX0tFWSQyfWA7XG4gIGNvbnN0IEVWRU5UX0xPQURfREFUQV9BUEkgPSBgbG9hZCR7RVZFTlRfS0VZJDJ9JHtEQVRBX0FQSV9LRVkkMX1gO1xuICBjb25zdCBDTEFTU19OQU1FX0RST1BET1dOX0lURU0gPSAnZHJvcGRvd24taXRlbSc7XG4gIGNvbnN0IENMQVNTX05BTUVfQUNUSVZFJDEgPSAnYWN0aXZlJztcbiAgY29uc3QgU0VMRUNUT1JfREFUQV9TUFkgPSAnW2RhdGEtYnMtc3B5PVwic2Nyb2xsXCJdJztcbiAgY29uc3QgU0VMRUNUT1JfTkFWX0xJU1RfR1JPVVAkMSA9ICcubmF2LCAubGlzdC1ncm91cCc7XG4gIGNvbnN0IFNFTEVDVE9SX05BVl9MSU5LUyA9ICcubmF2LWxpbmsnO1xuICBjb25zdCBTRUxFQ1RPUl9OQVZfSVRFTVMgPSAnLm5hdi1pdGVtJztcbiAgY29uc3QgU0VMRUNUT1JfTElTVF9JVEVNUyA9ICcubGlzdC1ncm91cC1pdGVtJztcbiAgY29uc3QgU0VMRUNUT1JfTElOS19JVEVNUyA9IGAke1NFTEVDVE9SX05BVl9MSU5LU30sICR7U0VMRUNUT1JfTElTVF9JVEVNU30sIC4ke0NMQVNTX05BTUVfRFJPUERPV05fSVRFTX1gO1xuICBjb25zdCBTRUxFQ1RPUl9EUk9QRE9XTiQxID0gJy5kcm9wZG93bic7XG4gIGNvbnN0IFNFTEVDVE9SX0RST1BET1dOX1RPR0dMRSQxID0gJy5kcm9wZG93bi10b2dnbGUnO1xuICBjb25zdCBNRVRIT0RfT0ZGU0VUID0gJ29mZnNldCc7XG4gIGNvbnN0IE1FVEhPRF9QT1NJVElPTiA9ICdwb3NpdGlvbic7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQ2xhc3MgRGVmaW5pdGlvblxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgY2xhc3MgU2Nyb2xsU3B5IGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoZWxlbWVudCwgY29uZmlnKSB7XG4gICAgICBzdXBlcihlbGVtZW50KTtcbiAgICAgIHRoaXMuX3Njcm9sbEVsZW1lbnQgPSB0aGlzLl9lbGVtZW50LnRhZ05hbWUgPT09ICdCT0RZJyA/IHdpbmRvdyA6IHRoaXMuX2VsZW1lbnQ7XG4gICAgICB0aGlzLl9jb25maWcgPSB0aGlzLl9nZXRDb25maWcoY29uZmlnKTtcbiAgICAgIHRoaXMuX29mZnNldHMgPSBbXTtcbiAgICAgIHRoaXMuX3RhcmdldHMgPSBbXTtcbiAgICAgIHRoaXMuX2FjdGl2ZVRhcmdldCA9IG51bGw7XG4gICAgICB0aGlzLl9zY3JvbGxIZWlnaHQgPSAwO1xuICAgICAgRXZlbnRIYW5kbGVyLm9uKHRoaXMuX3Njcm9sbEVsZW1lbnQsIEVWRU5UX1NDUk9MTCwgKCkgPT4gdGhpcy5fcHJvY2VzcygpKTtcbiAgICAgIHRoaXMucmVmcmVzaCgpO1xuXG4gICAgICB0aGlzLl9wcm9jZXNzKCk7XG4gICAgfSAvLyBHZXR0ZXJzXG5cblxuICAgIHN0YXRpYyBnZXQgRGVmYXVsdCgpIHtcbiAgICAgIHJldHVybiBEZWZhdWx0JDE7XG4gICAgfVxuXG4gICAgc3RhdGljIGdldCBOQU1FKCkge1xuICAgICAgcmV0dXJuIE5BTUUkMjtcbiAgICB9IC8vIFB1YmxpY1xuXG5cbiAgICByZWZyZXNoKCkge1xuICAgICAgY29uc3QgYXV0b01ldGhvZCA9IHRoaXMuX3Njcm9sbEVsZW1lbnQgPT09IHRoaXMuX3Njcm9sbEVsZW1lbnQud2luZG93ID8gTUVUSE9EX09GRlNFVCA6IE1FVEhPRF9QT1NJVElPTjtcbiAgICAgIGNvbnN0IG9mZnNldE1ldGhvZCA9IHRoaXMuX2NvbmZpZy5tZXRob2QgPT09ICdhdXRvJyA/IGF1dG9NZXRob2QgOiB0aGlzLl9jb25maWcubWV0aG9kO1xuICAgICAgY29uc3Qgb2Zmc2V0QmFzZSA9IG9mZnNldE1ldGhvZCA9PT0gTUVUSE9EX1BPU0lUSU9OID8gdGhpcy5fZ2V0U2Nyb2xsVG9wKCkgOiAwO1xuICAgICAgdGhpcy5fb2Zmc2V0cyA9IFtdO1xuICAgICAgdGhpcy5fdGFyZ2V0cyA9IFtdO1xuICAgICAgdGhpcy5fc2Nyb2xsSGVpZ2h0ID0gdGhpcy5fZ2V0U2Nyb2xsSGVpZ2h0KCk7XG4gICAgICBjb25zdCB0YXJnZXRzID0gU2VsZWN0b3JFbmdpbmUuZmluZChTRUxFQ1RPUl9MSU5LX0lURU1TLCB0aGlzLl9jb25maWcudGFyZ2V0KTtcbiAgICAgIHRhcmdldHMubWFwKGVsZW1lbnQgPT4ge1xuICAgICAgICBjb25zdCB0YXJnZXRTZWxlY3RvciA9IGdldFNlbGVjdG9yRnJvbUVsZW1lbnQoZWxlbWVudCk7XG4gICAgICAgIGNvbnN0IHRhcmdldCA9IHRhcmdldFNlbGVjdG9yID8gU2VsZWN0b3JFbmdpbmUuZmluZE9uZSh0YXJnZXRTZWxlY3RvcikgOiBudWxsO1xuXG4gICAgICAgIGlmICh0YXJnZXQpIHtcbiAgICAgICAgICBjb25zdCB0YXJnZXRCQ1IgPSB0YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAgICAgICBpZiAodGFyZ2V0QkNSLndpZHRoIHx8IHRhcmdldEJDUi5oZWlnaHQpIHtcbiAgICAgICAgICAgIHJldHVybiBbTWFuaXB1bGF0b3Jbb2Zmc2V0TWV0aG9kXSh0YXJnZXQpLnRvcCArIG9mZnNldEJhc2UsIHRhcmdldFNlbGVjdG9yXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH0pLmZpbHRlcihpdGVtID0+IGl0ZW0pLnNvcnQoKGEsIGIpID0+IGFbMF0gLSBiWzBdKS5mb3JFYWNoKGl0ZW0gPT4ge1xuICAgICAgICB0aGlzLl9vZmZzZXRzLnB1c2goaXRlbVswXSk7XG5cbiAgICAgICAgdGhpcy5fdGFyZ2V0cy5wdXNoKGl0ZW1bMV0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZGlzcG9zZSgpIHtcbiAgICAgIEV2ZW50SGFuZGxlci5vZmYodGhpcy5fc2Nyb2xsRWxlbWVudCwgRVZFTlRfS0VZJDIpO1xuICAgICAgc3VwZXIuZGlzcG9zZSgpO1xuICAgIH0gLy8gUHJpdmF0ZVxuXG5cbiAgICBfZ2V0Q29uZmlnKGNvbmZpZykge1xuICAgICAgY29uZmlnID0geyAuLi5EZWZhdWx0JDEsXG4gICAgICAgIC4uLk1hbmlwdWxhdG9yLmdldERhdGFBdHRyaWJ1dGVzKHRoaXMuX2VsZW1lbnQpLFxuICAgICAgICAuLi4odHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcgJiYgY29uZmlnID8gY29uZmlnIDoge30pXG4gICAgICB9O1xuICAgICAgY29uZmlnLnRhcmdldCA9IGdldEVsZW1lbnQoY29uZmlnLnRhcmdldCkgfHwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICAgICAgdHlwZUNoZWNrQ29uZmlnKE5BTUUkMiwgY29uZmlnLCBEZWZhdWx0VHlwZSQxKTtcbiAgICAgIHJldHVybiBjb25maWc7XG4gICAgfVxuXG4gICAgX2dldFNjcm9sbFRvcCgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9zY3JvbGxFbGVtZW50ID09PSB3aW5kb3cgPyB0aGlzLl9zY3JvbGxFbGVtZW50LnBhZ2VZT2Zmc2V0IDogdGhpcy5fc2Nyb2xsRWxlbWVudC5zY3JvbGxUb3A7XG4gICAgfVxuXG4gICAgX2dldFNjcm9sbEhlaWdodCgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9zY3JvbGxFbGVtZW50LnNjcm9sbEhlaWdodCB8fCBNYXRoLm1heChkb2N1bWVudC5ib2R5LnNjcm9sbEhlaWdodCwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbEhlaWdodCk7XG4gICAgfVxuXG4gICAgX2dldE9mZnNldEhlaWdodCgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9zY3JvbGxFbGVtZW50ID09PSB3aW5kb3cgPyB3aW5kb3cuaW5uZXJIZWlnaHQgOiB0aGlzLl9zY3JvbGxFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodDtcbiAgICB9XG5cbiAgICBfcHJvY2VzcygpIHtcbiAgICAgIGNvbnN0IHNjcm9sbFRvcCA9IHRoaXMuX2dldFNjcm9sbFRvcCgpICsgdGhpcy5fY29uZmlnLm9mZnNldDtcblxuICAgICAgY29uc3Qgc2Nyb2xsSGVpZ2h0ID0gdGhpcy5fZ2V0U2Nyb2xsSGVpZ2h0KCk7XG5cbiAgICAgIGNvbnN0IG1heFNjcm9sbCA9IHRoaXMuX2NvbmZpZy5vZmZzZXQgKyBzY3JvbGxIZWlnaHQgLSB0aGlzLl9nZXRPZmZzZXRIZWlnaHQoKTtcblxuICAgICAgaWYgKHRoaXMuX3Njcm9sbEhlaWdodCAhPT0gc2Nyb2xsSGVpZ2h0KSB7XG4gICAgICAgIHRoaXMucmVmcmVzaCgpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc2Nyb2xsVG9wID49IG1heFNjcm9sbCkge1xuICAgICAgICBjb25zdCB0YXJnZXQgPSB0aGlzLl90YXJnZXRzW3RoaXMuX3RhcmdldHMubGVuZ3RoIC0gMV07XG5cbiAgICAgICAgaWYgKHRoaXMuX2FjdGl2ZVRhcmdldCAhPT0gdGFyZ2V0KSB7XG4gICAgICAgICAgdGhpcy5fYWN0aXZhdGUodGFyZ2V0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX2FjdGl2ZVRhcmdldCAmJiBzY3JvbGxUb3AgPCB0aGlzLl9vZmZzZXRzWzBdICYmIHRoaXMuX29mZnNldHNbMF0gPiAwKSB7XG4gICAgICAgIHRoaXMuX2FjdGl2ZVRhcmdldCA9IG51bGw7XG5cbiAgICAgICAgdGhpcy5fY2xlYXIoKTtcblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGZvciAobGV0IGkgPSB0aGlzLl9vZmZzZXRzLmxlbmd0aDsgaS0tOykge1xuICAgICAgICBjb25zdCBpc0FjdGl2ZVRhcmdldCA9IHRoaXMuX2FjdGl2ZVRhcmdldCAhPT0gdGhpcy5fdGFyZ2V0c1tpXSAmJiBzY3JvbGxUb3AgPj0gdGhpcy5fb2Zmc2V0c1tpXSAmJiAodHlwZW9mIHRoaXMuX29mZnNldHNbaSArIDFdID09PSAndW5kZWZpbmVkJyB8fCBzY3JvbGxUb3AgPCB0aGlzLl9vZmZzZXRzW2kgKyAxXSk7XG5cbiAgICAgICAgaWYgKGlzQWN0aXZlVGFyZ2V0KSB7XG4gICAgICAgICAgdGhpcy5fYWN0aXZhdGUodGhpcy5fdGFyZ2V0c1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBfYWN0aXZhdGUodGFyZ2V0KSB7XG4gICAgICB0aGlzLl9hY3RpdmVUYXJnZXQgPSB0YXJnZXQ7XG5cbiAgICAgIHRoaXMuX2NsZWFyKCk7XG5cbiAgICAgIGNvbnN0IHF1ZXJpZXMgPSBTRUxFQ1RPUl9MSU5LX0lURU1TLnNwbGl0KCcsJykubWFwKHNlbGVjdG9yID0+IGAke3NlbGVjdG9yfVtkYXRhLWJzLXRhcmdldD1cIiR7dGFyZ2V0fVwiXSwke3NlbGVjdG9yfVtocmVmPVwiJHt0YXJnZXR9XCJdYCk7XG4gICAgICBjb25zdCBsaW5rID0gU2VsZWN0b3JFbmdpbmUuZmluZE9uZShxdWVyaWVzLmpvaW4oJywnKSwgdGhpcy5fY29uZmlnLnRhcmdldCk7XG4gICAgICBsaW5rLmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9BQ1RJVkUkMSk7XG5cbiAgICAgIGlmIChsaW5rLmNsYXNzTGlzdC5jb250YWlucyhDTEFTU19OQU1FX0RST1BET1dOX0lURU0pKSB7XG4gICAgICAgIFNlbGVjdG9yRW5naW5lLmZpbmRPbmUoU0VMRUNUT1JfRFJPUERPV05fVE9HR0xFJDEsIGxpbmsuY2xvc2VzdChTRUxFQ1RPUl9EUk9QRE9XTiQxKSkuY2xhc3NMaXN0LmFkZChDTEFTU19OQU1FX0FDVElWRSQxKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIFNlbGVjdG9yRW5naW5lLnBhcmVudHMobGluaywgU0VMRUNUT1JfTkFWX0xJU1RfR1JPVVAkMSkuZm9yRWFjaChsaXN0R3JvdXAgPT4ge1xuICAgICAgICAgIC8vIFNldCB0cmlnZ2VyZWQgbGlua3MgcGFyZW50cyBhcyBhY3RpdmVcbiAgICAgICAgICAvLyBXaXRoIGJvdGggPHVsPiBhbmQgPG5hdj4gbWFya3VwIGEgcGFyZW50IGlzIHRoZSBwcmV2aW91cyBzaWJsaW5nIG9mIGFueSBuYXYgYW5jZXN0b3JcbiAgICAgICAgICBTZWxlY3RvckVuZ2luZS5wcmV2KGxpc3RHcm91cCwgYCR7U0VMRUNUT1JfTkFWX0xJTktTfSwgJHtTRUxFQ1RPUl9MSVNUX0lURU1TfWApLmZvckVhY2goaXRlbSA9PiBpdGVtLmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9BQ1RJVkUkMSkpOyAvLyBIYW5kbGUgc3BlY2lhbCBjYXNlIHdoZW4gLm5hdi1saW5rIGlzIGluc2lkZSAubmF2LWl0ZW1cblxuICAgICAgICAgIFNlbGVjdG9yRW5naW5lLnByZXYobGlzdEdyb3VwLCBTRUxFQ1RPUl9OQVZfSVRFTVMpLmZvckVhY2gobmF2SXRlbSA9PiB7XG4gICAgICAgICAgICBTZWxlY3RvckVuZ2luZS5jaGlsZHJlbihuYXZJdGVtLCBTRUxFQ1RPUl9OQVZfTElOS1MpLmZvckVhY2goaXRlbSA9PiBpdGVtLmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9BQ1RJVkUkMSkpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgRXZlbnRIYW5kbGVyLnRyaWdnZXIodGhpcy5fc2Nyb2xsRWxlbWVudCwgRVZFTlRfQUNUSVZBVEUsIHtcbiAgICAgICAgcmVsYXRlZFRhcmdldDogdGFyZ2V0XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBfY2xlYXIoKSB7XG4gICAgICBTZWxlY3RvckVuZ2luZS5maW5kKFNFTEVDVE9SX0xJTktfSVRFTVMsIHRoaXMuX2NvbmZpZy50YXJnZXQpLmZpbHRlcihub2RlID0+IG5vZGUuY2xhc3NMaXN0LmNvbnRhaW5zKENMQVNTX05BTUVfQUNUSVZFJDEpKS5mb3JFYWNoKG5vZGUgPT4gbm9kZS5jbGFzc0xpc3QucmVtb3ZlKENMQVNTX05BTUVfQUNUSVZFJDEpKTtcbiAgICB9IC8vIFN0YXRpY1xuXG5cbiAgICBzdGF0aWMgalF1ZXJ5SW50ZXJmYWNlKGNvbmZpZykge1xuICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBTY3JvbGxTcHkuZ2V0T3JDcmVhdGVJbnN0YW5jZSh0aGlzLCBjb25maWcpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgY29uZmlnICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgZGF0YVtjb25maWddID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYE5vIG1ldGhvZCBuYW1lZCBcIiR7Y29uZmlnfVwiYCk7XG4gICAgICAgIH1cblxuICAgICAgICBkYXRhW2NvbmZpZ10oKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICB9XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogRGF0YSBBcGkgaW1wbGVtZW50YXRpb25cbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG5cbiAgRXZlbnRIYW5kbGVyLm9uKHdpbmRvdywgRVZFTlRfTE9BRF9EQVRBX0FQSSwgKCkgPT4ge1xuICAgIFNlbGVjdG9yRW5naW5lLmZpbmQoU0VMRUNUT1JfREFUQV9TUFkpLmZvckVhY2goc3B5ID0+IG5ldyBTY3JvbGxTcHkoc3B5KSk7XG4gIH0pO1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIGpRdWVyeVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogYWRkIC5TY3JvbGxTcHkgdG8galF1ZXJ5IG9ubHkgaWYgalF1ZXJ5IGlzIHByZXNlbnRcbiAgICovXG5cbiAgZGVmaW5lSlF1ZXJ5UGx1Z2luKFNjcm9sbFNweSk7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjUuMS4zKTogdGFiLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDb25zdGFudHNcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIGNvbnN0IE5BTUUkMSA9ICd0YWInO1xuICBjb25zdCBEQVRBX0tFWSQxID0gJ2JzLnRhYic7XG4gIGNvbnN0IEVWRU5UX0tFWSQxID0gYC4ke0RBVEFfS0VZJDF9YDtcbiAgY29uc3QgREFUQV9BUElfS0VZID0gJy5kYXRhLWFwaSc7XG4gIGNvbnN0IEVWRU5UX0hJREUkMSA9IGBoaWRlJHtFVkVOVF9LRVkkMX1gO1xuICBjb25zdCBFVkVOVF9ISURERU4kMSA9IGBoaWRkZW4ke0VWRU5UX0tFWSQxfWA7XG4gIGNvbnN0IEVWRU5UX1NIT1ckMSA9IGBzaG93JHtFVkVOVF9LRVkkMX1gO1xuICBjb25zdCBFVkVOVF9TSE9XTiQxID0gYHNob3duJHtFVkVOVF9LRVkkMX1gO1xuICBjb25zdCBFVkVOVF9DTElDS19EQVRBX0FQSSA9IGBjbGljayR7RVZFTlRfS0VZJDF9JHtEQVRBX0FQSV9LRVl9YDtcbiAgY29uc3QgQ0xBU1NfTkFNRV9EUk9QRE9XTl9NRU5VID0gJ2Ryb3Bkb3duLW1lbnUnO1xuICBjb25zdCBDTEFTU19OQU1FX0FDVElWRSA9ICdhY3RpdmUnO1xuICBjb25zdCBDTEFTU19OQU1FX0ZBREUkMSA9ICdmYWRlJztcbiAgY29uc3QgQ0xBU1NfTkFNRV9TSE9XJDEgPSAnc2hvdyc7XG4gIGNvbnN0IFNFTEVDVE9SX0RST1BET1dOID0gJy5kcm9wZG93bic7XG4gIGNvbnN0IFNFTEVDVE9SX05BVl9MSVNUX0dST1VQID0gJy5uYXYsIC5saXN0LWdyb3VwJztcbiAgY29uc3QgU0VMRUNUT1JfQUNUSVZFID0gJy5hY3RpdmUnO1xuICBjb25zdCBTRUxFQ1RPUl9BQ1RJVkVfVUwgPSAnOnNjb3BlID4gbGkgPiAuYWN0aXZlJztcbiAgY29uc3QgU0VMRUNUT1JfREFUQV9UT0dHTEUgPSAnW2RhdGEtYnMtdG9nZ2xlPVwidGFiXCJdLCBbZGF0YS1icy10b2dnbGU9XCJwaWxsXCJdLCBbZGF0YS1icy10b2dnbGU9XCJsaXN0XCJdJztcbiAgY29uc3QgU0VMRUNUT1JfRFJPUERPV05fVE9HR0xFID0gJy5kcm9wZG93bi10b2dnbGUnO1xuICBjb25zdCBTRUxFQ1RPUl9EUk9QRE9XTl9BQ1RJVkVfQ0hJTEQgPSAnOnNjb3BlID4gLmRyb3Bkb3duLW1lbnUgLmFjdGl2ZSc7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQ2xhc3MgRGVmaW5pdGlvblxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgY2xhc3MgVGFiIGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgLy8gR2V0dGVyc1xuICAgIHN0YXRpYyBnZXQgTkFNRSgpIHtcbiAgICAgIHJldHVybiBOQU1FJDE7XG4gICAgfSAvLyBQdWJsaWNcblxuXG4gICAgc2hvdygpIHtcbiAgICAgIGlmICh0aGlzLl9lbGVtZW50LnBhcmVudE5vZGUgJiYgdGhpcy5fZWxlbWVudC5wYXJlbnROb2RlLm5vZGVUeXBlID09PSBOb2RlLkVMRU1FTlRfTk9ERSAmJiB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhDTEFTU19OQU1FX0FDVElWRSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBsZXQgcHJldmlvdXM7XG4gICAgICBjb25zdCB0YXJnZXQgPSBnZXRFbGVtZW50RnJvbVNlbGVjdG9yKHRoaXMuX2VsZW1lbnQpO1xuXG4gICAgICBjb25zdCBsaXN0RWxlbWVudCA9IHRoaXMuX2VsZW1lbnQuY2xvc2VzdChTRUxFQ1RPUl9OQVZfTElTVF9HUk9VUCk7XG5cbiAgICAgIGlmIChsaXN0RWxlbWVudCkge1xuICAgICAgICBjb25zdCBpdGVtU2VsZWN0b3IgPSBsaXN0RWxlbWVudC5ub2RlTmFtZSA9PT0gJ1VMJyB8fCBsaXN0RWxlbWVudC5ub2RlTmFtZSA9PT0gJ09MJyA/IFNFTEVDVE9SX0FDVElWRV9VTCA6IFNFTEVDVE9SX0FDVElWRTtcbiAgICAgICAgcHJldmlvdXMgPSBTZWxlY3RvckVuZ2luZS5maW5kKGl0ZW1TZWxlY3RvciwgbGlzdEVsZW1lbnQpO1xuICAgICAgICBwcmV2aW91cyA9IHByZXZpb3VzW3ByZXZpb3VzLmxlbmd0aCAtIDFdO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBoaWRlRXZlbnQgPSBwcmV2aW91cyA/IEV2ZW50SGFuZGxlci50cmlnZ2VyKHByZXZpb3VzLCBFVkVOVF9ISURFJDEsIHtcbiAgICAgICAgcmVsYXRlZFRhcmdldDogdGhpcy5fZWxlbWVudFxuICAgICAgfSkgOiBudWxsO1xuICAgICAgY29uc3Qgc2hvd0V2ZW50ID0gRXZlbnRIYW5kbGVyLnRyaWdnZXIodGhpcy5fZWxlbWVudCwgRVZFTlRfU0hPVyQxLCB7XG4gICAgICAgIHJlbGF0ZWRUYXJnZXQ6IHByZXZpb3VzXG4gICAgICB9KTtcblxuICAgICAgaWYgKHNob3dFdmVudC5kZWZhdWx0UHJldmVudGVkIHx8IGhpZGVFdmVudCAhPT0gbnVsbCAmJiBoaWRlRXZlbnQuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2FjdGl2YXRlKHRoaXMuX2VsZW1lbnQsIGxpc3RFbGVtZW50KTtcblxuICAgICAgY29uc3QgY29tcGxldGUgPSAoKSA9PiB7XG4gICAgICAgIEV2ZW50SGFuZGxlci50cmlnZ2VyKHByZXZpb3VzLCBFVkVOVF9ISURERU4kMSwge1xuICAgICAgICAgIHJlbGF0ZWRUYXJnZXQ6IHRoaXMuX2VsZW1lbnRcbiAgICAgICAgfSk7XG4gICAgICAgIEV2ZW50SGFuZGxlci50cmlnZ2VyKHRoaXMuX2VsZW1lbnQsIEVWRU5UX1NIT1dOJDEsIHtcbiAgICAgICAgICByZWxhdGVkVGFyZ2V0OiBwcmV2aW91c1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIGlmICh0YXJnZXQpIHtcbiAgICAgICAgdGhpcy5fYWN0aXZhdGUodGFyZ2V0LCB0YXJnZXQucGFyZW50Tm9kZSwgY29tcGxldGUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29tcGxldGUoKTtcbiAgICAgIH1cbiAgICB9IC8vIFByaXZhdGVcblxuXG4gICAgX2FjdGl2YXRlKGVsZW1lbnQsIGNvbnRhaW5lciwgY2FsbGJhY2spIHtcbiAgICAgIGNvbnN0IGFjdGl2ZUVsZW1lbnRzID0gY29udGFpbmVyICYmIChjb250YWluZXIubm9kZU5hbWUgPT09ICdVTCcgfHwgY29udGFpbmVyLm5vZGVOYW1lID09PSAnT0wnKSA/IFNlbGVjdG9yRW5naW5lLmZpbmQoU0VMRUNUT1JfQUNUSVZFX1VMLCBjb250YWluZXIpIDogU2VsZWN0b3JFbmdpbmUuY2hpbGRyZW4oY29udGFpbmVyLCBTRUxFQ1RPUl9BQ1RJVkUpO1xuICAgICAgY29uc3QgYWN0aXZlID0gYWN0aXZlRWxlbWVudHNbMF07XG4gICAgICBjb25zdCBpc1RyYW5zaXRpb25pbmcgPSBjYWxsYmFjayAmJiBhY3RpdmUgJiYgYWN0aXZlLmNsYXNzTGlzdC5jb250YWlucyhDTEFTU19OQU1FX0ZBREUkMSk7XG5cbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gKCkgPT4gdGhpcy5fdHJhbnNpdGlvbkNvbXBsZXRlKGVsZW1lbnQsIGFjdGl2ZSwgY2FsbGJhY2spO1xuXG4gICAgICBpZiAoYWN0aXZlICYmIGlzVHJhbnNpdGlvbmluZykge1xuICAgICAgICBhY3RpdmUuY2xhc3NMaXN0LnJlbW92ZShDTEFTU19OQU1FX1NIT1ckMSk7XG5cbiAgICAgICAgdGhpcy5fcXVldWVDYWxsYmFjayhjb21wbGV0ZSwgZWxlbWVudCwgdHJ1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb21wbGV0ZSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIF90cmFuc2l0aW9uQ29tcGxldGUoZWxlbWVudCwgYWN0aXZlLCBjYWxsYmFjaykge1xuICAgICAgaWYgKGFjdGl2ZSkge1xuICAgICAgICBhY3RpdmUuY2xhc3NMaXN0LnJlbW92ZShDTEFTU19OQU1FX0FDVElWRSk7XG4gICAgICAgIGNvbnN0IGRyb3Bkb3duQ2hpbGQgPSBTZWxlY3RvckVuZ2luZS5maW5kT25lKFNFTEVDVE9SX0RST1BET1dOX0FDVElWRV9DSElMRCwgYWN0aXZlLnBhcmVudE5vZGUpO1xuXG4gICAgICAgIGlmIChkcm9wZG93bkNoaWxkKSB7XG4gICAgICAgICAgZHJvcGRvd25DaGlsZC5jbGFzc0xpc3QucmVtb3ZlKENMQVNTX05BTUVfQUNUSVZFKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhY3RpdmUuZ2V0QXR0cmlidXRlKCdyb2xlJykgPT09ICd0YWInKSB7XG4gICAgICAgICAgYWN0aXZlLnNldEF0dHJpYnV0ZSgnYXJpYS1zZWxlY3RlZCcsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9BQ1RJVkUpO1xuXG4gICAgICBpZiAoZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3JvbGUnKSA9PT0gJ3RhYicpIHtcbiAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2FyaWEtc2VsZWN0ZWQnLCB0cnVlKTtcbiAgICAgIH1cblxuICAgICAgcmVmbG93KGVsZW1lbnQpO1xuXG4gICAgICBpZiAoZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoQ0xBU1NfTkFNRV9GQURFJDEpKSB7XG4gICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZChDTEFTU19OQU1FX1NIT1ckMSk7XG4gICAgICB9XG5cbiAgICAgIGxldCBwYXJlbnQgPSBlbGVtZW50LnBhcmVudE5vZGU7XG5cbiAgICAgIGlmIChwYXJlbnQgJiYgcGFyZW50Lm5vZGVOYW1lID09PSAnTEknKSB7XG4gICAgICAgIHBhcmVudCA9IHBhcmVudC5wYXJlbnROb2RlO1xuICAgICAgfVxuXG4gICAgICBpZiAocGFyZW50ICYmIHBhcmVudC5jbGFzc0xpc3QuY29udGFpbnMoQ0xBU1NfTkFNRV9EUk9QRE9XTl9NRU5VKSkge1xuICAgICAgICBjb25zdCBkcm9wZG93bkVsZW1lbnQgPSBlbGVtZW50LmNsb3Nlc3QoU0VMRUNUT1JfRFJPUERPV04pO1xuXG4gICAgICAgIGlmIChkcm9wZG93bkVsZW1lbnQpIHtcbiAgICAgICAgICBTZWxlY3RvckVuZ2luZS5maW5kKFNFTEVDVE9SX0RST1BET1dOX1RPR0dMRSwgZHJvcGRvd25FbGVtZW50KS5mb3JFYWNoKGRyb3Bkb3duID0+IGRyb3Bkb3duLmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9BQ1RJVkUpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCdhcmlhLWV4cGFuZGVkJywgdHJ1ZSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgfVxuICAgIH0gLy8gU3RhdGljXG5cblxuICAgIHN0YXRpYyBqUXVlcnlJbnRlcmZhY2UoY29uZmlnKSB7XG4gICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IFRhYi5nZXRPckNyZWF0ZUluc3RhbmNlKHRoaXMpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIGlmICh0eXBlb2YgZGF0YVtjb25maWddID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgTm8gbWV0aG9kIG5hbWVkIFwiJHtjb25maWd9XCJgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBkYXRhW2NvbmZpZ10oKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gIH1cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBEYXRhIEFwaSBpbXBsZW1lbnRhdGlvblxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cblxuICBFdmVudEhhbmRsZXIub24oZG9jdW1lbnQsIEVWRU5UX0NMSUNLX0RBVEFfQVBJLCBTRUxFQ1RPUl9EQVRBX1RPR0dMRSwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgaWYgKFsnQScsICdBUkVBJ10uaW5jbHVkZXModGhpcy50YWdOYW1lKSkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG5cbiAgICBpZiAoaXNEaXNhYmxlZCh0aGlzKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGRhdGEgPSBUYWIuZ2V0T3JDcmVhdGVJbnN0YW5jZSh0aGlzKTtcbiAgICBkYXRhLnNob3coKTtcbiAgfSk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogalF1ZXJ5XG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBhZGQgLlRhYiB0byBqUXVlcnkgb25seSBpZiBqUXVlcnkgaXMgcHJlc2VudFxuICAgKi9cblxuICBkZWZpbmVKUXVlcnlQbHVnaW4oVGFiKTtcblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NS4xLjMpOiB0b2FzdC5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQ29uc3RhbnRzXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICBjb25zdCBOQU1FID0gJ3RvYXN0JztcbiAgY29uc3QgREFUQV9LRVkgPSAnYnMudG9hc3QnO1xuICBjb25zdCBFVkVOVF9LRVkgPSBgLiR7REFUQV9LRVl9YDtcbiAgY29uc3QgRVZFTlRfTU9VU0VPVkVSID0gYG1vdXNlb3ZlciR7RVZFTlRfS0VZfWA7XG4gIGNvbnN0IEVWRU5UX01PVVNFT1VUID0gYG1vdXNlb3V0JHtFVkVOVF9LRVl9YDtcbiAgY29uc3QgRVZFTlRfRk9DVVNJTiA9IGBmb2N1c2luJHtFVkVOVF9LRVl9YDtcbiAgY29uc3QgRVZFTlRfRk9DVVNPVVQgPSBgZm9jdXNvdXQke0VWRU5UX0tFWX1gO1xuICBjb25zdCBFVkVOVF9ISURFID0gYGhpZGUke0VWRU5UX0tFWX1gO1xuICBjb25zdCBFVkVOVF9ISURERU4gPSBgaGlkZGVuJHtFVkVOVF9LRVl9YDtcbiAgY29uc3QgRVZFTlRfU0hPVyA9IGBzaG93JHtFVkVOVF9LRVl9YDtcbiAgY29uc3QgRVZFTlRfU0hPV04gPSBgc2hvd24ke0VWRU5UX0tFWX1gO1xuICBjb25zdCBDTEFTU19OQU1FX0ZBREUgPSAnZmFkZSc7XG4gIGNvbnN0IENMQVNTX05BTUVfSElERSA9ICdoaWRlJzsgLy8gQGRlcHJlY2F0ZWQgLSBrZXB0IGhlcmUgb25seSBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcblxuICBjb25zdCBDTEFTU19OQU1FX1NIT1cgPSAnc2hvdyc7XG4gIGNvbnN0IENMQVNTX05BTUVfU0hPV0lORyA9ICdzaG93aW5nJztcbiAgY29uc3QgRGVmYXVsdFR5cGUgPSB7XG4gICAgYW5pbWF0aW9uOiAnYm9vbGVhbicsXG4gICAgYXV0b2hpZGU6ICdib29sZWFuJyxcbiAgICBkZWxheTogJ251bWJlcidcbiAgfTtcbiAgY29uc3QgRGVmYXVsdCA9IHtcbiAgICBhbmltYXRpb246IHRydWUsXG4gICAgYXV0b2hpZGU6IHRydWUsXG4gICAgZGVsYXk6IDUwMDBcbiAgfTtcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICBjbGFzcyBUb2FzdCBleHRlbmRzIEJhc2VDb21wb25lbnQge1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQsIGNvbmZpZykge1xuICAgICAgc3VwZXIoZWxlbWVudCk7XG4gICAgICB0aGlzLl9jb25maWcgPSB0aGlzLl9nZXRDb25maWcoY29uZmlnKTtcbiAgICAgIHRoaXMuX3RpbWVvdXQgPSBudWxsO1xuICAgICAgdGhpcy5faGFzTW91c2VJbnRlcmFjdGlvbiA9IGZhbHNlO1xuICAgICAgdGhpcy5faGFzS2V5Ym9hcmRJbnRlcmFjdGlvbiA9IGZhbHNlO1xuXG4gICAgICB0aGlzLl9zZXRMaXN0ZW5lcnMoKTtcbiAgICB9IC8vIEdldHRlcnNcblxuXG4gICAgc3RhdGljIGdldCBEZWZhdWx0VHlwZSgpIHtcbiAgICAgIHJldHVybiBEZWZhdWx0VHlwZTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZ2V0IERlZmF1bHQoKSB7XG4gICAgICByZXR1cm4gRGVmYXVsdDtcbiAgICB9XG5cbiAgICBzdGF0aWMgZ2V0IE5BTUUoKSB7XG4gICAgICByZXR1cm4gTkFNRTtcbiAgICB9IC8vIFB1YmxpY1xuXG5cbiAgICBzaG93KCkge1xuICAgICAgY29uc3Qgc2hvd0V2ZW50ID0gRXZlbnRIYW5kbGVyLnRyaWdnZXIodGhpcy5fZWxlbWVudCwgRVZFTlRfU0hPVyk7XG5cbiAgICAgIGlmIChzaG93RXZlbnQuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2NsZWFyVGltZW91dCgpO1xuXG4gICAgICBpZiAodGhpcy5fY29uZmlnLmFuaW1hdGlvbikge1xuICAgICAgICB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9GQURFKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY29tcGxldGUgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShDTEFTU19OQU1FX1NIT1dJTkcpO1xuXG4gICAgICAgIEV2ZW50SGFuZGxlci50cmlnZ2VyKHRoaXMuX2VsZW1lbnQsIEVWRU5UX1NIT1dOKTtcblxuICAgICAgICB0aGlzLl9tYXliZVNjaGVkdWxlSGlkZSgpO1xuICAgICAgfTtcblxuICAgICAgdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKENMQVNTX05BTUVfSElERSk7IC8vIEBkZXByZWNhdGVkXG5cblxuICAgICAgcmVmbG93KHRoaXMuX2VsZW1lbnQpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9TSE9XKTtcblxuICAgICAgdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuYWRkKENMQVNTX05BTUVfU0hPV0lORyk7XG5cbiAgICAgIHRoaXMuX3F1ZXVlQ2FsbGJhY2soY29tcGxldGUsIHRoaXMuX2VsZW1lbnQsIHRoaXMuX2NvbmZpZy5hbmltYXRpb24pO1xuICAgIH1cblxuICAgIGhpZGUoKSB7XG4gICAgICBpZiAoIXRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKENMQVNTX05BTUVfU0hPVykpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBoaWRlRXZlbnQgPSBFdmVudEhhbmRsZXIudHJpZ2dlcih0aGlzLl9lbGVtZW50LCBFVkVOVF9ISURFKTtcblxuICAgICAgaWYgKGhpZGVFdmVudC5kZWZhdWx0UHJldmVudGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY29tcGxldGUgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmFkZChDTEFTU19OQU1FX0hJREUpOyAvLyBAZGVwcmVjYXRlZFxuXG5cbiAgICAgICAgdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKENMQVNTX05BTUVfU0hPV0lORyk7XG5cbiAgICAgICAgdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKENMQVNTX05BTUVfU0hPVyk7XG5cbiAgICAgICAgRXZlbnRIYW5kbGVyLnRyaWdnZXIodGhpcy5fZWxlbWVudCwgRVZFTlRfSElEREVOKTtcbiAgICAgIH07XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmFkZChDTEFTU19OQU1FX1NIT1dJTkcpO1xuXG4gICAgICB0aGlzLl9xdWV1ZUNhbGxiYWNrKGNvbXBsZXRlLCB0aGlzLl9lbGVtZW50LCB0aGlzLl9jb25maWcuYW5pbWF0aW9uKTtcbiAgICB9XG5cbiAgICBkaXNwb3NlKCkge1xuICAgICAgdGhpcy5fY2xlYXJUaW1lb3V0KCk7XG5cbiAgICAgIGlmICh0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhDTEFTU19OQU1FX1NIT1cpKSB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShDTEFTU19OQU1FX1NIT1cpO1xuICAgICAgfVxuXG4gICAgICBzdXBlci5kaXNwb3NlKCk7XG4gICAgfSAvLyBQcml2YXRlXG5cblxuICAgIF9nZXRDb25maWcoY29uZmlnKSB7XG4gICAgICBjb25maWcgPSB7IC4uLkRlZmF1bHQsXG4gICAgICAgIC4uLk1hbmlwdWxhdG9yLmdldERhdGFBdHRyaWJ1dGVzKHRoaXMuX2VsZW1lbnQpLFxuICAgICAgICAuLi4odHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcgJiYgY29uZmlnID8gY29uZmlnIDoge30pXG4gICAgICB9O1xuICAgICAgdHlwZUNoZWNrQ29uZmlnKE5BTUUsIGNvbmZpZywgdGhpcy5jb25zdHJ1Y3Rvci5EZWZhdWx0VHlwZSk7XG4gICAgICByZXR1cm4gY29uZmlnO1xuICAgIH1cblxuICAgIF9tYXliZVNjaGVkdWxlSGlkZSgpIHtcbiAgICAgIGlmICghdGhpcy5fY29uZmlnLmF1dG9oaWRlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX2hhc01vdXNlSW50ZXJhY3Rpb24gfHwgdGhpcy5faGFzS2V5Ym9hcmRJbnRlcmFjdGlvbikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3RpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICB9LCB0aGlzLl9jb25maWcuZGVsYXkpO1xuICAgIH1cblxuICAgIF9vbkludGVyYWN0aW9uKGV2ZW50LCBpc0ludGVyYWN0aW5nKSB7XG4gICAgICBzd2l0Y2ggKGV2ZW50LnR5cGUpIHtcbiAgICAgICAgY2FzZSAnbW91c2VvdmVyJzpcbiAgICAgICAgY2FzZSAnbW91c2VvdXQnOlxuICAgICAgICAgIHRoaXMuX2hhc01vdXNlSW50ZXJhY3Rpb24gPSBpc0ludGVyYWN0aW5nO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ2ZvY3VzaW4nOlxuICAgICAgICBjYXNlICdmb2N1c291dCc6XG4gICAgICAgICAgdGhpcy5faGFzS2V5Ym9hcmRJbnRlcmFjdGlvbiA9IGlzSW50ZXJhY3Rpbmc7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIGlmIChpc0ludGVyYWN0aW5nKSB7XG4gICAgICAgIHRoaXMuX2NsZWFyVGltZW91dCgpO1xuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbmV4dEVsZW1lbnQgPSBldmVudC5yZWxhdGVkVGFyZ2V0O1xuXG4gICAgICBpZiAodGhpcy5fZWxlbWVudCA9PT0gbmV4dEVsZW1lbnQgfHwgdGhpcy5fZWxlbWVudC5jb250YWlucyhuZXh0RWxlbWVudCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9tYXliZVNjaGVkdWxlSGlkZSgpO1xuICAgIH1cblxuICAgIF9zZXRMaXN0ZW5lcnMoKSB7XG4gICAgICBFdmVudEhhbmRsZXIub24odGhpcy5fZWxlbWVudCwgRVZFTlRfTU9VU0VPVkVSLCBldmVudCA9PiB0aGlzLl9vbkludGVyYWN0aW9uKGV2ZW50LCB0cnVlKSk7XG4gICAgICBFdmVudEhhbmRsZXIub24odGhpcy5fZWxlbWVudCwgRVZFTlRfTU9VU0VPVVQsIGV2ZW50ID0+IHRoaXMuX29uSW50ZXJhY3Rpb24oZXZlbnQsIGZhbHNlKSk7XG4gICAgICBFdmVudEhhbmRsZXIub24odGhpcy5fZWxlbWVudCwgRVZFTlRfRk9DVVNJTiwgZXZlbnQgPT4gdGhpcy5fb25JbnRlcmFjdGlvbihldmVudCwgdHJ1ZSkpO1xuICAgICAgRXZlbnRIYW5kbGVyLm9uKHRoaXMuX2VsZW1lbnQsIEVWRU5UX0ZPQ1VTT1VULCBldmVudCA9PiB0aGlzLl9vbkludGVyYWN0aW9uKGV2ZW50LCBmYWxzZSkpO1xuICAgIH1cblxuICAgIF9jbGVhclRpbWVvdXQoKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGhpcy5fdGltZW91dCk7XG4gICAgICB0aGlzLl90aW1lb3V0ID0gbnVsbDtcbiAgICB9IC8vIFN0YXRpY1xuXG5cbiAgICBzdGF0aWMgalF1ZXJ5SW50ZXJmYWNlKGNvbmZpZykge1xuICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBUb2FzdC5nZXRPckNyZWF0ZUluc3RhbmNlKHRoaXMsIGNvbmZpZyk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2NvbmZpZ10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBObyBtZXRob2QgbmFtZWQgXCIke2NvbmZpZ31cImApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGRhdGFbY29uZmlnXSh0aGlzKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gIH1cblxuICBlbmFibGVEaXNtaXNzVHJpZ2dlcihUb2FzdCk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogalF1ZXJ5XG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBhZGQgLlRvYXN0IHRvIGpRdWVyeSBvbmx5IGlmIGpRdWVyeSBpcyBwcmVzZW50XG4gICAqL1xuXG4gIGRlZmluZUpRdWVyeVBsdWdpbihUb2FzdCk7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjUuMS4zKTogaW5kZXgudW1kLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cbiAgY29uc3QgaW5kZXhfdW1kID0ge1xuICAgIEFsZXJ0LFxuICAgIEJ1dHRvbixcbiAgICBDYXJvdXNlbCxcbiAgICBDb2xsYXBzZSxcbiAgICBEcm9wZG93bixcbiAgICBNb2RhbCxcbiAgICBPZmZjYW52YXMsXG4gICAgUG9wb3ZlcixcbiAgICBTY3JvbGxTcHksXG4gICAgVGFiLFxuICAgIFRvYXN0LFxuICAgIFRvb2x0aXBcbiAgfTtcblxuICByZXR1cm4gaW5kZXhfdW1kO1xuXG59KSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1ib290c3RyYXAuYnVuZGxlLmpzLm1hcFxuIiwiLy8gVGhlIG1vZHVsZSBjYWNoZVxudmFyIF9fd2VicGFja19tb2R1bGVfY2FjaGVfXyA9IHt9O1xuXG4vLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcblx0dmFyIGNhY2hlZE1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF07XG5cdGlmIChjYWNoZWRNb2R1bGUgIT09IHVuZGVmaW5lZCkge1xuXHRcdHJldHVybiBjYWNoZWRNb2R1bGUuZXhwb3J0cztcblx0fVxuXHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuXHR2YXIgbW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXSA9IHtcblx0XHQvLyBubyBtb2R1bGUuaWQgbmVlZGVkXG5cdFx0Ly8gbm8gbW9kdWxlLmxvYWRlZCBuZWVkZWRcblx0XHRleHBvcnRzOiB7fVxuXHR9O1xuXG5cdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuXHRfX3dlYnBhY2tfbW9kdWxlc19fW21vZHVsZUlkXS5jYWxsKG1vZHVsZS5leHBvcnRzLCBtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuXHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuXHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG59XG5cbiIsIi8vIGdldERlZmF1bHRFeHBvcnQgZnVuY3Rpb24gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBub24taGFybW9ueSBtb2R1bGVzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSAobW9kdWxlKSA9PiB7XG5cdHZhciBnZXR0ZXIgPSBtb2R1bGUgJiYgbW9kdWxlLl9fZXNNb2R1bGUgP1xuXHRcdCgpID0+IChtb2R1bGVbJ2RlZmF1bHQnXSkgOlxuXHRcdCgpID0+IChtb2R1bGUpO1xuXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCB7IGE6IGdldHRlciB9KTtcblx0cmV0dXJuIGdldHRlcjtcbn07IiwiLy8gZGVmaW5lIGdldHRlciBmdW5jdGlvbnMgZm9yIGhhcm1vbnkgZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5kID0gKGV4cG9ydHMsIGRlZmluaXRpb24pID0+IHtcblx0Zm9yKHZhciBrZXkgaW4gZGVmaW5pdGlvbikge1xuXHRcdGlmKF9fd2VicGFja19yZXF1aXJlX18ubyhkZWZpbml0aW9uLCBrZXkpICYmICFfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZXhwb3J0cywga2V5KSkge1xuXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIGtleSwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGRlZmluaXRpb25ba2V5XSB9KTtcblx0XHR9XG5cdH1cbn07IiwiX193ZWJwYWNrX3JlcXVpcmVfXy5vID0gKG9iaiwgcHJvcCkgPT4gKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApKSJdLCJuYW1lcyI6WyJtb2R1bGUiLCJleHBvcnRzIiwiTUFYX1VJRCIsIk1JTExJU0VDT05EU19NVUxUSVBMSUVSIiwiVFJBTlNJVElPTl9FTkQiLCJ0b1R5cGUiLCJvYmoiLCJ0b1N0cmluZyIsImNhbGwiLCJtYXRjaCIsInRvTG93ZXJDYXNlIiwiZ2V0VUlEIiwicHJlZml4IiwiTWF0aCIsImZsb29yIiwicmFuZG9tIiwiZG9jdW1lbnQiLCJnZXRFbGVtZW50QnlJZCIsImdldFNlbGVjdG9yIiwiZWxlbWVudCIsInNlbGVjdG9yIiwiZ2V0QXR0cmlidXRlIiwiaHJlZkF0dHIiLCJpbmNsdWRlcyIsInN0YXJ0c1dpdGgiLCJzcGxpdCIsInRyaW0iLCJnZXRTZWxlY3RvckZyb21FbGVtZW50IiwicXVlcnlTZWxlY3RvciIsImdldEVsZW1lbnRGcm9tU2VsZWN0b3IiLCJnZXRUcmFuc2l0aW9uRHVyYXRpb25Gcm9tRWxlbWVudCIsInRyYW5zaXRpb25EdXJhdGlvbiIsInRyYW5zaXRpb25EZWxheSIsIndpbmRvdyIsImdldENvbXB1dGVkU3R5bGUiLCJmbG9hdFRyYW5zaXRpb25EdXJhdGlvbiIsIk51bWJlciIsInBhcnNlRmxvYXQiLCJmbG9hdFRyYW5zaXRpb25EZWxheSIsInRyaWdnZXJUcmFuc2l0aW9uRW5kIiwiZGlzcGF0Y2hFdmVudCIsIkV2ZW50IiwiaXNFbGVtZW50JDEiLCJqcXVlcnkiLCJub2RlVHlwZSIsImdldEVsZW1lbnQiLCJsZW5ndGgiLCJ0eXBlQ2hlY2tDb25maWciLCJjb21wb25lbnROYW1lIiwiY29uZmlnIiwiY29uZmlnVHlwZXMiLCJPYmplY3QiLCJrZXlzIiwiZm9yRWFjaCIsInByb3BlcnR5IiwiZXhwZWN0ZWRUeXBlcyIsInZhbHVlIiwidmFsdWVUeXBlIiwiUmVnRXhwIiwidGVzdCIsIlR5cGVFcnJvciIsInRvVXBwZXJDYXNlIiwiaXNWaXNpYmxlIiwiZ2V0Q2xpZW50UmVjdHMiLCJnZXRQcm9wZXJ0eVZhbHVlIiwiaXNEaXNhYmxlZCIsIk5vZGUiLCJFTEVNRU5UX05PREUiLCJjbGFzc0xpc3QiLCJjb250YWlucyIsImRpc2FibGVkIiwiaGFzQXR0cmlidXRlIiwiZmluZFNoYWRvd1Jvb3QiLCJkb2N1bWVudEVsZW1lbnQiLCJhdHRhY2hTaGFkb3ciLCJnZXRSb290Tm9kZSIsInJvb3QiLCJTaGFkb3dSb290IiwicGFyZW50Tm9kZSIsIm5vb3AiLCJyZWZsb3ciLCJvZmZzZXRIZWlnaHQiLCJnZXRqUXVlcnkiLCJqUXVlcnkiLCJib2R5IiwiRE9NQ29udGVudExvYWRlZENhbGxiYWNrcyIsIm9uRE9NQ29udGVudExvYWRlZCIsImNhbGxiYWNrIiwicmVhZHlTdGF0ZSIsImFkZEV2ZW50TGlzdGVuZXIiLCJwdXNoIiwiaXNSVEwiLCJkaXIiLCJkZWZpbmVKUXVlcnlQbHVnaW4iLCJwbHVnaW4iLCIkIiwibmFtZSIsIk5BTUUiLCJKUVVFUllfTk9fQ09ORkxJQ1QiLCJmbiIsImpRdWVyeUludGVyZmFjZSIsIkNvbnN0cnVjdG9yIiwibm9Db25mbGljdCIsImV4ZWN1dGUiLCJleGVjdXRlQWZ0ZXJUcmFuc2l0aW9uIiwidHJhbnNpdGlvbkVsZW1lbnQiLCJ3YWl0Rm9yVHJhbnNpdGlvbiIsImR1cmF0aW9uUGFkZGluZyIsImVtdWxhdGVkRHVyYXRpb24iLCJjYWxsZWQiLCJoYW5kbGVyIiwidGFyZ2V0IiwicmVtb3ZlRXZlbnRMaXN0ZW5lciIsInNldFRpbWVvdXQiLCJnZXROZXh0QWN0aXZlRWxlbWVudCIsImxpc3QiLCJhY3RpdmVFbGVtZW50Iiwic2hvdWxkR2V0TmV4dCIsImlzQ3ljbGVBbGxvd2VkIiwiaW5kZXgiLCJpbmRleE9mIiwibGlzdExlbmd0aCIsIm1heCIsIm1pbiIsIm5hbWVzcGFjZVJlZ2V4Iiwic3RyaXBOYW1lUmVnZXgiLCJzdHJpcFVpZFJlZ2V4IiwiZXZlbnRSZWdpc3RyeSIsInVpZEV2ZW50IiwiY3VzdG9tRXZlbnRzIiwibW91c2VlbnRlciIsIm1vdXNlbGVhdmUiLCJjdXN0b21FdmVudHNSZWdleCIsIm5hdGl2ZUV2ZW50cyIsIlNldCIsImdldFVpZEV2ZW50IiwidWlkIiwiZ2V0RXZlbnQiLCJib290c3RyYXBIYW5kbGVyIiwiZXZlbnQiLCJkZWxlZ2F0ZVRhcmdldCIsIm9uZU9mZiIsIkV2ZW50SGFuZGxlciIsIm9mZiIsInR5cGUiLCJhcHBseSIsImJvb3RzdHJhcERlbGVnYXRpb25IYW5kbGVyIiwiZG9tRWxlbWVudHMiLCJxdWVyeVNlbGVjdG9yQWxsIiwidGhpcyIsImkiLCJmaW5kSGFuZGxlciIsImV2ZW50cyIsImRlbGVnYXRpb25TZWxlY3RvciIsInVpZEV2ZW50TGlzdCIsImxlbiIsIm9yaWdpbmFsSGFuZGxlciIsIm5vcm1hbGl6ZVBhcmFtcyIsIm9yaWdpbmFsVHlwZUV2ZW50IiwiZGVsZWdhdGlvbkZuIiwiZGVsZWdhdGlvbiIsInR5cGVFdmVudCIsImdldFR5cGVFdmVudCIsImhhcyIsImFkZEhhbmRsZXIiLCJ3cmFwRm4iLCJyZWxhdGVkVGFyZ2V0IiwiaGFuZGxlcnMiLCJwcmV2aW91c0ZuIiwicmVwbGFjZSIsInJlbW92ZUhhbmRsZXIiLCJCb29sZWFuIiwicmVtb3ZlTmFtZXNwYWNlZEhhbmRsZXJzIiwibmFtZXNwYWNlIiwic3RvcmVFbGVtZW50RXZlbnQiLCJoYW5kbGVyS2V5Iiwib24iLCJvbmUiLCJpbk5hbWVzcGFjZSIsImlzTmFtZXNwYWNlIiwiZWxlbWVudEV2ZW50Iiwic2xpY2UiLCJrZXlIYW5kbGVycyIsInRyaWdnZXIiLCJhcmdzIiwiaXNOYXRpdmUiLCJqUXVlcnlFdmVudCIsImJ1YmJsZXMiLCJuYXRpdmVEaXNwYXRjaCIsImRlZmF1bHRQcmV2ZW50ZWQiLCJldnQiLCJpc1Byb3BhZ2F0aW9uU3RvcHBlZCIsImlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkIiwiaXNEZWZhdWx0UHJldmVudGVkIiwiY3JlYXRlRXZlbnQiLCJpbml0RXZlbnQiLCJDdXN0b21FdmVudCIsImNhbmNlbGFibGUiLCJrZXkiLCJkZWZpbmVQcm9wZXJ0eSIsImdldCIsInByZXZlbnREZWZhdWx0IiwiZWxlbWVudE1hcCIsIk1hcCIsIkRhdGEiLCJzZXQiLCJpbnN0YW5jZSIsImluc3RhbmNlTWFwIiwic2l6ZSIsImNvbnNvbGUiLCJlcnJvciIsIkFycmF5IiwiZnJvbSIsInJlbW92ZSIsImRlbGV0ZSIsIlZFUlNJT04iLCJCYXNlQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJfZWxlbWVudCIsIkRBVEFfS0VZIiwiZGlzcG9zZSIsIkVWRU5UX0tFWSIsImdldE93blByb3BlcnR5TmFtZXMiLCJwcm9wZXJ0eU5hbWUiLCJfcXVldWVDYWxsYmFjayIsImlzQW5pbWF0ZWQiLCJzdGF0aWMiLCJnZXRJbnN0YW5jZSIsIkVycm9yIiwiZW5hYmxlRGlzbWlzc1RyaWdnZXIiLCJjb21wb25lbnQiLCJtZXRob2QiLCJjbGlja0V2ZW50IiwidGFnTmFtZSIsImNsb3Nlc3QiLCJnZXRPckNyZWF0ZUluc3RhbmNlIiwiTkFNRSRkIiwiRVZFTlRfS0VZJGMiLCJFVkVOVF9DTE9TRSIsIkVWRU5UX0NMT1NFRCIsIkNMQVNTX05BTUVfRkFERSQ1IiwiQ0xBU1NfTkFNRV9TSE9XJDgiLCJBbGVydCIsImNsb3NlIiwiX2Rlc3Ryb3lFbGVtZW50IiwiZWFjaCIsImRhdGEiLCJ1bmRlZmluZWQiLCJOQU1FJGMiLCJDTEFTU19OQU1FX0FDVElWRSQzIiwiU0VMRUNUT1JfREFUQV9UT0dHTEUkNSIsIkVWRU5UX0NMSUNLX0RBVEFfQVBJJDYiLCJCdXR0b24iLCJ0b2dnbGUiLCJzZXRBdHRyaWJ1dGUiLCJub3JtYWxpemVEYXRhIiwidmFsIiwibm9ybWFsaXplRGF0YUtleSIsImNociIsImJ1dHRvbiIsIk1hbmlwdWxhdG9yIiwic2V0RGF0YUF0dHJpYnV0ZSIsInJlbW92ZURhdGFBdHRyaWJ1dGUiLCJyZW1vdmVBdHRyaWJ1dGUiLCJnZXREYXRhQXR0cmlidXRlcyIsImF0dHJpYnV0ZXMiLCJkYXRhc2V0IiwiZmlsdGVyIiwicHVyZUtleSIsImNoYXJBdCIsImdldERhdGFBdHRyaWJ1dGUiLCJvZmZzZXQiLCJyZWN0IiwiZ2V0Qm91bmRpbmdDbGllbnRSZWN0IiwidG9wIiwicGFnZVlPZmZzZXQiLCJsZWZ0IiwicGFnZVhPZmZzZXQiLCJwb3NpdGlvbiIsIm9mZnNldFRvcCIsIm9mZnNldExlZnQiLCJOT0RFX1RFWFQiLCJTZWxlY3RvckVuZ2luZSIsImZpbmQiLCJjb25jYXQiLCJFbGVtZW50IiwicHJvdG90eXBlIiwiZmluZE9uZSIsImNoaWxkcmVuIiwiY2hpbGQiLCJtYXRjaGVzIiwicGFyZW50cyIsImFuY2VzdG9yIiwicHJldiIsInByZXZpb3VzIiwicHJldmlvdXNFbGVtZW50U2libGluZyIsIm5leHQiLCJuZXh0RWxlbWVudFNpYmxpbmciLCJmb2N1c2FibGVDaGlsZHJlbiIsImZvY3VzYWJsZXMiLCJtYXAiLCJqb2luIiwiZWwiLCJOQU1FJGIiLCJFVkVOVF9LRVkkYSIsIkRBVEFfQVBJX0tFWSQ2IiwiVE9VQ0hFVkVOVF9DT01QQVRfV0FJVCIsIlNXSVBFX1RIUkVTSE9MRCIsIkRlZmF1bHQkYSIsImludGVydmFsIiwia2V5Ym9hcmQiLCJzbGlkZSIsInBhdXNlIiwid3JhcCIsInRvdWNoIiwiRGVmYXVsdFR5cGUkYSIsIk9SREVSX05FWFQiLCJPUkRFUl9QUkVWIiwiRElSRUNUSU9OX0xFRlQiLCJESVJFQ1RJT05fUklHSFQiLCJLRVlfVE9fRElSRUNUSU9OIiwiRVZFTlRfU0xJREUiLCJFVkVOVF9TTElEIiwiRVZFTlRfS0VZRE9XTiIsIkVWRU5UX01PVVNFRU5URVIiLCJFVkVOVF9NT1VTRUxFQVZFIiwiRVZFTlRfVE9VQ0hTVEFSVCIsIkVWRU5UX1RPVUNITU9WRSIsIkVWRU5UX1RPVUNIRU5EIiwiRVZFTlRfUE9JTlRFUkRPV04iLCJFVkVOVF9QT0lOVEVSVVAiLCJFVkVOVF9EUkFHX1NUQVJUIiwiRVZFTlRfTE9BRF9EQVRBX0FQSSQyIiwiRVZFTlRfQ0xJQ0tfREFUQV9BUEkkNSIsIkNMQVNTX05BTUVfQ0FST1VTRUwiLCJDTEFTU19OQU1FX0FDVElWRSQyIiwiQ0xBU1NfTkFNRV9TTElERSIsIkNMQVNTX05BTUVfRU5EIiwiQ0xBU1NfTkFNRV9TVEFSVCIsIkNMQVNTX05BTUVfTkVYVCIsIkNMQVNTX05BTUVfUFJFViIsIkNMQVNTX05BTUVfUE9JTlRFUl9FVkVOVCIsIlNFTEVDVE9SX0FDVElWRSQxIiwiU0VMRUNUT1JfQUNUSVZFX0lURU0iLCJTRUxFQ1RPUl9JVEVNIiwiU0VMRUNUT1JfSVRFTV9JTUciLCJTRUxFQ1RPUl9ORVhUX1BSRVYiLCJTRUxFQ1RPUl9JTkRJQ0FUT1JTIiwiU0VMRUNUT1JfSU5ESUNBVE9SIiwiU0VMRUNUT1JfREFUQV9TTElERSIsIlNFTEVDVE9SX0RBVEFfUklERSIsIlBPSU5URVJfVFlQRV9UT1VDSCIsIlBPSU5URVJfVFlQRV9QRU4iLCJDYXJvdXNlbCIsInN1cGVyIiwiX2l0ZW1zIiwiX2ludGVydmFsIiwiX2FjdGl2ZUVsZW1lbnQiLCJfaXNQYXVzZWQiLCJfaXNTbGlkaW5nIiwidG91Y2hUaW1lb3V0IiwidG91Y2hTdGFydFgiLCJ0b3VjaERlbHRhWCIsIl9jb25maWciLCJfZ2V0Q29uZmlnIiwiX2luZGljYXRvcnNFbGVtZW50IiwiX3RvdWNoU3VwcG9ydGVkIiwibmF2aWdhdG9yIiwibWF4VG91Y2hQb2ludHMiLCJfcG9pbnRlckV2ZW50IiwiUG9pbnRlckV2ZW50IiwiX2FkZEV2ZW50TGlzdGVuZXJzIiwiRGVmYXVsdCIsIl9zbGlkZSIsIm5leHRXaGVuVmlzaWJsZSIsImhpZGRlbiIsImN5Y2xlIiwiY2xlYXJJbnRlcnZhbCIsIl91cGRhdGVJbnRlcnZhbCIsInNldEludGVydmFsIiwidmlzaWJpbGl0eVN0YXRlIiwiYmluZCIsInRvIiwiYWN0aXZlSW5kZXgiLCJfZ2V0SXRlbUluZGV4Iiwib3JkZXIiLCJfaGFuZGxlU3dpcGUiLCJhYnNEZWx0YXgiLCJhYnMiLCJkaXJlY3Rpb24iLCJfa2V5ZG93biIsIl9hZGRUb3VjaEV2ZW50TGlzdGVuZXJzIiwiaGFzUG9pbnRlclBlblRvdWNoIiwicG9pbnRlclR5cGUiLCJzdGFydCIsImNsaWVudFgiLCJ0b3VjaGVzIiwibW92ZSIsImVuZCIsImNsZWFyVGltZW91dCIsIml0ZW1JbWciLCJhZGQiLCJfZ2V0SXRlbUJ5T3JkZXIiLCJpc05leHQiLCJfdHJpZ2dlclNsaWRlRXZlbnQiLCJldmVudERpcmVjdGlvbk5hbWUiLCJ0YXJnZXRJbmRleCIsImZyb21JbmRleCIsIl9zZXRBY3RpdmVJbmRpY2F0b3JFbGVtZW50IiwiYWN0aXZlSW5kaWNhdG9yIiwiaW5kaWNhdG9ycyIsInBhcnNlSW50IiwiZWxlbWVudEludGVydmFsIiwiZGVmYXVsdEludGVydmFsIiwiZGlyZWN0aW9uT3JPcmRlciIsIl9kaXJlY3Rpb25Ub09yZGVyIiwiYWN0aXZlRWxlbWVudEluZGV4IiwibmV4dEVsZW1lbnQiLCJuZXh0RWxlbWVudEluZGV4IiwiaXNDeWNsaW5nIiwiZGlyZWN0aW9uYWxDbGFzc05hbWUiLCJvcmRlckNsYXNzTmFtZSIsIl9vcmRlclRvRGlyZWN0aW9uIiwidHJpZ2dlclNsaWRFdmVudCIsImNvbXBsZXRlQ2FsbEJhY2siLCJhY3Rpb24iLCJyaWRlIiwiY2Fyb3VzZWxJbnRlcmZhY2UiLCJzbGlkZUluZGV4IiwiZGF0YUFwaUNsaWNrSGFuZGxlciIsImNhcm91c2VscyIsIk5BTUUkYSIsIkRBVEFfS0VZJDkiLCJFVkVOVF9LRVkkOSIsIkRlZmF1bHQkOSIsInBhcmVudCIsIkRlZmF1bHRUeXBlJDkiLCJFVkVOVF9TSE9XJDUiLCJFVkVOVF9TSE9XTiQ1IiwiRVZFTlRfSElERSQ1IiwiRVZFTlRfSElEREVOJDUiLCJFVkVOVF9DTElDS19EQVRBX0FQSSQ0IiwiQ0xBU1NfTkFNRV9TSE9XJDciLCJDTEFTU19OQU1FX0NPTExBUFNFIiwiQ0xBU1NfTkFNRV9DT0xMQVBTSU5HIiwiQ0xBU1NfTkFNRV9DT0xMQVBTRUQiLCJDTEFTU19OQU1FX0RFRVBFUl9DSElMRFJFTiIsIkNMQVNTX05BTUVfSE9SSVpPTlRBTCIsIldJRFRIIiwiSEVJR0hUIiwiU0VMRUNUT1JfQUNUSVZFUyIsIlNFTEVDVE9SX0RBVEFfVE9HR0xFJDQiLCJDb2xsYXBzZSIsIl9pc1RyYW5zaXRpb25pbmciLCJfdHJpZ2dlckFycmF5IiwidG9nZ2xlTGlzdCIsImVsZW0iLCJmaWx0ZXJFbGVtZW50IiwiZm91bmRFbGVtIiwiX3NlbGVjdG9yIiwiX2luaXRpYWxpemVDaGlsZHJlbiIsIl9hZGRBcmlhQW5kQ29sbGFwc2VkQ2xhc3MiLCJfaXNTaG93biIsImhpZGUiLCJzaG93IiwiYWN0aXZlc0RhdGEiLCJhY3RpdmVzIiwiY29udGFpbmVyIiwidGVtcEFjdGl2ZURhdGEiLCJlbGVtQWN0aXZlIiwiZGltZW5zaW9uIiwiX2dldERpbWVuc2lvbiIsInN0eWxlIiwiY29tcGxldGUiLCJzY3JvbGxTaXplIiwidHJpZ2dlckFycmF5TGVuZ3RoIiwic2VsZWN0ZWQiLCJ0cmlnZ2VyQXJyYXkiLCJpc09wZW4iLCJib3R0b20iLCJyaWdodCIsImF1dG8iLCJiYXNlUGxhY2VtZW50cyIsImNsaXBwaW5nUGFyZW50cyIsInZpZXdwb3J0IiwicG9wcGVyIiwicmVmZXJlbmNlIiwidmFyaWF0aW9uUGxhY2VtZW50cyIsInJlZHVjZSIsImFjYyIsInBsYWNlbWVudCIsInBsYWNlbWVudHMiLCJiZWZvcmVSZWFkIiwicmVhZCIsImFmdGVyUmVhZCIsImJlZm9yZU1haW4iLCJtYWluIiwiYWZ0ZXJNYWluIiwiYmVmb3JlV3JpdGUiLCJ3cml0ZSIsImFmdGVyV3JpdGUiLCJtb2RpZmllclBoYXNlcyIsImdldE5vZGVOYW1lIiwibm9kZU5hbWUiLCJnZXRXaW5kb3ciLCJub2RlIiwib3duZXJEb2N1bWVudCIsImRlZmF1bHRWaWV3IiwiaXNFbGVtZW50IiwiaXNIVE1MRWxlbWVudCIsIkhUTUxFbGVtZW50IiwiaXNTaGFkb3dSb290IiwiYXBwbHlTdHlsZXMiLCJfcmVmIiwic3RhdGUiLCJlbGVtZW50cyIsInN0eWxlcyIsImFzc2lnbiIsImVmZmVjdCQyIiwiX3JlZjIiLCJpbml0aWFsU3R5bGVzIiwib3B0aW9ucyIsInN0cmF0ZWd5IiwibWFyZ2luIiwiYXJyb3ciLCJoYXNPd25Qcm9wZXJ0eSIsImF0dHJpYnV0ZSIsImFwcGx5U3R5bGVzJDEiLCJlbmFibGVkIiwicGhhc2UiLCJlZmZlY3QiLCJyZXF1aXJlcyIsImdldEJhc2VQbGFjZW1lbnQiLCJpbmNsdWRlU2NhbGUiLCJzY2FsZVgiLCJzY2FsZVkiLCJ3aWR0aCIsImhlaWdodCIsIngiLCJ5IiwiZ2V0TGF5b3V0UmVjdCIsImNsaWVudFJlY3QiLCJvZmZzZXRXaWR0aCIsInJvb3ROb2RlIiwiaXNTYW1lTm9kZSIsImhvc3QiLCJnZXRDb21wdXRlZFN0eWxlJDEiLCJpc1RhYmxlRWxlbWVudCIsImdldERvY3VtZW50RWxlbWVudCIsImdldFBhcmVudE5vZGUiLCJhc3NpZ25lZFNsb3QiLCJnZXRUcnVlT2Zmc2V0UGFyZW50Iiwib2Zmc2V0UGFyZW50IiwiZ2V0Q29udGFpbmluZ0Jsb2NrIiwiaXNGaXJlZm94IiwidXNlckFnZW50IiwiY3VycmVudE5vZGUiLCJjc3MiLCJ0cmFuc2Zvcm0iLCJwZXJzcGVjdGl2ZSIsImNvbnRhaW4iLCJ3aWxsQ2hhbmdlIiwiZ2V0T2Zmc2V0UGFyZW50IiwiZ2V0TWFpbkF4aXNGcm9tUGxhY2VtZW50Iiwicm91bmQiLCJ3aXRoaW4iLCJtaW4kMSIsIm1heCQxIiwiZ2V0RnJlc2hTaWRlT2JqZWN0IiwibWVyZ2VQYWRkaW5nT2JqZWN0IiwicGFkZGluZ09iamVjdCIsImV4cGFuZFRvSGFzaE1hcCIsImhhc2hNYXAiLCJ0b1BhZGRpbmdPYmplY3QiLCJwYWRkaW5nIiwicmVjdHMiLCJfc3RhdGUkbW9kaWZpZXJzRGF0YSQiLCJhcnJvd0VsZW1lbnQiLCJwb3BwZXJPZmZzZXRzIiwibW9kaWZpZXJzRGF0YSIsImJhc2VQbGFjZW1lbnQiLCJheGlzIiwiYXJyb3dSZWN0IiwibWluUHJvcCIsIm1heFByb3AiLCJlbmREaWZmIiwic3RhcnREaWZmIiwiYXJyb3dPZmZzZXRQYXJlbnQiLCJjbGllbnRTaXplIiwiY2xpZW50SGVpZ2h0IiwiY2xpZW50V2lkdGgiLCJjZW50ZXJUb1JlZmVyZW5jZSIsImNlbnRlciIsImF4aXNQcm9wIiwiY2VudGVyT2Zmc2V0IiwiZWZmZWN0JDEiLCJfb3B0aW9ucyRlbGVtZW50IiwiYXJyb3ckMSIsInJlcXVpcmVzSWZFeGlzdHMiLCJnZXRWYXJpYXRpb24iLCJ1bnNldFNpZGVzIiwicm91bmRPZmZzZXRzQnlEUFIiLCJkcHIiLCJkZXZpY2VQaXhlbFJhdGlvIiwibWFwVG9TdHlsZXMiLCJfT2JqZWN0JGFzc2lnbjIiLCJwb3BwZXJSZWN0IiwidmFyaWF0aW9uIiwib2Zmc2V0cyIsImdwdUFjY2VsZXJhdGlvbiIsImFkYXB0aXZlIiwicm91bmRPZmZzZXRzIiwiX3JlZjMiLCJfcmVmMyR4IiwiX3JlZjMkeSIsImhhc1giLCJoYXNZIiwic2lkZVgiLCJzaWRlWSIsIndpbiIsImhlaWdodFByb3AiLCJ3aWR0aFByb3AiLCJfT2JqZWN0JGFzc2lnbiIsImNvbW1vblN0eWxlcyIsImNvbXB1dGVTdHlsZXMiLCJfcmVmNCIsIl9vcHRpb25zJGdwdUFjY2VsZXJhdCIsIl9vcHRpb25zJGFkYXB0aXZlIiwiX29wdGlvbnMkcm91bmRPZmZzZXRzIiwiY29tcHV0ZVN0eWxlcyQxIiwicGFzc2l2ZSIsIl9vcHRpb25zJHNjcm9sbCIsInNjcm9sbCIsIl9vcHRpb25zJHJlc2l6ZSIsInJlc2l6ZSIsInNjcm9sbFBhcmVudHMiLCJzY3JvbGxQYXJlbnQiLCJ1cGRhdGUiLCJldmVudExpc3RlbmVycyIsImhhc2gkMSIsImdldE9wcG9zaXRlUGxhY2VtZW50IiwibWF0Y2hlZCIsImhhc2giLCJnZXRPcHBvc2l0ZVZhcmlhdGlvblBsYWNlbWVudCIsImdldFdpbmRvd1Njcm9sbCIsInNjcm9sbExlZnQiLCJzY3JvbGxUb3AiLCJnZXRXaW5kb3dTY3JvbGxCYXJYIiwiZ2V0Vmlld3BvcnRSZWN0IiwiaHRtbCIsInZpc3VhbFZpZXdwb3J0IiwiZ2V0RG9jdW1lbnRSZWN0IiwiX2VsZW1lbnQkb3duZXJEb2N1bWVuIiwid2luU2Nyb2xsIiwic2Nyb2xsV2lkdGgiLCJzY3JvbGxIZWlnaHQiLCJpc1Njcm9sbFBhcmVudCIsIl9nZXRDb21wdXRlZFN0eWxlIiwib3ZlcmZsb3ciLCJvdmVyZmxvd1giLCJvdmVyZmxvd1kiLCJnZXRTY3JvbGxQYXJlbnQiLCJsaXN0U2Nyb2xsUGFyZW50cyIsImlzQm9keSIsInVwZGF0ZWRMaXN0IiwicmVjdFRvQ2xpZW50UmVjdCIsImdldElubmVyQm91bmRpbmdDbGllbnRSZWN0IiwiY2xpZW50VG9wIiwiY2xpZW50TGVmdCIsImdldENsaWVudFJlY3RGcm9tTWl4ZWRUeXBlIiwiY2xpcHBpbmdQYXJlbnQiLCJnZXRDbGlwcGluZ1BhcmVudHMiLCJjbGlwcGVyRWxlbWVudCIsImdldENsaXBwaW5nUmVjdCIsImJvdW5kYXJ5Iiwicm9vdEJvdW5kYXJ5IiwibWFpbkNsaXBwaW5nUGFyZW50cyIsImZpcnN0Q2xpcHBpbmdQYXJlbnQiLCJjbGlwcGluZ1JlY3QiLCJhY2NSZWN0IiwiY29tcHV0ZU9mZnNldHMiLCJjb21tb25YIiwiY29tbW9uWSIsIm1haW5BeGlzIiwiZGV0ZWN0T3ZlcmZsb3ciLCJfb3B0aW9ucyIsIl9vcHRpb25zJHBsYWNlbWVudCIsIl9vcHRpb25zJGJvdW5kYXJ5IiwiX29wdGlvbnMkcm9vdEJvdW5kYXJ5IiwiX29wdGlvbnMkZWxlbWVudENvbnRlIiwiZWxlbWVudENvbnRleHQiLCJfb3B0aW9ucyRhbHRCb3VuZGFyeSIsImFsdEJvdW5kYXJ5IiwiX29wdGlvbnMkcGFkZGluZyIsImFsdENvbnRleHQiLCJjbGlwcGluZ0NsaWVudFJlY3QiLCJjb250ZXh0RWxlbWVudCIsInJlZmVyZW5jZUNsaWVudFJlY3QiLCJwb3BwZXJDbGllbnRSZWN0IiwiZWxlbWVudENsaWVudFJlY3QiLCJvdmVyZmxvd09mZnNldHMiLCJvZmZzZXREYXRhIiwibXVsdGlwbHkiLCJjb21wdXRlQXV0b1BsYWNlbWVudCIsImZsaXBWYXJpYXRpb25zIiwiX29wdGlvbnMkYWxsb3dlZEF1dG9QIiwiYWxsb3dlZEF1dG9QbGFjZW1lbnRzIiwicGxhY2VtZW50cyQxIiwiYWxsb3dlZFBsYWNlbWVudHMiLCJvdmVyZmxvd3MiLCJzb3J0IiwiYSIsImIiLCJnZXRFeHBhbmRlZEZhbGxiYWNrUGxhY2VtZW50cyIsIm9wcG9zaXRlUGxhY2VtZW50IiwiZmxpcCIsIl9za2lwIiwiX29wdGlvbnMkbWFpbkF4aXMiLCJjaGVja01haW5BeGlzIiwiX29wdGlvbnMkYWx0QXhpcyIsImFsdEF4aXMiLCJjaGVja0FsdEF4aXMiLCJzcGVjaWZpZWRGYWxsYmFja1BsYWNlbWVudHMiLCJmYWxsYmFja1BsYWNlbWVudHMiLCJfb3B0aW9ucyRmbGlwVmFyaWF0aW8iLCJwcmVmZXJyZWRQbGFjZW1lbnQiLCJyZWZlcmVuY2VSZWN0IiwiY2hlY2tzTWFwIiwibWFrZUZhbGxiYWNrQ2hlY2tzIiwiZmlyc3RGaXR0aW5nUGxhY2VtZW50IiwiX2Jhc2VQbGFjZW1lbnQiLCJpc1N0YXJ0VmFyaWF0aW9uIiwiaXNWZXJ0aWNhbCIsIm1haW5WYXJpYXRpb25TaWRlIiwiYWx0VmFyaWF0aW9uU2lkZSIsImNoZWNrcyIsImV2ZXJ5IiwiY2hlY2siLCJfbG9vcCIsIl9pIiwiZml0dGluZ1BsYWNlbWVudCIsInJlc2V0IiwiZmxpcCQxIiwiZ2V0U2lkZU9mZnNldHMiLCJwcmV2ZW50ZWRPZmZzZXRzIiwiaXNBbnlTaWRlRnVsbHlDbGlwcGVkIiwic29tZSIsInNpZGUiLCJwcmV2ZW50T3ZlcmZsb3ciLCJyZWZlcmVuY2VPdmVyZmxvdyIsInBvcHBlckFsdE92ZXJmbG93IiwicmVmZXJlbmNlQ2xpcHBpbmdPZmZzZXRzIiwicG9wcGVyRXNjYXBlT2Zmc2V0cyIsImlzUmVmZXJlbmNlSGlkZGVuIiwiaGFzUG9wcGVyRXNjYXBlZCIsImhpZGUkMSIsImRpc3RhbmNlQW5kU2tpZGRpbmdUb1hZIiwiaW52ZXJ0RGlzdGFuY2UiLCJza2lkZGluZyIsImRpc3RhbmNlIiwiX29wdGlvbnMkb2Zmc2V0IiwiX2RhdGEkc3RhdGUkcGxhY2VtZW50Iiwib2Zmc2V0JDEiLCJwb3BwZXJPZmZzZXRzJDEiLCJnZXRBbHRBeGlzIiwiX29wdGlvbnMkdGV0aGVyIiwidGV0aGVyIiwiX29wdGlvbnMkdGV0aGVyT2Zmc2V0IiwidGV0aGVyT2Zmc2V0IiwiaXNCYXNlUGxhY2VtZW50IiwidGV0aGVyT2Zmc2V0VmFsdWUiLCJtYWluU2lkZSIsImFsdFNpZGUiLCJhZGRpdGl2ZSIsIm1pbkxlbiIsIm1heExlbiIsImFycm93UGFkZGluZ09iamVjdCIsImFycm93UGFkZGluZ01pbiIsImFycm93UGFkZGluZ01heCIsImFycm93TGVuIiwibWluT2Zmc2V0IiwibWF4T2Zmc2V0IiwiY2xpZW50T2Zmc2V0Iiwib2Zmc2V0TW9kaWZpZXJWYWx1ZSIsInRldGhlck1pbiIsInRldGhlck1heCIsInByZXZlbnRlZE9mZnNldCIsIl9tYWluU2lkZSIsIl9hbHRTaWRlIiwiX29mZnNldCIsIl9taW4iLCJfbWF4IiwiX3ByZXZlbnRlZE9mZnNldCIsInByZXZlbnRPdmVyZmxvdyQxIiwiZ2V0SFRNTEVsZW1lbnRTY3JvbGwiLCJnZXROb2RlU2Nyb2xsIiwiaXNFbGVtZW50U2NhbGVkIiwiZ2V0Q29tcG9zaXRlUmVjdCIsImVsZW1lbnRPclZpcnR1YWxFbGVtZW50IiwiaXNGaXhlZCIsImlzT2Zmc2V0UGFyZW50QW5FbGVtZW50IiwibW9kaWZpZXJzIiwidmlzaXRlZCIsInJlc3VsdCIsIm1vZGlmaWVyIiwiZGVwIiwiZGVwTW9kaWZpZXIiLCJvcmRlck1vZGlmaWVycyIsIm9yZGVyZWRNb2RpZmllcnMiLCJkZWJvdW5jZSIsInBlbmRpbmciLCJQcm9taXNlIiwicmVzb2x2ZSIsInRoZW4iLCJtZXJnZUJ5TmFtZSIsIm1lcmdlZCIsImN1cnJlbnQiLCJleGlzdGluZyIsIkRFRkFVTFRfT1BUSU9OUyIsImFyZVZhbGlkRWxlbWVudHMiLCJfbGVuIiwiYXJndW1lbnRzIiwiX2tleSIsInBvcHBlckdlbmVyYXRvciIsImdlbmVyYXRvck9wdGlvbnMiLCJfZ2VuZXJhdG9yT3B0aW9ucyIsIl9nZW5lcmF0b3JPcHRpb25zJGRlZiIsImRlZmF1bHRNb2RpZmllcnMiLCJfZ2VuZXJhdG9yT3B0aW9ucyRkZWYyIiwiZGVmYXVsdE9wdGlvbnMiLCJlZmZlY3RDbGVhbnVwRm5zIiwiaXNEZXN0cm95ZWQiLCJzZXRPcHRpb25zIiwic2V0T3B0aW9uc0FjdGlvbiIsImNsZWFudXBNb2RpZmllckVmZmVjdHMiLCJtIiwicnVuTW9kaWZpZXJFZmZlY3RzIiwiZm9yY2VVcGRhdGUiLCJfc3RhdGUkZWxlbWVudHMiLCJfc3RhdGUkb3JkZXJlZE1vZGlmaWUiLCJfc3RhdGUkb3JkZXJlZE1vZGlmaWUyIiwiZGVzdHJveSIsIl9yZWYzJG9wdGlvbnMiLCJjbGVhbnVwRm4iLCJub29wRm4iLCJvbkZpcnN0VXBkYXRlIiwiY3JlYXRlUG9wcGVyJDIiLCJjcmVhdGVQb3BwZXIkMSIsImNyZWF0ZVBvcHBlciIsIlBvcHBlciIsImZyZWV6ZSIsIl9fcHJvdG9fXyIsImNyZWF0ZVBvcHBlckJhc2UiLCJjcmVhdGVQb3BwZXJMaXRlIiwiTkFNRSQ5IiwiRVZFTlRfS0VZJDgiLCJEQVRBX0FQSV9LRVkkNCIsIkVTQ0FQRV9LRVkkMiIsIlNQQUNFX0tFWSIsIlRBQl9LRVkkMSIsIkFSUk9XX1VQX0tFWSIsIkFSUk9XX0RPV05fS0VZIiwiUklHSFRfTU9VU0VfQlVUVE9OIiwiUkVHRVhQX0tFWURPV04iLCJFVkVOVF9ISURFJDQiLCJFVkVOVF9ISURERU4kNCIsIkVWRU5UX1NIT1ckNCIsIkVWRU5UX1NIT1dOJDQiLCJFVkVOVF9DTElDS19EQVRBX0FQSSQzIiwiRVZFTlRfS0VZRE9XTl9EQVRBX0FQSSIsIkVWRU5UX0tFWVVQX0RBVEFfQVBJIiwiQ0xBU1NfTkFNRV9TSE9XJDYiLCJDTEFTU19OQU1FX0RST1BVUCIsIkNMQVNTX05BTUVfRFJPUEVORCIsIkNMQVNTX05BTUVfRFJPUFNUQVJUIiwiQ0xBU1NfTkFNRV9OQVZCQVIiLCJTRUxFQ1RPUl9EQVRBX1RPR0dMRSQzIiwiU0VMRUNUT1JfTUVOVSIsIlNFTEVDVE9SX05BVkJBUl9OQVYiLCJTRUxFQ1RPUl9WSVNJQkxFX0lURU1TIiwiUExBQ0VNRU5UX1RPUCIsIlBMQUNFTUVOVF9UT1BFTkQiLCJQTEFDRU1FTlRfQk9UVE9NIiwiUExBQ0VNRU5UX0JPVFRPTUVORCIsIlBMQUNFTUVOVF9SSUdIVCIsIlBMQUNFTUVOVF9MRUZUIiwiRGVmYXVsdCQ4IiwiZGlzcGxheSIsInBvcHBlckNvbmZpZyIsImF1dG9DbG9zZSIsIkRlZmF1bHRUeXBlJDgiLCJEcm9wZG93biIsIl9wb3BwZXIiLCJfbWVudSIsIl9nZXRNZW51RWxlbWVudCIsIl9pbk5hdmJhciIsIl9kZXRlY3ROYXZiYXIiLCJEZWZhdWx0VHlwZSIsImdldFBhcmVudEZyb21FbGVtZW50IiwiX2NyZWF0ZVBvcHBlciIsImZvY3VzIiwiX2NvbXBsZXRlSGlkZSIsInJlZmVyZW5jZUVsZW1lbnQiLCJfZ2V0UG9wcGVyQ29uZmlnIiwiaXNEaXNwbGF5U3RhdGljIiwiX2dldFBsYWNlbWVudCIsInBhcmVudERyb3Bkb3duIiwiaXNFbmQiLCJfZ2V0T2Zmc2V0IiwicG9wcGVyRGF0YSIsImRlZmF1bHRCc1BvcHBlckNvbmZpZyIsIl9zZWxlY3RNZW51SXRlbSIsIml0ZW1zIiwidG9nZ2xlcyIsImNvbnRleHQiLCJjb21wb3NlZFBhdGgiLCJpc01lbnVUYXJnZXQiLCJpc0FjdGl2ZSIsInN0b3BQcm9wYWdhdGlvbiIsImdldFRvZ2dsZUJ1dHRvbiIsImNsZWFyTWVudXMiLCJkYXRhQXBpS2V5ZG93bkhhbmRsZXIiLCJTRUxFQ1RPUl9GSVhFRF9DT05URU5UIiwiU0VMRUNUT1JfU1RJQ0tZX0NPTlRFTlQiLCJTY3JvbGxCYXJIZWxwZXIiLCJnZXRXaWR0aCIsImRvY3VtZW50V2lkdGgiLCJpbm5lcldpZHRoIiwiX2Rpc2FibGVPdmVyRmxvdyIsIl9zZXRFbGVtZW50QXR0cmlidXRlcyIsImNhbGN1bGF0ZWRWYWx1ZSIsIl9zYXZlSW5pdGlhbEF0dHJpYnV0ZSIsInN0eWxlUHJvcCIsInNjcm9sbGJhcldpZHRoIiwibWFuaXB1bGF0aW9uQ2FsbEJhY2siLCJfYXBwbHlNYW5pcHVsYXRpb25DYWxsYmFjayIsIl9yZXNldEVsZW1lbnRBdHRyaWJ1dGVzIiwiYWN0dWFsVmFsdWUiLCJyZW1vdmVQcm9wZXJ0eSIsImNhbGxCYWNrIiwiaXNPdmVyZmxvd2luZyIsIkRlZmF1bHQkNyIsImNsYXNzTmFtZSIsInJvb3RFbGVtZW50IiwiY2xpY2tDYWxsYmFjayIsIkRlZmF1bHRUeXBlJDciLCJOQU1FJDgiLCJDTEFTU19OQU1FX0ZBREUkNCIsIkNMQVNTX05BTUVfU0hPVyQ1IiwiRVZFTlRfTU9VU0VET1dOIiwiQmFja2Ryb3AiLCJfaXNBcHBlbmRlZCIsIl9hcHBlbmQiLCJfZ2V0RWxlbWVudCIsIl9lbXVsYXRlQW5pbWF0aW9uIiwiYmFja2Ryb3AiLCJjcmVhdGVFbGVtZW50IiwiYXBwZW5kIiwiRGVmYXVsdCQ2IiwidHJhcEVsZW1lbnQiLCJhdXRvZm9jdXMiLCJEZWZhdWx0VHlwZSQ2IiwiTkFNRSQ3IiwiRVZFTlRfS0VZJDciLCJFVkVOVF9GT0NVU0lOJDEiLCJFVkVOVF9LRVlET1dOX1RBQiIsIlRBQl9LRVkiLCJUQUJfTkFWX0ZPUldBUkQiLCJUQUJfTkFWX0JBQ0tXQVJEIiwiRm9jdXNUcmFwIiwiX2lzQWN0aXZlIiwiX2xhc3RUYWJOYXZEaXJlY3Rpb24iLCJhY3RpdmF0ZSIsIl9oYW5kbGVGb2N1c2luIiwiX2hhbmRsZUtleWRvd24iLCJkZWFjdGl2YXRlIiwic2hpZnRLZXkiLCJOQU1FJDYiLCJFVkVOVF9LRVkkNiIsIkVTQ0FQRV9LRVkkMSIsIkRlZmF1bHQkNSIsIkRlZmF1bHRUeXBlJDUiLCJFVkVOVF9ISURFJDMiLCJFVkVOVF9ISURFX1BSRVZFTlRFRCIsIkVWRU5UX0hJRERFTiQzIiwiRVZFTlRfU0hPVyQzIiwiRVZFTlRfU0hPV04kMyIsIkVWRU5UX1JFU0laRSIsIkVWRU5UX0NMSUNLX0RJU01JU1MiLCJFVkVOVF9LRVlET1dOX0RJU01JU1MkMSIsIkVWRU5UX01PVVNFVVBfRElTTUlTUyIsIkVWRU5UX01PVVNFRE9XTl9ESVNNSVNTIiwiRVZFTlRfQ0xJQ0tfREFUQV9BUEkkMiIsIkNMQVNTX05BTUVfT1BFTiIsIkNMQVNTX05BTUVfRkFERSQzIiwiQ0xBU1NfTkFNRV9TSE9XJDQiLCJDTEFTU19OQU1FX1NUQVRJQyIsIk9QRU5fU0VMRUNUT1IkMSIsIlNFTEVDVE9SX0RJQUxPRyIsIlNFTEVDVE9SX01PREFMX0JPRFkiLCJTRUxFQ1RPUl9EQVRBX1RPR0dMRSQyIiwiTW9kYWwiLCJfZGlhbG9nIiwiX2JhY2tkcm9wIiwiX2luaXRpYWxpemVCYWNrRHJvcCIsIl9mb2N1c3RyYXAiLCJfaW5pdGlhbGl6ZUZvY3VzVHJhcCIsIl9pZ25vcmVCYWNrZHJvcENsaWNrIiwiX3Njcm9sbEJhciIsIl9pc0FuaW1hdGVkIiwiX2FkanVzdERpYWxvZyIsIl9zZXRFc2NhcGVFdmVudCIsIl9zZXRSZXNpemVFdmVudCIsIl9zaG93QmFja2Ryb3AiLCJfc2hvd0VsZW1lbnQiLCJfaGlkZU1vZGFsIiwiaHRtbEVsZW1lbnQiLCJoYW5kbGVVcGRhdGUiLCJtb2RhbEJvZHkiLCJ0cmFuc2l0aW9uQ29tcGxldGUiLCJfdHJpZ2dlckJhY2tkcm9wVHJhbnNpdGlvbiIsIl9yZXNldEFkanVzdG1lbnRzIiwiY3VycmVudFRhcmdldCIsImlzTW9kYWxPdmVyZmxvd2luZyIsImlzQm9keU92ZXJmbG93aW5nIiwicGFkZGluZ0xlZnQiLCJwYWRkaW5nUmlnaHQiLCJzaG93RXZlbnQiLCJhbGxSZWFkeU9wZW4iLCJOQU1FJDUiLCJFVkVOVF9LRVkkNSIsIkRBVEFfQVBJX0tFWSQyIiwiRVZFTlRfTE9BRF9EQVRBX0FQSSQxIiwiRVNDQVBFX0tFWSIsIkRlZmF1bHQkNCIsIkRlZmF1bHRUeXBlJDQiLCJDTEFTU19OQU1FX1NIT1ckMyIsIkNMQVNTX05BTUVfQkFDS0RST1AiLCJPUEVOX1NFTEVDVE9SIiwiRVZFTlRfU0hPVyQyIiwiRVZFTlRfU0hPV04kMiIsIkVWRU5UX0hJREUkMiIsIkVWRU5UX0hJRERFTiQyIiwiRVZFTlRfQ0xJQ0tfREFUQV9BUEkkMSIsIkVWRU5UX0tFWURPV05fRElTTUlTUyIsIlNFTEVDVE9SX0RBVEFfVE9HR0xFJDEiLCJPZmZjYW52YXMiLCJ2aXNpYmlsaXR5IiwiYmx1ciIsImNvbXBsZXRlQ2FsbGJhY2siLCJ1cmlBdHRyaWJ1dGVzIiwiU0FGRV9VUkxfUEFUVEVSTiIsIkRBVEFfVVJMX1BBVFRFUk4iLCJhbGxvd2VkQXR0cmlidXRlIiwiYWxsb3dlZEF0dHJpYnV0ZUxpc3QiLCJhdHRyaWJ1dGVOYW1lIiwibm9kZVZhbHVlIiwicmVnRXhwIiwiYXR0cmlidXRlUmVnZXgiLCJEZWZhdWx0QWxsb3dsaXN0IiwiYXJlYSIsImJyIiwiY29sIiwiY29kZSIsImRpdiIsImVtIiwiaHIiLCJoMSIsImgyIiwiaDMiLCJoNCIsImg1IiwiaDYiLCJpbWciLCJsaSIsIm9sIiwicCIsInByZSIsInMiLCJzbWFsbCIsInNwYW4iLCJzdWIiLCJzdXAiLCJzdHJvbmciLCJ1IiwidWwiLCJzYW5pdGl6ZUh0bWwiLCJ1bnNhZmVIdG1sIiwiYWxsb3dMaXN0Iiwic2FuaXRpemVGbiIsImNyZWF0ZWREb2N1bWVudCIsIkRPTVBhcnNlciIsInBhcnNlRnJvbVN0cmluZyIsImVsZW1lbnROYW1lIiwiYXR0cmlidXRlTGlzdCIsImFsbG93ZWRBdHRyaWJ1dGVzIiwiaW5uZXJIVE1MIiwiTkFNRSQ0IiwiRVZFTlRfS0VZJDQiLCJDTEFTU19QUkVGSVgkMSIsIkRJU0FMTE9XRURfQVRUUklCVVRFUyIsIkRlZmF1bHRUeXBlJDMiLCJhbmltYXRpb24iLCJ0ZW1wbGF0ZSIsInRpdGxlIiwiZGVsYXkiLCJjdXN0b21DbGFzcyIsInNhbml0aXplIiwiQXR0YWNobWVudE1hcCIsIkFVVE8iLCJUT1AiLCJSSUdIVCIsIkJPVFRPTSIsIkxFRlQiLCJEZWZhdWx0JDMiLCJFdmVudCQyIiwiSElERSIsIkhJRERFTiIsIlNIT1ciLCJTSE9XTiIsIklOU0VSVEVEIiwiQ0xJQ0siLCJGT0NVU0lOIiwiRk9DVVNPVVQiLCJNT1VTRUVOVEVSIiwiTU9VU0VMRUFWRSIsIkNMQVNTX05BTUVfRkFERSQyIiwiQ0xBU1NfTkFNRV9TSE9XJDIiLCJIT1ZFUl9TVEFURV9TSE9XIiwiSE9WRVJfU1RBVEVfT1VUIiwiU0VMRUNUT1JfVE9PTFRJUF9JTk5FUiIsIlNFTEVDVE9SX01PREFMIiwiRVZFTlRfTU9EQUxfSElERSIsIlRSSUdHRVJfSE9WRVIiLCJUUklHR0VSX0ZPQ1VTIiwiVFJJR0dFUl9DTElDSyIsIlRSSUdHRVJfTUFOVUFMIiwiVG9vbHRpcCIsIl9pc0VuYWJsZWQiLCJfdGltZW91dCIsIl9ob3ZlclN0YXRlIiwiX2FjdGl2ZVRyaWdnZXIiLCJ0aXAiLCJfc2V0TGlzdGVuZXJzIiwiZW5hYmxlIiwiZGlzYWJsZSIsInRvZ2dsZUVuYWJsZWQiLCJfaW5pdGlhbGl6ZU9uRGVsZWdhdGVkVGFyZ2V0IiwiY2xpY2siLCJfaXNXaXRoQWN0aXZlVHJpZ2dlciIsIl9lbnRlciIsIl9sZWF2ZSIsImdldFRpcEVsZW1lbnQiLCJfaGlkZU1vZGFsSGFuZGxlciIsIl9kaXNwb3NlUG9wcGVyIiwiaXNXaXRoQ29udGVudCIsInNoYWRvd1Jvb3QiLCJpc0luVGhlRG9tIiwiZ2V0VGl0bGUiLCJ0aXBJZCIsImF0dGFjaG1lbnQiLCJfZ2V0QXR0YWNobWVudCIsIl9hZGRBdHRhY2htZW50Q2xhc3MiLCJfcmVzb2x2ZVBvc3NpYmxlRnVuY3Rpb24iLCJwcmV2SG92ZXJTdGF0ZSIsIl9jbGVhblRpcENsYXNzIiwic2V0Q29udGVudCIsIl9zYW5pdGl6ZUFuZFNldENvbnRlbnQiLCJjb250ZW50IiwidGVtcGxhdGVFbGVtZW50Iiwic2V0RWxlbWVudENvbnRlbnQiLCJ0ZXh0Q29udGVudCIsInVwZGF0ZUF0dGFjaG1lbnQiLCJfZ2V0RGVsZWdhdGVDb25maWciLCJfaGFuZGxlUG9wcGVyUGxhY2VtZW50Q2hhbmdlIiwiX2dldEJhc2ljQ2xhc3NQcmVmaXgiLCJldmVudEluIiwiZXZlbnRPdXQiLCJfZml4VGl0bGUiLCJvcmlnaW5hbFRpdGxlVHlwZSIsImRhdGFBdHRyaWJ1dGVzIiwiZGF0YUF0dHIiLCJiYXNpY0NsYXNzUHJlZml4UmVnZXgiLCJ0YWJDbGFzcyIsInRva2VuIiwidENsYXNzIiwiTkFNRSQzIiwiRVZFTlRfS0VZJDMiLCJDTEFTU19QUkVGSVgiLCJEZWZhdWx0JDIiLCJEZWZhdWx0VHlwZSQyIiwiRXZlbnQkMSIsIlNFTEVDVE9SX1RJVExFIiwiU0VMRUNUT1JfQ09OVEVOVCIsIlBvcG92ZXIiLCJfZ2V0Q29udGVudCIsIk5BTUUkMiIsIkVWRU5UX0tFWSQyIiwiRGVmYXVsdCQxIiwiRGVmYXVsdFR5cGUkMSIsIkVWRU5UX0FDVElWQVRFIiwiRVZFTlRfU0NST0xMIiwiRVZFTlRfTE9BRF9EQVRBX0FQSSIsIkNMQVNTX05BTUVfRFJPUERPV05fSVRFTSIsIkNMQVNTX05BTUVfQUNUSVZFJDEiLCJTRUxFQ1RPUl9EQVRBX1NQWSIsIlNFTEVDVE9SX05BVl9MSVNUX0dST1VQJDEiLCJTRUxFQ1RPUl9OQVZfTElOS1MiLCJTRUxFQ1RPUl9OQVZfSVRFTVMiLCJTRUxFQ1RPUl9MSVNUX0lURU1TIiwiU0VMRUNUT1JfTElOS19JVEVNUyIsIlNFTEVDVE9SX0RST1BET1dOJDEiLCJTRUxFQ1RPUl9EUk9QRE9XTl9UT0dHTEUkMSIsIk1FVEhPRF9PRkZTRVQiLCJNRVRIT0RfUE9TSVRJT04iLCJTY3JvbGxTcHkiLCJfc2Nyb2xsRWxlbWVudCIsIl9vZmZzZXRzIiwiX3RhcmdldHMiLCJfYWN0aXZlVGFyZ2V0IiwiX3Njcm9sbEhlaWdodCIsIl9wcm9jZXNzIiwicmVmcmVzaCIsImF1dG9NZXRob2QiLCJvZmZzZXRNZXRob2QiLCJvZmZzZXRCYXNlIiwiX2dldFNjcm9sbFRvcCIsIl9nZXRTY3JvbGxIZWlnaHQiLCJ0YXJnZXRTZWxlY3RvciIsInRhcmdldEJDUiIsIml0ZW0iLCJfZ2V0T2Zmc2V0SGVpZ2h0IiwiaW5uZXJIZWlnaHQiLCJtYXhTY3JvbGwiLCJfYWN0aXZhdGUiLCJfY2xlYXIiLCJxdWVyaWVzIiwibGluayIsImxpc3RHcm91cCIsIm5hdkl0ZW0iLCJzcHkiLCJOQU1FJDEiLCJFVkVOVF9LRVkkMSIsIkVWRU5UX0hJREUkMSIsIkVWRU5UX0hJRERFTiQxIiwiRVZFTlRfU0hPVyQxIiwiRVZFTlRfU0hPV04kMSIsIkVWRU5UX0NMSUNLX0RBVEFfQVBJIiwiQ0xBU1NfTkFNRV9EUk9QRE9XTl9NRU5VIiwiQ0xBU1NfTkFNRV9BQ1RJVkUiLCJDTEFTU19OQU1FX0ZBREUkMSIsIkNMQVNTX05BTUVfU0hPVyQxIiwiU0VMRUNUT1JfRFJPUERPV04iLCJTRUxFQ1RPUl9OQVZfTElTVF9HUk9VUCIsIlNFTEVDVE9SX0FDVElWRSIsIlNFTEVDVE9SX0FDVElWRV9VTCIsIlNFTEVDVE9SX0RBVEFfVE9HR0xFIiwiU0VMRUNUT1JfRFJPUERPV05fVE9HR0xFIiwiU0VMRUNUT1JfRFJPUERPV05fQUNUSVZFX0NISUxEIiwiVGFiIiwibGlzdEVsZW1lbnQiLCJpdGVtU2VsZWN0b3IiLCJoaWRlRXZlbnQiLCJhY3RpdmUiLCJpc1RyYW5zaXRpb25pbmciLCJfdHJhbnNpdGlvbkNvbXBsZXRlIiwiZHJvcGRvd25DaGlsZCIsImRyb3Bkb3duRWxlbWVudCIsImRyb3Bkb3duIiwiRVZFTlRfTU9VU0VPVkVSIiwiRVZFTlRfTU9VU0VPVVQiLCJFVkVOVF9GT0NVU0lOIiwiRVZFTlRfRk9DVVNPVVQiLCJFVkVOVF9ISURFIiwiRVZFTlRfSElEREVOIiwiRVZFTlRfU0hPVyIsIkVWRU5UX1NIT1dOIiwiQ0xBU1NfTkFNRV9GQURFIiwiQ0xBU1NfTkFNRV9ISURFIiwiQ0xBU1NfTkFNRV9TSE9XIiwiQ0xBU1NfTkFNRV9TSE9XSU5HIiwiYXV0b2hpZGUiLCJUb2FzdCIsIl9oYXNNb3VzZUludGVyYWN0aW9uIiwiX2hhc0tleWJvYXJkSW50ZXJhY3Rpb24iLCJfY2xlYXJUaW1lb3V0IiwiX21heWJlU2NoZWR1bGVIaWRlIiwiX29uSW50ZXJhY3Rpb24iLCJpc0ludGVyYWN0aW5nIiwiZmFjdG9yeSIsIl9fd2VicGFja19tb2R1bGVfY2FjaGVfXyIsIl9fd2VicGFja19yZXF1aXJlX18iLCJtb2R1bGVJZCIsImNhY2hlZE1vZHVsZSIsIl9fd2VicGFja19tb2R1bGVzX18iLCJuIiwiZ2V0dGVyIiwiX19lc01vZHVsZSIsImQiLCJkZWZpbml0aW9uIiwibyIsImVudW1lcmFibGUiLCJwcm9wIl0sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/themes/demo/assets/vendor/bootstrap/bootstrap.min.js.LICENSE.txt b/themes/demo/assets/vendor/bootstrap/bootstrap.min.js.LICENSE.txt new file mode 100644 index 0000000..0fe76a6 --- /dev/null +++ b/themes/demo/assets/vendor/bootstrap/bootstrap.min.js.LICENSE.txt @@ -0,0 +1,5 @@ +/*! + * Bootstrap v5.1.3 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ diff --git a/themes/demo/assets/vendor/bootstrap/bootstrap.scss b/themes/demo/assets/vendor/bootstrap/bootstrap.scss new file mode 100644 index 0000000..9516a91 --- /dev/null +++ b/themes/demo/assets/vendor/bootstrap/bootstrap.scss @@ -0,0 +1,75 @@ +// Override Bootstrap's Sass default variables +// +// Nearly all variables in Bootstrap are written with the `!default` flag. +// This allows you to override the default values of those variables before +// you import Bootstrap's source Sass files. +// +// Overriding the default variable values is the best way to customize your +// CSS without writing _new_ styles. For example, change you can either change +// `$body-color` or write more CSS that override's Bootstrap's CSS like so: +// `body { color: red; }`. + +// +// Bring in Bootstrap +// + +// Option 1 +// +// Import all of Bootstrap's CSS + +@import "bootstrap/scss/bootstrap"; + +/* +// Option 2 +// +// Place variable overrides first, then import just the styles you need. Note that some stylesheets are required no matter what. + +// Toggle global options +$enable-gradients: true; +$enable-shadows: true; + +// Customize some defaults +$body-color: #333; +$body-bg: #fff; +$border-radius: .4rem; +$success: #7952b3; + +@import "bootstrap/scss/functions"; // Required +@import "bootstrap/scss/variables"; // Required +@import "bootstrap/scss/mixins"; // Required + +@import "bootstrap/scss/root"; // Required +@import "bootstrap/scss/reboot"; // Required +@import "bootstrap/scss/type"; +// @import "bootstrap/scss/images"; +// @import "bootstrap/scss/code"; +@import "bootstrap/scss/grid"; +// @import "bootstrap/scss/tables"; +// @import "bootstrap/scss/forms"; +@import "bootstrap/scss/buttons"; +@import "bootstrap/scss/transitions"; +// @import "bootstrap/scss/dropdown"; +// @import "bootstrap/scss/button-group"; +// @import "bootstrap/scss/input-group"; // Requires forms +// @import "bootstrap/scss/custom-forms"; +// @import "bootstrap/scss/nav"; +// @import "bootstrap/scss/navbar"; // Requires nav +// @import "bootstrap/scss/card"; +// @import "bootstrap/scss/breadcrumb"; +// @import "bootstrap/scss/pagination"; +// @import "bootstrap/scss/badge"; +// @import "bootstrap/scss/jumbotron"; +// @import "bootstrap/scss/alert"; +// @import "bootstrap/scss/progress"; +// @import "bootstrap/scss/media"; +// @import "bootstrap/scss/list-group"; +@import "bootstrap/scss/close"; +// @import "bootstrap/scss/toasts"; +@import "bootstrap/scss/modal"; // Requires transitions +// @import "bootstrap/scss/tooltip"; +// @import "bootstrap/scss/popover"; +// @import "bootstrap/scss/carousel"; +// @import "bootstrap/scss/spinners"; +@import "bootstrap/scss/utilities"; +// @import "bootstrap/scss/print"; +*/ diff --git a/themes/demo/assets/vendor/codeblocks/codeblocks.js b/themes/demo/assets/vendor/codeblocks/codeblocks.js new file mode 100644 index 0000000..bc46c72 --- /dev/null +++ b/themes/demo/assets/vendor/codeblocks/codeblocks.js @@ -0,0 +1,50 @@ +/* + * Code Blocks + */ +import $ from 'jquery'; +import CodeMirror from 'codemirror'; +import 'codemirror/lib/codemirror.css'; +import 'codemirror/theme/twilight.css'; +import 'codemirror/mode/twig/twig'; +import 'codemirror/mode/php/php'; +import 'codemirror/mode/clike/clike'; +import 'codemirror/mode/xml/xml'; +import 'codemirror/addon/mode/multiplex'; + +$(document).on('render', function() { + $('.code-block > pre').each(function () { + if (this.dataset.disposable) { + return; + } + this.dataset.disposable = true; + + var $pre = $(this), + codeValue = $pre.text(), + language = $pre.data('language'), + modeValue; + + if (language === 'php') { + modeValue = 'text/x-php'; + } + else { + modeValue = { + name: 'twig', + base: 'text/html' + }; + } + + $pre.empty(); + + new CodeMirror(this, { + value: codeValue, + mode: modeValue, + lineNumbers: true, + readOnly: true + }); + }); + +}); + +$(document).on('click', '.expand-code', function () { + $(this).closest('.collapsed-code-block').removeClass('collapsed'); +}); diff --git a/themes/demo/assets/vendor/codeblocks/codeblocks.min.js b/themes/demo/assets/vendor/codeblocks/codeblocks.min.js new file mode 100644 index 0000000..096986f --- /dev/null +++ b/themes/demo/assets/vendor/codeblocks/codeblocks.min.js @@ -0,0 +1,2 @@ +(()=>{var e,t={830:(e,t,r)=>{"use strict";const n=jQuery;var i=r.n(n),o=r(631),a=r.n(o),l=r(379),s=r.n(l),c=r(789),u={insert:"head",singleton:!1};s()(c.Z,u);c.Z.locals;var d=r(845),f={insert:"head",singleton:!1};s()(d.Z,f);d.Z.locals;r(702),r(959),r(762),r(589),r(93);i()(document).on("render",(function(){i()(".code-block > pre").each((function(){if(!this.dataset.disposable){this.dataset.disposable=!0;var e,t=i()(this),r=t.text();e="php"===t.data("language")?"text/x-php":{name:"twig",base:"text/html"},t.empty(),new(a())(this,{value:r,mode:e,lineNumbers:!0,readOnly:!0})}}))})),i()(document).on("click",".expand-code",(function(){i()(this).closest(".collapsed-code-block").removeClass("collapsed")}))},93:(e,t,r)=>{!function(e){"use strict";e.multiplexingMode=function(t){var r=Array.prototype.slice.call(arguments,1);function n(e,t,r,n){if("string"==typeof t){var i=e.indexOf(t,r);return n&&i>-1?i+t.length:i}var o=t.exec(r?e.slice(r):e);return o?o.index+r+(n?o[0].length:0):-1}return{startState:function(){return{outer:e.startState(t),innerActive:null,inner:null,startingInner:!1}},copyState:function(r){return{outer:e.copyState(t,r.outer),innerActive:r.innerActive,inner:r.innerActive&&e.copyState(r.innerActive.mode,r.inner),startingInner:r.startingInner}},token:function(i,o){if(o.innerActive){var a=o.innerActive;if(c=i.string,!a.close&&i.sol())return o.innerActive=o.inner=null,this.token(i,o);if((d=a.close&&!o.startingInner?n(c,a.close,i.pos,a.parseDelimiters):-1)==i.pos&&!a.parseDelimiters)return i.match(a.close),o.innerActive=o.inner=null,a.delimStyle&&a.delimStyle+" "+a.delimStyle+"-close";d>-1&&(i.string=c.slice(0,d));var l=a.mode.token(i,o.inner);return d>-1?i.string=c:i.pos>i.start&&(o.startingInner=!1),d==i.pos&&a.parseDelimiters&&(o.innerActive=o.inner=null),a.innerStyle&&(l=l?l+" "+a.innerStyle:a.innerStyle),l}for(var s=1/0,c=i.string,u=0;u2),v=/Android/.test(e),y=g||v||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(e),b=g||/Mac/.test(t),w=/\bCrOS\b/.test(e),C=/win/i.test(t),x=f&&e.match(/Version\/(\d*\.\d*)/);x&&(x=Number(x[1])),x&&x>=15&&(f=!1,s=!0);var k=b&&(c||f&&(null==x||x<12.11)),A=r||a&&l>=9;function _(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}var M,S=function(e,t){var r=e.className,n=_(t).exec(r);if(n){var i=r.slice(n.index+n[0].length);e.className=r.slice(0,n.index)+(i?n[1]+i:"")}};function T(e){for(var t=e.childNodes.length;t>0;--t)e.removeChild(e.firstChild);return e}function B(e,t){return T(e).appendChild(t)}function L(e,t,r,n){var i=document.createElement(e);if(r&&(i.className=r),n&&(i.style.cssText=n),"string"==typeof t)i.appendChild(document.createTextNode(t));else if(t)for(var o=0;o=t)return a+(t-o);a+=l-o,a+=r-a%r,o=l+1}}g?F=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:a&&(F=function(e){try{e.select()}catch(e){}});var W=function(){this.id=null,this.f=null,this.time=0,this.handler=I(this.onTimeout,this)};function H(e,t){for(var r=0;r=t)return n+Math.min(a,t-i);if(i+=o-n,n=o+1,(i+=r-i%r)>=t)return n}}var $=[""];function Y(e){for(;$.length<=e;)$.push(X($)+" ");return $[e]}function X(e){return e[e.length-1]}function Z(e,t){for(var r=[],n=0;n"€"&&(e.toUpperCase()!=e.toLowerCase()||te.test(e))}function ne(e,t){return t?!!(t.source.indexOf("\\w")>-1&&re(e))||t.test(e):re(e)}function ie(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return!1;return!0}var oe=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function ae(e){return e.charCodeAt(0)>=768&&oe.test(e)}function le(e,t,r){for(;(r<0?t>0:tr?-1:1;;){if(t==r)return t;var i=(t+r)/2,o=n<0?Math.ceil(i):Math.floor(i);if(o==t)return e(o)?t:r;e(o)?r=o:t=o+n}}function ce(e,t,r,n){if(!e)return n(t,r,"ltr",0);for(var i=!1,o=0;ot||t==r&&a.to==t)&&(n(Math.max(a.from,t),Math.min(a.to,r),1==a.level?"rtl":"ltr",o),i=!0)}i||n(t,r,"ltr")}var ue=null;function de(e,t,r){var n;ue=null;for(var i=0;it)return i;o.to==t&&(o.from!=o.to&&"before"==r?n=i:ue=i),o.from==t&&(o.from!=o.to&&"before"!=r?n=i:ue=i)}return null!=n?n:ue}var fe=function(){var e="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",t="nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111";function r(r){return r<=247?e.charAt(r):1424<=r&&r<=1524?"R":1536<=r&&r<=1785?t.charAt(r-1536):1774<=r&&r<=2220?"r":8192<=r&&r<=8203?"w":8204==r?"b":"L"}var n=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,i=/[stwN]/,o=/[LRr]/,a=/[Lb1n]/,l=/[1n]/;function s(e,t,r){this.level=e,this.from=t,this.to=r}return function(e,t){var c="ltr"==t?"L":"R";if(0==e.length||"ltr"==t&&!n.test(e))return!1;for(var u=e.length,d=[],f=0;f-1&&(n[t]=i.slice(0,o).concat(i.slice(o+1)))}}}function ye(e,t){var r=ge(e,t);if(r.length)for(var n=Array.prototype.slice.call(arguments,2),i=0;i0}function xe(e){e.prototype.on=function(e,t){me(this,e,t)},e.prototype.off=function(e,t){ve(this,e,t)}}function ke(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function Ae(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function _e(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function Me(e){ke(e),Ae(e)}function Se(e){return e.target||e.srcElement}function Te(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),b&&e.ctrlKey&&1==t&&(t=3),t}var Be,Le,Ee=function(){if(a&&l<9)return!1;var e=L("div");return"draggable"in e||"dragDrop"in e}();function Ne(e){if(null==Be){var t=L("span","​");B(e,L("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(Be=t.offsetWidth<=1&&t.offsetHeight>2&&!(a&&l<8))}var r=Be?L("span","​"):L("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return r.setAttribute("cm-text",""),r}function ze(e){if(null!=Le)return Le;var t=B(e,document.createTextNode("AخA")),r=M(t,0,1).getBoundingClientRect(),n=M(t,1,2).getBoundingClientRect();return T(e),!(!r||r.left==r.right)&&(Le=n.right-r.right<3)}var Oe,De=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,r=[],n=e.length;t<=n;){var i=e.indexOf("\n",t);-1==i&&(i=e.length);var o=e.slice(t,"\r"==e.charAt(i-1)?i-1:i),a=o.indexOf("\r");-1!=a?(r.push(o.slice(0,a)),t+=a+1):(r.push(o),t=i+1)}return r}:function(e){return e.split(/\r\n?|\n/)},Fe=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(e){return!1}}:function(e){var t;try{t=e.ownerDocument.selection.createRange()}catch(e){}return!(!t||t.parentElement()!=e)&&0!=t.compareEndPoints("StartToEnd",t)},Ie="oncopy"in(Oe=L("div"))||(Oe.setAttribute("oncopy","return;"),"function"==typeof Oe.oncopy),Pe=null;function qe(e){if(null!=Pe)return Pe;var t=B(e,L("span","x")),r=t.getBoundingClientRect(),n=M(t,0,1).getBoundingClientRect();return Pe=Math.abs(r.left-n.left)>1}var We={},He={};function Re(e,t){arguments.length>2&&(t.dependencies=Array.prototype.slice.call(arguments,2)),We[e]=t}function je(e,t){He[e]=t}function Ue(e){if("string"==typeof e&&He.hasOwnProperty(e))e=He[e];else if(e&&"string"==typeof e.name&&He.hasOwnProperty(e.name)){var t=He[e.name];"string"==typeof t&&(t={name:t}),(e=ee(t,e)).name=t.name}else{if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+xml$/.test(e))return Ue("application/xml");if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+json$/.test(e))return Ue("application/json")}return"string"==typeof e?{name:e}:e||{name:"null"}}function Ke(e,t){t=Ue(t);var r=We[t.name];if(!r)return Ke(e,"text/plain");var n=r(e,t);if(Ge.hasOwnProperty(t.name)){var i=Ge[t.name];for(var o in i)i.hasOwnProperty(o)&&(n.hasOwnProperty(o)&&(n["_"+o]=n[o]),n[o]=i[o])}if(n.name=t.name,t.helperType&&(n.helperType=t.helperType),t.modeProps)for(var a in t.modeProps)n[a]=t.modeProps[a];return n}var Ge={};function Ve(e,t){P(t,Ge.hasOwnProperty(e)?Ge[e]:Ge[e]={})}function $e(e,t){if(!0===t)return t;if(e.copyState)return e.copyState(t);var r={};for(var n in t){var i=t[n];i instanceof Array&&(i=i.concat([])),r[n]=i}return r}function Ye(e,t){for(var r;e.innerMode&&(r=e.innerMode(t))&&r.mode!=e;)t=r.state,e=r.mode;return r||{mode:e,state:t}}function Xe(e,t,r){return!e.startState||e.startState(t,r)}var Ze=function(e,t,r){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=r};function Qe(e,t){if((t-=e.first)<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var r=e;!r.lines;)for(var n=0;;++n){var i=r.children[n],o=i.chunkSize();if(t=e.first&&tr?at(r,Qe(e,r).text.length):ht(t,Qe(e,t.line).text.length)}function ht(e,t){var r=e.ch;return null==r||r>t?at(e.line,t):r<0?at(e.line,0):e}function mt(e,t){for(var r=[],n=0;n=this.string.length},Ze.prototype.sol=function(){return this.pos==this.lineStart},Ze.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},Ze.prototype.next=function(){if(this.post},Ze.prototype.eatSpace=function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},Ze.prototype.skipToEnd=function(){this.pos=this.string.length},Ze.prototype.skipTo=function(e){var t=this.string.indexOf(e,this.pos);if(t>-1)return this.pos=t,!0},Ze.prototype.backUp=function(e){this.pos-=e},Ze.prototype.column=function(){return this.lastColumnPos0?null:(n&&!1!==t&&(this.pos+=n[0].length),n)}var i=function(e){return r?e.toLowerCase():e};if(i(this.string.substr(this.pos,e.length))==i(e))return!1!==t&&(this.pos+=e.length),!0},Ze.prototype.current=function(){return this.string.slice(this.start,this.pos)},Ze.prototype.hideFirstChars=function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}},Ze.prototype.lookAhead=function(e){var t=this.lineOracle;return t&&t.lookAhead(e)},Ze.prototype.baseToken=function(){var e=this.lineOracle;return e&&e.baseToken(this.pos)};var gt=function(e,t){this.state=e,this.lookAhead=t},vt=function(e,t,r,n){this.state=t,this.doc=e,this.line=r,this.maxLookAhead=n||0,this.baseTokens=null,this.baseTokenPos=1};function yt(e,t,r,n){var i=[e.state.modeGen],o={};St(e,t.text,e.doc.mode,r,(function(e,t){return i.push(e,t)}),o,n);for(var a=r.state,l=function(n){r.baseTokens=i;var l=e.state.overlays[n],s=1,c=0;r.state=!0,St(e,t.text,l.mode,r,(function(e,t){for(var r=s;ce&&i.splice(s,1,e,i[s+1],n),s+=2,c=Math.min(e,n)}if(t)if(l.opaque)i.splice(r,s-r,e,"overlay "+t),s=r+2;else for(;re.options.maxHighlightLength&&$e(e.doc.mode,n.state),o=yt(e,t,n);i&&(n.state=i),t.stateAfter=n.save(!i),t.styles=o.styles,o.classes?t.styleClasses=o.classes:t.styleClasses&&(t.styleClasses=null),r===e.doc.highlightFrontier&&(e.doc.modeFrontier=Math.max(e.doc.modeFrontier,++e.doc.highlightFrontier))}return t.styles}function wt(e,t,r){var n=e.doc,i=e.display;if(!n.mode.startState)return new vt(n,!0,t);var o=Tt(e,t,r),a=o>n.first&&Qe(n,o-1).stateAfter,l=a?vt.fromSaved(n,a,o):new vt(n,Xe(n.mode),o);return n.iter(o,t,(function(r){Ct(e,r.text,l);var n=l.line;r.stateAfter=n==t-1||n%5==0||n>=i.viewFrom&&nt.start)return o}throw new Error("Mode "+e.name+" failed to advance stream.")}vt.prototype.lookAhead=function(e){var t=this.doc.getLine(this.line+e);return null!=t&&e>this.maxLookAhead&&(this.maxLookAhead=e),t},vt.prototype.baseToken=function(e){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=e;)this.baseTokenPos+=2;var t=this.baseTokens[this.baseTokenPos+1];return{type:t&&t.replace(/( |^)overlay .*/,""),size:this.baseTokens[this.baseTokenPos]-e}},vt.prototype.nextLine=function(){this.line++,this.maxLookAhead>0&&this.maxLookAhead--},vt.fromSaved=function(e,t,r){return t instanceof gt?new vt(e,$e(e.mode,t.state),r,t.lookAhead):new vt(e,$e(e.mode,t),r)},vt.prototype.save=function(e){var t=!1!==e?$e(this.doc.mode,this.state):this.state;return this.maxLookAhead>0?new gt(t,this.maxLookAhead):t};var At=function(e,t,r){this.start=e.start,this.end=e.pos,this.string=e.current(),this.type=t||null,this.state=r};function _t(e,t,r,n){var i,o,a=e.doc,l=a.mode,s=Qe(a,(t=pt(a,t)).line),c=wt(e,t.line,r),u=new Ze(s.text,e.options.tabSize,c);for(n&&(o=[]);(n||u.pose.options.maxHighlightLength?(l=!1,a&&Ct(e,t,n,d.pos),d.pos=t.length,s=null):s=Mt(kt(r,d,n.state,f),o),f){var p=f[0].name;p&&(s="m-"+(s?p+" "+s:p))}if(!l||u!=s){for(;ca;--l){if(l<=o.first)return o.first;var s=Qe(o,l-1),c=s.stateAfter;if(c&&(!r||l+(c instanceof gt?c.lookAhead:0)<=o.modeFrontier))return l;var u=q(s.text,null,e.options.tabSize);(null==i||n>u)&&(i=l-1,n=u)}return i}function Bt(e,t){if(e.modeFrontier=Math.min(e.modeFrontier,t),!(e.highlightFrontierr;n--){var i=Qe(e,n).stateAfter;if(i&&(!(i instanceof gt)||n+i.lookAhead=t:o.to>t);(n||(n=[])).push(new Ot(a,o.from,l?null:o.to))}}return n}function qt(e,t,r){var n;if(e)for(var i=0;i=t:o.to>t)||o.from==t&&"bookmark"==a.type&&(!r||o.marker.insertLeft)){var l=null==o.from||(a.inclusiveLeft?o.from<=t:o.from0&&l)for(var b=0;b0)){var u=[s,1],d=lt(c.from,l.from),f=lt(c.to,l.to);(d<0||!a.inclusiveLeft&&!d)&&u.push({from:c.from,to:l.from}),(f>0||!a.inclusiveRight&&!f)&&u.push({from:l.to,to:c.to}),i.splice.apply(i,u),s+=u.length-3}}return i}function jt(e){var t=e.markedSpans;if(t){for(var r=0;rt)&&(!r||Vt(r,o.marker)<0)&&(r=o.marker)}return r}function Qt(e,t,r,n,i){var o=Qe(e,t),a=Et&&o.markedSpans;if(a)for(var l=0;l=0&&d<=0||u<=0&&d>=0)&&(u<=0&&(s.marker.inclusiveRight&&i.inclusiveLeft?lt(c.to,r)>=0:lt(c.to,r)>0)||u>=0&&(s.marker.inclusiveRight&&i.inclusiveLeft?lt(c.from,n)<=0:lt(c.from,n)<0)))return!0}}}function Jt(e){for(var t;t=Yt(e);)e=t.find(-1,!0).line;return e}function er(e){for(var t;t=Xt(e);)e=t.find(1,!0).line;return e}function tr(e){for(var t,r;t=Xt(e);)e=t.find(1,!0).line,(r||(r=[])).push(e);return r}function rr(e,t){var r=Qe(e,t),n=Jt(r);return r==n?t:rt(n)}function nr(e,t){if(t>e.lastLine())return t;var r,n=Qe(e,t);if(!ir(e,n))return t;for(;r=Xt(n);)n=r.find(1,!0).line;return rt(n)+1}function ir(e,t){var r=Et&&t.markedSpans;if(r)for(var n=void 0,i=0;it.maxLineLength&&(t.maxLineLength=r,t.maxLine=e)}))}var cr=function(e,t,r){this.text=e,Ut(this,t),this.height=r?r(this):1};function ur(e,t,r,n){e.text=t,e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null),null!=e.order&&(e.order=null),jt(e),Ut(e,r);var i=n?n(e):1;i!=e.height&&tt(e,i)}function dr(e){e.parent=null,jt(e)}cr.prototype.lineNo=function(){return rt(this)},xe(cr);var fr={},pr={};function hr(e,t){if(!e||/^\s*$/.test(e))return null;var r=t.addModeClass?pr:fr;return r[e]||(r[e]=e.replace(/\S+/g,"cm-$&"))}function mr(e,t){var r=E("span",null,null,s?"padding-right: .1px":null),n={pre:E("pre",[r],"CodeMirror-line"),content:r,col:0,pos:0,cm:e,trailingSpace:!1,splitSpaces:e.getOption("lineWrapping")};t.measure={};for(var i=0;i<=(t.rest?t.rest.length:0);i++){var o=i?t.rest[i-1]:t.line,a=void 0;n.pos=0,n.addToken=vr,ze(e.display.measure)&&(a=pe(o,e.doc.direction))&&(n.addToken=br(n.addToken,a)),n.map=[],Cr(o,n,bt(e,o,t!=e.display.externalMeasured&&rt(o))),o.styleClasses&&(o.styleClasses.bgClass&&(n.bgClass=D(o.styleClasses.bgClass,n.bgClass||"")),o.styleClasses.textClass&&(n.textClass=D(o.styleClasses.textClass,n.textClass||""))),0==n.map.length&&n.map.push(0,0,n.content.appendChild(Ne(e.display.measure))),0==i?(t.measure.map=n.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(n.map),(t.measure.caches||(t.measure.caches=[])).push({}))}if(s){var l=n.content.lastChild;(/\bcm-tab\b/.test(l.className)||l.querySelector&&l.querySelector(".cm-tab"))&&(n.content.className="cm-tab-wrap-hack")}return ye(e,"renderLine",e,t.line,n.pre),n.pre.className&&(n.textClass=D(n.pre.className,n.textClass||"")),n}function gr(e){var t=L("span","•","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function vr(e,t,r,n,i,o,s){if(t){var c,u=e.splitSpaces?yr(t,e.trailingSpace):t,d=e.cm.state.specialChars,f=!1;if(d.test(t)){c=document.createDocumentFragment();for(var p=0;;){d.lastIndex=p;var h=d.exec(t),m=h?h.index-p:t.length-p;if(m){var g=document.createTextNode(u.slice(p,p+m));a&&l<9?c.appendChild(L("span",[g])):c.appendChild(g),e.map.push(e.pos,e.pos+m,g),e.col+=m,e.pos+=m}if(!h)break;p+=m+1;var v=void 0;if("\t"==h[0]){var y=e.cm.options.tabSize,b=y-e.col%y;(v=c.appendChild(L("span",Y(b),"cm-tab"))).setAttribute("role","presentation"),v.setAttribute("cm-text","\t"),e.col+=b}else"\r"==h[0]||"\n"==h[0]?((v=c.appendChild(L("span","\r"==h[0]?"␍":"␤","cm-invalidchar"))).setAttribute("cm-text",h[0]),e.col+=1):((v=e.cm.options.specialCharPlaceholder(h[0])).setAttribute("cm-text",h[0]),a&&l<9?c.appendChild(L("span",[v])):c.appendChild(v),e.col+=1);e.map.push(e.pos,e.pos+1,v),e.pos++}}else e.col+=t.length,c=document.createTextNode(u),e.map.push(e.pos,e.pos+t.length,c),a&&l<9&&(f=!0),e.pos+=t.length;if(e.trailingSpace=32==u.charCodeAt(t.length-1),r||n||i||f||o||s){var w=r||"";n&&(w+=n),i&&(w+=i);var C=L("span",[c],w,o);if(s)for(var x in s)s.hasOwnProperty(x)&&"style"!=x&&"class"!=x&&C.setAttribute(x,s[x]);return e.content.appendChild(C)}e.content.appendChild(c)}}function yr(e,t){if(e.length>1&&!/ /.test(e))return e;for(var r=t,n="",i=0;ic&&d.from<=c);f++);if(d.to>=u)return e(r,n,i,o,a,l,s);e(r,n.slice(0,d.to-c),i,o,null,l,s),o=null,n=n.slice(d.to-c),c=d.to}}}function wr(e,t,r,n){var i=!n&&r.widgetNode;i&&e.map.push(e.pos,e.pos+t,i),!n&&e.cm.display.input.needsContentAttribute&&(i||(i=e.content.appendChild(document.createElement("span"))),i.setAttribute("cm-marker",r.id)),i&&(e.cm.display.input.setUneditable(i),e.content.appendChild(i)),e.pos+=t,e.trailingSpace=!1}function Cr(e,t,r){var n=e.markedSpans,i=e.text,o=0;if(n)for(var a,l,s,c,u,d,f,p=i.length,h=0,m=1,g="",v=0;;){if(v==h){s=c=u=l="",f=null,d=null,v=1/0;for(var y=[],b=void 0,w=0;wh||x.collapsed&&C.to==h&&C.from==h)){if(null!=C.to&&C.to!=h&&v>C.to&&(v=C.to,c=""),x.className&&(s+=" "+x.className),x.css&&(l=(l?l+";":"")+x.css),x.startStyle&&C.from==h&&(u+=" "+x.startStyle),x.endStyle&&C.to==v&&(b||(b=[])).push(x.endStyle,C.to),x.title&&((f||(f={})).title=x.title),x.attributes)for(var k in x.attributes)(f||(f={}))[k]=x.attributes[k];x.collapsed&&(!d||Vt(d.marker,x)<0)&&(d=C)}else C.from>h&&v>C.from&&(v=C.from)}if(b)for(var A=0;A=p)break;for(var M=Math.min(p,v);;){if(g){var S=h+g.length;if(!d){var T=S>M?g.slice(0,M-h):g;t.addToken(t,T,a?a+s:s,u,h+T.length==v?c:"",l,f)}if(S>=M){g=g.slice(M-h),h=M;break}h=S,u=""}g=i.slice(o,o=r[m++]),a=hr(r[m++],t.cm.options)}}else for(var B=1;B2&&o.push((s.bottom+c.top)/2-r.top)}}o.push(r.bottom-r.top)}}function Qr(e,t,r){if(e.line==t)return{map:e.measure.map,cache:e.measure.cache};if(e.rest){for(var n=0;nr)return{map:e.measure.maps[i],cache:e.measure.caches[i],before:!0}}}function Jr(e,t){var r=rt(t=Jt(t)),n=e.display.externalMeasured=new xr(e.doc,t,r);n.lineN=r;var i=n.built=mr(e,n);return n.text=i.pre,B(e.display.lineMeasure,i.pre),n}function en(e,t,r,n){return nn(e,rn(e,t),r,n)}function tn(e,t){if(t>=e.display.viewFrom&&t=r.lineN&&tt)&&(i=(o=s-l)-1,t>=s&&(a="right")),null!=i){if(n=e[c+2],l==s&&r==(n.insertLeft?"left":"right")&&(a=r),"left"==r&&0==i)for(;c&&e[c-2]==e[c-3]&&e[c-1].insertLeft;)n=e[2+(c-=3)],a="left";if("right"==r&&i==s-l)for(;c=0&&(r=e[i]).left==r.right;i--);return r}function cn(e,t,r,n){var i,o=ln(t.map,r,n),s=o.node,c=o.start,u=o.end,d=o.collapse;if(3==s.nodeType){for(var f=0;f<4;f++){for(;c&&ae(t.line.text.charAt(o.coverStart+c));)--c;for(;o.coverStart+u0&&(d=n="right"),i=e.options.lineWrapping&&(p=s.getClientRects()).length>1?p["right"==n?p.length-1:0]:s.getBoundingClientRect()}if(a&&l<9&&!c&&(!i||!i.left&&!i.right)){var h=s.parentNode.getClientRects()[0];i=h?{left:h.left,right:h.left+En(e.display),top:h.top,bottom:h.bottom}:an}for(var m=i.top-t.rect.top,g=i.bottom-t.rect.top,v=(m+g)/2,y=t.view.measure.heights,b=0;b=n.text.length?(s=n.text.length,c="before"):s<=0&&(s=0,c="after"),!l)return a("before"==c?s-1:s,"before"==c);function u(e,t,r){return a(r?e-1:e,1==l[t].level!=r)}var d=de(l,s,c),f=ue,p=u(s,d,"before"==c);return null!=f&&(p.other=u(s,f,"before"!=c)),p}function Cn(e,t){var r=0;t=pt(e.doc,t),e.options.lineWrapping||(r=En(e.display)*t.ch);var n=Qe(e.doc,t.line),i=ar(n)+Kr(e.display);return{left:r,right:r,top:i,bottom:i+n.height}}function xn(e,t,r,n,i){var o=at(e,t,r);return o.xRel=i,n&&(o.outside=n),o}function kn(e,t,r){var n=e.doc;if((r+=e.display.viewOffset)<0)return xn(n.first,0,null,-1,-1);var i=nt(n,r),o=n.first+n.size-1;if(i>o)return xn(n.first+n.size-1,Qe(n,o).text.length,null,1,1);t<0&&(t=0);for(var a=Qe(n,i);;){var l=Sn(e,a,i,t,r),s=Zt(a,l.ch+(l.xRel>0||l.outside>0?1:0));if(!s)return l;var c=s.find(1);if(c.line==i)return c;a=Qe(n,i=c.line)}}function An(e,t,r,n){n-=gn(t);var i=t.text.length,o=se((function(t){return nn(e,r,t-1).bottom<=n}),i,0);return{begin:o,end:i=se((function(t){return nn(e,r,t).top>n}),o,i)}}function _n(e,t,r,n){return r||(r=rn(e,t)),An(e,t,r,vn(e,t,nn(e,r,n),"line").top)}function Mn(e,t,r,n){return!(e.bottom<=r)&&(e.top>r||(n?e.left:e.right)>t)}function Sn(e,t,r,n,i){i-=ar(t);var o=rn(e,t),a=gn(t),l=0,s=t.text.length,c=!0,u=pe(t,e.doc.direction);if(u){var d=(e.options.lineWrapping?Bn:Tn)(e,t,r,o,u,n,i);l=(c=1!=d.level)?d.from:d.to-1,s=c?d.to:d.from-1}var f,p,h=null,m=null,g=se((function(t){var r=nn(e,o,t);return r.top+=a,r.bottom+=a,!!Mn(r,n,i,!1)&&(r.top<=i&&r.left<=n&&(h=t,m=r),!0)}),l,s),v=!1;if(m){var y=n-m.left=w.bottom?1:0}return xn(r,g=le(t.text,g,1),p,v,n-f)}function Tn(e,t,r,n,i,o,a){var l=se((function(l){var s=i[l],c=1!=s.level;return Mn(wn(e,at(r,c?s.to:s.from,c?"before":"after"),"line",t,n),o,a,!0)}),0,i.length-1),s=i[l];if(l>0){var c=1!=s.level,u=wn(e,at(r,c?s.from:s.to,c?"after":"before"),"line",t,n);Mn(u,o,a,!0)&&u.top>a&&(s=i[l-1])}return s}function Bn(e,t,r,n,i,o,a){var l=An(e,t,n,a),s=l.begin,c=l.end;/\s/.test(t.text.charAt(c-1))&&c--;for(var u=null,d=null,f=0;f=c||p.to<=s)){var h=nn(e,n,1!=p.level?Math.min(c,p.to)-1:Math.max(s,p.from)).right,m=hm)&&(u=p,d=m)}}return u||(u=i[i.length-1]),u.fromc&&(u={from:u.from,to:c,level:u.level}),u}function Ln(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==on){on=L("pre",null,"CodeMirror-line-like");for(var t=0;t<49;++t)on.appendChild(document.createTextNode("x")),on.appendChild(L("br"));on.appendChild(document.createTextNode("x"))}B(e.measure,on);var r=on.offsetHeight/50;return r>3&&(e.cachedTextHeight=r),T(e.measure),r||1}function En(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=L("span","xxxxxxxxxx"),r=L("pre",[t],"CodeMirror-line-like");B(e.measure,r);var n=t.getBoundingClientRect(),i=(n.right-n.left)/10;return i>2&&(e.cachedCharWidth=i),i||10}function Nn(e){for(var t=e.display,r={},n={},i=t.gutters.clientLeft,o=t.gutters.firstChild,a=0;o;o=o.nextSibling,++a){var l=e.display.gutterSpecs[a].className;r[l]=o.offsetLeft+o.clientLeft+i,n[l]=o.clientWidth}return{fixedPos:zn(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:r,gutterWidth:n,wrapperWidth:t.wrapper.clientWidth}}function zn(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function On(e){var t=Ln(e.display),r=e.options.lineWrapping,n=r&&Math.max(5,e.display.scroller.clientWidth/En(e.display)-3);return function(i){if(ir(e.doc,i))return 0;var o=0;if(i.widgets)for(var a=0;a0&&(s=Qe(e.doc,c.line).text).length==c.ch){var u=q(s,s.length,e.options.tabSize)-s.length;c=at(c.line,Math.max(0,Math.round((o-Vr(e.display).left)/En(e.display))-u))}return c}function In(e,t){if(t>=e.display.viewTo)return null;if((t-=e.display.viewFrom)<0)return null;for(var r=e.display.view,n=0;nt)&&(i.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=i.viewTo)Et&&rr(e.doc,t)i.viewFrom?Wn(e):(i.viewFrom+=n,i.viewTo+=n);else if(t<=i.viewFrom&&r>=i.viewTo)Wn(e);else if(t<=i.viewFrom){var o=Hn(e,r,r+n,1);o?(i.view=i.view.slice(o.index),i.viewFrom=o.lineN,i.viewTo+=n):Wn(e)}else if(r>=i.viewTo){var a=Hn(e,t,t,-1);a?(i.view=i.view.slice(0,a.index),i.viewTo=a.lineN):Wn(e)}else{var l=Hn(e,t,t,-1),s=Hn(e,r,r+n,1);l&&s?(i.view=i.view.slice(0,l.index).concat(kr(e,l.lineN,s.lineN)).concat(i.view.slice(s.index)),i.viewTo+=n):Wn(e)}var c=i.externalMeasured;c&&(r=i.lineN&&t=n.viewTo)){var o=n.view[In(e,t)];if(null!=o.node){var a=o.changes||(o.changes=[]);-1==H(a,r)&&a.push(r)}}}function Wn(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function Hn(e,t,r,n){var i,o=In(e,t),a=e.display.view;if(!Et||r==e.doc.first+e.doc.size)return{index:o,lineN:r};for(var l=e.display.viewFrom,s=0;s0){if(o==a.length-1)return null;i=l+a[o].size-t,o++}else i=l-t;t+=i,r+=i}for(;rr(e.doc,r)!=r;){if(o==(n<0?0:a.length-1))return null;r+=n*a[o-(n<0?1:0)].size,o+=n}return{index:o,lineN:r}}function Rn(e,t,r){var n=e.display;0==n.view.length||t>=n.viewTo||r<=n.viewFrom?(n.view=kr(e,t,r),n.viewFrom=t):(n.viewFrom>t?n.view=kr(e,t,n.viewFrom).concat(n.view):n.viewFromr&&(n.view=n.view.slice(0,In(e,r)))),n.viewTo=r}function jn(e){for(var t=e.display.view,r=0,n=0;n=e.display.viewTo||s.to().line0?a:e.defaultCharWidth())+"px"}if(n.other){var l=r.appendChild(L("div"," ","CodeMirror-cursor CodeMirror-secondarycursor"));l.style.display="",l.style.left=n.other.left+"px",l.style.top=n.other.top+"px",l.style.height=.85*(n.other.bottom-n.other.top)+"px"}}function Vn(e,t){return e.top-t.top||e.left-t.left}function $n(e,t,r){var n=e.display,i=e.doc,o=document.createDocumentFragment(),a=Vr(e.display),l=a.left,s=Math.max(n.sizerWidth,Yr(e)-n.sizer.offsetLeft)-a.right,c="ltr"==i.direction;function u(e,t,r,n){t<0&&(t=0),t=Math.round(t),n=Math.round(n),o.appendChild(L("div",null,"CodeMirror-selected","position: absolute; left: "+e+"px;\n top: "+t+"px; width: "+(null==r?s-e:r)+"px;\n height: "+(n-t)+"px"))}function d(t,r,n){var o,a,d=Qe(i,t),f=d.text.length;function p(r,n){return bn(e,at(t,r),"div",d,n)}function h(t,r,n){var i=_n(e,d,null,t),o="ltr"==r==("after"==n)?"left":"right";return p("after"==n?i.begin:i.end-(/\s/.test(d.text.charAt(i.end-1))?2:1),o)[o]}var m=pe(d,i.direction);return ce(m,r||0,null==n?f:n,(function(e,t,i,d){var g="ltr"==i,v=p(e,g?"left":"right"),y=p(t-1,g?"right":"left"),b=null==r&&0==e,w=null==n&&t==f,C=0==d,x=!m||d==m.length-1;if(y.top-v.top<=3){var k=(c?w:b)&&x,A=(c?b:w)&&C?l:(g?v:y).left,_=k?s:(g?y:v).right;u(A,v.top,_-A,v.bottom)}else{var M,S,T,B;g?(M=c&&b&&C?l:v.left,S=c?s:h(e,i,"before"),T=c?l:h(t,i,"after"),B=c&&w&&x?s:y.right):(M=c?h(e,i,"before"):l,S=!c&&b&&C?s:v.right,T=!c&&w&&x?l:y.left,B=c?h(t,i,"after"):s),u(M,v.top,S-M,v.bottom),v.bottom0?t.blinker=setInterval((function(){e.hasFocus()||Jn(e),t.cursorDiv.style.visibility=(r=!r)?"":"hidden"}),e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden")}}function Xn(e){e.hasFocus()||(e.display.input.focus(),e.state.focused||Qn(e))}function Zn(e){e.state.delayingBlurEvent=!0,setTimeout((function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,e.state.focused&&Jn(e))}),100)}function Qn(e,t){e.state.delayingBlurEvent&&!e.state.draggingText&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(ye(e,"focus",e,t),e.state.focused=!0,O(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),s&&setTimeout((function(){return e.display.input.reset(!0)}),20)),e.display.input.receivedFocus()),Yn(e))}function Jn(e,t){e.state.delayingBlurEvent||(e.state.focused&&(ye(e,"blur",e,t),e.state.focused=!1,S(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout((function(){e.state.focused||(e.display.shift=!1)}),150))}function ei(e){for(var t=e.display,r=t.lineDiv.offsetTop,n=Math.max(0,t.scroller.getBoundingClientRect().top),i=t.lineDiv.getBoundingClientRect().top,o=0,s=0;s.005||m<-.005)&&(ie.display.sizerWidth){var v=Math.ceil(f/En(e.display));v>e.display.maxLineLength&&(e.display.maxLineLength=v,e.display.maxLine=c.line,e.display.maxLineChanged=!0)}}}Math.abs(o)>2&&(t.scroller.scrollTop+=o)}function ti(e){if(e.widgets)for(var t=0;t=a&&(o=nt(t,ar(Qe(t,s))-e.wrapper.clientHeight),a=s)}return{from:o,to:Math.max(a,o+1)}}function ni(e,t){if(!be(e,"scrollCursorIntoView")){var r=e.display,n=r.sizer.getBoundingClientRect(),i=null;if(t.top+n.top<0?i=!0:t.bottom+n.top>(window.innerHeight||document.documentElement.clientHeight)&&(i=!1),null!=i&&!m){var o=L("div","​",null,"position: absolute;\n top: "+(t.top-r.viewOffset-Kr(e.display))+"px;\n height: "+(t.bottom-t.top+$r(e)+r.barHeight)+"px;\n left: "+t.left+"px; width: "+Math.max(2,t.right-t.left)+"px;");e.display.lineSpace.appendChild(o),o.scrollIntoView(i),e.display.lineSpace.removeChild(o)}}}function ii(e,t,r,n){var i;null==n&&(n=0),e.options.lineWrapping||t!=r||(r="before"==t.sticky?at(t.line,t.ch+1,"before"):t,t=t.ch?at(t.line,"before"==t.sticky?t.ch-1:t.ch,"after"):t);for(var o=0;o<5;o++){var a=!1,l=wn(e,t),s=r&&r!=t?wn(e,r):l,c=ai(e,i={left:Math.min(l.left,s.left),top:Math.min(l.top,s.top)-n,right:Math.max(l.left,s.left),bottom:Math.max(l.bottom,s.bottom)+n}),u=e.doc.scrollTop,d=e.doc.scrollLeft;if(null!=c.scrollTop&&(pi(e,c.scrollTop),Math.abs(e.doc.scrollTop-u)>1&&(a=!0)),null!=c.scrollLeft&&(mi(e,c.scrollLeft),Math.abs(e.doc.scrollLeft-d)>1&&(a=!0)),!a)break}return i}function oi(e,t){var r=ai(e,t);null!=r.scrollTop&&pi(e,r.scrollTop),null!=r.scrollLeft&&mi(e,r.scrollLeft)}function ai(e,t){var r=e.display,n=Ln(e.display);t.top<0&&(t.top=0);var i=e.curOp&&null!=e.curOp.scrollTop?e.curOp.scrollTop:r.scroller.scrollTop,o=Xr(e),a={};t.bottom-t.top>o&&(t.bottom=t.top+o);var l=e.doc.height+Gr(r),s=t.topl-n;if(t.topi+o){var u=Math.min(t.top,(c?l:t.bottom)-o);u!=i&&(a.scrollTop=u)}var d=e.options.fixedGutter?0:r.gutters.offsetWidth,f=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:r.scroller.scrollLeft-d,p=Yr(e)-r.gutters.offsetWidth,h=t.right-t.left>p;return h&&(t.right=t.left+p),t.left<10?a.scrollLeft=0:t.leftp+f-3&&(a.scrollLeft=t.right+(h?0:10)-p),a}function li(e,t){null!=t&&(di(e),e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+t)}function si(e){di(e);var t=e.getCursor();e.curOp.scrollToPos={from:t,to:t,margin:e.options.cursorScrollMargin}}function ci(e,t,r){null==t&&null==r||di(e),null!=t&&(e.curOp.scrollLeft=t),null!=r&&(e.curOp.scrollTop=r)}function ui(e,t){di(e),e.curOp.scrollToPos=t}function di(e){var t=e.curOp.scrollToPos;t&&(e.curOp.scrollToPos=null,fi(e,Cn(e,t.from),Cn(e,t.to),t.margin))}function fi(e,t,r,n){var i=ai(e,{left:Math.min(t.left,r.left),top:Math.min(t.top,r.top)-n,right:Math.max(t.right,r.right),bottom:Math.max(t.bottom,r.bottom)+n});ci(e,i.scrollLeft,i.scrollTop)}function pi(e,t){Math.abs(e.doc.scrollTop-t)<2||(r||Ui(e,{top:t}),hi(e,t,!0),r&&Ui(e),Fi(e,100))}function hi(e,t,r){t=Math.max(0,Math.min(e.display.scroller.scrollHeight-e.display.scroller.clientHeight,t)),(e.display.scroller.scrollTop!=t||r)&&(e.doc.scrollTop=t,e.display.scrollbars.setScrollTop(t),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t))}function mi(e,t,r,n){t=Math.max(0,Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth)),(r?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)&&!n||(e.doc.scrollLeft=t,$i(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function gi(e){var t=e.display,r=t.gutters.offsetWidth,n=Math.round(e.doc.height+Gr(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?r:0,docHeight:n,scrollHeight:n+$r(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:r}}var vi=function(e,t,r){this.cm=r;var n=this.vert=L("div",[L("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),i=this.horiz=L("div",[L("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");n.tabIndex=i.tabIndex=-1,e(n),e(i),me(n,"scroll",(function(){n.clientHeight&&t(n.scrollTop,"vertical")})),me(i,"scroll",(function(){i.clientWidth&&t(i.scrollLeft,"horizontal")})),this.checkedZeroWidth=!1,a&&l<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")};vi.prototype.update=function(e){var t=e.scrollWidth>e.clientWidth+1,r=e.scrollHeight>e.clientHeight+1,n=e.nativeBarWidth;if(r){this.vert.style.display="block",this.vert.style.bottom=t?n+"px":"0";var i=e.viewHeight-(t?n:0);this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+i)+"px"}else this.vert.scrollTop=0,this.vert.style.display="",this.vert.firstChild.style.height="0";if(t){this.horiz.style.display="block",this.horiz.style.right=r?n+"px":"0",this.horiz.style.left=e.barLeft+"px";var o=e.viewWidth-e.barLeft-(r?n:0);this.horiz.firstChild.style.width=Math.max(0,e.scrollWidth-e.clientWidth+o)+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedZeroWidth&&e.clientHeight>0&&(0==n&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:r?n:0,bottom:t?n:0}},vi.prototype.setScrollLeft=function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},vi.prototype.setScrollTop=function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert")},vi.prototype.zeroWidthHack=function(){var e=b&&!h?"12px":"18px";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new W,this.disableVert=new W},vi.prototype.enableZeroWidthBar=function(e,t,r){function n(){var i=e.getBoundingClientRect();("vert"==r?document.elementFromPoint(i.right-1,(i.top+i.bottom)/2):document.elementFromPoint((i.right+i.left)/2,i.bottom-1))!=e?e.style.pointerEvents="none":t.set(1e3,n)}e.style.pointerEvents="auto",t.set(1e3,n)},vi.prototype.clear=function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)};var yi=function(){};function bi(e,t){t||(t=gi(e));var r=e.display.barWidth,n=e.display.barHeight;wi(e,t);for(var i=0;i<4&&r!=e.display.barWidth||n!=e.display.barHeight;i++)r!=e.display.barWidth&&e.options.lineWrapping&&ei(e),wi(e,gi(e)),r=e.display.barWidth,n=e.display.barHeight}function wi(e,t){var r=e.display,n=r.scrollbars.update(t);r.sizer.style.paddingRight=(r.barWidth=n.right)+"px",r.sizer.style.paddingBottom=(r.barHeight=n.bottom)+"px",r.heightForcer.style.borderBottom=n.bottom+"px solid transparent",n.right&&n.bottom?(r.scrollbarFiller.style.display="block",r.scrollbarFiller.style.height=n.bottom+"px",r.scrollbarFiller.style.width=n.right+"px"):r.scrollbarFiller.style.display="",n.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(r.gutterFiller.style.display="block",r.gutterFiller.style.height=n.bottom+"px",r.gutterFiller.style.width=t.gutterWidth+"px"):r.gutterFiller.style.display=""}yi.prototype.update=function(){return{bottom:0,right:0}},yi.prototype.setScrollLeft=function(){},yi.prototype.setScrollTop=function(){},yi.prototype.clear=function(){};var Ci={native:vi,null:yi};function xi(e){e.display.scrollbars&&(e.display.scrollbars.clear(),e.display.scrollbars.addClass&&S(e.display.wrapper,e.display.scrollbars.addClass)),e.display.scrollbars=new Ci[e.options.scrollbarStyle]((function(t){e.display.wrapper.insertBefore(t,e.display.scrollbarFiller),me(t,"mousedown",(function(){e.state.focused&&setTimeout((function(){return e.display.input.focus()}),0)})),t.setAttribute("cm-not-content","true")}),(function(t,r){"horizontal"==r?mi(e,t):pi(e,t)}),e),e.display.scrollbars.addClass&&O(e.display.wrapper,e.display.scrollbars.addClass)}var ki=0;function Ai(e){e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++ki,markArrays:null},_r(e.curOp)}function _i(e){var t=e.curOp;t&&Sr(t,(function(e){for(var t=0;t=r.viewTo)||r.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new Pi(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}function Ti(e){e.updatedDisplay=e.mustUpdate&&Ri(e.cm,e.update)}function Bi(e){var t=e.cm,r=t.display;e.updatedDisplay&&ei(t),e.barMeasure=gi(t),r.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=en(t,r.maxLine,r.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(r.scroller.clientWidth,r.sizer.offsetLeft+e.adjustWidthTo+$r(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,r.sizer.offsetLeft+e.adjustWidthTo-Yr(t))),(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=r.input.prepareSelection())}function Li(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft=e.display.viewTo)){var r=+new Date+e.options.workTime,n=wt(e,t.highlightFrontier),i=[];t.iter(n.line,Math.min(t.first+t.size,e.display.viewTo+500),(function(o){if(n.line>=e.display.viewFrom){var a=o.styles,l=o.text.length>e.options.maxHighlightLength?$e(t.mode,n.state):null,s=yt(e,o,n,!0);l&&(n.state=l),o.styles=s.styles;var c=o.styleClasses,u=s.classes;u?o.styleClasses=u:c&&(o.styleClasses=null);for(var d=!a||a.length!=o.styles.length||c!=u&&(!c||!u||c.bgClass!=u.bgClass||c.textClass!=u.textClass),f=0;!d&&fr)return Fi(e,e.options.workDelay),!0})),t.highlightFrontier=n.line,t.modeFrontier=Math.max(t.modeFrontier,n.line),i.length&&Ni(e,(function(){for(var t=0;t=r.viewFrom&&t.visible.to<=r.viewTo&&(null==r.updateLineNumbers||r.updateLineNumbers>=r.viewTo)&&r.renderedView==r.view&&0==jn(e))return!1;Yi(e)&&(Wn(e),t.dims=Nn(e));var i=n.first+n.size,o=Math.max(t.visible.from-e.options.viewportMargin,n.first),a=Math.min(i,t.visible.to+e.options.viewportMargin);r.viewFroma&&r.viewTo-a<20&&(a=Math.min(i,r.viewTo)),Et&&(o=rr(e.doc,o),a=nr(e.doc,a));var l=o!=r.viewFrom||a!=r.viewTo||r.lastWrapHeight!=t.wrapperHeight||r.lastWrapWidth!=t.wrapperWidth;Rn(e,o,a),r.viewOffset=ar(Qe(e.doc,r.viewFrom)),e.display.mover.style.top=r.viewOffset+"px";var s=jn(e);if(!l&&0==s&&!t.force&&r.renderedView==r.view&&(null==r.updateLineNumbers||r.updateLineNumbers>=r.viewTo))return!1;var c=Wi(e);return s>4&&(r.lineDiv.style.display="none"),Ki(e,r.updateLineNumbers,t.dims),s>4&&(r.lineDiv.style.display=""),r.renderedView=r.view,Hi(c),T(r.cursorDiv),T(r.selectionDiv),r.gutters.style.height=r.sizer.style.minHeight=0,l&&(r.lastWrapHeight=t.wrapperHeight,r.lastWrapWidth=t.wrapperWidth,Fi(e,400)),r.updateLineNumbers=null,!0}function ji(e,t){for(var r=t.viewport,n=!0;;n=!1){if(n&&e.options.lineWrapping&&t.oldDisplayWidth!=Yr(e))n&&(t.visible=ri(e.display,e.doc,r));else if(r&&null!=r.top&&(r={top:Math.min(e.doc.height+Gr(e.display)-Xr(e),r.top)}),t.visible=ri(e.display,e.doc,r),t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)break;if(!Ri(e,t))break;ei(e);var i=gi(e);Un(e),bi(e,i),Vi(e,i),t.force=!1}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function Ui(e,t){var r=new Pi(e,t);if(Ri(e,r)){ei(e),ji(e,r);var n=gi(e);Un(e),bi(e,n),Vi(e,n),r.finish()}}function Ki(e,t,r){var n=e.display,i=e.options.lineNumbers,o=n.lineDiv,a=o.firstChild;function l(t){var r=t.nextSibling;return s&&b&&e.display.currentWheelTarget==t?t.style.display="none":t.parentNode.removeChild(t),r}for(var c=n.view,u=n.viewFrom,d=0;d-1&&(p=!1),Er(e,f,u,r)),p&&(T(f.lineNumber),f.lineNumber.appendChild(document.createTextNode(ot(e.options,u)))),a=f.node.nextSibling}else{var h=qr(e,f,u,r);o.insertBefore(h,a)}u+=f.size}for(;a;)a=l(a)}function Gi(e){var t=e.gutters.offsetWidth;e.sizer.style.marginLeft=t+"px",Br(e,"gutterChanged",e)}function Vi(e,t){e.display.sizer.style.minHeight=t.docHeight+"px",e.display.heightForcer.style.top=t.docHeight+"px",e.display.gutters.style.height=t.docHeight+e.display.barHeight+$r(e)+"px"}function $i(e){var t=e.display,r=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var n=zn(t)-t.scroller.scrollLeft+e.doc.scrollLeft,i=t.gutters.offsetWidth,o=n+"px",a=0;a=102&&(null==e.display.chromeScrollHack?e.display.sizer.style.pointerEvents="none":clearTimeout(e.display.chromeScrollHack),e.display.chromeScrollHack=setTimeout((function(){e.display.chromeScrollHack=null,e.display.sizer.style.pointerEvents=""}),100));var n=ro(t),i=n.x,o=n.y,a=to;0===t.deltaMode&&(i=t.deltaX,o=t.deltaY,a=1);var l=e.display,c=l.scroller,p=c.scrollWidth>c.clientWidth,h=c.scrollHeight>c.clientHeight;if(i&&p||o&&h){if(o&&b&&s)e:for(var m=t.target,g=l.view;m!=c;m=m.parentNode)for(var v=0;v=0&<(e,n.to())<=0)return r}return-1};var ao=function(e,t){this.anchor=e,this.head=t};function lo(e,t,r){var n=e&&e.options.selectionsMayTouch,i=t[r];t.sort((function(e,t){return lt(e.from(),t.from())})),r=H(t,i);for(var o=1;o0:s>=0){var c=dt(l.from(),a.from()),u=ut(l.to(),a.to()),d=l.empty()?a.from()==a.head:l.from()==l.head;o<=r&&--r,t.splice(--o,2,new ao(d?u:c,d?c:u))}}return new oo(t,r)}function so(e,t){return new oo([new ao(e,t||e)],0)}function co(e){return e.text?at(e.from.line+e.text.length-1,X(e.text).length+(1==e.text.length?e.from.ch:0)):e.to}function uo(e,t){if(lt(e,t.from)<0)return e;if(lt(e,t.to)<=0)return co(t);var r=e.line+t.text.length-(t.to.line-t.from.line)-1,n=e.ch;return e.line==t.to.line&&(n+=co(t).ch-t.to.ch),at(r,n)}function fo(e,t){for(var r=[],n=0;n1&&e.remove(l.line+1,h-1),e.insert(l.line+1,v)}Br(e,"change",e,t)}function bo(e,t,r){function n(e,i,o){if(e.linked)for(var a=0;a1&&!e.done[e.done.length-2].ranges?(e.done.pop(),X(e.done)):void 0}function So(e,t,r,n){var i=e.history;i.undone.length=0;var o,a,l=+new Date;if((i.lastOp==n||i.lastOrigin==t.origin&&t.origin&&("+"==t.origin.charAt(0)&&i.lastModTime>l-(e.cm?e.cm.options.historyEventDelay:500)||"*"==t.origin.charAt(0)))&&(o=Mo(i,i.lastOp==n)))a=X(o.changes),0==lt(t.from,t.to)&&0==lt(t.from,a.to)?a.to=co(t):o.changes.push(Ao(e,t));else{var s=X(i.done);for(s&&s.ranges||Lo(e.sel,i.done),o={changes:[Ao(e,t)],generation:i.generation},i.done.push(o);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(r),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=l,i.lastOp=i.lastSelOp=n,i.lastOrigin=i.lastSelOrigin=t.origin,a||ye(e,"historyAdded")}function To(e,t,r,n){var i=t.charAt(0);return"*"==i||"+"==i&&r.ranges.length==n.ranges.length&&r.somethingSelected()==n.somethingSelected()&&new Date-e.history.lastSelTime<=(e.cm?e.cm.options.historyEventDelay:500)}function Bo(e,t,r,n){var i=e.history,o=n&&n.origin;r==i.lastSelOp||o&&i.lastSelOrigin==o&&(i.lastModTime==i.lastSelTime&&i.lastOrigin==o||To(e,o,X(i.done),t))?i.done[i.done.length-1]=t:Lo(t,i.done),i.lastSelTime=+new Date,i.lastSelOrigin=o,i.lastSelOp=r,n&&!1!==n.clearRedo&&_o(i.undone)}function Lo(e,t){var r=X(t);r&&r.ranges&&r.equals(e)||t.push(e)}function Eo(e,t,r,n){var i=t["spans_"+e.id],o=0;e.iter(Math.max(e.first,r),Math.min(e.first+e.size,n),(function(r){r.markedSpans&&((i||(i=t["spans_"+e.id]={}))[o]=r.markedSpans),++o}))}function No(e){if(!e)return null;for(var t,r=0;r-1&&(X(l)[d]=c[d],delete c[d])}}}return n}function Fo(e,t,r,n){if(n){var i=e.anchor;if(r){var o=lt(t,i)<0;o!=lt(r,i)<0?(i=t,t=r):o!=lt(t,r)<0&&(t=r)}return new ao(i,t)}return new ao(r||t,t)}function Io(e,t,r,n,i){null==i&&(i=e.cm&&(e.cm.display.shift||e.extend)),jo(e,new oo([Fo(e.sel.primary(),t,r,i)],0),n)}function Po(e,t,r){for(var n=[],i=e.cm&&(e.cm.display.shift||e.extend),o=0;o=t.ch:l.to>t.ch))){if(i&&(ye(s,"beforeCursorEnter"),s.explicitlyCleared)){if(o.markedSpans){--a;continue}break}if(!s.atomic)continue;if(r){var d=s.find(n<0?1:-1),f=void 0;if((n<0?u:c)&&(d=Xo(e,d,-n,d&&d.line==t.line?o:null)),d&&d.line==t.line&&(f=lt(d,r))&&(n<0?f<0:f>0))return $o(e,d,t,n,i)}var p=s.find(n<0?-1:1);return(n<0?c:u)&&(p=Xo(e,p,n,p.line==t.line?o:null)),p?$o(e,p,t,n,i):null}}return t}function Yo(e,t,r,n,i){var o=n||1,a=$o(e,t,r,o,i)||!i&&$o(e,t,r,o,!0)||$o(e,t,r,-o,i)||!i&&$o(e,t,r,-o,!0);return a||(e.cantEdit=!0,at(e.first,0))}function Xo(e,t,r,n){return r<0&&0==t.ch?t.line>e.first?pt(e,at(t.line-1)):null:r>0&&t.ch==(n||Qe(e,t.line)).text.length?t.line=0;--i)ea(e,{from:n[i].from,to:n[i].to,text:i?[""]:t.text,origin:t.origin});else ea(e,t)}}function ea(e,t){if(1!=t.text.length||""!=t.text[0]||0!=lt(t.from,t.to)){var r=fo(e,t);So(e,t,r,e.cm?e.cm.curOp.id:NaN),na(e,t,r,Wt(e,t));var n=[];bo(e,(function(e,r){r||-1!=H(n,e.history)||(sa(e.history,t),n.push(e.history)),na(e,t,null,Wt(e,t))}))}}function ta(e,t,r){var n=e.cm&&e.cm.state.suppressEdits;if(!n||r){for(var i,o=e.history,a=e.sel,l="undo"==t?o.done:o.undone,s="undo"==t?o.undone:o.done,c=0;c=0;--p){var h=f(p);if(h)return h.v}}}}function ra(e,t){if(0!=t&&(e.first+=t,e.sel=new oo(Z(e.sel.ranges,(function(e){return new ao(at(e.anchor.line+t,e.anchor.ch),at(e.head.line+t,e.head.ch))})),e.sel.primIndex),e.cm)){Pn(e.cm,e.first,e.first-t,t);for(var r=e.cm.display,n=r.viewFrom;ne.lastLine())){if(t.from.lineo&&(t={from:t.from,to:at(o,Qe(e,o).text.length),text:[t.text[0]],origin:t.origin}),t.removed=Je(e,t.from,t.to),r||(r=fo(e,t)),e.cm?ia(e.cm,t,n):yo(e,t,n),Uo(e,r,U),e.cantEdit&&Yo(e,at(e.firstLine(),0))&&(e.cantEdit=!1)}}function ia(e,t,r){var n=e.doc,i=e.display,o=t.from,a=t.to,l=!1,s=o.line;e.options.lineWrapping||(s=rt(Jt(Qe(n,o.line))),n.iter(s,a.line+1,(function(e){if(e==i.maxLine)return l=!0,!0}))),n.sel.contains(t.from,t.to)>-1&&we(e),yo(n,t,r,On(e)),e.options.lineWrapping||(n.iter(s,o.line+t.text.length,(function(e){var t=lr(e);t>i.maxLineLength&&(i.maxLine=e,i.maxLineLength=t,i.maxLineChanged=!0,l=!1)})),l&&(e.curOp.updateMaxLine=!0)),Bt(n,o.line),Fi(e,400);var c=t.text.length-(a.line-o.line)-1;t.full?Pn(e):o.line!=a.line||1!=t.text.length||vo(e.doc,t)?Pn(e,o.line,a.line+1,c):qn(e,o.line,"text");var u=Ce(e,"changes"),d=Ce(e,"change");if(d||u){var f={from:o,to:a,text:t.text,removed:t.removed,origin:t.origin};d&&Br(e,"change",e,f),u&&(e.curOp.changeObjs||(e.curOp.changeObjs=[])).push(f)}e.display.selForContextMenu=null}function oa(e,t,r,n,i){var o;n||(n=r),lt(n,r)<0&&(r=(o=[n,r])[0],n=o[1]),"string"==typeof t&&(t=e.splitLines(t)),Jo(e,{from:r,to:n,text:t,origin:i})}function aa(e,t,r,n){r1||!(this.children[0]instanceof ua))){var l=[];this.collapse(l),this.children=[new ua(l)],this.children[0].parent=this}},collapse:function(e){for(var t=0;t50){for(var a=i.lines.length%25+25,l=a;l10);e.parent.maybeSpill()}},iterN:function(e,t,r){for(var n=0;n0||0==a&&!1!==o.clearWhenEmpty)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=E("span",[o.replacedWith],"CodeMirror-widget"),n.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),n.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(Qt(e,t.line,t,r,o)||t.line!=r.line&&Qt(e,r.line,t,r,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");zt()}o.addToHistory&&So(e,{from:t,to:r,origin:"markText"},e.sel,NaN);var l,s=t.line,c=e.cm;if(e.iter(s,r.line+1,(function(n){c&&o.collapsed&&!c.options.lineWrapping&&Jt(n)==c.display.maxLine&&(l=!0),o.collapsed&&s!=t.line&&tt(n,0),It(n,new Ot(o,s==t.line?t.ch:null,s==r.line?r.ch:null),e.cm&&e.cm.curOp),++s})),o.collapsed&&e.iter(t.line,r.line+1,(function(t){ir(e,t)&&tt(t,0)})),o.clearOnEnter&&me(o,"beforeCursorEnter",(function(){return o.clear()})),o.readOnly&&(Nt(),(e.history.done.length||e.history.undone.length)&&e.clearHistory()),o.collapsed&&(o.id=++ma,o.atomic=!0),c){if(l&&(c.curOp.updateMaxLine=!0),o.collapsed)Pn(c,t.line,r.line+1);else if(o.className||o.startStyle||o.endStyle||o.css||o.attributes||o.title)for(var u=t.line;u<=r.line;u++)qn(c,u,"text");o.atomic&&Go(c.doc),Br(c,"markerAdded",c,o)}return o}ga.prototype.clear=function(){if(!this.explicitlyCleared){var e=this.doc.cm,t=e&&!e.curOp;if(t&&Ai(e),Ce(this,"clear")){var r=this.find();r&&Br(this,"clear",r.from,r.to)}for(var n=null,i=null,o=0;oe.display.maxLineLength&&(e.display.maxLine=c,e.display.maxLineLength=u,e.display.maxLineChanged=!0)}null!=n&&e&&this.collapsed&&Pn(e,n,i+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,e&&Go(e.doc)),e&&Br(e,"markerCleared",e,this,n,i),t&&_i(e),this.parent&&this.parent.clear()}},ga.prototype.find=function(e,t){var r,n;null==e&&"bookmark"==this.type&&(e=1);for(var i=0;i=0;s--)Jo(this,n[s]);l?Ro(this,l):this.cm&&si(this.cm)})),undo:Di((function(){ta(this,"undo")})),redo:Di((function(){ta(this,"redo")})),undoSelection:Di((function(){ta(this,"undo",!0)})),redoSelection:Di((function(){ta(this,"redo",!0)})),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,r=0,n=0;n=e.ch)&&t.push(i.marker.parent||i.marker)}return t},findMarks:function(e,t,r){e=pt(this,e),t=pt(this,t);var n=[],i=e.line;return this.iter(e.line,t.line+1,(function(o){var a=o.markedSpans;if(a)for(var l=0;l=s.to||null==s.from&&i!=e.line||null!=s.from&&i==t.line&&s.from>=t.ch||r&&!r(s.marker)||n.push(s.marker.parent||s.marker)}++i})),n},getAllMarks:function(){var e=[];return this.iter((function(t){var r=t.markedSpans;if(r)for(var n=0;ne)return t=e,!0;e-=o,++r})),pt(this,at(r,t))},indexFromPos:function(e){var t=(e=pt(this,e)).ch;if(e.linet&&(t=e.from),null!=e.to&&e.to-1)return t.state.draggingText(e),void setTimeout((function(){return t.display.input.focus()}),20);try{var d=e.dataTransfer.getData("Text");if(d){var f;if(t.state.draggingText&&!t.state.draggingText.copy&&(f=t.listSelections()),Uo(t.doc,so(r,r)),f)for(var p=0;p=0;t--)oa(e.doc,"",n[t].from,n[t].to,"+delete");si(e)}))}function $a(e,t,r){var n=le(e.text,t+r,r);return n<0||n>e.text.length?null:n}function Ya(e,t,r){var n=$a(e,t.ch,r);return null==n?null:new at(t.line,n,r<0?"after":"before")}function Xa(e,t,r,n,i){if(e){"rtl"==t.doc.direction&&(i=-i);var o=pe(r,t.doc.direction);if(o){var a,l=i<0?X(o):o[0],s=i<0==(1==l.level)?"after":"before";if(l.level>0||"rtl"==t.doc.direction){var c=rn(t,r);a=i<0?r.text.length-1:0;var u=nn(t,c,a).top;a=se((function(e){return nn(t,c,e).top==u}),i<0==(1==l.level)?l.from:l.to-1,a),"before"==s&&(a=$a(r,a,1))}else a=i<0?l.to:l.from;return new at(n,a,s)}}return new at(n,i<0?r.text.length:0,i<0?"before":"after")}function Za(e,t,r,n){var i=pe(t,e.doc.direction);if(!i)return Ya(t,r,n);r.ch>=t.text.length?(r.ch=t.text.length,r.sticky="before"):r.ch<=0&&(r.ch=0,r.sticky="after");var o=de(i,r.ch,r.sticky),a=i[o];if("ltr"==e.doc.direction&&a.level%2==0&&(n>0?a.to>r.ch:a.from=a.from&&f>=u.begin)){var p=d?"before":"after";return new at(r.line,f,p)}}var h=function(e,t,n){for(var o=function(e,t){return t?new at(r.line,s(e,1),"before"):new at(r.line,e,"after")};e>=0&&e0==(1!=a.level),c=l?n.begin:s(n.end,-1);if(a.from<=c&&c0?u.end:s(u.begin,-1);return null==g||n>0&&g==t.text.length||!(m=h(n>0?0:i.length-1,n,c(g)))?null:m}qa.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},qa.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},qa.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars","Ctrl-O":"openLine"},qa.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},qa.default=b?qa.macDefault:qa.pcDefault;var Qa={selectAll:Zo,singleSelection:function(e){return e.setSelection(e.getCursor("anchor"),e.getCursor("head"),U)},killLine:function(e){return Va(e,(function(t){if(t.empty()){var r=Qe(e.doc,t.head.line).text.length;return t.head.ch==r&&t.head.line0)i=new at(i.line,i.ch+1),e.replaceRange(o.charAt(i.ch-1)+o.charAt(i.ch-2),at(i.line,i.ch-2),i,"+transpose");else if(i.line>e.doc.first){var a=Qe(e.doc,i.line-1).text;a&&(i=new at(i.line,1),e.replaceRange(o.charAt(0)+e.doc.lineSeparator()+a.charAt(a.length-1),at(i.line-1,a.length-1),i,"+transpose"))}r.push(new ao(i,i))}e.setSelections(r)}))},newlineAndIndent:function(e){return Ni(e,(function(){for(var t=e.listSelections(),r=t.length-1;r>=0;r--)e.replaceRange(e.doc.lineSeparator(),t[r].anchor,t[r].head,"+input");t=e.listSelections();for(var n=0;n-1&&(lt((i=l.ranges[i]).from(),t)<0||t.xRel>0)&&(lt(i.to(),t)>0||t.xRel<0)?kl(e,n,t,o):_l(e,n,t,o)}function kl(e,t,r,n){var i=e.display,o=!1,c=zi(e,(function(t){s&&(i.scroller.draggable=!1),e.state.draggingText=!1,e.state.delayingBlurEvent&&(e.hasFocus()?e.state.delayingBlurEvent=!1:Zn(e)),ve(i.wrapper.ownerDocument,"mouseup",c),ve(i.wrapper.ownerDocument,"mousemove",u),ve(i.scroller,"dragstart",d),ve(i.scroller,"drop",c),o||(ke(t),n.addNew||Io(e.doc,r,null,null,n.extend),s&&!p||a&&9==l?setTimeout((function(){i.wrapper.ownerDocument.body.focus({preventScroll:!0}),i.input.focus()}),20):i.input.focus())})),u=function(e){o=o||Math.abs(t.clientX-e.clientX)+Math.abs(t.clientY-e.clientY)>=10},d=function(){return o=!0};s&&(i.scroller.draggable=!0),e.state.draggingText=c,c.copy=!n.moveOnDrag,me(i.wrapper.ownerDocument,"mouseup",c),me(i.wrapper.ownerDocument,"mousemove",u),me(i.scroller,"dragstart",d),me(i.scroller,"drop",c),e.state.delayingBlurEvent=!0,setTimeout((function(){return i.input.focus()}),20),i.scroller.dragDrop&&i.scroller.dragDrop()}function Al(e,t,r){if("char"==r)return new ao(t,t);if("word"==r)return e.findWordAt(t);if("line"==r)return new ao(at(t.line,0),pt(e.doc,at(t.line+1,0)));var n=r(e,t);return new ao(n.from,n.to)}function _l(e,t,r,n){a&&Zn(e);var i=e.display,o=e.doc;ke(t);var l,s,c=o.sel,u=c.ranges;if(n.addNew&&!n.extend?(s=o.sel.contains(r),l=s>-1?u[s]:new ao(r,r)):(l=o.sel.primary(),s=o.sel.primIndex),"rectangle"==n.unit)n.addNew||(l=new ao(r,r)),r=Fn(e,t,!0,!0),s=-1;else{var d=Al(e,r,n.unit);l=n.extend?Fo(l,d.anchor,d.head,n.extend):d}n.addNew?-1==s?(s=u.length,jo(o,lo(e,u.concat([l]),s),{scroll:!1,origin:"*mouse"})):u.length>1&&u[s].empty()&&"char"==n.unit&&!n.extend?(jo(o,lo(e,u.slice(0,s).concat(u.slice(s+1)),0),{scroll:!1,origin:"*mouse"}),c=o.sel):qo(o,s,l,K):(s=0,jo(o,new oo([l],0),K),c=o.sel);var f=r;function p(t){if(0!=lt(f,t))if(f=t,"rectangle"==n.unit){for(var i=[],a=e.options.tabSize,u=q(Qe(o,r.line).text,r.ch,a),d=q(Qe(o,t.line).text,t.ch,a),p=Math.min(u,d),h=Math.max(u,d),m=Math.min(r.line,t.line),g=Math.min(e.lastLine(),Math.max(r.line,t.line));m<=g;m++){var v=Qe(o,m).text,y=V(v,p,a);p==h?i.push(new ao(at(m,y),at(m,y))):v.length>y&&i.push(new ao(at(m,y),at(m,V(v,h,a))))}i.length||i.push(new ao(r,r)),jo(o,lo(e,c.ranges.slice(0,s).concat(i),s),{origin:"*mouse",scroll:!1}),e.scrollIntoView(t)}else{var b,w=l,C=Al(e,t,n.unit),x=w.anchor;lt(C.anchor,x)>0?(b=C.head,x=dt(w.from(),C.anchor)):(b=C.anchor,x=ut(w.to(),C.head));var k=c.ranges.slice(0);k[s]=Ml(e,new ao(pt(o,x),b)),jo(o,lo(e,k,s),K)}}var h=i.wrapper.getBoundingClientRect(),m=0;function g(t){var r=++m,a=Fn(e,t,!0,"rectangle"==n.unit);if(a)if(0!=lt(a,f)){e.curOp.focus=z(),p(a);var l=ri(i,o);(a.line>=l.to||a.lineh.bottom?20:0;s&&setTimeout(zi(e,(function(){m==r&&(i.scroller.scrollTop+=s,g(t))})),50)}}function v(t){e.state.selectingText=!1,m=1/0,t&&(ke(t),i.input.focus()),ve(i.wrapper.ownerDocument,"mousemove",y),ve(i.wrapper.ownerDocument,"mouseup",b),o.history.lastSelOrigin=null}var y=zi(e,(function(e){0!==e.buttons&&Te(e)?g(e):v(e)})),b=zi(e,v);e.state.selectingText=b,me(i.wrapper.ownerDocument,"mousemove",y),me(i.wrapper.ownerDocument,"mouseup",b)}function Ml(e,t){var r=t.anchor,n=t.head,i=Qe(e.doc,r.line);if(0==lt(r,n)&&r.sticky==n.sticky)return t;var o=pe(i);if(!o)return t;var a=de(o,r.ch,r.sticky),l=o[a];if(l.from!=r.ch&&l.to!=r.ch)return t;var s,c=a+(l.from==r.ch==(1!=l.level)?0:1);if(0==c||c==o.length)return t;if(n.line!=r.line)s=(n.line-r.line)*("ltr"==e.doc.direction?1:-1)>0;else{var u=de(o,n.ch,n.sticky),d=u-a||(n.ch-r.ch)*(1==l.level?-1:1);s=u==c-1||u==c?d<0:d>0}var f=o[c+(s?-1:0)],p=s==(1==f.level),h=p?f.from:f.to,m=p?"after":"before";return r.ch==h&&r.sticky==m?t:new ao(new at(r.line,h,m),n)}function Sl(e,t,r,n){var i,o;if(t.touches)i=t.touches[0].clientX,o=t.touches[0].clientY;else try{i=t.clientX,o=t.clientY}catch(e){return!1}if(i>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;n&&ke(t);var a=e.display,l=a.lineDiv.getBoundingClientRect();if(o>l.bottom||!Ce(e,r))return _e(t);o-=l.top-a.viewOffset;for(var s=0;s=i)return ye(e,r,e,nt(e.doc,o),e.display.gutterSpecs[s].className,t),_e(t)}}function Tl(e,t){return Sl(e,t,"gutterClick",!0)}function Bl(e,t){Ur(e.display,t)||Ll(e,t)||be(e,t,"contextmenu")||A||e.display.input.onContextMenu(t)}function Ll(e,t){return!!Ce(e,"gutterContextMenu")&&Sl(e,t,"gutterContextMenu",!1)}function El(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),pn(e)}vl.prototype.compare=function(e,t,r){return this.time+gl>e&&0==lt(t,this.pos)&&r==this.button};var Nl={toString:function(){return"CodeMirror.Init"}},zl={},Ol={};function Dl(e){var t=e.optionHandlers;function r(r,n,i,o){e.defaults[r]=n,i&&(t[r]=o?function(e,t,r){r!=Nl&&i(e,t,r)}:i)}e.defineOption=r,e.Init=Nl,r("value","",(function(e,t){return e.setValue(t)}),!0),r("mode",null,(function(e,t){e.doc.modeOption=t,mo(e)}),!0),r("indentUnit",2,mo,!0),r("indentWithTabs",!1),r("smartIndent",!0),r("tabSize",4,(function(e){go(e),pn(e),Pn(e)}),!0),r("lineSeparator",null,(function(e,t){if(e.doc.lineSep=t,t){var r=[],n=e.doc.first;e.doc.iter((function(e){for(var i=0;;){var o=e.text.indexOf(t,i);if(-1==o)break;i=o+t.length,r.push(at(n,o))}n++}));for(var i=r.length-1;i>=0;i--)oa(e.doc,t,r[i],at(r[i].line,r[i].ch+t.length))}})),r("specialChars",/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g,(function(e,t,r){e.state.specialChars=new RegExp(t.source+(t.test("\t")?"":"|\t"),"g"),r!=Nl&&e.refresh()})),r("specialCharPlaceholder",gr,(function(e){return e.refresh()}),!0),r("electricChars",!0),r("inputStyle",y?"contenteditable":"textarea",(function(){throw new Error("inputStyle can not (yet) be changed in a running editor")}),!0),r("spellcheck",!1,(function(e,t){return e.getInputField().spellcheck=t}),!0),r("autocorrect",!1,(function(e,t){return e.getInputField().autocorrect=t}),!0),r("autocapitalize",!1,(function(e,t){return e.getInputField().autocapitalize=t}),!0),r("rtlMoveVisually",!C),r("wholeLineUpdateBefore",!0),r("theme","default",(function(e){El(e),Qi(e)}),!0),r("keyMap","default",(function(e,t,r){var n=Ga(t),i=r!=Nl&&Ga(r);i&&i.detach&&i.detach(e,n),n.attach&&n.attach(e,i||null)})),r("extraKeys",null),r("configureMouse",null),r("lineWrapping",!1,Il,!0),r("gutters",[],(function(e,t){e.display.gutterSpecs=Xi(t,e.options.lineNumbers),Qi(e)}),!0),r("fixedGutter",!0,(function(e,t){e.display.gutters.style.left=t?zn(e.display)+"px":"0",e.refresh()}),!0),r("coverGutterNextToScrollbar",!1,(function(e){return bi(e)}),!0),r("scrollbarStyle","native",(function(e){xi(e),bi(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)}),!0),r("lineNumbers",!1,(function(e,t){e.display.gutterSpecs=Xi(e.options.gutters,t),Qi(e)}),!0),r("firstLineNumber",1,Qi,!0),r("lineNumberFormatter",(function(e){return e}),Qi,!0),r("showCursorWhenSelecting",!1,Un,!0),r("resetSelectionOnContextMenu",!0),r("lineWiseCopyCut",!0),r("pasteLinesPerSelection",!0),r("selectionsMayTouch",!1),r("readOnly",!1,(function(e,t){"nocursor"==t&&(Jn(e),e.display.input.blur()),e.display.input.readOnlyChanged(t)})),r("screenReaderLabel",null,(function(e,t){t=""===t?null:t,e.display.input.screenReaderLabelChanged(t)})),r("disableInput",!1,(function(e,t){t||e.display.input.reset()}),!0),r("dragDrop",!0,Fl),r("allowDropFileTypes",null),r("cursorBlinkRate",530),r("cursorScrollMargin",0),r("cursorHeight",1,Un,!0),r("singleCursorHeightPerLine",!0,Un,!0),r("workTime",100),r("workDelay",100),r("flattenSpans",!0,go,!0),r("addModeClass",!1,go,!0),r("pollInterval",100),r("undoDepth",200,(function(e,t){return e.doc.history.undoDepth=t})),r("historyEventDelay",1250),r("viewportMargin",10,(function(e){return e.refresh()}),!0),r("maxHighlightLength",1e4,go,!0),r("moveInputWithCursor",!0,(function(e,t){t||e.display.input.resetPosition()})),r("tabindex",null,(function(e,t){return e.display.input.getField().tabIndex=t||""})),r("autofocus",null),r("direction","ltr",(function(e,t){return e.doc.setDirection(t)}),!0),r("phrases",null)}function Fl(e,t,r){if(!t!=!(r&&r!=Nl)){var n=e.display.dragFunctions,i=t?me:ve;i(e.display.scroller,"dragstart",n.start),i(e.display.scroller,"dragenter",n.enter),i(e.display.scroller,"dragover",n.over),i(e.display.scroller,"dragleave",n.leave),i(e.display.scroller,"drop",n.drop)}}function Il(e){e.options.lineWrapping?(O(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(S(e.display.wrapper,"CodeMirror-wrap"),sr(e)),Dn(e),Pn(e),pn(e),setTimeout((function(){return bi(e)}),100)}function Pl(e,t){var r=this;if(!(this instanceof Pl))return new Pl(e,t);this.options=t=t?P(t):{},P(zl,t,!1);var n=t.value;"string"==typeof n?n=new Aa(n,t.mode,null,t.lineSeparator,t.direction):t.mode&&(n.modeOption=t.mode),this.doc=n;var i=new Pl.inputStyles[t.inputStyle](this),o=this.display=new Ji(e,n,i,t);for(var c in o.wrapper.CodeMirror=this,El(this),t.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),xi(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:-1,cutIncoming:-1,selectingText:!1,draggingText:!1,highlight:new W,keySeq:null,specialChars:null},t.autofocus&&!y&&o.input.focus(),a&&l<11&&setTimeout((function(){return r.display.input.reset(!0)}),20),ql(this),Na(),Ai(this),this.curOp.forceUpdate=!0,wo(this,n),t.autofocus&&!y||this.hasFocus()?setTimeout((function(){r.hasFocus()&&!r.state.focused&&Qn(r)}),20):Jn(this),Ol)Ol.hasOwnProperty(c)&&Ol[c](this,t[c],Nl);Yi(this),t.finishInit&&t.finishInit(this);for(var u=0;u400}me(t.scroller,"touchstart",(function(i){if(!be(e,i)&&!o(i)&&!Tl(e,i)){t.input.ensurePolled(),clearTimeout(r);var a=+new Date;t.activeTouch={start:a,moved:!1,prev:a-n.end<=300?n:null},1==i.touches.length&&(t.activeTouch.left=i.touches[0].pageX,t.activeTouch.top=i.touches[0].pageY)}})),me(t.scroller,"touchmove",(function(){t.activeTouch&&(t.activeTouch.moved=!0)})),me(t.scroller,"touchend",(function(r){var n=t.activeTouch;if(n&&!Ur(t,r)&&null!=n.left&&!n.moved&&new Date-n.start<300){var o,a=e.coordsChar(t.activeTouch,"page");o=!n.prev||s(n,n.prev)?new ao(a,a):!n.prev.prev||s(n,n.prev.prev)?e.findWordAt(a):new ao(at(a.line,0),pt(e.doc,at(a.line+1,0))),e.setSelection(o.anchor,o.head),e.focus(),ke(r)}i()})),me(t.scroller,"touchcancel",i),me(t.scroller,"scroll",(function(){t.scroller.clientHeight&&(pi(e,t.scroller.scrollTop),mi(e,t.scroller.scrollLeft,!0),ye(e,"scroll",e))})),me(t.scroller,"mousewheel",(function(t){return io(e,t)})),me(t.scroller,"DOMMouseScroll",(function(t){return io(e,t)})),me(t.wrapper,"scroll",(function(){return t.wrapper.scrollTop=t.wrapper.scrollLeft=0})),t.dragFunctions={enter:function(t){be(e,t)||Me(t)},over:function(t){be(e,t)||(Ta(e,t),Me(t))},start:function(t){return Sa(e,t)},drop:zi(e,Ma),leave:function(t){be(e,t)||Ba(e)}};var c=t.input.getField();me(c,"keyup",(function(t){return fl.call(e,t)})),me(c,"keydown",zi(e,ul)),me(c,"keypress",zi(e,pl)),me(c,"focus",(function(t){return Qn(e,t)})),me(c,"blur",(function(t){return Jn(e,t)}))}Pl.defaults=zl,Pl.optionHandlers=Ol;var Wl=[];function Hl(e,t,r,n){var i,o=e.doc;null==r&&(r="add"),"smart"==r&&(o.mode.indent?i=wt(e,t).state:r="prev");var a=e.options.tabSize,l=Qe(o,t),s=q(l.text,null,a);l.stateAfter&&(l.stateAfter=null);var c,u=l.text.match(/^\s*/)[0];if(n||/\S/.test(l.text)){if("smart"==r&&((c=o.mode.indent(i,l.text.slice(u.length),l.text))==j||c>150)){if(!n)return;r="prev"}}else c=0,r="not";"prev"==r?c=t>o.first?q(Qe(o,t-1).text,null,a):0:"add"==r?c=s+e.options.indentUnit:"subtract"==r?c=s-e.options.indentUnit:"number"==typeof r&&(c=s+r),c=Math.max(0,c);var d="",f=0;if(e.options.indentWithTabs)for(var p=Math.floor(c/a);p;--p)f+=a,d+="\t";if(fa,s=De(t),c=null;if(l&&n.ranges.length>1)if(Rl&&Rl.text.join("\n")==t){if(n.ranges.length%Rl.text.length==0){c=[];for(var u=0;u=0;f--){var p=n.ranges[f],h=p.from(),m=p.to();p.empty()&&(r&&r>0?h=at(h.line,h.ch-r):e.state.overwrite&&!l?m=at(m.line,Math.min(Qe(o,m.line).text.length,m.ch+X(s).length)):l&&Rl&&Rl.lineWise&&Rl.text.join("\n")==s.join("\n")&&(h=m=at(h.line,0)));var g={from:h,to:m,text:c?c[f%c.length]:s,origin:i||(l?"paste":e.state.cutIncoming>a?"cut":"+input")};Jo(e.doc,g),Br(e,"inputRead",e,g)}t&&!l&&Gl(e,t),si(e),e.curOp.updateInput<2&&(e.curOp.updateInput=d),e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=-1}function Kl(e,t){var r=e.clipboardData&&e.clipboardData.getData("Text");if(r)return e.preventDefault(),t.isReadOnly()||t.options.disableInput||!t.hasFocus()||Ni(t,(function(){return Ul(t,r,0,null,"paste")})),!0}function Gl(e,t){if(e.options.electricChars&&e.options.smartIndent)for(var r=e.doc.sel,n=r.ranges.length-1;n>=0;n--){var i=r.ranges[n];if(!(i.head.ch>100||n&&r.ranges[n-1].head.line==i.head.line)){var o=e.getModeAt(i.head),a=!1;if(o.electricChars){for(var l=0;l-1){a=Hl(e,i.head.line,"smart");break}}else o.electricInput&&o.electricInput.test(Qe(e.doc,i.head.line).text.slice(0,i.head.ch))&&(a=Hl(e,i.head.line,"smart"));a&&Br(e,"electricInput",e,i.head.line)}}}function Vl(e){for(var t=[],r=[],n=0;nr&&(Hl(this,i.head.line,e,!0),r=i.head.line,n==this.doc.sel.primIndex&&si(this));else{var o=i.from(),a=i.to(),l=Math.max(r,o.line);r=Math.min(this.lastLine(),a.line-(a.ch?0:1))+1;for(var s=l;s0&&qo(this.doc,n,new ao(o,c[n].to()),U)}}})),getTokenAt:function(e,t){return _t(this,e,t)},getLineTokens:function(e,t){return _t(this,at(e),t,!0)},getTokenTypeAt:function(e){e=pt(this.doc,e);var t,r=bt(this,Qe(this.doc,e.line)),n=0,i=(r.length-1)/2,o=e.ch;if(0==o)t=r[2];else for(;;){var a=n+i>>1;if((a?r[2*a-1]:0)>=o)i=a;else{if(!(r[2*a+1]o&&(e=o,i=!0),n=Qe(this.doc,e)}else n=e;return vn(this,n,{top:0,left:0},t||"page",r||i).top+(i?this.doc.height-ar(n):0)},defaultTextHeight:function(){return Ln(this.display)},defaultCharWidth:function(){return En(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,r,n,i){var o=this.display,a=(e=wn(this,pt(this.doc,e))).bottom,l=e.left;if(t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),o.sizer.appendChild(t),"over"==n)a=e.top;else if("above"==n||"near"==n){var s=Math.max(o.wrapper.clientHeight,this.doc.height),c=Math.max(o.sizer.clientWidth,o.lineSpace.clientWidth);("above"==n||e.bottom+t.offsetHeight>s)&&e.top>t.offsetHeight?a=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=s&&(a=e.bottom),l+t.offsetWidth>c&&(l=c-t.offsetWidth)}t.style.top=a+"px",t.style.left=t.style.right="","right"==i?(l=o.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==i?l=0:"middle"==i&&(l=(o.sizer.clientWidth-t.offsetWidth)/2),t.style.left=l+"px"),r&&oi(this,{left:l,top:a,right:l+t.offsetWidth,bottom:a+t.offsetHeight})},triggerOnKeyDown:Oi(ul),triggerOnKeyPress:Oi(pl),triggerOnKeyUp:fl,triggerOnMouseDown:Oi(bl),execCommand:function(e){if(Qa.hasOwnProperty(e))return Qa[e].call(null,this)},triggerElectric:Oi((function(e){Gl(this,e)})),findPosH:function(e,t,r,n){var i=1;t<0&&(i=-1,t=-t);for(var o=pt(this.doc,e),a=0;a0&&a(t.charAt(r-1));)--r;for(;n.5||this.options.lineWrapping)&&Dn(this),ye(this,"refresh",this)})),swapDoc:Oi((function(e){var t=this.doc;return t.cm=null,this.state.selectingText&&this.state.selectingText(),wo(this,e),pn(this),this.display.input.reset(),ci(this,e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,Br(this,"swapDoc",this,t),t})),phrase:function(e){var t=this.options.phrases;return t&&Object.prototype.hasOwnProperty.call(t,e)?t[e]:e},getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},xe(e),e.registerHelper=function(t,n,i){r.hasOwnProperty(t)||(r[t]=e[t]={_global:[]}),r[t][n]=i},e.registerGlobalHelper=function(t,n,i,o){e.registerHelper(t,n,o),r[t]._global.push({pred:i,val:o})}}function Zl(e,t,r,n,i){var o=t,a=r,l=Qe(e,t.line),s=i&&"rtl"==e.direction?-r:r;function c(){var r=t.line+s;return!(r=e.first+e.size)&&(t=new at(r,t.ch,t.sticky),l=Qe(e,r))}function u(o){var a;if("codepoint"==n){var u=l.text.charCodeAt(t.ch+(r>0?0:-1));if(isNaN(u))a=null;else{var d=r>0?u>=55296&&u<56320:u>=56320&&u<57343;a=new at(t.line,Math.max(0,Math.min(l.text.length,t.ch+r*(d?2:1))),-r)}}else a=i?Za(e.cm,l,t,r):Ya(l,t,r);if(null==a){if(o||!c())return!1;t=Xa(i,e.cm,l,t.line,s)}else t=a;return!0}if("char"==n||"codepoint"==n)u();else if("column"==n)u(!0);else if("word"==n||"group"==n)for(var d=null,f="group"==n,p=e.cm&&e.cm.getHelper(t,"wordChars"),h=!0;!(r<0)||u(!h);h=!1){var m=l.text.charAt(t.ch)||"\n",g=ne(m,p)?"w":f&&"\n"==m?"n":!f||/\s/.test(m)?null:"p";if(!f||h||g||(g="s"),d&&d!=g){r<0&&(r=1,u(),t.sticky="after");break}if(g&&(d=g),r>0&&!u(!h))break}var v=Yo(e,t,o,a,!0);return st(o,v)&&(v.hitSide=!0),v}function Ql(e,t,r,n){var i,o,a=e.doc,l=t.left;if("page"==n){var s=Math.min(e.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight),c=Math.max(s-.5*Ln(e.display),3);i=(r>0?t.bottom:t.top)+r*c}else"line"==n&&(i=r>0?t.bottom+3:t.top-3);for(;(o=kn(e,l,i)).outside;){if(r<0?i<=0:i>=a.height){o.hitSide=!0;break}i+=5*r}return o}var Jl=function(e){this.cm=e,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new W,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null};function es(e,t){var r=tn(e,t.line);if(!r||r.hidden)return null;var n=Qe(e.doc,t.line),i=Qr(r,n,t.line),o=pe(n,e.doc.direction),a="left";o&&(a=de(o,t.ch)%2?"right":"left");var l=ln(i.map,t.ch,a);return l.offset="right"==l.collapse?l.end:l.start,l}function ts(e){for(var t=e;t;t=t.parentNode)if(/CodeMirror-gutter-wrapper/.test(t.className))return!0;return!1}function rs(e,t){return t&&(e.bad=!0),e}function ns(e,t,r,n,i){var o="",a=!1,l=e.doc.lineSeparator(),s=!1;function c(e){return function(t){return t.id==e}}function u(){a&&(o+=l,s&&(o+=l),a=s=!1)}function d(e){e&&(u(),o+=e)}function f(t){if(1==t.nodeType){var r=t.getAttribute("cm-text");if(r)return void d(r);var o,p=t.getAttribute("cm-marker");if(p){var h=e.findMarks(at(n,0),at(i+1,0),c(+p));return void(h.length&&(o=h[0].find(0))&&d(Je(e.doc,o.from,o.to).join(l)))}if("false"==t.getAttribute("contenteditable"))return;var m=/^(pre|div|p|li|table|br)$/i.test(t.nodeName);if(!/^br$/i.test(t.nodeName)&&0==t.textContent.length)return;m&&u();for(var g=0;g=t.display.viewTo||o.line=t.display.viewFrom&&es(t,i)||{node:s[0].measure.map[2],offset:0},u=o.linen.firstLine()&&(a=at(a.line-1,Qe(n.doc,a.line-1).length)),l.ch==Qe(n.doc,l.line).text.length&&l.linei.viewTo-1)return!1;a.line==i.viewFrom||0==(e=In(n,a.line))?(t=rt(i.view[0].line),r=i.view[0].node):(t=rt(i.view[e].line),r=i.view[e-1].node.nextSibling);var s,c,u=In(n,l.line);if(u==i.view.length-1?(s=i.viewTo-1,c=i.lineDiv.lastChild):(s=rt(i.view[u+1].line)-1,c=i.view[u+1].node.previousSibling),!r)return!1;for(var d=n.doc.splitLines(ns(n,r,c,t,s)),f=Je(n.doc,at(t,0),at(s,Qe(n.doc,s).text.length));d.length>1&&f.length>1;)if(X(d)==X(f))d.pop(),f.pop(),s--;else{if(d[0]!=f[0])break;d.shift(),f.shift(),t++}for(var p=0,h=0,m=d[0],g=f[0],v=Math.min(m.length,g.length);pa.ch&&y.charCodeAt(y.length-h-1)==b.charCodeAt(b.length-h-1);)p--,h++;d[d.length-1]=y.slice(0,y.length-h).replace(/^\u200b+/,""),d[0]=d[0].slice(p).replace(/\u200b+$/,"");var C=at(t,p),x=at(s,f.length?X(f).length-h:0);return d.length>1||d[0]||lt(C,x)?(oa(n.doc,d,C,x,"+input"),!0):void 0},Jl.prototype.ensurePolled=function(){this.forceCompositionEnd()},Jl.prototype.reset=function(){this.forceCompositionEnd()},Jl.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},Jl.prototype.readFromDOMSoon=function(){var e=this;null==this.readDOMTimeout&&(this.readDOMTimeout=setTimeout((function(){if(e.readDOMTimeout=null,e.composing){if(!e.composing.done)return;e.composing=null}e.updateFromDOM()}),80))},Jl.prototype.updateFromDOM=function(){var e=this;!this.cm.isReadOnly()&&this.pollContent()||Ni(this.cm,(function(){return Pn(e.cm)}))},Jl.prototype.setUneditable=function(e){e.contentEditable="false"},Jl.prototype.onKeyPress=function(e){0==e.charCode||this.composing||(e.preventDefault(),this.cm.isReadOnly()||zi(this.cm,Ul)(this.cm,String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),0))},Jl.prototype.readOnlyChanged=function(e){this.div.contentEditable=String("nocursor"!=e)},Jl.prototype.onContextMenu=function(){},Jl.prototype.resetPosition=function(){},Jl.prototype.needsContentAttribute=!0;var as=function(e){this.cm=e,this.prevInput="",this.pollingFast=!1,this.polling=new W,this.hasSelection=!1,this.composing=null};function ls(e,t){if((t=t?P(t):{}).value=e.value,!t.tabindex&&e.tabIndex&&(t.tabindex=e.tabIndex),!t.placeholder&&e.placeholder&&(t.placeholder=e.placeholder),null==t.autofocus){var r=z();t.autofocus=r==e||null!=e.getAttribute("autofocus")&&r==document.body}function n(){e.value=l.getValue()}var i;if(e.form&&(me(e.form,"submit",n),!t.leaveSubmitMethodAlone)){var o=e.form;i=o.submit;try{var a=o.submit=function(){n(),o.submit=i,o.submit(),o.submit=a}}catch(e){}}t.finishInit=function(r){r.save=n,r.getTextArea=function(){return e},r.toTextArea=function(){r.toTextArea=isNaN,n(),e.parentNode.removeChild(r.getWrapperElement()),e.style.display="",e.form&&(ve(e.form,"submit",n),t.leaveSubmitMethodAlone||"function"!=typeof e.form.submit||(e.form.submit=i))}},e.style.display="none";var l=Pl((function(t){return e.parentNode.insertBefore(t,e.nextSibling)}),t);return l}function ss(e){e.off=ve,e.on=me,e.wheelEventPixels=no,e.Doc=Aa,e.splitLines=De,e.countColumn=q,e.findColumn=V,e.isWordChar=re,e.Pass=j,e.signal=ye,e.Line=cr,e.changeEnd=co,e.scrollbarModel=Ci,e.Pos=at,e.cmpPos=lt,e.modes=We,e.mimeModes=He,e.resolveMode=Ue,e.getMode=Ke,e.modeExtensions=Ge,e.extendMode=Ve,e.copyState=$e,e.startState=Xe,e.innerMode=Ye,e.commands=Qa,e.keyMap=qa,e.keyName=Ka,e.isModifierKey=ja,e.lookupKey=Ra,e.normalizeKeyMap=Ha,e.StringStream=Ze,e.SharedTextMarker=ya,e.TextMarker=ga,e.LineWidget=fa,e.e_preventDefault=ke,e.e_stopPropagation=Ae,e.e_stop=Me,e.addClass=O,e.contains=N,e.rmClass=S,e.keyNames=Da}as.prototype.init=function(e){var t=this,r=this,n=this.cm;this.createField(e);var i=this.textarea;function o(e){if(!be(n,e)){if(n.somethingSelected())jl({lineWise:!1,text:n.getSelections()});else{if(!n.options.lineWiseCopyCut)return;var t=Vl(n);jl({lineWise:!0,text:t.text}),"cut"==e.type?n.setSelections(t.ranges,null,U):(r.prevInput="",i.value=t.text.join("\n"),F(i))}"cut"==e.type&&(n.state.cutIncoming=+new Date)}}e.wrapper.insertBefore(this.wrapper,e.wrapper.firstChild),g&&(i.style.width="0px"),me(i,"input",(function(){a&&l>=9&&t.hasSelection&&(t.hasSelection=null),r.poll()})),me(i,"paste",(function(e){be(n,e)||Kl(e,n)||(n.state.pasteIncoming=+new Date,r.fastPoll())})),me(i,"cut",o),me(i,"copy",o),me(e.scroller,"paste",(function(t){if(!Ur(e,t)&&!be(n,t)){if(!i.dispatchEvent)return n.state.pasteIncoming=+new Date,void r.focus();var o=new Event("paste");o.clipboardData=t.clipboardData,i.dispatchEvent(o)}})),me(e.lineSpace,"selectstart",(function(t){Ur(e,t)||ke(t)})),me(i,"compositionstart",(function(){var e=n.getCursor("from");r.composing&&r.composing.range.clear(),r.composing={start:e,range:n.markText(e,n.getCursor("to"),{className:"CodeMirror-composing"})}})),me(i,"compositionend",(function(){r.composing&&(r.poll(),r.composing.range.clear(),r.composing=null)}))},as.prototype.createField=function(e){this.wrapper=Yl(),this.textarea=this.wrapper.firstChild},as.prototype.screenReaderLabelChanged=function(e){e?this.textarea.setAttribute("aria-label",e):this.textarea.removeAttribute("aria-label")},as.prototype.prepareSelection=function(){var e=this.cm,t=e.display,r=e.doc,n=Kn(e);if(e.options.moveInputWithCursor){var i=wn(e,r.sel.primary().head,"div"),o=t.wrapper.getBoundingClientRect(),a=t.lineDiv.getBoundingClientRect();n.teTop=Math.max(0,Math.min(t.wrapper.clientHeight-10,i.top+a.top-o.top)),n.teLeft=Math.max(0,Math.min(t.wrapper.clientWidth-10,i.left+a.left-o.left))}return n},as.prototype.showSelection=function(e){var t=this.cm.display;B(t.cursorDiv,e.cursors),B(t.selectionDiv,e.selection),null!=e.teTop&&(this.wrapper.style.top=e.teTop+"px",this.wrapper.style.left=e.teLeft+"px")},as.prototype.reset=function(e){if(!this.contextMenuPending&&!this.composing){var t=this.cm;if(t.somethingSelected()){this.prevInput="";var r=t.getSelection();this.textarea.value=r,t.state.focused&&F(this.textarea),a&&l>=9&&(this.hasSelection=r)}else e||(this.prevInput=this.textarea.value="",a&&l>=9&&(this.hasSelection=null))}},as.prototype.getField=function(){return this.textarea},as.prototype.supportsTouch=function(){return!1},as.prototype.focus=function(){if("nocursor"!=this.cm.options.readOnly&&(!y||z()!=this.textarea))try{this.textarea.focus()}catch(e){}},as.prototype.blur=function(){this.textarea.blur()},as.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},as.prototype.receivedFocus=function(){this.slowPoll()},as.prototype.slowPoll=function(){var e=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,(function(){e.poll(),e.cm.state.focused&&e.slowPoll()}))},as.prototype.fastPoll=function(){var e=!1,t=this;function r(){t.poll()||e?(t.pollingFast=!1,t.slowPoll()):(e=!0,t.polling.set(60,r))}t.pollingFast=!0,t.polling.set(20,r)},as.prototype.poll=function(){var e=this,t=this.cm,r=this.textarea,n=this.prevInput;if(this.contextMenuPending||!t.state.focused||Fe(r)&&!n&&!this.composing||t.isReadOnly()||t.options.disableInput||t.state.keySeq)return!1;var i=r.value;if(i==n&&!t.somethingSelected())return!1;if(a&&l>=9&&this.hasSelection===i||b&&/[\uf700-\uf7ff]/.test(i))return t.display.input.reset(),!1;if(t.doc.sel==t.display.selForContextMenu){var o=i.charCodeAt(0);if(8203!=o||n||(n="​"),8666==o)return this.reset(),this.cm.execCommand("undo")}for(var s=0,c=Math.min(n.length,i.length);s1e3||i.indexOf("\n")>-1?r.value=e.prevInput="":e.prevInput=i,e.composing&&(e.composing.range.clear(),e.composing.range=t.markText(e.composing.start,t.getCursor("to"),{className:"CodeMirror-composing"}))})),!0},as.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},as.prototype.onKeyPress=function(){a&&l>=9&&(this.hasSelection=null),this.fastPoll()},as.prototype.onContextMenu=function(e){var t=this,r=t.cm,n=r.display,i=t.textarea;t.contextMenuPending&&t.contextMenuPending();var o=Fn(r,e),c=n.scroller.scrollTop;if(o&&!f){r.options.resetSelectionOnContextMenu&&-1==r.doc.sel.contains(o)&&zi(r,jo)(r.doc,so(o),U);var u,d=i.style.cssText,p=t.wrapper.style.cssText,h=t.wrapper.offsetParent.getBoundingClientRect();if(t.wrapper.style.cssText="position: static",i.style.cssText="position: absolute; width: 30px; height: 30px;\n top: "+(e.clientY-h.top-5)+"px; left: "+(e.clientX-h.left-5)+"px;\n z-index: 1000; background: "+(a?"rgba(255, 255, 255, .05)":"transparent")+";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",s&&(u=window.scrollY),n.input.focus(),s&&window.scrollTo(null,u),n.input.reset(),r.somethingSelected()||(i.value=t.prevInput=" "),t.contextMenuPending=v,n.selForContextMenu=r.doc.sel,clearTimeout(n.detectingSelectAll),a&&l>=9&&g(),A){Me(e);var m=function(){ve(window,"mouseup",m),setTimeout(v,20)};me(window,"mouseup",m)}else setTimeout(v,50)}function g(){if(null!=i.selectionStart){var e=r.somethingSelected(),o="​"+(e?i.value:"");i.value="⇚",i.value=o,t.prevInput=e?"":"​",i.selectionStart=1,i.selectionEnd=o.length,n.selForContextMenu=r.doc.sel}}function v(){if(t.contextMenuPending==v&&(t.contextMenuPending=!1,t.wrapper.style.cssText=p,i.style.cssText=d,a&&l<9&&n.scrollbars.setScrollTop(n.scroller.scrollTop=c),null!=i.selectionStart)){(!a||a&&l<9)&&g();var e=0,o=function(){n.selForContextMenu==r.doc.sel&&0==i.selectionStart&&i.selectionEnd>0&&"​"==t.prevInput?zi(r,Zo)(r):e++<10?n.detectingSelectAll=setTimeout(o,500):(n.selForContextMenu=null,n.input.reset())};n.detectingSelectAll=setTimeout(o,200)}}},as.prototype.readOnlyChanged=function(e){e||this.reset(),this.textarea.disabled="nocursor"==e,this.textarea.readOnly=!!e},as.prototype.setUneditable=function(){},as.prototype.needsContentAttribute=!1,Dl(Pl),Xl(Pl);var cs="iter insert remove copy getEditor constructor".split(" ");for(var us in Aa.prototype)Aa.prototype.hasOwnProperty(us)&&H(cs,us)<0&&(Pl.prototype[us]=function(e){return function(){return e.apply(this.doc,arguments)}}(Aa.prototype[us]));return xe(Aa),Pl.inputStyles={textarea:as,contenteditable:Jl},Pl.defineMode=function(e){Pl.defaults.mode||"null"==e||(Pl.defaults.mode=e),Re.apply(this,arguments)},Pl.defineMIME=je,Pl.defineMode("null",(function(){return{token:function(e){return e.skipToEnd()}}})),Pl.defineMIME("text/plain","null"),Pl.defineExtension=function(e,t){Pl.prototype[e]=t},Pl.defineDocExtension=function(e,t){Aa.prototype[e]=t},Pl.fromTextArea=ls,ss(Pl),Pl.version="5.65.5",Pl}()},762:(e,t,r)=>{!function(e){"use strict";function t(e,t,r,n,i,o){this.indented=e,this.column=t,this.type=r,this.info=n,this.align=i,this.prev=o}function r(e,r,n,i){var o=e.indented;return e.context&&"statement"==e.context.type&&"statement"!=n&&(o=e.context.indented),e.context=new t(o,r,n,i,null,e.context)}function n(e){var t=e.context.type;return")"!=t&&"]"!=t&&"}"!=t||(e.indented=e.context.indented),e.context=e.context.prev}function i(e,t,r){return"variable"==t.prevToken||"type"==t.prevToken||!!/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(e.string.slice(0,r))||!(!t.typeAtEndOfLine||e.column()!=e.indentation())||void 0}function o(e){for(;;){if(!e||"top"==e.type)return!0;if("}"==e.type&&"namespace"!=e.prev.info)return!1;e=e.prev}}function a(e){for(var t={},r=e.split(" "),n=0;n!?|\/]/,B=s.isIdentifierChar||/[\w\$_\xa1-\uffff]/,L=s.isReservedIdentifier||!1;function E(e,t){var r=e.next();if(w[r]){var n=w[r](e,t);if(!1!==n)return n}if('"'==r||"'"==r)return t.tokenize=N(r),t.tokenize(e,t);if(M.test(r)){if(e.backUp(1),e.match(S))return"number";e.next()}if(_.test(r))return c=r,null;if("/"==r){if(e.eat("*"))return t.tokenize=z,z(e,t);if(e.eat("/"))return e.skipToEnd(),"comment"}if(T.test(r)){for(;!e.match(/^\/[\/*]/,!1)&&e.eat(T););return"operator"}if(e.eatWhile(B),A)for(;e.match(A);)e.eatWhile(B);var i=e.current();return l(h,i)?(l(v,i)&&(c="newstatement"),l(y,i)&&(u=!0),"keyword"):l(m,i)?"type":l(g,i)||L&&L(i)?(l(v,i)&&(c="newstatement"),"builtin"):l(b,i)?"atom":"variable"}function N(e){return function(t,r){for(var n,i=!1,o=!1;null!=(n=t.next());){if(n==e&&!i){o=!0;break}i=!i&&"\\"==n}return(o||!i&&!C)&&(r.tokenize=null),"string"}}function z(e,t){for(var r,n=!1;r=e.next();){if("/"==r&&n){t.tokenize=null;break}n="*"==r}return"comment"}function O(e,t){s.typeFirstDefinitions&&e.eol()&&o(t.context)&&(t.typeAtEndOfLine=i(e,t,e.pos))}return{startState:function(e){return{tokenize:null,context:new t((e||0)-d,0,"top",null,!1),indented:0,startOfLine:!0,prevToken:null}},token:function(e,t){var a=t.context;if(e.sol()&&(null==a.align&&(a.align=!1),t.indented=e.indentation(),t.startOfLine=!0),e.eatSpace())return O(e,t),null;c=u=null;var l=(t.tokenize||E)(e,t);if("comment"==l||"meta"==l)return l;if(null==a.align&&(a.align=!0),";"==c||":"==c||","==c&&e.match(/^\s*(?:\/\/.*)?$/,!1))for(;"statement"==t.context.type;)n(t);else if("{"==c)r(t,e.column(),"}");else if("["==c)r(t,e.column(),"]");else if("("==c)r(t,e.column(),")");else if("}"==c){for(;"statement"==a.type;)a=n(t);for("}"==a.type&&(a=n(t));"statement"==a.type;)a=n(t)}else c==a.type?n(t):x&&(("}"==a.type||"top"==a.type)&&";"!=c||"statement"==a.type&&"newstatement"==c)&&r(t,e.column(),"statement",e.current());if("variable"==l&&("def"==t.prevToken||s.typeFirstDefinitions&&i(e,t,e.start)&&o(t.context)&&e.match(/^\s*\(/,!1))&&(l="def"),w.token){var d=w.token(e,t,l);void 0!==d&&(l=d)}return"def"==l&&!1===s.styleDefs&&(l="variable"),t.startOfLine=!1,t.prevToken=u?"def":l||c,O(e,t),l},indent:function(t,r){if(t.tokenize!=E&&null!=t.tokenize||t.typeAtEndOfLine)return e.Pass;var n=t.context,i=r&&r.charAt(0),o=i==n.type;if("statement"==n.type&&"}"==i&&(n=n.prev),s.dontIndentStatements)for(;"statement"==n.type&&s.dontIndentStatements.test(n.info);)n=n.prev;if(w.indent){var a=w.indent(t,n,r,d);if("number"==typeof a)return a}var l=n.prev&&"switch"==n.prev.info;if(s.allmanIndentation&&/[{(]/.test(i)){for(;"top"!=n.type&&"}"!=n.type;)n=n.prev;return n.indented}return"statement"==n.type?n.indented+("{"==i?0:f):!n.align||p&&")"==n.type?")"!=n.type||o?n.indented+(o?0:d)+(o||!l||/^(?:case|default)\b/.test(r)?0:d):n.indented+f:n.column+(o?0:1)},electricInput:k?/^\s*(?:case .*?:|default:|\{\}?|\})$/:/^\s*[{}]$/,blockCommentStart:"/*",blockCommentEnd:"*/",blockCommentContinue:" * ",lineComment:"//",fold:"brace"}}));var s="auto if break case register continue return default do sizeof static else struct switch extern typedef union for goto while enum const volatile inline restrict asm fortran",c="alignas alignof and and_eq audit axiom bitand bitor catch class compl concept constexpr const_cast decltype delete dynamic_cast explicit export final friend import module mutable namespace new noexcept not not_eq operator or or_eq override private protected public reinterpret_cast requires static_assert static_cast template this thread_local throw try typeid typename using virtual xor xor_eq",u="bycopy byref in inout oneway out self super atomic nonatomic retain copy readwrite readonly strong weak assign typeof nullable nonnull null_resettable _cmd @interface @implementation @end @protocol @encode @property @synthesize @dynamic @class @public @package @private @protected @required @optional @try @catch @finally @import @selector @encode @defs @synchronized @autoreleasepool @compatibility_alias @available",d="FOUNDATION_EXPORT FOUNDATION_EXTERN NS_INLINE NS_FORMAT_FUNCTION NS_RETURNS_RETAINEDNS_ERROR_ENUM NS_RETURNS_NOT_RETAINED NS_RETURNS_INNER_POINTER NS_DESIGNATED_INITIALIZER NS_ENUM NS_OPTIONS NS_REQUIRES_NIL_TERMINATION NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_SWIFT_NAME NS_REFINED_FOR_SWIFT",f=a("int long char short double float unsigned signed void bool"),p=a("SEL instancetype id Class Protocol BOOL");function h(e){return l(f,e)||/.+_t$/.test(e)}function m(e){return h(e)||l(p,e)}var g="case do else for if switch while struct enum union",v="struct enum union";function y(e,t){if(!t.startOfLine)return!1;for(var r,n=null;r=e.peek();){if("\\"==r&&e.match(/^.$/)){n=y;break}if("/"==r&&e.match(/^\/[\/\*]/,!1))break;e.next()}return t.tokenize=n,"meta"}function b(e,t){return"type"==t.prevToken&&"type"}function w(e){return!(!e||e.length<2||"_"!=e[0]||"_"!=e[1]&&e[1]===e[1].toLowerCase())}function C(e){return e.eatWhile(/[\w\.']/),"number"}function x(e,t){if(e.backUp(1),e.match(/^(?:R|u8R|uR|UR|LR)/)){var r=e.match(/^"([^\s\\()]{0,16})\(/);return!!r&&(t.cpp11RawStringDelim=r[1],t.tokenize=_,_(e,t))}return e.match(/^(?:u8|u|U|L)/)?!!e.match(/^["']/,!1)&&"string":(e.next(),!1)}function k(e){var t=/(\w+)::~?(\w+)$/.exec(e);return t&&t[1]==t[2]}function A(e,t){for(var r;null!=(r=e.next());)if('"'==r&&!e.eat('"')){t.tokenize=null;break}return"string"}function _(e,t){var r=t.cpp11RawStringDelim.replace(/[^\w\s]/g,"\\$&");return e.match(new RegExp(".*?\\)"+r+'"'))?t.tokenize=null:e.skipToEnd(),"string"}function M(t,r){"string"==typeof t&&(t=[t]);var n=[];function i(e){if(e)for(var t in e)e.hasOwnProperty(t)&&n.push(t)}i(r.keywords),i(r.types),i(r.builtin),i(r.atoms),n.length&&(r.helperType=t[0],e.registerHelper("hintWords",t[0],n));for(var o=0;o!?|\/#:@]/,hooks:{"@":function(e){return e.eatWhile(/[\w\$_]/),"meta"},'"':function(e,t){return!!e.match('""')&&(t.tokenize=S,t.tokenize(e,t))},"'":function(e){return e.eatWhile(/[\w\$_\xa1-\uffff]/),"atom"},"=":function(e,r){var n=r.context;return!("}"!=n.type||!n.align||!e.eat(">"))&&(r.context=new t(n.indented,n.column,n.type,n.info,null,n.prev),"operator")},"/":function(e,t){return!!e.eat("*")&&(t.tokenize=T(1),t.tokenize(e,t))}},modeProps:{closeBrackets:{pairs:'()[]{}""',triples:'"'}}}),M("text/x-kotlin",{name:"clike",keywords:a("package as typealias class interface this super val operator var fun for is in This throw return annotation break continue object if else while do try when !in !is as? file import where by get set abstract enum open inner override private public internal protected catch finally out final vararg reified dynamic companion constructor init sealed field property receiver param sparam lateinit data inline noinline tailrec external annotation crossinline const operator infix suspend actual expect setparam value"),types:a("Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable Compiler Double Exception Float Integer Long Math Number Object Package Pair Process Runtime Runnable SecurityManager Short StackTraceElement StrictMath String StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void Annotation Any BooleanArray ByteArray Char CharArray DeprecationLevel DoubleArray Enum FloatArray Function Int IntArray Lazy LazyThreadSafetyMode LongArray Nothing ShortArray Unit"),intendSwitch:!1,indentStatements:!1,multiLineStrings:!0,number:/^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+(\.\d+)?|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,blockKeywords:a("catch class do else finally for if where try while enum"),defKeywords:a("class val var object interface fun"),atoms:a("true false null this"),hooks:{"@":function(e){return e.eatWhile(/[\w\$_]/),"meta"},"*":function(e,t){return"."==t.prevToken?"variable":"operator"},'"':function(e,t){return t.tokenize=B(e.match('""')),t.tokenize(e,t)},"/":function(e,t){return!!e.eat("*")&&(t.tokenize=T(1),t.tokenize(e,t))},indent:function(e,t,r,n){var i=r&&r.charAt(0);return"}"!=e.prevToken&&")"!=e.prevToken||""!=r?"operator"==e.prevToken&&"}"!=r&&"}"!=e.context.type||"variable"==e.prevToken&&"."==i||("}"==e.prevToken||")"==e.prevToken)&&"."==i?2*n+t.indented:t.align&&"}"==t.type?t.indented+(e.context.type==(r||"").charAt(0)?0:n):void 0:e.indented}},modeProps:{closeBrackets:{triples:'"'}}}),M(["x-shader/x-vertex","x-shader/x-fragment"],{name:"clike",keywords:a("sampler1D sampler2D sampler3D samplerCube sampler1DShadow sampler2DShadow const attribute uniform varying break continue discard return for while do if else struct in out inout"),types:a("float int bool void vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 mat2 mat3 mat4"),blockKeywords:a("for while do if else struct"),builtin:a("radians degrees sin cos tan asin acos atan pow exp log exp2 sqrt inversesqrt abs sign floor ceil fract mod min max clamp mix step smoothstep length distance dot cross normalize ftransform faceforward reflect refract matrixCompMult lessThan lessThanEqual greaterThan greaterThanEqual equal notEqual any all not texture1D texture1DProj texture1DLod texture1DProjLod texture2D texture2DProj texture2DLod texture2DProjLod texture3D texture3DProj texture3DLod texture3DProjLod textureCube textureCubeLod shadow1D shadow2D shadow1DProj shadow2DProj shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod dFdx dFdy fwidth noise1 noise2 noise3 noise4"),atoms:a("true false gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 gl_FogCoord gl_PointCoord gl_Position gl_PointSize gl_ClipVertex gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor gl_TexCoord gl_FogFragCoord gl_FragCoord gl_FrontFacing gl_FragData gl_FragDepth gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse gl_TextureMatrixTranspose gl_ModelViewMatrixInverseTranspose gl_ProjectionMatrixInverseTranspose gl_ModelViewProjectionMatrixInverseTranspose gl_TextureMatrixInverseTranspose gl_NormalScale gl_DepthRange gl_ClipPlane gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel gl_FrontLightModelProduct gl_BackLightModelProduct gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ gl_FogParameters gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits gl_MaxDrawBuffers"),indentSwitch:!1,hooks:{"#":y},modeProps:{fold:["brace","include"]}}),M("text/x-nesc",{name:"clike",keywords:a(s+" as atomic async call command component components configuration event generic implementation includes interface module new norace nx_struct nx_union post provides signal task uses abstract extends"),types:h,blockKeywords:a(g),atoms:a("null true false"),hooks:{"#":y},modeProps:{fold:["brace","include"]}}),M("text/x-objectivec",{name:"clike",keywords:a(s+" "+u),types:m,builtin:a(d),blockKeywords:a(g+" @synthesize @try @catch @finally @autoreleasepool @synchronized"),defKeywords:a(v+" @interface @implementation @protocol @class"),dontIndentStatements:/^@.*$/,typeFirstDefinitions:!0,atoms:a("YES NO NULL Nil nil true false nullptr"),isReservedIdentifier:w,hooks:{"#":y,"*":b},modeProps:{fold:["brace","include"]}}),M("text/x-objectivec++",{name:"clike",keywords:a(s+" "+u+" "+c),types:m,builtin:a(d),blockKeywords:a(g+" @synthesize @try @catch @finally @autoreleasepool @synchronized class try catch"),defKeywords:a(v+" @interface @implementation @protocol @class class namespace"),dontIndentStatements:/^@.*$|^template$/,typeFirstDefinitions:!0,atoms:a("YES NO NULL Nil nil true false nullptr"),isReservedIdentifier:w,hooks:{"#":y,"*":b,u:x,U:x,L:x,R:x,0:C,1:C,2:C,3:C,4:C,5:C,6:C,7:C,8:C,9:C,token:function(e,t,r){if("variable"==r&&"("==e.peek()&&(";"==t.prevToken||null==t.prevToken||"}"==t.prevToken)&&k(e.current()))return"def"}},namespaceSeparator:"::",modeProps:{fold:["brace","include"]}}),M("text/x-squirrel",{name:"clike",keywords:a("base break clone continue const default delete enum extends function in class foreach local resume return this throw typeof yield constructor instanceof static"),types:h,blockKeywords:a("case catch class else for foreach if switch try while"),defKeywords:a("function local class"),typeFirstDefinitions:!0,atoms:a("true false null"),hooks:{"#":y},modeProps:{fold:["brace","include"]}});var L=null;function E(e){return function(t,r){for(var n,i=!1,o=!1;!t.eol();){if(!i&&t.match('"')&&("single"==e||t.match('""'))){o=!0;break}if(!i&&t.match("``")){L=E(e),o=!0;break}n=t.next(),i="single"==e&&!i&&"\\"==n}return o&&(r.tokenize=null),"string"}}M("text/x-ceylon",{name:"clike",keywords:a("abstracts alias assembly assert assign break case catch class continue dynamic else exists extends finally for function given if import in interface is let module new nonempty object of out outer package return satisfies super switch then this throw try value void while"),types:function(e){var t=e.charAt(0);return t===t.toUpperCase()&&t!==t.toLowerCase()},blockKeywords:a("case catch class dynamic else finally for function if interface module new object switch try while"),defKeywords:a("class dynamic function interface module object package value"),builtin:a("abstract actual aliased annotation by default deprecated doc final formal late license native optional sealed see serializable shared suppressWarnings tagged throws variable"),isPunctuationChar:/[\[\]{}\(\),;\:\.`]/,isOperatorChar:/[+\-*&%=<>!?|^~:\/]/,numberStart:/[\d#$]/,number:/^(?:#[\da-fA-F_]+|\$[01_]+|[\d_]+[kMGTPmunpf]?|[\d_]+\.[\d_]+(?:[eE][-+]?\d+|[kMGTPmunpf]|)|)/i,multiLineStrings:!0,typeFirstDefinitions:!0,atoms:a("true false null larger smaller equal empty finished"),indentSwitch:!1,styleDefs:!1,hooks:{"@":function(e){return e.eatWhile(/[\w\$_]/),"meta"},'"':function(e,t){return t.tokenize=E(e.match('""')?"triple":"single"),t.tokenize(e,t)},"`":function(e,t){return!(!L||!e.match("`"))&&(t.tokenize=L,L=null,t.tokenize(e,t))},"'":function(e){return e.eatWhile(/[\w\$_\xa1-\uffff]/),"atom"},token:function(e,t,r){if(("variable"==r||"type"==r)&&"."==t.prevToken)return"variable-2"}},modeProps:{fold:["brace","import"],closeBrackets:{triples:'"'}}})}(r(631))},629:(e,t,r)=>{!function(e){"use strict";function t(e){for(var t={},r=0;r*\/]/.test(r)?x(null,"select-op"):"."==r&&e.match(/^-?[_a-z][_a-z0-9-]*/i)?x("qualifier","qualifier"):/[:;{}\[\]\(\)]/.test(r)?x(null,r):e.match(/^[\w-.]+(?=\()/)?(/^(url(-prefix)?|domain|regexp)$/i.test(e.current())&&(t.tokenize=_),x("variable callee","variable")):/[\w\\\-]/.test(r)?(e.eatWhile(/[\w\\\-]/),x("property","word")):x(null,null):/[\d.]/.test(e.peek())?(e.eatWhile(/[\w.%]/),x("number","unit")):e.match(/^-[\w\\\-]*/)?(e.eatWhile(/[\w\\\-]/),e.match(/^\s*:/,!1)?x("variable-2","variable-definition"):x("variable-2","variable")):e.match(/^\w+-/)?x("meta","meta"):void 0}function A(e){return function(t,r){for(var n,i=!1;null!=(n=t.next());){if(n==e&&!i){")"==e&&t.backUp(1);break}i=!i&&"\\"==n}return(n==e||!i&&")"!=e)&&(r.tokenize=null),x("string","string")}}function _(e,t){return e.next(),e.match(/^\s*[\"\')]/,!1)?t.tokenize=null:t.tokenize=A(")"),x(null,"(")}function M(e,t,r){this.type=e,this.indent=t,this.prev=r}function S(e,t,r,n){return e.context=new M(r,t.indentation()+(!1===n?0:a),e.context),r}function T(e){return e.context.prev&&(e.context=e.context.prev),e.context.type}function B(e,t,r){return N[r.context.type](e,t,r)}function L(e,t,r,n){for(var i=n||1;i>0;i--)r.context=r.context.prev;return B(e,t,r)}function E(e){var t=e.current().toLowerCase();o=v.hasOwnProperty(t)?"atom":g.hasOwnProperty(t)?"keyword":"variable"}var N={top:function(e,t,r){if("{"==e)return S(r,t,"block");if("}"==e&&r.context.prev)return T(r);if(w&&/@component/i.test(e))return S(r,t,"atComponentBlock");if(/^@(-moz-)?document$/i.test(e))return S(r,t,"documentTypes");if(/^@(media|supports|(-moz-)?document|import)$/i.test(e))return S(r,t,"atBlock");if(/^@(font-face|counter-style)/i.test(e))return r.stateArg=e,"restricted_atBlock_before";if(/^@(-(moz|ms|o|webkit)-)?keyframes$/i.test(e))return"keyframes";if(e&&"@"==e.charAt(0))return S(r,t,"at");if("hash"==e)o="builtin";else if("word"==e)o="tag";else{if("variable-definition"==e)return"maybeprop";if("interpolation"==e)return S(r,t,"interpolation");if(":"==e)return"pseudo";if(y&&"("==e)return S(r,t,"parens")}return r.context.type},block:function(e,t,r){if("word"==e){var n=t.current().toLowerCase();return f.hasOwnProperty(n)?(o="property","maybeprop"):p.hasOwnProperty(n)?(o=C?"string-2":"property","maybeprop"):y?(o=t.match(/^\s*:(?:\s|$)/,!1)?"property":"tag","block"):(o+=" error","maybeprop")}return"meta"==e?"block":y||"hash"!=e&&"qualifier"!=e?N.top(e,t,r):(o="error","block")},maybeprop:function(e,t,r){return":"==e?S(r,t,"prop"):B(e,t,r)},prop:function(e,t,r){if(";"==e)return T(r);if("{"==e&&y)return S(r,t,"propBlock");if("}"==e||"{"==e)return L(e,t,r);if("("==e)return S(r,t,"parens");if("hash"!=e||/^#([0-9a-fA-f]{3,4}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/.test(t.current())){if("word"==e)E(t);else if("interpolation"==e)return S(r,t,"interpolation")}else o+=" error";return"prop"},propBlock:function(e,t,r){return"}"==e?T(r):"word"==e?(o="property","maybeprop"):r.context.type},parens:function(e,t,r){return"{"==e||"}"==e?L(e,t,r):")"==e?T(r):"("==e?S(r,t,"parens"):"interpolation"==e?S(r,t,"interpolation"):("word"==e&&E(t),"parens")},pseudo:function(e,t,r){return"meta"==e?"pseudo":"word"==e?(o="variable-3",r.context.type):B(e,t,r)},documentTypes:function(e,t,r){return"word"==e&&s.hasOwnProperty(t.current())?(o="tag",r.context.type):N.atBlock(e,t,r)},atBlock:function(e,t,r){if("("==e)return S(r,t,"atBlock_parens");if("}"==e||";"==e)return L(e,t,r);if("{"==e)return T(r)&&S(r,t,y?"block":"top");if("interpolation"==e)return S(r,t,"interpolation");if("word"==e){var n=t.current().toLowerCase();o="only"==n||"not"==n||"and"==n||"or"==n?"keyword":c.hasOwnProperty(n)?"attribute":u.hasOwnProperty(n)?"property":d.hasOwnProperty(n)?"keyword":f.hasOwnProperty(n)?"property":p.hasOwnProperty(n)?C?"string-2":"property":v.hasOwnProperty(n)?"atom":g.hasOwnProperty(n)?"keyword":"error"}return r.context.type},atComponentBlock:function(e,t,r){return"}"==e?L(e,t,r):"{"==e?T(r)&&S(r,t,y?"block":"top",!1):("word"==e&&(o="error"),r.context.type)},atBlock_parens:function(e,t,r){return")"==e?T(r):"{"==e||"}"==e?L(e,t,r,2):N.atBlock(e,t,r)},restricted_atBlock_before:function(e,t,r){return"{"==e?S(r,t,"restricted_atBlock"):"word"==e&&"@counter-style"==r.stateArg?(o="variable","restricted_atBlock_before"):B(e,t,r)},restricted_atBlock:function(e,t,r){return"}"==e?(r.stateArg=null,T(r)):"word"==e?(o="@font-face"==r.stateArg&&!h.hasOwnProperty(t.current().toLowerCase())||"@counter-style"==r.stateArg&&!m.hasOwnProperty(t.current().toLowerCase())?"error":"property","maybeprop"):"restricted_atBlock"},keyframes:function(e,t,r){return"word"==e?(o="variable","keyframes"):"{"==e?S(r,t,"top"):B(e,t,r)},at:function(e,t,r){return";"==e?T(r):"{"==e||"}"==e?L(e,t,r):("word"==e?o="tag":"hash"==e&&(o="builtin"),"at")},interpolation:function(e,t,r){return"}"==e?T(r):"{"==e||";"==e?L(e,t,r):("word"==e?o="variable":"variable"!=e&&"("!=e&&")"!=e&&(o="error"),"interpolation")}};return{startState:function(e){return{tokenize:null,state:n?"block":"top",stateArg:null,context:new M(n?"block":"top",e||0,null)}},token:function(e,t){if(!t.tokenize&&e.eatSpace())return null;var r=(t.tokenize||k)(e,t);return r&&"object"==typeof r&&(i=r[1],r=r[0]),o=r,"comment"!=i&&(t.state=N[t.state](i,e,t)),o},indent:function(e,t){var r=e.context,n=t&&t.charAt(0),i=r.indent;return"prop"!=r.type||"}"!=n&&")"!=n||(r=r.prev),r.prev&&("}"!=n||"block"!=r.type&&"top"!=r.type&&"interpolation"!=r.type&&"restricted_atBlock"!=r.type?(")"!=n||"parens"!=r.type&&"atBlock_parens"!=r.type)&&("{"!=n||"at"!=r.type&&"atBlock"!=r.type)||(i=Math.max(0,r.indent-a)):i=(r=r.prev).indent),i},electricChars:"}",blockCommentStart:"/*",blockCommentEnd:"*/",blockCommentContinue:" * ",lineComment:b,fold:"brace"}}));var r=["domain","regexp","url","url-prefix"],n=t(r),i=["all","aural","braille","handheld","print","projection","screen","tty","tv","embossed"],o=t(i),a=["width","min-width","max-width","height","min-height","max-height","device-width","min-device-width","max-device-width","device-height","min-device-height","max-device-height","aspect-ratio","min-aspect-ratio","max-aspect-ratio","device-aspect-ratio","min-device-aspect-ratio","max-device-aspect-ratio","color","min-color","max-color","color-index","min-color-index","max-color-index","monochrome","min-monochrome","max-monochrome","resolution","min-resolution","max-resolution","scan","grid","orientation","device-pixel-ratio","min-device-pixel-ratio","max-device-pixel-ratio","pointer","any-pointer","hover","any-hover","prefers-color-scheme","dynamic-range","video-dynamic-range"],l=t(a),s=["landscape","portrait","none","coarse","fine","on-demand","hover","interlace","progressive","dark","light","standard","high"],c=t(s),u=["align-content","align-items","align-self","alignment-adjust","alignment-baseline","all","anchor-point","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","azimuth","backdrop-filter","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-position-x","background-position-y","background-repeat","background-size","baseline-shift","binding","bleed","block-size","bookmark-label","bookmark-level","bookmark-state","bookmark-target","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","caret-color","clear","clip","color","color-profile","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","contain","content","counter-increment","counter-reset","crop","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","drop-initial-after-adjust","drop-initial-after-align","drop-initial-before-adjust","drop-initial-before-align","drop-initial-size","drop-initial-value","elevation","empty-cells","fit","fit-content","fit-position","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","float-offset","flow-from","flow-into","font","font-family","font-feature-settings","font-kerning","font-language-override","font-optical-sizing","font-size","font-size-adjust","font-stretch","font-style","font-synthesis","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-variation-settings","font-weight","gap","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-gap","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-gap","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","inline-box-align","inset","inset-block","inset-block-end","inset-block-start","inset-inline","inset-inline-end","inset-inline-start","isolation","justify-content","justify-items","justify-self","left","letter-spacing","line-break","line-height","line-height-step","line-stacking","line-stacking-ruby","line-stacking-shift","line-stacking-strategy","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marks","marquee-direction","marquee-loop","marquee-play-count","marquee-speed","marquee-style","mask-clip","mask-composite","mask-image","mask-mode","mask-origin","mask-position","mask-repeat","mask-size","mask-type","max-block-size","max-height","max-inline-size","max-width","min-block-size","min-height","min-inline-size","min-width","mix-blend-mode","move-to","nav-down","nav-index","nav-left","nav-right","nav-up","object-fit","object-position","offset","offset-anchor","offset-distance","offset-path","offset-position","offset-rotate","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-style","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","page-policy","pause","pause-after","pause-before","perspective","perspective-origin","pitch","pitch-range","place-content","place-items","place-self","play-during","position","presentation-level","punctuation-trim","quotes","region-break-after","region-break-before","region-break-inside","region-fragment","rendering-intent","resize","rest","rest-after","rest-before","richness","right","rotate","rotation","rotation-point","row-gap","ruby-align","ruby-overhang","ruby-position","ruby-span","scale","scroll-behavior","scroll-margin","scroll-margin-block","scroll-margin-block-end","scroll-margin-block-start","scroll-margin-bottom","scroll-margin-inline","scroll-margin-inline-end","scroll-margin-inline-start","scroll-margin-left","scroll-margin-right","scroll-margin-top","scroll-padding","scroll-padding-block","scroll-padding-block-end","scroll-padding-block-start","scroll-padding-bottom","scroll-padding-inline","scroll-padding-inline-end","scroll-padding-inline-start","scroll-padding-left","scroll-padding-right","scroll-padding-top","scroll-snap-align","scroll-snap-type","shape-image-threshold","shape-inside","shape-margin","shape-outside","size","speak","speak-as","speak-header","speak-numeral","speak-punctuation","speech-rate","stress","string-set","tab-size","table-layout","target","target-name","target-new","target-position","text-align","text-align-last","text-combine-upright","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-skip-ink","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-height","text-indent","text-justify","text-orientation","text-outline","text-overflow","text-rendering","text-shadow","text-size-adjust","text-space-collapse","text-transform","text-underline-position","text-wrap","top","touch-action","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","translate","unicode-bidi","user-select","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","volume","white-space","widows","width","will-change","word-break","word-spacing","word-wrap","writing-mode","z-index","clip-path","clip-rule","mask","enable-background","filter","flood-color","flood-opacity","lighting-color","stop-color","stop-opacity","pointer-events","color-interpolation","color-interpolation-filters","color-rendering","fill","fill-opacity","fill-rule","image-rendering","marker","marker-end","marker-mid","marker-start","paint-order","shape-rendering","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-rendering","baseline-shift","dominant-baseline","glyph-orientation-horizontal","glyph-orientation-vertical","text-anchor","writing-mode"],d=t(u),f=["accent-color","aspect-ratio","border-block","border-block-color","border-block-end","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start","border-block-start-color","border-block-start-style","border-block-start-width","border-block-style","border-block-width","border-inline","border-inline-color","border-inline-end","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-style","border-inline-width","content-visibility","margin-block","margin-block-end","margin-block-start","margin-inline","margin-inline-end","margin-inline-start","overflow-anchor","overscroll-behavior","padding-block","padding-block-end","padding-block-start","padding-inline","padding-inline-end","padding-inline-start","scroll-snap-stop","scrollbar-3d-light-color","scrollbar-arrow-color","scrollbar-base-color","scrollbar-dark-shadow-color","scrollbar-face-color","scrollbar-highlight-color","scrollbar-shadow-color","scrollbar-track-color","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","shape-inside","zoom"],p=t(f),h=t(["font-display","font-family","src","unicode-range","font-variant","font-feature-settings","font-stretch","font-weight","font-style"]),m=t(["additive-symbols","fallback","negative","pad","prefix","range","speak-as","suffix","symbols","system"]),g=["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"],v=t(g),y=["above","absolute","activeborder","additive","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alphabetic","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","attr","auto","auto-flow","avoid","avoid-column","avoid-page","avoid-region","axis-pan","background","backwards","baseline","below","bidi-override","binary","bengali","blink","block","block-axis","blur","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","brightness","bullets","button","buttonface","buttonhighlight","buttonshadow","buttontext","calc","cambodian","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-decimal","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","color","color-burn","color-dodge","column","column-reverse","compact","condensed","conic-gradient","contain","content","contents","content-box","context-menu","continuous","contrast","copy","counter","counters","cover","crop","cross","crosshair","cubic-bezier","currentcolor","cursive","cyclic","darken","dashed","decimal","decimal-leading-zero","default","default-button","dense","destination-atop","destination-in","destination-out","destination-over","devanagari","difference","disc","discard","disclosure-closed","disclosure-open","document","dot-dash","dot-dot-dash","dotted","double","down","drop-shadow","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ethiopic-numeric","ew-resize","exclusion","expanded","extends","extra-condensed","extra-expanded","fantasy","fast","fill","fill-box","fixed","flat","flex","flex-end","flex-start","footnotes","forwards","from","geometricPrecision","georgian","grayscale","graytext","grid","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hard-light","hebrew","help","hidden","hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","hue","hue-rotate","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-flex","inline-grid","inline-table","inset","inside","intrinsic","invert","italic","japanese-formal","japanese-informal","justify","kannada","katakana","katakana-iroha","keep-all","khmer","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","landscape","lao","large","larger","left","level","lighter","lighten","line-through","linear","linear-gradient","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","luminosity","malayalam","manipulation","match","matrix","matrix3d","media-play-button","media-slider","media-sliderthumb","media-volume-slider","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","multiple_mask_images","multiply","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","numbers","numeric","nw-resize","nwse-resize","oblique","octal","opacity","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","perspective","pinch-zoom","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radial-gradient","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeating-linear-gradient","repeating-radial-gradient","repeating-conic-gradient","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","rotate","rotate3d","rotateX","rotateY","rotateZ","round","row","row-resize","row-reverse","rtl","run-in","running","s-resize","sans-serif","saturate","saturation","scale","scale3d","scaleX","scaleY","scaleZ","screen","scroll","scrollbar","scroll-position","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","self-start","self-end","semi-condensed","semi-expanded","separate","sepia","serif","show","sidama","simp-chinese-formal","simp-chinese-informal","single","skew","skewX","skewY","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","soft-light","solid","somali","source-atop","source-in","source-out","source-over","space","space-around","space-between","space-evenly","spell-out","square","square-button","start","static","status-bar","stretch","stroke","stroke-box","sub","subpixel-antialiased","svg_masks","super","sw-resize","symbolic","symbols","system-ui","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","tamil","telugu","text","text-bottom","text-top","textarea","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","trad-chinese-formal","trad-chinese-informal","transform","translate","translate3d","translateX","translateY","translateZ","transparent","ultra-condensed","ultra-expanded","underline","unidirectional-pan","unset","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","var","vertical","vertical-text","view-box","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","words","wrap","wrap-reverse","x-large","x-small","xor","xx-large","xx-small"],b=t(y),w=r.concat(i).concat(a).concat(s).concat(u).concat(f).concat(g).concat(y);function C(e,t){for(var r,n=!1;null!=(r=e.next());){if(n&&"/"==r){t.tokenize=null;break}n="*"==r}return["comment","comment"]}e.registerHelper("hintWords","css",w),e.defineMIME("text/css",{documentTypes:n,mediaTypes:o,mediaFeatures:l,mediaValueKeywords:c,propertyKeywords:d,nonStandardPropertyKeywords:p,fontProperties:h,counterDescriptors:m,colorKeywords:v,valueKeywords:b,tokenHooks:{"/":function(e,t){return!!e.eat("*")&&(t.tokenize=C,C(e,t))}},name:"css"}),e.defineMIME("text/x-scss",{mediaTypes:o,mediaFeatures:l,mediaValueKeywords:c,propertyKeywords:d,nonStandardPropertyKeywords:p,colorKeywords:v,valueKeywords:b,fontProperties:h,allowNested:!0,lineComment:"//",tokenHooks:{"/":function(e,t){return e.eat("/")?(e.skipToEnd(),["comment","comment"]):e.eat("*")?(t.tokenize=C,C(e,t)):["operator","operator"]},":":function(e){return!!e.match(/^\s*\{/,!1)&&[null,null]},$:function(e){return e.match(/^[\w-]+/),e.match(/^\s*:/,!1)?["variable-2","variable-definition"]:["variable-2","variable"]},"#":function(e){return!!e.eat("{")&&[null,"interpolation"]}},name:"css",helperType:"scss"}),e.defineMIME("text/x-less",{mediaTypes:o,mediaFeatures:l,mediaValueKeywords:c,propertyKeywords:d,nonStandardPropertyKeywords:p,colorKeywords:v,valueKeywords:b,fontProperties:h,allowNested:!0,lineComment:"//",tokenHooks:{"/":function(e,t){return e.eat("/")?(e.skipToEnd(),["comment","comment"]):e.eat("*")?(t.tokenize=C,C(e,t)):["operator","operator"]},"@":function(e){return e.eat("{")?[null,"interpolation"]:!e.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/i,!1)&&(e.eatWhile(/[\w\\\-]/),e.match(/^\s*:/,!1)?["variable-2","variable-definition"]:["variable-2","variable"])},"&":function(){return["atom","atom"]}},name:"css",helperType:"less"}),e.defineMIME("text/x-gss",{documentTypes:n,mediaTypes:o,mediaFeatures:l,propertyKeywords:d,nonStandardPropertyKeywords:p,fontProperties:h,counterDescriptors:m,colorKeywords:v,valueKeywords:b,supportsAtComponent:!0,tokenHooks:{"/":function(e,t){return!!e.eat("*")&&(t.tokenize=C,C(e,t))}},name:"css",helperType:"gss"})}(r(631))},531:(e,t,r)=>{!function(e){"use strict";var t={script:[["lang",/(javascript|babel)/i,"javascript"],["type",/^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i,"javascript"],["type",/./,"text/plain"],[null,null,"javascript"]],style:[["lang",/^css$/i,"css"],["type",/^(text\/)?(x-)?(stylesheet|css)$/i,"css"],["type",/./,"text/plain"],[null,null,"css"]]};function r(e,t,r){var n=e.current(),i=n.search(t);return i>-1?e.backUp(n.length-i):n.match(/<\/?$/)&&(e.backUp(n.length),e.match(t,!1)||e.match(n)),r}var n={};function i(e){var t=n[e];return t||(n[e]=new RegExp("\\s+"+e+"\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*"))}function o(e,t){var r=e.match(i(t));return r?/^\s*(.*?)\s*$/.exec(r[2])[1]:""}function a(e,t){return new RegExp((t?"^":"")+"","i")}function l(e,t){for(var r in e)for(var n=t[r]||(t[r]=[]),i=e[r],o=i.length-1;o>=0;o--)n.unshift(i[o])}function s(e,t){for(var r=0;r=0;f--)c.script.unshift(["type",d[f].matches,d[f].mode]);function p(t,i){var l,u=o.token(t,i.htmlState),d=/\btag\b/.test(u);if(d&&!/[<>\s\/]/.test(t.current())&&(l=i.htmlState.tagName&&i.htmlState.tagName.toLowerCase())&&c.hasOwnProperty(l))i.inTag=l+" ";else if(i.inTag&&d&&/>$/.test(t.current())){var f=/^([\S]+) (.*)/.exec(i.inTag);i.inTag=null;var h=">"==t.current()&&s(c[f[1]],f[2]),m=e.getMode(n,h),g=a(f[1],!0),v=a(f[1],!1);i.token=function(e,t){return e.match(g,!1)?(t.token=p,t.localState=t.localMode=null,null):r(e,v,t.localMode.token(e,t.localState))},i.localMode=m,i.localState=e.startState(m,o.indent(i.htmlState,"",""))}else i.inTag&&(i.inTag+=t.current(),t.eol()&&(i.inTag+=" "));return u}return{startState:function(){return{token:p,inTag:null,localMode:null,localState:null,htmlState:e.startState(o)}},copyState:function(t){var r;return t.localState&&(r=e.copyState(t.localMode,t.localState)),{token:t.token,inTag:t.inTag,localMode:t.localMode,localState:r,htmlState:e.copyState(o,t.htmlState)}},token:function(e,t){return t.token(e,t)},indent:function(t,r,n){return!t.localMode||/^\s*<\//.test(r)?o.indent(t.htmlState,r,n):t.localMode.indent?t.localMode.indent(t.localState,r,n):e.Pass},innerMode:function(e){return{state:e.localState||e.htmlState,mode:e.localMode||o}}}}),"xml","javascript","css"),e.defineMIME("text/html","htmlmixed")}(r(631),r(589),r(876),r(629))},876:(e,t,r)=>{!function(e){"use strict";e.defineMode("javascript",(function(t,r){var n,i,o=t.indentUnit,a=r.statementIndent,l=r.jsonld,s=r.json||l,c=!1!==r.trackScope,u=r.typescript,d=r.wordCharacters||/[\w$\xa1-\uffff]/,f=function(){function e(e){return{type:e,style:"keyword"}}var t=e("keyword a"),r=e("keyword b"),n=e("keyword c"),i=e("keyword d"),o=e("operator"),a={type:"atom",style:"atom"};return{if:e("if"),while:t,with:t,else:r,do:r,try:r,finally:r,return:i,break:i,continue:i,new:e("new"),delete:n,void:n,throw:n,debugger:e("debugger"),var:e("var"),const:e("var"),let:e("var"),function:e("function"),catch:e("catch"),for:e("for"),switch:e("switch"),case:e("case"),default:e("default"),in:o,typeof:o,instanceof:o,true:a,false:a,null:a,undefined:a,NaN:a,Infinity:a,this:e("this"),class:e("class"),super:e("atom"),yield:n,export:e("export"),import:e("import"),extends:n,await:n}}(),p=/[+\-*&%=<>!?|~^@]/,h=/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;function m(e){for(var t,r=!1,n=!1;null!=(t=e.next());){if(!r){if("/"==t&&!n)return;"["==t?n=!0:n&&"]"==t&&(n=!1)}r=!r&&"\\"==t}}function g(e,t,r){return n=e,i=r,t}function v(e,t){var r=e.next();if('"'==r||"'"==r)return t.tokenize=y(r),t.tokenize(e,t);if("."==r&&e.match(/^\d[\d_]*(?:[eE][+\-]?[\d_]+)?/))return g("number","number");if("."==r&&e.match(".."))return g("spread","meta");if(/[\[\]{}\(\),;\:\.]/.test(r))return g(r);if("="==r&&e.eat(">"))return g("=>","operator");if("0"==r&&e.match(/^(?:x[\dA-Fa-f_]+|o[0-7_]+|b[01_]+)n?/))return g("number","number");if(/\d/.test(r))return e.match(/^[\d_]*(?:n|(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)?/),g("number","number");if("/"==r)return e.eat("*")?(t.tokenize=b,b(e,t)):e.eat("/")?(e.skipToEnd(),g("comment","comment")):it(e,t,1)?(m(e),e.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/),g("regexp","string-2")):(e.eat("="),g("operator","operator",e.current()));if("`"==r)return t.tokenize=w,w(e,t);if("#"==r&&"!"==e.peek())return e.skipToEnd(),g("meta","meta");if("#"==r&&e.eatWhile(d))return g("variable","property");if("<"==r&&e.match("!--")||"-"==r&&e.match("->")&&!/\S/.test(e.string.slice(0,e.start)))return e.skipToEnd(),g("comment","comment");if(p.test(r))return">"==r&&t.lexical&&">"==t.lexical.type||(e.eat("=")?"!"!=r&&"="!=r||e.eat("="):/[<>*+\-|&?]/.test(r)&&(e.eat(r),">"==r&&e.eat(r))),"?"==r&&e.eat(".")?g("."):g("operator","operator",e.current());if(d.test(r)){e.eatWhile(d);var n=e.current();if("."!=t.lastType){if(f.propertyIsEnumerable(n)){var i=f[n];return g(i.type,i.style,n)}if("async"==n&&e.match(/^(\s|\/\*([^*]|\*(?!\/))*?\*\/)*[\[\(\w]/,!1))return g("async","keyword",n)}return g("variable","variable",n)}}function y(e){return function(t,r){var n,i=!1;if(l&&"@"==t.peek()&&t.match(h))return r.tokenize=v,g("jsonld-keyword","meta");for(;null!=(n=t.next())&&(n!=e||i);)i=!i&&"\\"==n;return i||(r.tokenize=v),g("string","string")}}function b(e,t){for(var r,n=!1;r=e.next();){if("/"==r&&n){t.tokenize=v;break}n="*"==r}return g("comment","comment")}function w(e,t){for(var r,n=!1;null!=(r=e.next());){if(!n&&("`"==r||"$"==r&&e.eat("{"))){t.tokenize=v;break}n=!n&&"\\"==r}return g("quasi","string-2",e.current())}var C="([{}])";function x(e,t){t.fatArrowAt&&(t.fatArrowAt=null);var r=e.string.indexOf("=>",e.start);if(!(r<0)){if(u){var n=/:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(e.string.slice(e.start,r));n&&(r=n.index)}for(var i=0,o=!1,a=r-1;a>=0;--a){var l=e.string.charAt(a),s=C.indexOf(l);if(s>=0&&s<3){if(!i){++a;break}if(0==--i){"("==l&&(o=!0);break}}else if(s>=3&&s<6)++i;else if(d.test(l))o=!0;else if(/["'\/`]/.test(l))for(;;--a){if(0==a)return;if(e.string.charAt(a-1)==l&&"\\"!=e.string.charAt(a-2)){a--;break}}else if(o&&!i){++a;break}}o&&!i&&(t.fatArrowAt=a)}}var k={atom:!0,number:!0,variable:!0,string:!0,regexp:!0,this:!0,import:!0,"jsonld-keyword":!0};function A(e,t,r,n,i,o){this.indented=e,this.column=t,this.type=r,this.prev=i,this.info=o,null!=n&&(this.align=n)}function _(e,t){if(!c)return!1;for(var r=e.localVars;r;r=r.next)if(r.name==t)return!0;for(var n=e.context;n;n=n.prev)for(r=n.vars;r;r=r.next)if(r.name==t)return!0}function M(e,t,r,n,i){var o=e.cc;for(S.state=e,S.stream=i,S.marked=null,S.cc=o,S.style=t,e.lexical.hasOwnProperty("align")||(e.lexical.align=!0);;)if((o.length?o.pop():s?K:j)(r,n)){for(;o.length&&o[o.length-1].lex;)o.pop()();return S.marked?S.marked:"variable"==r&&_(e,n)?"variable-2":t}}var S={state:null,column:null,marked:null,cc:null};function T(){for(var e=arguments.length-1;e>=0;e--)S.cc.push(arguments[e])}function B(){return T.apply(null,arguments),!0}function L(e,t){for(var r=t;r;r=r.next)if(r.name==e)return!0;return!1}function E(e){var t=S.state;if(S.marked="def",c){if(t.context)if("var"==t.lexical.info&&t.context&&t.context.block){var n=N(e,t.context);if(null!=n)return void(t.context=n)}else if(!L(e,t.localVars))return void(t.localVars=new D(e,t.localVars));r.globalVars&&!L(e,t.globalVars)&&(t.globalVars=new D(e,t.globalVars))}}function N(e,t){if(t){if(t.block){var r=N(e,t.prev);return r?r==t.prev?t:new O(r,t.vars,!0):null}return L(e,t.vars)?t:new O(t.prev,new D(e,t.vars),!1)}return null}function z(e){return"public"==e||"private"==e||"protected"==e||"abstract"==e||"readonly"==e}function O(e,t,r){this.prev=e,this.vars=t,this.block=r}function D(e,t){this.name=e,this.next=t}var F=new D("this",new D("arguments",null));function I(){S.state.context=new O(S.state.context,S.state.localVars,!1),S.state.localVars=F}function P(){S.state.context=new O(S.state.context,S.state.localVars,!0),S.state.localVars=null}function q(){S.state.localVars=S.state.context.vars,S.state.context=S.state.context.prev}function W(e,t){var r=function(){var r=S.state,n=r.indented;if("stat"==r.lexical.type)n=r.lexical.indented;else for(var i=r.lexical;i&&")"==i.type&&i.align;i=i.prev)n=i.indented;r.lexical=new A(n,S.stream.column(),e,null,r.lexical,t)};return r.lex=!0,r}function H(){var e=S.state;e.lexical.prev&&(")"==e.lexical.type&&(e.indented=e.lexical.indented),e.lexical=e.lexical.prev)}function R(e){function t(r){return r==e?B():";"==e||"}"==r||")"==r||"]"==r?T():B(t)}return t}function j(e,t){return"var"==e?B(W("vardef",t),Te,R(";"),H):"keyword a"==e?B(W("form"),V,j,H):"keyword b"==e?B(W("form"),j,H):"keyword d"==e?S.stream.match(/^\s*$/,!1)?B():B(W("stat"),Y,R(";"),H):"debugger"==e?B(R(";")):"{"==e?B(W("}"),P,fe,H,q):";"==e?B():"if"==e?("else"==S.state.lexical.info&&S.state.cc[S.state.cc.length-1]==H&&S.state.cc.pop()(),B(W("form"),V,j,H,Oe)):"function"==e?B(Pe):"for"==e?B(W("form"),P,De,j,q,H):"class"==e||u&&"interface"==t?(S.marked="keyword",B(W("form","class"==e?e:t),je,H)):"variable"==e?u&&"declare"==t?(S.marked="keyword",B(j)):u&&("module"==t||"enum"==t||"type"==t)&&S.stream.match(/^\s*\w/,!1)?(S.marked="keyword","enum"==t?B(tt):"type"==t?B(We,R("operator"),ve,R(";")):B(W("form"),Be,R("{"),W("}"),fe,H,H)):u&&"namespace"==t?(S.marked="keyword",B(W("form"),K,j,H)):u&&"abstract"==t?(S.marked="keyword",B(j)):B(W("stat"),oe):"switch"==e?B(W("form"),V,R("{"),W("}","switch"),P,fe,H,H,q):"case"==e?B(K,R(":")):"default"==e?B(R(":")):"catch"==e?B(W("form"),I,U,j,H,q):"export"==e?B(W("stat"),Ve,H):"import"==e?B(W("stat"),Ye,H):"async"==e?B(j):"@"==t?B(K,j):T(W("stat"),K,R(";"),H)}function U(e){if("("==e)return B(He,R(")"))}function K(e,t){return $(e,t,!1)}function G(e,t){return $(e,t,!0)}function V(e){return"("!=e?T():B(W(")"),Y,R(")"),H)}function $(e,t,r){if(S.state.fatArrowAt==S.stream.start){var n=r?te:ee;if("("==e)return B(I,W(")"),ue(He,")"),H,R("=>"),n,q);if("variable"==e)return T(I,Be,R("=>"),n,q)}var i=r?Z:X;return k.hasOwnProperty(e)?B(i):"function"==e?B(Pe,i):"class"==e||u&&"interface"==t?(S.marked="keyword",B(W("form"),Re,H)):"keyword c"==e||"async"==e?B(r?G:K):"("==e?B(W(")"),Y,R(")"),H,i):"operator"==e||"spread"==e?B(r?G:K):"["==e?B(W("]"),et,H,i):"{"==e?de(le,"}",null,i):"quasi"==e?T(Q,i):"new"==e?B(re(r)):B()}function Y(e){return e.match(/[;\}\)\],]/)?T():T(K)}function X(e,t){return","==e?B(Y):Z(e,t,!1)}function Z(e,t,r){var n=0==r?X:Z,i=0==r?K:G;return"=>"==e?B(I,r?te:ee,q):"operator"==e?/\+\+|--/.test(t)||u&&"!"==t?B(n):u&&"<"==t&&S.stream.match(/^([^<>]|<[^<>]*>)*>\s*\(/,!1)?B(W(">"),ue(ve,">"),H,n):"?"==t?B(K,R(":"),i):B(i):"quasi"==e?T(Q,n):";"!=e?"("==e?de(G,")","call",n):"."==e?B(ae,n):"["==e?B(W("]"),Y,R("]"),H,n):u&&"as"==t?(S.marked="keyword",B(ve,n)):"regexp"==e?(S.state.lastType=S.marked="operator",S.stream.backUp(S.stream.pos-S.stream.start-1),B(i)):void 0:void 0}function Q(e,t){return"quasi"!=e?T():"${"!=t.slice(t.length-2)?B(Q):B(Y,J)}function J(e){if("}"==e)return S.marked="string-2",S.state.tokenize=w,B(Q)}function ee(e){return x(S.stream,S.state),T("{"==e?j:K)}function te(e){return x(S.stream,S.state),T("{"==e?j:G)}function re(e){return function(t){return"."==t?B(e?ie:ne):"variable"==t&&u?B(_e,e?Z:X):T(e?G:K)}}function ne(e,t){if("target"==t)return S.marked="keyword",B(X)}function ie(e,t){if("target"==t)return S.marked="keyword",B(Z)}function oe(e){return":"==e?B(H,j):T(X,R(";"),H)}function ae(e){if("variable"==e)return S.marked="property",B()}function le(e,t){return"async"==e?(S.marked="property",B(le)):"variable"==e||"keyword"==S.style?(S.marked="property","get"==t||"set"==t?B(se):(u&&S.state.fatArrowAt==S.stream.start&&(r=S.stream.match(/^\s*:\s*/,!1))&&(S.state.fatArrowAt=S.stream.pos+r[0].length),B(ce))):"number"==e||"string"==e?(S.marked=l?"property":S.style+" property",B(ce)):"jsonld-keyword"==e?B(ce):u&&z(t)?(S.marked="keyword",B(le)):"["==e?B(K,pe,R("]"),ce):"spread"==e?B(G,ce):"*"==t?(S.marked="keyword",B(le)):":"==e?T(ce):void 0;var r}function se(e){return"variable"!=e?T(ce):(S.marked="property",B(Pe))}function ce(e){return":"==e?B(G):"("==e?T(Pe):void 0}function ue(e,t,r){function n(i,o){if(r?r.indexOf(i)>-1:","==i){var a=S.state.lexical;return"call"==a.info&&(a.pos=(a.pos||0)+1),B((function(r,n){return r==t||n==t?T():T(e)}),n)}return i==t||o==t?B():r&&r.indexOf(";")>-1?T(e):B(R(t))}return function(r,i){return r==t||i==t?B():T(e,n)}}function de(e,t,r){for(var n=3;n"),ve):"quasi"==e?T(Ce,Ae):void 0}function ye(e){if("=>"==e)return B(ve)}function be(e){return e.match(/[\}\)\]]/)?B():","==e||";"==e?B(be):T(we,be)}function we(e,t){return"variable"==e||"keyword"==S.style?(S.marked="property",B(we)):"?"==t||"number"==e||"string"==e?B(we):":"==e?B(ve):"["==e?B(R("variable"),he,R("]"),we):"("==e?T(qe,we):e.match(/[;\}\)\],]/)?void 0:B()}function Ce(e,t){return"quasi"!=e?T():"${"!=t.slice(t.length-2)?B(Ce):B(ve,xe)}function xe(e){if("}"==e)return S.marked="string-2",S.state.tokenize=w,B(Ce)}function ke(e,t){return"variable"==e&&S.stream.match(/^\s*[?:]/,!1)||"?"==t?B(ke):":"==e?B(ve):"spread"==e?B(ke):T(ve)}function Ae(e,t){return"<"==t?B(W(">"),ue(ve,">"),H,Ae):"|"==t||"."==e||"&"==t?B(ve):"["==e?B(ve,R("]"),Ae):"extends"==t||"implements"==t?(S.marked="keyword",B(ve)):"?"==t?B(ve,R(":"),ve):void 0}function _e(e,t){if("<"==t)return B(W(">"),ue(ve,">"),H,Ae)}function Me(){return T(ve,Se)}function Se(e,t){if("="==t)return B(ve)}function Te(e,t){return"enum"==t?(S.marked="keyword",B(tt)):T(Be,pe,Ne,ze)}function Be(e,t){return u&&z(t)?(S.marked="keyword",B(Be)):"variable"==e?(E(t),B()):"spread"==e?B(Be):"["==e?de(Ee,"]"):"{"==e?de(Le,"}"):void 0}function Le(e,t){return"variable"!=e||S.stream.match(/^\s*:/,!1)?("variable"==e&&(S.marked="property"),"spread"==e?B(Be):"}"==e?T():"["==e?B(K,R("]"),R(":"),Le):B(R(":"),Be,Ne)):(E(t),B(Ne))}function Ee(){return T(Be,Ne)}function Ne(e,t){if("="==t)return B(G)}function ze(e){if(","==e)return B(Te)}function Oe(e,t){if("keyword b"==e&&"else"==t)return B(W("form","else"),j,H)}function De(e,t){return"await"==t?B(De):"("==e?B(W(")"),Fe,H):void 0}function Fe(e){return"var"==e?B(Te,Ie):"variable"==e?B(Ie):T(Ie)}function Ie(e,t){return")"==e?B():";"==e?B(Ie):"in"==t||"of"==t?(S.marked="keyword",B(K,Ie)):T(K,Ie)}function Pe(e,t){return"*"==t?(S.marked="keyword",B(Pe)):"variable"==e?(E(t),B(Pe)):"("==e?B(I,W(")"),ue(He,")"),H,me,j,q):u&&"<"==t?B(W(">"),ue(Me,">"),H,Pe):void 0}function qe(e,t){return"*"==t?(S.marked="keyword",B(qe)):"variable"==e?(E(t),B(qe)):"("==e?B(I,W(")"),ue(He,")"),H,me,q):u&&"<"==t?B(W(">"),ue(Me,">"),H,qe):void 0}function We(e,t){return"keyword"==e||"variable"==e?(S.marked="type",B(We)):"<"==t?B(W(">"),ue(Me,">"),H):void 0}function He(e,t){return"@"==t&&B(K,He),"spread"==e?B(He):u&&z(t)?(S.marked="keyword",B(He)):u&&"this"==e?B(pe,Ne):T(Be,pe,Ne)}function Re(e,t){return"variable"==e?je(e,t):Ue(e,t)}function je(e,t){if("variable"==e)return E(t),B(Ue)}function Ue(e,t){return"<"==t?B(W(">"),ue(Me,">"),H,Ue):"extends"==t||"implements"==t||u&&","==e?("implements"==t&&(S.marked="keyword"),B(u?ve:K,Ue)):"{"==e?B(W("}"),Ke,H):void 0}function Ke(e,t){return"async"==e||"variable"==e&&("static"==t||"get"==t||"set"==t||u&&z(t))&&S.stream.match(/^\s+[\w$\xa1-\uffff]/,!1)?(S.marked="keyword",B(Ke)):"variable"==e||"keyword"==S.style?(S.marked="property",B(Ge,Ke)):"number"==e||"string"==e?B(Ge,Ke):"["==e?B(K,pe,R("]"),Ge,Ke):"*"==t?(S.marked="keyword",B(Ke)):u&&"("==e?T(qe,Ke):";"==e||","==e?B(Ke):"}"==e?B():"@"==t?B(K,Ke):void 0}function Ge(e,t){if("!"==t)return B(Ge);if("?"==t)return B(Ge);if(":"==e)return B(ve,Ne);if("="==t)return B(G);var r=S.state.lexical.prev;return T(r&&"interface"==r.info?qe:Pe)}function Ve(e,t){return"*"==t?(S.marked="keyword",B(Je,R(";"))):"default"==t?(S.marked="keyword",B(K,R(";"))):"{"==e?B(ue($e,"}"),Je,R(";")):T(j)}function $e(e,t){return"as"==t?(S.marked="keyword",B(R("variable"))):"variable"==e?T(G,$e):void 0}function Ye(e){return"string"==e?B():"("==e?T(K):"."==e?T(X):T(Xe,Ze,Je)}function Xe(e,t){return"{"==e?de(Xe,"}"):("variable"==e&&E(t),"*"==t&&(S.marked="keyword"),B(Qe))}function Ze(e){if(","==e)return B(Xe,Ze)}function Qe(e,t){if("as"==t)return S.marked="keyword",B(Xe)}function Je(e,t){if("from"==t)return S.marked="keyword",B(K)}function et(e){return"]"==e?B():T(ue(G,"]"))}function tt(){return T(W("form"),Be,R("{"),W("}"),ue(rt,"}"),H,H)}function rt(){return T(Be,Ne)}function nt(e,t){return"operator"==e.lastType||","==e.lastType||p.test(t.charAt(0))||/[,.]/.test(t.charAt(0))}function it(e,t,r){return t.tokenize==v&&/^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(t.lastType)||"quasi"==t.lastType&&/\{\s*$/.test(e.string.slice(0,e.pos-(r||0)))}return I.lex=P.lex=!0,q.lex=!0,H.lex=!0,{startState:function(e){var t={tokenize:v,lastType:"sof",cc:[],lexical:new A((e||0)-o,0,"block",!1),localVars:r.localVars,context:r.localVars&&new O(null,null,!1),indented:e||0};return r.globalVars&&"object"==typeof r.globalVars&&(t.globalVars=r.globalVars),t},token:function(e,t){if(e.sol()&&(t.lexical.hasOwnProperty("align")||(t.lexical.align=!1),t.indented=e.indentation(),x(e,t)),t.tokenize!=b&&e.eatSpace())return null;var r=t.tokenize(e,t);return"comment"==n?r:(t.lastType="operator"!=n||"++"!=i&&"--"!=i?n:"incdec",M(t,r,n,i,e))},indent:function(t,n){if(t.tokenize==b||t.tokenize==w)return e.Pass;if(t.tokenize!=v)return 0;var i,l=n&&n.charAt(0),s=t.lexical;if(!/^\s*else\b/.test(n))for(var c=t.cc.length-1;c>=0;--c){var u=t.cc[c];if(u==H)s=s.prev;else if(u!=Oe&&u!=q)break}for(;("stat"==s.type||"form"==s.type)&&("}"==l||(i=t.cc[t.cc.length-1])&&(i==X||i==Z)&&!/^[,\.=+\-*:?[\(]/.test(n));)s=s.prev;a&&")"==s.type&&"stat"==s.prev.type&&(s=s.prev);var d=s.type,f=l==d;return"vardef"==d?s.indented+("operator"==t.lastType||","==t.lastType?s.info.length+1:0):"form"==d&&"{"==l?s.indented:"form"==d?s.indented+o:"stat"==d?s.indented+(nt(t,n)?a||o:0):"switch"!=s.info||f||0==r.doubleIndentSwitch?s.align?s.column+(f?0:1):s.indented+(f?0:o):s.indented+(/^(?:case|default)\b/.test(n)?o:2*o)},electricInput:/^\s*(?:case .*?:|default:|\{|\})$/,blockCommentStart:s?null:"/*",blockCommentEnd:s?null:"*/",blockCommentContinue:s?null:" * ",lineComment:s?null:"//",fold:"brace",closeBrackets:"()[]{}''\"\"``",helperType:s?"json":"javascript",jsonldMode:l,jsonMode:s,expressionAllowed:it,skipExpression:function(t){M(t,"atom","atom","true",new e.StringStream("",2,null))}}})),e.registerHelper("wordChars","javascript",/[\w$]/),e.defineMIME("text/javascript","javascript"),e.defineMIME("text/ecmascript","javascript"),e.defineMIME("application/javascript","javascript"),e.defineMIME("application/x-javascript","javascript"),e.defineMIME("application/ecmascript","javascript"),e.defineMIME("application/json",{name:"javascript",json:!0}),e.defineMIME("application/x-json",{name:"javascript",json:!0}),e.defineMIME("application/manifest+json",{name:"javascript",json:!0}),e.defineMIME("application/ld+json",{name:"javascript",jsonld:!0}),e.defineMIME("text/typescript",{name:"javascript",typescript:!0}),e.defineMIME("application/typescript",{name:"javascript",typescript:!0})}(r(631))},959:(e,t,r)=>{!function(e){"use strict";function t(e){for(var t={},r=e.split(" "),n=0;n\w/,!1)&&(t.tokenize=r([[["->",null]],[[/[\w]+/,"variable"]]],n,i)),"variable-2";for(var o=!1;!e.eol()&&(o||!1===i||!e.match("{$",!1)&&!e.match(/^(\$[a-zA-Z_][a-zA-Z0-9_]*|\$\{)/,!1));){if(!o&&e.match(n)){t.tokenize=null,t.tokStack.pop(),t.tokStack.pop();break}o="\\"==e.next()&&!o}return"string"}var o="abstract and array as break case catch class clone const continue declare default do else elseif enddeclare endfor endforeach endif endswitch endwhile enum extends final for foreach function global goto if implements interface instanceof namespace new or private protected public static switch throw trait try use var while xor die echo empty exit eval include include_once isset list require require_once return print unset __halt_compiler self static parent yield insteadof finally readonly match",a="true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__",l="func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage memory_get_peak_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents file_put_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists array_intersect_key array_combine array_column pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once json_decode json_encode json_last_error json_last_error_msg curl_close curl_copy_handle curl_errno curl_error curl_escape curl_exec curl_file_create curl_getinfo curl_init curl_multi_add_handle curl_multi_close curl_multi_exec curl_multi_getcontent curl_multi_info_read curl_multi_init curl_multi_remove_handle curl_multi_select curl_multi_setopt curl_multi_strerror curl_pause curl_reset curl_setopt_array curl_setopt curl_share_close curl_share_init curl_share_setopt curl_strerror curl_unescape curl_version mysqli_affected_rows mysqli_autocommit mysqli_change_user mysqli_character_set_name mysqli_close mysqli_commit mysqli_connect_errno mysqli_connect_error mysqli_connect mysqli_data_seek mysqli_debug mysqli_dump_debug_info mysqli_errno mysqli_error_list mysqli_error mysqli_fetch_all mysqli_fetch_array mysqli_fetch_assoc mysqli_fetch_field_direct mysqli_fetch_field mysqli_fetch_fields mysqli_fetch_lengths mysqli_fetch_object mysqli_fetch_row mysqli_field_count mysqli_field_seek mysqli_field_tell mysqli_free_result mysqli_get_charset mysqli_get_client_info mysqli_get_client_stats mysqli_get_client_version mysqli_get_connection_stats mysqli_get_host_info mysqli_get_proto_info mysqli_get_server_info mysqli_get_server_version mysqli_info mysqli_init mysqli_insert_id mysqli_kill mysqli_more_results mysqli_multi_query mysqli_next_result mysqli_num_fields mysqli_num_rows mysqli_options mysqli_ping mysqli_prepare mysqli_query mysqli_real_connect mysqli_real_escape_string mysqli_real_query mysqli_reap_async_query mysqli_refresh mysqli_rollback mysqli_select_db mysqli_set_charset mysqli_set_local_infile_default mysqli_set_local_infile_handler mysqli_sqlstate mysqli_ssl_set mysqli_stat mysqli_stmt_init mysqli_store_result mysqli_thread_id mysqli_thread_safe mysqli_use_result mysqli_warning_count";e.registerHelper("hintWords","php",[o,a,l].join(" ").split(" ")),e.registerHelper("wordChars","php",/[\w$]/);var s={name:"clike",helperType:"php",keywords:t(o),blockKeywords:t("catch do else elseif for foreach if switch try while finally"),defKeywords:t("class enum function interface namespace trait"),atoms:t(a),builtin:t(l),multiLineStrings:!0,hooks:{$:function(e){return e.eatWhile(/[\w\$_]/),"variable-2"},"<":function(e,t){var r;if(r=e.match(/^<<\s*/)){var i=e.eat(/['"]/);e.eatWhile(/[\w\.]/);var o=e.current().slice(r[0].length+(i?2:1));if(i&&e.eat(i),o)return(t.tokStack||(t.tokStack=[])).push(o,0),t.tokenize=n(o,"'"!=i),"string"}return!1},"#":function(e){for(;!e.eol()&&!e.match("?>",!1);)e.next();return"comment"},"/":function(e){if(e.eat("/")){for(;!e.eol()&&!e.match("?>",!1);)e.next();return"comment"}return!1},'"':function(e,t){return(t.tokStack||(t.tokStack=[])).push('"',0),t.tokenize=n('"'),"string"},"{":function(e,t){return t.tokStack&&t.tokStack.length&&t.tokStack[t.tokStack.length-1]++,!1},"}":function(e,t){return t.tokStack&&t.tokStack.length>0&&!--t.tokStack[t.tokStack.length-1]&&(t.tokenize=n(t.tokStack[t.tokStack.length-2])),!1}}};e.defineMode("php",(function(t,r){var n=e.getMode(t,r&&r.htmlMode||"text/html"),i=e.getMode(t,s);function o(t,r){var o=r.curMode==i;if(t.sol()&&r.pending&&'"'!=r.pending&&"'"!=r.pending&&(r.pending=null),o)return o&&null==r.php.tokenize&&t.match("?>")?(r.curMode=n,r.curState=r.html,r.php.context.prev||(r.php=null),"meta"):i.token(t,r.curState);if(t.match(/^<\?\w*/))return r.curMode=i,r.php||(r.php=e.startState(i,n.indent(r.html,"",""))),r.curState=r.php,"meta";if('"'==r.pending||"'"==r.pending){for(;!t.eol()&&t.next()!=r.pending;);var a="string"}else r.pending&&t.pos/.test(s)?r.pending=l[0]:r.pending={end:t.pos,style:a},t.backUp(s.length-c)),a}return{startState:function(){var t=e.startState(n),o=r.startOpen?e.startState(i):null;return{html:t,php:o,curMode:r.startOpen?i:n,curState:r.startOpen?o:t,pending:null}},copyState:function(t){var r,o=t.html,a=e.copyState(n,o),l=t.php,s=l&&e.copyState(i,l);return r=t.curMode==n?a:s,{html:a,php:s,curMode:t.curMode,curState:r,pending:t.pending}},token:o,indent:function(e,t,r){return e.curMode!=i&&/^\s*<\//.test(t)||e.curMode==i&&/^\?>/.test(t)?n.indent(e.html,t,r):e.curMode.indent(e.curState,t,r)},blockCommentStart:"/*",blockCommentEnd:"*/",lineComment:"//",innerMode:function(e){return{state:e.curState,mode:e.curMode}}}}),"htmlmixed","clike"),e.defineMIME("application/x-httpd-php","php"),e.defineMIME("application/x-httpd-php-open",{name:"php",startOpen:!0}),e.defineMIME("text/x-php",s)}(r(631),r(531),r(762))},702:(e,t,r)=>{!function(e){"use strict";e.defineMode("twig:inner",(function(){var e=["and","as","autoescape","endautoescape","block","do","endblock","else","elseif","extends","for","endfor","embed","endembed","filter","endfilter","flush","from","if","endif","in","is","include","import","not","or","set","spaceless","endspaceless","with","endwith","trans","endtrans","blocktrans","endblocktrans","macro","endmacro","use","verbatim","endverbatim"],t=/^[+\-*&%=<>!?|~^]/,r=/^[:\[\(\{]/,n=["true","false","null","empty","defined","divisibleby","divisible by","even","odd","iterable","sameas","same as"],i=/^(\d[+\-\*\/])?\d+(\.\d+)?/;function o(o,a){var l=o.peek();if(a.incomment)return o.skipTo("#}")?(o.eatWhile(/\#|}/),a.incomment=!1):o.skipToEnd(),"comment";if(a.intag){if(a.operator){if(a.operator=!1,o.match(n))return"atom";if(o.match(i))return"number"}if(a.sign){if(a.sign=!1,o.match(n))return"atom";if(o.match(i))return"number"}if(a.instring)return l==a.instring&&(a.instring=!1),o.next(),"string";if("'"==l||'"'==l)return a.instring=l,o.next(),"string";if(o.match(a.intag+"}")||o.eat("-")&&o.match(a.intag+"}"))return a.intag=!1,"tag";if(o.match(t))return a.operator=!0,"operator";if(o.match(r))a.sign=!0;else if(o.eat(" ")||o.sol()){if(o.match(e))return"keyword";if(o.match(n))return"atom";if(o.match(i))return"number";o.sol()&&o.next()}else o.next();return"variable"}if(o.eat("{")){if(o.eat("#"))return a.incomment=!0,o.skipTo("#}")?(o.eatWhile(/\#|}/),a.incomment=!1):o.skipToEnd(),"comment";if(l=o.eat(/\{|%/))return a.intag=l,"{"==l&&(a.intag="}"),o.eat("-"),"tag"}o.next()}return e=new RegExp("(("+e.join(")|(")+"))\\b"),n=new RegExp("(("+n.join(")|(")+"))\\b"),{startState:function(){return{}},token:function(e,t){return o(e,t)}}})),e.defineMode("twig",(function(t,r){var n=e.getMode(t,"twig:inner");return r&&r.base?e.multiplexingMode(e.getMode(t,r.base),{open:/\{[{#%]/,close:/[}#%]\}/,mode:n,parseDelimiters:!0}):n})),e.defineMIME("text/x-twig","twig")}(r(631),r(93))},589:(e,t,r)=>{!function(e){"use strict";var t={autoSelfClosers:{area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,frame:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0,menuitem:!0},implicitlyClosed:{dd:!0,li:!0,optgroup:!0,option:!0,p:!0,rp:!0,rt:!0,tbody:!0,td:!0,tfoot:!0,th:!0,tr:!0},contextGrabbers:{dd:{dd:!0,dt:!0},dt:{dd:!0,dt:!0},li:{li:!0},option:{option:!0,optgroup:!0},optgroup:{optgroup:!0},p:{address:!0,article:!0,aside:!0,blockquote:!0,dir:!0,div:!0,dl:!0,fieldset:!0,footer:!0,form:!0,h1:!0,h2:!0,h3:!0,h4:!0,h5:!0,h6:!0,header:!0,hgroup:!0,hr:!0,menu:!0,nav:!0,ol:!0,p:!0,pre:!0,section:!0,table:!0,ul:!0},rp:{rp:!0,rt:!0},rt:{rp:!0,rt:!0},tbody:{tbody:!0,tfoot:!0},td:{td:!0,th:!0},tfoot:{tbody:!0},th:{td:!0,th:!0},thead:{tbody:!0,tfoot:!0},tr:{tr:!0}},doNotIndent:{pre:!0},allowUnquoted:!0,allowMissing:!0,caseFold:!0},r={autoSelfClosers:{},implicitlyClosed:{},contextGrabbers:{},doNotIndent:{},allowUnquoted:!1,allowMissing:!1,allowMissingTagName:!1,caseFold:!1};e.defineMode("xml",(function(n,i){var o,a,l=n.indentUnit,s={},c=i.htmlMode?t:r;for(var u in c)s[u]=c[u];for(var u in i)s[u]=i[u];function d(e,t){function r(r){return t.tokenize=r,r(e,t)}var n=e.next();return"<"==n?e.eat("!")?e.eat("[")?e.match("CDATA[")?r(h("atom","]]>")):null:e.match("--")?r(h("comment","--\x3e")):e.match("DOCTYPE",!0,!0)?(e.eatWhile(/[\w\._\-]/),r(m(1))):null:e.eat("?")?(e.eatWhile(/[\w\._\-]/),t.tokenize=h("meta","?>"),"meta"):(o=e.eat("/")?"closeTag":"openTag",t.tokenize=f,"tag bracket"):"&"==n?(e.eat("#")?e.eat("x")?e.eatWhile(/[a-fA-F\d]/)&&e.eat(";"):e.eatWhile(/[\d]/)&&e.eat(";"):e.eatWhile(/[\w\.\-:]/)&&e.eat(";"))?"atom":"error":(e.eatWhile(/[^&<]/),null)}function f(e,t){var r=e.next();if(">"==r||"/"==r&&e.eat(">"))return t.tokenize=d,o=">"==r?"endTag":"selfcloseTag","tag bracket";if("="==r)return o="equals",null;if("<"==r){t.tokenize=d,t.state=w,t.tagName=t.tagStart=null;var n=t.tokenize(e,t);return n?n+" tag error":"tag error"}return/[\'\"]/.test(r)?(t.tokenize=p(r),t.stringStartCol=e.column(),t.tokenize(e,t)):(e.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/),"word")}function p(e){var t=function(t,r){for(;!t.eol();)if(t.next()==e){r.tokenize=f;break}return"string"};return t.isInAttribute=!0,t}function h(e,t){return function(r,n){for(;!r.eol();){if(r.match(t)){n.tokenize=d;break}r.next()}return e}}function m(e){return function(t,r){for(var n;null!=(n=t.next());){if("<"==n)return r.tokenize=m(e+1),r.tokenize(t,r);if(">"==n){if(1==e){r.tokenize=d;break}return r.tokenize=m(e-1),r.tokenize(t,r)}}return"meta"}}function g(e){return e&&e.toLowerCase()}function v(e,t,r){this.prev=e.context,this.tagName=t||"",this.indent=e.indented,this.startOfLine=r,(s.doNotIndent.hasOwnProperty(t)||e.context&&e.context.noIndent)&&(this.noIndent=!0)}function y(e){e.context&&(e.context=e.context.prev)}function b(e,t){for(var r;;){if(!e.context)return;if(r=e.context.tagName,!s.contextGrabbers.hasOwnProperty(g(r))||!s.contextGrabbers[g(r)].hasOwnProperty(g(t)))return;y(e)}}function w(e,t,r){return"openTag"==e?(r.tagStart=t.column(),C):"closeTag"==e?x:w}function C(e,t,r){return"word"==e?(r.tagName=t.current(),a="tag",_):s.allowMissingTagName&&"endTag"==e?(a="tag bracket",_(e,t,r)):(a="error",C)}function x(e,t,r){if("word"==e){var n=t.current();return r.context&&r.context.tagName!=n&&s.implicitlyClosed.hasOwnProperty(g(r.context.tagName))&&y(r),r.context&&r.context.tagName==n||!1===s.matchClosing?(a="tag",k):(a="tag error",A)}return s.allowMissingTagName&&"endTag"==e?(a="tag bracket",k(e,t,r)):(a="error",A)}function k(e,t,r){return"endTag"!=e?(a="error",k):(y(r),w)}function A(e,t,r){return a="error",k(e,t,r)}function _(e,t,r){if("word"==e)return a="attribute",M;if("endTag"==e||"selfcloseTag"==e){var n=r.tagName,i=r.tagStart;return r.tagName=r.tagStart=null,"selfcloseTag"==e||s.autoSelfClosers.hasOwnProperty(g(n))?b(r,n):(b(r,n),r.context=new v(r,n,i==r.indented)),w}return a="error",_}function M(e,t,r){return"equals"==e?S:(s.allowMissing||(a="error"),_(e,t,r))}function S(e,t,r){return"string"==e?T:"word"==e&&s.allowUnquoted?(a="string",_):(a="error",_(e,t,r))}function T(e,t,r){return"string"==e?T:_(e,t,r)}return d.isInText=!0,{startState:function(e){var t={tokenize:d,state:w,indented:e||0,tagName:null,tagStart:null,context:null};return null!=e&&(t.baseIndent=e),t},token:function(e,t){if(!t.tagName&&e.sol()&&(t.indented=e.indentation()),e.eatSpace())return null;o=null;var r=t.tokenize(e,t);return(r||o)&&"comment"!=r&&(a=null,t.state=t.state(o||r,e,t),a&&(r="error"==a?r+" error":a)),r},indent:function(t,r,n){var i=t.context;if(t.tokenize.isInAttribute)return t.tagStart==t.indented?t.stringStartCol+1:t.indented+l;if(i&&i.noIndent)return e.Pass;if(t.tokenize!=f&&t.tokenize!=d)return n?n.match(/^(\s*)/)[0].length:0;if(t.tagName)return!1!==s.multilineTagIndentPastTag?t.tagStart+t.tagName.length+2:t.tagStart+l*(s.multilineTagIndentFactor||1);if(s.alignCDATA&&/$/,blockCommentStart:"\x3c!--",blockCommentEnd:"--\x3e",configuration:s.htmlMode?"html":"xml",helperType:s.htmlMode?"html":"xml",skipAttribute:function(e){e.state==S&&(e.state=_)},xmlCurrentTag:function(e){return e.tagName?{name:e.tagName,close:"closeTag"==e.type}:null},xmlCurrentContext:function(e){for(var t=[],r=e.context;r;r=r.prev)t.push(r.tagName);return t.reverse()}}})),e.defineMIME("text/xml","xml"),e.defineMIME("application/xml","xml"),e.mimeModes.hasOwnProperty("text/html")||e.defineMIME("text/html",{name:"xml",htmlMode:!0})}(r(631))},789:(e,t,r)=>{"use strict";r.d(t,{Z:()=>l});var n=r(15),i=r.n(n),o=r(645),a=r.n(o)()(i());a.push([e.id,'.CodeMirror{color:#000;direction:ltr;font-family:monospace;height:300px}.CodeMirror-lines{padding:4px 0}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{padding:0 4px}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{background-color:#f7f7f7;border-right:1px solid #ddd;white-space:nowrap}.CodeMirror-linenumber{color:#999;min-width:20px;padding:0 3px 0 5px;text-align:right;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid #000;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{background:#7e7;border:0!important;width:auto}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-fat-cursor .CodeMirror-line::selection,.cm-fat-cursor .CodeMirror-line>span::selection,.cm-fat-cursor .CodeMirror-line>span>span::selection{background:transparent}.cm-fat-cursor .CodeMirror-line::-moz-selection,.cm-fat-cursor .CodeMirror-line>span::-moz-selection,.cm-fat-cursor .CodeMirror-line>span>span::-moz-selection{background:transparent}.cm-fat-cursor{caret-color:transparent}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{bottom:0;left:0;overflow:hidden;position:absolute;right:0;top:-50px}.CodeMirror-ruler{border-left:1px solid #ccc;bottom:0;position:absolute;top:0}.cm-s-default .cm-header{color:blue}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-type,.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-invalidchar,.cm-s-default .cm-error{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{background:#fff;overflow:hidden;position:relative}.CodeMirror-scroll{height:100%;margin-bottom:-50px;margin-right:-50px;outline:none;overflow:scroll!important;padding-bottom:50px;position:relative;z-index:0}.CodeMirror-sizer{border-right:50px solid transparent;position:relative}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{display:none;outline:none;position:absolute;z-index:6}.CodeMirror-vscrollbar{overflow-x:hidden;overflow-y:scroll;right:0;top:0}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-x:scroll;overflow-y:hidden}.CodeMirror-scrollbar-filler{bottom:0;right:0}.CodeMirror-gutter-filler{bottom:0;left:0}.CodeMirror-gutters{left:0;min-height:100%;position:absolute;top:0;z-index:3}.CodeMirror-gutter{display:inline-block;height:100%;margin-bottom:-50px;vertical-align:top;white-space:normal}.CodeMirror-gutter-wrapper{background:none!important;border:none!important;position:absolute;z-index:4}.CodeMirror-gutter-background{bottom:0;position:absolute;top:0;z-index:4}.CodeMirror-gutter-elt{cursor:default;position:absolute;z-index:4}.CodeMirror-gutter-wrapper ::selection{background-color:transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{word-wrap:normal;-webkit-tap-highlight-color:transparent;background:transparent;border-radius:0;border-width:0;color:inherit;font-family:inherit;font-size:inherit;font-variant-ligatures:contextual;line-height:inherit;margin:0;overflow:visible;position:relative;white-space:pre;z-index:2}.CodeMirror-wrap pre.CodeMirror-line,.CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{bottom:0;left:0;position:absolute;right:0;top:0;z-index:0}.CodeMirror-linewidget{padding:.1px;position:relative;z-index:2}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:none}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{box-sizing:content-box}.CodeMirror-measure{height:0;overflow:hidden;position:absolute;visibility:hidden;width:100%}.CodeMirror-cursor{pointer-events:none;position:absolute}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{position:relative;visibility:hidden;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:""}span.CodeMirror-selectedtext{background:none}',"",{version:3,sources:["webpack://./node_modules/codemirror/lib/codemirror.css"],names:[],mappings:"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",sourcesContent:["/* BASICS */\n\n.CodeMirror {\n /* Set height, width, borders, and global font properties here */\n font-family: monospace;\n height: 300px;\n color: black;\n direction: ltr;\n}\n\n/* PADDING */\n\n.CodeMirror-lines {\n padding: 4px 0; /* Vertical padding around content */\n}\n.CodeMirror pre.CodeMirror-line,\n.CodeMirror pre.CodeMirror-line-like {\n padding: 0 4px; /* Horizontal padding of content */\n}\n\n.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {\n background-color: white; /* The little square between H and V scrollbars */\n}\n\n/* GUTTER */\n\n.CodeMirror-gutters {\n border-right: 1px solid #ddd;\n background-color: #f7f7f7;\n white-space: nowrap;\n}\n.CodeMirror-linenumbers {}\n.CodeMirror-linenumber {\n padding: 0 3px 0 5px;\n min-width: 20px;\n text-align: right;\n color: #999;\n white-space: nowrap;\n}\n\n.CodeMirror-guttermarker { color: black; }\n.CodeMirror-guttermarker-subtle { color: #999; }\n\n/* CURSOR */\n\n.CodeMirror-cursor {\n border-left: 1px solid black;\n border-right: none;\n width: 0;\n}\n/* Shown when moving in bi-directional text */\n.CodeMirror div.CodeMirror-secondarycursor {\n border-left: 1px solid silver;\n}\n.cm-fat-cursor .CodeMirror-cursor {\n width: auto;\n border: 0 !important;\n background: #7e7;\n}\n.cm-fat-cursor div.CodeMirror-cursors {\n z-index: 1;\n}\n.cm-fat-cursor .CodeMirror-line::selection,\n.cm-fat-cursor .CodeMirror-line > span::selection, \n.cm-fat-cursor .CodeMirror-line > span > span::selection { background: transparent; }\n.cm-fat-cursor .CodeMirror-line::-moz-selection,\n.cm-fat-cursor .CodeMirror-line > span::-moz-selection,\n.cm-fat-cursor .CodeMirror-line > span > span::-moz-selection { background: transparent; }\n.cm-fat-cursor { caret-color: transparent; }\n@-moz-keyframes blink {\n 0% {}\n 50% { background-color: transparent; }\n 100% {}\n}\n@-webkit-keyframes blink {\n 0% {}\n 50% { background-color: transparent; }\n 100% {}\n}\n@keyframes blink {\n 0% {}\n 50% { background-color: transparent; }\n 100% {}\n}\n\n/* Can style cursor different in overwrite (non-insert) mode */\n.CodeMirror-overwrite .CodeMirror-cursor {}\n\n.cm-tab { display: inline-block; text-decoration: inherit; }\n\n.CodeMirror-rulers {\n position: absolute;\n left: 0; right: 0; top: -50px; bottom: 0;\n overflow: hidden;\n}\n.CodeMirror-ruler {\n border-left: 1px solid #ccc;\n top: 0; bottom: 0;\n position: absolute;\n}\n\n/* DEFAULT THEME */\n\n.cm-s-default .cm-header {color: blue;}\n.cm-s-default .cm-quote {color: #090;}\n.cm-negative {color: #d44;}\n.cm-positive {color: #292;}\n.cm-header, .cm-strong {font-weight: bold;}\n.cm-em {font-style: italic;}\n.cm-link {text-decoration: underline;}\n.cm-strikethrough {text-decoration: line-through;}\n\n.cm-s-default .cm-keyword {color: #708;}\n.cm-s-default .cm-atom {color: #219;}\n.cm-s-default .cm-number {color: #164;}\n.cm-s-default .cm-def {color: #00f;}\n.cm-s-default .cm-variable,\n.cm-s-default .cm-punctuation,\n.cm-s-default .cm-property,\n.cm-s-default .cm-operator {}\n.cm-s-default .cm-variable-2 {color: #05a;}\n.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;}\n.cm-s-default .cm-comment {color: #a50;}\n.cm-s-default .cm-string {color: #a11;}\n.cm-s-default .cm-string-2 {color: #f50;}\n.cm-s-default .cm-meta {color: #555;}\n.cm-s-default .cm-qualifier {color: #555;}\n.cm-s-default .cm-builtin {color: #30a;}\n.cm-s-default .cm-bracket {color: #997;}\n.cm-s-default .cm-tag {color: #170;}\n.cm-s-default .cm-attribute {color: #00c;}\n.cm-s-default .cm-hr {color: #999;}\n.cm-s-default .cm-link {color: #00c;}\n\n.cm-s-default .cm-error {color: #f00;}\n.cm-invalidchar {color: #f00;}\n\n.CodeMirror-composing { border-bottom: 2px solid; }\n\n/* Default styles for common addons */\n\ndiv.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;}\ndiv.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}\n.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }\n.CodeMirror-activeline-background {background: #e8f2ff;}\n\n/* STOP */\n\n/* The rest of this file contains styles related to the mechanics of\n the editor. You probably shouldn't touch them. */\n\n.CodeMirror {\n position: relative;\n overflow: hidden;\n background: white;\n}\n\n.CodeMirror-scroll {\n overflow: scroll !important; /* Things will break if this is overridden */\n /* 50px is the magic margin used to hide the element's real scrollbars */\n /* See overflow: hidden in .CodeMirror */\n margin-bottom: -50px; margin-right: -50px;\n padding-bottom: 50px;\n height: 100%;\n outline: none; /* Prevent dragging from highlighting the element */\n position: relative;\n z-index: 0;\n}\n.CodeMirror-sizer {\n position: relative;\n border-right: 50px solid transparent;\n}\n\n/* The fake, visible scrollbars. Used to force redraw during scrolling\n before actual scrolling happens, thus preventing shaking and\n flickering artifacts. */\n.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {\n position: absolute;\n z-index: 6;\n display: none;\n outline: none;\n}\n.CodeMirror-vscrollbar {\n right: 0; top: 0;\n overflow-x: hidden;\n overflow-y: scroll;\n}\n.CodeMirror-hscrollbar {\n bottom: 0; left: 0;\n overflow-y: hidden;\n overflow-x: scroll;\n}\n.CodeMirror-scrollbar-filler {\n right: 0; bottom: 0;\n}\n.CodeMirror-gutter-filler {\n left: 0; bottom: 0;\n}\n\n.CodeMirror-gutters {\n position: absolute; left: 0; top: 0;\n min-height: 100%;\n z-index: 3;\n}\n.CodeMirror-gutter {\n white-space: normal;\n height: 100%;\n display: inline-block;\n vertical-align: top;\n margin-bottom: -50px;\n}\n.CodeMirror-gutter-wrapper {\n position: absolute;\n z-index: 4;\n background: none !important;\n border: none !important;\n}\n.CodeMirror-gutter-background {\n position: absolute;\n top: 0; bottom: 0;\n z-index: 4;\n}\n.CodeMirror-gutter-elt {\n position: absolute;\n cursor: default;\n z-index: 4;\n}\n.CodeMirror-gutter-wrapper ::selection { background-color: transparent }\n.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }\n\n.CodeMirror-lines {\n cursor: text;\n min-height: 1px; /* prevents collapsing before first draw */\n}\n.CodeMirror pre.CodeMirror-line,\n.CodeMirror pre.CodeMirror-line-like {\n /* Reset some styles that the rest of the page might have set */\n -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;\n border-width: 0;\n background: transparent;\n font-family: inherit;\n font-size: inherit;\n margin: 0;\n white-space: pre;\n word-wrap: normal;\n line-height: inherit;\n color: inherit;\n z-index: 2;\n position: relative;\n overflow: visible;\n -webkit-tap-highlight-color: transparent;\n -webkit-font-variant-ligatures: contextual;\n font-variant-ligatures: contextual;\n}\n.CodeMirror-wrap pre.CodeMirror-line,\n.CodeMirror-wrap pre.CodeMirror-line-like {\n word-wrap: break-word;\n white-space: pre-wrap;\n word-break: normal;\n}\n\n.CodeMirror-linebackground {\n position: absolute;\n left: 0; right: 0; top: 0; bottom: 0;\n z-index: 0;\n}\n\n.CodeMirror-linewidget {\n position: relative;\n z-index: 2;\n padding: 0.1px; /* Force widget margins to stay inside of the container */\n}\n\n.CodeMirror-widget {}\n\n.CodeMirror-rtl pre { direction: rtl; }\n\n.CodeMirror-code {\n outline: none;\n}\n\n/* Force content-box sizing for the elements where we expect it */\n.CodeMirror-scroll,\n.CodeMirror-sizer,\n.CodeMirror-gutter,\n.CodeMirror-gutters,\n.CodeMirror-linenumber {\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n}\n\n.CodeMirror-measure {\n position: absolute;\n width: 100%;\n height: 0;\n overflow: hidden;\n visibility: hidden;\n}\n\n.CodeMirror-cursor {\n position: absolute;\n pointer-events: none;\n}\n.CodeMirror-measure pre { position: static; }\n\ndiv.CodeMirror-cursors {\n visibility: hidden;\n position: relative;\n z-index: 3;\n}\ndiv.CodeMirror-dragcursors {\n visibility: visible;\n}\n\n.CodeMirror-focused div.CodeMirror-cursors {\n visibility: visible;\n}\n\n.CodeMirror-selected { background: #d9d9d9; }\n.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }\n.CodeMirror-crosshair { cursor: crosshair; }\n.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }\n.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }\n\n.cm-searching {\n background-color: #ffa;\n background-color: rgba(255, 255, 0, .4);\n}\n\n/* Used to force a border model for a node */\n.cm-force-border { padding-right: .1px; }\n\n@media print {\n /* Hide the cursor when printing */\n .CodeMirror div.CodeMirror-cursors {\n visibility: hidden;\n }\n}\n\n/* See issue #2901 */\n.cm-tab-wrap-hack:after { content: ''; }\n\n/* Help users use markselection to safely style text background */\nspan.CodeMirror-selectedtext { background: none; }\n"],sourceRoot:""}]);const l=a},845:(e,t,r)=>{"use strict";r.d(t,{Z:()=>l});var n=r(15),i=r.n(n),o=r(645),a=r.n(o)()(i());a.push([e.id,".cm-s-twilight.CodeMirror{background:#141414;color:#f7f7f7}.cm-s-twilight div.CodeMirror-selected{background:#323232}.cm-s-twilight .CodeMirror-line::selection,.cm-s-twilight .CodeMirror-line>span::selection,.cm-s-twilight .CodeMirror-line>span>span::selection{background:rgba(50,50,50,.99)}.cm-s-twilight .CodeMirror-line::-moz-selection,.cm-s-twilight .CodeMirror-line>span::-moz-selection,.cm-s-twilight .CodeMirror-line>span>span::-moz-selection{background:rgba(50,50,50,.99)}.cm-s-twilight .CodeMirror-gutters{background:#222;border-right:1px solid #aaa}.cm-s-twilight .CodeMirror-guttermarker{color:#fff}.cm-s-twilight .CodeMirror-guttermarker-subtle,.cm-s-twilight .CodeMirror-linenumber{color:#aaa}.cm-s-twilight .CodeMirror-cursor{border-left:1px solid #fff}.cm-s-twilight .cm-keyword{color:#f9ee98}.cm-s-twilight .cm-atom{color:#fc0}.cm-s-twilight .cm-number{color:#ca7841}.cm-s-twilight .cm-def{color:#8da6ce}.cm-s-twilight span.cm-def,.cm-s-twilight span.cm-tag,.cm-s-twilight span.cm-type,.cm-s-twilight span.cm-variable-2,.cm-s-twilight span.cm-variable-3{color:#607392}.cm-s-twilight .cm-operator{color:#cda869}.cm-s-twilight .cm-comment{color:#777;font-style:italic;font-weight:400}.cm-s-twilight .cm-string{color:#8f9d6a;font-style:italic}.cm-s-twilight .cm-string-2{color:#bd6b18}.cm-s-twilight .cm-meta{background-color:#141414;color:#f7f7f7}.cm-s-twilight .cm-builtin{color:#cda869}.cm-s-twilight .cm-tag{color:#997643}.cm-s-twilight .cm-attribute{color:#d6bb6d}.cm-s-twilight .cm-header{color:#ff6400}.cm-s-twilight .cm-hr{color:#aeaeae}.cm-s-twilight .cm-link{color:#ad9361;font-style:italic;text-decoration:none}.cm-s-twilight .cm-error{border-bottom:1px solid red}.cm-s-twilight .CodeMirror-activeline-background{background:#27282e}.cm-s-twilight .CodeMirror-matchingbracket{color:#fff!important;outline:1px solid grey}","",{version:3,sources:["webpack://./node_modules/codemirror/theme/twilight.css"],names:[],mappings:"AAAA,0BAA4B,kBAAmB,CAAE,aAAgB,CACjE,uCAAyC,kBAAqB,CAC9D,gJAA0J,6BAAoC,CAC9L,+JAAyK,6BAAoC,CAE7M,mCAAqC,eAAgB,CAAE,2BAA8B,CACrF,wCAA0C,UAAc,CAExD,qFAAwC,UAAa,CACrD,kCAAoC,0BAA8B,CAElE,2BAA6B,aAAgB,CAC7C,wBAA0B,UAAa,CACvC,0BAA4B,aAAiB,CAC7C,uBAAyB,aAAgB,CAEzC,sJAA6F,aAAgB,CAC7G,4BAA8B,aAAgB,CAC9C,2BAA6B,UAAU,CAAE,iBAAiB,CAAE,eAAoB,CAChF,0BAA4B,aAAa,CAAE,iBAAmB,CAC9D,4BAA8B,aAAe,CAC7C,wBAA0B,wBAAwB,CAAE,aAAe,CACnE,2BAA6B,aAAgB,CAC7C,uBAAyB,aAAgB,CACzC,6BAA+B,aAAgB,CAC/C,0BAA4B,aAAgB,CAC5C,sBAAwB,aAAgB,CACxC,wBAA0B,aAAa,CAAE,iBAAiB,CAAE,oBAAsB,CAClF,yBAA2B,2BAA8B,CAEzD,iDAAmD,kBAAqB,CACxE,2CAAqE,oBAAsB,CAA9C,sBAAgD",sourcesContent:[".cm-s-twilight.CodeMirror { background: #141414; color: #f7f7f7; } /**/\n.cm-s-twilight div.CodeMirror-selected { background: #323232; } /**/\n.cm-s-twilight .CodeMirror-line::selection, .cm-s-twilight .CodeMirror-line > span::selection, .cm-s-twilight .CodeMirror-line > span > span::selection { background: rgba(50, 50, 50, 0.99); }\n.cm-s-twilight .CodeMirror-line::-moz-selection, .cm-s-twilight .CodeMirror-line > span::-moz-selection, .cm-s-twilight .CodeMirror-line > span > span::-moz-selection { background: rgba(50, 50, 50, 0.99); }\n\n.cm-s-twilight .CodeMirror-gutters { background: #222; border-right: 1px solid #aaa; }\n.cm-s-twilight .CodeMirror-guttermarker { color: white; }\n.cm-s-twilight .CodeMirror-guttermarker-subtle { color: #aaa; }\n.cm-s-twilight .CodeMirror-linenumber { color: #aaa; }\n.cm-s-twilight .CodeMirror-cursor { border-left: 1px solid white; }\n\n.cm-s-twilight .cm-keyword { color: #f9ee98; } /**/\n.cm-s-twilight .cm-atom { color: #FC0; }\n.cm-s-twilight .cm-number { color: #ca7841; } /**/\n.cm-s-twilight .cm-def { color: #8DA6CE; }\n.cm-s-twilight span.cm-variable-2, .cm-s-twilight span.cm-tag { color: #607392; } /**/\n.cm-s-twilight span.cm-variable-3, .cm-s-twilight span.cm-def, .cm-s-twilight span.cm-type { color: #607392; } /**/\n.cm-s-twilight .cm-operator { color: #cda869; } /**/\n.cm-s-twilight .cm-comment { color:#777; font-style:italic; font-weight:normal; } /**/\n.cm-s-twilight .cm-string { color:#8f9d6a; font-style:italic; } /**/\n.cm-s-twilight .cm-string-2 { color:#bd6b18; } /*?*/\n.cm-s-twilight .cm-meta { background-color:#141414; color:#f7f7f7; } /*?*/\n.cm-s-twilight .cm-builtin { color: #cda869; } /*?*/\n.cm-s-twilight .cm-tag { color: #997643; } /**/\n.cm-s-twilight .cm-attribute { color: #d6bb6d; } /*?*/\n.cm-s-twilight .cm-header { color: #FF6400; }\n.cm-s-twilight .cm-hr { color: #AEAEAE; }\n.cm-s-twilight .cm-link { color:#ad9361; font-style:italic; text-decoration:none; } /**/\n.cm-s-twilight .cm-error { border-bottom: 1px solid red; }\n\n.cm-s-twilight .CodeMirror-activeline-background { background: #27282E; }\n.cm-s-twilight .CodeMirror-matchingbracket { outline:1px solid grey; color:white !important; }\n"],sourceRoot:""}]);const l=a},645:e=>{"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var r=e(t);return t[2]?"@media ".concat(t[2]," {").concat(r,"}"):r})).join("")},t.i=function(e,r,n){"string"==typeof e&&(e=[[null,e,""]]);var i={};if(n)for(var o=0;o{"use strict";function t(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r=e&&("undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"]);if(null==r)return;var n,i,o=[],a=!0,l=!1;try{for(r=r.call(e);!(a=(n=r.next()).done)&&(o.push(n.value),!t||o.length!==t);a=!0);}catch(e){l=!0,i=e}finally{try{a||null==r.return||r.return()}finally{if(l)throw i}}return o}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r{},937:()=>{},379:(e,t,r)=>{"use strict";var n,i=function(){return void 0===n&&(n=Boolean(window&&document&&document.all&&!window.atob)),n},o=function(){var e={};return function(t){if(void 0===e[t]){var r=document.querySelector(t);if(window.HTMLIFrameElement&&r instanceof window.HTMLIFrameElement)try{r=r.contentDocument.head}catch(e){r=null}e[t]=r}return e[t]}}(),a=[];function l(e){for(var t=-1,r=0;r{if(!r){var a=1/0;for(u=0;u=o)&&Object.keys(n.O).every((e=>n.O[e](r[s])))?r.splice(s--,1):(l=!1,o0&&e[u-1][2]>o;u--)e[u]=e[u-1];e[u]=[r,i,o]},n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={138:0,118:0,766:0};n.O.j=t=>0===e[t];var t=(t,r)=>{var i,o,[a,l,s]=r,c=0;if(a.some((t=>0!==e[t]))){for(i in l)n.o(l,i)&&(n.m[i]=l[i]);if(s)var u=s(n)}for(t&&t(r);cn(830))),n.O(void 0,[118,766],(()=>n(158)));var i=n.O(void 0,[118,766],(()=>n(937)));i=n.O(i)})(); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiL2Fzc2V0cy92ZW5kb3IvY29kZWJsb2Nrcy9jb2RlYmxvY2tzLm1pbi5qcyIsIm1hcHBpbmdzIjoiVUFBSUEsRSw4QkNBSixNQUFNLEVBQStCQyxPLDBEQ0dqQ0MsRUFBVSxDQUVkQSxPQUFpQixPQUNqQkEsV0FBb0IsR0FFUCxJQUFJLElBQVNBLEdBSVgsVyxhQ1RYLEVBQVUsQ0FFZCxPQUFpQixPQUNqQixXQUFvQixHQUVQLElBQUksSUFBUyxHQUlYLFcsa0NDQ2ZDLElBQUVDLFVBQVVDLEdBQUcsVUFBVSxXQUNyQkYsSUFBRSxxQkFBcUJHLE1BQUssV0FDeEIsSUFBSUMsS0FBS0MsUUFBUUMsV0FBakIsQ0FHQUYsS0FBS0MsUUFBUUMsWUFBYSxFQUUxQixJQUdJQyxFQUhBQyxFQUFPUixJQUFFSSxNQUNUSyxFQUFZRCxFQUFLRSxPQUtqQkgsRUFEYSxRQUhGQyxFQUFLRyxLQUFLLFlBSVQsYUFHQSxDQUNSQyxLQUFNLE9BQ05DLEtBQU0sYUFJZEwsRUFBS00sUUFFTCxJQUFJQyxJQUFKLENBQWVYLEtBQU0sQ0FDakJZLE1BQU9QLEVBQ1BRLEtBQU1WLEVBQ05XLGFBQWEsRUFDYkMsVUFBVSxXQU10Qm5CLElBQUVDLFVBQVVDLEdBQUcsUUFBUyxnQkFBZ0IsV0FDcENGLElBQUVJLE1BQU1nQixRQUFRLHlCQUF5QkMsWUFBWSxpQixjQ3RDdEQsU0FBU04sR0FDWixhQUVBQSxFQUFXTyxpQkFBbUIsU0FBU0MsR0FFckMsSUFBSUMsRUFBU0MsTUFBTUMsVUFBVUMsTUFBTUMsS0FBS0MsVUFBVyxHQUVuRCxTQUFTQyxFQUFRQyxFQUFRQyxFQUFTQyxFQUFNQyxHQUN0QyxHQUFzQixpQkFBWEYsRUFBcUIsQ0FDOUIsSUFBSUcsRUFBUUosRUFBT0QsUUFBUUUsRUFBU0MsR0FDcEMsT0FBT0MsR0FBYUMsR0FBUyxFQUFJQSxFQUFRSCxFQUFRSSxPQUFTRCxFQUU1RCxJQUFJRSxFQUFJTCxFQUFRTSxLQUFLTCxFQUFPRixFQUFPSixNQUFNTSxHQUFRRixHQUNqRCxPQUFP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Q0FBQyxJQUFJLE1BQU0sSUFBTzA4RCxFQUFvQixPQUN2RUEsRUFBb0JJLE9BQUU5OEQsRUFBVyxDQUFDLElBQUksTUFBTSxJQUFPMDhELEVBQW9CLE9BQ3ZFLElBQUl3QixFQUFzQnhCLEVBQW9CSSxPQUFFOThELEVBQVcsQ0FBQyxJQUFJLE1BQU0sSUFBTzA4RCxFQUFvQixPQUNqR3dCLEVBQXNCeEIsRUFBb0JJLEVBQUVvQixJIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vL3dlYnBhY2svcnVudGltZS9jaHVuayBsb2FkZWQiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIHZhciBcImpRdWVyeVwiIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb2RlbWlycm9yL2xpYi9jb2RlbWlycm9yLmNzcz8yMDhmIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb2RlbWlycm9yL3RoZW1lL3R3aWxpZ2h0LmNzcz8zZmZlIiwid2VicGFjazovLy8uL2Fzc2V0cy92ZW5kb3IvY29kZWJsb2Nrcy9jb2RlYmxvY2tzLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb2RlbWlycm9yL2FkZG9uL21vZGUvbXVsdGlwbGV4LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb2RlbWlycm9yL2xpYi9jb2RlbWlycm9yLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb2RlbWlycm9yL21vZGUvY2xpa2UvY2xpa2UuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvZGVtaXJyb3IvbW9kZS9jc3MvY3NzLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb2RlbWlycm9yL21vZGUvaHRtbG1peGVkL2h0bWxtaXhlZC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29kZW1pcnJvci9tb2RlL2phdmFzY3JpcHQvamF2YXNjcmlwdC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29kZW1pcnJvci9tb2RlL3BocC9waHAuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvZGVtaXJyb3IvbW9kZS90d2lnL3R3aWcuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvZGVtaXJyb3IvbW9kZS94bWwveG1sLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb2RlbWlycm9yL2xpYi9jb2RlbWlycm9yLmNzcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29kZW1pcnJvci90aGVtZS90d2lsaWdodC5jc3MiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Nzcy1sb2FkZXIvZGlzdC9ydW50aW1lL2FwaS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY3NzLWxvYWRlci9kaXN0L3J1bnRpbWUvY3NzV2l0aE1hcHBpbmdUb1N0cmluZy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9pbmplY3RTdHlsZXNJbnRvU3R5bGVUYWcuanMiLCJ3ZWJwYWNrOi8vL3dlYnBhY2svYm9vdHN0cmFwIiwid2VicGFjazovLy93ZWJwYWNrL3J1bnRpbWUvY29tcGF0IGdldCBkZWZhdWx0IGV4cG9ydCIsIndlYnBhY2s6Ly8vd2VicGFjay9ydW50aW1lL2RlZmluZSBwcm9wZXJ0eSBnZXR0ZXJzIiwid2VicGFjazovLy93ZWJwYWNrL3J1bnRpbWUvaGFzT3duUHJvcGVydHkgc2hvcnRoYW5kIiwid2VicGFjazovLy93ZWJwYWNrL3J1bnRpbWUvanNvbnAgY2h1bmsgbG9hZGluZyIsIndlYnBhY2s6Ly8vd2VicGFjay9ydW50aW1lL25vbmNlIiwid2VicGFjazovLy93ZWJwYWNrL3N0YXJ0dXAiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIGRlZmVycmVkID0gW107XG5fX3dlYnBhY2tfcmVxdWlyZV9fLk8gPSAocmVzdWx0LCBjaHVua0lkcywgZm4sIHByaW9yaXR5KSA9PiB7XG5cdGlmKGNodW5rSWRzKSB7XG5cdFx0cHJpb3JpdHkgPSBwcmlvcml0eSB8fCAwO1xuXHRcdGZvcih2YXIgaSA9IGRlZmVycmVkLmxlbmd0aDsgaSA+IDAgJiYgZGVmZXJyZWRbaSAtIDFdWzJdID4gcHJpb3JpdHk7IGktLSkgZGVmZXJyZWRbaV0gPSBkZWZlcnJlZFtpIC0gMV07XG5cdFx0ZGVmZXJyZWRbaV0gPSBbY2h1bmtJZHMsIGZuLCBwcmlvcml0eV07XG5cdFx0cmV0dXJuO1xuXHR9XG5cdHZhciBub3RGdWxmaWxsZWQgPSBJbmZpbml0eTtcblx0Zm9yICh2YXIgaSA9IDA7IGkgPCBkZWZlcnJlZC5sZW5ndGg7IGkrKykge1xuXHRcdHZhciBbY2h1bmtJZHMsIGZuLCBwcmlvcml0eV0gPSBkZWZlcnJlZFtpXTtcblx0XHR2YXIgZnVsZmlsbGVkID0gdHJ1ZTtcblx0XHRmb3IgKHZhciBqID0gMDsgaiA8IGNodW5rSWRzLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRpZiAoKHByaW9yaXR5ICYgMSA9PT0gMCB8fCBub3RGdWxmaWxsZWQgPj0gcHJpb3JpdHkpICYmIE9iamVjdC5rZXlzKF9fd2VicGFja19yZXF1aXJlX18uTykuZXZlcnkoKGtleSkgPT4gKF9fd2VicGFja19yZXF1aXJlX18uT1trZXldKGNodW5rSWRzW2pdKSkpKSB7XG5cdFx0XHRcdGNodW5rSWRzLnNwbGljZShqLS0sIDEpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZnVsZmlsbGVkID0gZmFsc2U7XG5cdFx0XHRcdGlmKHByaW9yaXR5IDwgbm90RnVsZmlsbGVkKSBub3RGdWxmaWxsZWQgPSBwcmlvcml0eTtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYoZnVsZmlsbGVkKSB7XG5cdFx0XHRkZWZlcnJlZC5zcGxpY2UoaS0tLCAxKVxuXHRcdFx0dmFyIHIgPSBmbigpO1xuXHRcdFx0aWYgKHIgIT09IHVuZGVmaW5lZCkgcmVzdWx0ID0gcjtcblx0XHR9XG5cdH1cblx0cmV0dXJuIHJlc3VsdDtcbn07IiwiY29uc3QgX19XRUJQQUNLX05BTUVTUEFDRV9PQkpFQ1RfXyA9IGpRdWVyeTsiLCJpbXBvcnQgYXBpIGZyb20gXCIhLi4vLi4vc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9pbmplY3RTdHlsZXNJbnRvU3R5bGVUYWcuanNcIjtcbiAgICAgICAgICAgIGltcG9ydCBjb250ZW50IGZyb20gXCIhIS4uLy4uL2Nzcy1sb2FkZXIvZGlzdC9janMuanM/P3J1bGVTZXRbMV0ucnVsZXNbN10ub25lT2ZbMV0udXNlWzFdIS4uLy4uL3Bvc3Rjc3MtbG9hZGVyL2Rpc3QvY2pzLmpzPz9ydWxlU2V0WzFdLnJ1bGVzWzddLm9uZU9mWzFdLnVzZVsyXSEuL2NvZGVtaXJyb3IuY3NzXCI7XG5cbnZhciBvcHRpb25zID0ge307XG5cbm9wdGlvbnMuaW5zZXJ0ID0gXCJoZWFkXCI7XG5vcHRpb25zLnNpbmdsZXRvbiA9IGZhbHNlO1xuXG52YXIgdXBkYXRlID0gYXBpKGNvbnRlbnQsIG9wdGlvbnMpO1xuXG5cblxuZXhwb3J0IGRlZmF1bHQgY29udGVudC5sb2NhbHMgfHwge307IiwiaW1wb3J0IGFwaSBmcm9tIFwiIS4uLy4uL3N0eWxlLWxvYWRlci9kaXN0L3J1bnRpbWUvaW5qZWN0U3R5bGVzSW50b1N0eWxlVGFnLmpzXCI7XG4gICAgICAgICAgICBpbXBvcnQgY29udGVudCBmcm9tIFwiISEuLi8uLi9jc3MtbG9hZGVyL2Rpc3QvY2pzLmpzPz9ydWxlU2V0WzFdLnJ1bGVzWzddLm9uZU9mWzFdLnVzZVsxXSEuLi8uLi9wb3N0Y3NzLWxvYWRlci9kaXN0L2Nqcy5qcz8/cnVsZVNldFsxXS5ydWxlc1s3XS5vbmVPZlsxXS51c2VbMl0hLi90d2lsaWdodC5jc3NcIjtcblxudmFyIG9wdGlvbnMgPSB7fTtcblxub3B0aW9ucy5pbnNlcnQgPSBcImhlYWRcIjtcbm9wdGlvbnMuc2luZ2xldG9uID0gZmFsc2U7XG5cbnZhciB1cGRhdGUgPSBhcGkoY29udGVudCwgb3B0aW9ucyk7XG5cblxuXG5leHBvcnQgZGVmYXVsdCBjb250ZW50LmxvY2FscyB8fCB7fTsiLCIvKlxuICogQ29kZSBCbG9ja3NcbiAqL1xuaW1wb3J0ICQgZnJvbSAnanF1ZXJ5JztcbmltcG9ydCBDb2RlTWlycm9yICBmcm9tICdjb2RlbWlycm9yJztcbmltcG9ydCAnY29kZW1pcnJvci9saWIvY29kZW1pcnJvci5jc3MnO1xuaW1wb3J0ICdjb2RlbWlycm9yL3RoZW1lL3R3aWxpZ2h0LmNzcyc7XG5pbXBvcnQgJ2NvZGVtaXJyb3IvbW9kZS90d2lnL3R3aWcnO1xuaW1wb3J0ICdjb2RlbWlycm9yL21vZGUvcGhwL3BocCc7XG5pbXBvcnQgJ2NvZGVtaXJyb3IvbW9kZS9jbGlrZS9jbGlrZSc7XG5pbXBvcnQgJ2NvZGVtaXJyb3IvbW9kZS94bWwveG1sJztcbmltcG9ydCAnY29kZW1pcnJvci9hZGRvbi9tb2RlL211bHRpcGxleCc7XG5cbiQoZG9jdW1lbnQpLm9uKCdyZW5kZXInLCBmdW5jdGlvbigpIHtcbiAgICAkKCcuY29kZS1ibG9jayA+IHByZScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5kYXRhc2V0LmRpc3Bvc2FibGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRhdGFzZXQuZGlzcG9zYWJsZSA9IHRydWU7XG5cbiAgICAgICAgdmFyICRwcmUgPSAkKHRoaXMpLFxuICAgICAgICAgICAgY29kZVZhbHVlID0gJHByZS50ZXh0KCksXG4gICAgICAgICAgICBsYW5ndWFnZSA9ICRwcmUuZGF0YSgnbGFuZ3VhZ2UnKSxcbiAgICAgICAgICAgIG1vZGVWYWx1ZTtcblxuICAgICAgICBpZiAobGFuZ3VhZ2UgPT09ICdwaHAnKSB7XG4gICAgICAgICAgICBtb2RlVmFsdWUgPSAndGV4dC94LXBocCc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBtb2RlVmFsdWUgPSB7XG4gICAgICAgICAgICAgICAgbmFtZTogJ3R3aWcnLFxuICAgICAgICAgICAgICAgIGJhc2U6ICd0ZXh0L2h0bWwnXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgJHByZS5lbXB0eSgpO1xuXG4gICAgICAgIG5ldyBDb2RlTWlycm9yKHRoaXMsIHtcbiAgICAgICAgICAgIHZhbHVlOiBjb2RlVmFsdWUsXG4gICAgICAgICAgICBtb2RlOiBtb2RlVmFsdWUsXG4gICAgICAgICAgICBsaW5lTnVtYmVyczogdHJ1ZSxcbiAgICAgICAgICAgIHJlYWRPbmx5OiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG59KTtcblxuJChkb2N1bWVudCkub24oJ2NsaWNrJywgJy5leHBhbmQtY29kZScsIGZ1bmN0aW9uICgpIHtcbiAgICAkKHRoaXMpLmNsb3Nlc3QoJy5jb2xsYXBzZWQtY29kZS1ibG9jaycpLnJlbW92ZUNsYXNzKCdjb2xsYXBzZWQnKTtcbn0pO1xuIiwiLy8gQ29kZU1pcnJvciwgY29weXJpZ2h0IChjKSBieSBNYXJpam4gSGF2ZXJiZWtlIGFuZCBvdGhlcnNcbi8vIERpc3RyaWJ1dGVkIHVuZGVyIGFuIE1JVCBsaWNlbnNlOiBodHRwczovL2NvZGVtaXJyb3IubmV0L0xJQ0VOU0VcblxuKGZ1bmN0aW9uKG1vZCkge1xuICBpZiAodHlwZW9mIGV4cG9ydHMgPT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlID09IFwib2JqZWN0XCIpIC8vIENvbW1vbkpTXG4gICAgbW9kKHJlcXVpcmUoXCIuLi8uLi9saWIvY29kZW1pcnJvclwiKSk7XG4gIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIC8vIEFNRFxuICAgIGRlZmluZShbXCIuLi8uLi9saWIvY29kZW1pcnJvclwiXSwgbW9kKTtcbiAgZWxzZSAvLyBQbGFpbiBicm93c2VyIGVudlxuICAgIG1vZChDb2RlTWlycm9yKTtcbn0pKGZ1bmN0aW9uKENvZGVNaXJyb3IpIHtcblwidXNlIHN0cmljdFwiO1xuXG5Db2RlTWlycm9yLm11bHRpcGxleGluZ01vZGUgPSBmdW5jdGlvbihvdXRlciAvKiwgb3RoZXJzICovKSB7XG4gIC8vIE90aGVycyBzaG91bGQgYmUge29wZW4sIGNsb3NlLCBtb2RlIFssIGRlbGltU3R5bGVdIFssIGlubmVyU3R5bGVdIFssIHBhcnNlRGVsaW1pdGVyc119IG9iamVjdHNcbiAgdmFyIG90aGVycyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG5cbiAgZnVuY3Rpb24gaW5kZXhPZihzdHJpbmcsIHBhdHRlcm4sIGZyb20sIHJldHVybkVuZCkge1xuICAgIGlmICh0eXBlb2YgcGF0dGVybiA9PSBcInN0cmluZ1wiKSB7XG4gICAgICB2YXIgZm91bmQgPSBzdHJpbmcuaW5kZXhPZihwYXR0ZXJuLCBmcm9tKTtcbiAgICAgIHJldHVybiByZXR1cm5FbmQgJiYgZm91bmQgPiAtMSA/IGZvdW5kICsgcGF0dGVybi5sZW5ndGggOiBmb3VuZDtcbiAgICB9XG4gICAgdmFyIG0gPSBwYXR0ZXJuLmV4ZWMoZnJvbSA/IHN0cmluZy5zbGljZShmcm9tKSA6IHN0cmluZyk7XG4gICAgcmV0dXJuIG0gPyBtLmluZGV4ICsgZnJvbSArIChyZXR1cm5FbmQgPyBtWzBdLmxlbmd0aCA6IDApIDogLTE7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHN0YXJ0U3RhdGU6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgb3V0ZXI6IENvZGVNaXJyb3Iuc3RhcnRTdGF0ZShvdXRlciksXG4gICAgICAgIGlubmVyQWN0aXZlOiBudWxsLFxuICAgICAgICBpbm5lcjogbnVsbCxcbiAgICAgICAgc3RhcnRpbmdJbm5lcjogZmFsc2VcbiAgICAgIH07XG4gICAgfSxcblxuICAgIGNvcHlTdGF0ZTogZnVuY3Rpb24oc3RhdGUpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG91dGVyOiBDb2RlTWlycm9yLmNvcHlTdGF0ZShvdXRlciwgc3RhdGUub3V0ZXIpLFxuICAgICAgICBpbm5lckFjdGl2ZTogc3RhdGUuaW5uZXJBY3RpdmUsXG4gICAgICAgIGlubmVyOiBzdGF0ZS5pbm5lckFjdGl2ZSAmJiBDb2RlTWlycm9yLmNvcHlTdGF0ZShzdGF0ZS5pbm5lckFjdGl2ZS5tb2RlLCBzdGF0ZS5pbm5lciksXG4gICAgICAgIHN0YXJ0aW5nSW5uZXI6IHN0YXRlLnN0YXJ0aW5nSW5uZXJcbiAgICAgIH07XG4gICAgfSxcblxuICAgIHRva2VuOiBmdW5jdGlvbihzdHJlYW0sIHN0YXRlKSB7XG4gICAgICBpZiAoIXN0YXRlLmlubmVyQWN0aXZlKSB7XG4gICAgICAgIHZhciBjdXRPZmYgPSBJbmZpbml0eSwgb2xkQ29udGVudCA9IHN0cmVhbS5zdHJpbmc7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3RoZXJzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgdmFyIG90aGVyID0gb3RoZXJzW2ldO1xuICAgICAgICAgIHZhciBmb3VuZCA9IGluZGV4T2Yob2xkQ29udGVudCwgb3RoZXIub3Blbiwgc3RyZWFtLnBvcyk7XG4gICAgICAgICAgaWYgKGZvdW5kID09IHN0cmVhbS5wb3MpIHtcbiAgICAgICAgICAgIGlmICghb3RoZXIucGFyc2VEZWxpbWl0ZXJzKSBzdHJlYW0ubWF0Y2gob3RoZXIub3Blbik7XG4gICAgICAgICAgICBzdGF0ZS5zdGFydGluZ0lubmVyID0gISFvdGhlci5wYXJzZURlbGltaXRlcnNcbiAgICAgICAgICAgIHN0YXRlLmlubmVyQWN0aXZlID0gb3RoZXI7XG5cbiAgICAgICAgICAgIC8vIEdldCB0aGUgb3V0ZXIgaW5kZW50LCBtYWtpbmcgc3VyZSB0byBoYW5kbGUgQ29kZU1pcnJvci5QYXNzXG4gICAgICAgICAgICB2YXIgb3V0ZXJJbmRlbnQgPSAwO1xuICAgICAgICAgICAgaWYgKG91dGVyLmluZGVudCkge1xuICAgICAgICAgICAgICB2YXIgcG9zc2libGVPdXRlckluZGVudCA9IG91dGVyLmluZGVudChzdGF0ZS5vdXRlciwgXCJcIiwgXCJcIik7XG4gICAgICAgICAgICAgIGlmIChwb3NzaWJsZU91dGVySW5kZW50ICE9PSBDb2RlTWlycm9yLlBhc3MpIG91dGVySW5kZW50ID0gcG9zc2libGVPdXRlckluZGVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3RhdGUuaW5uZXIgPSBDb2RlTWlycm9yLnN0YXJ0U3RhdGUob3RoZXIubW9kZSwgb3V0ZXJJbmRlbnQpO1xuICAgICAgICAgICAgcmV0dXJuIG90aGVyLmRlbGltU3R5bGUgJiYgKG90aGVyLmRlbGltU3R5bGUgKyBcIiBcIiArIG90aGVyLmRlbGltU3R5bGUgKyBcIi1vcGVuXCIpO1xuICAgICAgICAgIH0gZWxzZSBpZiAoZm91bmQgIT0gLTEgJiYgZm91bmQgPCBjdXRPZmYpIHtcbiAgICAgICAgICAgIGN1dE9mZiA9IGZvdW5kO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoY3V0T2ZmICE9IEluZmluaXR5KSBzdHJlYW0uc3RyaW5nID0gb2xkQ29udGVudC5zbGljZSgwLCBjdXRPZmYpO1xuICAgICAgICB2YXIgb3V0ZXJUb2tlbiA9IG91dGVyLnRva2VuKHN0cmVhbSwgc3RhdGUub3V0ZXIpO1xuICAgICAgICBpZiAoY3V0T2ZmICE9IEluZmluaXR5KSBzdHJlYW0uc3RyaW5nID0gb2xkQ29udGVudDtcbiAgICAgICAgcmV0dXJuIG91dGVyVG9rZW47XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgY3VySW5uZXIgPSBzdGF0ZS5pbm5lckFjdGl2ZSwgb2xkQ29udGVudCA9IHN0cmVhbS5zdHJpbmc7XG4gICAgICAgIGlmICghY3VySW5uZXIuY2xvc2UgJiYgc3RyZWFtLnNvbCgpKSB7XG4gICAgICAgICAgc3RhdGUuaW5uZXJBY3RpdmUgPSBzdGF0ZS5pbm5lciA9IG51bGw7XG4gICAgICAgICAgcmV0dXJuIHRoaXMudG9rZW4oc3RyZWFtLCBzdGF0ZSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGZvdW5kID0gY3VySW5uZXIuY2xvc2UgJiYgIXN0YXRlLnN0YXJ0aW5nSW5uZXIgP1xuICAgICAgICAgICAgaW5kZXhPZihvbGRDb250ZW50LCBjdXJJbm5lci5jbG9zZSwgc3RyZWFtLnBvcywgY3VySW5uZXIucGFyc2VEZWxpbWl0ZXJzKSA6IC0xO1xuICAgICAgICBpZiAoZm91bmQgPT0gc3RyZWFtLnBvcyAmJiAhY3VySW5uZXIucGFyc2VEZWxpbWl0ZXJzKSB7XG4gICAgICAgICAgc3RyZWFtLm1hdGNoKGN1cklubmVyLmNsb3NlKTtcbiAgICAgICAgICBzdGF0ZS5pbm5lckFjdGl2ZSA9IHN0YXRlLmlubmVyID0gbnVsbDtcbiAgICAgICAgICByZXR1cm4gY3VySW5uZXIuZGVsaW1TdHlsZSAmJiAoY3VySW5uZXIuZGVsaW1TdHlsZSArIFwiIFwiICsgY3VySW5uZXIuZGVsaW1TdHlsZSArIFwiLWNsb3NlXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmb3VuZCA+IC0xKSBzdHJlYW0uc3RyaW5nID0gb2xkQ29udGVudC5zbGljZSgwLCBmb3VuZCk7XG4gICAgICAgIHZhciBpbm5lclRva2VuID0gY3VySW5uZXIubW9kZS50b2tlbihzdHJlYW0sIHN0YXRlLmlubmVyKTtcbiAgICAgICAgaWYgKGZvdW5kID4gLTEpIHN0cmVhbS5zdHJpbmcgPSBvbGRDb250ZW50O1xuICAgICAgICBlbHNlIGlmIChzdHJlYW0ucG9zID4gc3RyZWFtLnN0YXJ0KSBzdGF0ZS5zdGFydGluZ0lubmVyID0gZmFsc2VcblxuICAgICAgICBpZiAoZm91bmQgPT0gc3RyZWFtLnBvcyAmJiBjdXJJbm5lci5wYXJzZURlbGltaXRlcnMpXG4gICAgICAgICAgc3RhdGUuaW5uZXJBY3RpdmUgPSBzdGF0ZS5pbm5lciA9IG51bGw7XG5cbiAgICAgICAgaWYgKGN1cklubmVyLmlubmVyU3R5bGUpIHtcbiAgICAgICAgICBpZiAoaW5uZXJUb2tlbikgaW5uZXJUb2tlbiA9IGlubmVyVG9rZW4gKyBcIiBcIiArIGN1cklubmVyLmlubmVyU3R5bGU7XG4gICAgICAgICAgZWxzZSBpbm5lclRva2VuID0gY3VySW5uZXIuaW5uZXJTdHlsZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpbm5lclRva2VuO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICBpbmRlbnQ6IGZ1bmN0aW9uKHN0YXRlLCB0ZXh0QWZ0ZXIsIGxpbmUpIHtcbiAgICAgIHZhciBtb2RlID0gc3RhdGUuaW5uZXJBY3RpdmUgPyBzdGF0ZS5pbm5lckFjdGl2ZS5tb2RlIDogb3V0ZXI7XG4gICAgICBpZiAoIW1vZGUuaW5kZW50KSByZXR1cm4gQ29kZU1pcnJvci5QYXNzO1xuICAgICAgcmV0dXJuIG1vZGUuaW5kZW50KHN0YXRlLmlubmVyQWN0aXZlID8gc3RhdGUuaW5uZXIgOiBzdGF0ZS5vdXRlciwgdGV4dEFmdGVyLCBsaW5lKTtcbiAgICB9LFxuXG4gICAgYmxhbmtMaW5lOiBmdW5jdGlvbihzdGF0ZSkge1xuICAgICAgdmFyIG1vZGUgPSBzdGF0ZS5pbm5lckFjdGl2ZSA/IHN0YXRlLmlubmVyQWN0aXZlLm1vZGUgOiBvdXRlcjtcbiAgICAgIGlmIChtb2RlLmJsYW5rTGluZSkge1xuICAgICAgICBtb2RlLmJsYW5rTGluZShzdGF0ZS5pbm5lckFjdGl2ZSA/IHN0YXRlLmlubmVyIDogc3RhdGUub3V0ZXIpO1xuICAgICAgfVxuICAgICAgaWYgKCFzdGF0ZS5pbm5lckFjdGl2ZSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG90aGVycy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgIHZhciBvdGhlciA9IG90aGVyc1tpXTtcbiAgICAgICAgICBpZiAob3RoZXIub3BlbiA9PT0gXCJcXG5cIikge1xuICAgICAgICAgICAgc3RhdGUuaW5uZXJBY3RpdmUgPSBvdGhlcjtcbiAgICAgICAgICAgIHN0YXRlLmlubmVyID0gQ29kZU1pcnJvci5zdGFydFN0YXRlKG90aGVyLm1vZGUsIG1vZGUuaW5kZW50ID8gbW9kZS5pbmRlbnQoc3RhdGUub3V0ZXIsIFwiXCIsIFwiXCIpIDogMCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHN0YXRlLmlubmVyQWN0aXZlLmNsb3NlID09PSBcIlxcblwiKSB7XG4gICAgICAgIHN0YXRlLmlubmVyQWN0aXZlID0gc3RhdGUuaW5uZXIgPSBudWxsO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICBlbGVjdHJpY0NoYXJzOiBvdXRlci5lbGVjdHJpY0NoYXJzLFxuXG4gICAgaW5uZXJNb2RlOiBmdW5jdGlvbihzdGF0ZSkge1xuICAgICAgcmV0dXJuIHN0YXRlLmlubmVyID8ge3N0YXRlOiBzdGF0ZS5pbm5lciwgbW9kZTogc3RhdGUuaW5uZXJBY3RpdmUubW9kZX0gOiB7c3RhdGU6IHN0YXRlLm91dGVyLCBtb2RlOiBvdXRlcn07XG4gICAgfVxuICB9O1xufTtcblxufSk7XG4iLCIvLyBDb2RlTWlycm9yLCBjb3B5cmlnaHQgKGMpIGJ5IE1hcmlqbiBIYXZlcmJla2UgYW5kIG90aGVyc1xuLy8gRGlzdHJpYnV0ZWQgdW5kZXIgYW4gTUlUIGxpY2Vuc2U6IGh0dHBzOi8vY29kZW1pcnJvci5uZXQvTElDRU5TRVxuXG4vLyBUaGlzIGlzIENvZGVNaXJyb3IgKGh0dHBzOi8vY29kZW1pcnJvci5uZXQpLCBhIGNvZGUgZWRpdG9yXG4vLyBpbXBsZW1lbnRlZCBpbiBKYXZhU2NyaXB0IG9uIHRvcCBvZiB0aGUgYnJvd3NlcidzIERPTS5cbi8vXG4vLyBZb3UgY2FuIGZpbmQgc29tZSB0ZWNobmljYWwgYmFja2dyb3VuZCBmb3Igc29tZSBvZiB0aGUgY29kZSBiZWxvd1xuLy8gYXQgaHR0cDovL21hcmlqbmhhdmVyYmVrZS5ubC9ibG9nLyNjbS1pbnRlcm5hbHMgLlxuXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoKSA6XG4gIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShmYWN0b3J5KSA6XG4gIChnbG9iYWwgPSBnbG9iYWwgfHwgc2VsZiwgZ2xvYmFsLkNvZGVNaXJyb3IgPSBmYWN0b3J5KCkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKCkgeyAndXNlIHN0cmljdCc7XG5cbiAgLy8gS2x1ZGdlcyBmb3IgYnVncyBhbmQgYmVoYXZpb3IgZGlmZmVyZW5jZXMgdGhhdCBjYW4ndCBiZSBmZWF0dXJlXG4gIC8vIGRldGVjdGVkIGFyZSBlbmFibGVkIGJhc2VkIG9uIHVzZXJBZ2VudCBldGMgc25pZmZpbmcuXG4gIHZhciB1c2VyQWdlbnQgPSBuYXZpZ2F0b3IudXNlckFnZW50O1xuICB2YXIgcGxhdGZvcm0gPSBuYXZpZ2F0b3IucGxhdGZvcm07XG5cbiAgdmFyIGdlY2tvID0gL2dlY2tvXFwvXFxkL2kudGVzdCh1c2VyQWdlbnQpO1xuICB2YXIgaWVfdXB0bzEwID0gL01TSUUgXFxkLy50ZXN0KHVzZXJBZ2VudCk7XG4gIHZhciBpZV8xMXVwID0gL1RyaWRlbnRcXC8oPzpbNy05XXxcXGR7Mix9KVxcLi4qcnY6KFxcZCspLy5leGVjKHVzZXJBZ2VudCk7XG4gIHZhciBlZGdlID0gL0VkZ2VcXC8oXFxkKykvLmV4ZWModXNlckFnZW50KTtcbiAgdmFyIGllID0gaWVfdXB0bzEwIHx8IGllXzExdXAgfHwgZWRnZTtcbiAgdmFyIGllX3ZlcnNpb24gPSBpZSAmJiAoaWVfdXB0bzEwID8gZG9jdW1lbnQuZG9jdW1lbnRNb2RlIHx8IDYgOiArKGVkZ2UgfHwgaWVfMTF1cClbMV0pO1xuICB2YXIgd2Via2l0ID0gIWVkZ2UgJiYgL1dlYktpdFxcLy8udGVzdCh1c2VyQWdlbnQpO1xuICB2YXIgcXR3ZWJraXQgPSB3ZWJraXQgJiYgL1F0XFwvXFxkK1xcLlxcZCsvLnRlc3QodXNlckFnZW50KTtcbiAgdmFyIGNocm9tZSA9ICFlZGdlICYmIC9DaHJvbWVcXC8oXFxkKykvLmV4ZWModXNlckFnZW50KTtcbiAgdmFyIGNocm9tZV92ZXJzaW9uID0gY2hyb21lICYmICtjaHJvbWVbMV07XG4gIHZhciBwcmVzdG8gPSAvT3BlcmFcXC8vLnRlc3QodXNlckFnZW50KTtcbiAgdmFyIHNhZmFyaSA9IC9BcHBsZSBDb21wdXRlci8udGVzdChuYXZpZ2F0b3IudmVuZG9yKTtcbiAgdmFyIG1hY19nZU1vdW50YWluTGlvbiA9IC9NYWMgT1MgWCAxXFxkXFxEKFs4LTldfFxcZFxcZClcXEQvLnRlc3QodXNlckFnZW50KTtcbiAgdmFyIHBoYW50b20gPSAvUGhhbnRvbUpTLy50ZXN0KHVzZXJBZ2VudCk7XG5cbiAgdmFyIGlvcyA9IHNhZmFyaSAmJiAoL01vYmlsZVxcL1xcdysvLnRlc3QodXNlckFnZW50KSB8fCBuYXZpZ2F0b3IubWF4VG91Y2hQb2ludHMgPiAyKTtcbiAgdmFyIGFuZHJvaWQgPSAvQW5kcm9pZC8udGVzdCh1c2VyQWdlbnQpO1xuICAvLyBUaGlzIGlzIHdvZWZ1bGx5IGluY29tcGxldGUuIFN1Z2dlc3Rpb25zIGZvciBhbHRlcm5hdGl2ZSBtZXRob2RzIHdlbGNvbWUuXG4gIHZhciBtb2JpbGUgPSBpb3MgfHwgYW5kcm9pZCB8fCAvd2ViT1N8QmxhY2tCZXJyeXxPcGVyYSBNaW5pfE9wZXJhIE1vYml8SUVNb2JpbGUvaS50ZXN0KHVzZXJBZ2VudCk7XG4gIHZhciBtYWMgPSBpb3MgfHwgL01hYy8udGVzdChwbGF0Zm9ybSk7XG4gIHZhciBjaHJvbWVPUyA9IC9cXGJDck9TXFxiLy50ZXN0KHVzZXJBZ2VudCk7XG4gIHZhciB3aW5kb3dzID0gL3dpbi9pLnRlc3QocGxhdGZvcm0pO1xuXG4gIHZhciBwcmVzdG9fdmVyc2lvbiA9IHByZXN0byAmJiB1c2VyQWdlbnQubWF0Y2goL1ZlcnNpb25cXC8oXFxkKlxcLlxcZCopLyk7XG4gIGlmIChwcmVzdG9fdmVyc2lvbikgeyBwcmVzdG9fdmVyc2lvbiA9IE51bWJlcihwcmVzdG9fdmVyc2lvblsxXSk7IH1cbiAgaWYgKHByZXN0b192ZXJzaW9uICYmIHByZXN0b192ZXJzaW9uID49IDE1KSB7IHByZXN0byA9IGZhbHNlOyB3ZWJraXQgPSB0cnVlOyB9XG4gIC8vIFNvbWUgYnJvd3NlcnMgdXNlIHRoZSB3cm9uZyBldmVudCBwcm9wZXJ0aWVzIHRvIHNpZ25hbCBjbWQvY3RybCBvbiBPUyBYXG4gIHZhciBmbGlwQ3RybENtZCA9IG1hYyAmJiAocXR3ZWJraXQgfHwgcHJlc3RvICYmIChwcmVzdG9fdmVyc2lvbiA9PSBudWxsIHx8IHByZXN0b192ZXJzaW9uIDwgMTIuMTEpKTtcbiAgdmFyIGNhcHR1cmVSaWdodENsaWNrID0gZ2Vja28gfHwgKGllICYmIGllX3ZlcnNpb24gPj0gOSk7XG5cbiAgZnVuY3Rpb24gY2xhc3NUZXN0KGNscykgeyByZXR1cm4gbmV3IFJlZ0V4cChcIihefFxcXFxzKVwiICsgY2xzICsgXCIoPzokfFxcXFxzKVxcXFxzKlwiKSB9XG5cbiAgdmFyIHJtQ2xhc3MgPSBmdW5jdGlvbihub2RlLCBjbHMpIHtcbiAgICB2YXIgY3VycmVudCA9IG5vZGUuY2xhc3NOYW1lO1xuICAgIHZhciBtYXRjaCA9IGNsYXNzVGVzdChjbHMpLmV4ZWMoY3VycmVudCk7XG4gICAgaWYgKG1hdGNoKSB7XG4gICAgICB2YXIgYWZ0ZXIgPSBjdXJyZW50LnNsaWNlKG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoKTtcbiAgICAgIG5vZGUuY2xhc3NOYW1lID0gY3VycmVudC5zbGljZSgwLCBtYXRjaC5pbmRleCkgKyAoYWZ0ZXIgPyBtYXRjaFsxXSArIGFmdGVyIDogXCJcIik7XG4gICAgfVxuICB9O1xuXG4gIGZ1bmN0aW9uIHJlbW92ZUNoaWxkcmVuKGUpIHtcbiAgICBmb3IgKHZhciBjb3VudCA9IGUuY2hpbGROb2Rlcy5sZW5ndGg7IGNvdW50ID4gMDsgLS1jb3VudClcbiAgICAgIHsgZS5yZW1vdmVDaGlsZChlLmZpcnN0Q2hpbGQpOyB9XG4gICAgcmV0dXJuIGVcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlbW92ZUNoaWxkcmVuQW5kQWRkKHBhcmVudCwgZSkge1xuICAgIHJldHVybiByZW1vdmVDaGlsZHJlbihwYXJlbnQpLmFwcGVuZENoaWxkKGUpXG4gIH1cblxuICBmdW5jdGlvbiBlbHQodGFnLCBjb250ZW50LCBjbGFzc05hbWUsIHN0eWxlKSB7XG4gICAgdmFyIGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KHRhZyk7XG4gICAgaWYgKGNsYXNzTmFtZSkgeyBlLmNsYXNzTmFtZSA9IGNsYXNzTmFtZTsgfVxuICAgIGlmIChzdHlsZSkgeyBlLnN0eWxlLmNzc1RleHQgPSBzdHlsZTsgfVxuICAgIGlmICh0eXBlb2YgY29udGVudCA9PSBcInN0cmluZ1wiKSB7IGUuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoY29udGVudCkpOyB9XG4gICAgZWxzZSBpZiAoY29udGVudCkgeyBmb3IgKHZhciBpID0gMDsgaSA8IGNvbnRlbnQubGVuZ3RoOyArK2kpIHsgZS5hcHBlbmRDaGlsZChjb250ZW50W2ldKTsgfSB9XG4gICAgcmV0dXJuIGVcbiAgfVxuICAvLyB3cmFwcGVyIGZvciBlbHQsIHdoaWNoIHJlbW92ZXMgdGhlIGVsdCBmcm9tIHRoZSBhY2Nlc3NpYmlsaXR5IHRyZWVcbiAgZnVuY3Rpb24gZWx0UCh0YWcsIGNvbnRlbnQsIGNsYXNzTmFtZSwgc3R5bGUpIHtcbiAgICB2YXIgZSA9IGVsdCh0YWcsIGNvbnRlbnQsIGNsYXNzTmFtZSwgc3R5bGUpO1xuICAgIGUuc2V0QXR0cmlidXRlKFwicm9sZVwiLCBcInByZXNlbnRhdGlvblwiKTtcbiAgICByZXR1cm4gZVxuICB9XG5cbiAgdmFyIHJhbmdlO1xuICBpZiAoZG9jdW1lbnQuY3JlYXRlUmFuZ2UpIHsgcmFuZ2UgPSBmdW5jdGlvbihub2RlLCBzdGFydCwgZW5kLCBlbmROb2RlKSB7XG4gICAgdmFyIHIgPSBkb2N1bWVudC5jcmVhdGVSYW5nZSgpO1xuICAgIHIuc2V0RW5kKGVuZE5vZGUgfHwgbm9kZSwgZW5kKTtcbiAgICByLnNldFN0YXJ0KG5vZGUsIHN0YXJ0KTtcbiAgICByZXR1cm4gclxuICB9OyB9XG4gIGVsc2UgeyByYW5nZSA9IGZ1bmN0aW9uKG5vZGUsIHN0YXJ0LCBlbmQpIHtcbiAgICB2YXIgciA9IGRvY3VtZW50LmJvZHkuY3JlYXRlVGV4dFJhbmdlKCk7XG4gICAgdHJ5IHsgci5tb3ZlVG9FbGVtZW50VGV4dChub2RlLnBhcmVudE5vZGUpOyB9XG4gICAgY2F0Y2goZSkgeyByZXR1cm4gciB9XG4gICAgci5jb2xsYXBzZSh0cnVlKTtcbiAgICByLm1vdmVFbmQoXCJjaGFyYWN0ZXJcIiwgZW5kKTtcbiAgICByLm1vdmVTdGFydChcImNoYXJhY3RlclwiLCBzdGFydCk7XG4gICAgcmV0dXJuIHJcbiAgfTsgfVxuXG4gIGZ1bmN0aW9uIGNvbnRhaW5zKHBhcmVudCwgY2hpbGQpIHtcbiAgICBpZiAoY2hpbGQubm9kZVR5cGUgPT0gMykgLy8gQW5kcm9pZCBicm93c2VyIGFsd2F5cyByZXR1cm5zIGZhbHNlIHdoZW4gY2hpbGQgaXMgYSB0ZXh0bm9kZVxuICAgICAgeyBjaGlsZCA9IGNoaWxkLnBhcmVudE5vZGU7IH1cbiAgICBpZiAocGFyZW50LmNvbnRhaW5zKVxuICAgICAgeyByZXR1cm4gcGFyZW50LmNvbnRhaW5zKGNoaWxkKSB9XG4gICAgZG8ge1xuICAgICAgaWYgKGNoaWxkLm5vZGVUeXBlID09IDExKSB7IGNoaWxkID0gY2hpbGQuaG9zdDsgfVxuICAgICAgaWYgKGNoaWxkID09IHBhcmVudCkgeyByZXR1cm4gdHJ1ZSB9XG4gICAgfSB3aGlsZSAoY2hpbGQgPSBjaGlsZC5wYXJlbnROb2RlKVxuICB9XG5cbiAgZnVuY3Rpb24gYWN0aXZlRWx0KCkge1xuICAgIC8vIElFIGFuZCBFZGdlIG1heSB0aHJvdyBhbiBcIlVuc3BlY2lmaWVkIEVycm9yXCIgd2hlbiBhY2Nlc3NpbmcgZG9jdW1lbnQuYWN0aXZlRWxlbWVudC5cbiAgICAvLyBJRSA8IDEwIHdpbGwgdGhyb3cgd2hlbiBhY2Nlc3NlZCB3aGlsZSB0aGUgcGFnZSBpcyBsb2FkaW5nIG9yIGluIGFuIGlmcmFtZS5cbiAgICAvLyBJRSA+IDkgYW5kIEVkZ2Ugd2lsbCB0aHJvdyB3aGVuIGFjY2Vzc2VkIGluIGFuIGlmcmFtZSBpZiBkb2N1bWVudC5ib2R5IGlzIHVuYXZhaWxhYmxlLlxuICAgIHZhciBhY3RpdmVFbGVtZW50O1xuICAgIHRyeSB7XG4gICAgICBhY3RpdmVFbGVtZW50ID0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcbiAgICB9IGNhdGNoKGUpIHtcbiAgICAgIGFjdGl2ZUVsZW1lbnQgPSBkb2N1bWVudC5ib2R5IHx8IG51bGw7XG4gICAgfVxuICAgIHdoaWxlIChhY3RpdmVFbGVtZW50ICYmIGFjdGl2ZUVsZW1lbnQuc2hhZG93Um9vdCAmJiBhY3RpdmVFbGVtZW50LnNoYWRvd1Jvb3QuYWN0aXZlRWxlbWVudClcbiAgICAgIHsgYWN0aXZlRWxlbWVudCA9IGFjdGl2ZUVsZW1lbnQuc2hhZG93Um9vdC5hY3RpdmVFbGVtZW50OyB9XG4gICAgcmV0dXJuIGFjdGl2ZUVsZW1lbnRcbiAgfVxuXG4gIGZ1bmN0aW9uIGFkZENsYXNzKG5vZGUsIGNscykge1xuICAgIHZhciBjdXJyZW50ID0gbm9kZS5jbGFzc05hbWU7XG4gICAgaWYgKCFjbGFzc1Rlc3QoY2xzKS50ZXN0KGN1cnJlbnQpKSB7IG5vZGUuY2xhc3NOYW1lICs9IChjdXJyZW50ID8gXCIgXCIgOiBcIlwiKSArIGNsczsgfVxuICB9XG4gIGZ1bmN0aW9uIGpvaW5DbGFzc2VzKGEsIGIpIHtcbiAgICB2YXIgYXMgPSBhLnNwbGl0KFwiIFwiKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFzLmxlbmd0aDsgaSsrKVxuICAgICAgeyBpZiAoYXNbaV0gJiYgIWNsYXNzVGVzdChhc1tpXSkudGVzdChiKSkgeyBiICs9IFwiIFwiICsgYXNbaV07IH0gfVxuICAgIHJldHVybiBiXG4gIH1cblxuICB2YXIgc2VsZWN0SW5wdXQgPSBmdW5jdGlvbihub2RlKSB7IG5vZGUuc2VsZWN0KCk7IH07XG4gIGlmIChpb3MpIC8vIE1vYmlsZSBTYWZhcmkgYXBwYXJlbnRseSBoYXMgYSBidWcgd2hlcmUgc2VsZWN0KCkgaXMgYnJva2VuLlxuICAgIHsgc2VsZWN0SW5wdXQgPSBmdW5jdGlvbihub2RlKSB7IG5vZGUuc2VsZWN0aW9uU3RhcnQgPSAwOyBub2RlLnNlbGVjdGlvbkVuZCA9IG5vZGUudmFsdWUubGVuZ3RoOyB9OyB9XG4gIGVsc2UgaWYgKGllKSAvLyBTdXBwcmVzcyBteXN0ZXJpb3VzIElFMTAgZXJyb3JzXG4gICAgeyBzZWxlY3RJbnB1dCA9IGZ1bmN0aW9uKG5vZGUpIHsgdHJ5IHsgbm9kZS5zZWxlY3QoKTsgfSBjYXRjaChfZSkge30gfTsgfVxuXG4gIGZ1bmN0aW9uIGJpbmQoZikge1xuICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICByZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gZi5hcHBseShudWxsLCBhcmdzKX1cbiAgfVxuXG4gIGZ1bmN0aW9uIGNvcHlPYmoob2JqLCB0YXJnZXQsIG92ZXJ3cml0ZSkge1xuICAgIGlmICghdGFyZ2V0KSB7IHRhcmdldCA9IHt9OyB9XG4gICAgZm9yICh2YXIgcHJvcCBpbiBvYmopXG4gICAgICB7IGlmIChvYmouaGFzT3duUHJvcGVydHkocHJvcCkgJiYgKG92ZXJ3cml0ZSAhPT0gZmFsc2UgfHwgIXRhcmdldC5oYXNPd25Qcm9wZXJ0eShwcm9wKSkpXG4gICAgICAgIHsgdGFyZ2V0W3Byb3BdID0gb2JqW3Byb3BdOyB9IH1cbiAgICByZXR1cm4gdGFyZ2V0XG4gIH1cblxuICAvLyBDb3VudHMgdGhlIGNvbHVtbiBvZmZzZXQgaW4gYSBzdHJpbmcsIHRha2luZyB0YWJzIGludG8gYWNjb3VudC5cbiAgLy8gVXNlZCBtb3N0bHkgdG8gZmluZCBpbmRlbnRhdGlvbi5cbiAgZnVuY3Rpb24gY291bnRDb2x1bW4oc3RyaW5nLCBlbmQsIHRhYlNpemUsIHN0YXJ0SW5kZXgsIHN0YXJ0VmFsdWUpIHtcbiAgICBpZiAoZW5kID09IG51bGwpIHtcbiAgICAgIGVuZCA9IHN0cmluZy5zZWFyY2goL1teXFxzXFx1MDBhMF0vKTtcbiAgICAgIGlmIChlbmQgPT0gLTEpIHsgZW5kID0gc3RyaW5nLmxlbmd0aDsgfVxuICAgIH1cbiAgICBmb3IgKHZhciBpID0gc3RhcnRJbmRleCB8fCAwLCBuID0gc3RhcnRWYWx1ZSB8fCAwOzspIHtcbiAgICAgIHZhciBuZXh0VGFiID0gc3RyaW5nLmluZGV4T2YoXCJcXHRcIiwgaSk7XG4gICAgICBpZiAobmV4dFRhYiA8IDAgfHwgbmV4dFRhYiA+PSBlbmQpXG4gICAgICAgIHsgcmV0dXJuIG4gKyAoZW5kIC0gaSkgfVxuICAgICAgbiArPSBuZXh0VGFiIC0gaTtcbiAgICAgIG4gKz0gdGFiU2l6ZSAtIChuICUgdGFiU2l6ZSk7XG4gICAgICBpID0gbmV4dFRhYiArIDE7XG4gICAgfVxuICB9XG5cbiAgdmFyIERlbGF5ZWQgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLmlkID0gbnVsbDtcbiAgICB0aGlzLmYgPSBudWxsO1xuICAgIHRoaXMudGltZSA9IDA7XG4gICAgdGhpcy5oYW5kbGVyID0gYmluZCh0aGlzLm9uVGltZW91dCwgdGhpcyk7XG4gIH07XG4gIERlbGF5ZWQucHJvdG90eXBlLm9uVGltZW91dCA9IGZ1bmN0aW9uIChzZWxmKSB7XG4gICAgc2VsZi5pZCA9IDA7XG4gICAgaWYgKHNlbGYudGltZSA8PSArbmV3IERhdGUpIHtcbiAgICAgIHNlbGYuZigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzZXRUaW1lb3V0KHNlbGYuaGFuZGxlciwgc2VsZi50aW1lIC0gK25ldyBEYXRlKTtcbiAgICB9XG4gIH07XG4gIERlbGF5ZWQucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uIChtcywgZikge1xuICAgIHRoaXMuZiA9IGY7XG4gICAgdmFyIHRpbWUgPSArbmV3IERhdGUgKyBtcztcbiAgICBpZiAoIXRoaXMuaWQgfHwgdGltZSA8IHRoaXMudGltZSkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuaWQpO1xuICAgICAgdGhpcy5pZCA9IHNldFRpbWVvdXQodGhpcy5oYW5kbGVyLCBtcyk7XG4gICAgICB0aGlzLnRpbWUgPSB0aW1lO1xuICAgIH1cbiAgfTtcblxuICBmdW5jdGlvbiBpbmRleE9mKGFycmF5LCBlbHQpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgKytpKVxuICAgICAgeyBpZiAoYXJyYXlbaV0gPT0gZWx0KSB7IHJldHVybiBpIH0gfVxuICAgIHJldHVybiAtMVxuICB9XG5cbiAgLy8gTnVtYmVyIG9mIHBpeGVscyBhZGRlZCB0byBzY3JvbGxlciBhbmQgc2l6ZXIgdG8gaGlkZSBzY3JvbGxiYXJcbiAgdmFyIHNjcm9sbGVyR2FwID0gNTA7XG5cbiAgLy8gUmV0dXJuZWQgb3IgdGhyb3duIGJ5IHZhcmlvdXMgcHJvdG9jb2xzIHRvIHNpZ25hbCAnSSdtIG5vdFxuICAvLyBoYW5kbGluZyB0aGlzJy5cbiAgdmFyIFBhc3MgPSB7dG9TdHJpbmc6IGZ1bmN0aW9uKCl7cmV0dXJuIFwiQ29kZU1pcnJvci5QYXNzXCJ9fTtcblxuICAvLyBSZXVzZWQgb3B0aW9uIG9iamVjdHMgZm9yIHNldFNlbGVjdGlvbiAmIGZyaWVuZHNcbiAgdmFyIHNlbF9kb250U2Nyb2xsID0ge3Njcm9sbDogZmFsc2V9LCBzZWxfbW91c2UgPSB7b3JpZ2luOiBcIiptb3VzZVwifSwgc2VsX21vdmUgPSB7b3JpZ2luOiBcIittb3ZlXCJ9O1xuXG4gIC8vIFRoZSBpbnZlcnNlIG9mIGNvdW50Q29sdW1uIC0tIGZpbmQgdGhlIG9mZnNldCB0aGF0IGNvcnJlc3BvbmRzIHRvXG4gIC8vIGEgcGFydGljdWxhciBjb2x1bW4uXG4gIGZ1bmN0aW9uIGZpbmRDb2x1bW4oc3RyaW5nLCBnb2FsLCB0YWJTaXplKSB7XG4gICAgZm9yICh2YXIgcG9zID0gMCwgY29sID0gMDs7KSB7XG4gICAgICB2YXIgbmV4dFRhYiA9IHN0cmluZy5pbmRleE9mKFwiXFx0XCIsIHBvcyk7XG4gICAgICBpZiAobmV4dFRhYiA9PSAtMSkgeyBuZXh0VGFiID0gc3RyaW5nLmxlbmd0aDsgfVxuICAgICAgdmFyIHNraXBwZWQgPSBuZXh0VGFiIC0gcG9zO1xuICAgICAgaWYgKG5leHRUYWIgPT0gc3RyaW5nLmxlbmd0aCB8fCBjb2wgKyBza2lwcGVkID49IGdvYWwpXG4gICAgICAgIHsgcmV0dXJuIHBvcyArIE1hdGgubWluKHNraXBwZWQsIGdvYWwgLSBjb2wpIH1cbiAgICAgIGNvbCArPSBuZXh0VGFiIC0gcG9zO1xuICAgICAgY29sICs9IHRhYlNpemUgLSAoY29sICUgdGFiU2l6ZSk7XG4gICAgICBwb3MgPSBuZXh0VGFiICsgMTtcbiAgICAgIGlmIChjb2wgPj0gZ29hbCkgeyByZXR1cm4gcG9zIH1cbiAgICB9XG4gIH1cblxuICB2YXIgc3BhY2VTdHJzID0gW1wiXCJdO1xuICBmdW5jdGlvbiBzcGFjZVN0cihuKSB7XG4gICAgd2hpbGUgKHNwYWNlU3Rycy5sZW5ndGggPD0gbilcbiAgICAgIHsgc3BhY2VTdHJzLnB1c2gobHN0KHNwYWNlU3RycykgKyBcIiBcIik7IH1cbiAgICByZXR1cm4gc3BhY2VTdHJzW25dXG4gIH1cblxuICBmdW5jdGlvbiBsc3QoYXJyKSB7IHJldHVybiBhcnJbYXJyLmxlbmd0aC0xXSB9XG5cbiAgZnVuY3Rpb24gbWFwKGFycmF5LCBmKSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHsgb3V0W2ldID0gZihhcnJheVtpXSwgaSk7IH1cbiAgICByZXR1cm4gb3V0XG4gIH1cblxuICBmdW5jdGlvbiBpbnNlcnRTb3J0ZWQoYXJyYXksIHZhbHVlLCBzY29yZSkge1xuICAgIHZhciBwb3MgPSAwLCBwcmlvcml0eSA9IHNjb3JlKHZhbHVlKTtcbiAgICB3aGlsZSAocG9zIDwgYXJyYXkubGVuZ3RoICYmIHNjb3JlKGFycmF5W3Bvc10pIDw9IHByaW9yaXR5KSB7IHBvcysrOyB9XG4gICAgYXJyYXkuc3BsaWNlKHBvcywgMCwgdmFsdWUpO1xuICB9XG5cbiAgZnVuY3Rpb24gbm90aGluZygpIHt9XG5cbiAgZnVuY3Rpb24gY3JlYXRlT2JqKGJhc2UsIHByb3BzKSB7XG4gICAgdmFyIGluc3Q7XG4gICAgaWYgKE9iamVjdC5jcmVhdGUpIHtcbiAgICAgIGluc3QgPSBPYmplY3QuY3JlYXRlKGJhc2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICBub3RoaW5nLnByb3RvdHlwZSA9IGJhc2U7XG4gICAgICBpbnN0ID0gbmV3IG5vdGhpbmcoKTtcbiAgICB9XG4gICAgaWYgKHByb3BzKSB7IGNvcHlPYmoocHJvcHMsIGluc3QpOyB9XG4gICAgcmV0dXJuIGluc3RcbiAgfVxuXG4gIHZhciBub25BU0NJSVNpbmdsZUNhc2VXb3JkQ2hhciA9IC9bXFx1MDBkZlxcdTA1ODdcXHUwNTkwLVxcdTA1ZjRcXHUwNjAwLVxcdTA2ZmZcXHUzMDQwLVxcdTMwOWZcXHUzMGEwLVxcdTMwZmZcXHUzNDAwLVxcdTRkYjVcXHU0ZTAwLVxcdTlmY2NcXHVhYzAwLVxcdWQ3YWZdLztcbiAgZnVuY3Rpb24gaXNXb3JkQ2hhckJhc2ljKGNoKSB7XG4gICAgcmV0dXJuIC9cXHcvLnRlc3QoY2gpIHx8IGNoID4gXCJcXHg4MFwiICYmXG4gICAgICAoY2gudG9VcHBlckNhc2UoKSAhPSBjaC50b0xvd2VyQ2FzZSgpIHx8IG5vbkFTQ0lJU2luZ2xlQ2FzZVdvcmRDaGFyLnRlc3QoY2gpKVxuICB9XG4gIGZ1bmN0aW9uIGlzV29yZENoYXIoY2gsIGhlbHBlcikge1xuICAgIGlmICghaGVscGVyKSB7IHJldHVybiBpc1dvcmRDaGFyQmFzaWMoY2gpIH1cbiAgICBpZiAoaGVscGVyLnNvdXJjZS5pbmRleE9mKFwiXFxcXHdcIikgPiAtMSAmJiBpc1dvcmRDaGFyQmFzaWMoY2gpKSB7IHJldHVybiB0cnVlIH1cbiAgICByZXR1cm4gaGVscGVyLnRlc3QoY2gpXG4gIH1cblxuICBmdW5jdGlvbiBpc0VtcHR5KG9iaikge1xuICAgIGZvciAodmFyIG4gaW4gb2JqKSB7IGlmIChvYmouaGFzT3duUHJvcGVydHkobikgJiYgb2JqW25dKSB7IHJldHVybiBmYWxzZSB9IH1cbiAgICByZXR1cm4gdHJ1ZVxuICB9XG5cbiAgLy8gRXh0ZW5kaW5nIHVuaWNvZGUgY2hhcmFjdGVycy4gQSBzZXJpZXMgb2YgYSBub24tZXh0ZW5kaW5nIGNoYXIgK1xuICAvLyBhbnkgbnVtYmVyIG9mIGV4dGVuZGluZyBjaGFycyBpcyB0cmVhdGVkIGFzIGEgc2luZ2xlIHVuaXQgYXMgZmFyXG4gIC8vIGFzIGVkaXRpbmcgYW5kIG1lYXN1cmluZyBpcyBjb25jZXJuZWQuIFRoaXMgaXMgbm90IGZ1bGx5IGNvcnJlY3QsXG4gIC8vIHNpbmNlIHNvbWUgc2NyaXB0cy9mb250cy9icm93c2VycyBhbHNvIHRyZWF0IG90aGVyIGNvbmZpZ3VyYXRpb25zXG4gIC8vIG9mIGNvZGUgcG9pbnRzIGFzIGEgZ3JvdXAuXG4gIHZhciBleHRlbmRpbmdDaGFycyA9IC9bXFx1MDMwMC1cXHUwMzZmXFx1MDQ4My1cXHUwNDg5XFx1MDU5MS1cXHUwNWJkXFx1MDViZlxcdTA1YzFcXHUwNWMyXFx1MDVjNFxcdTA1YzVcXHUwNWM3XFx1MDYxMC1cXHUwNjFhXFx1MDY0Yi1cXHUwNjVlXFx1MDY3MFxcdTA2ZDYtXFx1MDZkY1xcdTA2ZGUtXFx1MDZlNFxcdTA2ZTdcXHUwNmU4XFx1MDZlYS1cXHUwNmVkXFx1MDcxMVxcdTA3MzAtXFx1MDc0YVxcdTA3YTYtXFx1MDdiMFxcdTA3ZWItXFx1MDdmM1xcdTA4MTYtXFx1MDgxOVxcdTA4MWItXFx1MDgyM1xcdTA4MjUtXFx1MDgyN1xcdTA4MjktXFx1MDgyZFxcdTA5MDAtXFx1MDkwMlxcdTA5M2NcXHUwOTQxLVxcdTA5NDhcXHUwOTRkXFx1MDk1MS1cXHUwOTU1XFx1MDk2MlxcdTA5NjNcXHUwOTgxXFx1MDliY1xcdTA5YmVcXHUwOWMxLVxcdTA5YzRcXHUwOWNkXFx1MDlkN1xcdTA5ZTJcXHUwOWUzXFx1MGEwMVxcdTBhMDJcXHUwYTNjXFx1MGE0MVxcdTBhNDJcXHUwYTQ3XFx1MGE0OFxcdTBhNGItXFx1MGE0ZFxcdTBhNTFcXHUwYTcwXFx1MGE3MVxcdTBhNzVcXHUwYTgxXFx1MGE4MlxcdTBhYmNcXHUwYWMxLVxcdTBhYzVcXHUwYWM3XFx1MGFjOFxcdTBhY2RcXHUwYWUyXFx1MGFlM1xcdTBiMDFcXHUwYjNjXFx1MGIzZVxcdTBiM2ZcXHUwYjQxLVxcdTBiNDRcXHUwYjRkXFx1MGI1NlxcdTBiNTdcXHUwYjYyXFx1MGI2M1xcdTBiODJcXHUwYmJlXFx1MGJjMFxcdTBiY2RcXHUwYmQ3XFx1MGMzZS1cXHUwYzQwXFx1MGM0Ni1cXHUwYzQ4XFx1MGM0YS1cXHUwYzRkXFx1MGM1NVxcdTBjNTZcXHUwYzYyXFx1MGM2M1xcdTBjYmNcXHUwY2JmXFx1MGNjMlxcdTBjYzZcXHUwY2NjXFx1MGNjZFxcdTBjZDVcXHUwY2Q2XFx1MGNlMlxcdTBjZTNcXHUwZDNlXFx1MGQ0MS1cXHUwZDQ0XFx1MGQ0ZFxcdTBkNTdcXHUwZDYyXFx1MGQ2M1xcdTBkY2FcXHUwZGNmXFx1MGRkMi1cXHUwZGQ0XFx1MGRkNlxcdTBkZGZcXHUwZTMxXFx1MGUzNC1cXHUwZTNhXFx1MGU0Ny1cXHUwZTRlXFx1MGViMVxcdTBlYjQtXFx1MGViOVxcdTBlYmJcXHUwZWJjXFx1MGVjOC1cXHUwZWNkXFx1MGYxOFxcdTBmMTlcXHUwZjM1XFx1MGYzN1xcdTBmMzlcXHUwZjcxLVxcdTBmN2VcXHUwZjgwLVxcdTBmODRcXHUwZjg2XFx1MGY4N1xcdTBmOTAtXFx1MGY5N1xcdTBmOTktXFx1MGZiY1xcdTBmYzZcXHUxMDJkLVxcdTEwMzBcXHUxMDMyLVxcdTEwMzdcXHUxMDM5XFx1MTAzYVxcdTEwM2RcXHUxMDNlXFx1MTA1OFxcdTEwNTlcXHUxMDVlLVxcdTEwNjBcXHUxMDcxLVxcdTEwNzRcXHUxMDgyXFx1MTA4NVxcdTEwODZcXHUxMDhkXFx1MTA5ZFxcdTEzNWZcXHUxNzEyLVxcdTE3MTRcXHUxNzMyLVxcdTE3MzRcXHUxNzUyXFx1MTc1M1xcdTE3NzJcXHUxNzczXFx1MTdiNy1cXHUxN2JkXFx1MTdjNlxcdTE3YzktXFx1MTdkM1xcdTE3ZGRcXHUxODBiLVxcdTE4MGRcXHUxOGE5XFx1MTkyMC1cXHUxOTIyXFx1MTkyN1xcdTE5MjhcXHUxOTMyXFx1MTkzOS1cXHUxOTNiXFx1MWExN1xcdTFhMThcXHUxYTU2XFx1MWE1OC1cXHUxYTVlXFx1MWE2MFxcdTFhNjJcXHUxYTY1LVxcdTFhNmNcXHUxYTczLVxcdTFhN2NcXHUxYTdmXFx1MWIwMC1cXHUxYjAzXFx1MWIzNFxcdTFiMzYtXFx1MWIzYVxcdTFiM2NcXHUxYjQyXFx1MWI2Yi1cXHUxYjczXFx1MWI4MFxcdTFiODFcXHUxYmEyLVxcdTFiYTVcXHUxYmE4XFx1MWJhOVxcdTFjMmMtXFx1MWMzM1xcdTFjMzZcXHUxYzM3XFx1MWNkMC1cXHUxY2QyXFx1MWNkNC1cXHUxY2UwXFx1MWNlMi1cXHUxY2U4XFx1MWNlZFxcdTFkYzAtXFx1MWRlNlxcdTFkZmQtXFx1MWRmZlxcdTIwMGNcXHUyMDBkXFx1MjBkMC1cXHUyMGYwXFx1MmNlZi1cXHUyY2YxXFx1MmRlMC1cXHUyZGZmXFx1MzAyYS1cXHUzMDJmXFx1MzA5OVxcdTMwOWFcXHVhNjZmLVxcdWE2NzJcXHVhNjdjXFx1YTY3ZFxcdWE2ZjBcXHVhNmYxXFx1YTgwMlxcdWE4MDZcXHVhODBiXFx1YTgyNVxcdWE4MjZcXHVhOGM0XFx1YThlMC1cXHVhOGYxXFx1YTkyNi1cXHVhOTJkXFx1YTk0Ny1cXHVhOTUxXFx1YTk4MC1cXHVhOTgyXFx1YTliM1xcdWE5YjYtXFx1YTliOVxcdWE5YmNcXHVhYTI5LVxcdWFhMmVcXHVhYTMxXFx1YWEzMlxcdWFhMzVcXHVhYTM2XFx1YWE0M1xcdWFhNGNcXHVhYWIwXFx1YWFiMi1cXHVhYWI0XFx1YWFiN1xcdWFhYjhcXHVhYWJlXFx1YWFiZlxcdWFhYzFcXHVhYmU1XFx1YWJlOFxcdWFiZWRcXHVkYzAwLVxcdWRmZmZcXHVmYjFlXFx1ZmUwMC1cXHVmZTBmXFx1ZmUyMC1cXHVmZTI2XFx1ZmY5ZVxcdWZmOWZdLztcbiAgZnVuY3Rpb24gaXNFeHRlbmRpbmdDaGFyKGNoKSB7IHJldHVybiBjaC5jaGFyQ29kZUF0KDApID49IDc2OCAmJiBleHRlbmRpbmdDaGFycy50ZXN0KGNoKSB9XG5cbiAgLy8gUmV0dXJucyBhIG51bWJlciBmcm9tIHRoZSByYW5nZSBbYDBgOyBgc3RyLmxlbmd0aGBdIHVubGVzcyBgcG9zYCBpcyBvdXRzaWRlIHRoYXQgcmFuZ2UuXG4gIGZ1bmN0aW9uIHNraXBFeHRlbmRpbmdDaGFycyhzdHIsIHBvcywgZGlyKSB7XG4gICAgd2hpbGUgKChkaXIgPCAwID8gcG9zID4gMCA6IHBvcyA8IHN0ci5sZW5ndGgpICYmIGlzRXh0ZW5kaW5nQ2hhcihzdHIuY2hhckF0KHBvcykpKSB7IHBvcyArPSBkaXI7IH1cbiAgICByZXR1cm4gcG9zXG4gIH1cblxuICAvLyBSZXR1cm5zIHRoZSB2YWx1ZSBmcm9tIHRoZSByYW5nZSBbYGZyb21gOyBgdG9gXSB0aGF0IHNhdGlzZmllc1xuICAvLyBgcHJlZGAgYW5kIGlzIGNsb3Nlc3QgdG8gYGZyb21gLiBBc3N1bWVzIHRoYXQgYXQgbGVhc3QgYHRvYFxuICAvLyBzYXRpc2ZpZXMgYHByZWRgLiBTdXBwb3J0cyBgZnJvbWAgYmVpbmcgZ3JlYXRlciB0aGFuIGB0b2AuXG4gIGZ1bmN0aW9uIGZpbmRGaXJzdChwcmVkLCBmcm9tLCB0bykge1xuICAgIC8vIEF0IGFueSBwb2ludCB3ZSBhcmUgY2VydGFpbiBgdG9gIHNhdGlzZmllcyBgcHJlZGAsIGRvbid0IGtub3dcbiAgICAvLyB3aGV0aGVyIGBmcm9tYCBkb2VzLlxuICAgIHZhciBkaXIgPSBmcm9tID4gdG8gPyAtMSA6IDE7XG4gICAgZm9yICg7Oykge1xuICAgICAgaWYgKGZyb20gPT0gdG8pIHsgcmV0dXJuIGZyb20gfVxuICAgICAgdmFyIG1pZEYgPSAoZnJvbSArIHRvKSAvIDIsIG1pZCA9IGRpciA8IDAgPyBNYXRoLmNlaWwobWlkRikgOiBNYXRoLmZsb29yKG1pZEYpO1xuICAgICAgaWYgKG1pZCA9PSBmcm9tKSB7IHJldHVybiBwcmVkKG1pZCkgPyBmcm9tIDogdG8gfVxuICAgICAgaWYgKHByZWQobWlkKSkgeyB0byA9IG1pZDsgfVxuICAgICAgZWxzZSB7IGZyb20gPSBtaWQgKyBkaXI7IH1cbiAgICB9XG4gIH1cblxuICAvLyBCSURJIEhFTFBFUlNcblxuICBmdW5jdGlvbiBpdGVyYXRlQmlkaVNlY3Rpb25zKG9yZGVyLCBmcm9tLCB0bywgZikge1xuICAgIGlmICghb3JkZXIpIHsgcmV0dXJuIGYoZnJvbSwgdG8sIFwibHRyXCIsIDApIH1cbiAgICB2YXIgZm91bmQgPSBmYWxzZTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9yZGVyLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgcGFydCA9IG9yZGVyW2ldO1xuICAgICAgaWYgKHBhcnQuZnJvbSA8IHRvICYmIHBhcnQudG8gPiBmcm9tIHx8IGZyb20gPT0gdG8gJiYgcGFydC50byA9PSBmcm9tKSB7XG4gICAgICAgIGYoTWF0aC5tYXgocGFydC5mcm9tLCBmcm9tKSwgTWF0aC5taW4ocGFydC50bywgdG8pLCBwYXJ0LmxldmVsID09IDEgPyBcInJ0bFwiIDogXCJsdHJcIiwgaSk7XG4gICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFmb3VuZCkgeyBmKGZyb20sIHRvLCBcImx0clwiKTsgfVxuICB9XG5cbiAgdmFyIGJpZGlPdGhlciA9IG51bGw7XG4gIGZ1bmN0aW9uIGdldEJpZGlQYXJ0QXQob3JkZXIsIGNoLCBzdGlja3kpIHtcbiAgICB2YXIgZm91bmQ7XG4gICAgYmlkaU90aGVyID0gbnVsbDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9yZGVyLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgY3VyID0gb3JkZXJbaV07XG4gICAgICBpZiAoY3VyLmZyb20gPCBjaCAmJiBjdXIudG8gPiBjaCkgeyByZXR1cm4gaSB9XG4gICAgICBpZiAoY3VyLnRvID09IGNoKSB7XG4gICAgICAgIGlmIChjdXIuZnJvbSAhPSBjdXIudG8gJiYgc3RpY2t5ID09IFwiYmVmb3JlXCIpIHsgZm91bmQgPSBpOyB9XG4gICAgICAgIGVsc2UgeyBiaWRpT3RoZXIgPSBpOyB9XG4gICAgICB9XG4gICAgICBpZiAoY3VyLmZyb20gPT0gY2gpIHtcbiAgICAgICAgaWYgKGN1ci5mcm9tICE9IGN1ci50byAmJiBzdGlja3kgIT0gXCJiZWZvcmVcIikgeyBmb3VuZCA9IGk7IH1cbiAgICAgICAgZWxzZSB7IGJpZGlPdGhlciA9IGk7IH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZvdW5kICE9IG51bGwgPyBmb3VuZCA6IGJpZGlPdGhlclxuICB9XG5cbiAgLy8gQmlkaXJlY3Rpb25hbCBvcmRlcmluZyBhbGdvcml0aG1cbiAgLy8gU2VlIGh0dHA6Ly91bmljb2RlLm9yZy9yZXBvcnRzL3RyOS90cjktMTMuaHRtbCBmb3IgdGhlIGFsZ29yaXRobVxuICAvLyB0aGF0IHRoaXMgKHBhcnRpYWxseSkgaW1wbGVtZW50cy5cblxuICAvLyBPbmUtY2hhciBjb2RlcyB1c2VkIGZvciBjaGFyYWN0ZXIgdHlwZXM6XG4gIC8vIEwgKEwpOiAgIExlZnQtdG8tUmlnaHRcbiAgLy8gUiAoUik6ICAgUmlnaHQtdG8tTGVmdFxuICAvLyByIChBTCk6ICBSaWdodC10by1MZWZ0IEFyYWJpY1xuICAvLyAxIChFTik6ICBFdXJvcGVhbiBOdW1iZXJcbiAgLy8gKyAoRVMpOiAgRXVyb3BlYW4gTnVtYmVyIFNlcGFyYXRvclxuICAvLyAlIChFVCk6ICBFdXJvcGVhbiBOdW1iZXIgVGVybWluYXRvclxuICAvLyBuIChBTik6ICBBcmFiaWMgTnVtYmVyXG4gIC8vICwgKENTKTogIENvbW1vbiBOdW1iZXIgU2VwYXJhdG9yXG4gIC8vIG0gKE5TTSk6IE5vbi1TcGFjaW5nIE1hcmtcbiAgLy8gYiAoQk4pOiAgQm91bmRhcnkgTmV1dHJhbFxuICAvLyBzIChCKTogICBQYXJhZ3JhcGggU2VwYXJhdG9yXG4gIC8vIHQgKFMpOiAgIFNlZ21lbnQgU2VwYXJhdG9yXG4gIC8vIHcgKFdTKTogIFdoaXRlc3BhY2VcbiAgLy8gTiAoT04pOiAgT3RoZXIgTmV1dHJhbHNcblxuICAvLyBSZXR1cm5zIG51bGwgaWYgY2hhcmFjdGVycyBhcmUgb3JkZXJlZCBhcyB0aGV5IGFwcGVhclxuICAvLyAobGVmdC10by1yaWdodCksIG9yIGFuIGFycmF5IG9mIHNlY3Rpb25zICh7ZnJvbSwgdG8sIGxldmVsfVxuICAvLyBvYmplY3RzKSBpbiB0aGUgb3JkZXIgaW4gd2hpY2ggdGhleSBvY2N1ciB2aXN1YWxseS5cbiAgdmFyIGJpZGlPcmRlcmluZyA9IChmdW5jdGlvbigpIHtcbiAgICAvLyBDaGFyYWN0ZXIgdHlwZXMgZm9yIGNvZGVwb2ludHMgMCB0byAweGZmXG4gICAgdmFyIGxvd1R5cGVzID0gXCJiYmJiYmJiYmJ0c3R3c2JiYmJiYmJiYmJiYmJic3NzdHdOTiUlJU5OTk5OTixOLE4xMTExMTExMTExTk5OTk5OTkxMTExMTExMTExMTExMTExMTExMTExMTExMTk5OTk5OTExMTExMTExMTExMTExMTExMTExMTExMTExOTk5OYmJiYmJic2JiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiLE4lJSUlTk5OTkxOTk5OTiUlMTFOTE5OTjFMTk5OTk5MTExMTExMTExMTExMTExMTExMTExMTE5MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTlwiO1xuICAgIC8vIENoYXJhY3RlciB0eXBlcyBmb3IgY29kZXBvaW50cyAweDYwMCB0byAweDZmOVxuICAgIHZhciBhcmFiaWNUeXBlcyA9IFwibm5ubm5uTk5yJSVyLHJOTm1tbW1tbW1tbW1tcnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJybW1tbW1tbW1tbW1tbW1tbW1tbW1tbm5ubm5ubm5ubiVubnJycm1ycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycm1tbW1tbW1uTm1tbW1tbXJybW1ObW1tbXJyMTExMTExMTExMVwiO1xuICAgIGZ1bmN0aW9uIGNoYXJUeXBlKGNvZGUpIHtcbiAgICAgIGlmIChjb2RlIDw9IDB4ZjcpIHsgcmV0dXJuIGxvd1R5cGVzLmNoYXJBdChjb2RlKSB9XG4gICAgICBlbHNlIGlmICgweDU5MCA8PSBjb2RlICYmIGNvZGUgPD0gMHg1ZjQpIHsgcmV0dXJuIFwiUlwiIH1cbiAgICAgIGVsc2UgaWYgKDB4NjAwIDw9IGNvZGUgJiYgY29kZSA8PSAweDZmOSkgeyByZXR1cm4gYXJhYmljVHlwZXMuY2hhckF0KGNvZGUgLSAweDYwMCkgfVxuICAgICAgZWxzZSBpZiAoMHg2ZWUgPD0gY29kZSAmJiBjb2RlIDw9IDB4OGFjKSB7IHJldHVybiBcInJcIiB9XG4gICAgICBlbHNlIGlmICgweDIwMDAgPD0gY29kZSAmJiBjb2RlIDw9IDB4MjAwYikgeyByZXR1cm4gXCJ3XCIgfVxuICAgICAgZWxzZSBpZiAoY29kZSA9PSAweDIwMGMpIHsgcmV0dXJuIFwiYlwiIH1cbiAgICAgIGVsc2UgeyByZXR1cm4gXCJMXCIgfVxuICAgIH1cblxuICAgIHZhciBiaWRpUkUgPSAvW1xcdTA1OTAtXFx1MDVmNFxcdTA2MDAtXFx1MDZmZlxcdTA3MDAtXFx1MDhhY10vO1xuICAgIHZhciBpc05ldXRyYWwgPSAvW3N0d05dLywgaXNTdHJvbmcgPSAvW0xScl0vLCBjb3VudHNBc0xlZnQgPSAvW0xiMW5dLywgY291bnRzQXNOdW0gPSAvWzFuXS87XG5cbiAgICBmdW5jdGlvbiBCaWRpU3BhbihsZXZlbCwgZnJvbSwgdG8pIHtcbiAgICAgIHRoaXMubGV2ZWwgPSBsZXZlbDtcbiAgICAgIHRoaXMuZnJvbSA9IGZyb207IHRoaXMudG8gPSB0bztcbiAgICB9XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oc3RyLCBkaXJlY3Rpb24pIHtcbiAgICAgIHZhciBvdXRlclR5cGUgPSBkaXJlY3Rpb24gPT0gXCJsdHJcIiA/IFwiTFwiIDogXCJSXCI7XG5cbiAgICAgIGlmIChzdHIubGVuZ3RoID09IDAgfHwgZGlyZWN0aW9uID09IFwibHRyXCIgJiYgIWJpZGlSRS50ZXN0KHN0cikpIHsgcmV0dXJuIGZhbHNlIH1cbiAgICAgIHZhciBsZW4gPSBzdHIubGVuZ3RoLCB0eXBlcyA9IFtdO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgICAgeyB0eXBlcy5wdXNoKGNoYXJUeXBlKHN0ci5jaGFyQ29kZUF0KGkpKSk7IH1cblxuICAgICAgLy8gVzEuIEV4YW1pbmUgZWFjaCBub24tc3BhY2luZyBtYXJrIChOU00pIGluIHRoZSBsZXZlbCBydW4sIGFuZFxuICAgICAgLy8gY2hhbmdlIHRoZSB0eXBlIG9mIHRoZSBOU00gdG8gdGhlIHR5cGUgb2YgdGhlIHByZXZpb3VzXG4gICAgICAvLyBjaGFyYWN0ZXIuIElmIHRoZSBOU00gaXMgYXQgdGhlIHN0YXJ0IG9mIHRoZSBsZXZlbCBydW4sIGl0IHdpbGxcbiAgICAgIC8vIGdldCB0aGUgdHlwZSBvZiBzb3IuXG4gICAgICBmb3IgKHZhciBpJDEgPSAwLCBwcmV2ID0gb3V0ZXJUeXBlOyBpJDEgPCBsZW47ICsraSQxKSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZXNbaSQxXTtcbiAgICAgICAgaWYgKHR5cGUgPT0gXCJtXCIpIHsgdHlwZXNbaSQxXSA9IHByZXY7IH1cbiAgICAgICAgZWxzZSB7IHByZXYgPSB0eXBlOyB9XG4gICAgICB9XG5cbiAgICAgIC8vIFcyLiBTZWFyY2ggYmFja3dhcmRzIGZyb20gZWFjaCBpbnN0YW5jZSBvZiBhIEV1cm9wZWFuIG51bWJlclxuICAgICAgLy8gdW50aWwgdGhlIGZpcnN0IHN0cm9uZyB0eXBlIChSLCBMLCBBTCwgb3Igc29yKSBpcyBmb3VuZC4gSWYgYW5cbiAgICAgIC8vIEFMIGlzIGZvdW5kLCBjaGFuZ2UgdGhlIHR5cGUgb2YgdGhlIEV1cm9wZWFuIG51bWJlciB0byBBcmFiaWNcbiAgICAgIC8vIG51bWJlci5cbiAgICAgIC8vIFczLiBDaGFuZ2UgYWxsIEFMcyB0byBSLlxuICAgICAgZm9yICh2YXIgaSQyID0gMCwgY3VyID0gb3V0ZXJUeXBlOyBpJDIgPCBsZW47ICsraSQyKSB7XG4gICAgICAgIHZhciB0eXBlJDEgPSB0eXBlc1tpJDJdO1xuICAgICAgICBpZiAodHlwZSQxID09IFwiMVwiICYmIGN1ciA9PSBcInJcIikgeyB0eXBlc1tpJDJdID0gXCJuXCI7IH1cbiAgICAgICAgZWxzZSBpZiAoaXNTdHJvbmcudGVzdCh0eXBlJDEpKSB7IGN1ciA9IHR5cGUkMTsgaWYgKHR5cGUkMSA9PSBcInJcIikgeyB0eXBlc1tpJDJdID0gXCJSXCI7IH0gfVxuICAgICAgfVxuXG4gICAgICAvLyBXNC4gQSBzaW5nbGUgRXVyb3BlYW4gc2VwYXJhdG9yIGJldHdlZW4gdHdvIEV1cm9wZWFuIG51bWJlcnNcbiAgICAgIC8vIGNoYW5nZXMgdG8gYSBFdXJvcGVhbiBudW1iZXIuIEEgc2luZ2xlIGNvbW1vbiBzZXBhcmF0b3IgYmV0d2VlblxuICAgICAgLy8gdHdvIG51bWJlcnMgb2YgdGhlIHNhbWUgdHlwZSBjaGFuZ2VzIHRvIHRoYXQgdHlwZS5cbiAgICAgIGZvciAodmFyIGkkMyA9IDEsIHByZXYkMSA9IHR5cGVzWzBdOyBpJDMgPCBsZW4gLSAxOyArK2kkMykge1xuICAgICAgICB2YXIgdHlwZSQyID0gdHlwZXNbaSQzXTtcbiAgICAgICAgaWYgKHR5cGUkMiA9PSBcIitcIiAmJiBwcmV2JDEgPT0gXCIxXCIgJiYgdHlwZXNbaSQzKzFdID09IFwiMVwiKSB7IHR5cGVzW2kkM10gPSBcIjFcIjsgfVxuICAgICAgICBlbHNlIGlmICh0eXBlJDIgPT0gXCIsXCIgJiYgcHJldiQxID09IHR5cGVzW2kkMysxXSAmJlxuICAgICAgICAgICAgICAgICAocHJldiQxID09IFwiMVwiIHx8IHByZXYkMSA9PSBcIm5cIikpIHsgdHlwZXNbaSQzXSA9IHByZXYkMTsgfVxuICAgICAgICBwcmV2JDEgPSB0eXBlJDI7XG4gICAgICB9XG5cbiAgICAgIC8vIFc1LiBBIHNlcXVlbmNlIG9mIEV1cm9wZWFuIHRlcm1pbmF0b3JzIGFkamFjZW50IHRvIEV1cm9wZWFuXG4gICAgICAvLyBudW1iZXJzIGNoYW5nZXMgdG8gYWxsIEV1cm9wZWFuIG51bWJlcnMuXG4gICAgICAvLyBXNi4gT3RoZXJ3aXNlLCBzZXBhcmF0b3JzIGFuZCB0ZXJtaW5hdG9ycyBjaGFuZ2UgdG8gT3RoZXJcbiAgICAgIC8vIE5ldXRyYWwuXG4gICAgICBmb3IgKHZhciBpJDQgPSAwOyBpJDQgPCBsZW47ICsraSQ0KSB7XG4gICAgICAgIHZhciB0eXBlJDMgPSB0eXBlc1tpJDRdO1xuICAgICAgICBpZiAodHlwZSQzID09IFwiLFwiKSB7IHR5cGVzW2kkNF0gPSBcIk5cIjsgfVxuICAgICAgICBlbHNlIGlmICh0eXBlJDMgPT0gXCIlXCIpIHtcbiAgICAgICAgICB2YXIgZW5kID0gKHZvaWQgMCk7XG4gICAgICAgICAgZm9yIChlbmQgPSBpJDQgKyAxOyBlbmQgPCBsZW4gJiYgdHlwZXNbZW5kXSA9PSBcIiVcIjsgKytlbmQpIHt9XG4gICAgICAgICAgdmFyIHJlcGxhY2UgPSAoaSQ0ICYmIHR5cGVzW2kkNC0xXSA9PSBcIiFcIikgfHwgKGVuZCA8IGxlbiAmJiB0eXBlc1tlbmRdID09IFwiMVwiKSA/IFwiMVwiIDogXCJOXCI7XG4gICAgICAgICAgZm9yICh2YXIgaiA9IGkkNDsgaiA8IGVuZDsgKytqKSB7IHR5cGVzW2pdID0gcmVwbGFjZTsgfVxuICAgICAgICAgIGkkNCA9IGVuZCAtIDE7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gVzcuIFNlYXJjaCBiYWNrd2FyZHMgZnJvbSBlYWNoIGluc3RhbmNlIG9mIGEgRXVyb3BlYW4gbnVtYmVyXG4gICAgICAvLyB1bnRpbCB0aGUgZmlyc3Qgc3Ryb25nIHR5cGUgKFIsIEwsIG9yIHNvcikgaXMgZm91bmQuIElmIGFuIEwgaXNcbiAgICAgIC8vIGZvdW5kLCB0aGVuIGNoYW5nZSB0aGUgdHlwZSBvZiB0aGUgRXVyb3BlYW4gbnVtYmVyIHRvIEwuXG4gICAgICBmb3IgKHZhciBpJDUgPSAwLCBjdXIkMSA9IG91dGVyVHlwZTsgaSQ1IDwgbGVuOyArK2kkNSkge1xuICAgICAgICB2YXIgdHlwZSQ0ID0gdHlwZXNbaSQ1XTtcbiAgICAgICAgaWYgKGN1ciQxID09IFwiTFwiICYmIHR5cGUkNCA9PSBcIjFcIikgeyB0eXBlc1tpJDVdID0gXCJMXCI7IH1cbiAgICAgICAgZWxzZSBpZiAoaXNTdHJvbmcudGVzdCh0eXBlJDQpKSB7IGN1ciQxID0gdHlwZSQ0OyB9XG4gICAgICB9XG5cbiAgICAgIC8vIE4xLiBBIHNlcXVlbmNlIG9mIG5ldXRyYWxzIHRha2VzIHRoZSBkaXJlY3Rpb24gb2YgdGhlXG4gICAgICAvLyBzdXJyb3VuZGluZyBzdHJvbmcgdGV4dCBpZiB0aGUgdGV4dCBvbiBib3RoIHNpZGVzIGhhcyB0aGUgc2FtZVxuICAgICAgLy8gZGlyZWN0aW9uLiBFdXJvcGVhbiBhbmQgQXJhYmljIG51bWJlcnMgYWN0IGFzIGlmIHRoZXkgd2VyZSBSIGluXG4gICAgICAvLyB0ZXJtcyBvZiB0aGVpciBpbmZsdWVuY2Ugb24gbmV1dHJhbHMuIFN0YXJ0LW9mLWxldmVsLXJ1biAoc29yKVxuICAgICAgLy8gYW5kIGVuZC1vZi1sZXZlbC1ydW4gKGVvcikgYXJlIHVzZWQgYXQgbGV2ZWwgcnVuIGJvdW5kYXJpZXMuXG4gICAgICAvLyBOMi4gQW55IHJlbWFpbmluZyBuZXV0cmFscyB0YWtlIHRoZSBlbWJlZGRpbmcgZGlyZWN0aW9uLlxuICAgICAgZm9yICh2YXIgaSQ2ID0gMDsgaSQ2IDwgbGVuOyArK2kkNikge1xuICAgICAgICBpZiAoaXNOZXV0cmFsLnRlc3QodHlwZXNbaSQ2XSkpIHtcbiAgICAgICAgICB2YXIgZW5kJDEgPSAodm9pZCAwKTtcbiAgICAgICAgICBmb3IgKGVuZCQxID0gaSQ2ICsgMTsgZW5kJDEgPCBsZW4gJiYgaXNOZXV0cmFsLnRlc3QodHlwZXNbZW5kJDFdKTsgKytlbmQkMSkge31cbiAgICAgICAgICB2YXIgYmVmb3JlID0gKGkkNiA/IHR5cGVzW2kkNi0xXSA6IG91dGVyVHlwZSkgPT0gXCJMXCI7XG4gICAgICAgICAgdmFyIGFmdGVyID0gKGVuZCQxIDwgbGVuID8gdHlwZXNbZW5kJDFdIDogb3V0ZXJUeXBlKSA9PSBcIkxcIjtcbiAgICAgICAgICB2YXIgcmVwbGFjZSQxID0gYmVmb3JlID09IGFmdGVyID8gKGJlZm9yZSA/IFwiTFwiIDogXCJSXCIpIDogb3V0ZXJUeXBlO1xuICAgICAgICAgIGZvciAodmFyIGokMSA9IGkkNjsgaiQxIDwgZW5kJDE7ICsraiQxKSB7IHR5cGVzW2okMV0gPSByZXBsYWNlJDE7IH1cbiAgICAgICAgICBpJDYgPSBlbmQkMSAtIDE7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gSGVyZSB3ZSBkZXBhcnQgZnJvbSB0aGUgZG9jdW1lbnRlZCBhbGdvcml0aG0sIGluIG9yZGVyIHRvIGF2b2lkXG4gICAgICAvLyBidWlsZGluZyB1cCBhbiBhY3R1YWwgbGV2ZWxzIGFycmF5LiBTaW5jZSB0aGVyZSBhcmUgb25seSB0aHJlZVxuICAgICAgLy8gbGV2ZWxzICgwLCAxLCAyKSBpbiBhbiBpbXBsZW1lbnRhdGlvbiB0aGF0IGRvZXNuJ3QgdGFrZVxuICAgICAgLy8gZXhwbGljaXQgZW1iZWRkaW5nIGludG8gYWNjb3VudCwgd2UgY2FuIGJ1aWxkIHVwIHRoZSBvcmRlciBvblxuICAgICAgLy8gdGhlIGZseSwgd2l0aG91dCBmb2xsb3dpbmcgdGhlIGxldmVsLWJhc2VkIGFsZ29yaXRobS5cbiAgICAgIHZhciBvcmRlciA9IFtdLCBtO1xuICAgICAgZm9yICh2YXIgaSQ3ID0gMDsgaSQ3IDwgbGVuOykge1xuICAgICAgICBpZiAoY291bnRzQXNMZWZ0LnRlc3QodHlwZXNbaSQ3XSkpIHtcbiAgICAgICAgICB2YXIgc3RhcnQgPSBpJDc7XG4gICAgICAgICAgZm9yICgrK2kkNzsgaSQ3IDwgbGVuICYmIGNvdW50c0FzTGVmdC50ZXN0KHR5cGVzW2kkN10pOyArK2kkNykge31cbiAgICAgICAgICBvcmRlci5wdXNoKG5ldyBCaWRpU3BhbigwLCBzdGFydCwgaSQ3KSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHBvcyA9IGkkNywgYXQgPSBvcmRlci5sZW5ndGgsIGlzUlRMID0gZGlyZWN0aW9uID09IFwicnRsXCIgPyAxIDogMDtcbiAgICAgICAgICBmb3IgKCsraSQ3OyBpJDcgPCBsZW4gJiYgdHlwZXNbaSQ3XSAhPSBcIkxcIjsgKytpJDcpIHt9XG4gICAgICAgICAgZm9yICh2YXIgaiQyID0gcG9zOyBqJDIgPCBpJDc7KSB7XG4gICAgICAgICAgICBpZiAoY291bnRzQXNOdW0udGVzdCh0eXBlc1tqJDJdKSkge1xuICAgICAgICAgICAgICBpZiAocG9zIDwgaiQyKSB7IG9yZGVyLnNwbGljZShhdCwgMCwgbmV3IEJpZGlTcGFuKDEsIHBvcywgaiQyKSk7IGF0ICs9IGlzUlRMOyB9XG4gICAgICAgICAgICAgIHZhciBuc3RhcnQgPSBqJDI7XG4gICAgICAgICAgICAgIGZvciAoKytqJDI7IGokMiA8IGkkNyAmJiBjb3VudHNBc051bS50ZXN0KHR5cGVzW2okMl0pOyArK2okMikge31cbiAgICAgICAgICAgICAgb3JkZXIuc3BsaWNlKGF0LCAwLCBuZXcgQmlkaVNwYW4oMiwgbnN0YXJ0LCBqJDIpKTtcbiAgICAgICAgICAgICAgYXQgKz0gaXNSVEw7XG4gICAgICAgICAgICAgIHBvcyA9IGokMjtcbiAgICAgICAgICAgIH0gZWxzZSB7ICsraiQyOyB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChwb3MgPCBpJDcpIHsgb3JkZXIuc3BsaWNlKGF0LCAwLCBuZXcgQmlkaVNwYW4oMSwgcG9zLCBpJDcpKTsgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZGlyZWN0aW9uID09IFwibHRyXCIpIHtcbiAgICAgICAgaWYgKG9yZGVyWzBdLmxldmVsID09IDEgJiYgKG0gPSBzdHIubWF0Y2goL15cXHMrLykpKSB7XG4gICAgICAgICAgb3JkZXJbMF0uZnJvbSA9IG1bMF0ubGVuZ3RoO1xuICAgICAgICAgIG9yZGVyLnVuc2hpZnQobmV3IEJpZGlTcGFuKDAsIDAsIG1bMF0ubGVuZ3RoKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxzdChvcmRlcikubGV2ZWwgPT0gMSAmJiAobSA9IHN0ci5tYXRjaCgvXFxzKyQvKSkpIHtcbiAgICAgICAgICBsc3Qob3JkZXIpLnRvIC09IG1bMF0ubGVuZ3RoO1xuICAgICAgICAgIG9yZGVyLnB1c2gobmV3IEJpZGlTcGFuKDAsIGxlbiAtIG1bMF0ubGVuZ3RoLCBsZW4pKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gZGlyZWN0aW9uID09IFwicnRsXCIgPyBvcmRlci5yZXZlcnNlKCkgOiBvcmRlclxuICAgIH1cbiAgfSkoKTtcblxuICAvLyBHZXQgdGhlIGJpZGkgb3JkZXJpbmcgZm9yIHRoZSBnaXZlbiBsaW5lIChhbmQgY2FjaGUgaXQpLiBSZXR1cm5zXG4gIC8vIGZhbHNlIGZvciBsaW5lcyB0aGF0IGFyZSBmdWxseSBsZWZ0LXRvLXJpZ2h0LCBhbmQgYW4gYXJyYXkgb2ZcbiAgLy8gQmlkaVNwYW4gb2JqZWN0cyBvdGhlcndpc2UuXG4gIGZ1bmN0aW9uIGdldE9yZGVyKGxpbmUsIGRpcmVjdGlvbikge1xuICAgIHZhciBvcmRlciA9IGxpbmUub3JkZXI7XG4gICAgaWYgKG9yZGVyID09IG51bGwpIHsgb3JkZXIgPSBsaW5lLm9yZGVyID0gYmlkaU9yZGVyaW5nKGxpbmUudGV4dCwgZGlyZWN0aW9uKTsgfVxuICAgIHJldHVybiBvcmRlclxuICB9XG5cbiAgLy8gRVZFTlQgSEFORExJTkdcblxuICAvLyBMaWdodHdlaWdodCBldmVudCBmcmFtZXdvcmsuIG9uL29mZiBhbHNvIHdvcmsgb24gRE9NIG5vZGVzLFxuICAvLyByZWdpc3RlcmluZyBuYXRpdmUgRE9NIGhhbmRsZXJzLlxuXG4gIHZhciBub0hhbmRsZXJzID0gW107XG5cbiAgdmFyIG9uID0gZnVuY3Rpb24oZW1pdHRlciwgdHlwZSwgZikge1xuICAgIGlmIChlbWl0dGVyLmFkZEV2ZW50TGlzdGVuZXIpIHtcbiAgICAgIGVtaXR0ZXIuYWRkRXZlbnRMaXN0ZW5lcih0eXBlLCBmLCBmYWxzZSk7XG4gICAgfSBlbHNlIGlmIChlbWl0dGVyLmF0dGFjaEV2ZW50KSB7XG4gICAgICBlbWl0dGVyLmF0dGFjaEV2ZW50KFwib25cIiArIHR5cGUsIGYpO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgbWFwID0gZW1pdHRlci5faGFuZGxlcnMgfHwgKGVtaXR0ZXIuX2hhbmRsZXJzID0ge30pO1xuICAgICAgbWFwW3R5cGVdID0gKG1hcFt0eXBlXSB8fCBub0hhbmRsZXJzKS5jb25jYXQoZik7XG4gICAgfVxuICB9O1xuXG4gIGZ1bmN0aW9uIGdldEhhbmRsZXJzKGVtaXR0ZXIsIHR5cGUpIHtcbiAgICByZXR1cm4gZW1pdHRlci5faGFuZGxlcnMgJiYgZW1pdHRlci5faGFuZGxlcnNbdHlwZV0gfHwgbm9IYW5kbGVyc1xuICB9XG5cbiAgZnVuY3Rpb24gb2ZmKGVtaXR0ZXIsIHR5cGUsIGYpIHtcbiAgICBpZiAoZW1pdHRlci5yZW1vdmVFdmVudExpc3RlbmVyKSB7XG4gICAgICBlbWl0dGVyLnJlbW92ZUV2ZW50TGlzdGVuZXIodHlwZSwgZiwgZmFsc2UpO1xuICAgIH0gZWxzZSBpZiAoZW1pdHRlci5kZXRhY2hFdmVudCkge1xuICAgICAgZW1pdHRlci5kZXRhY2hFdmVudChcIm9uXCIgKyB0eXBlLCBmKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIG1hcCA9IGVtaXR0ZXIuX2hhbmRsZXJzLCBhcnIgPSBtYXAgJiYgbWFwW3R5cGVdO1xuICAgICAgaWYgKGFycikge1xuICAgICAgICB2YXIgaW5kZXggPSBpbmRleE9mKGFyciwgZik7XG4gICAgICAgIGlmIChpbmRleCA+IC0xKVxuICAgICAgICAgIHsgbWFwW3R5cGVdID0gYXJyLnNsaWNlKDAsIGluZGV4KS5jb25jYXQoYXJyLnNsaWNlKGluZGV4ICsgMSkpOyB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gc2lnbmFsKGVtaXR0ZXIsIHR5cGUgLyosIHZhbHVlcy4uLiovKSB7XG4gICAgdmFyIGhhbmRsZXJzID0gZ2V0SGFuZGxlcnMoZW1pdHRlciwgdHlwZSk7XG4gICAgaWYgKCFoYW5kbGVycy5sZW5ndGgpIHsgcmV0dXJuIH1cbiAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoYW5kbGVycy5sZW5ndGg7ICsraSkgeyBoYW5kbGVyc1tpXS5hcHBseShudWxsLCBhcmdzKTsgfVxuICB9XG5cbiAgLy8gVGhlIERPTSBldmVudHMgdGhhdCBDb2RlTWlycm9yIGhhbmRsZXMgY2FuIGJlIG92ZXJyaWRkZW4gYnlcbiAgLy8gcmVnaXN0ZXJpbmcgYSAobm9uLURPTSkgaGFuZGxlciBvbiB0aGUgZWRpdG9yIGZvciB0aGUgZXZlbnQgbmFtZSxcbiAgLy8gYW5kIHByZXZlbnREZWZhdWx0LWluZyB0aGUgZXZlbnQgaW4gdGhhdCBoYW5kbGVyLlxuICBmdW5jdGlvbiBzaWduYWxET01FdmVudChjbSwgZSwgb3ZlcnJpZGUpIHtcbiAgICBpZiAodHlwZW9mIGUgPT0gXCJzdHJpbmdcIilcbiAgICAgIHsgZSA9IHt0eXBlOiBlLCBwcmV2ZW50RGVmYXVsdDogZnVuY3Rpb24oKSB7IHRoaXMuZGVmYXVsdFByZXZlbnRlZCA9IHRydWU7IH19OyB9XG4gICAgc2lnbmFsKGNtLCBvdmVycmlkZSB8fCBlLnR5cGUsIGNtLCBlKTtcbiAgICByZXR1cm4gZV9kZWZhdWx0UHJldmVudGVkKGUpIHx8IGUuY29kZW1pcnJvcklnbm9yZVxuICB9XG5cbiAgZnVuY3Rpb24gc2lnbmFsQ3Vyc29yQWN0aXZpdHkoY20pIHtcbiAgICB2YXIgYXJyID0gY20uX2hhbmRsZXJzICYmIGNtLl9oYW5kbGVycy5jdXJzb3JBY3Rpdml0eTtcbiAgICBpZiAoIWFycikgeyByZXR1cm4gfVxuICAgIHZhciBzZXQgPSBjbS5jdXJPcC5jdXJzb3JBY3Rpdml0eUhhbmRsZXJzIHx8IChjbS5jdXJPcC5jdXJzb3JBY3Rpdml0eUhhbmRsZXJzID0gW10pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgKytpKSB7IGlmIChpbmRleE9mKHNldCwgYXJyW2ldKSA9PSAtMSlcbiAgICAgIHsgc2V0LnB1c2goYXJyW2ldKTsgfSB9XG4gIH1cblxuICBmdW5jdGlvbiBoYXNIYW5kbGVyKGVtaXR0ZXIsIHR5cGUpIHtcbiAgICByZXR1cm4gZ2V0SGFuZGxlcnMoZW1pdHRlciwgdHlwZSkubGVuZ3RoID4gMFxuICB9XG5cbiAgLy8gQWRkIG9uIGFuZCBvZmYgbWV0aG9kcyB0byBhIGNvbnN0cnVjdG9yJ3MgcHJvdG90eXBlLCB0byBtYWtlXG4gIC8vIHJlZ2lzdGVyaW5nIGV2ZW50cyBvbiBzdWNoIG9iamVjdHMgbW9yZSBjb252ZW5pZW50LlxuICBmdW5jdGlvbiBldmVudE1peGluKGN0b3IpIHtcbiAgICBjdG9yLnByb3RvdHlwZS5vbiA9IGZ1bmN0aW9uKHR5cGUsIGYpIHtvbih0aGlzLCB0eXBlLCBmKTt9O1xuICAgIGN0b3IucHJvdG90eXBlLm9mZiA9IGZ1bmN0aW9uKHR5cGUsIGYpIHtvZmYodGhpcywgdHlwZSwgZik7fTtcbiAgfVxuXG4gIC8vIER1ZSB0byB0aGUgZmFjdCB0aGF0IHdlIHN0aWxsIHN1cHBvcnQganVyYXNzaWMgSUUgdmVyc2lvbnMsIHNvbWVcbiAgLy8gY29tcGF0aWJpbGl0eSB3cmFwcGVycyBhcmUgbmVlZGVkLlxuXG4gIGZ1bmN0aW9uIGVfcHJldmVudERlZmF1bHQoZSkge1xuICAgIGlmIChlLnByZXZlbnREZWZhdWx0KSB7IGUucHJldmVudERlZmF1bHQoKTsgfVxuICAgIGVsc2UgeyBlLnJldHVyblZhbHVlID0gZmFsc2U7IH1cbiAgfVxuICBmdW5jdGlvbiBlX3N0b3BQcm9wYWdhdGlvbihlKSB7XG4gICAgaWYgKGUuc3RvcFByb3BhZ2F0aW9uKSB7IGUuc3RvcFByb3BhZ2F0aW9uKCk7IH1cbiAgICBlbHNlIHsgZS5jYW5jZWxCdWJibGUgPSB0cnVlOyB9XG4gIH1cbiAgZnVuY3Rpb24gZV9kZWZhdWx0UHJldmVudGVkKGUpIHtcbiAgICByZXR1cm4gZS5kZWZhdWx0UHJldmVudGVkICE9IG51bGwgPyBlLmRlZmF1bHRQcmV2ZW50ZWQgOiBlLnJldHVyblZhbHVlID09IGZhbHNlXG4gIH1cbiAgZnVuY3Rpb24gZV9zdG9wKGUpIHtlX3ByZXZlbnREZWZhdWx0KGUpOyBlX3N0b3BQcm9wYWdhdGlvbihlKTt9XG5cbiAgZnVuY3Rpb24gZV90YXJnZXQoZSkge3JldHVybiBlLnRhcmdldCB8fCBlLnNyY0VsZW1lbnR9XG4gIGZ1bmN0aW9uIGVfYnV0dG9uKGUpIHtcbiAgICB2YXIgYiA9IGUud2hpY2g7XG4gICAgaWYgKGIgPT0gbnVsbCkge1xuICAgICAgaWYgKGUuYnV0dG9uICYgMSkgeyBiID0gMTsgfVxuICAgICAgZWxzZSBpZiAoZS5idXR0b24gJiAyKSB7IGIgPSAzOyB9XG4gICAgICBlbHNlIGlmIChlLmJ1dHRvbiAmIDQpIHsgYiA9IDI7IH1cbiAgICB9XG4gICAgaWYgKG1hYyAmJiBlLmN0cmxLZXkgJiYgYiA9PSAxKSB7IGIgPSAzOyB9XG4gICAgcmV0dXJuIGJcbiAgfVxuXG4gIC8vIERldGVjdCBkcmFnLWFuZC1kcm9wXG4gIHZhciBkcmFnQW5kRHJvcCA9IGZ1bmN0aW9uKCkge1xuICAgIC8vIFRoZXJlIGlzICpzb21lKiBraW5kIG9mIGRyYWctYW5kLWRyb3Agc3VwcG9ydCBpbiBJRTYtOCwgYnV0IElcbiAgICAvLyBjb3VsZG4ndCBnZXQgaXQgdG8gd29yayB5ZXQuXG4gICAgaWYgKGllICYmIGllX3ZlcnNpb24gPCA5KSB7IHJldHVybiBmYWxzZSB9XG4gICAgdmFyIGRpdiA9IGVsdCgnZGl2Jyk7XG4gICAgcmV0dXJuIFwiZHJhZ2dhYmxlXCIgaW4gZGl2IHx8IFwiZHJhZ0Ryb3BcIiBpbiBkaXZcbiAgfSgpO1xuXG4gIHZhciB6d3NwU3VwcG9ydGVkO1xuICBmdW5jdGlvbiB6ZXJvV2lkdGhFbGVtZW50KG1lYXN1cmUpIHtcbiAgICBpZiAoendzcFN1cHBvcnRlZCA9PSBudWxsKSB7XG4gICAgICB2YXIgdGVzdCA9IGVsdChcInNwYW5cIiwgXCJcXHUyMDBiXCIpO1xuICAgICAgcmVtb3ZlQ2hpbGRyZW5BbmRBZGQobWVhc3VyZSwgZWx0KFwic3BhblwiLCBbdGVzdCwgZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoXCJ4XCIpXSkpO1xuICAgICAgaWYgKG1lYXN1cmUuZmlyc3RDaGlsZC5vZmZzZXRIZWlnaHQgIT0gMClcbiAgICAgICAgeyB6d3NwU3VwcG9ydGVkID0gdGVzdC5vZmZzZXRXaWR0aCA8PSAxICYmIHRlc3Qub2Zmc2V0SGVpZ2h0ID4gMiAmJiAhKGllICYmIGllX3ZlcnNpb24gPCA4KTsgfVxuICAgIH1cbiAgICB2YXIgbm9kZSA9IHp3c3BTdXBwb3J0ZWQgPyBlbHQoXCJzcGFuXCIsIFwiXFx1MjAwYlwiKSA6XG4gICAgICBlbHQoXCJzcGFuXCIsIFwiXFx1MDBhMFwiLCBudWxsLCBcImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2lkdGg6IDFweDsgbWFyZ2luLXJpZ2h0OiAtMXB4XCIpO1xuICAgIG5vZGUuc2V0QXR0cmlidXRlKFwiY20tdGV4dFwiLCBcIlwiKTtcbiAgICByZXR1cm4gbm9kZVxuICB9XG5cbiAgLy8gRmVhdHVyZS1kZXRlY3QgSUUncyBjcnVtbXkgY2xpZW50IHJlY3QgcmVwb3J0aW5nIGZvciBiaWRpIHRleHRcbiAgdmFyIGJhZEJpZGlSZWN0cztcbiAgZnVuY3Rpb24gaGFzQmFkQmlkaVJlY3RzKG1lYXN1cmUpIHtcbiAgICBpZiAoYmFkQmlkaVJlY3RzICE9IG51bGwpIHsgcmV0dXJuIGJhZEJpZGlSZWN0cyB9XG4gICAgdmFyIHR4dCA9IHJlbW92ZUNoaWxkcmVuQW5kQWRkKG1lYXN1cmUsIGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKFwiQVxcdTA2MmVBXCIpKTtcbiAgICB2YXIgcjAgPSByYW5nZSh0eHQsIDAsIDEpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHZhciByMSA9IHJhbmdlKHR4dCwgMSwgMikuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgcmVtb3ZlQ2hpbGRyZW4obWVhc3VyZSk7XG4gICAgaWYgKCFyMCB8fCByMC5sZWZ0ID09IHIwLnJpZ2h0KSB7IHJldHVybiBmYWxzZSB9IC8vIFNhZmFyaSByZXR1cm5zIG51bGwgaW4gc29tZSBjYXNlcyAoIzI3ODApXG4gICAgcmV0dXJuIGJhZEJpZGlSZWN0cyA9IChyMS5yaWdodCAtIHIwLnJpZ2h0IDwgMylcbiAgfVxuXG4gIC8vIFNlZSBpZiBcIlwiLnNwbGl0IGlzIHRoZSBicm9rZW4gSUUgdmVyc2lvbiwgaWYgc28sIHByb3ZpZGUgYW5cbiAgLy8gYWx0ZXJuYXRpdmUgd2F5IHRvIHNwbGl0IGxpbmVzLlxuICB2YXIgc3BsaXRMaW5lc0F1dG8gPSBcIlxcblxcbmJcIi5zcGxpdCgvXFxuLykubGVuZ3RoICE9IDMgPyBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgdmFyIHBvcyA9IDAsIHJlc3VsdCA9IFtdLCBsID0gc3RyaW5nLmxlbmd0aDtcbiAgICB3aGlsZSAocG9zIDw9IGwpIHtcbiAgICAgIHZhciBubCA9IHN0cmluZy5pbmRleE9mKFwiXFxuXCIsIHBvcyk7XG4gICAgICBpZiAobmwgPT0gLTEpIHsgbmwgPSBzdHJpbmcubGVuZ3RoOyB9XG4gICAgICB2YXIgbGluZSA9IHN0cmluZy5zbGljZShwb3MsIHN0cmluZy5jaGFyQXQobmwgLSAxKSA9PSBcIlxcclwiID8gbmwgLSAxIDogbmwpO1xuICAgICAgdmFyIHJ0ID0gbGluZS5pbmRleE9mKFwiXFxyXCIpO1xuICAgICAgaWYgKHJ0ICE9IC0xKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGxpbmUuc2xpY2UoMCwgcnQpKTtcbiAgICAgICAgcG9zICs9IHJ0ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGxpbmUpO1xuICAgICAgICBwb3MgPSBubCArIDE7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHRcbiAgfSA6IGZ1bmN0aW9uIChzdHJpbmcpIHsgcmV0dXJuIHN0cmluZy5zcGxpdCgvXFxyXFxuP3xcXG4vKTsgfTtcblxuICB2YXIgaGFzU2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbiA/IGZ1bmN0aW9uICh0ZSkge1xuICAgIHRyeSB7IHJldHVybiB0ZS5zZWxlY3Rpb25TdGFydCAhPSB0ZS5zZWxlY3Rpb25FbmQgfVxuICAgIGNhdGNoKGUpIHsgcmV0dXJuIGZhbHNlIH1cbiAgfSA6IGZ1bmN0aW9uICh0ZSkge1xuICAgIHZhciByYW5nZTtcbiAgICB0cnkge3JhbmdlID0gdGUub3duZXJEb2N1bWVudC5zZWxlY3Rpb24uY3JlYXRlUmFuZ2UoKTt9XG4gICAgY2F0Y2goZSkge31cbiAgICBpZiAoIXJhbmdlIHx8IHJhbmdlLnBhcmVudEVsZW1lbnQoKSAhPSB0ZSkgeyByZXR1cm4gZmFsc2UgfVxuICAgIHJldHVybiByYW5nZS5jb21wYXJlRW5kUG9pbnRzKFwiU3RhcnRUb0VuZFwiLCByYW5nZSkgIT0gMFxuICB9O1xuXG4gIHZhciBoYXNDb3B5RXZlbnQgPSAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBlID0gZWx0KFwiZGl2XCIpO1xuICAgIGlmIChcIm9uY29weVwiIGluIGUpIHsgcmV0dXJuIHRydWUgfVxuICAgIGUuc2V0QXR0cmlidXRlKFwib25jb3B5XCIsIFwicmV0dXJuO1wiKTtcbiAgICByZXR1cm4gdHlwZW9mIGUub25jb3B5ID09IFwiZnVuY3Rpb25cIlxuICB9KSgpO1xuXG4gIHZhciBiYWRab29tZWRSZWN0cyA9IG51bGw7XG4gIGZ1bmN0aW9uIGhhc0JhZFpvb21lZFJlY3RzKG1lYXN1cmUpIHtcbiAgICBpZiAoYmFkWm9vbWVkUmVjdHMgIT0gbnVsbCkgeyByZXR1cm4gYmFkWm9vbWVkUmVjdHMgfVxuICAgIHZhciBub2RlID0gcmVtb3ZlQ2hpbGRyZW5BbmRBZGQobWVhc3VyZSwgZWx0KFwic3BhblwiLCBcInhcIikpO1xuICAgIHZhciBub3JtYWwgPSBub2RlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHZhciBmcm9tUmFuZ2UgPSByYW5nZShub2RlLCAwLCAxKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICByZXR1cm4gYmFkWm9vbWVkUmVjdHMgPSBNYXRoLmFicyhub3JtYWwubGVmdCAtIGZyb21SYW5nZS5sZWZ0KSA+IDFcbiAgfVxuXG4gIC8vIEtub3duIG1vZGVzLCBieSBuYW1lIGFuZCBieSBNSU1FXG4gIHZhciBtb2RlcyA9IHt9LCBtaW1lTW9kZXMgPSB7fTtcblxuICAvLyBFeHRyYSBhcmd1bWVudHMgYXJlIHN0b3JlZCBhcyB0aGUgbW9kZSdzIGRlcGVuZGVuY2llcywgd2hpY2ggaXNcbiAgLy8gdXNlZCBieSAobGVnYWN5KSBtZWNoYW5pc21zIGxpa2UgbG9hZG1vZGUuanMgdG8gYXV0b21hdGljYWxseVxuICAvLyBsb2FkIGEgbW9kZS4gKFByZWZlcnJlZCBtZWNoYW5pc20gaXMgdGhlIHJlcXVpcmUvZGVmaW5lIGNhbGxzLilcbiAgZnVuY3Rpb24gZGVmaW5lTW9kZShuYW1lLCBtb2RlKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAyKVxuICAgICAgeyBtb2RlLmRlcGVuZGVuY2llcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMik7IH1cbiAgICBtb2Rlc1tuYW1lXSA9IG1vZGU7XG4gIH1cblxuICBmdW5jdGlvbiBkZWZpbmVNSU1FKG1pbWUsIHNwZWMpIHtcbiAgICBtaW1lTW9kZXNbbWltZV0gPSBzcGVjO1xuICB9XG5cbiAgLy8gR2l2ZW4gYSBNSU1FIHR5cGUsIGEge25hbWUsIC4uLm9wdGlvbnN9IGNvbmZpZyBvYmplY3QsIG9yIGEgbmFtZVxuICAvLyBzdHJpbmcsIHJldHVybiBhIG1vZGUgY29uZmlnIG9iamVjdC5cbiAgZnVuY3Rpb24gcmVzb2x2ZU1vZGUoc3BlYykge1xuICAgIGlmICh0eXBlb2Ygc3BlYyA9PSBcInN0cmluZ1wiICYmIG1pbWVNb2Rlcy5oYXNPd25Qcm9wZXJ0eShzcGVjKSkge1xuICAgICAgc3BlYyA9IG1pbWVNb2Rlc1tzcGVjXTtcbiAgICB9IGVsc2UgaWYgKHNwZWMgJiYgdHlwZW9mIHNwZWMubmFtZSA9PSBcInN0cmluZ1wiICYmIG1pbWVNb2Rlcy5oYXNPd25Qcm9wZXJ0eShzcGVjLm5hbWUpKSB7XG4gICAgICB2YXIgZm91bmQgPSBtaW1lTW9kZXNbc3BlYy5uYW1lXTtcbiAgICAgIGlmICh0eXBlb2YgZm91bmQgPT0gXCJzdHJpbmdcIikgeyBmb3VuZCA9IHtuYW1lOiBmb3VuZH07IH1cbiAgICAgIHNwZWMgPSBjcmVhdGVPYmooZm91bmQsIHNwZWMpO1xuICAgICAgc3BlYy5uYW1lID0gZm91bmQubmFtZTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBzcGVjID09IFwic3RyaW5nXCIgJiYgL15bXFx3XFwtXStcXC9bXFx3XFwtXStcXCt4bWwkLy50ZXN0KHNwZWMpKSB7XG4gICAgICByZXR1cm4gcmVzb2x2ZU1vZGUoXCJhcHBsaWNhdGlvbi94bWxcIilcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBzcGVjID09IFwic3RyaW5nXCIgJiYgL15bXFx3XFwtXStcXC9bXFx3XFwtXStcXCtqc29uJC8udGVzdChzcGVjKSkge1xuICAgICAgcmV0dXJuIHJlc29sdmVNb2RlKFwiYXBwbGljYXRpb24vanNvblwiKVxuICAgIH1cbiAgICBpZiAodHlwZW9mIHNwZWMgPT0gXCJzdHJpbmdcIikgeyByZXR1cm4ge25hbWU6IHNwZWN9IH1cbiAgICBlbHNlIHsgcmV0dXJuIHNwZWMgfHwge25hbWU6IFwibnVsbFwifSB9XG4gIH1cblxuICAvLyBHaXZlbiBhIG1vZGUgc3BlYyAoYW55dGhpbmcgdGhhdCByZXNvbHZlTW9kZSBhY2NlcHRzKSwgZmluZCBhbmRcbiAgLy8gaW5pdGlhbGl6ZSBhbiBhY3R1YWwgbW9kZSBvYmplY3QuXG4gIGZ1bmN0aW9uIGdldE1vZGUob3B0aW9ucywgc3BlYykge1xuICAgIHNwZWMgPSByZXNvbHZlTW9kZShzcGVjKTtcbiAgICB2YXIgbWZhY3RvcnkgPSBtb2Rlc1tzcGVjLm5hbWVdO1xuICAgIGlmICghbWZhY3RvcnkpIHsgcmV0dXJuIGdldE1vZGUob3B0aW9ucywgXCJ0ZXh0L3BsYWluXCIpIH1cbiAgICB2YXIgbW9kZU9iaiA9IG1mYWN0b3J5KG9wdGlvbnMsIHNwZWMpO1xuICAgIGlmIChtb2RlRXh0ZW5zaW9ucy5oYXNPd25Qcm9wZXJ0eShzcGVjLm5hbWUpKSB7XG4gICAgICB2YXIgZXh0cyA9IG1vZGVFeHRlbnNpb25zW3NwZWMubmFtZV07XG4gICAgICBmb3IgKHZhciBwcm9wIGluIGV4dHMpIHtcbiAgICAgICAgaWYgKCFleHRzLmhhc093blByb3BlcnR5KHByb3ApKSB7IGNvbnRpbnVlIH1cbiAgICAgICAgaWYgKG1vZGVPYmouaGFzT3duUHJvcGVydHkocHJvcCkpIHsgbW9kZU9ialtcIl9cIiArIHByb3BdID0gbW9kZU9ialtwcm9wXTsgfVxuICAgICAgICBtb2RlT2JqW3Byb3BdID0gZXh0c1twcm9wXTtcbiAgICAgIH1cbiAgICB9XG4gICAgbW9kZU9iai5uYW1lID0gc3BlYy5uYW1lO1xuICAgIGlmIChzcGVjLmhlbHBlclR5cGUpIHsgbW9kZU9iai5oZWxwZXJUeXBlID0gc3BlYy5oZWxwZXJUeXBlOyB9XG4gICAgaWYgKHNwZWMubW9kZVByb3BzKSB7IGZvciAodmFyIHByb3AkMSBpbiBzcGVjLm1vZGVQcm9wcylcbiAgICAgIHsgbW9kZU9ialtwcm9wJDFdID0gc3BlYy5tb2RlUHJvcHNbcHJvcCQxXTsgfSB9XG5cbiAgICByZXR1cm4gbW9kZU9ialxuICB9XG5cbiAgLy8gVGhpcyBjYW4gYmUgdXNlZCB0byBhdHRhY2ggcHJvcGVydGllcyB0byBtb2RlIG9iamVjdHMgZnJvbVxuICAvLyBvdXRzaWRlIHRoZSBhY3R1YWwgbW9kZSBkZWZpbml0aW9uLlxuICB2YXIgbW9kZUV4dGVuc2lvbnMgPSB7fTtcbiAgZnVuY3Rpb24gZXh0ZW5kTW9kZShtb2RlLCBwcm9wZXJ0aWVzKSB7XG4gICAgdmFyIGV4dHMgPSBtb2RlRXh0ZW5zaW9ucy5oYXNPd25Qcm9wZXJ0eShtb2RlKSA/IG1vZGVFeHRlbnNpb25zW21vZGVdIDogKG1vZGVFeHRlbnNpb25zW21vZGVdID0ge30pO1xuICAgIGNvcHlPYmoocHJvcGVydGllcywgZXh0cyk7XG4gIH1cblxuICBmdW5jdGlvbiBjb3B5U3RhdGUobW9kZSwgc3RhdGUpIHtcbiAgICBpZiAoc3RhdGUgPT09IHRydWUpIHsgcmV0dXJuIHN0YXRlIH1cbiAgICBpZiAobW9kZS5jb3B5U3RhdGUpIHsgcmV0dXJuIG1vZGUuY29weVN0YXRlKHN0YXRlKSB9XG4gICAgdmFyIG5zdGF0ZSA9IHt9O1xuICAgIGZvciAodmFyIG4gaW4gc3RhdGUpIHtcbiAgICAgIHZhciB2YWwgPSBzdGF0ZVtuXTtcbiAgICAgIGlmICh2YWwgaW5zdGFuY2VvZiBBcnJheSkgeyB2YWwgPSB2YWwuY29uY2F0KFtdKTsgfVxuICAgICAgbnN0YXRlW25dID0gdmFsO1xuICAgIH1cbiAgICByZXR1cm4gbnN0YXRlXG4gIH1cblxuICAvLyBHaXZlbiBhIG1vZGUgYW5kIGEgc3RhdGUgKGZvciB0aGF0IG1vZGUpLCBmaW5kIHRoZSBpbm5lciBtb2RlIGFuZFxuICAvLyBzdGF0ZSBhdCB0aGUgcG9zaXRpb24gdGhhdCB0aGUgc3RhdGUgcmVmZXJzIHRvLlxuICBmdW5jdGlvbiBpbm5lck1vZGUobW9kZSwgc3RhdGUpIHtcbiAgICB2YXIgaW5mbztcbiAgICB3aGlsZSAobW9kZS5pbm5lck1vZGUpIHtcbiAgICAgIGluZm8gPSBtb2RlLmlubmVyTW9kZShzdGF0ZSk7XG4gICAgICBpZiAoIWluZm8gfHwgaW5mby5tb2RlID09IG1vZGUpIHsgYnJlYWsgfVxuICAgICAgc3RhdGUgPSBpbmZvLnN0YXRlO1xuICAgICAgbW9kZSA9IGluZm8ubW9kZTtcbiAgICB9XG4gICAgcmV0dXJuIGluZm8gfHwge21vZGU6IG1vZGUsIHN0YXRlOiBzdGF0ZX1cbiAgfVxuXG4gIGZ1bmN0aW9uIHN0YXJ0U3RhdGUobW9kZSwgYTEsIGEyKSB7XG4gICAgcmV0dXJuIG1vZGUuc3RhcnRTdGF0ZSA/IG1vZGUuc3RhcnRTdGF0ZShhMSwgYTIpIDogdHJ1ZVxuICB9XG5cbiAgLy8gU1RSSU5HIFNUUkVBTVxuXG4gIC8vIEZlZCB0byB0aGUgbW9kZSBwYXJzZXJzLCBwcm92aWRlcyBoZWxwZXIgZnVuY3Rpb25zIHRvIG1ha2VcbiAgLy8gcGFyc2VycyBtb3JlIHN1Y2NpbmN0LlxuXG4gIHZhciBTdHJpbmdTdHJlYW0gPSBmdW5jdGlvbihzdHJpbmcsIHRhYlNpemUsIGxpbmVPcmFjbGUpIHtcbiAgICB0aGlzLnBvcyA9IHRoaXMuc3RhcnQgPSAwO1xuICAgIHRoaXMuc3RyaW5nID0gc3RyaW5nO1xuICAgIHRoaXMudGFiU2l6ZSA9IHRhYlNpemUgfHwgODtcbiAgICB0aGlzLmxhc3RDb2x1bW5Qb3MgPSB0aGlzLmxhc3RDb2x1bW5WYWx1ZSA9IDA7XG4gICAgdGhpcy5saW5lU3RhcnQgPSAwO1xuICAgIHRoaXMubGluZU9yYWNsZSA9IGxpbmVPcmFjbGU7XG4gIH07XG5cbiAgU3RyaW5nU3RyZWFtLnByb3RvdHlwZS5lb2wgPSBmdW5jdGlvbiAoKSB7cmV0dXJuIHRoaXMucG9zID49IHRoaXMuc3RyaW5nLmxlbmd0aH07XG4gIFN0cmluZ1N0cmVhbS5wcm90b3R5cGUuc29sID0gZnVuY3Rpb24gKCkge3JldHVybiB0aGlzLnBvcyA9PSB0aGlzLmxpbmVTdGFydH07XG4gIFN0cmluZ1N0cmVhbS5wcm90b3R5cGUucGVlayA9IGZ1bmN0aW9uICgpIHtyZXR1cm4gdGhpcy5zdHJpbmcuY2hhckF0KHRoaXMucG9zKSB8fCB1bmRlZmluZWR9O1xuICBTdHJpbmdTdHJlYW0ucHJvdG90eXBlLm5leHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMucG9zIDwgdGhpcy5zdHJpbmcubGVuZ3RoKVxuICAgICAgeyByZXR1cm4gdGhpcy5zdHJpbmcuY2hhckF0KHRoaXMucG9zKyspIH1cbiAgfTtcbiAgU3RyaW5nU3RyZWFtLnByb3RvdHlwZS5lYXQgPSBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICB2YXIgY2ggPSB0aGlzLnN0cmluZy5jaGFyQXQodGhpcy5wb3MpO1xuICAgIHZhciBvaztcbiAgICBpZiAodHlwZW9mIG1hdGNoID09IFwic3RyaW5nXCIpIHsgb2sgPSBjaCA9PSBtYXRjaDsgfVxuICAgIGVsc2UgeyBvayA9IGNoICYmIChtYXRjaC50ZXN0ID8gbWF0Y2gudGVzdChjaCkgOiBtYXRjaChjaCkpOyB9XG4gICAgaWYgKG9rKSB7Kyt0aGlzLnBvczsgcmV0dXJuIGNofVxuICB9O1xuICBTdHJpbmdTdHJlYW0ucHJvdG90eXBlLmVhdFdoaWxlID0gZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgdmFyIHN0YXJ0ID0gdGhpcy5wb3M7XG4gICAgd2hpbGUgKHRoaXMuZWF0KG1hdGNoKSl7fVxuICAgIHJldHVybiB0aGlzLnBvcyA+IHN0YXJ0XG4gIH07XG4gIFN0cmluZ1N0cmVhbS5wcm90b3R5cGUuZWF0U3BhY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHN0YXJ0ID0gdGhpcy5wb3M7XG4gICAgd2hpbGUgKC9bXFxzXFx1MDBhMF0vLnRlc3QodGhpcy5zdHJpbmcuY2hhckF0KHRoaXMucG9zKSkpIHsgKyt0aGlzLnBvczsgfVxuICAgIHJldHVybiB0aGlzLnBvcyA+IHN0YXJ0XG4gIH07XG4gIFN0cmluZ1N0cmVhbS5wcm90b3R5cGUuc2tpcFRvRW5kID0gZnVuY3Rpb24gKCkge3RoaXMucG9zID0gdGhpcy5zdHJpbmcubGVuZ3RoO307XG4gIFN0cmluZ1N0cmVhbS5wcm90b3R5cGUuc2tpcFRvID0gZnVuY3Rpb24gKGNoKSB7XG4gICAgdmFyIGZvdW5kID0gdGhpcy5zdHJpbmcuaW5kZXhPZihjaCwgdGhpcy5wb3MpO1xuICAgIGlmIChmb3VuZCA+IC0xKSB7dGhpcy5wb3MgPSBmb3VuZDsgcmV0dXJuIHRydWV9XG4gIH07XG4gIFN0cmluZ1N0cmVhbS5wcm90b3R5cGUuYmFja1VwID0gZnVuY3Rpb24gKG4pIHt0aGlzLnBvcyAtPSBuO307XG4gIFN0cmluZ1N0cmVhbS5wcm90b3R5cGUuY29sdW1uID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLmxhc3RDb2x1bW5Qb3MgPCB0aGlzLnN0YXJ0KSB7XG4gICAgICB0aGlzLmxhc3RDb2x1bW5WYWx1ZSA9IGNvdW50Q29sdW1uKHRoaXMuc3RyaW5nLCB0aGlzLnN0YXJ0LCB0aGlzLnRhYlNpemUsIHRoaXMubGFzdENvbHVtblBvcywgdGhpcy5sYXN0Q29sdW1uVmFsdWUpO1xuICAgICAgdGhpcy5sYXN0Q29sdW1uUG9zID0gdGhpcy5zdGFydDtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMubGFzdENvbHVtblZhbHVlIC0gKHRoaXMubGluZVN0YXJ0ID8gY291bnRDb2x1bW4odGhpcy5zdHJpbmcsIHRoaXMubGluZVN0YXJ0LCB0aGlzLnRhYlNpemUpIDogMClcbiAgfTtcbiAgU3RyaW5nU3RyZWFtLnByb3RvdHlwZS5pbmRlbnRhdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gY291bnRDb2x1bW4odGhpcy5zdHJpbmcsIG51bGwsIHRoaXMudGFiU2l6ZSkgLVxuICAgICAgKHRoaXMubGluZVN0YXJ0ID8gY291bnRDb2x1bW4odGhpcy5zdHJpbmcsIHRoaXMubGluZVN0YXJ0LCB0aGlzLnRhYlNpemUpIDogMClcbiAgfTtcbiAgU3RyaW5nU3RyZWFtLnByb3RvdHlwZS5tYXRjaCA9IGZ1bmN0aW9uIChwYXR0ZXJuLCBjb25zdW1lLCBjYXNlSW5zZW5zaXRpdmUpIHtcbiAgICBpZiAodHlwZW9mIHBhdHRlcm4gPT0gXCJzdHJpbmdcIikge1xuICAgICAgdmFyIGNhc2VkID0gZnVuY3Rpb24gKHN0cikgeyByZXR1cm4gY2FzZUluc2Vuc2l0aXZlID8gc3RyLnRvTG93ZXJDYXNlKCkgOiBzdHI7IH07XG4gICAgICB2YXIgc3Vic3RyID0gdGhpcy5zdHJpbmcuc3Vic3RyKHRoaXMucG9zLCBwYXR0ZXJuLmxlbmd0aCk7XG4gICAgICBpZiAoY2FzZWQoc3Vic3RyKSA9PSBjYXNlZChwYXR0ZXJuKSkge1xuICAgICAgICBpZiAoY29uc3VtZSAhPT0gZmFsc2UpIHsgdGhpcy5wb3MgKz0gcGF0dGVybi5sZW5ndGg7IH1cbiAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIG1hdGNoID0gdGhpcy5zdHJpbmcuc2xpY2UodGhpcy5wb3MpLm1hdGNoKHBhdHRlcm4pO1xuICAgICAgaWYgKG1hdGNoICYmIG1hdGNoLmluZGV4ID4gMCkgeyByZXR1cm4gbnVsbCB9XG4gICAgICBpZiAobWF0Y2ggJiYgY29uc3VtZSAhPT0gZmFsc2UpIHsgdGhpcy5wb3MgKz0gbWF0Y2hbMF0ubGVuZ3RoOyB9XG4gICAgICByZXR1cm4gbWF0Y2hcbiAgICB9XG4gIH07XG4gIFN0cmluZ1N0cmVhbS5wcm90b3R5cGUuY3VycmVudCA9IGZ1bmN0aW9uICgpe3JldHVybiB0aGlzLnN0cmluZy5zbGljZSh0aGlzLnN0YXJ0LCB0aGlzLnBvcyl9O1xuICBTdHJpbmdTdHJlYW0ucHJvdG90eXBlLmhpZGVGaXJzdENoYXJzID0gZnVuY3Rpb24gKG4sIGlubmVyKSB7XG4gICAgdGhpcy5saW5lU3RhcnQgKz0gbjtcbiAgICB0cnkgeyByZXR1cm4gaW5uZXIoKSB9XG4gICAgZmluYWxseSB7IHRoaXMubGluZVN0YXJ0IC09IG47IH1cbiAgfTtcbiAgU3RyaW5nU3RyZWFtLnByb3RvdHlwZS5sb29rQWhlYWQgPSBmdW5jdGlvbiAobikge1xuICAgIHZhciBvcmFjbGUgPSB0aGlzLmxpbmVPcmFjbGU7XG4gICAgcmV0dXJuIG9yYWNsZSAmJiBvcmFjbGUubG9va0FoZWFkKG4pXG4gIH07XG4gIFN0cmluZ1N0cmVhbS5wcm90b3R5cGUuYmFzZVRva2VuID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBvcmFjbGUgPSB0aGlzLmxpbmVPcmFjbGU7XG4gICAgcmV0dXJuIG9yYWNsZSAmJiBvcmFjbGUuYmFzZVRva2VuKHRoaXMucG9zKVxuICB9O1xuXG4gIC8vIEZpbmQgdGhlIGxpbmUgb2JqZWN0IGNvcnJlc3BvbmRpbmcgdG8gdGhlIGdpdmVuIGxpbmUgbnVtYmVyLlxuICBmdW5jdGlvbiBnZXRMaW5lKGRvYywgbikge1xuICAgIG4gLT0gZG9jLmZpcnN0O1xuICAgIGlmIChuIDwgMCB8fCBuID49IGRvYy5zaXplKSB7IHRocm93IG5ldyBFcnJvcihcIlRoZXJlIGlzIG5vIGxpbmUgXCIgKyAobiArIGRvYy5maXJzdCkgKyBcIiBpbiB0aGUgZG9jdW1lbnQuXCIpIH1cbiAgICB2YXIgY2h1bmsgPSBkb2M7XG4gICAgd2hpbGUgKCFjaHVuay5saW5lcykge1xuICAgICAgZm9yICh2YXIgaSA9IDA7OyArK2kpIHtcbiAgICAgICAgdmFyIGNoaWxkID0gY2h1bmsuY2hpbGRyZW5baV0sIHN6ID0gY2hpbGQuY2h1bmtTaXplKCk7XG4gICAgICAgIGlmIChuIDwgc3opIHsgY2h1bmsgPSBjaGlsZDsgYnJlYWsgfVxuICAgICAgICBuIC09IHN6O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY2h1bmsubGluZXNbbl1cbiAgfVxuXG4gIC8vIEdldCB0aGUgcGFydCBvZiBhIGRvY3VtZW50IGJldHdlZW4gdHdvIHBvc2l0aW9ucywgYXMgYW4gYXJyYXkgb2ZcbiAgLy8gc3RyaW5ncy5cbiAgZnVuY3Rpb24gZ2V0QmV0d2Vlbihkb2MsIHN0YXJ0LCBlbmQpIHtcbiAgICB2YXIgb3V0ID0gW10sIG4gPSBzdGFydC5saW5lO1xuICAgIGRvYy5pdGVyKHN0YXJ0LmxpbmUsIGVuZC5saW5lICsgMSwgZnVuY3Rpb24gKGxpbmUpIHtcbiAgICAgIHZhciB0ZXh0ID0gbGluZS50ZXh0O1xuICAgICAgaWYgKG4gPT0gZW5kLmxpbmUpIHsgdGV4dCA9IHRleHQuc2xpY2UoMCwgZW5kLmNoKTsgfVxuICAgICAgaWYgKG4gPT0gc3RhcnQubGluZSkgeyB0ZXh0ID0gdGV4dC5zbGljZShzdGFydC5jaCk7IH1cbiAgICAgIG91dC5wdXNoKHRleHQpO1xuICAgICAgKytuO1xuICAgIH0pO1xuICAgIHJldHVybiBvdXRcbiAgfVxuICAvLyBHZXQgdGhlIGxpbmVzIGJldHdlZW4gZnJvbSBhbmQgdG8sIGFzIGFycmF5IG9mIHN0cmluZ3MuXG4gIGZ1bmN0aW9uIGdldExpbmVzKGRvYywgZnJvbSwgdG8pIHtcbiAgICB2YXIgb3V0ID0gW107XG4gICAgZG9jLml0ZXIoZnJvbSwgdG8sIGZ1bmN0aW9uIChsaW5lKSB7IG91dC5wdXNoKGxpbmUudGV4dCk7IH0pOyAvLyBpdGVyIGFib3J0cyB3aGVuIGNhbGxiYWNrIHJldHVybnMgdHJ1dGh5IHZhbHVlXG4gICAgcmV0dXJuIG91dFxuICB9XG5cbiAgLy8gVXBkYXRlIHRoZSBoZWlnaHQgb2YgYSBsaW5lLCBwcm9wYWdhdGluZyB0aGUgaGVpZ2h0IGNoYW5nZVxuICAvLyB1cHdhcmRzIHRvIHBhcmVudCBub2Rlcy5cbiAgZnVuY3Rpb24gdXBkYXRlTGluZUhlaWdodChsaW5lLCBoZWlnaHQpIHtcbiAgICB2YXIgZGlmZiA9IGhlaWdodCAtIGxpbmUuaGVpZ2h0O1xuICAgIGlmIChkaWZmKSB7IGZvciAodmFyIG4gPSBsaW5lOyBuOyBuID0gbi5wYXJlbnQpIHsgbi5oZWlnaHQgKz0gZGlmZjsgfSB9XG4gIH1cblxuICAvLyBHaXZlbiBhIGxpbmUgb2JqZWN0LCBmaW5kIGl0cyBsaW5lIG51bWJlciBieSB3YWxraW5nIHVwIHRocm91Z2hcbiAgLy8gaXRzIHBhcmVudCBsaW5rcy5cbiAgZnVuY3Rpb24gbGluZU5vKGxpbmUpIHtcbiAgICBpZiAobGluZS5wYXJlbnQgPT0gbnVsbCkgeyByZXR1cm4gbnVsbCB9XG4gICAgdmFyIGN1ciA9IGxpbmUucGFyZW50LCBubyA9IGluZGV4T2YoY3VyLmxpbmVzLCBsaW5lKTtcbiAgICBmb3IgKHZhciBjaHVuayA9IGN1ci5wYXJlbnQ7IGNodW5rOyBjdXIgPSBjaHVuaywgY2h1bmsgPSBjaHVuay5wYXJlbnQpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOzsgKytpKSB7XG4gICAgICAgIGlmIChjaHVuay5jaGlsZHJlbltpXSA9PSBjdXIpIHsgYnJlYWsgfVxuICAgICAgICBubyArPSBjaHVuay5jaGlsZHJlbltpXS5jaHVua1NpemUoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG5vICsgY3VyLmZpcnN0XG4gIH1cblxuICAvLyBGaW5kIHRoZSBsaW5lIGF0IHRoZSBnaXZlbiB2ZXJ0aWNhbCBwb3NpdGlvbiwgdXNpbmcgdGhlIGhlaWdodFxuICAvLyBpbmZvcm1hdGlvbiBpbiB0aGUgZG9jdW1lbnQgdHJlZS5cbiAgZnVuY3Rpb24gbGluZUF0SGVpZ2h0KGNodW5rLCBoKSB7XG4gICAgdmFyIG4gPSBjaHVuay5maXJzdDtcbiAgICBvdXRlcjogZG8ge1xuICAgICAgZm9yICh2YXIgaSQxID0gMDsgaSQxIDwgY2h1bmsuY2hpbGRyZW4ubGVuZ3RoOyArK2kkMSkge1xuICAgICAgICB2YXIgY2hpbGQgPSBjaHVuay5jaGlsZHJlbltpJDFdLCBjaCA9IGNoaWxkLmhlaWdodDtcbiAgICAgICAgaWYgKGggPCBjaCkgeyBjaHVuayA9IGNoaWxkOyBjb250aW51ZSBvdXRlciB9XG4gICAgICAgIGggLT0gY2g7XG4gICAgICAgIG4gKz0gY2hpbGQuY2h1bmtTaXplKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gblxuICAgIH0gd2hpbGUgKCFjaHVuay5saW5lcylcbiAgICB2YXIgaSA9IDA7XG4gICAgZm9yICg7IGkgPCBjaHVuay5saW5lcy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGxpbmUgPSBjaHVuay5saW5lc1tpXSwgbGggPSBsaW5lLmhlaWdodDtcbiAgICAgIGlmIChoIDwgbGgpIHsgYnJlYWsgfVxuICAgICAgaCAtPSBsaDtcbiAgICB9XG4gICAgcmV0dXJuIG4gKyBpXG4gIH1cblxuICBmdW5jdGlvbiBpc0xpbmUoZG9jLCBsKSB7cmV0dXJuIGwgPj0gZG9jLmZpcnN0ICYmIGwgPCBkb2MuZmlyc3QgKyBkb2Muc2l6ZX1cblxuICBmdW5jdGlvbiBsaW5lTnVtYmVyRm9yKG9wdGlvbnMsIGkpIHtcbiAgICByZXR1cm4gU3RyaW5nKG9wdGlvbnMubGluZU51bWJlckZvcm1hdHRlcihpICsgb3B0aW9ucy5maXJzdExpbmVOdW1iZXIpKVxuICB9XG5cbiAgLy8gQSBQb3MgaW5zdGFuY2UgcmVwcmVzZW50cyBhIHBvc2l0aW9uIHdpdGhpbiB0aGUgdGV4dC5cbiAgZnVuY3Rpb24gUG9zKGxpbmUsIGNoLCBzdGlja3kpIHtcbiAgICBpZiAoIHN0aWNreSA9PT0gdm9pZCAwICkgc3RpY2t5ID0gbnVsbDtcblxuICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBQb3MpKSB7IHJldHVybiBuZXcgUG9zKGxpbmUsIGNoLCBzdGlja3kpIH1cbiAgICB0aGlzLmxpbmUgPSBsaW5lO1xuICAgIHRoaXMuY2ggPSBjaDtcbiAgICB0aGlzLnN0aWNreSA9IHN0aWNreTtcbiAgfVxuXG4gIC8vIENvbXBhcmUgdHdvIHBvc2l0aW9ucywgcmV0dXJuIDAgaWYgdGhleSBhcmUgdGhlIHNhbWUsIGEgbmVnYXRpdmVcbiAgLy8gbnVtYmVyIHdoZW4gYSBpcyBsZXNzLCBhbmQgYSBwb3NpdGl2ZSBudW1iZXIgb3RoZXJ3aXNlLlxuICBmdW5jdGlvbiBjbXAoYSwgYikgeyByZXR1cm4gYS5saW5lIC0gYi5saW5lIHx8IGEuY2ggLSBiLmNoIH1cblxuICBmdW5jdGlvbiBlcXVhbEN1cnNvclBvcyhhLCBiKSB7IHJldHVybiBhLnN0aWNreSA9PSBiLnN0aWNreSAmJiBjbXAoYSwgYikgPT0gMCB9XG5cbiAgZnVuY3Rpb24gY29weVBvcyh4KSB7cmV0dXJuIFBvcyh4LmxpbmUsIHguY2gpfVxuICBmdW5jdGlvbiBtYXhQb3MoYSwgYikgeyByZXR1cm4gY21wKGEsIGIpIDwgMCA/IGIgOiBhIH1cbiAgZnVuY3Rpb24gbWluUG9zKGEsIGIpIHsgcmV0dXJuIGNtcChhLCBiKSA8IDAgPyBhIDogYiB9XG5cbiAgLy8gTW9zdCBvZiB0aGUgZXh0ZXJuYWwgQVBJIGNsaXBzIGdpdmVuIHBvc2l0aW9ucyB0byBtYWtlIHN1cmUgdGhleVxuICAvLyBhY3R1YWxseSBleGlzdCB3aXRoaW4gdGhlIGRvY3VtZW50LlxuICBmdW5jdGlvbiBjbGlwTGluZShkb2MsIG4pIHtyZXR1cm4gTWF0aC5tYXgoZG9jLmZpcnN0LCBNYXRoLm1pbihuLCBkb2MuZmlyc3QgKyBkb2Muc2l6ZSAtIDEpKX1cbiAgZnVuY3Rpb24gY2xpcFBvcyhkb2MsIHBvcykge1xuICAgIGlmIChwb3MubGluZSA8IGRvYy5maXJzdCkgeyByZXR1cm4gUG9zKGRvYy5maXJzdCwgMCkgfVxuICAgIHZhciBsYXN0ID0gZG9jLmZpcnN0ICsgZG9jLnNpemUgLSAxO1xuICAgIGlmIChwb3MubGluZSA+IGxhc3QpIHsgcmV0dXJuIFBvcyhsYXN0LCBnZXRMaW5lKGRvYywgbGFzdCkudGV4dC5sZW5ndGgpIH1cbiAgICByZXR1cm4gY2xpcFRvTGVuKHBvcywgZ2V0TGluZShkb2MsIHBvcy5saW5lKS50ZXh0Lmxlbmd0aClcbiAgfVxuICBmdW5jdGlvbiBjbGlwVG9MZW4ocG9zLCBsaW5lbGVuKSB7XG4gICAgdmFyIGNoID0gcG9zLmNoO1xuICAgIGlmIChjaCA9PSBudWxsIHx8IGNoID4gbGluZWxlbikgeyByZXR1cm4gUG9zKHBvcy5saW5lLCBsaW5lbGVuKSB9XG4gICAgZWxzZSBpZiAoY2ggPCAwKSB7IHJldHVybiBQb3MocG9zLmxpbmUsIDApIH1cbiAgICBlbHNlIHsgcmV0dXJuIHBvcyB9XG4gIH1cbiAgZnVuY3Rpb24gY2xpcFBvc0FycmF5KGRvYywgYXJyYXkpIHtcbiAgICB2YXIgb3V0ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykgeyBvdXRbaV0gPSBjbGlwUG9zKGRvYywgYXJyYXlbaV0pOyB9XG4gICAgcmV0dXJuIG91dFxuICB9XG5cbiAgdmFyIFNhdmVkQ29udGV4dCA9IGZ1bmN0aW9uKHN0YXRlLCBsb29rQWhlYWQpIHtcbiAgICB0aGlzLnN0YXRlID0gc3RhdGU7XG4gICAgdGhpcy5sb29rQWhlYWQgPSBsb29rQWhlYWQ7XG4gIH07XG5cbiAgdmFyIENvbnRleHQgPSBmdW5jdGlvbihkb2MsIHN0YXRlLCBsaW5lLCBsb29rQWhlYWQpIHtcbiAgICB0aGlzLnN0YXRlID0gc3RhdGU7XG4gICAgdGhpcy5kb2MgPSBkb2M7XG4gICAgdGhpcy5saW5lID0gbGluZTtcbiAgICB0aGlzLm1heExvb2tBaGVhZCA9IGxvb2tBaGVhZCB8fCAwO1xuICAgIHRoaXMuYmFzZVRva2VucyA9IG51bGw7XG4gICAgdGhpcy5iYXNlVG9rZW5Qb3MgPSAxO1xuICB9O1xuXG4gIENvbnRleHQucHJvdG90eXBlLmxvb2tBaGVhZCA9IGZ1bmN0aW9uIChuKSB7XG4gICAgdmFyIGxpbmUgPSB0aGlzLmRvYy5nZXRMaW5lKHRoaXMubGluZSArIG4pO1xuICAgIGlmIChsaW5lICE9IG51bGwgJiYgbiA+IHRoaXMubWF4TG9va0FoZWFkKSB7IHRoaXMubWF4TG9va0FoZWFkID0gbjsgfVxuICAgIHJldHVybiBsaW5lXG4gIH07XG5cbiAgQ29udGV4dC5wcm90b3R5cGUuYmFzZVRva2VuID0gZnVuY3Rpb24gKG4pIHtcbiAgICBpZiAoIXRoaXMuYmFzZVRva2VucykgeyByZXR1cm4gbnVsbCB9XG4gICAgd2hpbGUgKHRoaXMuYmFzZVRva2Vuc1t0aGlzLmJhc2VUb2tlblBvc10gPD0gbilcbiAgICAgIHsgdGhpcy5iYXNlVG9rZW5Qb3MgKz0gMjsgfVxuICAgIHZhciB0eXBlID0gdGhpcy5iYXNlVG9rZW5zW3RoaXMuYmFzZVRva2VuUG9zICsgMV07XG4gICAgcmV0dXJuIHt0eXBlOiB0eXBlICYmIHR5cGUucmVwbGFjZSgvKCB8XilvdmVybGF5IC4qLywgXCJcIiksXG4gICAgICAgICAgICBzaXplOiB0aGlzLmJhc2VUb2tlbnNbdGhpcy5iYXNlVG9rZW5Qb3NdIC0gbn1cbiAgfTtcblxuICBDb250ZXh0LnByb3RvdHlwZS5uZXh0TGluZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmxpbmUrKztcbiAgICBpZiAodGhpcy5tYXhMb29rQWhlYWQgPiAwKSB7IHRoaXMubWF4TG9va0FoZWFkLS07IH1cbiAgfTtcblxuICBDb250ZXh0LmZyb21TYXZlZCA9IGZ1bmN0aW9uIChkb2MsIHNhdmVkLCBsaW5lKSB7XG4gICAgaWYgKHNhdmVkIGluc3RhbmNlb2YgU2F2ZWRDb250ZXh0KVxuICAgICAgeyByZXR1cm4gbmV3IENvbnRleHQoZG9jLCBjb3B5U3RhdGUoZG9jLm1vZGUsIHNhdmVkLnN0YXRlKSwgbGluZSwgc2F2ZWQubG9va0FoZWFkKSB9XG4gICAgZWxzZVxuICAgICAgeyByZXR1cm4gbmV3IENvbnRleHQoZG9jLCBjb3B5U3RhdGUoZG9jLm1vZGUsIHNhdmVkKSwgbGluZSkgfVxuICB9O1xuXG4gIENvbnRleHQucHJvdG90eXBlLnNhdmUgPSBmdW5jdGlvbiAoY29weSkge1xuICAgIHZhciBzdGF0ZSA9IGNvcHkgIT09IGZhbHNlID8gY29weVN0YXRlKHRoaXMuZG9jLm1vZGUsIHRoaXMuc3RhdGUpIDogdGhpcy5zdGF0ZTtcbiAgICByZXR1cm4gdGhpcy5tYXhMb29rQWhlYWQgPiAwID8gbmV3IFNhdmVkQ29udGV4dChzdGF0ZSwgdGhpcy5tYXhMb29rQWhlYWQpIDogc3RhdGVcbiAgfTtcblxuXG4gIC8vIENvbXB1dGUgYSBzdHlsZSBhcnJheSAoYW4gYXJyYXkgc3RhcnRpbmcgd2l0aCBhIG1vZGUgZ2VuZXJhdGlvblxuICAvLyAtLSBmb3IgaW52YWxpZGF0aW9uIC0tIGZvbGxvd2VkIGJ5IHBhaXJzIG9mIGVuZCBwb3NpdGlvbnMgYW5kXG4gIC8vIHN0eWxlIHN0cmluZ3MpLCB3aGljaCBpcyB1c2VkIHRvIGhpZ2hsaWdodCB0aGUgdG9rZW5zIG9uIHRoZVxuICAvLyBsaW5lLlxuICBmdW5jdGlvbiBoaWdobGlnaHRMaW5lKGNtLCBsaW5lLCBjb250ZXh0LCBmb3JjZVRvRW5kKSB7XG4gICAgLy8gQSBzdHlsZXMgYXJyYXkgYWx3YXlzIHN0YXJ0cyB3aXRoIGEgbnVtYmVyIGlkZW50aWZ5aW5nIHRoZVxuICAgIC8vIG1vZGUvb3ZlcmxheXMgdGhhdCBpdCBpcyBiYXNlZCBvbiAoZm9yIGVhc3kgaW52YWxpZGF0aW9uKS5cbiAgICB2YXIgc3QgPSBbY20uc3RhdGUubW9kZUdlbl0sIGxpbmVDbGFzc2VzID0ge307XG4gICAgLy8gQ29tcHV0ZSB0aGUgYmFzZSBhcnJheSBvZiBzdHlsZXNcbiAgICBydW5Nb2RlKGNtLCBsaW5lLnRleHQsIGNtLmRvYy5tb2RlLCBjb250ZXh0LCBmdW5jdGlvbiAoZW5kLCBzdHlsZSkgeyByZXR1cm4gc3QucHVzaChlbmQsIHN0eWxlKTsgfSxcbiAgICAgICAgICAgIGxpbmVDbGFzc2VzLCBmb3JjZVRvRW5kKTtcbiAgICB2YXIgc3RhdGUgPSBjb250ZXh0LnN0YXRlO1xuXG4gICAgLy8gUnVuIG92ZXJsYXlzLCBhZGp1c3Qgc3R5bGUgYXJyYXkuXG4gICAgdmFyIGxvb3AgPSBmdW5jdGlvbiAoIG8gKSB7XG4gICAgICBjb250ZXh0LmJhc2VUb2tlbnMgPSBzdDtcbiAgICAgIHZhciBvdmVybGF5ID0gY20uc3RhdGUub3ZlcmxheXNbb10sIGkgPSAxLCBhdCA9IDA7XG4gICAgICBjb250ZXh0LnN0YXRlID0gdHJ1ZTtcbiAgICAgIHJ1bk1vZGUoY20sIGxpbmUudGV4dCwgb3ZlcmxheS5tb2RlLCBjb250ZXh0LCBmdW5jdGlvbiAoZW5kLCBzdHlsZSkge1xuICAgICAgICB2YXIgc3RhcnQgPSBpO1xuICAgICAgICAvLyBFbnN1cmUgdGhlcmUncyBhIHRva2VuIGVuZCBhdCB0aGUgY3VycmVudCBwb3NpdGlvbiwgYW5kIHRoYXQgaSBwb2ludHMgYXQgaXRcbiAgICAgICAgd2hpbGUgKGF0IDwgZW5kKSB7XG4gICAgICAgICAgdmFyIGlfZW5kID0gc3RbaV07XG4gICAgICAgICAgaWYgKGlfZW5kID4gZW5kKVxuICAgICAgICAgICAgeyBzdC5zcGxpY2UoaSwgMSwgZW5kLCBzdFtpKzFdLCBpX2VuZCk7IH1cbiAgICAgICAgICBpICs9IDI7XG4gICAgICAgICAgYXQgPSBNYXRoLm1pbihlbmQsIGlfZW5kKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXN0eWxlKSB7IHJldHVybiB9XG4gICAgICAgIGlmIChvdmVybGF5Lm9wYXF1ZSkge1xuICAgICAgICAgIHN0LnNwbGljZShzdGFydCwgaSAtIHN0YXJ0LCBlbmQsIFwib3ZlcmxheSBcIiArIHN0eWxlKTtcbiAgICAgICAgICBpID0gc3RhcnQgKyAyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZvciAoOyBzdGFydCA8IGk7IHN0YXJ0ICs9IDIpIHtcbiAgICAgICAgICAgIHZhciBjdXIgPSBzdFtzdGFydCsxXTtcbiAgICAgICAgICAgIHN0W3N0YXJ0KzFdID0gKGN1ciA/IGN1ciArIFwiIFwiIDogXCJcIikgKyBcIm92ZXJsYXkgXCIgKyBzdHlsZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sIGxpbmVDbGFzc2VzKTtcbiAgICAgIGNvbnRleHQuc3RhdGUgPSBzdGF0ZTtcbiAgICAgIGNvbnRleHQuYmFzZVRva2VucyA9IG51bGw7XG4gICAgICBjb250ZXh0LmJhc2VUb2tlblBvcyA9IDE7XG4gICAgfTtcblxuICAgIGZvciAodmFyIG8gPSAwOyBvIDwgY20uc3RhdGUub3ZlcmxheXMubGVuZ3RoOyArK28pIGxvb3AoIG8gKTtcblxuICAgIHJldHVybiB7c3R5bGVzOiBzdCwgY2xhc3NlczogbGluZUNsYXNzZXMuYmdDbGFzcyB8fCBsaW5lQ2xhc3Nlcy50ZXh0Q2xhc3MgPyBsaW5lQ2xhc3NlcyA6IG51bGx9XG4gIH1cblxuICBmdW5jdGlvbiBnZXRMaW5lU3R5bGVzKGNtLCBsaW5lLCB1cGRhdGVGcm9udGllcikge1xuICAgIGlmICghbGluZS5zdHlsZXMgfHwgbGluZS5zdHlsZXNbMF0gIT0gY20uc3RhdGUubW9kZUdlbikge1xuICAgICAgdmFyIGNvbnRleHQgPSBnZXRDb250ZXh0QmVmb3JlKGNtLCBsaW5lTm8obGluZSkpO1xuICAgICAgdmFyIHJlc2V0U3RhdGUgPSBsaW5lLnRleHQubGVuZ3RoID4gY20ub3B0aW9ucy5tYXhIaWdobGlnaHRMZW5ndGggJiYgY29weVN0YXRlKGNtLmRvYy5tb2RlLCBjb250ZXh0LnN0YXRlKTtcbiAgICAgIHZhciByZXN1bHQgPSBoaWdobGlnaHRMaW5lKGNtLCBsaW5lLCBjb250ZXh0KTtcbiAgICAgIGlmIChyZXNldFN0YXRlKSB7IGNvbnRleHQuc3RhdGUgPSByZXNldFN0YXRlOyB9XG4gICAgICBsaW5lLnN0YXRlQWZ0ZXIgPSBjb250ZXh0LnNhdmUoIXJlc2V0U3RhdGUpO1xuICAgICAgbGluZS5zdHlsZXMgPSByZXN1bHQuc3R5bGVzO1xuICAgICAgaWYgKHJlc3VsdC5jbGFzc2VzKSB7IGxpbmUuc3R5bGVDbGFzc2VzID0gcmVzdWx0LmNsYXNzZXM7IH1cbiAgICAgIGVsc2UgaWYgKGxpbmUuc3R5bGVDbGFzc2VzKSB7IGxpbmUuc3R5bGVDbGFzc2VzID0gbnVsbDsgfVxuICAgICAgaWYgKHVwZGF0ZUZyb250aWVyID09PSBjbS5kb2MuaGlnaGxpZ2h0RnJvbnRpZXIpXG4gICAgICAgIHsgY20uZG9jLm1vZGVGcm9udGllciA9IE1hdGgubWF4KGNtLmRvYy5tb2RlRnJvbnRpZXIsICsrY20uZG9jLmhpZ2hsaWdodEZyb250aWVyKTsgfVxuICAgIH1cbiAgICByZXR1cm4gbGluZS5zdHlsZXNcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldENvbnRleHRCZWZvcmUoY20sIG4sIHByZWNpc2UpIHtcbiAgICB2YXIgZG9jID0gY20uZG9jLCBkaXNwbGF5ID0gY20uZGlzcGxheTtcbiAgICBpZiAoIWRvYy5tb2RlLnN0YXJ0U3RhdGUpIHsgcmV0dXJuIG5ldyBDb250ZXh0KGRvYywgdHJ1ZSwgbikgfVxuICAgIHZhciBzdGFydCA9IGZpbmRTdGFydExpbmUoY20sIG4sIHByZWNpc2UpO1xuICAgIHZhciBzYXZlZCA9IHN0YXJ0ID4gZG9jLmZpcnN0ICYmIGdldExpbmUoZG9jLCBzdGFydCAtIDEpLnN0YXRlQWZ0ZXI7XG4gICAgdmFyIGNvbnRleHQgPSBzYXZlZCA/IENvbnRleHQuZnJvbVNhdmVkKGRvYywgc2F2ZWQsIHN0YXJ0KSA6IG5ldyBDb250ZXh0KGRvYywgc3RhcnRTdGF0ZShkb2MubW9kZSksIHN0YXJ0KTtcblxuICAgIGRvYy5pdGVyKHN0YXJ0LCBuLCBmdW5jdGlvbiAobGluZSkge1xuICAgICAgcHJvY2Vzc0xpbmUoY20sIGxpbmUudGV4dCwgY29udGV4dCk7XG4gICAgICB2YXIgcG9zID0gY29udGV4dC5saW5lO1xuICAgICAgbGluZS5zdGF0ZUFmdGVyID0gcG9zID09IG4gLSAxIHx8IHBvcyAlIDUgPT0gMCB8fCBwb3MgPj0gZGlzcGxheS52aWV3RnJvbSAmJiBwb3MgPCBkaXNwbGF5LnZpZXdUbyA/IGNvbnRleHQuc2F2ZSgpIDogbnVsbDtcbiAgICAgIGNvbnRleHQubmV4dExpbmUoKTtcbiAgICB9KTtcbiAgICBpZiAocHJlY2lzZSkgeyBkb2MubW9kZUZyb250aWVyID0gY29udGV4dC5saW5lOyB9XG4gICAgcmV0dXJuIGNvbnRleHRcbiAgfVxuXG4gIC8vIExpZ2h0d2VpZ2h0IGZvcm0gb2YgaGlnaGxpZ2h0IC0tIHByb2NlZWQgb3ZlciB0aGlzIGxpbmUgYW5kXG4gIC8vIHVwZGF0ZSBzdGF0ZSwgYnV0IGRvbid0IHNhdmUgYSBzdHlsZSBhcnJheS4gVXNlZCBmb3IgbGluZXMgdGhhdFxuICAvLyBhcmVuJ3QgY3VycmVudGx5IHZpc2libGUuXG4gIGZ1bmN0aW9uIHByb2Nlc3NMaW5lKGNtLCB0ZXh0LCBjb250ZXh0LCBzdGFydEF0KSB7XG4gICAgdmFyIG1vZGUgPSBjbS5kb2MubW9kZTtcbiAgICB2YXIgc3RyZWFtID0gbmV3IFN0cmluZ1N0cmVhbSh0ZXh0LCBjbS5vcHRpb25zLnRhYlNpemUsIGNvbnRleHQpO1xuICAgIHN0cmVhbS5zdGFydCA9IHN0cmVhbS5wb3MgPSBzdGFydEF0IHx8IDA7XG4gICAgaWYgKHRleHQgPT0gXCJcIikgeyBjYWxsQmxhbmtMaW5lKG1vZGUsIGNvbnRleHQuc3RhdGUpOyB9XG4gICAgd2hpbGUgKCFzdHJlYW0uZW9sKCkpIHtcbiAgICAgIHJlYWRUb2tlbihtb2RlLCBzdHJlYW0sIGNvbnRleHQuc3RhdGUpO1xuICAgICAgc3RyZWFtLnN0YXJ0ID0gc3RyZWFtLnBvcztcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBjYWxsQmxhbmtMaW5lKG1vZGUsIHN0YXRlKSB7XG4gICAgaWYgKG1vZGUuYmxhbmtMaW5lKSB7IHJldHVybiBtb2RlLmJsYW5rTGluZShzdGF0ZSkgfVxuICAgIGlmICghbW9kZS5pbm5lck1vZGUpIHsgcmV0dXJuIH1cbiAgICB2YXIgaW5uZXIgPSBpbm5lck1vZGUobW9kZSwgc3RhdGUpO1xuICAgIGlmIChpbm5lci5tb2RlLmJsYW5rTGluZSkgeyByZXR1cm4gaW5uZXIubW9kZS5ibGFua0xpbmUoaW5uZXIuc3RhdGUpIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHJlYWRUb2tlbihtb2RlLCBzdHJlYW0sIHN0YXRlLCBpbm5lcikge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMTA7IGkrKykge1xuICAgICAgaWYgKGlubmVyKSB7IGlubmVyWzBdID0gaW5uZXJNb2RlKG1vZGUsIHN0YXRlKS5tb2RlOyB9XG4gICAgICB2YXIgc3R5bGUgPSBtb2RlLnRva2VuKHN0cmVhbSwgc3RhdGUpO1xuICAgICAgaWYgKHN0cmVhbS5wb3MgPiBzdHJlYW0uc3RhcnQpIHsgcmV0dXJuIHN0eWxlIH1cbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiTW9kZSBcIiArIG1vZGUubmFtZSArIFwiIGZhaWxlZCB0byBhZHZhbmNlIHN0cmVhbS5cIilcbiAgfVxuXG4gIHZhciBUb2tlbiA9IGZ1bmN0aW9uKHN0cmVhbSwgdHlwZSwgc3RhdGUpIHtcbiAgICB0aGlzLnN0YXJ0ID0gc3RyZWFtLnN0YXJ0OyB0aGlzLmVuZCA9IHN0cmVhbS5wb3M7XG4gICAgdGhpcy5zdHJpbmcgPSBzdHJlYW0uY3VycmVudCgpO1xuICAgIHRoaXMudHlwZSA9IHR5cGUgfHwgbnVsbDtcbiAgICB0aGlzLnN0YXRlID0gc3RhdGU7XG4gIH07XG5cbiAgLy8gVXRpbGl0eSBmb3IgZ2V0VG9rZW5BdCBhbmQgZ2V0TGluZVRva2Vuc1xuICBmdW5jdGlvbiB0YWtlVG9rZW4oY20sIHBvcywgcHJlY2lzZSwgYXNBcnJheSkge1xuICAgIHZhciBkb2MgPSBjbS5kb2MsIG1vZGUgPSBkb2MubW9kZSwgc3R5bGU7XG4gICAgcG9zID0gY2xpcFBvcyhkb2MsIHBvcyk7XG4gICAgdmFyIGxpbmUgPSBnZXRMaW5lKGRvYywgcG9zLmxpbmUpLCBjb250ZXh0ID0gZ2V0Q29udGV4dEJlZm9yZShjbSwgcG9zLmxpbmUsIHByZWNpc2UpO1xuICAgIHZhciBzdHJlYW0gPSBuZXcgU3RyaW5nU3RyZWFtKGxpbmUudGV4dCwgY20ub3B0aW9ucy50YWJTaXplLCBjb250ZXh0KSwgdG9rZW5zO1xuICAgIGlmIChhc0FycmF5KSB7IHRva2VucyA9IFtdOyB9XG4gICAgd2hpbGUgKChhc0FycmF5IHx8IHN0cmVhbS5wb3MgPCBwb3MuY2gpICYmICFzdHJlYW0uZW9sKCkpIHtcbiAgICAgIHN0cmVhbS5zdGFydCA9IHN0cmVhbS5wb3M7XG4gICAgICBzdHlsZSA9IHJlYWRUb2tlbihtb2RlLCBzdHJlYW0sIGNvbnRleHQuc3RhdGUpO1xuICAgICAgaWYgKGFzQXJyYXkpIHsgdG9rZW5zLnB1c2gobmV3IFRva2VuKHN0cmVhbSwgc3R5bGUsIGNvcHlTdGF0ZShkb2MubW9kZSwgY29udGV4dC5zdGF0ZSkpKTsgfVxuICAgIH1cbiAgICByZXR1cm4gYXNBcnJheSA/IHRva2VucyA6IG5ldyBUb2tlbihzdHJlYW0sIHN0eWxlLCBjb250ZXh0LnN0YXRlKVxuICB9XG5cbiAgZnVuY3Rpb24gZXh0cmFjdExpbmVDbGFzc2VzKHR5cGUsIG91dHB1dCkge1xuICAgIGlmICh0eXBlKSB7IGZvciAoOzspIHtcbiAgICAgIHZhciBsaW5lQ2xhc3MgPSB0eXBlLm1hdGNoKC8oPzpefFxccyspbGluZS0oYmFja2dyb3VuZC0pPyhcXFMrKS8pO1xuICAgICAgaWYgKCFsaW5lQ2xhc3MpIHsgYnJlYWsgfVxuICAgICAgdHlwZSA9IHR5cGUuc2xpY2UoMCwgbGluZUNsYXNzLmluZGV4KSArIHR5cGUuc2xpY2UobGluZUNsYXNzLmluZGV4ICsgbGluZUNsYXNzWzBdLmxlbmd0aCk7XG4gICAgICB2YXIgcHJvcCA9IGxpbmVDbGFzc1sxXSA/IFwiYmdDbGFzc1wiIDogXCJ0ZXh0Q2xhc3NcIjtcbiAgICAgIGlmIChvdXRwdXRbcHJvcF0gPT0gbnVsbClcbiAgICAgICAgeyBvdXRwdXRbcHJvcF0gPSBsaW5lQ2xhc3NbMl07IH1cbiAgICAgIGVsc2UgaWYgKCEobmV3IFJlZ0V4cChcIig/Ol58XFxcXHMpXCIgKyBsaW5lQ2xhc3NbMl0gKyBcIig/OiR8XFxcXHMpXCIpKS50ZXN0KG91dHB1dFtwcm9wXSkpXG4gICAgICAgIHsgb3V0cHV0W3Byb3BdICs9IFwiIFwiICsgbGluZUNsYXNzWzJdOyB9XG4gICAgfSB9XG4gICAgcmV0dXJuIHR5cGVcbiAgfVxuXG4gIC8vIFJ1biB0aGUgZ2l2ZW4gbW9kZSdzIHBhcnNlciBvdmVyIGEgbGluZSwgY2FsbGluZyBmIGZvciBlYWNoIHRva2VuLlxuICBmdW5jdGlvbiBydW5Nb2RlKGNtLCB0ZXh0LCBtb2RlLCBjb250ZXh0LCBmLCBsaW5lQ2xhc3NlcywgZm9yY2VUb0VuZCkge1xuICAgIHZhciBmbGF0dGVuU3BhbnMgPSBtb2RlLmZsYXR0ZW5TcGFucztcbiAgICBpZiAoZmxhdHRlblNwYW5zID09IG51bGwpIHsgZmxhdHRlblNwYW5zID0gY20ub3B0aW9ucy5mbGF0dGVuU3BhbnM7IH1cbiAgICB2YXIgY3VyU3RhcnQgPSAwLCBjdXJTdHlsZSA9IG51bGw7XG4gICAgdmFyIHN0cmVhbSA9IG5ldyBTdHJpbmdTdHJlYW0odGV4dCwgY20ub3B0aW9ucy50YWJTaXplLCBjb250ZXh0KSwgc3R5bGU7XG4gICAgdmFyIGlubmVyID0gY20ub3B0aW9ucy5hZGRNb2RlQ2xhc3MgJiYgW251bGxdO1xuICAgIGlmICh0ZXh0ID09IFwiXCIpIHsgZXh0cmFjdExpbmVDbGFzc2VzKGNhbGxCbGFua0xpbmUobW9kZSwgY29udGV4dC5zdGF0ZSksIGxpbmVDbGFzc2VzKTsgfVxuICAgIHdoaWxlICghc3RyZWFtLmVvbCgpKSB7XG4gICAgICBpZiAoc3RyZWFtLnBvcyA+IGNtLm9wdGlvbnMubWF4SGlnaGxpZ2h0TGVuZ3RoKSB7XG4gICAgICAgIGZsYXR0ZW5TcGFucyA9IGZhbHNlO1xuICAgICAgICBpZiAoZm9yY2VUb0VuZCkgeyBwcm9jZXNzTGluZShjbSwgdGV4dCwgY29udGV4dCwgc3RyZWFtLnBvcyk7IH1cbiAgICAgICAgc3RyZWFtLnBvcyA9IHRleHQubGVuZ3RoO1xuICAgICAgICBzdHlsZSA9IG51bGw7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdHlsZSA9IGV4dHJhY3RMaW5lQ2xhc3NlcyhyZWFkVG9rZW4obW9kZSwgc3RyZWFtLCBjb250ZXh0LnN0YXRlLCBpbm5lciksIGxpbmVDbGFzc2VzKTtcbiAgICAgIH1cbiAgICAgIGlmIChpbm5lcikge1xuICAgICAgICB2YXIgbU5hbWUgPSBpbm5lclswXS5uYW1lO1xuICAgICAgICBpZiAobU5hbWUpIHsgc3R5bGUgPSBcIm0tXCIgKyAoc3R5bGUgPyBtTmFtZSArIFwiIFwiICsgc3R5bGUgOiBtTmFtZSk7IH1cbiAgICAgIH1cbiAgICAgIGlmICghZmxhdHRlblNwYW5zIHx8IGN1clN0eWxlICE9IHN0eWxlKSB7XG4gICAgICAgIHdoaWxlIChjdXJTdGFydCA8IHN0cmVhbS5zdGFydCkge1xuICAgICAgICAgIGN1clN0YXJ0ID0gTWF0aC5taW4oc3RyZWFtLnN0YXJ0LCBjdXJTdGFydCArIDUwMDApO1xuICAgICAgICAgIGYoY3VyU3RhcnQsIGN1clN0eWxlKTtcbiAgICAgICAgfVxuICAgICAgICBjdXJTdHlsZSA9IHN0eWxlO1xuICAgICAgfVxuICAgICAgc3RyZWFtLnN0YXJ0ID0gc3RyZWFtLnBvcztcbiAgICB9XG4gICAgd2hpbGUgKGN1clN0YXJ0IDwgc3RyZWFtLnBvcykge1xuICAgICAgLy8gV2Via2l0IHNlZW1zIHRvIHJlZnVzZSB0byByZW5kZXIgdGV4dCBub2RlcyBsb25nZXIgdGhhbiA1NzQ0NFxuICAgICAgLy8gY2hhcmFjdGVycywgYW5kIHJldHVybnMgaW5hY2N1cmF0ZSBtZWFzdXJlbWVudHMgaW4gbm9kZXNcbiAgICAgIC8vIHN0YXJ0aW5nIGFyb3VuZCA1MDAwIGNoYXJzLlxuICAgICAgdmFyIHBvcyA9IE1hdGgubWluKHN0cmVhbS5wb3MsIGN1clN0YXJ0ICsgNTAwMCk7XG4gICAgICBmKHBvcywgY3VyU3R5bGUpO1xuICAgICAgY3VyU3RhcnQgPSBwb3M7XG4gICAgfVxuICB9XG5cbiAgLy8gRmluZHMgdGhlIGxpbmUgdG8gc3RhcnQgd2l0aCB3aGVuIHN0YXJ0aW5nIGEgcGFyc2UuIFRyaWVzIHRvXG4gIC8vIGZpbmQgYSBsaW5lIHdpdGggYSBzdGF0ZUFmdGVyLCBzbyB0aGF0IGl0IGNhbiBzdGFydCB3aXRoIGFcbiAgLy8gdmFsaWQgc3RhdGUuIElmIHRoYXQgZmFpbHMsIGl0IHJldHVybnMgdGhlIGxpbmUgd2l0aCB0aGVcbiAgLy8gc21hbGxlc3QgaW5kZW50YXRpb24sIHdoaWNoIHRlbmRzIHRvIG5lZWQgdGhlIGxlYXN0IGNvbnRleHQgdG9cbiAgLy8gcGFyc2UgY29ycmVjdGx5LlxuICBmdW5jdGlvbiBmaW5kU3RhcnRMaW5lKGNtLCBuLCBwcmVjaXNlKSB7XG4gICAgdmFyIG1pbmluZGVudCwgbWlubGluZSwgZG9jID0gY20uZG9jO1xuICAgIHZhciBsaW0gPSBwcmVjaXNlID8gLTEgOiBuIC0gKGNtLmRvYy5tb2RlLmlubmVyTW9kZSA/IDEwMDAgOiAxMDApO1xuICAgIGZvciAodmFyIHNlYXJjaCA9IG47IHNlYXJjaCA+IGxpbTsgLS1zZWFyY2gpIHtcbiAgICAgIGlmIChzZWFyY2ggPD0gZG9jLmZpcnN0KSB7IHJldHVybiBkb2MuZmlyc3QgfVxuICAgICAgdmFyIGxpbmUgPSBnZXRMaW5lKGRvYywgc2VhcmNoIC0gMSksIGFmdGVyID0gbGluZS5zdGF0ZUFmdGVyO1xuICAgICAgaWYgKGFmdGVyICYmICghcHJlY2lzZSB8fCBzZWFyY2ggKyAoYWZ0ZXIgaW5zdGFuY2VvZiBTYXZlZENvbnRleHQgPyBhZnRlci5sb29rQWhlYWQgOiAwKSA8PSBkb2MubW9kZUZyb250aWVyKSlcbiAgICAgICAgeyByZXR1cm4gc2VhcmNoIH1cbiAgICAgIHZhciBpbmRlbnRlZCA9IGNvdW50Q29sdW1uKGxpbmUudGV4dCwgbnVsbCwgY20ub3B0aW9ucy50YWJTaXplKTtcbiAgICAgIGlmIChtaW5saW5lID09IG51bGwgfHwgbWluaW5kZW50ID4gaW5kZW50ZWQpIHtcbiAgICAgICAgbWlubGluZSA9IHNlYXJjaCAtIDE7XG4gICAgICAgIG1pbmluZGVudCA9IGluZGVudGVkO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbWlubGluZVxuICB9XG5cbiAgZnVuY3Rpb24gcmV0cmVhdEZyb250aWVyKGRvYywgbikge1xuICAgIGRvYy5tb2RlRnJvbnRpZXIgPSBNYXRoLm1pbihkb2MubW9kZUZyb250aWVyLCBuKTtcbiAgICBpZiAoZG9jLmhpZ2hsaWdodEZyb250aWVyIDwgbiAtIDEwKSB7IHJldHVybiB9XG4gICAgdmFyIHN0YXJ0ID0gZG9jLmZpcnN0O1xuICAgIGZvciAodmFyIGxpbmUgPSBuIC0gMTsgbGluZSA+IHN0YXJ0OyBsaW5lLS0pIHtcbiAgICAgIHZhciBzYXZlZCA9IGdldExpbmUoZG9jLCBsaW5lKS5zdGF0ZUFmdGVyO1xuICAgICAgLy8gY2hhbmdlIGlzIG9uIDNcbiAgICAgIC8vIHN0YXRlIG9uIGxpbmUgMSBsb29rZWQgYWhlYWQgMiAtLSBzbyBzYXcgM1xuICAgICAgLy8gdGVzdCAxICsgMiA8IDMgc2hvdWxkIGNvdmVyIHRoaXNcbiAgICAgIGlmIChzYXZlZCAmJiAoIShzYXZlZCBpbnN0YW5jZW9mIFNhdmVkQ29udGV4dCkgfHwgbGluZSArIHNhdmVkLmxvb2tBaGVhZCA8IG4pKSB7XG4gICAgICAgIHN0YXJ0ID0gbGluZSArIDE7XG4gICAgICAgIGJyZWFrXG4gICAgICB9XG4gICAgfVxuICAgIGRvYy5oaWdobGlnaHRGcm9udGllciA9IE1hdGgubWluKGRvYy5oaWdobGlnaHRGcm9udGllciwgc3RhcnQpO1xuICB9XG5cbiAgLy8gT3B0aW1pemUgc29tZSBjb2RlIHdoZW4gdGhlc2UgZmVhdHVyZXMgYXJlIG5vdCB1c2VkLlxuICB2YXIgc2F3UmVhZE9ubHlTcGFucyA9IGZhbHNlLCBzYXdDb2xsYXBzZWRTcGFucyA9IGZhbHNlO1xuXG4gIGZ1bmN0aW9uIHNlZVJlYWRPbmx5U3BhbnMoKSB7XG4gICAgc2F3UmVhZE9ubHlTcGFucyA9IHRydWU7XG4gIH1cblxuICBmdW5jdGlvbiBzZWVDb2xsYXBzZWRTcGFucygpIHtcbiAgICBzYXdDb2xsYXBzZWRTcGFucyA9IHRydWU7XG4gIH1cblxuICAvLyBURVhUTUFSS0VSIFNQQU5TXG5cbiAgZnVuY3Rpb24gTWFya2VkU3BhbihtYXJrZXIsIGZyb20sIHRvKSB7XG4gICAgdGhpcy5tYXJrZXIgPSBtYXJrZXI7XG4gICAgdGhpcy5mcm9tID0gZnJvbTsgdGhpcy50byA9IHRvO1xuICB9XG5cbiAgLy8gU2VhcmNoIGFuIGFycmF5IG9mIHNwYW5zIGZvciBhIHNwYW4gbWF0Y2hpbmcgdGhlIGdpdmVuIG1hcmtlci5cbiAgZnVuY3Rpb24gZ2V0TWFya2VkU3BhbkZvcihzcGFucywgbWFya2VyKSB7XG4gICAgaWYgKHNwYW5zKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgc3BhbnMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBzcGFuID0gc3BhbnNbaV07XG4gICAgICBpZiAoc3Bhbi5tYXJrZXIgPT0gbWFya2VyKSB7IHJldHVybiBzcGFuIH1cbiAgICB9IH1cbiAgfVxuXG4gIC8vIFJlbW92ZSBhIHNwYW4gZnJvbSBhbiBhcnJheSwgcmV0dXJuaW5nIHVuZGVmaW5lZCBpZiBubyBzcGFucyBhcmVcbiAgLy8gbGVmdCAod2UgZG9uJ3Qgc3RvcmUgYXJyYXlzIGZvciBsaW5lcyB3aXRob3V0IHNwYW5zKS5cbiAgZnVuY3Rpb24gcmVtb3ZlTWFya2VkU3BhbihzcGFucywgc3Bhbikge1xuICAgIHZhciByO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3BhbnMubGVuZ3RoOyArK2kpXG4gICAgICB7IGlmIChzcGFuc1tpXSAhPSBzcGFuKSB7IChyIHx8IChyID0gW10pKS5wdXNoKHNwYW5zW2ldKTsgfSB9XG4gICAgcmV0dXJuIHJcbiAgfVxuXG4gIC8vIEFkZCBhIHNwYW4gdG8gYSBsaW5lLlxuICBmdW5jdGlvbiBhZGRNYXJrZWRTcGFuKGxpbmUsIHNwYW4sIG9wKSB7XG4gICAgdmFyIGluVGhpc09wID0gb3AgJiYgd2luZG93LldlYWtTZXQgJiYgKG9wLm1hcmtlZFNwYW5zIHx8IChvcC5tYXJrZWRTcGFucyA9IG5ldyBXZWFrU2V0KSk7XG4gICAgaWYgKGluVGhpc09wICYmIGxpbmUubWFya2VkU3BhbnMgJiYgaW5UaGlzT3AuaGFzKGxpbmUubWFya2VkU3BhbnMpKSB7XG4gICAgICBsaW5lLm1hcmtlZFNwYW5zLnB1c2goc3Bhbik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxpbmUubWFya2VkU3BhbnMgPSBsaW5lLm1hcmtlZFNwYW5zID8gbGluZS5tYXJrZWRTcGFucy5jb25jYXQoW3NwYW5dKSA6IFtzcGFuXTtcbiAgICAgIGlmIChpblRoaXNPcCkgeyBpblRoaXNPcC5hZGQobGluZS5tYXJrZWRTcGFucyk7IH1cbiAgICB9XG4gICAgc3Bhbi5tYXJrZXIuYXR0YWNoTGluZShsaW5lKTtcbiAgfVxuXG4gIC8vIFVzZWQgZm9yIHRoZSBhbGdvcml0aG0gdGhhdCBhZGp1c3RzIG1hcmtlcnMgZm9yIGEgY2hhbmdlIGluIHRoZVxuICAvLyBkb2N1bWVudC4gVGhlc2UgZnVuY3Rpb25zIGN1dCBhbiBhcnJheSBvZiBzcGFucyBhdCBhIGdpdmVuXG4gIC8vIGNoYXJhY3RlciBwb3NpdGlvbiwgcmV0dXJuaW5nIGFuIGFycmF5IG9mIHJlbWFpbmluZyBjaHVua3MgKG9yXG4gIC8vIHVuZGVmaW5lZCBpZiBub3RoaW5nIHJlbWFpbnMpLlxuICBmdW5jdGlvbiBtYXJrZWRTcGFuc0JlZm9yZShvbGQsIHN0YXJ0Q2gsIGlzSW5zZXJ0KSB7XG4gICAgdmFyIG53O1xuICAgIGlmIChvbGQpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBvbGQubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBzcGFuID0gb2xkW2ldLCBtYXJrZXIgPSBzcGFuLm1hcmtlcjtcbiAgICAgIHZhciBzdGFydHNCZWZvcmUgPSBzcGFuLmZyb20gPT0gbnVsbCB8fCAobWFya2VyLmluY2x1c2l2ZUxlZnQgPyBzcGFuLmZyb20gPD0gc3RhcnRDaCA6IHNwYW4uZnJvbSA8IHN0YXJ0Q2gpO1xuICAgICAgaWYgKHN0YXJ0c0JlZm9yZSB8fCBzcGFuLmZyb20gPT0gc3RhcnRDaCAmJiBtYXJrZXIudHlwZSA9PSBcImJvb2ttYXJrXCIgJiYgKCFpc0luc2VydCB8fCAhc3Bhbi5tYXJrZXIuaW5zZXJ0TGVmdCkpIHtcbiAgICAgICAgdmFyIGVuZHNBZnRlciA9IHNwYW4udG8gPT0gbnVsbCB8fCAobWFya2VyLmluY2x1c2l2ZVJpZ2h0ID8gc3Bhbi50byA+PSBzdGFydENoIDogc3Bhbi50byA+IHN0YXJ0Q2gpXG4gICAgICAgIDsobncgfHwgKG53ID0gW10pKS5wdXNoKG5ldyBNYXJrZWRTcGFuKG1hcmtlciwgc3Bhbi5mcm9tLCBlbmRzQWZ0ZXIgPyBudWxsIDogc3Bhbi50bykpO1xuICAgICAgfVxuICAgIH0gfVxuICAgIHJldHVybiBud1xuICB9XG4gIGZ1bmN0aW9uIG1hcmtlZFNwYW5zQWZ0ZXIob2xkLCBlbmRDaCwgaXNJbnNlcnQpIHtcbiAgICB2YXIgbnc7XG4gICAgaWYgKG9sZCkgeyBmb3IgKHZhciBpID0gMDsgaSA8IG9sZC5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIHNwYW4gPSBvbGRbaV0sIG1hcmtlciA9IHNwYW4ubWFya2VyO1xuICAgICAgdmFyIGVuZHNBZnRlciA9IHNwYW4udG8gPT0gbnVsbCB8fCAobWFya2VyLmluY2x1c2l2ZVJpZ2h0ID8gc3Bhbi50byA+PSBlbmRDaCA6IHNwYW4udG8gPiBlbmRDaCk7XG4gICAgICBpZiAoZW5kc0FmdGVyIHx8IHNwYW4uZnJvbSA9PSBlbmRDaCAmJiBtYXJrZXIudHlwZSA9PSBcImJvb2ttYXJrXCIgJiYgKCFpc0luc2VydCB8fCBzcGFuLm1hcmtlci5pbnNlcnRMZWZ0KSkge1xuICAgICAgICB2YXIgc3RhcnRzQmVmb3JlID0gc3Bhbi5mcm9tID09IG51bGwgfHwgKG1hcmtlci5pbmNsdXNpdmVMZWZ0ID8gc3Bhbi5mcm9tIDw9IGVuZENoIDogc3Bhbi5mcm9tIDwgZW5kQ2gpXG4gICAgICAgIDsobncgfHwgKG53ID0gW10pKS5wdXNoKG5ldyBNYXJrZWRTcGFuKG1hcmtlciwgc3RhcnRzQmVmb3JlID8gbnVsbCA6IHNwYW4uZnJvbSAtIGVuZENoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwYW4udG8gPT0gbnVsbCA/IG51bGwgOiBzcGFuLnRvIC0gZW5kQ2gpKTtcbiAgICAgIH1cbiAgICB9IH1cbiAgICByZXR1cm4gbndcbiAgfVxuXG4gIC8vIEdpdmVuIGEgY2hhbmdlIG9iamVjdCwgY29tcHV0ZSB0aGUgbmV3IHNldCBvZiBtYXJrZXIgc3BhbnMgdGhhdFxuICAvLyBjb3ZlciB0aGUgbGluZSBpbiB3aGljaCB0aGUgY2hhbmdlIHRvb2sgcGxhY2UuIFJlbW92ZXMgc3BhbnNcbiAgLy8gZW50aXJlbHkgd2l0aGluIHRoZSBjaGFuZ2UsIHJlY29ubmVjdHMgc3BhbnMgYmVsb25naW5nIHRvIHRoZVxuICAvLyBzYW1lIG1hcmtlciB0aGF0IGFwcGVhciBvbiBib3RoIHNpZGVzIG9mIHRoZSBjaGFuZ2UsIGFuZCBjdXRzIG9mZlxuICAvLyBzcGFucyBwYXJ0aWFsbHkgd2l0aGluIHRoZSBjaGFuZ2UuIFJldHVybnMgYW4gYXJyYXkgb2Ygc3BhblxuICAvLyBhcnJheXMgd2l0aCBvbmUgZWxlbWVudCBmb3IgZWFjaCBsaW5lIGluIChhZnRlcikgdGhlIGNoYW5nZS5cbiAgZnVuY3Rpb24gc3RyZXRjaFNwYW5zT3ZlckNoYW5nZShkb2MsIGNoYW5nZSkge1xuICAgIGlmIChjaGFuZ2UuZnVsbCkgeyByZXR1cm4gbnVsbCB9XG4gICAgdmFyIG9sZEZpcnN0ID0gaXNMaW5lKGRvYywgY2hhbmdlLmZyb20ubGluZSkgJiYgZ2V0TGluZShkb2MsIGNoYW5nZS5mcm9tLmxpbmUpLm1hcmtlZFNwYW5zO1xuICAgIHZhciBvbGRMYXN0ID0gaXNMaW5lKGRvYywgY2hhbmdlLnRvLmxpbmUpICYmIGdldExpbmUoZG9jLCBjaGFuZ2UudG8ubGluZSkubWFya2VkU3BhbnM7XG4gICAgaWYgKCFvbGRGaXJzdCAmJiAhb2xkTGFzdCkgeyByZXR1cm4gbnVsbCB9XG5cbiAgICB2YXIgc3RhcnRDaCA9IGNoYW5nZS5mcm9tLmNoLCBlbmRDaCA9IGNoYW5nZS50by5jaCwgaXNJbnNlcnQgPSBjbXAoY2hhbmdlLmZyb20sIGNoYW5nZS50bykgPT0gMDtcbiAgICAvLyBHZXQgdGhlIHNwYW5zIHRoYXQgJ3N0aWNrIG91dCcgb24gYm90aCBzaWRlc1xuICAgIHZhciBmaXJzdCA9IG1hcmtlZFNwYW5zQmVmb3JlKG9sZEZpcnN0LCBzdGFydENoLCBpc0luc2VydCk7XG4gICAgdmFyIGxhc3QgPSBtYXJrZWRTcGFuc0FmdGVyKG9sZExhc3QsIGVuZENoLCBpc0luc2VydCk7XG5cbiAgICAvLyBOZXh0LCBtZXJnZSB0aG9zZSB0d28gZW5kc1xuICAgIHZhciBzYW1lTGluZSA9IGNoYW5nZS50ZXh0Lmxlbmd0aCA9PSAxLCBvZmZzZXQgPSBsc3QoY2hhbmdlLnRleHQpLmxlbmd0aCArIChzYW1lTGluZSA/IHN0YXJ0Q2ggOiAwKTtcbiAgICBpZiAoZmlyc3QpIHtcbiAgICAgIC8vIEZpeCB1cCAudG8gcHJvcGVydGllcyBvZiBmaXJzdFxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmaXJzdC5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgc3BhbiA9IGZpcnN0W2ldO1xuICAgICAgICBpZiAoc3Bhbi50byA9PSBudWxsKSB7XG4gICAgICAgICAgdmFyIGZvdW5kID0gZ2V0TWFya2VkU3BhbkZvcihsYXN0LCBzcGFuLm1hcmtlcik7XG4gICAgICAgICAgaWYgKCFmb3VuZCkgeyBzcGFuLnRvID0gc3RhcnRDaDsgfVxuICAgICAgICAgIGVsc2UgaWYgKHNhbWVMaW5lKSB7IHNwYW4udG8gPSBmb3VuZC50byA9PSBudWxsID8gbnVsbCA6IGZvdW5kLnRvICsgb2Zmc2V0OyB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGxhc3QpIHtcbiAgICAgIC8vIEZpeCB1cCAuZnJvbSBpbiBsYXN0IChvciBtb3ZlIHRoZW0gaW50byBmaXJzdCBpbiBjYXNlIG9mIHNhbWVMaW5lKVxuICAgICAgZm9yICh2YXIgaSQxID0gMDsgaSQxIDwgbGFzdC5sZW5ndGg7ICsraSQxKSB7XG4gICAgICAgIHZhciBzcGFuJDEgPSBsYXN0W2kkMV07XG4gICAgICAgIGlmIChzcGFuJDEudG8gIT0gbnVsbCkgeyBzcGFuJDEudG8gKz0gb2Zmc2V0OyB9XG4gICAgICAgIGlmIChzcGFuJDEuZnJvbSA9PSBudWxsKSB7XG4gICAgICAgICAgdmFyIGZvdW5kJDEgPSBnZXRNYXJrZWRTcGFuRm9yKGZpcnN0LCBzcGFuJDEubWFya2VyKTtcbiAgICAgICAgICBpZiAoIWZvdW5kJDEpIHtcbiAgICAgICAgICAgIHNwYW4kMS5mcm9tID0gb2Zmc2V0O1xuICAgICAgICAgICAgaWYgKHNhbWVMaW5lKSB7IChmaXJzdCB8fCAoZmlyc3QgPSBbXSkpLnB1c2goc3BhbiQxKTsgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzcGFuJDEuZnJvbSArPSBvZmZzZXQ7XG4gICAgICAgICAgaWYgKHNhbWVMaW5lKSB7IChmaXJzdCB8fCAoZmlyc3QgPSBbXSkpLnB1c2goc3BhbiQxKTsgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIC8vIE1ha2Ugc3VyZSB3ZSBkaWRuJ3QgY3JlYXRlIGFueSB6ZXJvLWxlbmd0aCBzcGFuc1xuICAgIGlmIChmaXJzdCkgeyBmaXJzdCA9IGNsZWFyRW1wdHlTcGFucyhmaXJzdCk7IH1cbiAgICBpZiAobGFzdCAmJiBsYXN0ICE9IGZpcnN0KSB7IGxhc3QgPSBjbGVhckVtcHR5U3BhbnMobGFzdCk7IH1cblxuICAgIHZhciBuZXdNYXJrZXJzID0gW2ZpcnN0XTtcbiAgICBpZiAoIXNhbWVMaW5lKSB7XG4gICAgICAvLyBGaWxsIGdhcCB3aXRoIHdob2xlLWxpbmUtc3BhbnNcbiAgICAgIHZhciBnYXAgPSBjaGFuZ2UudGV4dC5sZW5ndGggLSAyLCBnYXBNYXJrZXJzO1xuICAgICAgaWYgKGdhcCA+IDAgJiYgZmlyc3QpXG4gICAgICAgIHsgZm9yICh2YXIgaSQyID0gMDsgaSQyIDwgZmlyc3QubGVuZ3RoOyArK2kkMilcbiAgICAgICAgICB7IGlmIChmaXJzdFtpJDJdLnRvID09IG51bGwpXG4gICAgICAgICAgICB7IChnYXBNYXJrZXJzIHx8IChnYXBNYXJrZXJzID0gW10pKS5wdXNoKG5ldyBNYXJrZWRTcGFuKGZpcnN0W2kkMl0ubWFya2VyLCBudWxsLCBudWxsKSk7IH0gfSB9XG4gICAgICBmb3IgKHZhciBpJDMgPSAwOyBpJDMgPCBnYXA7ICsraSQzKVxuICAgICAgICB7IG5ld01hcmtlcnMucHVzaChnYXBNYXJrZXJzKTsgfVxuICAgICAgbmV3TWFya2Vycy5wdXNoKGxhc3QpO1xuICAgIH1cbiAgICByZXR1cm4gbmV3TWFya2Vyc1xuICB9XG5cbiAgLy8gUmVtb3ZlIHNwYW5zIHRoYXQgYXJlIGVtcHR5IGFuZCBkb24ndCBoYXZlIGEgY2xlYXJXaGVuRW1wdHlcbiAgLy8gb3B0aW9uIG9mIGZhbHNlLlxuICBmdW5jdGlvbiBjbGVhckVtcHR5U3BhbnMoc3BhbnMpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNwYW5zLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgc3BhbiA9IHNwYW5zW2ldO1xuICAgICAgaWYgKHNwYW4uZnJvbSAhPSBudWxsICYmIHNwYW4uZnJvbSA9PSBzcGFuLnRvICYmIHNwYW4ubWFya2VyLmNsZWFyV2hlbkVtcHR5ICE9PSBmYWxzZSlcbiAgICAgICAgeyBzcGFucy5zcGxpY2UoaS0tLCAxKTsgfVxuICAgIH1cbiAgICBpZiAoIXNwYW5zLmxlbmd0aCkgeyByZXR1cm4gbnVsbCB9XG4gICAgcmV0dXJuIHNwYW5zXG4gIH1cblxuICAvLyBVc2VkIHRvICdjbGlwJyBvdXQgcmVhZE9ubHkgcmFuZ2VzIHdoZW4gbWFraW5nIGEgY2hhbmdlLlxuICBmdW5jdGlvbiByZW1vdmVSZWFkT25seVJhbmdlcyhkb2MsIGZyb20sIHRvKSB7XG4gICAgdmFyIG1hcmtlcnMgPSBudWxsO1xuICAgIGRvYy5pdGVyKGZyb20ubGluZSwgdG8ubGluZSArIDEsIGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICBpZiAobGluZS5tYXJrZWRTcGFucykgeyBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmUubWFya2VkU3BhbnMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIG1hcmsgPSBsaW5lLm1hcmtlZFNwYW5zW2ldLm1hcmtlcjtcbiAgICAgICAgaWYgKG1hcmsucmVhZE9ubHkgJiYgKCFtYXJrZXJzIHx8IGluZGV4T2YobWFya2VycywgbWFyaykgPT0gLTEpKVxuICAgICAgICAgIHsgKG1hcmtlcnMgfHwgKG1hcmtlcnMgPSBbXSkpLnB1c2gobWFyayk7IH1cbiAgICAgIH0gfVxuICAgIH0pO1xuICAgIGlmICghbWFya2VycykgeyByZXR1cm4gbnVsbCB9XG4gICAgdmFyIHBhcnRzID0gW3tmcm9tOiBmcm9tLCB0bzogdG99XTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1hcmtlcnMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBtayA9IG1hcmtlcnNbaV0sIG0gPSBtay5maW5kKDApO1xuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBwYXJ0cy5sZW5ndGg7ICsraikge1xuICAgICAgICB2YXIgcCA9IHBhcnRzW2pdO1xuICAgICAgICBpZiAoY21wKHAudG8sIG0uZnJvbSkgPCAwIHx8IGNtcChwLmZyb20sIG0udG8pID4gMCkgeyBjb250aW51ZSB9XG4gICAgICAgIHZhciBuZXdQYXJ0cyA9IFtqLCAxXSwgZGZyb20gPSBjbXAocC5mcm9tLCBtLmZyb20pLCBkdG8gPSBjbXAocC50bywgbS50byk7XG4gICAgICAgIGlmIChkZnJvbSA8IDAgfHwgIW1rLmluY2x1c2l2ZUxlZnQgJiYgIWRmcm9tKVxuICAgICAgICAgIHsgbmV3UGFydHMucHVzaCh7ZnJvbTogcC5mcm9tLCB0bzogbS5mcm9tfSk7IH1cbiAgICAgICAgaWYgKGR0byA+IDAgfHwgIW1rLmluY2x1c2l2ZVJpZ2h0ICYmICFkdG8pXG4gICAgICAgICAgeyBuZXdQYXJ0cy5wdXNoKHtmcm9tOiBtLnRvLCB0bzogcC50b30pOyB9XG4gICAgICAgIHBhcnRzLnNwbGljZS5hcHBseShwYXJ0cywgbmV3UGFydHMpO1xuICAgICAgICBqICs9IG5ld1BhcnRzLmxlbmd0aCAtIDM7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwYXJ0c1xuICB9XG5cbiAgLy8gQ29ubmVjdCBvciBkaXNjb25uZWN0IHNwYW5zIGZyb20gYSBsaW5lLlxuICBmdW5jdGlvbiBkZXRhY2hNYXJrZWRTcGFucyhsaW5lKSB7XG4gICAgdmFyIHNwYW5zID0gbGluZS5tYXJrZWRTcGFucztcbiAgICBpZiAoIXNwYW5zKSB7IHJldHVybiB9XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzcGFucy5sZW5ndGg7ICsraSlcbiAgICAgIHsgc3BhbnNbaV0ubWFya2VyLmRldGFjaExpbmUobGluZSk7IH1cbiAgICBsaW5lLm1hcmtlZFNwYW5zID0gbnVsbDtcbiAgfVxuICBmdW5jdGlvbiBhdHRhY2hNYXJrZWRTcGFucyhsaW5lLCBzcGFucykge1xuICAgIGlmICghc3BhbnMpIHsgcmV0dXJuIH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNwYW5zLmxlbmd0aDsgKytpKVxuICAgICAgeyBzcGFuc1tpXS5tYXJrZXIuYXR0YWNoTGluZShsaW5lKTsgfVxuICAgIGxpbmUubWFya2VkU3BhbnMgPSBzcGFucztcbiAgfVxuXG4gIC8vIEhlbHBlcnMgdXNlZCB3aGVuIGNvbXB1dGluZyB3aGljaCBvdmVybGFwcGluZyBjb2xsYXBzZWQgc3BhblxuICAvLyBjb3VudHMgYXMgdGhlIGxhcmdlciBvbmUuXG4gIGZ1bmN0aW9uIGV4dHJhTGVmdChtYXJrZXIpIHsgcmV0dXJuIG1hcmtlci5pbmNsdXNpdmVMZWZ0ID8gLTEgOiAwIH1cbiAgZnVuY3Rpb24gZXh0cmFSaWdodChtYXJrZXIpIHsgcmV0dXJuIG1hcmtlci5pbmNsdXNpdmVSaWdodCA/IDEgOiAwIH1cblxuICAvLyBSZXR1cm5zIGEgbnVtYmVyIGluZGljYXRpbmcgd2hpY2ggb2YgdHdvIG92ZXJsYXBwaW5nIGNvbGxhcHNlZFxuICAvLyBzcGFucyBpcyBsYXJnZXIgKGFuZCB0aHVzIGluY2x1ZGVzIHRoZSBvdGhlcikuIEZhbGxzIGJhY2sgdG9cbiAgLy8gY29tcGFyaW5nIGlkcyB3aGVuIHRoZSBzcGFucyBjb3ZlciBleGFjdGx5IHRoZSBzYW1lIHJhbmdlLlxuICBmdW5jdGlvbiBjb21wYXJlQ29sbGFwc2VkTWFya2VycyhhLCBiKSB7XG4gICAgdmFyIGxlbkRpZmYgPSBhLmxpbmVzLmxlbmd0aCAtIGIubGluZXMubGVuZ3RoO1xuICAgIGlmIChsZW5EaWZmICE9IDApIHsgcmV0dXJuIGxlbkRpZmYgfVxuICAgIHZhciBhUG9zID0gYS5maW5kKCksIGJQb3MgPSBiLmZpbmQoKTtcbiAgICB2YXIgZnJvbUNtcCA9IGNtcChhUG9zLmZyb20sIGJQb3MuZnJvbSkgfHwgZXh0cmFMZWZ0KGEpIC0gZXh0cmFMZWZ0KGIpO1xuICAgIGlmIChmcm9tQ21wKSB7IHJldHVybiAtZnJvbUNtcCB9XG4gICAgdmFyIHRvQ21wID0gY21wKGFQb3MudG8sIGJQb3MudG8pIHx8IGV4dHJhUmlnaHQoYSkgLSBleHRyYVJpZ2h0KGIpO1xuICAgIGlmICh0b0NtcCkgeyByZXR1cm4gdG9DbXAgfVxuICAgIHJldHVybiBiLmlkIC0gYS5pZFxuICB9XG5cbiAgLy8gRmluZCBvdXQgd2hldGhlciBhIGxpbmUgZW5kcyBvciBzdGFydHMgaW4gYSBjb2xsYXBzZWQgc3Bhbi4gSWZcbiAgLy8gc28sIHJldHVybiB0aGUgbWFya2VyIGZvciB0aGF0IHNwYW4uXG4gIGZ1bmN0aW9uIGNvbGxhcHNlZFNwYW5BdFNpZGUobGluZSwgc3RhcnQpIHtcbiAgICB2YXIgc3BzID0gc2F3Q29sbGFwc2VkU3BhbnMgJiYgbGluZS5tYXJrZWRTcGFucywgZm91bmQ7XG4gICAgaWYgKHNwcykgeyBmb3IgKHZhciBzcCA9ICh2b2lkIDApLCBpID0gMDsgaSA8IHNwcy5sZW5ndGg7ICsraSkge1xuICAgICAgc3AgPSBzcHNbaV07XG4gICAgICBpZiAoc3AubWFya2VyLmNvbGxhcHNlZCAmJiAoc3RhcnQgPyBzcC5mcm9tIDogc3AudG8pID09IG51bGwgJiZcbiAgICAgICAgICAoIWZvdW5kIHx8IGNvbXBhcmVDb2xsYXBzZWRNYXJrZXJzKGZvdW5kLCBzcC5tYXJrZXIpIDwgMCkpXG4gICAgICAgIHsgZm91bmQgPSBzcC5tYXJrZXI7IH1cbiAgICB9IH1cbiAgICByZXR1cm4gZm91bmRcbiAgfVxuICBmdW5jdGlvbiBjb2xsYXBzZWRTcGFuQXRTdGFydChsaW5lKSB7IHJldHVybiBjb2xsYXBzZWRTcGFuQXRTaWRlKGxpbmUsIHRydWUpIH1cbiAgZnVuY3Rpb24gY29sbGFwc2VkU3BhbkF0RW5kKGxpbmUpIHsgcmV0dXJuIGNvbGxhcHNlZFNwYW5BdFNpZGUobGluZSwgZmFsc2UpIH1cblxuICBmdW5jdGlvbiBjb2xsYXBzZWRTcGFuQXJvdW5kKGxpbmUsIGNoKSB7XG4gICAgdmFyIHNwcyA9IHNhd0NvbGxhcHNlZFNwYW5zICYmIGxpbmUubWFya2VkU3BhbnMsIGZvdW5kO1xuICAgIGlmIChzcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBzcHMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBzcCA9IHNwc1tpXTtcbiAgICAgIGlmIChzcC5tYXJrZXIuY29sbGFwc2VkICYmIChzcC5mcm9tID09IG51bGwgfHwgc3AuZnJvbSA8IGNoKSAmJiAoc3AudG8gPT0gbnVsbCB8fCBzcC50byA+IGNoKSAmJlxuICAgICAgICAgICghZm91bmQgfHwgY29tcGFyZUNvbGxhcHNlZE1hcmtlcnMoZm91bmQsIHNwLm1hcmtlcikgPCAwKSkgeyBmb3VuZCA9IHNwLm1hcmtlcjsgfVxuICAgIH0gfVxuICAgIHJldHVybiBmb3VuZFxuICB9XG5cbiAgLy8gVGVzdCB3aGV0aGVyIHRoZXJlIGV4aXN0cyBhIGNvbGxhcHNlZCBzcGFuIHRoYXQgcGFydGlhbGx5XG4gIC8vIG92ZXJsYXBzIChjb3ZlcnMgdGhlIHN0YXJ0IG9yIGVuZCwgYnV0IG5vdCBib3RoKSBvZiBhIG5ldyBzcGFuLlxuICAvLyBTdWNoIG92ZXJsYXAgaXMgbm90IGFsbG93ZWQuXG4gIGZ1bmN0aW9uIGNvbmZsaWN0aW5nQ29sbGFwc2VkUmFuZ2UoZG9jLCBsaW5lTm8sIGZyb20sIHRvLCBtYXJrZXIpIHtcbiAgICB2YXIgbGluZSA9IGdldExpbmUoZG9jLCBsaW5lTm8pO1xuICAgIHZhciBzcHMgPSBzYXdDb2xsYXBzZWRTcGFucyAmJiBsaW5lLm1hcmtlZFNwYW5zO1xuICAgIGlmIChzcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBzcHMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBzcCA9IHNwc1tpXTtcbiAgICAgIGlmICghc3AubWFya2VyLmNvbGxhcHNlZCkgeyBjb250aW51ZSB9XG4gICAgICB2YXIgZm91bmQgPSBzcC5tYXJrZXIuZmluZCgwKTtcbiAgICAgIHZhciBmcm9tQ21wID0gY21wKGZvdW5kLmZyb20sIGZyb20pIHx8IGV4dHJhTGVmdChzcC5tYXJrZXIpIC0gZXh0cmFMZWZ0KG1hcmtlcik7XG4gICAgICB2YXIgdG9DbXAgPSBjbXAoZm91bmQudG8sIHRvKSB8fCBleHRyYVJpZ2h0KHNwLm1hcmtlcikgLSBleHRyYVJpZ2h0KG1hcmtlcik7XG4gICAgICBpZiAoZnJvbUNtcCA+PSAwICYmIHRvQ21wIDw9IDAgfHwgZnJvbUNtcCA8PSAwICYmIHRvQ21wID49IDApIHsgY29udGludWUgfVxuICAgICAgaWYgKGZyb21DbXAgPD0gMCAmJiAoc3AubWFya2VyLmluY2x1c2l2ZVJpZ2h0ICYmIG1hcmtlci5pbmNsdXNpdmVMZWZ0ID8gY21wKGZvdW5kLnRvLCBmcm9tKSA+PSAwIDogY21wKGZvdW5kLnRvLCBmcm9tKSA+IDApIHx8XG4gICAgICAgICAgZnJvbUNtcCA+PSAwICYmIChzcC5tYXJrZXIuaW5jbHVzaXZlUmlnaHQgJiYgbWFya2VyLmluY2x1c2l2ZUxlZnQgPyBjbXAoZm91bmQuZnJvbSwgdG8pIDw9IDAgOiBjbXAoZm91bmQuZnJvbSwgdG8pIDwgMCkpXG4gICAgICAgIHsgcmV0dXJuIHRydWUgfVxuICAgIH0gfVxuICB9XG5cbiAgLy8gQSB2aXN1YWwgbGluZSBpcyBhIGxpbmUgYXMgZHJhd24gb24gdGhlIHNjcmVlbi4gRm9sZGluZywgZm9yXG4gIC8vIGV4YW1wbGUsIGNhbiBjYXVzZSBtdWx0aXBsZSBsb2dpY2FsIGxpbmVzIHRvIGFwcGVhciBvbiB0aGUgc2FtZVxuICAvLyB2aXN1YWwgbGluZS4gVGhpcyBmaW5kcyB0aGUgc3RhcnQgb2YgdGhlIHZpc3VhbCBsaW5lIHRoYXQgdGhlXG4gIC8vIGdpdmVuIGxpbmUgaXMgcGFydCBvZiAodXN1YWxseSB0aGF0IGlzIHRoZSBsaW5lIGl0c2VsZikuXG4gIGZ1bmN0aW9uIHZpc3VhbExpbmUobGluZSkge1xuICAgIHZhciBtZXJnZWQ7XG4gICAgd2hpbGUgKG1lcmdlZCA9IGNvbGxhcHNlZFNwYW5BdFN0YXJ0KGxpbmUpKVxuICAgICAgeyBsaW5lID0gbWVyZ2VkLmZpbmQoLTEsIHRydWUpLmxpbmU7IH1cbiAgICByZXR1cm4gbGluZVxuICB9XG5cbiAgZnVuY3Rpb24gdmlzdWFsTGluZUVuZChsaW5lKSB7XG4gICAgdmFyIG1lcmdlZDtcbiAgICB3aGlsZSAobWVyZ2VkID0gY29sbGFwc2VkU3BhbkF0RW5kKGxpbmUpKVxuICAgICAgeyBsaW5lID0gbWVyZ2VkLmZpbmQoMSwgdHJ1ZSkubGluZTsgfVxuICAgIHJldHVybiBsaW5lXG4gIH1cblxuICAvLyBSZXR1cm5zIGFuIGFycmF5IG9mIGxvZ2ljYWwgbGluZXMgdGhhdCBjb250aW51ZSB0aGUgdmlzdWFsIGxpbmVcbiAgLy8gc3RhcnRlZCBieSB0aGUgYXJndW1lbnQsIG9yIHVuZGVmaW5lZCBpZiB0aGVyZSBhcmUgbm8gc3VjaCBsaW5lcy5cbiAgZnVuY3Rpb24gdmlzdWFsTGluZUNvbnRpbnVlZChsaW5lKSB7XG4gICAgdmFyIG1lcmdlZCwgbGluZXM7XG4gICAgd2hpbGUgKG1lcmdlZCA9IGNvbGxhcHNlZFNwYW5BdEVuZChsaW5lKSkge1xuICAgICAgbGluZSA9IG1lcmdlZC5maW5kKDEsIHRydWUpLmxpbmVcbiAgICAgIDsobGluZXMgfHwgKGxpbmVzID0gW10pKS5wdXNoKGxpbmUpO1xuICAgIH1cbiAgICByZXR1cm4gbGluZXNcbiAgfVxuXG4gIC8vIEdldCB0aGUgbGluZSBudW1iZXIgb2YgdGhlIHN0YXJ0IG9mIHRoZSB2aXN1YWwgbGluZSB0aGF0IHRoZVxuICAvLyBnaXZlbiBsaW5lIG51bWJlciBpcyBwYXJ0IG9mLlxuICBmdW5jdGlvbiB2aXN1YWxMaW5lTm8oZG9jLCBsaW5lTikge1xuICAgIHZhciBsaW5lID0gZ2V0TGluZShkb2MsIGxpbmVOKSwgdmlzID0gdmlzdWFsTGluZShsaW5lKTtcbiAgICBpZiAobGluZSA9PSB2aXMpIHsgcmV0dXJuIGxpbmVOIH1cbiAgICByZXR1cm4gbGluZU5vKHZpcylcbiAgfVxuXG4gIC8vIEdldCB0aGUgbGluZSBudW1iZXIgb2YgdGhlIHN0YXJ0IG9mIHRoZSBuZXh0IHZpc3VhbCBsaW5lIGFmdGVyXG4gIC8vIHRoZSBnaXZlbiBsaW5lLlxuICBmdW5jdGlvbiB2aXN1YWxMaW5lRW5kTm8oZG9jLCBsaW5lTikge1xuICAgIGlmIChsaW5lTiA+IGRvYy5sYXN0TGluZSgpKSB7IHJldHVybiBsaW5lTiB9XG4gICAgdmFyIGxpbmUgPSBnZXRMaW5lKGRvYywgbGluZU4pLCBtZXJnZWQ7XG4gICAgaWYgKCFsaW5lSXNIaWRkZW4oZG9jLCBsaW5lKSkgeyByZXR1cm4gbGluZU4gfVxuICAgIHdoaWxlIChtZXJnZWQgPSBjb2xsYXBzZWRTcGFuQXRFbmQobGluZSkpXG4gICAgICB7IGxpbmUgPSBtZXJnZWQuZmluZCgxLCB0cnVlKS5saW5lOyB9XG4gICAgcmV0dXJuIGxpbmVObyhsaW5lKSArIDFcbiAgfVxuXG4gIC8vIENvbXB1dGUgd2hldGhlciBhIGxpbmUgaXMgaGlkZGVuLiBMaW5lcyBjb3VudCBhcyBoaWRkZW4gd2hlbiB0aGV5XG4gIC8vIGFyZSBwYXJ0IG9mIGEgdmlzdWFsIGxpbmUgdGhhdCBzdGFydHMgd2l0aCBhbm90aGVyIGxpbmUsIG9yIHdoZW5cbiAgLy8gdGhleSBhcmUgZW50aXJlbHkgY292ZXJlZCBieSBjb2xsYXBzZWQsIG5vbi13aWRnZXQgc3Bhbi5cbiAgZnVuY3Rpb24gbGluZUlzSGlkZGVuKGRvYywgbGluZSkge1xuICAgIHZhciBzcHMgPSBzYXdDb2xsYXBzZWRTcGFucyAmJiBsaW5lLm1hcmtlZFNwYW5zO1xuICAgIGlmIChzcHMpIHsgZm9yICh2YXIgc3AgPSAodm9pZCAwKSwgaSA9IDA7IGkgPCBzcHMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHNwID0gc3BzW2ldO1xuICAgICAgaWYgKCFzcC5tYXJrZXIuY29sbGFwc2VkKSB7IGNvbnRpbnVlIH1cbiAgICAgIGlmIChzcC5mcm9tID09IG51bGwpIHsgcmV0dXJuIHRydWUgfVxuICAgICAgaWYgKHNwLm1hcmtlci53aWRnZXROb2RlKSB7IGNvbnRpbnVlIH1cbiAgICAgIGlmIChzcC5mcm9tID09IDAgJiYgc3AubWFya2VyLmluY2x1c2l2ZUxlZnQgJiYgbGluZUlzSGlkZGVuSW5uZXIoZG9jLCBsaW5lLCBzcCkpXG4gICAgICAgIHsgcmV0dXJuIHRydWUgfVxuICAgIH0gfVxuICB9XG4gIGZ1bmN0aW9uIGxpbmVJc0hpZGRlbklubmVyKGRvYywgbGluZSwgc3Bhbikge1xuICAgIGlmIChzcGFuLnRvID09IG51bGwpIHtcbiAgICAgIHZhciBlbmQgPSBzcGFuLm1hcmtlci5maW5kKDEsIHRydWUpO1xuICAgICAgcmV0dXJuIGxpbmVJc0hpZGRlbklubmVyKGRvYywgZW5kLmxpbmUsIGdldE1hcmtlZFNwYW5Gb3IoZW5kLmxpbmUubWFya2VkU3BhbnMsIHNwYW4ubWFya2VyKSlcbiAgICB9XG4gICAgaWYgKHNwYW4ubWFya2VyLmluY2x1c2l2ZVJpZ2h0ICYmIHNwYW4udG8gPT0gbGluZS50ZXh0Lmxlbmd0aClcbiAgICAgIHsgcmV0dXJuIHRydWUgfVxuICAgIGZvciAodmFyIHNwID0gKHZvaWQgMCksIGkgPSAwOyBpIDwgbGluZS5tYXJrZWRTcGFucy5sZW5ndGg7ICsraSkge1xuICAgICAgc3AgPSBsaW5lLm1hcmtlZFNwYW5zW2ldO1xuICAgICAgaWYgKHNwLm1hcmtlci5jb2xsYXBzZWQgJiYgIXNwLm1hcmtlci53aWRnZXROb2RlICYmIHNwLmZyb20gPT0gc3Bhbi50byAmJlxuICAgICAgICAgIChzcC50byA9PSBudWxsIHx8IHNwLnRvICE9IHNwYW4uZnJvbSkgJiZcbiAgICAgICAgICAoc3AubWFya2VyLmluY2x1c2l2ZUxlZnQgfHwgc3Bhbi5tYXJrZXIuaW5jbHVzaXZlUmlnaHQpICYmXG4gICAgICAgICAgbGluZUlzSGlkZGVuSW5uZXIoZG9jLCBsaW5lLCBzcCkpIHsgcmV0dXJuIHRydWUgfVxuICAgIH1cbiAgfVxuXG4gIC8vIEZpbmQgdGhlIGhlaWdodCBhYm92ZSB0aGUgZ2l2ZW4gbGluZS5cbiAgZnVuY3Rpb24gaGVpZ2h0QXRMaW5lKGxpbmVPYmopIHtcbiAgICBsaW5lT2JqID0gdmlzdWFsTGluZShsaW5lT2JqKTtcblxuICAgIHZhciBoID0gMCwgY2h1bmsgPSBsaW5lT2JqLnBhcmVudDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNodW5rLmxpbmVzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgbGluZSA9IGNodW5rLmxpbmVzW2ldO1xuICAgICAgaWYgKGxpbmUgPT0gbGluZU9iaikgeyBicmVhayB9XG4gICAgICBlbHNlIHsgaCArPSBsaW5lLmhlaWdodDsgfVxuICAgIH1cbiAgICBmb3IgKHZhciBwID0gY2h1bmsucGFyZW50OyBwOyBjaHVuayA9IHAsIHAgPSBjaHVuay5wYXJlbnQpIHtcbiAgICAgIGZvciAodmFyIGkkMSA9IDA7IGkkMSA8IHAuY2hpbGRyZW4ubGVuZ3RoOyArK2kkMSkge1xuICAgICAgICB2YXIgY3VyID0gcC5jaGlsZHJlbltpJDFdO1xuICAgICAgICBpZiAoY3VyID09IGNodW5rKSB7IGJyZWFrIH1cbiAgICAgICAgZWxzZSB7IGggKz0gY3VyLmhlaWdodDsgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gaFxuICB9XG5cbiAgLy8gQ29tcHV0ZSB0aGUgY2hhcmFjdGVyIGxlbmd0aCBvZiBhIGxpbmUsIHRha2luZyBpbnRvIGFjY291bnRcbiAgLy8gY29sbGFwc2VkIHJhbmdlcyAoc2VlIG1hcmtUZXh0KSB0aGF0IG1pZ2h0IGhpZGUgcGFydHMsIGFuZCBqb2luXG4gIC8vIG90aGVyIGxpbmVzIG9udG8gaXQuXG4gIGZ1bmN0aW9uIGxpbmVMZW5ndGgobGluZSkge1xuICAgIGlmIChsaW5lLmhlaWdodCA9PSAwKSB7IHJldHVybiAwIH1cbiAgICB2YXIgbGVuID0gbGluZS50ZXh0Lmxlbmd0aCwgbWVyZ2VkLCBjdXIgPSBsaW5lO1xuICAgIHdoaWxlIChtZXJnZWQgPSBjb2xsYXBzZWRTcGFuQXRTdGFydChjdXIpKSB7XG4gICAgICB2YXIgZm91bmQgPSBtZXJnZWQuZmluZCgwLCB0cnVlKTtcbiAgICAgIGN1ciA9IGZvdW5kLmZyb20ubGluZTtcbiAgICAgIGxlbiArPSBmb3VuZC5mcm9tLmNoIC0gZm91bmQudG8uY2g7XG4gICAgfVxuICAgIGN1ciA9IGxpbmU7XG4gICAgd2hpbGUgKG1lcmdlZCA9IGNvbGxhcHNlZFNwYW5BdEVuZChjdXIpKSB7XG4gICAgICB2YXIgZm91bmQkMSA9IG1lcmdlZC5maW5kKDAsIHRydWUpO1xuICAgICAgbGVuIC09IGN1ci50ZXh0Lmxlbmd0aCAtIGZvdW5kJDEuZnJvbS5jaDtcbiAgICAgIGN1ciA9IGZvdW5kJDEudG8ubGluZTtcbiAgICAgIGxlbiArPSBjdXIudGV4dC5sZW5ndGggLSBmb3VuZCQxLnRvLmNoO1xuICAgIH1cbiAgICByZXR1cm4gbGVuXG4gIH1cblxuICAvLyBGaW5kIHRoZSBsb25nZXN0IGxpbmUgaW4gdGhlIGRvY3VtZW50LlxuICBmdW5jdGlvbiBmaW5kTWF4TGluZShjbSkge1xuICAgIHZhciBkID0gY20uZGlzcGxheSwgZG9jID0gY20uZG9jO1xuICAgIGQubWF4TGluZSA9IGdldExpbmUoZG9jLCBkb2MuZmlyc3QpO1xuICAgIGQubWF4TGluZUxlbmd0aCA9IGxpbmVMZW5ndGgoZC5tYXhMaW5lKTtcbiAgICBkLm1heExpbmVDaGFuZ2VkID0gdHJ1ZTtcbiAgICBkb2MuaXRlcihmdW5jdGlvbiAobGluZSkge1xuICAgICAgdmFyIGxlbiA9IGxpbmVMZW5ndGgobGluZSk7XG4gICAgICBpZiAobGVuID4gZC5tYXhMaW5lTGVuZ3RoKSB7XG4gICAgICAgIGQubWF4TGluZUxlbmd0aCA9IGxlbjtcbiAgICAgICAgZC5tYXhMaW5lID0gbGluZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vIExJTkUgREFUQSBTVFJVQ1RVUkVcblxuICAvLyBMaW5lIG9iamVjdHMuIFRoZXNlIGhvbGQgc3RhdGUgcmVsYXRlZCB0byBhIGxpbmUsIGluY2x1ZGluZ1xuICAvLyBoaWdobGlnaHRpbmcgaW5mbyAodGhlIHN0eWxlcyBhcnJheSkuXG4gIHZhciBMaW5lID0gZnVuY3Rpb24odGV4dCwgbWFya2VkU3BhbnMsIGVzdGltYXRlSGVpZ2h0KSB7XG4gICAgdGhpcy50ZXh0ID0gdGV4dDtcbiAgICBhdHRhY2hNYXJrZWRTcGFucyh0aGlzLCBtYXJrZWRTcGFucyk7XG4gICAgdGhpcy5oZWlnaHQgPSBlc3RpbWF0ZUhlaWdodCA/IGVzdGltYXRlSGVpZ2h0KHRoaXMpIDogMTtcbiAgfTtcblxuICBMaW5lLnByb3RvdHlwZS5saW5lTm8gPSBmdW5jdGlvbiAoKSB7IHJldHVybiBsaW5lTm8odGhpcykgfTtcbiAgZXZlbnRNaXhpbihMaW5lKTtcblxuICAvLyBDaGFuZ2UgdGhlIGNvbnRlbnQgKHRleHQsIG1hcmtlcnMpIG9mIGEgbGluZS4gQXV0b21hdGljYWxseVxuICAvLyBpbnZhbGlkYXRlcyBjYWNoZWQgaW5mb3JtYXRpb24gYW5kIHRyaWVzIHRvIHJlLWVzdGltYXRlIHRoZVxuICAvLyBsaW5lJ3MgaGVpZ2h0LlxuICBmdW5jdGlvbiB1cGRhdGVMaW5lKGxpbmUsIHRleHQsIG1hcmtlZFNwYW5zLCBlc3RpbWF0ZUhlaWdodCkge1xuICAgIGxpbmUudGV4dCA9IHRleHQ7XG4gICAgaWYgKGxpbmUuc3RhdGVBZnRlcikgeyBsaW5lLnN0YXRlQWZ0ZXIgPSBudWxsOyB9XG4gICAgaWYgKGxpbmUuc3R5bGVzKSB7IGxpbmUuc3R5bGVzID0gbnVsbDsgfVxuICAgIGlmIChsaW5lLm9yZGVyICE9IG51bGwpIHsgbGluZS5vcmRlciA9IG51bGw7IH1cbiAgICBkZXRhY2hNYXJrZWRTcGFucyhsaW5lKTtcbiAgICBhdHRhY2hNYXJrZWRTcGFucyhsaW5lLCBtYXJrZWRTcGFucyk7XG4gICAgdmFyIGVzdEhlaWdodCA9IGVzdGltYXRlSGVpZ2h0ID8gZXN0aW1hdGVIZWlnaHQobGluZSkgOiAxO1xuICAgIGlmIChlc3RIZWlnaHQgIT0gbGluZS5oZWlnaHQpIHsgdXBkYXRlTGluZUhlaWdodChsaW5lLCBlc3RIZWlnaHQpOyB9XG4gIH1cblxuICAvLyBEZXRhY2ggYSBsaW5lIGZyb20gdGhlIGRvY3VtZW50IHRyZWUgYW5kIGl0cyBtYXJrZXJzLlxuICBmdW5jdGlvbiBjbGVhblVwTGluZShsaW5lKSB7XG4gICAgbGluZS5wYXJlbnQgPSBudWxsO1xuICAgIGRldGFjaE1hcmtlZFNwYW5zKGxpbmUpO1xuICB9XG5cbiAgLy8gQ29udmVydCBhIHN0eWxlIGFzIHJldHVybmVkIGJ5IGEgbW9kZSAoZWl0aGVyIG51bGwsIG9yIGEgc3RyaW5nXG4gIC8vIGNvbnRhaW5pbmcgb25lIG9yIG1vcmUgc3R5bGVzKSB0byBhIENTUyBzdHlsZS4gVGhpcyBpcyBjYWNoZWQsXG4gIC8vIGFuZCBhbHNvIGxvb2tzIGZvciBsaW5lLXdpZGUgc3R5bGVzLlxuICB2YXIgc3R5bGVUb0NsYXNzQ2FjaGUgPSB7fSwgc3R5bGVUb0NsYXNzQ2FjaGVXaXRoTW9kZSA9IHt9O1xuICBmdW5jdGlvbiBpbnRlcnByZXRUb2tlblN0eWxlKHN0eWxlLCBvcHRpb25zKSB7XG4gICAgaWYgKCFzdHlsZSB8fCAvXlxccyokLy50ZXN0KHN0eWxlKSkgeyByZXR1cm4gbnVsbCB9XG4gICAgdmFyIGNhY2hlID0gb3B0aW9ucy5hZGRNb2RlQ2xhc3MgPyBzdHlsZVRvQ2xhc3NDYWNoZVdpdGhNb2RlIDogc3R5bGVUb0NsYXNzQ2FjaGU7XG4gICAgcmV0dXJuIGNhY2hlW3N0eWxlXSB8fFxuICAgICAgKGNhY2hlW3N0eWxlXSA9IHN0eWxlLnJlcGxhY2UoL1xcUysvZywgXCJjbS0kJlwiKSlcbiAgfVxuXG4gIC8vIFJlbmRlciB0aGUgRE9NIHJlcHJlc2VudGF0aW9uIG9mIHRoZSB0ZXh0IG9mIGEgbGluZS4gQWxzbyBidWlsZHNcbiAgLy8gdXAgYSAnbGluZSBtYXAnLCB3aGljaCBwb2ludHMgYXQgdGhlIERPTSBub2RlcyB0aGF0IHJlcHJlc2VudFxuICAvLyBzcGVjaWZpYyBzdHJldGNoZXMgb2YgdGV4dCwgYW5kIGlzIHVzZWQgYnkgdGhlIG1lYXN1cmluZyBjb2RlLlxuICAvLyBUaGUgcmV0dXJuZWQgb2JqZWN0IGNvbnRhaW5zIHRoZSBET00gbm9kZSwgdGhpcyBtYXAsIGFuZFxuICAvLyBpbmZvcm1hdGlvbiBhYm91dCBsaW5lLXdpZGUgc3R5bGVzIHRoYXQgd2VyZSBzZXQgYnkgdGhlIG1vZGUuXG4gIGZ1bmN0aW9uIGJ1aWxkTGluZUNvbnRlbnQoY20sIGxpbmVWaWV3KSB7XG4gICAgLy8gVGhlIHBhZGRpbmctcmlnaHQgZm9yY2VzIHRoZSBlbGVtZW50IHRvIGhhdmUgYSAnYm9yZGVyJywgd2hpY2hcbiAgICAvLyBpcyBuZWVkZWQgb24gV2Via2l0IHRvIGJlIGFibGUgdG8gZ2V0IGxpbmUtbGV2ZWwgYm91bmRpbmdcbiAgICAvLyByZWN0YW5nbGVzIGZvciBpdCAoaW4gbWVhc3VyZUNoYXIpLlxuICAgIHZhciBjb250ZW50ID0gZWx0UChcInNwYW5cIiwgbnVsbCwgbnVsbCwgd2Via2l0ID8gXCJwYWRkaW5nLXJpZ2h0OiAuMXB4XCIgOiBudWxsKTtcbiAgICB2YXIgYnVpbGRlciA9IHtwcmU6IGVsdFAoXCJwcmVcIiwgW2NvbnRlbnRdLCBcIkNvZGVNaXJyb3ItbGluZVwiKSwgY29udGVudDogY29udGVudCxcbiAgICAgICAgICAgICAgICAgICBjb2w6IDAsIHBvczogMCwgY206IGNtLFxuICAgICAgICAgICAgICAgICAgIHRyYWlsaW5nU3BhY2U6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgIHNwbGl0U3BhY2VzOiBjbS5nZXRPcHRpb24oXCJsaW5lV3JhcHBpbmdcIil9O1xuICAgIGxpbmVWaWV3Lm1lYXN1cmUgPSB7fTtcblxuICAgIC8vIEl0ZXJhdGUgb3ZlciB0aGUgbG9naWNhbCBsaW5lcyB0aGF0IG1ha2UgdXAgdGhpcyB2aXN1YWwgbGluZS5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8PSAobGluZVZpZXcucmVzdCA/IGxpbmVWaWV3LnJlc3QubGVuZ3RoIDogMCk7IGkrKykge1xuICAgICAgdmFyIGxpbmUgPSBpID8gbGluZVZpZXcucmVzdFtpIC0gMV0gOiBsaW5lVmlldy5saW5lLCBvcmRlciA9ICh2b2lkIDApO1xuICAgICAgYnVpbGRlci5wb3MgPSAwO1xuICAgICAgYnVpbGRlci5hZGRUb2tlbiA9IGJ1aWxkVG9rZW47XG4gICAgICAvLyBPcHRpb25hbGx5IHdpcmUgaW4gc29tZSBoYWNrcyBpbnRvIHRoZSB0b2tlbi1yZW5kZXJpbmdcbiAgICAgIC8vIGFsZ29yaXRobSwgdG8gZGVhbCB3aXRoIGJyb3dzZXIgcXVpcmtzLlxuICAgICAgaWYgKGhhc0JhZEJpZGlSZWN0cyhjbS5kaXNwbGF5Lm1lYXN1cmUpICYmIChvcmRlciA9IGdldE9yZGVyKGxpbmUsIGNtLmRvYy5kaXJlY3Rpb24pKSlcbiAgICAgICAgeyBidWlsZGVyLmFkZFRva2VuID0gYnVpbGRUb2tlbkJhZEJpZGkoYnVpbGRlci5hZGRUb2tlbiwgb3JkZXIpOyB9XG4gICAgICBidWlsZGVyLm1hcCA9IFtdO1xuICAgICAgdmFyIGFsbG93RnJvbnRpZXJVcGRhdGUgPSBsaW5lVmlldyAhPSBjbS5kaXNwbGF5LmV4dGVybmFsTWVhc3VyZWQgJiYgbGluZU5vKGxpbmUpO1xuICAgICAgaW5zZXJ0TGluZUNvbnRlbnQobGluZSwgYnVpbGRlciwgZ2V0TGluZVN0eWxlcyhjbSwgbGluZSwgYWxsb3dGcm9udGllclVwZGF0ZSkpO1xuICAgICAgaWYgKGxpbmUuc3R5bGVDbGFzc2VzKSB7XG4gICAgICAgIGlmIChsaW5lLnN0eWxlQ2xhc3Nlcy5iZ0NsYXNzKVxuICAgICAgICAgIHsgYnVpbGRlci5iZ0NsYXNzID0gam9pbkNsYXNzZXMobGluZS5zdHlsZUNsYXNzZXMuYmdDbGFzcywgYnVpbGRlci5iZ0NsYXNzIHx8IFwiXCIpOyB9XG4gICAgICAgIGlmIChsaW5lLnN0eWxlQ2xhc3Nlcy50ZXh0Q2xhc3MpXG4gICAgICAgICAgeyBidWlsZGVyLnRleHRDbGFzcyA9IGpvaW5DbGFzc2VzKGxpbmUuc3R5bGVDbGFzc2VzLnRleHRDbGFzcywgYnVpbGRlci50ZXh0Q2xhc3MgfHwgXCJcIik7IH1cbiAgICAgIH1cblxuICAgICAgLy8gRW5zdXJlIGF0IGxlYXN0IGEgc2luZ2xlIG5vZGUgaXMgcHJlc2VudCwgZm9yIG1lYXN1cmluZy5cbiAgICAgIGlmIChidWlsZGVyLm1hcC5sZW5ndGggPT0gMClcbiAgICAgICAgeyBidWlsZGVyLm1hcC5wdXNoKDAsIDAsIGJ1aWxkZXIuY29udGVudC5hcHBlbmRDaGlsZCh6ZXJvV2lkdGhFbGVtZW50KGNtLmRpc3BsYXkubWVhc3VyZSkpKTsgfVxuXG4gICAgICAvLyBTdG9yZSB0aGUgbWFwIGFuZCBhIGNhY2hlIG9iamVjdCBmb3IgdGhlIGN1cnJlbnQgbG9naWNhbCBsaW5lXG4gICAgICBpZiAoaSA9PSAwKSB7XG4gICAgICAgIGxpbmVWaWV3Lm1lYXN1cmUubWFwID0gYnVpbGRlci5tYXA7XG4gICAgICAgIGxpbmVWaWV3Lm1lYXN1cmUuY2FjaGUgPSB7fTtcbiAgICAgIH0gZWxzZSB7XG4gIChsaW5lVmlldy5tZWFzdXJlLm1hcHMgfHwgKGxpbmVWaWV3Lm1lYXN1cmUubWFwcyA9IFtdKSkucHVzaChidWlsZGVyLm1hcClcbiAgICAgICAgOyhsaW5lVmlldy5tZWFzdXJlLmNhY2hlcyB8fCAobGluZVZpZXcubWVhc3VyZS5jYWNoZXMgPSBbXSkpLnB1c2goe30pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFNlZSBpc3N1ZSAjMjkwMVxuICAgIGlmICh3ZWJraXQpIHtcbiAgICAgIHZhciBsYXN0ID0gYnVpbGRlci5jb250ZW50Lmxhc3RDaGlsZDtcbiAgICAgIGlmICgvXFxiY20tdGFiXFxiLy50ZXN0KGxhc3QuY2xhc3NOYW1lKSB8fCAobGFzdC5xdWVyeVNlbGVjdG9yICYmIGxhc3QucXVlcnlTZWxlY3RvcihcIi5jbS10YWJcIikpKVxuICAgICAgICB7IGJ1aWxkZXIuY29udGVudC5jbGFzc05hbWUgPSBcImNtLXRhYi13cmFwLWhhY2tcIjsgfVxuICAgIH1cblxuICAgIHNpZ25hbChjbSwgXCJyZW5kZXJMaW5lXCIsIGNtLCBsaW5lVmlldy5saW5lLCBidWlsZGVyLnByZSk7XG4gICAgaWYgKGJ1aWxkZXIucHJlLmNsYXNzTmFtZSlcbiAgICAgIHsgYnVpbGRlci50ZXh0Q2xhc3MgPSBqb2luQ2xhc3NlcyhidWlsZGVyLnByZS5jbGFzc05hbWUsIGJ1aWxkZXIudGV4dENsYXNzIHx8IFwiXCIpOyB9XG5cbiAgICByZXR1cm4gYnVpbGRlclxuICB9XG5cbiAgZnVuY3Rpb24gZGVmYXVsdFNwZWNpYWxDaGFyUGxhY2Vob2xkZXIoY2gpIHtcbiAgICB2YXIgdG9rZW4gPSBlbHQoXCJzcGFuXCIsIFwiXFx1MjAyMlwiLCBcImNtLWludmFsaWRjaGFyXCIpO1xuICAgIHRva2VuLnRpdGxlID0gXCJcXFxcdVwiICsgY2guY2hhckNvZGVBdCgwKS50b1N0cmluZygxNik7XG4gICAgdG9rZW4uc2V0QXR0cmlidXRlKFwiYXJpYS1sYWJlbFwiLCB0b2tlbi50aXRsZSk7XG4gICAgcmV0dXJuIHRva2VuXG4gIH1cblxuICAvLyBCdWlsZCB1cCB0aGUgRE9NIHJlcHJlc2VudGF0aW9uIGZvciBhIHNpbmdsZSB0b2tlbiwgYW5kIGFkZCBpdCB0b1xuICAvLyB0aGUgbGluZSBtYXAuIFRha2VzIGNhcmUgdG8gcmVuZGVyIHNwZWNpYWwgY2hhcmFjdGVycyBzZXBhcmF0ZWx5LlxuICBmdW5jdGlvbiBidWlsZFRva2VuKGJ1aWxkZXIsIHRleHQsIHN0eWxlLCBzdGFydFN0eWxlLCBlbmRTdHlsZSwgY3NzLCBhdHRyaWJ1dGVzKSB7XG4gICAgaWYgKCF0ZXh0KSB7IHJldHVybiB9XG4gICAgdmFyIGRpc3BsYXlUZXh0ID0gYnVpbGRlci5zcGxpdFNwYWNlcyA/IHNwbGl0U3BhY2VzKHRleHQsIGJ1aWxkZXIudHJhaWxpbmdTcGFjZSkgOiB0ZXh0O1xuICAgIHZhciBzcGVjaWFsID0gYnVpbGRlci5jbS5zdGF0ZS5zcGVjaWFsQ2hhcnMsIG11c3RXcmFwID0gZmFsc2U7XG4gICAgdmFyIGNvbnRlbnQ7XG4gICAgaWYgKCFzcGVjaWFsLnRlc3QodGV4dCkpIHtcbiAgICAgIGJ1aWxkZXIuY29sICs9IHRleHQubGVuZ3RoO1xuICAgICAgY29udGVudCA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGRpc3BsYXlUZXh0KTtcbiAgICAgIGJ1aWxkZXIubWFwLnB1c2goYnVpbGRlci5wb3MsIGJ1aWxkZXIucG9zICsgdGV4dC5sZW5ndGgsIGNvbnRlbnQpO1xuICAgICAgaWYgKGllICYmIGllX3ZlcnNpb24gPCA5KSB7IG11c3RXcmFwID0gdHJ1ZTsgfVxuICAgICAgYnVpbGRlci5wb3MgKz0gdGV4dC5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnRlbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG4gICAgICB2YXIgcG9zID0gMDtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIHNwZWNpYWwubGFzdEluZGV4ID0gcG9zO1xuICAgICAgICB2YXIgbSA9IHNwZWNpYWwuZXhlYyh0ZXh0KTtcbiAgICAgICAgdmFyIHNraXBwZWQgPSBtID8gbS5pbmRleCAtIHBvcyA6IHRleHQubGVuZ3RoIC0gcG9zO1xuICAgICAgICBpZiAoc2tpcHBlZCkge1xuICAgICAgICAgIHZhciB0eHQgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShkaXNwbGF5VGV4dC5zbGljZShwb3MsIHBvcyArIHNraXBwZWQpKTtcbiAgICAgICAgICBpZiAoaWUgJiYgaWVfdmVyc2lvbiA8IDkpIHsgY29udGVudC5hcHBlbmRDaGlsZChlbHQoXCJzcGFuXCIsIFt0eHRdKSk7IH1cbiAgICAgICAgICBlbHNlIHsgY29udGVudC5hcHBlbmRDaGlsZCh0eHQpOyB9XG4gICAgICAgICAgYnVpbGRlci5tYXAucHVzaChidWlsZGVyLnBvcywgYnVpbGRlci5wb3MgKyBza2lwcGVkLCB0eHQpO1xuICAgICAgICAgIGJ1aWxkZXIuY29sICs9IHNraXBwZWQ7XG4gICAgICAgICAgYnVpbGRlci5wb3MgKz0gc2tpcHBlZDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIW0pIHsgYnJlYWsgfVxuICAgICAgICBwb3MgKz0gc2tpcHBlZCArIDE7XG4gICAgICAgIHZhciB0eHQkMSA9ICh2b2lkIDApO1xuICAgICAgICBpZiAobVswXSA9PSBcIlxcdFwiKSB7XG4gICAgICAgICAgdmFyIHRhYlNpemUgPSBidWlsZGVyLmNtLm9wdGlvbnMudGFiU2l6ZSwgdGFiV2lkdGggPSB0YWJTaXplIC0gYnVpbGRlci5jb2wgJSB0YWJTaXplO1xuICAgICAgICAgIHR4dCQxID0gY29udGVudC5hcHBlbmRDaGlsZChlbHQoXCJzcGFuXCIsIHNwYWNlU3RyKHRhYldpZHRoKSwgXCJjbS10YWJcIikpO1xuICAgICAgICAgIHR4dCQxLnNldEF0dHJpYnV0ZShcInJvbGVcIiwgXCJwcmVzZW50YXRpb25cIik7XG4gICAgICAgICAgdHh0JDEuc2V0QXR0cmlidXRlKFwiY20tdGV4dFwiLCBcIlxcdFwiKTtcbiAgICAgICAgICBidWlsZGVyLmNvbCArPSB0YWJXaWR0aDtcbiAgICAgICAgfSBlbHNlIGlmIChtWzBdID09IFwiXFxyXCIgfHwgbVswXSA9PSBcIlxcblwiKSB7XG4gICAgICAgICAgdHh0JDEgPSBjb250ZW50LmFwcGVuZENoaWxkKGVsdChcInNwYW5cIiwgbVswXSA9PSBcIlxcclwiID8gXCJcXHUyNDBkXCIgOiBcIlxcdTI0MjRcIiwgXCJjbS1pbnZhbGlkY2hhclwiKSk7XG4gICAgICAgICAgdHh0JDEuc2V0QXR0cmlidXRlKFwiY20tdGV4dFwiLCBtWzBdKTtcbiAgICAgICAgICBidWlsZGVyLmNvbCArPSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHR4dCQxID0gYnVpbGRlci5jbS5vcHRpb25zLnNwZWNpYWxDaGFyUGxhY2Vob2xkZXIobVswXSk7XG4gICAgICAgICAgdHh0JDEuc2V0QXR0cmlidXRlKFwiY20tdGV4dFwiLCBtWzBdKTtcbiAgICAgICAgICBpZiAoaWUgJiYgaWVfdmVyc2lvbiA8IDkpIHsgY29udGVudC5hcHBlbmRDaGlsZChlbHQoXCJzcGFuXCIsIFt0eHQkMV0pKTsgfVxuICAgICAgICAgIGVsc2UgeyBjb250ZW50LmFwcGVuZENoaWxkKHR4dCQxKTsgfVxuICAgICAgICAgIGJ1aWxkZXIuY29sICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgYnVpbGRlci5tYXAucHVzaChidWlsZGVyLnBvcywgYnVpbGRlci5wb3MgKyAxLCB0eHQkMSk7XG4gICAgICAgIGJ1aWxkZXIucG9zKys7XG4gICAgICB9XG4gICAgfVxuICAgIGJ1aWxkZXIudHJhaWxpbmdTcGFjZSA9IGRpc3BsYXlUZXh0LmNoYXJDb2RlQXQodGV4dC5sZW5ndGggLSAxKSA9PSAzMjtcbiAgICBpZiAoc3R5bGUgfHwgc3RhcnRTdHlsZSB8fCBlbmRTdHlsZSB8fCBtdXN0V3JhcCB8fCBjc3MgfHwgYXR0cmlidXRlcykge1xuICAgICAgdmFyIGZ1bGxTdHlsZSA9IHN0eWxlIHx8IFwiXCI7XG4gICAgICBpZiAoc3RhcnRTdHlsZSkgeyBmdWxsU3R5bGUgKz0gc3RhcnRTdHlsZTsgfVxuICAgICAgaWYgKGVuZFN0eWxlKSB7IGZ1bGxTdHlsZSArPSBlbmRTdHlsZTsgfVxuICAgICAgdmFyIHRva2VuID0gZWx0KFwic3BhblwiLCBbY29udGVudF0sIGZ1bGxTdHlsZSwgY3NzKTtcbiAgICAgIGlmIChhdHRyaWJ1dGVzKSB7XG4gICAgICAgIGZvciAodmFyIGF0dHIgaW4gYXR0cmlidXRlcykgeyBpZiAoYXR0cmlidXRlcy5oYXNPd25Qcm9wZXJ0eShhdHRyKSAmJiBhdHRyICE9IFwic3R5bGVcIiAmJiBhdHRyICE9IFwiY2xhc3NcIilcbiAgICAgICAgICB7IHRva2VuLnNldEF0dHJpYnV0ZShhdHRyLCBhdHRyaWJ1dGVzW2F0dHJdKTsgfSB9XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5jb250ZW50LmFwcGVuZENoaWxkKHRva2VuKVxuICAgIH1cbiAgICBidWlsZGVyLmNvbnRlbnQuYXBwZW5kQ2hpbGQoY29udGVudCk7XG4gIH1cblxuICAvLyBDaGFuZ2Ugc29tZSBzcGFjZXMgdG8gTkJTUCB0byBwcmV2ZW50IHRoZSBicm93c2VyIGZyb20gY29sbGFwc2luZ1xuICAvLyB0cmFpbGluZyBzcGFjZXMgYXQgdGhlIGVuZCBvZiBhIGxpbmUgd2hlbiByZW5kZXJpbmcgdGV4dCAoaXNzdWUgIzEzNjIpLlxuICBmdW5jdGlvbiBzcGxpdFNwYWNlcyh0ZXh0LCB0cmFpbGluZ0JlZm9yZSkge1xuICAgIGlmICh0ZXh0Lmxlbmd0aCA+IDEgJiYgIS8gIC8udGVzdCh0ZXh0KSkgeyByZXR1cm4gdGV4dCB9XG4gICAgdmFyIHNwYWNlQmVmb3JlID0gdHJhaWxpbmdCZWZvcmUsIHJlc3VsdCA9IFwiXCI7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0ZXh0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2ggPSB0ZXh0LmNoYXJBdChpKTtcbiAgICAgIGlmIChjaCA9PSBcIiBcIiAmJiBzcGFjZUJlZm9yZSAmJiAoaSA9PSB0ZXh0Lmxlbmd0aCAtIDEgfHwgdGV4dC5jaGFyQ29kZUF0KGkgKyAxKSA9PSAzMikpXG4gICAgICAgIHsgY2ggPSBcIlxcdTAwYTBcIjsgfVxuICAgICAgcmVzdWx0ICs9IGNoO1xuICAgICAgc3BhY2VCZWZvcmUgPSBjaCA9PSBcIiBcIjtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG5cbiAgLy8gV29yayBhcm91bmQgbm9uc2Vuc2UgZGltZW5zaW9ucyBiZWluZyByZXBvcnRlZCBmb3Igc3RyZXRjaGVzIG9mXG4gIC8vIHJpZ2h0LXRvLWxlZnQgdGV4dC5cbiAgZnVuY3Rpb24gYnVpbGRUb2tlbkJhZEJpZGkoaW5uZXIsIG9yZGVyKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChidWlsZGVyLCB0ZXh0LCBzdHlsZSwgc3RhcnRTdHlsZSwgZW5kU3R5bGUsIGNzcywgYXR0cmlidXRlcykge1xuICAgICAgc3R5bGUgPSBzdHlsZSA/IHN0eWxlICsgXCIgY20tZm9yY2UtYm9yZGVyXCIgOiBcImNtLWZvcmNlLWJvcmRlclwiO1xuICAgICAgdmFyIHN0YXJ0ID0gYnVpbGRlci5wb3MsIGVuZCA9IHN0YXJ0ICsgdGV4dC5sZW5ndGg7XG4gICAgICBmb3IgKDs7KSB7XG4gICAgICAgIC8vIEZpbmQgdGhlIHBhcnQgdGhhdCBvdmVybGFwcyB3aXRoIHRoZSBzdGFydCBvZiB0aGlzIHRleHRcbiAgICAgICAgdmFyIHBhcnQgPSAodm9pZCAwKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvcmRlci5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHBhcnQgPSBvcmRlcltpXTtcbiAgICAgICAgICBpZiAocGFydC50byA+IHN0YXJ0ICYmIHBhcnQuZnJvbSA8PSBzdGFydCkgeyBicmVhayB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcnQudG8gPj0gZW5kKSB7IHJldHVybiBpbm5lcihidWlsZGVyLCB0ZXh0LCBzdHlsZSwgc3RhcnRTdHlsZSwgZW5kU3R5bGUsIGNzcywgYXR0cmlidXRlcykgfVxuICAgICAgICBpbm5lcihidWlsZGVyLCB0ZXh0LnNsaWNlKDAsIHBhcnQudG8gLSBzdGFydCksIHN0eWxlLCBzdGFydFN0eWxlLCBudWxsLCBjc3MsIGF0dHJpYnV0ZXMpO1xuICAgICAgICBzdGFydFN0eWxlID0gbnVsbDtcbiAgICAgICAgdGV4dCA9IHRleHQuc2xpY2UocGFydC50byAtIHN0YXJ0KTtcbiAgICAgICAgc3RhcnQgPSBwYXJ0LnRvO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGJ1aWxkQ29sbGFwc2VkU3BhbihidWlsZGVyLCBzaXplLCBtYXJrZXIsIGlnbm9yZVdpZGdldCkge1xuICAgIHZhciB3aWRnZXQgPSAhaWdub3JlV2lkZ2V0ICYmIG1hcmtlci53aWRnZXROb2RlO1xuICAgIGlmICh3aWRnZXQpIHsgYnVpbGRlci5tYXAucHVzaChidWlsZGVyLnBvcywgYnVpbGRlci5wb3MgKyBzaXplLCB3aWRnZXQpOyB9XG4gICAgaWYgKCFpZ25vcmVXaWRnZXQgJiYgYnVpbGRlci5jbS5kaXNwbGF5LmlucHV0Lm5lZWRzQ29udGVudEF0dHJpYnV0ZSkge1xuICAgICAgaWYgKCF3aWRnZXQpXG4gICAgICAgIHsgd2lkZ2V0ID0gYnVpbGRlci5jb250ZW50LmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIpKTsgfVxuICAgICAgd2lkZ2V0LnNldEF0dHJpYnV0ZShcImNtLW1hcmtlclwiLCBtYXJrZXIuaWQpO1xuICAgIH1cbiAgICBpZiAod2lkZ2V0KSB7XG4gICAgICBidWlsZGVyLmNtLmRpc3BsYXkuaW5wdXQuc2V0VW5lZGl0YWJsZSh3aWRnZXQpO1xuICAgICAgYnVpbGRlci5jb250ZW50LmFwcGVuZENoaWxkKHdpZGdldCk7XG4gICAgfVxuICAgIGJ1aWxkZXIucG9zICs9IHNpemU7XG4gICAgYnVpbGRlci50cmFpbGluZ1NwYWNlID0gZmFsc2U7XG4gIH1cblxuICAvLyBPdXRwdXRzIGEgbnVtYmVyIG9mIHNwYW5zIHRvIG1ha2UgdXAgYSBsaW5lLCB0YWtpbmcgaGlnaGxpZ2h0aW5nXG4gIC8vIGFuZCBtYXJrZWQgdGV4dCBpbnRvIGFjY291bnQuXG4gIGZ1bmN0aW9uIGluc2VydExpbmVDb250ZW50KGxpbmUsIGJ1aWxkZXIsIHN0eWxlcykge1xuICAgIHZhciBzcGFucyA9IGxpbmUubWFya2VkU3BhbnMsIGFsbFRleHQgPSBsaW5lLnRleHQsIGF0ID0gMDtcbiAgICBpZiAoIXNwYW5zKSB7XG4gICAgICBmb3IgKHZhciBpJDEgPSAxOyBpJDEgPCBzdHlsZXMubGVuZ3RoOyBpJDErPTIpXG4gICAgICAgIHsgYnVpbGRlci5hZGRUb2tlbihidWlsZGVyLCBhbGxUZXh0LnNsaWNlKGF0LCBhdCA9IHN0eWxlc1tpJDFdKSwgaW50ZXJwcmV0VG9rZW5TdHlsZShzdHlsZXNbaSQxKzFdLCBidWlsZGVyLmNtLm9wdGlvbnMpKTsgfVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgdmFyIGxlbiA9IGFsbFRleHQubGVuZ3RoLCBwb3MgPSAwLCBpID0gMSwgdGV4dCA9IFwiXCIsIHN0eWxlLCBjc3M7XG4gICAgdmFyIG5leHRDaGFuZ2UgPSAwLCBzcGFuU3R5bGUsIHNwYW5FbmRTdHlsZSwgc3BhblN0YXJ0U3R5bGUsIGNvbGxhcHNlZCwgYXR0cmlidXRlcztcbiAgICBmb3IgKDs7KSB7XG4gICAgICBpZiAobmV4dENoYW5nZSA9PSBwb3MpIHsgLy8gVXBkYXRlIGN1cnJlbnQgbWFya2VyIHNldFxuICAgICAgICBzcGFuU3R5bGUgPSBzcGFuRW5kU3R5bGUgPSBzcGFuU3RhcnRTdHlsZSA9IGNzcyA9IFwiXCI7XG4gICAgICAgIGF0dHJpYnV0ZXMgPSBudWxsO1xuICAgICAgICBjb2xsYXBzZWQgPSBudWxsOyBuZXh0Q2hhbmdlID0gSW5maW5pdHk7XG4gICAgICAgIHZhciBmb3VuZEJvb2ttYXJrcyA9IFtdLCBlbmRTdHlsZXMgPSAodm9pZCAwKTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBzcGFucy5sZW5ndGg7ICsraikge1xuICAgICAgICAgIHZhciBzcCA9IHNwYW5zW2pdLCBtID0gc3AubWFya2VyO1xuICAgICAgICAgIGlmIChtLnR5cGUgPT0gXCJib29rbWFya1wiICYmIHNwLmZyb20gPT0gcG9zICYmIG0ud2lkZ2V0Tm9kZSkge1xuICAgICAgICAgICAgZm91bmRCb29rbWFya3MucHVzaChtKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHNwLmZyb20gPD0gcG9zICYmIChzcC50byA9PSBudWxsIHx8IHNwLnRvID4gcG9zIHx8IG0uY29sbGFwc2VkICYmIHNwLnRvID09IHBvcyAmJiBzcC5mcm9tID09IHBvcykpIHtcbiAgICAgICAgICAgIGlmIChzcC50byAhPSBudWxsICYmIHNwLnRvICE9IHBvcyAmJiBuZXh0Q2hhbmdlID4gc3AudG8pIHtcbiAgICAgICAgICAgICAgbmV4dENoYW5nZSA9IHNwLnRvO1xuICAgICAgICAgICAgICBzcGFuRW5kU3R5bGUgPSBcIlwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG0uY2xhc3NOYW1lKSB7IHNwYW5TdHlsZSArPSBcIiBcIiArIG0uY2xhc3NOYW1lOyB9XG4gICAgICAgICAgICBpZiAobS5jc3MpIHsgY3NzID0gKGNzcyA/IGNzcyArIFwiO1wiIDogXCJcIikgKyBtLmNzczsgfVxuICAgICAgICAgICAgaWYgKG0uc3RhcnRTdHlsZSAmJiBzcC5mcm9tID09IHBvcykgeyBzcGFuU3RhcnRTdHlsZSArPSBcIiBcIiArIG0uc3RhcnRTdHlsZTsgfVxuICAgICAgICAgICAgaWYgKG0uZW5kU3R5bGUgJiYgc3AudG8gPT0gbmV4dENoYW5nZSkgeyAoZW5kU3R5bGVzIHx8IChlbmRTdHlsZXMgPSBbXSkpLnB1c2gobS5lbmRTdHlsZSwgc3AudG8pOyB9XG4gICAgICAgICAgICAvLyBzdXBwb3J0IGZvciB0aGUgb2xkIHRpdGxlIHByb3BlcnR5XG4gICAgICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vY29kZW1pcnJvci9Db2RlTWlycm9yL3B1bGwvNTY3M1xuICAgICAgICAgICAgaWYgKG0udGl0bGUpIHsgKGF0dHJpYnV0ZXMgfHwgKGF0dHJpYnV0ZXMgPSB7fSkpLnRpdGxlID0gbS50aXRsZTsgfVxuICAgICAgICAgICAgaWYgKG0uYXR0cmlidXRlcykge1xuICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyIGluIG0uYXR0cmlidXRlcylcbiAgICAgICAgICAgICAgICB7IChhdHRyaWJ1dGVzIHx8IChhdHRyaWJ1dGVzID0ge30pKVthdHRyXSA9IG0uYXR0cmlidXRlc1thdHRyXTsgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG0uY29sbGFwc2VkICYmICghY29sbGFwc2VkIHx8IGNvbXBhcmVDb2xsYXBzZWRNYXJrZXJzKGNvbGxhcHNlZC5tYXJrZXIsIG0pIDwgMCkpXG4gICAgICAgICAgICAgIHsgY29sbGFwc2VkID0gc3A7IH1cbiAgICAgICAgICB9IGVsc2UgaWYgKHNwLmZyb20gPiBwb3MgJiYgbmV4dENoYW5nZSA+IHNwLmZyb20pIHtcbiAgICAgICAgICAgIG5leHRDaGFuZ2UgPSBzcC5mcm9tO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoZW5kU3R5bGVzKSB7IGZvciAodmFyIGokMSA9IDA7IGokMSA8IGVuZFN0eWxlcy5sZW5ndGg7IGokMSArPSAyKVxuICAgICAgICAgIHsgaWYgKGVuZFN0eWxlc1tqJDEgKyAxXSA9PSBuZXh0Q2hhbmdlKSB7IHNwYW5FbmRTdHlsZSArPSBcIiBcIiArIGVuZFN0eWxlc1tqJDFdOyB9IH0gfVxuXG4gICAgICAgIGlmICghY29sbGFwc2VkIHx8IGNvbGxhcHNlZC5mcm9tID09IHBvcykgeyBmb3IgKHZhciBqJDIgPSAwOyBqJDIgPCBmb3VuZEJvb2ttYXJrcy5sZW5ndGg7ICsraiQyKVxuICAgICAgICAgIHsgYnVpbGRDb2xsYXBzZWRTcGFuKGJ1aWxkZXIsIDAsIGZvdW5kQm9va21hcmtzW2okMl0pOyB9IH1cbiAgICAgICAgaWYgKGNvbGxhcHNlZCAmJiAoY29sbGFwc2VkLmZyb20gfHwgMCkgPT0gcG9zKSB7XG4gICAgICAgICAgYnVpbGRDb2xsYXBzZWRTcGFuKGJ1aWxkZXIsIChjb2xsYXBzZWQudG8gPT0gbnVsbCA/IGxlbiArIDEgOiBjb2xsYXBzZWQudG8pIC0gcG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZWQubWFya2VyLCBjb2xsYXBzZWQuZnJvbSA9PSBudWxsKTtcbiAgICAgICAgICBpZiAoY29sbGFwc2VkLnRvID09IG51bGwpIHsgcmV0dXJuIH1cbiAgICAgICAgICBpZiAoY29sbGFwc2VkLnRvID09IHBvcykgeyBjb2xsYXBzZWQgPSBmYWxzZTsgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAocG9zID49IGxlbikgeyBicmVhayB9XG5cbiAgICAgIHZhciB1cHRvID0gTWF0aC5taW4obGVuLCBuZXh0Q2hhbmdlKTtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGlmICh0ZXh0KSB7XG4gICAgICAgICAgdmFyIGVuZCA9IHBvcyArIHRleHQubGVuZ3RoO1xuICAgICAgICAgIGlmICghY29sbGFwc2VkKSB7XG4gICAgICAgICAgICB2YXIgdG9rZW5UZXh0ID0gZW5kID4gdXB0byA/IHRleHQuc2xpY2UoMCwgdXB0byAtIHBvcykgOiB0ZXh0O1xuICAgICAgICAgICAgYnVpbGRlci5hZGRUb2tlbihidWlsZGVyLCB0b2tlblRleHQsIHN0eWxlID8gc3R5bGUgKyBzcGFuU3R5bGUgOiBzcGFuU3R5bGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwYW5TdGFydFN0eWxlLCBwb3MgKyB0b2tlblRleHQubGVuZ3RoID09IG5leHRDaGFuZ2UgPyBzcGFuRW5kU3R5bGUgOiBcIlwiLCBjc3MsIGF0dHJpYnV0ZXMpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZW5kID49IHVwdG8pIHt0ZXh0ID0gdGV4dC5zbGljZSh1cHRvIC0gcG9zKTsgcG9zID0gdXB0bzsgYnJlYWt9XG4gICAgICAgICAgcG9zID0gZW5kO1xuICAgICAgICAgIHNwYW5TdGFydFN0eWxlID0gXCJcIjtcbiAgICAgICAgfVxuICAgICAgICB0ZXh0ID0gYWxsVGV4dC5zbGljZShhdCwgYXQgPSBzdHlsZXNbaSsrXSk7XG4gICAgICAgIHN0eWxlID0gaW50ZXJwcmV0VG9rZW5TdHlsZShzdHlsZXNbaSsrXSwgYnVpbGRlci5jbS5vcHRpb25zKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuXG4gIC8vIFRoZXNlIG9iamVjdHMgYXJlIHVzZWQgdG8gcmVwcmVzZW50IHRoZSB2aXNpYmxlIChjdXJyZW50bHkgZHJhd24pXG4gIC8vIHBhcnQgb2YgdGhlIGRvY3VtZW50LiBBIExpbmVWaWV3IG1heSBjb3JyZXNwb25kIHRvIG11bHRpcGxlXG4gIC8vIGxvZ2ljYWwgbGluZXMsIGlmIHRob3NlIGFyZSBjb25uZWN0ZWQgYnkgY29sbGFwc2VkIHJhbmdlcy5cbiAgZnVuY3Rpb24gTGluZVZpZXcoZG9jLCBsaW5lLCBsaW5lTikge1xuICAgIC8vIFRoZSBzdGFydGluZyBsaW5lXG4gICAgdGhpcy5saW5lID0gbGluZTtcbiAgICAvLyBDb250aW51aW5nIGxpbmVzLCBpZiBhbnlcbiAgICB0aGlzLnJlc3QgPSB2aXN1YWxMaW5lQ29udGludWVkKGxpbmUpO1xuICAgIC8vIE51bWJlciBvZiBsb2dpY2FsIGxpbmVzIGluIHRoaXMgdmlzdWFsIGxpbmVcbiAgICB0aGlzLnNpemUgPSB0aGlzLnJlc3QgPyBsaW5lTm8obHN0KHRoaXMucmVzdCkpIC0gbGluZU4gKyAxIDogMTtcbiAgICB0aGlzLm5vZGUgPSB0aGlzLnRleHQgPSBudWxsO1xuICAgIHRoaXMuaGlkZGVuID0gbGluZUlzSGlkZGVuKGRvYywgbGluZSk7XG4gIH1cblxuICAvLyBDcmVhdGUgYSByYW5nZSBvZiBMaW5lVmlldyBvYmplY3RzIGZvciB0aGUgZ2l2ZW4gbGluZXMuXG4gIGZ1bmN0aW9uIGJ1aWxkVmlld0FycmF5KGNtLCBmcm9tLCB0bykge1xuICAgIHZhciBhcnJheSA9IFtdLCBuZXh0UG9zO1xuICAgIGZvciAodmFyIHBvcyA9IGZyb207IHBvcyA8IHRvOyBwb3MgPSBuZXh0UG9zKSB7XG4gICAgICB2YXIgdmlldyA9IG5ldyBMaW5lVmlldyhjbS5kb2MsIGdldExpbmUoY20uZG9jLCBwb3MpLCBwb3MpO1xuICAgICAgbmV4dFBvcyA9IHBvcyArIHZpZXcuc2l6ZTtcbiAgICAgIGFycmF5LnB1c2godmlldyk7XG4gICAgfVxuICAgIHJldHVybiBhcnJheVxuICB9XG5cbiAgdmFyIG9wZXJhdGlvbkdyb3VwID0gbnVsbDtcblxuICBmdW5jdGlvbiBwdXNoT3BlcmF0aW9uKG9wKSB7XG4gICAgaWYgKG9wZXJhdGlvbkdyb3VwKSB7XG4gICAgICBvcGVyYXRpb25Hcm91cC5vcHMucHVzaChvcCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG9wLm93bnNHcm91cCA9IG9wZXJhdGlvbkdyb3VwID0ge1xuICAgICAgICBvcHM6IFtvcF0sXG4gICAgICAgIGRlbGF5ZWRDYWxsYmFja3M6IFtdXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGZpcmVDYWxsYmFja3NGb3JPcHMoZ3JvdXApIHtcbiAgICAvLyBDYWxscyBkZWxheWVkIGNhbGxiYWNrcyBhbmQgY3Vyc29yQWN0aXZpdHkgaGFuZGxlcnMgdW50aWwgbm9cbiAgICAvLyBuZXcgb25lcyBhcHBlYXJcbiAgICB2YXIgY2FsbGJhY2tzID0gZ3JvdXAuZGVsYXllZENhbGxiYWNrcywgaSA9IDA7XG4gICAgZG8ge1xuICAgICAgZm9yICg7IGkgPCBjYWxsYmFja3MubGVuZ3RoOyBpKyspXG4gICAgICAgIHsgY2FsbGJhY2tzW2ldLmNhbGwobnVsbCk7IH1cbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgZ3JvdXAub3BzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIHZhciBvcCA9IGdyb3VwLm9wc1tqXTtcbiAgICAgICAgaWYgKG9wLmN1cnNvckFjdGl2aXR5SGFuZGxlcnMpXG4gICAgICAgICAgeyB3aGlsZSAob3AuY3Vyc29yQWN0aXZpdHlDYWxsZWQgPCBvcC5jdXJzb3JBY3Rpdml0eUhhbmRsZXJzLmxlbmd0aClcbiAgICAgICAgICAgIHsgb3AuY3Vyc29yQWN0aXZpdHlIYW5kbGVyc1tvcC5jdXJzb3JBY3Rpdml0eUNhbGxlZCsrXS5jYWxsKG51bGwsIG9wLmNtKTsgfSB9XG4gICAgICB9XG4gICAgfSB3aGlsZSAoaSA8IGNhbGxiYWNrcy5sZW5ndGgpXG4gIH1cblxuICBmdW5jdGlvbiBmaW5pc2hPcGVyYXRpb24ob3AsIGVuZENiKSB7XG4gICAgdmFyIGdyb3VwID0gb3Aub3duc0dyb3VwO1xuICAgIGlmICghZ3JvdXApIHsgcmV0dXJuIH1cblxuICAgIHRyeSB7IGZpcmVDYWxsYmFja3NGb3JPcHMoZ3JvdXApOyB9XG4gICAgZmluYWxseSB7XG4gICAgICBvcGVyYXRpb25Hcm91cCA9IG51bGw7XG4gICAgICBlbmRDYihncm91cCk7XG4gICAgfVxuICB9XG5cbiAgdmFyIG9ycGhhbkRlbGF5ZWRDYWxsYmFja3MgPSBudWxsO1xuXG4gIC8vIE9mdGVuLCB3ZSB3YW50IHRvIHNpZ25hbCBldmVudHMgYXQgYSBwb2ludCB3aGVyZSB3ZSBhcmUgaW4gdGhlXG4gIC8vIG1pZGRsZSBvZiBzb21lIHdvcmssIGJ1dCBkb24ndCB3YW50IHRoZSBoYW5kbGVyIHRvIHN0YXJ0IGNhbGxpbmdcbiAgLy8gb3RoZXIgbWV0aG9kcyBvbiB0aGUgZWRpdG9yLCB3aGljaCBtaWdodCBiZSBpbiBhbiBpbmNvbnNpc3RlbnRcbiAgLy8gc3RhdGUgb3Igc2ltcGx5IG5vdCBleHBlY3QgYW55IG90aGVyIGV2ZW50cyB0byBoYXBwZW4uXG4gIC8vIHNpZ25hbExhdGVyIGxvb2tzIHdoZXRoZXIgdGhlcmUgYXJlIGFueSBoYW5kbGVycywgYW5kIHNjaGVkdWxlc1xuICAvLyB0aGVtIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIGxhc3Qgb3BlcmF0aW9uIGVuZHMsIG9yLCBpZiBub1xuICAvLyBvcGVyYXRpb24gaXMgYWN0aXZlLCB3aGVuIGEgdGltZW91dCBmaXJlcy5cbiAgZnVuY3Rpb24gc2lnbmFsTGF0ZXIoZW1pdHRlciwgdHlwZSAvKiwgdmFsdWVzLi4uKi8pIHtcbiAgICB2YXIgYXJyID0gZ2V0SGFuZGxlcnMoZW1pdHRlciwgdHlwZSk7XG4gICAgaWYgKCFhcnIubGVuZ3RoKSB7IHJldHVybiB9XG4gICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpLCBsaXN0O1xuICAgIGlmIChvcGVyYXRpb25Hcm91cCkge1xuICAgICAgbGlzdCA9IG9wZXJhdGlvbkdyb3VwLmRlbGF5ZWRDYWxsYmFja3M7XG4gICAgfSBlbHNlIGlmIChvcnBoYW5EZWxheWVkQ2FsbGJhY2tzKSB7XG4gICAgICBsaXN0ID0gb3JwaGFuRGVsYXllZENhbGxiYWNrcztcbiAgICB9IGVsc2Uge1xuICAgICAgbGlzdCA9IG9ycGhhbkRlbGF5ZWRDYWxsYmFja3MgPSBbXTtcbiAgICAgIHNldFRpbWVvdXQoZmlyZU9ycGhhbkRlbGF5ZWQsIDApO1xuICAgIH1cbiAgICB2YXIgbG9vcCA9IGZ1bmN0aW9uICggaSApIHtcbiAgICAgIGxpc3QucHVzaChmdW5jdGlvbiAoKSB7IHJldHVybiBhcnJbaV0uYXBwbHkobnVsbCwgYXJncyk7IH0pO1xuICAgIH07XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyci5sZW5ndGg7ICsraSlcbiAgICAgIGxvb3AoIGkgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpcmVPcnBoYW5EZWxheWVkKCkge1xuICAgIHZhciBkZWxheWVkID0gb3JwaGFuRGVsYXllZENhbGxiYWNrcztcbiAgICBvcnBoYW5EZWxheWVkQ2FsbGJhY2tzID0gbnVsbDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRlbGF5ZWQubGVuZ3RoOyArK2kpIHsgZGVsYXllZFtpXSgpOyB9XG4gIH1cblxuICAvLyBXaGVuIGFuIGFzcGVjdCBvZiBhIGxpbmUgY2hhbmdlcywgYSBzdHJpbmcgaXMgYWRkZWQgdG9cbiAgLy8gbGluZVZpZXcuY2hhbmdlcy4gVGhpcyB1cGRhdGVzIHRoZSByZWxldmFudCBwYXJ0IG9mIHRoZSBsaW5lJ3NcbiAgLy8gRE9NIHN0cnVjdHVyZS5cbiAgZnVuY3Rpb24gdXBkYXRlTGluZUZvckNoYW5nZXMoY20sIGxpbmVWaWV3LCBsaW5lTiwgZGltcykge1xuICAgIGZvciAodmFyIGogPSAwOyBqIDwgbGluZVZpZXcuY2hhbmdlcy5sZW5ndGg7IGorKykge1xuICAgICAgdmFyIHR5cGUgPSBsaW5lVmlldy5jaGFuZ2VzW2pdO1xuICAgICAgaWYgKHR5cGUgPT0gXCJ0ZXh0XCIpIHsgdXBkYXRlTGluZVRleHQoY20sIGxpbmVWaWV3KTsgfVxuICAgICAgZWxzZSBpZiAodHlwZSA9PSBcImd1dHRlclwiKSB7IHVwZGF0ZUxpbmVHdXR0ZXIoY20sIGxpbmVWaWV3LCBsaW5lTiwgZGltcyk7IH1cbiAgICAgIGVsc2UgaWYgKHR5cGUgPT0gXCJjbGFzc1wiKSB7IHVwZGF0ZUxpbmVDbGFzc2VzKGNtLCBsaW5lVmlldyk7IH1cbiAgICAgIGVsc2UgaWYgKHR5cGUgPT0gXCJ3aWRnZXRcIikgeyB1cGRhdGVMaW5lV2lkZ2V0cyhjbSwgbGluZVZpZXcsIGRpbXMpOyB9XG4gICAgfVxuICAgIGxpbmVWaWV3LmNoYW5nZXMgPSBudWxsO1xuICB9XG5cbiAgLy8gTGluZXMgd2l0aCBndXR0ZXIgZWxlbWVudHMsIHdpZGdldHMgb3IgYSBiYWNrZ3JvdW5kIGNsYXNzIG5lZWQgdG9cbiAgLy8gYmUgd3JhcHBlZCwgYW5kIGhhdmUgdGhlIGV4dHJhIGVsZW1lbnRzIGFkZGVkIHRvIHRoZSB3cmFwcGVyIGRpdlxuICBmdW5jdGlvbiBlbnN1cmVMaW5lV3JhcHBlZChsaW5lVmlldykge1xuICAgIGlmIChsaW5lVmlldy5ub2RlID09IGxpbmVWaWV3LnRleHQpIHtcbiAgICAgIGxpbmVWaWV3Lm5vZGUgPSBlbHQoXCJkaXZcIiwgbnVsbCwgbnVsbCwgXCJwb3NpdGlvbjogcmVsYXRpdmVcIik7XG4gICAgICBpZiAobGluZVZpZXcudGV4dC5wYXJlbnROb2RlKVxuICAgICAgICB7IGxpbmVWaWV3LnRleHQucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobGluZVZpZXcubm9kZSwgbGluZVZpZXcudGV4dCk7IH1cbiAgICAgIGxpbmVWaWV3Lm5vZGUuYXBwZW5kQ2hpbGQobGluZVZpZXcudGV4dCk7XG4gICAgICBpZiAoaWUgJiYgaWVfdmVyc2lvbiA8IDgpIHsgbGluZVZpZXcubm9kZS5zdHlsZS56SW5kZXggPSAyOyB9XG4gICAgfVxuICAgIHJldHVybiBsaW5lVmlldy5ub2RlXG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGVMaW5lQmFja2dyb3VuZChjbSwgbGluZVZpZXcpIHtcbiAgICB2YXIgY2xzID0gbGluZVZpZXcuYmdDbGFzcyA/IGxpbmVWaWV3LmJnQ2xhc3MgKyBcIiBcIiArIChsaW5lVmlldy5saW5lLmJnQ2xhc3MgfHwgXCJcIikgOiBsaW5lVmlldy5saW5lLmJnQ2xhc3M7XG4gICAgaWYgKGNscykgeyBjbHMgKz0gXCIgQ29kZU1pcnJvci1saW5lYmFja2dyb3VuZFwiOyB9XG4gICAgaWYgKGxpbmVWaWV3LmJhY2tncm91bmQpIHtcbiAgICAgIGlmIChjbHMpIHsgbGluZVZpZXcuYmFja2dyb3VuZC5jbGFzc05hbWUgPSBjbHM7IH1cbiAgICAgIGVsc2UgeyBsaW5lVmlldy5iYWNrZ3JvdW5kLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQobGluZVZpZXcuYmFja2dyb3VuZCk7IGxpbmVWaWV3LmJhY2tncm91bmQgPSBudWxsOyB9XG4gICAgfSBlbHNlIGlmIChjbHMpIHtcbiAgICAgIHZhciB3cmFwID0gZW5zdXJlTGluZVdyYXBwZWQobGluZVZpZXcpO1xuICAgICAgbGluZVZpZXcuYmFja2dyb3VuZCA9IHdyYXAuaW5zZXJ0QmVmb3JlKGVsdChcImRpdlwiLCBudWxsLCBjbHMpLCB3cmFwLmZpcnN0Q2hpbGQpO1xuICAgICAgY20uZGlzcGxheS5pbnB1dC5zZXRVbmVkaXRhYmxlKGxpbmVWaWV3LmJhY2tncm91bmQpO1xuICAgIH1cbiAgfVxuXG4gIC8vIFdyYXBwZXIgYXJvdW5kIGJ1aWxkTGluZUNvbnRlbnQgd2hpY2ggd2lsbCByZXVzZSB0aGUgc3RydWN0dXJlXG4gIC8vIGluIGRpc3BsYXkuZXh0ZXJuYWxNZWFzdXJlZCB3aGVuIHBvc3NpYmxlLlxuICBmdW5jdGlvbiBnZXRMaW5lQ29udGVudChjbSwgbGluZVZpZXcpIHtcbiAgICB2YXIgZXh0ID0gY20uZGlzcGxheS5leHRlcm5hbE1lYXN1cmVkO1xuICAgIGlmIChleHQgJiYgZXh0LmxpbmUgPT0gbGluZVZpZXcubGluZSkge1xuICAgICAgY20uZGlzcGxheS5leHRlcm5hbE1lYXN1cmVkID0gbnVsbDtcbiAgICAgIGxpbmVWaWV3Lm1lYXN1cmUgPSBleHQubWVhc3VyZTtcbiAgICAgIHJldHVybiBleHQuYnVpbHRcbiAgICB9XG4gICAgcmV0dXJuIGJ1aWxkTGluZUNvbnRlbnQoY20sIGxpbmVWaWV3KVxuICB9XG5cbiAgLy8gUmVkcmF3IHRoZSBsaW5lJ3MgdGV4dC4gSW50ZXJhY3RzIHdpdGggdGhlIGJhY2tncm91bmQgYW5kIHRleHRcbiAgLy8gY2xhc3NlcyBiZWNhdXNlIHRoZSBtb2RlIG1heSBvdXRwdXQgdG9rZW5zIHRoYXQgaW5mbHVlbmNlIHRoZXNlXG4gIC8vIGNsYXNzZXMuXG4gIGZ1bmN0aW9uIHVwZGF0ZUxpbmVUZXh0KGNtLCBsaW5lVmlldykge1xuICAgIHZhciBjbHMgPSBsaW5lVmlldy50ZXh0LmNsYXNzTmFtZTtcbiAgICB2YXIgYnVpbHQgPSBnZXRMaW5lQ29udGVudChjbSwgbGluZVZpZXcpO1xuICAgIGlmIChsaW5lVmlldy50ZXh0ID09IGxpbmVWaWV3Lm5vZGUpIHsgbGluZVZpZXcubm9kZSA9IGJ1aWx0LnByZTsgfVxuICAgIGxpbmVWaWV3LnRleHQucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQoYnVpbHQucHJlLCBsaW5lVmlldy50ZXh0KTtcbiAgICBsaW5lVmlldy50ZXh0ID0gYnVpbHQucHJlO1xuICAgIGlmIChidWlsdC5iZ0NsYXNzICE9IGxpbmVWaWV3LmJnQ2xhc3MgfHwgYnVpbHQudGV4dENsYXNzICE9IGxpbmVWaWV3LnRleHRDbGFzcykge1xuICAgICAgbGluZVZpZXcuYmdDbGFzcyA9IGJ1aWx0LmJnQ2xhc3M7XG4gICAgICBsaW5lVmlldy50ZXh0Q2xhc3MgPSBidWlsdC50ZXh0Q2xhc3M7XG4gICAgICB1cGRhdGVMaW5lQ2xhc3NlcyhjbSwgbGluZVZpZXcpO1xuICAgIH0gZWxzZSBpZiAoY2xzKSB7XG4gICAgICBsaW5lVmlldy50ZXh0LmNsYXNzTmFtZSA9IGNscztcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGVMaW5lQ2xhc3NlcyhjbSwgbGluZVZpZXcpIHtcbiAgICB1cGRhdGVMaW5lQmFja2dyb3VuZChjbSwgbGluZVZpZXcpO1xuICAgIGlmIChsaW5lVmlldy5saW5lLndyYXBDbGFzcylcbiAgICAgIHsgZW5zdXJlTGluZVdyYXBwZWQobGluZVZpZXcpLmNsYXNzTmFtZSA9IGxpbmVWaWV3LmxpbmUud3JhcENsYXNzOyB9XG4gICAgZWxzZSBpZiAobGluZVZpZXcubm9kZSAhPSBsaW5lVmlldy50ZXh0KVxuICAgICAgeyBsaW5lVmlldy5ub2RlLmNsYXNzTmFtZSA9IFwiXCI7IH1cbiAgICB2YXIgdGV4dENsYXNzID0gbGluZVZpZXcudGV4dENsYXNzID8gbGluZVZpZXcudGV4dENsYXNzICsgXCIgXCIgKyAobGluZVZpZXcubGluZS50ZXh0Q2xhc3MgfHwgXCJcIikgOiBsaW5lVmlldy5saW5lLnRleHRDbGFzcztcbiAgICBsaW5lVmlldy50ZXh0LmNsYXNzTmFtZSA9IHRleHRDbGFzcyB8fCBcIlwiO1xuICB9XG5cbiAgZnVuY3Rpb24gdXBkYXRlTGluZUd1dHRlcihjbSwgbGluZVZpZXcsIGxpbmVOLCBkaW1zKSB7XG4gICAgaWYgKGxpbmVWaWV3Lmd1dHRlcikge1xuICAgICAgbGluZVZpZXcubm9kZS5yZW1vdmVDaGlsZChsaW5lVmlldy5ndXR0ZXIpO1xuICAgICAgbGluZVZpZXcuZ3V0dGVyID0gbnVsbDtcbiAgICB9XG4gICAgaWYgKGxpbmVWaWV3Lmd1dHRlckJhY2tncm91bmQpIHtcbiAgICAgIGxpbmVWaWV3Lm5vZGUucmVtb3ZlQ2hpbGQobGluZVZpZXcuZ3V0dGVyQmFja2dyb3VuZCk7XG4gICAgICBsaW5lVmlldy5ndXR0ZXJCYWNrZ3JvdW5kID0gbnVsbDtcbiAgICB9XG4gICAgaWYgKGxpbmVWaWV3LmxpbmUuZ3V0dGVyQ2xhc3MpIHtcbiAgICAgIHZhciB3cmFwID0gZW5zdXJlTGluZVdyYXBwZWQobGluZVZpZXcpO1xuICAgICAgbGluZVZpZXcuZ3V0dGVyQmFja2dyb3VuZCA9IGVsdChcImRpdlwiLCBudWxsLCBcIkNvZGVNaXJyb3ItZ3V0dGVyLWJhY2tncm91bmQgXCIgKyBsaW5lVmlldy5saW5lLmd1dHRlckNsYXNzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoXCJsZWZ0OiBcIiArIChjbS5vcHRpb25zLmZpeGVkR3V0dGVyID8gZGltcy5maXhlZFBvcyA6IC1kaW1zLmd1dHRlclRvdGFsV2lkdGgpICsgXCJweDsgd2lkdGg6IFwiICsgKGRpbXMuZ3V0dGVyVG90YWxXaWR0aCkgKyBcInB4XCIpKTtcbiAgICAgIGNtLmRpc3BsYXkuaW5wdXQuc2V0VW5lZGl0YWJsZShsaW5lVmlldy5ndXR0ZXJCYWNrZ3JvdW5kKTtcbiAgICAgIHdyYXAuaW5zZXJ0QmVmb3JlKGxpbmVWaWV3Lmd1dHRlckJhY2tncm91bmQsIGxpbmVWaWV3LnRleHQpO1xuICAgIH1cbiAgICB2YXIgbWFya2VycyA9IGxpbmVWaWV3LmxpbmUuZ3V0dGVyTWFya2VycztcbiAgICBpZiAoY20ub3B0aW9ucy5saW5lTnVtYmVycyB8fCBtYXJrZXJzKSB7XG4gICAgICB2YXIgd3JhcCQxID0gZW5zdXJlTGluZVdyYXBwZWQobGluZVZpZXcpO1xuICAgICAgdmFyIGd1dHRlcldyYXAgPSBsaW5lVmlldy5ndXR0ZXIgPSBlbHQoXCJkaXZcIiwgbnVsbCwgXCJDb2RlTWlycm9yLWd1dHRlci13cmFwcGVyXCIsIChcImxlZnQ6IFwiICsgKGNtLm9wdGlvbnMuZml4ZWRHdXR0ZXIgPyBkaW1zLmZpeGVkUG9zIDogLWRpbXMuZ3V0dGVyVG90YWxXaWR0aCkgKyBcInB4XCIpKTtcbiAgICAgIGd1dHRlcldyYXAuc2V0QXR0cmlidXRlKFwiYXJpYS1oaWRkZW5cIiwgXCJ0cnVlXCIpO1xuICAgICAgY20uZGlzcGxheS5pbnB1dC5zZXRVbmVkaXRhYmxlKGd1dHRlcldyYXApO1xuICAgICAgd3JhcCQxLmluc2VydEJlZm9yZShndXR0ZXJXcmFwLCBsaW5lVmlldy50ZXh0KTtcbiAgICAgIGlmIChsaW5lVmlldy5saW5lLmd1dHRlckNsYXNzKVxuICAgICAgICB7IGd1dHRlcldyYXAuY2xhc3NOYW1lICs9IFwiIFwiICsgbGluZVZpZXcubGluZS5ndXR0ZXJDbGFzczsgfVxuICAgICAgaWYgKGNtLm9wdGlvbnMubGluZU51bWJlcnMgJiYgKCFtYXJrZXJzIHx8ICFtYXJrZXJzW1wiQ29kZU1pcnJvci1saW5lbnVtYmVyc1wiXSkpXG4gICAgICAgIHsgbGluZVZpZXcubGluZU51bWJlciA9IGd1dHRlcldyYXAuYXBwZW5kQ2hpbGQoXG4gICAgICAgICAgZWx0KFwiZGl2XCIsIGxpbmVOdW1iZXJGb3IoY20ub3B0aW9ucywgbGluZU4pLFxuICAgICAgICAgICAgICBcIkNvZGVNaXJyb3ItbGluZW51bWJlciBDb2RlTWlycm9yLWd1dHRlci1lbHRcIixcbiAgICAgICAgICAgICAgKFwibGVmdDogXCIgKyAoZGltcy5ndXR0ZXJMZWZ0W1wiQ29kZU1pcnJvci1saW5lbnVtYmVyc1wiXSkgKyBcInB4OyB3aWR0aDogXCIgKyAoY20uZGlzcGxheS5saW5lTnVtSW5uZXJXaWR0aCkgKyBcInB4XCIpKSk7IH1cbiAgICAgIGlmIChtYXJrZXJzKSB7IGZvciAodmFyIGsgPSAwOyBrIDwgY20uZGlzcGxheS5ndXR0ZXJTcGVjcy5sZW5ndGg7ICsraykge1xuICAgICAgICB2YXIgaWQgPSBjbS5kaXNwbGF5Lmd1dHRlclNwZWNzW2tdLmNsYXNzTmFtZSwgZm91bmQgPSBtYXJrZXJzLmhhc093blByb3BlcnR5KGlkKSAmJiBtYXJrZXJzW2lkXTtcbiAgICAgICAgaWYgKGZvdW5kKVxuICAgICAgICAgIHsgZ3V0dGVyV3JhcC5hcHBlbmRDaGlsZChlbHQoXCJkaXZcIiwgW2ZvdW5kXSwgXCJDb2RlTWlycm9yLWd1dHRlci1lbHRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoXCJsZWZ0OiBcIiArIChkaW1zLmd1dHRlckxlZnRbaWRdKSArIFwicHg7IHdpZHRoOiBcIiArIChkaW1zLmd1dHRlcldpZHRoW2lkXSkgKyBcInB4XCIpKSk7IH1cbiAgICAgIH0gfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHVwZGF0ZUxpbmVXaWRnZXRzKGNtLCBsaW5lVmlldywgZGltcykge1xuICAgIGlmIChsaW5lVmlldy5hbGlnbmFibGUpIHsgbGluZVZpZXcuYWxpZ25hYmxlID0gbnVsbDsgfVxuICAgIHZhciBpc1dpZGdldCA9IGNsYXNzVGVzdChcIkNvZGVNaXJyb3ItbGluZXdpZGdldFwiKTtcbiAgICBmb3IgKHZhciBub2RlID0gbGluZVZpZXcubm9kZS5maXJzdENoaWxkLCBuZXh0ID0gKHZvaWQgMCk7IG5vZGU7IG5vZGUgPSBuZXh0KSB7XG4gICAgICBuZXh0ID0gbm9kZS5uZXh0U2libGluZztcbiAgICAgIGlmIChpc1dpZGdldC50ZXN0KG5vZGUuY2xhc3NOYW1lKSkgeyBsaW5lVmlldy5ub2RlLnJlbW92ZUNoaWxkKG5vZGUpOyB9XG4gICAgfVxuICAgIGluc2VydExpbmVXaWRnZXRzKGNtLCBsaW5lVmlldywgZGltcyk7XG4gIH1cblxuICAvLyBCdWlsZCBhIGxpbmUncyBET00gcmVwcmVzZW50YXRpb24gZnJvbSBzY3JhdGNoXG4gIGZ1bmN0aW9uIGJ1aWxkTGluZUVsZW1lbnQoY20sIGxpbmVWaWV3LCBsaW5lTiwgZGltcykge1xuICAgIHZhciBidWlsdCA9IGdldExpbmVDb250ZW50KGNtLCBsaW5lVmlldyk7XG4gICAgbGluZVZpZXcudGV4dCA9IGxpbmVWaWV3Lm5vZGUgPSBidWlsdC5wcmU7XG4gICAgaWYgKGJ1aWx0LmJnQ2xhc3MpIHsgbGluZVZpZXcuYmdDbGFzcyA9IGJ1aWx0LmJnQ2xhc3M7IH1cbiAgICBpZiAoYnVpbHQudGV4dENsYXNzKSB7IGxpbmVWaWV3LnRleHRDbGFzcyA9IGJ1aWx0LnRleHRDbGFzczsgfVxuXG4gICAgdXBkYXRlTGluZUNsYXNzZXMoY20sIGxpbmVWaWV3KTtcbiAgICB1cGRhdGVMaW5lR3V0dGVyKGNtLCBsaW5lVmlldywgbGluZU4sIGRpbXMpO1xuICAgIGluc2VydExpbmVXaWRnZXRzKGNtLCBsaW5lVmlldywgZGltcyk7XG4gICAgcmV0dXJuIGxpbmVWaWV3Lm5vZGVcbiAgfVxuXG4gIC8vIEEgbGluZVZpZXcgbWF5IGNvbnRhaW4gbXVsdGlwbGUgbG9naWNhbCBsaW5lcyAod2hlbiBtZXJnZWQgYnlcbiAgLy8gY29sbGFwc2VkIHNwYW5zKS4gVGhlIHdpZGdldHMgZm9yIGFsbCBvZiB0aGVtIG5lZWQgdG8gYmUgZHJhd24uXG4gIGZ1bmN0aW9uIGluc2VydExpbmVXaWRnZXRzKGNtLCBsaW5lVmlldywgZGltcykge1xuICAgIGluc2VydExpbmVXaWRnZXRzRm9yKGNtLCBsaW5lVmlldy5saW5lLCBsaW5lVmlldywgZGltcywgdHJ1ZSk7XG4gICAgaWYgKGxpbmVWaWV3LnJlc3QpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lVmlldy5yZXN0Lmxlbmd0aDsgaSsrKVxuICAgICAgeyBpbnNlcnRMaW5lV2lkZ2V0c0ZvcihjbSwgbGluZVZpZXcucmVzdFtpXSwgbGluZVZpZXcsIGRpbXMsIGZhbHNlKTsgfSB9XG4gIH1cblxuICBmdW5jdGlvbiBpbnNlcnRMaW5lV2lkZ2V0c0ZvcihjbSwgbGluZSwgbGluZVZpZXcsIGRpbXMsIGFsbG93QWJvdmUpIHtcbiAgICBpZiAoIWxpbmUud2lkZ2V0cykgeyByZXR1cm4gfVxuICAgIHZhciB3cmFwID0gZW5zdXJlTGluZVdyYXBwZWQobGluZVZpZXcpO1xuICAgIGZvciAodmFyIGkgPSAwLCB3cyA9IGxpbmUud2lkZ2V0czsgaSA8IHdzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgd2lkZ2V0ID0gd3NbaV0sIG5vZGUgPSBlbHQoXCJkaXZcIiwgW3dpZGdldC5ub2RlXSwgXCJDb2RlTWlycm9yLWxpbmV3aWRnZXRcIiArICh3aWRnZXQuY2xhc3NOYW1lID8gXCIgXCIgKyB3aWRnZXQuY2xhc3NOYW1lIDogXCJcIikpO1xuICAgICAgaWYgKCF3aWRnZXQuaGFuZGxlTW91c2VFdmVudHMpIHsgbm9kZS5zZXRBdHRyaWJ1dGUoXCJjbS1pZ25vcmUtZXZlbnRzXCIsIFwidHJ1ZVwiKTsgfVxuICAgICAgcG9zaXRpb25MaW5lV2lkZ2V0KHdpZGdldCwgbm9kZSwgbGluZVZpZXcsIGRpbXMpO1xuICAgICAgY20uZGlzcGxheS5pbnB1dC5zZXRVbmVkaXRhYmxlKG5vZGUpO1xuICAgICAgaWYgKGFsbG93QWJvdmUgJiYgd2lkZ2V0LmFib3ZlKVxuICAgICAgICB7IHdyYXAuaW5zZXJ0QmVmb3JlKG5vZGUsIGxpbmVWaWV3Lmd1dHRlciB8fCBsaW5lVmlldy50ZXh0KTsgfVxuICAgICAgZWxzZVxuICAgICAgICB7IHdyYXAuYXBwZW5kQ2hpbGQobm9kZSk7IH1cbiAgICAgIHNpZ25hbExhdGVyKHdpZGdldCwgXCJyZWRyYXdcIik7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcG9zaXRpb25MaW5lV2lkZ2V0KHdpZGdldCwgbm9kZSwgbGluZVZpZXcsIGRpbXMpIHtcbiAgICBpZiAod2lkZ2V0Lm5vSFNjcm9sbCkge1xuICAobGluZVZpZXcuYWxpZ25hYmxlIHx8IChsaW5lVmlldy5hbGlnbmFibGUgPSBbXSkpLnB1c2gobm9kZSk7XG4gICAgICB2YXIgd2lkdGggPSBkaW1zLndyYXBwZXJXaWR0aDtcbiAgICAgIG5vZGUuc3R5bGUubGVmdCA9IGRpbXMuZml4ZWRQb3MgKyBcInB4XCI7XG4gICAgICBpZiAoIXdpZGdldC5jb3Zlckd1dHRlcikge1xuICAgICAgICB3aWR0aCAtPSBkaW1zLmd1dHRlclRvdGFsV2lkdGg7XG4gICAgICAgIG5vZGUuc3R5bGUucGFkZGluZ0xlZnQgPSBkaW1zLmd1dHRlclRvdGFsV2lkdGggKyBcInB4XCI7XG4gICAgICB9XG4gICAgICBub2RlLnN0eWxlLndpZHRoID0gd2lkdGggKyBcInB4XCI7XG4gICAgfVxuICAgIGlmICh3aWRnZXQuY292ZXJHdXR0ZXIpIHtcbiAgICAgIG5vZGUuc3R5bGUuekluZGV4ID0gNTtcbiAgICAgIG5vZGUuc3R5bGUucG9zaXRpb24gPSBcInJlbGF0aXZlXCI7XG4gICAgICBpZiAoIXdpZGdldC5ub0hTY3JvbGwpIHsgbm9kZS5zdHlsZS5tYXJnaW5MZWZ0ID0gLWRpbXMuZ3V0dGVyVG90YWxXaWR0aCArIFwicHhcIjsgfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHdpZGdldEhlaWdodCh3aWRnZXQpIHtcbiAgICBpZiAod2lkZ2V0LmhlaWdodCAhPSBudWxsKSB7IHJldHVybiB3aWRnZXQuaGVpZ2h0IH1cbiAgICB2YXIgY20gPSB3aWRnZXQuZG9jLmNtO1xuICAgIGlmICghY20pIHsgcmV0dXJuIDAgfVxuICAgIGlmICghY29udGFpbnMoZG9jdW1lbnQuYm9keSwgd2lkZ2V0Lm5vZGUpKSB7XG4gICAgICB2YXIgcGFyZW50U3R5bGUgPSBcInBvc2l0aW9uOiByZWxhdGl2ZTtcIjtcbiAgICAgIGlmICh3aWRnZXQuY292ZXJHdXR0ZXIpXG4gICAgICAgIHsgcGFyZW50U3R5bGUgKz0gXCJtYXJnaW4tbGVmdDogLVwiICsgY20uZGlzcGxheS5ndXR0ZXJzLm9mZnNldFdpZHRoICsgXCJweDtcIjsgfVxuICAgICAgaWYgKHdpZGdldC5ub0hTY3JvbGwpXG4gICAgICAgIHsgcGFyZW50U3R5bGUgKz0gXCJ3aWR0aDogXCIgKyBjbS5kaXNwbGF5LndyYXBwZXIuY2xpZW50V2lkdGggKyBcInB4O1wiOyB9XG4gICAgICByZW1vdmVDaGlsZHJlbkFuZEFkZChjbS5kaXNwbGF5Lm1lYXN1cmUsIGVsdChcImRpdlwiLCBbd2lkZ2V0Lm5vZGVdLCBudWxsLCBwYXJlbnRTdHlsZSkpO1xuICAgIH1cbiAgICByZXR1cm4gd2lkZ2V0LmhlaWdodCA9IHdpZGdldC5ub2RlLnBhcmVudE5vZGUub2Zmc2V0SGVpZ2h0XG4gIH1cblxuICAvLyBSZXR1cm4gdHJ1ZSB3aGVuIHRoZSBnaXZlbiBtb3VzZSBldmVudCBoYXBwZW5lZCBpbiBhIHdpZGdldFxuICBmdW5jdGlvbiBldmVudEluV2lkZ2V0KGRpc3BsYXksIGUpIHtcbiAgICBmb3IgKHZhciBuID0gZV90YXJnZXQoZSk7IG4gIT0gZGlzcGxheS53cmFwcGVyOyBuID0gbi5wYXJlbnROb2RlKSB7XG4gICAgICBpZiAoIW4gfHwgKG4ubm9kZVR5cGUgPT0gMSAmJiBuLmdldEF0dHJpYnV0ZShcImNtLWlnbm9yZS1ldmVudHNcIikgPT0gXCJ0cnVlXCIpIHx8XG4gICAgICAgICAgKG4ucGFyZW50Tm9kZSA9PSBkaXNwbGF5LnNpemVyICYmIG4gIT0gZGlzcGxheS5tb3ZlcikpXG4gICAgICAgIHsgcmV0dXJuIHRydWUgfVxuICAgIH1cbiAgfVxuXG4gIC8vIFBPU0lUSU9OIE1FQVNVUkVNRU5UXG5cbiAgZnVuY3Rpb24gcGFkZGluZ1RvcChkaXNwbGF5KSB7cmV0dXJuIGRpc3BsYXkubGluZVNwYWNlLm9mZnNldFRvcH1cbiAgZnVuY3Rpb24gcGFkZGluZ1ZlcnQoZGlzcGxheSkge3JldHVybiBkaXNwbGF5Lm1vdmVyLm9mZnNldEhlaWdodCAtIGRpc3BsYXkubGluZVNwYWNlLm9mZnNldEhlaWdodH1cbiAgZnVuY3Rpb24gcGFkZGluZ0goZGlzcGxheSkge1xuICAgIGlmIChkaXNwbGF5LmNhY2hlZFBhZGRpbmdIKSB7IHJldHVybiBkaXNwbGF5LmNhY2hlZFBhZGRpbmdIIH1cbiAgICB2YXIgZSA9IHJlbW92ZUNoaWxkcmVuQW5kQWRkKGRpc3BsYXkubWVhc3VyZSwgZWx0KFwicHJlXCIsIFwieFwiLCBcIkNvZGVNaXJyb3ItbGluZS1saWtlXCIpKTtcbiAgICB2YXIgc3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSA/IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGUpIDogZS5jdXJyZW50U3R5bGU7XG4gICAgdmFyIGRhdGEgPSB7bGVmdDogcGFyc2VJbnQoc3R5bGUucGFkZGluZ0xlZnQpLCByaWdodDogcGFyc2VJbnQoc3R5bGUucGFkZGluZ1JpZ2h0KX07XG4gICAgaWYgKCFpc05hTihkYXRhLmxlZnQpICYmICFpc05hTihkYXRhLnJpZ2h0KSkgeyBkaXNwbGF5LmNhY2hlZFBhZGRpbmdIID0gZGF0YTsgfVxuICAgIHJldHVybiBkYXRhXG4gIH1cblxuICBmdW5jdGlvbiBzY3JvbGxHYXAoY20pIHsgcmV0dXJuIHNjcm9sbGVyR2FwIC0gY20uZGlzcGxheS5uYXRpdmVCYXJXaWR0aCB9XG4gIGZ1bmN0aW9uIGRpc3BsYXlXaWR0aChjbSkge1xuICAgIHJldHVybiBjbS5kaXNwbGF5LnNjcm9sbGVyLmNsaWVudFdpZHRoIC0gc2Nyb2xsR2FwKGNtKSAtIGNtLmRpc3BsYXkuYmFyV2lkdGhcbiAgfVxuICBmdW5jdGlvbiBkaXNwbGF5SGVpZ2h0KGNtKSB7XG4gICAgcmV0dXJuIGNtLmRpc3BsYXkuc2Nyb2xsZXIuY2xpZW50SGVpZ2h0IC0gc2Nyb2xsR2FwKGNtKSAtIGNtLmRpc3BsYXkuYmFySGVpZ2h0XG4gIH1cblxuICAvLyBFbnN1cmUgdGhlIGxpbmVWaWV3LndyYXBwaW5nLmhlaWdodHMgYXJyYXkgaXMgcG9wdWxhdGVkLiBUaGlzIGlzXG4gIC8vIGFuIGFycmF5IG9mIGJvdHRvbSBvZmZzZXRzIGZvciB0aGUgbGluZXMgdGhhdCBtYWtlIHVwIGEgZHJhd25cbiAgLy8gbGluZS4gV2hlbiBsaW5lV3JhcHBpbmcgaXMgb24sIHRoZXJlIG1pZ2h0IGJlIG1vcmUgdGhhbiBvbmVcbiAgLy8gaGVpZ2h0LlxuICBmdW5jdGlvbiBlbnN1cmVMaW5lSGVpZ2h0cyhjbSwgbGluZVZpZXcsIHJlY3QpIHtcbiAgICB2YXIgd3JhcHBpbmcgPSBjbS5vcHRpb25zLmxpbmVXcmFwcGluZztcbiAgICB2YXIgY3VyV2lkdGggPSB3cmFwcGluZyAmJiBkaXNwbGF5V2lkdGgoY20pO1xuICAgIGlmICghbGluZVZpZXcubWVhc3VyZS5oZWlnaHRzIHx8IHdyYXBwaW5nICYmIGxpbmVWaWV3Lm1lYXN1cmUud2lkdGggIT0gY3VyV2lkdGgpIHtcbiAgICAgIHZhciBoZWlnaHRzID0gbGluZVZpZXcubWVhc3VyZS5oZWlnaHRzID0gW107XG4gICAgICBpZiAod3JhcHBpbmcpIHtcbiAgICAgICAgbGluZVZpZXcubWVhc3VyZS53aWR0aCA9IGN1cldpZHRoO1xuICAgICAgICB2YXIgcmVjdHMgPSBsaW5lVmlldy50ZXh0LmZpcnN0Q2hpbGQuZ2V0Q2xpZW50UmVjdHMoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZWN0cy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgICB2YXIgY3VyID0gcmVjdHNbaV0sIG5leHQgPSByZWN0c1tpICsgMV07XG4gICAgICAgICAgaWYgKE1hdGguYWJzKGN1ci5ib3R0b20gLSBuZXh0LmJvdHRvbSkgPiAyKVxuICAgICAgICAgICAgeyBoZWlnaHRzLnB1c2goKGN1ci5ib3R0b20gKyBuZXh0LnRvcCkgLyAyIC0gcmVjdC50b3ApOyB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhlaWdodHMucHVzaChyZWN0LmJvdHRvbSAtIHJlY3QudG9wKTtcbiAgICB9XG4gIH1cblxuICAvLyBGaW5kIGEgbGluZSBtYXAgKG1hcHBpbmcgY2hhcmFjdGVyIG9mZnNldHMgdG8gdGV4dCBub2RlcykgYW5kIGFcbiAgLy8gbWVhc3VyZW1lbnQgY2FjaGUgZm9yIHRoZSBnaXZlbiBsaW5lIG51bWJlci4gKEEgbGluZSB2aWV3IG1pZ2h0XG4gIC8vIGNvbnRhaW4gbXVsdGlwbGUgbGluZXMgd2hlbiBjb2xsYXBzZWQgcmFuZ2VzIGFyZSBwcmVzZW50LilcbiAgZnVuY3Rpb24gbWFwRnJvbUxpbmVWaWV3KGxpbmVWaWV3LCBsaW5lLCBsaW5lTikge1xuICAgIGlmIChsaW5lVmlldy5saW5lID09IGxpbmUpXG4gICAgICB7IHJldHVybiB7bWFwOiBsaW5lVmlldy5tZWFzdXJlLm1hcCwgY2FjaGU6IGxpbmVWaWV3Lm1lYXN1cmUuY2FjaGV9IH1cbiAgICBpZiAobGluZVZpZXcucmVzdCkge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lVmlldy5yZXN0Lmxlbmd0aDsgaSsrKVxuICAgICAgICB7IGlmIChsaW5lVmlldy5yZXN0W2ldID09IGxpbmUpXG4gICAgICAgICAgeyByZXR1cm4ge21hcDogbGluZVZpZXcubWVhc3VyZS5tYXBzW2ldLCBjYWNoZTogbGluZVZpZXcubWVhc3VyZS5jYWNoZXNbaV19IH0gfVxuICAgICAgZm9yICh2YXIgaSQxID0gMDsgaSQxIDwgbGluZVZpZXcucmVzdC5sZW5ndGg7IGkkMSsrKVxuICAgICAgICB7IGlmIChsaW5lTm8obGluZVZpZXcucmVzdFtpJDFdKSA+IGxpbmVOKVxuICAgICAgICAgIHsgcmV0dXJuIHttYXA6IGxpbmVWaWV3Lm1lYXN1cmUubWFwc1tpJDFdLCBjYWNoZTogbGluZVZpZXcubWVhc3VyZS5jYWNoZXNbaSQxXSwgYmVmb3JlOiB0cnVlfSB9IH1cbiAgICB9XG4gIH1cblxuICAvLyBSZW5kZXIgYSBsaW5lIGludG8gdGhlIGhpZGRlbiBub2RlIGRpc3BsYXkuZXh0ZXJuYWxNZWFzdXJlZC4gVXNlZFxuICAvLyB3aGVuIG1lYXN1cmVtZW50IGlzIG5lZWRlZCBmb3IgYSBsaW5lIHRoYXQncyBub3QgaW4gdGhlIHZpZXdwb3J0LlxuICBmdW5jdGlvbiB1cGRhdGVFeHRlcm5hbE1lYXN1cmVtZW50KGNtLCBsaW5lKSB7XG4gICAgbGluZSA9IHZpc3VhbExpbmUobGluZSk7XG4gICAgdmFyIGxpbmVOID0gbGluZU5vKGxpbmUpO1xuICAgIHZhciB2aWV3ID0gY20uZGlzcGxheS5leHRlcm5hbE1lYXN1cmVkID0gbmV3IExpbmVWaWV3KGNtLmRvYywgbGluZSwgbGluZU4pO1xuICAgIHZpZXcubGluZU4gPSBsaW5lTjtcbiAgICB2YXIgYnVpbHQgPSB2aWV3LmJ1aWx0ID0gYnVpbGRMaW5lQ29udGVudChjbSwgdmlldyk7XG4gICAgdmlldy50ZXh0ID0gYnVpbHQucHJlO1xuICAgIHJlbW92ZUNoaWxkcmVuQW5kQWRkKGNtLmRpc3BsYXkubGluZU1lYXN1cmUsIGJ1aWx0LnByZSk7XG4gICAgcmV0dXJuIHZpZXdcbiAgfVxuXG4gIC8vIEdldCBhIHt0b3AsIGJvdHRvbSwgbGVmdCwgcmlnaHR9IGJveCAoaW4gbGluZS1sb2NhbCBjb29yZGluYXRlcylcbiAgLy8gZm9yIGEgZ2l2ZW4gY2hhcmFjdGVyLlxuICBmdW5jdGlvbiBtZWFzdXJlQ2hhcihjbSwgbGluZSwgY2gsIGJpYXMpIHtcbiAgICByZXR1cm4gbWVhc3VyZUNoYXJQcmVwYXJlZChjbSwgcHJlcGFyZU1lYXN1cmVGb3JMaW5lKGNtLCBsaW5lKSwgY2gsIGJpYXMpXG4gIH1cblxuICAvLyBGaW5kIGEgbGluZSB2aWV3IHRoYXQgY29ycmVzcG9uZHMgdG8gdGhlIGdpdmVuIGxpbmUgbnVtYmVyLlxuICBmdW5jdGlvbiBmaW5kVmlld0ZvckxpbmUoY20sIGxpbmVOKSB7XG4gICAgaWYgKGxpbmVOID49IGNtLmRpc3BsYXkudmlld0Zyb20gJiYgbGluZU4gPCBjbS5kaXNwbGF5LnZpZXdUbylcbiAgICAgIHsgcmV0dXJuIGNtLmRpc3BsYXkudmlld1tmaW5kVmlld0luZGV4KGNtLCBsaW5lTildIH1cbiAgICB2YXIgZXh0ID0gY20uZGlzcGxheS5leHRlcm5hbE1lYXN1cmVkO1xuICAgIGlmIChleHQgJiYgbGluZU4gPj0gZXh0LmxpbmVOICYmIGxpbmVOIDwgZXh0LmxpbmVOICsgZXh0LnNpemUpXG4gICAgICB7IHJldHVybiBleHQgfVxuICB9XG5cbiAgLy8gTWVhc3VyZW1lbnQgY2FuIGJlIHNwbGl0IGluIHR3byBzdGVwcywgdGhlIHNldC11cCB3b3JrIHRoYXRcbiAgLy8gYXBwbGllcyB0byB0aGUgd2hvbGUgbGluZSwgYW5kIHRoZSBtZWFzdXJlbWVudCBvZiB0aGUgYWN0dWFsXG4gIC8vIGNoYXJhY3Rlci4gRnVuY3Rpb25zIGxpa2UgY29vcmRzQ2hhciwgdGhhdCBuZWVkIHRvIGRvIGEgbG90IG9mXG4gIC8vIG1lYXN1cmVtZW50cyBpbiBhIHJvdywgY2FuIHRodXMgZW5zdXJlIHRoYXQgdGhlIHNldC11cCB3b3JrIGlzXG4gIC8vIG9ubHkgZG9uZSBvbmNlLlxuICBmdW5jdGlvbiBwcmVwYXJlTWVhc3VyZUZvckxpbmUoY20sIGxpbmUpIHtcbiAgICB2YXIgbGluZU4gPSBsaW5lTm8obGluZSk7XG4gICAgdmFyIHZpZXcgPSBmaW5kVmlld0ZvckxpbmUoY20sIGxpbmVOKTtcbiAgICBpZiAodmlldyAmJiAhdmlldy50ZXh0KSB7XG4gICAgICB2aWV3ID0gbnVsbDtcbiAgICB9IGVsc2UgaWYgKHZpZXcgJiYgdmlldy5jaGFuZ2VzKSB7XG4gICAgICB1cGRhdGVMaW5lRm9yQ2hhbmdlcyhjbSwgdmlldywgbGluZU4sIGdldERpbWVuc2lvbnMoY20pKTtcbiAgICAgIGNtLmN1ck9wLmZvcmNlVXBkYXRlID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKCF2aWV3KVxuICAgICAgeyB2aWV3ID0gdXBkYXRlRXh0ZXJuYWxNZWFzdXJlbWVudChjbSwgbGluZSk7IH1cblxuICAgIHZhciBpbmZvID0gbWFwRnJvbUxpbmVWaWV3KHZpZXcsIGxpbmUsIGxpbmVOKTtcbiAgICByZXR1cm4ge1xuICAgICAgbGluZTogbGluZSwgdmlldzogdmlldywgcmVjdDogbnVsbCxcbiAgICAgIG1hcDogaW5mby5tYXAsIGNhY2hlOiBpbmZvLmNhY2hlLCBiZWZvcmU6IGluZm8uYmVmb3JlLFxuICAgICAgaGFzSGVpZ2h0czogZmFsc2VcbiAgICB9XG4gIH1cblxuICAvLyBHaXZlbiBhIHByZXBhcmVkIG1lYXN1cmVtZW50IG9iamVjdCwgbWVhc3VyZXMgdGhlIHBvc2l0aW9uIG9mIGFuXG4gIC8vIGFjdHVhbCBjaGFyYWN0ZXIgKG9yIGZldGNoZXMgaXQgZnJvbSB0aGUgY2FjaGUpLlxuICBmdW5jdGlvbiBtZWFzdXJlQ2hhclByZXBhcmVkKGNtLCBwcmVwYXJlZCwgY2gsIGJpYXMsIHZhckhlaWdodCkge1xuICAgIGlmIChwcmVwYXJlZC5iZWZvcmUpIHsgY2ggPSAtMTsgfVxuICAgIHZhciBrZXkgPSBjaCArIChiaWFzIHx8IFwiXCIpLCBmb3VuZDtcbiAgICBpZiAocHJlcGFyZWQuY2FjaGUuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgZm91bmQgPSBwcmVwYXJlZC5jYWNoZVtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIXByZXBhcmVkLnJlY3QpXG4gICAgICAgIHsgcHJlcGFyZWQucmVjdCA9IHByZXBhcmVkLnZpZXcudGV4dC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTsgfVxuICAgICAgaWYgKCFwcmVwYXJlZC5oYXNIZWlnaHRzKSB7XG4gICAgICAgIGVuc3VyZUxpbmVIZWlnaHRzKGNtLCBwcmVwYXJlZC52aWV3LCBwcmVwYXJlZC5yZWN0KTtcbiAgICAgICAgcHJlcGFyZWQuaGFzSGVpZ2h0cyA9IHRydWU7XG4gICAgICB9XG4gICAgICBmb3VuZCA9IG1lYXN1cmVDaGFySW5uZXIoY20sIHByZXBhcmVkLCBjaCwgYmlhcyk7XG4gICAgICBpZiAoIWZvdW5kLmJvZ3VzKSB7IHByZXBhcmVkLmNhY2hlW2tleV0gPSBmb3VuZDsgfVxuICAgIH1cbiAgICByZXR1cm4ge2xlZnQ6IGZvdW5kLmxlZnQsIHJpZ2h0OiBmb3VuZC5yaWdodCxcbiAgICAgICAgICAgIHRvcDogdmFySGVpZ2h0ID8gZm91bmQucnRvcCA6IGZvdW5kLnRvcCxcbiAgICAgICAgICAgIGJvdHRvbTogdmFySGVpZ2h0ID8gZm91bmQucmJvdHRvbSA6IGZvdW5kLmJvdHRvbX1cbiAgfVxuXG4gIHZhciBudWxsUmVjdCA9IHtsZWZ0OiAwLCByaWdodDogMCwgdG9wOiAwLCBib3R0b206IDB9O1xuXG4gIGZ1bmN0aW9uIG5vZGVBbmRPZmZzZXRJbkxpbmVNYXAobWFwLCBjaCwgYmlhcykge1xuICAgIHZhciBub2RlLCBzdGFydCwgZW5kLCBjb2xsYXBzZSwgbVN0YXJ0LCBtRW5kO1xuICAgIC8vIEZpcnN0LCBzZWFyY2ggdGhlIGxpbmUgbWFwIGZvciB0aGUgdGV4dCBub2RlIGNvcnJlc3BvbmRpbmcgdG8sXG4gICAgLy8gb3IgY2xvc2VzdCB0bywgdGhlIHRhcmdldCBjaGFyYWN0ZXIuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtYXAubGVuZ3RoOyBpICs9IDMpIHtcbiAgICAgIG1TdGFydCA9IG1hcFtpXTtcbiAgICAgIG1FbmQgPSBtYXBbaSArIDFdO1xuICAgICAgaWYgKGNoIDwgbVN0YXJ0KSB7XG4gICAgICAgIHN0YXJ0ID0gMDsgZW5kID0gMTtcbiAgICAgICAgY29sbGFwc2UgPSBcImxlZnRcIjtcbiAgICAgIH0gZWxzZSBpZiAoY2ggPCBtRW5kKSB7XG4gICAgICAgIHN0YXJ0ID0gY2ggLSBtU3RhcnQ7XG4gICAgICAgIGVuZCA9IHN0YXJ0ICsgMTtcbiAgICAgIH0gZWxzZSBpZiAoaSA9PSBtYXAubGVuZ3RoIC0gMyB8fCBjaCA9PSBtRW5kICYmIG1hcFtpICsgM10gPiBjaCkge1xuICAgICAgICBlbmQgPSBtRW5kIC0gbVN0YXJ0O1xuICAgICAgICBzdGFydCA9IGVuZCAtIDE7XG4gICAgICAgIGlmIChjaCA+PSBtRW5kKSB7IGNvbGxhcHNlID0gXCJyaWdodFwiOyB9XG4gICAgICB9XG4gICAgICBpZiAoc3RhcnQgIT0gbnVsbCkge1xuICAgICAgICBub2RlID0gbWFwW2kgKyAyXTtcbiAgICAgICAgaWYgKG1TdGFydCA9PSBtRW5kICYmIGJpYXMgPT0gKG5vZGUuaW5zZXJ0TGVmdCA/IFwibGVmdFwiIDogXCJyaWdodFwiKSlcbiAgICAgICAgICB7IGNvbGxhcHNlID0gYmlhczsgfVxuICAgICAgICBpZiAoYmlhcyA9PSBcImxlZnRcIiAmJiBzdGFydCA9PSAwKVxuICAgICAgICAgIHsgd2hpbGUgKGkgJiYgbWFwW2kgLSAyXSA9PSBtYXBbaSAtIDNdICYmIG1hcFtpIC0gMV0uaW5zZXJ0TGVmdCkge1xuICAgICAgICAgICAgbm9kZSA9IG1hcFsoaSAtPSAzKSArIDJdO1xuICAgICAgICAgICAgY29sbGFwc2UgPSBcImxlZnRcIjtcbiAgICAgICAgICB9IH1cbiAgICAgICAgaWYgKGJpYXMgPT0gXCJyaWdodFwiICYmIHN0YXJ0ID09IG1FbmQgLSBtU3RhcnQpXG4gICAgICAgICAgeyB3aGlsZSAoaSA8IG1hcC5sZW5ndGggLSAzICYmIG1hcFtpICsgM10gPT0gbWFwW2kgKyA0XSAmJiAhbWFwW2kgKyA1XS5pbnNlcnRMZWZ0KSB7XG4gICAgICAgICAgICBub2RlID0gbWFwWyhpICs9IDMpICsgMl07XG4gICAgICAgICAgICBjb2xsYXBzZSA9IFwicmlnaHRcIjtcbiAgICAgICAgICB9IH1cbiAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtub2RlOiBub2RlLCBzdGFydDogc3RhcnQsIGVuZDogZW5kLCBjb2xsYXBzZTogY29sbGFwc2UsIGNvdmVyU3RhcnQ6IG1TdGFydCwgY292ZXJFbmQ6IG1FbmR9XG4gIH1cblxuICBmdW5jdGlvbiBnZXRVc2VmdWxSZWN0KHJlY3RzLCBiaWFzKSB7XG4gICAgdmFyIHJlY3QgPSBudWxsUmVjdDtcbiAgICBpZiAoYmlhcyA9PSBcImxlZnRcIikgeyBmb3IgKHZhciBpID0gMDsgaSA8IHJlY3RzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoKHJlY3QgPSByZWN0c1tpXSkubGVmdCAhPSByZWN0LnJpZ2h0KSB7IGJyZWFrIH1cbiAgICB9IH0gZWxzZSB7IGZvciAodmFyIGkkMSA9IHJlY3RzLmxlbmd0aCAtIDE7IGkkMSA+PSAwOyBpJDEtLSkge1xuICAgICAgaWYgKChyZWN0ID0gcmVjdHNbaSQxXSkubGVmdCAhPSByZWN0LnJpZ2h0KSB7IGJyZWFrIH1cbiAgICB9IH1cbiAgICByZXR1cm4gcmVjdFxuICB9XG5cbiAgZnVuY3Rpb24gbWVhc3VyZUNoYXJJbm5lcihjbSwgcHJlcGFyZWQsIGNoLCBiaWFzKSB7XG4gICAgdmFyIHBsYWNlID0gbm9kZUFuZE9mZnNldEluTGluZU1hcChwcmVwYXJlZC5tYXAsIGNoLCBiaWFzKTtcbiAgICB2YXIgbm9kZSA9IHBsYWNlLm5vZGUsIHN0YXJ0ID0gcGxhY2Uuc3RhcnQsIGVuZCA9IHBsYWNlLmVuZCwgY29sbGFwc2UgPSBwbGFjZS5jb2xsYXBzZTtcblxuICAgIHZhciByZWN0O1xuICAgIGlmIChub2RlLm5vZGVUeXBlID09IDMpIHsgLy8gSWYgaXQgaXMgYSB0ZXh0IG5vZGUsIHVzZSBhIHJhbmdlIHRvIHJldHJpZXZlIHRoZSBjb29yZGluYXRlcy5cbiAgICAgIGZvciAodmFyIGkkMSA9IDA7IGkkMSA8IDQ7IGkkMSsrKSB7IC8vIFJldHJ5IGEgbWF4aW11bSBvZiA0IHRpbWVzIHdoZW4gbm9uc2Vuc2UgcmVjdGFuZ2xlcyBhcmUgcmV0dXJuZWRcbiAgICAgICAgd2hpbGUgKHN0YXJ0ICYmIGlzRXh0ZW5kaW5nQ2hhcihwcmVwYXJlZC5saW5lLnRleHQuY2hhckF0KHBsYWNlLmNvdmVyU3RhcnQgKyBzdGFydCkpKSB7IC0tc3RhcnQ7IH1cbiAgICAgICAgd2hpbGUgKHBsYWNlLmNvdmVyU3RhcnQgKyBlbmQgPCBwbGFjZS5jb3ZlckVuZCAmJiBpc0V4dGVuZGluZ0NoYXIocHJlcGFyZWQubGluZS50ZXh0LmNoYXJBdChwbGFjZS5jb3ZlclN0YXJ0ICsgZW5kKSkpIHsgKytlbmQ7IH1cbiAgICAgICAgaWYgKGllICYmIGllX3ZlcnNpb24gPCA5ICYmIHN0YXJ0ID09IDAgJiYgZW5kID09IHBsYWNlLmNvdmVyRW5kIC0gcGxhY2UuY292ZXJTdGFydClcbiAgICAgICAgICB7IHJlY3QgPSBub2RlLnBhcmVudE5vZGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7IH1cbiAgICAgICAgZWxzZVxuICAgICAgICAgIHsgcmVjdCA9IGdldFVzZWZ1bFJlY3QocmFuZ2Uobm9kZSwgc3RhcnQsIGVuZCkuZ2V0Q2xpZW50UmVjdHMoKSwgYmlhcyk7IH1cbiAgICAgICAgaWYgKHJlY3QubGVmdCB8fCByZWN0LnJpZ2h0IHx8IHN0YXJ0ID09IDApIHsgYnJlYWsgfVxuICAgICAgICBlbmQgPSBzdGFydDtcbiAgICAgICAgc3RhcnQgPSBzdGFydCAtIDE7XG4gICAgICAgIGNvbGxhcHNlID0gXCJyaWdodFwiO1xuICAgICAgfVxuICAgICAgaWYgKGllICYmIGllX3ZlcnNpb24gPCAxMSkgeyByZWN0ID0gbWF5YmVVcGRhdGVSZWN0Rm9yWm9vbWluZyhjbS5kaXNwbGF5Lm1lYXN1cmUsIHJlY3QpOyB9XG4gICAgfSBlbHNlIHsgLy8gSWYgaXQgaXMgYSB3aWRnZXQsIHNpbXBseSBnZXQgdGhlIGJveCBmb3IgdGhlIHdob2xlIHdpZGdldC5cbiAgICAgIGlmIChzdGFydCA+IDApIHsgY29sbGFwc2UgPSBiaWFzID0gXCJyaWdodFwiOyB9XG4gICAgICB2YXIgcmVjdHM7XG4gICAgICBpZiAoY20ub3B0aW9ucy5saW5lV3JhcHBpbmcgJiYgKHJlY3RzID0gbm9kZS5nZXRDbGllbnRSZWN0cygpKS5sZW5ndGggPiAxKVxuICAgICAgICB7IHJlY3QgPSByZWN0c1tiaWFzID09IFwicmlnaHRcIiA/IHJlY3RzLmxlbmd0aCAtIDEgOiAwXTsgfVxuICAgICAgZWxzZVxuICAgICAgICB7IHJlY3QgPSBub2RlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyB9XG4gICAgfVxuICAgIGlmIChpZSAmJiBpZV92ZXJzaW9uIDwgOSAmJiAhc3RhcnQgJiYgKCFyZWN0IHx8ICFyZWN0LmxlZnQgJiYgIXJlY3QucmlnaHQpKSB7XG4gICAgICB2YXIgclNwYW4gPSBub2RlLnBhcmVudE5vZGUuZ2V0Q2xpZW50UmVjdHMoKVswXTtcbiAgICAgIGlmIChyU3BhbilcbiAgICAgICAgeyByZWN0ID0ge2xlZnQ6IHJTcGFuLmxlZnQsIHJpZ2h0OiByU3Bhbi5sZWZ0ICsgY2hhcldpZHRoKGNtLmRpc3BsYXkpLCB0b3A6IHJTcGFuLnRvcCwgYm90dG9tOiByU3Bhbi5ib3R0b219OyB9XG4gICAgICBlbHNlXG4gICAgICAgIHsgcmVjdCA9IG51bGxSZWN0OyB9XG4gICAgfVxuXG4gICAgdmFyIHJ0b3AgPSByZWN0LnRvcCAtIHByZXBhcmVkLnJlY3QudG9wLCByYm90ID0gcmVjdC5ib3R0b20gLSBwcmVwYXJlZC5yZWN0LnRvcDtcbiAgICB2YXIgbWlkID0gKHJ0b3AgKyByYm90KSAvIDI7XG4gICAgdmFyIGhlaWdodHMgPSBwcmVwYXJlZC52aWV3Lm1lYXN1cmUuaGVpZ2h0cztcbiAgICB2YXIgaSA9IDA7XG4gICAgZm9yICg7IGkgPCBoZWlnaHRzLmxlbmd0aCAtIDE7IGkrKylcbiAgICAgIHsgaWYgKG1pZCA8IGhlaWdodHNbaV0pIHsgYnJlYWsgfSB9XG4gICAgdmFyIHRvcCA9IGkgPyBoZWlnaHRzW2kgLSAxXSA6IDAsIGJvdCA9IGhlaWdodHNbaV07XG4gICAgdmFyIHJlc3VsdCA9IHtsZWZ0OiAoY29sbGFwc2UgPT0gXCJyaWdodFwiID8gcmVjdC5yaWdodCA6IHJlY3QubGVmdCkgLSBwcmVwYXJlZC5yZWN0LmxlZnQsXG4gICAgICAgICAgICAgICAgICByaWdodDogKGNvbGxhcHNlID09IFwibGVmdFwiID8gcmVjdC5sZWZ0IDogcmVjdC5yaWdodCkgLSBwcmVwYXJlZC5yZWN0LmxlZnQsXG4gICAgICAgICAgICAgICAgICB0b3A6IHRvcCwgYm90dG9tOiBib3R9O1xuICAgIGlmICghcmVjdC5sZWZ0ICYmICFyZWN0LnJpZ2h0KSB7IHJlc3VsdC5ib2d1cyA9IHRydWU7IH1cbiAgICBpZiAoIWNtLm9wdGlvbnMuc2luZ2xlQ3Vyc29ySGVpZ2h0UGVyTGluZSkgeyByZXN1bHQucnRvcCA9IHJ0b3A7IHJlc3VsdC5yYm90dG9tID0gcmJvdDsgfVxuXG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG5cbiAgLy8gV29yayBhcm91bmQgcHJvYmxlbSB3aXRoIGJvdW5kaW5nIGNsaWVudCByZWN0cyBvbiByYW5nZXMgYmVpbmdcbiAgLy8gcmV0dXJuZWQgaW5jb3JyZWN0bHkgd2hlbiB6b29tZWQgb24gSUUxMCBhbmQgYmVsb3cuXG4gIGZ1bmN0aW9uIG1heWJlVXBkYXRlUmVjdEZvclpvb21pbmcobWVhc3VyZSwgcmVjdCkge1xuICAgIGlmICghd2luZG93LnNjcmVlbiB8fCBzY3JlZW4ubG9naWNhbFhEUEkgPT0gbnVsbCB8fFxuICAgICAgICBzY3JlZW4ubG9naWNhbFhEUEkgPT0gc2NyZWVuLmRldmljZVhEUEkgfHwgIWhhc0JhZFpvb21lZFJlY3RzKG1lYXN1cmUpKVxuICAgICAgeyByZXR1cm4gcmVjdCB9XG4gICAgdmFyIHNjYWxlWCA9IHNjcmVlbi5sb2dpY2FsWERQSSAvIHNjcmVlbi5kZXZpY2VYRFBJO1xuICAgIHZhciBzY2FsZVkgPSBzY3JlZW4ubG9naWNhbFlEUEkgLyBzY3JlZW4uZGV2aWNlWURQSTtcbiAgICByZXR1cm4ge2xlZnQ6IHJlY3QubGVmdCAqIHNjYWxlWCwgcmlnaHQ6IHJlY3QucmlnaHQgKiBzY2FsZVgsXG4gICAgICAgICAgICB0b3A6IHJlY3QudG9wICogc2NhbGVZLCBib3R0b206IHJlY3QuYm90dG9tICogc2NhbGVZfVxuICB9XG5cbiAgZnVuY3Rpb24gY2xlYXJMaW5lTWVhc3VyZW1lbnRDYWNoZUZvcihsaW5lVmlldykge1xuICAgIGlmIChsaW5lVmlldy5tZWFzdXJlKSB7XG4gICAgICBsaW5lVmlldy5tZWFzdXJlLmNhY2hlID0ge307XG4gICAgICBsaW5lVmlldy5tZWFzdXJlLmhlaWdodHMgPSBudWxsO1xuICAgICAgaWYgKGxpbmVWaWV3LnJlc3QpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lVmlldy5yZXN0Lmxlbmd0aDsgaSsrKVxuICAgICAgICB7IGxpbmVWaWV3Lm1lYXN1cmUuY2FjaGVzW2ldID0ge307IH0gfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGNsZWFyTGluZU1lYXN1cmVtZW50Q2FjaGUoY20pIHtcbiAgICBjbS5kaXNwbGF5LmV4dGVybmFsTWVhc3VyZSA9IG51bGw7XG4gICAgcmVtb3ZlQ2hpbGRyZW4oY20uZGlzcGxheS5saW5lTWVhc3VyZSk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjbS5kaXNwbGF5LnZpZXcubGVuZ3RoOyBpKyspXG4gICAgICB7IGNsZWFyTGluZU1lYXN1cmVtZW50Q2FjaGVGb3IoY20uZGlzcGxheS52aWV3W2ldKTsgfVxuICB9XG5cbiAgZnVuY3Rpb24gY2xlYXJDYWNoZXMoY20pIHtcbiAgICBjbGVhckxpbmVNZWFzdXJlbWVudENhY2hlKGNtKTtcbiAgICBjbS5kaXNwbGF5LmNhY2hlZENoYXJXaWR0aCA9IGNtLmRpc3BsYXkuY2FjaGVkVGV4dEhlaWdodCA9IGNtLmRpc3BsYXkuY2FjaGVkUGFkZGluZ0ggPSBudWxsO1xuICAgIGlmICghY20ub3B0aW9ucy5saW5lV3JhcHBpbmcpIHsgY20uZGlzcGxheS5tYXhMaW5lQ2hhbmdlZCA9IHRydWU7IH1cbiAgICBjbS5kaXNwbGF5LmxpbmVOdW1DaGFycyA9IG51bGw7XG4gIH1cblxuICBmdW5jdGlvbiBwYWdlU2Nyb2xsWCgpIHtcbiAgICAvLyBXb3JrIGFyb3VuZCBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD00ODkyMDZcbiAgICAvLyB3aGljaCBjYXVzZXMgcGFnZV9PZmZzZXQgYW5kIGJvdW5kaW5nIGNsaWVudCByZWN0cyB0byB1c2VcbiAgICAvLyBkaWZmZXJlbnQgcmVmZXJlbmNlIHZpZXdwb3J0cyBhbmQgaW52YWxpZGF0ZSBvdXIgY2FsY3VsYXRpb25zLlxuICAgIGlmIChjaHJvbWUgJiYgYW5kcm9pZCkgeyByZXR1cm4gLShkb2N1bWVudC5ib2R5LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmxlZnQgLSBwYXJzZUludChnZXRDb21wdXRlZFN0eWxlKGRvY3VtZW50LmJvZHkpLm1hcmdpbkxlZnQpKSB9XG4gICAgcmV0dXJuIHdpbmRvdy5wYWdlWE9mZnNldCB8fCAoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50IHx8IGRvY3VtZW50LmJvZHkpLnNjcm9sbExlZnRcbiAgfVxuICBmdW5jdGlvbiBwYWdlU2Nyb2xsWSgpIHtcbiAgICBpZiAoY2hyb21lICYmIGFuZHJvaWQpIHsgcmV0dXJuIC0oZG9jdW1lbnQuYm9keS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3AgLSBwYXJzZUludChnZXRDb21wdXRlZFN0eWxlKGRvY3VtZW50LmJvZHkpLm1hcmdpblRvcCkpIH1cbiAgICByZXR1cm4gd2luZG93LnBhZ2VZT2Zmc2V0IHx8IChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgfHwgZG9jdW1lbnQuYm9keSkuc2Nyb2xsVG9wXG4gIH1cblxuICBmdW5jdGlvbiB3aWRnZXRUb3BIZWlnaHQobGluZU9iaikge1xuICAgIHZhciByZWYgPSB2aXN1YWxMaW5lKGxpbmVPYmopO1xuICAgIHZhciB3aWRnZXRzID0gcmVmLndpZGdldHM7XG4gICAgdmFyIGhlaWdodCA9IDA7XG4gICAgaWYgKHdpZGdldHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCB3aWRnZXRzLmxlbmd0aDsgKytpKSB7IGlmICh3aWRnZXRzW2ldLmFib3ZlKVxuICAgICAgeyBoZWlnaHQgKz0gd2lkZ2V0SGVpZ2h0KHdpZGdldHNbaV0pOyB9IH0gfVxuICAgIHJldHVybiBoZWlnaHRcbiAgfVxuXG4gIC8vIENvbnZlcnRzIGEge3RvcCwgYm90dG9tLCBsZWZ0LCByaWdodH0gYm94IGZyb20gbGluZS1sb2NhbFxuICAvLyBjb29yZGluYXRlcyBpbnRvIGFub3RoZXIgY29vcmRpbmF0ZSBzeXN0ZW0uIENvbnRleHQgbWF5IGJlIG9uZSBvZlxuICAvLyBcImxpbmVcIiwgXCJkaXZcIiAoZGlzcGxheS5saW5lRGl2KSwgXCJsb2NhbFwiLi9udWxsIChlZGl0b3IpLCBcIndpbmRvd1wiLFxuICAvLyBvciBcInBhZ2VcIi5cbiAgZnVuY3Rpb24gaW50b0Nvb3JkU3lzdGVtKGNtLCBsaW5lT2JqLCByZWN0LCBjb250ZXh0LCBpbmNsdWRlV2lkZ2V0cykge1xuICAgIGlmICghaW5jbHVkZVdpZGdldHMpIHtcbiAgICAgIHZhciBoZWlnaHQgPSB3aWRnZXRUb3BIZWlnaHQobGluZU9iaik7XG4gICAgICByZWN0LnRvcCArPSBoZWlnaHQ7IHJlY3QuYm90dG9tICs9IGhlaWdodDtcbiAgICB9XG4gICAgaWYgKGNvbnRleHQgPT0gXCJsaW5lXCIpIHsgcmV0dXJuIHJlY3QgfVxuICAgIGlmICghY29udGV4dCkgeyBjb250ZXh0ID0gXCJsb2NhbFwiOyB9XG4gICAgdmFyIHlPZmYgPSBoZWlnaHRBdExpbmUobGluZU9iaik7XG4gICAgaWYgKGNvbnRleHQgPT0gXCJsb2NhbFwiKSB7IHlPZmYgKz0gcGFkZGluZ1RvcChjbS5kaXNwbGF5KTsgfVxuICAgIGVsc2UgeyB5T2ZmIC09IGNtLmRpc3BsYXkudmlld09mZnNldDsgfVxuICAgIGlmIChjb250ZXh0ID09IFwicGFnZVwiIHx8IGNvbnRleHQgPT0gXCJ3aW5kb3dcIikge1xuICAgICAgdmFyIGxPZmYgPSBjbS5kaXNwbGF5LmxpbmVTcGFjZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIHlPZmYgKz0gbE9mZi50b3AgKyAoY29udGV4dCA9PSBcIndpbmRvd1wiID8gMCA6IHBhZ2VTY3JvbGxZKCkpO1xuICAgICAgdmFyIHhPZmYgPSBsT2ZmLmxlZnQgKyAoY29udGV4dCA9PSBcIndpbmRvd1wiID8gMCA6IHBhZ2VTY3JvbGxYKCkpO1xuICAgICAgcmVjdC5sZWZ0ICs9IHhPZmY7IHJlY3QucmlnaHQgKz0geE9mZjtcbiAgICB9XG4gICAgcmVjdC50b3AgKz0geU9mZjsgcmVjdC5ib3R0b20gKz0geU9mZjtcbiAgICByZXR1cm4gcmVjdFxuICB9XG5cbiAgLy8gQ292ZXJ0cyBhIGJveCBmcm9tIFwiZGl2XCIgY29vcmRzIHRvIGFub3RoZXIgY29vcmRpbmF0ZSBzeXN0ZW0uXG4gIC8vIENvbnRleHQgbWF5IGJlIFwid2luZG93XCIsIFwicGFnZVwiLCBcImRpdlwiLCBvciBcImxvY2FsXCIuL251bGwuXG4gIGZ1bmN0aW9uIGZyb21Db29yZFN5c3RlbShjbSwgY29vcmRzLCBjb250ZXh0KSB7XG4gICAgaWYgKGNvbnRleHQgPT0gXCJkaXZcIikgeyByZXR1cm4gY29vcmRzIH1cbiAgICB2YXIgbGVmdCA9IGNvb3Jkcy5sZWZ0LCB0b3AgPSBjb29yZHMudG9wO1xuICAgIC8vIEZpcnN0IG1vdmUgaW50byBcInBhZ2VcIiBjb29yZGluYXRlIHN5c3RlbVxuICAgIGlmIChjb250ZXh0ID09IFwicGFnZVwiKSB7XG4gICAgICBsZWZ0IC09IHBhZ2VTY3JvbGxYKCk7XG4gICAgICB0b3AgLT0gcGFnZVNjcm9sbFkoKTtcbiAgICB9IGVsc2UgaWYgKGNvbnRleHQgPT0gXCJsb2NhbFwiIHx8ICFjb250ZXh0KSB7XG4gICAgICB2YXIgbG9jYWxCb3ggPSBjbS5kaXNwbGF5LnNpemVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgbGVmdCArPSBsb2NhbEJveC5sZWZ0O1xuICAgICAgdG9wICs9IGxvY2FsQm94LnRvcDtcbiAgICB9XG5cbiAgICB2YXIgbGluZVNwYWNlQm94ID0gY20uZGlzcGxheS5saW5lU3BhY2UuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgcmV0dXJuIHtsZWZ0OiBsZWZ0IC0gbGluZVNwYWNlQm94LmxlZnQsIHRvcDogdG9wIC0gbGluZVNwYWNlQm94LnRvcH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGNoYXJDb29yZHMoY20sIHBvcywgY29udGV4dCwgbGluZU9iaiwgYmlhcykge1xuICAgIGlmICghbGluZU9iaikgeyBsaW5lT2JqID0gZ2V0TGluZShjbS5kb2MsIHBvcy5saW5lKTsgfVxuICAgIHJldHVybiBpbnRvQ29vcmRTeXN0ZW0oY20sIGxpbmVPYmosIG1lYXN1cmVDaGFyKGNtLCBsaW5lT2JqLCBwb3MuY2gsIGJpYXMpLCBjb250ZXh0KVxuICB9XG5cbiAgLy8gUmV0dXJucyBhIGJveCBmb3IgYSBnaXZlbiBjdXJzb3IgcG9zaXRpb24sIHdoaWNoIG1heSBoYXZlIGFuXG4gIC8vICdvdGhlcicgcHJvcGVydHkgY29udGFpbmluZyB0aGUgcG9zaXRpb24gb2YgdGhlIHNlY29uZGFyeSBjdXJzb3JcbiAgLy8gb24gYSBiaWRpIGJvdW5kYXJ5LlxuICAvLyBBIGN1cnNvciBQb3MobGluZSwgY2hhciwgXCJiZWZvcmVcIikgaXMgb24gdGhlIHNhbWUgdmlzdWFsIGxpbmUgYXMgYGNoYXIgLSAxYFxuICAvLyBhbmQgYWZ0ZXIgYGNoYXIgLSAxYCBpbiB3cml0aW5nIG9yZGVyIG9mIGBjaGFyIC0gMWBcbiAgLy8gQSBjdXJzb3IgUG9zKGxpbmUsIGNoYXIsIFwiYWZ0ZXJcIikgaXMgb24gdGhlIHNhbWUgdmlzdWFsIGxpbmUgYXMgYGNoYXJgXG4gIC8vIGFuZCBiZWZvcmUgYGNoYXJgIGluIHdyaXRpbmcgb3JkZXIgb2YgYGNoYXJgXG4gIC8vIEV4YW1wbGVzICh1cHBlci1jYXNlIGxldHRlcnMgYXJlIFJUTCwgbG93ZXItY2FzZSBhcmUgTFRSKTpcbiAgLy8gICAgIFBvcygwLCAxLCAuLi4pXG4gIC8vICAgICBiZWZvcmUgICBhZnRlclxuICAvLyBhYiAgICAgYXxiICAgICBhfGJcbiAgLy8gYUIgICAgIGF8QiAgICAgYUJ8XG4gIC8vIEFiICAgICB8QWIgICAgIEF8YlxuICAvLyBBQiAgICAgQnxBICAgICBCfEFcbiAgLy8gRXZlcnkgcG9zaXRpb24gYWZ0ZXIgdGhlIGxhc3QgY2hhcmFjdGVyIG9uIGEgbGluZSBpcyBjb25zaWRlcmVkIHRvIHN0aWNrXG4gIC8vIHRvIHRoZSBsYXN0IGNoYXJhY3RlciBvbiB0aGUgbGluZS5cbiAgZnVuY3Rpb24gY3Vyc29yQ29vcmRzKGNtLCBwb3MsIGNvbnRleHQsIGxpbmVPYmosIHByZXBhcmVkTWVhc3VyZSwgdmFySGVpZ2h0KSB7XG4gICAgbGluZU9iaiA9IGxpbmVPYmogfHwgZ2V0TGluZShjbS5kb2MsIHBvcy5saW5lKTtcbiAgICBpZiAoIXByZXBhcmVkTWVhc3VyZSkgeyBwcmVwYXJlZE1lYXN1cmUgPSBwcmVwYXJlTWVhc3VyZUZvckxpbmUoY20sIGxpbmVPYmopOyB9XG4gICAgZnVuY3Rpb24gZ2V0KGNoLCByaWdodCkge1xuICAgICAgdmFyIG0gPSBtZWFzdXJlQ2hhclByZXBhcmVkKGNtLCBwcmVwYXJlZE1lYXN1cmUsIGNoLCByaWdodCA/IFwicmlnaHRcIiA6IFwibGVmdFwiLCB2YXJIZWlnaHQpO1xuICAgICAgaWYgKHJpZ2h0KSB7IG0ubGVmdCA9IG0ucmlnaHQ7IH0gZWxzZSB7IG0ucmlnaHQgPSBtLmxlZnQ7IH1cbiAgICAgIHJldHVybiBpbnRvQ29vcmRTeXN0ZW0oY20sIGxpbmVPYmosIG0sIGNvbnRleHQpXG4gICAgfVxuICAgIHZhciBvcmRlciA9IGdldE9yZGVyKGxpbmVPYmosIGNtLmRvYy5kaXJlY3Rpb24pLCBjaCA9IHBvcy5jaCwgc3RpY2t5ID0gcG9zLnN0aWNreTtcbiAgICBpZiAoY2ggPj0gbGluZU9iai50ZXh0Lmxlbmd0aCkge1xuICAgICAgY2ggPSBsaW5lT2JqLnRleHQubGVuZ3RoO1xuICAgICAgc3RpY2t5ID0gXCJiZWZvcmVcIjtcbiAgICB9IGVsc2UgaWYgKGNoIDw9IDApIHtcbiAgICAgIGNoID0gMDtcbiAgICAgIHN0aWNreSA9IFwiYWZ0ZXJcIjtcbiAgICB9XG4gICAgaWYgKCFvcmRlcikgeyByZXR1cm4gZ2V0KHN0aWNreSA9PSBcImJlZm9yZVwiID8gY2ggLSAxIDogY2gsIHN0aWNreSA9PSBcImJlZm9yZVwiKSB9XG5cbiAgICBmdW5jdGlvbiBnZXRCaWRpKGNoLCBwYXJ0UG9zLCBpbnZlcnQpIHtcbiAgICAgIHZhciBwYXJ0ID0gb3JkZXJbcGFydFBvc10sIHJpZ2h0ID0gcGFydC5sZXZlbCA9PSAxO1xuICAgICAgcmV0dXJuIGdldChpbnZlcnQgPyBjaCAtIDEgOiBjaCwgcmlnaHQgIT0gaW52ZXJ0KVxuICAgIH1cbiAgICB2YXIgcGFydFBvcyA9IGdldEJpZGlQYXJ0QXQob3JkZXIsIGNoLCBzdGlja3kpO1xuICAgIHZhciBvdGhlciA9IGJpZGlPdGhlcjtcbiAgICB2YXIgdmFsID0gZ2V0QmlkaShjaCwgcGFydFBvcywgc3RpY2t5ID09IFwiYmVmb3JlXCIpO1xuICAgIGlmIChvdGhlciAhPSBudWxsKSB7IHZhbC5vdGhlciA9IGdldEJpZGkoY2gsIG90aGVyLCBzdGlja3kgIT0gXCJiZWZvcmVcIik7IH1cbiAgICByZXR1cm4gdmFsXG4gIH1cblxuICAvLyBVc2VkIHRvIGNoZWFwbHkgZXN0aW1hdGUgdGhlIGNvb3JkaW5hdGVzIGZvciBhIHBvc2l0aW9uLiBVc2VkIGZvclxuICAvLyBpbnRlcm1lZGlhdGUgc2Nyb2xsIHVwZGF0ZXMuXG4gIGZ1bmN0aW9uIGVzdGltYXRlQ29vcmRzKGNtLCBwb3MpIHtcbiAgICB2YXIgbGVmdCA9IDA7XG4gICAgcG9zID0gY2xpcFBvcyhjbS5kb2MsIHBvcyk7XG4gICAgaWYgKCFjbS5vcHRpb25zLmxpbmVXcmFwcGluZykgeyBsZWZ0ID0gY2hhcldpZHRoKGNtLmRpc3BsYXkpICogcG9zLmNoOyB9XG4gICAgdmFyIGxpbmVPYmogPSBnZXRMaW5lKGNtLmRvYywgcG9zLmxpbmUpO1xuICAgIHZhciB0b3AgPSBoZWlnaHRBdExpbmUobGluZU9iaikgKyBwYWRkaW5nVG9wKGNtLmRpc3BsYXkpO1xuICAgIHJldHVybiB7bGVmdDogbGVmdCwgcmlnaHQ6IGxlZnQsIHRvcDogdG9wLCBib3R0b206IHRvcCArIGxpbmVPYmouaGVpZ2h0fVxuICB9XG5cbiAgLy8gUG9zaXRpb25zIHJldHVybmVkIGJ5IGNvb3Jkc0NoYXIgY29udGFpbiBzb21lIGV4dHJhIGluZm9ybWF0aW9uLlxuICAvLyB4UmVsIGlzIHRoZSByZWxhdGl2ZSB4IHBvc2l0aW9uIG9mIHRoZSBpbnB1dCBjb29yZGluYXRlcyBjb21wYXJlZFxuICAvLyB0byB0aGUgZm91bmQgcG9zaXRpb24gKHNvIHhSZWwgPiAwIG1lYW5zIHRoZSBjb29yZGluYXRlcyBhcmUgdG9cbiAgLy8gdGhlIHJpZ2h0IG9mIHRoZSBjaGFyYWN0ZXIgcG9zaXRpb24sIGZvciBleGFtcGxlKS4gV2hlbiBvdXRzaWRlXG4gIC8vIGlzIHRydWUsIHRoYXQgbWVhbnMgdGhlIGNvb3JkaW5hdGVzIGxpZSBvdXRzaWRlIHRoZSBsaW5lJ3NcbiAgLy8gdmVydGljYWwgcmFuZ2UuXG4gIGZ1bmN0aW9uIFBvc1dpdGhJbmZvKGxpbmUsIGNoLCBzdGlja3ksIG91dHNpZGUsIHhSZWwpIHtcbiAgICB2YXIgcG9zID0gUG9zKGxpbmUsIGNoLCBzdGlja3kpO1xuICAgIHBvcy54UmVsID0geFJlbDtcbiAgICBpZiAob3V0c2lkZSkgeyBwb3Mub3V0c2lkZSA9IG91dHNpZGU7IH1cbiAgICByZXR1cm4gcG9zXG4gIH1cblxuICAvLyBDb21wdXRlIHRoZSBjaGFyYWN0ZXIgcG9zaXRpb24gY2xvc2VzdCB0byB0aGUgZ2l2ZW4gY29vcmRpbmF0ZXMuXG4gIC8vIElucHV0IG11c3QgYmUgbGluZVNwYWNlLWxvY2FsIChcImRpdlwiIGNvb3JkaW5hdGUgc3lzdGVtKS5cbiAgZnVuY3Rpb24gY29vcmRzQ2hhcihjbSwgeCwgeSkge1xuICAgIHZhciBkb2MgPSBjbS5kb2M7XG4gICAgeSArPSBjbS5kaXNwbGF5LnZpZXdPZmZzZXQ7XG4gICAgaWYgKHkgPCAwKSB7IHJldHVybiBQb3NXaXRoSW5mbyhkb2MuZmlyc3QsIDAsIG51bGwsIC0xLCAtMSkgfVxuICAgIHZhciBsaW5lTiA9IGxpbmVBdEhlaWdodChkb2MsIHkpLCBsYXN0ID0gZG9jLmZpcnN0ICsgZG9jLnNpemUgLSAxO1xuICAgIGlmIChsaW5lTiA+IGxhc3QpXG4gICAgICB7IHJldHVybiBQb3NXaXRoSW5mbyhkb2MuZmlyc3QgKyBkb2Muc2l6ZSAtIDEsIGdldExpbmUoZG9jLCBsYXN0KS50ZXh0Lmxlbmd0aCwgbnVsbCwgMSwgMSkgfVxuICAgIGlmICh4IDwgMCkgeyB4ID0gMDsgfVxuXG4gICAgdmFyIGxpbmVPYmogPSBnZXRMaW5lKGRvYywgbGluZU4pO1xuICAgIGZvciAoOzspIHtcbiAgICAgIHZhciBmb3VuZCA9IGNvb3Jkc0NoYXJJbm5lcihjbSwgbGluZU9iaiwgbGluZU4sIHgsIHkpO1xuICAgICAgdmFyIGNvbGxhcHNlZCA9IGNvbGxhcHNlZFNwYW5Bcm91bmQobGluZU9iaiwgZm91bmQuY2ggKyAoZm91bmQueFJlbCA+IDAgfHwgZm91bmQub3V0c2lkZSA+IDAgPyAxIDogMCkpO1xuICAgICAgaWYgKCFjb2xsYXBzZWQpIHsgcmV0dXJuIGZvdW5kIH1cbiAgICAgIHZhciByYW5nZUVuZCA9IGNvbGxhcHNlZC5maW5kKDEpO1xuICAgICAgaWYgKHJhbmdlRW5kLmxpbmUgPT0gbGluZU4pIHsgcmV0dXJuIHJhbmdlRW5kIH1cbiAgICAgIGxpbmVPYmogPSBnZXRMaW5lKGRvYywgbGluZU4gPSByYW5nZUVuZC5saW5lKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiB3cmFwcGVkTGluZUV4dGVudChjbSwgbGluZU9iaiwgcHJlcGFyZWRNZWFzdXJlLCB5KSB7XG4gICAgeSAtPSB3aWRnZXRUb3BIZWlnaHQobGluZU9iaik7XG4gICAgdmFyIGVuZCA9IGxpbmVPYmoudGV4dC5sZW5ndGg7XG4gICAgdmFyIGJlZ2luID0gZmluZEZpcnN0KGZ1bmN0aW9uIChjaCkgeyByZXR1cm4gbWVhc3VyZUNoYXJQcmVwYXJlZChjbSwgcHJlcGFyZWRNZWFzdXJlLCBjaCAtIDEpLmJvdHRvbSA8PSB5OyB9LCBlbmQsIDApO1xuICAgIGVuZCA9IGZpbmRGaXJzdChmdW5jdGlvbiAoY2gpIHsgcmV0dXJuIG1lYXN1cmVDaGFyUHJlcGFyZWQoY20sIHByZXBhcmVkTWVhc3VyZSwgY2gpLnRvcCA+IHk7IH0sIGJlZ2luLCBlbmQpO1xuICAgIHJldHVybiB7YmVnaW46IGJlZ2luLCBlbmQ6IGVuZH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHdyYXBwZWRMaW5lRXh0ZW50Q2hhcihjbSwgbGluZU9iaiwgcHJlcGFyZWRNZWFzdXJlLCB0YXJnZXQpIHtcbiAgICBpZiAoIXByZXBhcmVkTWVhc3VyZSkgeyBwcmVwYXJlZE1lYXN1cmUgPSBwcmVwYXJlTWVhc3VyZUZvckxpbmUoY20sIGxpbmVPYmopOyB9XG4gICAgdmFyIHRhcmdldFRvcCA9IGludG9Db29yZFN5c3RlbShjbSwgbGluZU9iaiwgbWVhc3VyZUNoYXJQcmVwYXJlZChjbSwgcHJlcGFyZWRNZWFzdXJlLCB0YXJnZXQpLCBcImxpbmVcIikudG9wO1xuICAgIHJldHVybiB3cmFwcGVkTGluZUV4dGVudChjbSwgbGluZU9iaiwgcHJlcGFyZWRNZWFzdXJlLCB0YXJnZXRUb3ApXG4gIH1cblxuICAvLyBSZXR1cm5zIHRydWUgaWYgdGhlIGdpdmVuIHNpZGUgb2YgYSBib3ggaXMgYWZ0ZXIgdGhlIGdpdmVuXG4gIC8vIGNvb3JkaW5hdGVzLCBpbiB0b3AtdG8tYm90dG9tLCBsZWZ0LXRvLXJpZ2h0IG9yZGVyLlxuICBmdW5jdGlvbiBib3hJc0FmdGVyKGJveCwgeCwgeSwgbGVmdCkge1xuICAgIHJldHVybiBib3guYm90dG9tIDw9IHkgPyBmYWxzZSA6IGJveC50b3AgPiB5ID8gdHJ1ZSA6IChsZWZ0ID8gYm94LmxlZnQgOiBib3gucmlnaHQpID4geFxuICB9XG5cbiAgZnVuY3Rpb24gY29vcmRzQ2hhcklubmVyKGNtLCBsaW5lT2JqLCBsaW5lTm8sIHgsIHkpIHtcbiAgICAvLyBNb3ZlIHkgaW50byBsaW5lLWxvY2FsIGNvb3JkaW5hdGUgc3BhY2VcbiAgICB5IC09IGhlaWdodEF0TGluZShsaW5lT2JqKTtcbiAgICB2YXIgcHJlcGFyZWRNZWFzdXJlID0gcHJlcGFyZU1lYXN1cmVGb3JMaW5lKGNtLCBsaW5lT2JqKTtcbiAgICAvLyBXaGVuIGRpcmVjdGx5IGNhbGxpbmcgYG1lYXN1cmVDaGFyUHJlcGFyZWRgLCB3ZSBoYXZlIHRvIGFkanVzdFxuICAgIC8vIGZvciB0aGUgd2lkZ2V0cyBhdCB0aGlzIGxpbmUuXG4gICAgdmFyIHdpZGdldEhlaWdodCA9IHdpZGdldFRvcEhlaWdodChsaW5lT2JqKTtcbiAgICB2YXIgYmVnaW4gPSAwLCBlbmQgPSBsaW5lT2JqLnRleHQubGVuZ3RoLCBsdHIgPSB0cnVlO1xuXG4gICAgdmFyIG9yZGVyID0gZ2V0T3JkZXIobGluZU9iaiwgY20uZG9jLmRpcmVjdGlvbik7XG4gICAgLy8gSWYgdGhlIGxpbmUgaXNuJ3QgcGxhaW4gbGVmdC10by1yaWdodCB0ZXh0LCBmaXJzdCBmaWd1cmUgb3V0XG4gICAgLy8gd2hpY2ggYmlkaSBzZWN0aW9uIHRoZSBjb29yZGluYXRlcyBmYWxsIGludG8uXG4gICAgaWYgKG9yZGVyKSB7XG4gICAgICB2YXIgcGFydCA9IChjbS5vcHRpb25zLmxpbmVXcmFwcGluZyA/IGNvb3Jkc0JpZGlQYXJ0V3JhcHBlZCA6IGNvb3Jkc0JpZGlQYXJ0KVxuICAgICAgICAgICAgICAgICAgIChjbSwgbGluZU9iaiwgbGluZU5vLCBwcmVwYXJlZE1lYXN1cmUsIG9yZGVyLCB4LCB5KTtcbiAgICAgIGx0ciA9IHBhcnQubGV2ZWwgIT0gMTtcbiAgICAgIC8vIFRoZSBhd2t3YXJkIC0xIG9mZnNldHMgYXJlIG5lZWRlZCBiZWNhdXNlIGZpbmRGaXJzdCAoY2FsbGVkXG4gICAgICAvLyBvbiB0aGVzZSBiZWxvdykgd2lsbCB0cmVhdCBpdHMgZmlyc3QgYm91bmQgYXMgaW5jbHVzaXZlLFxuICAgICAgLy8gc2Vjb25kIGFzIGV4Y2x1c2l2ZSwgYnV0IHdlIHdhbnQgdG8gYWN0dWFsbHkgYWRkcmVzcyB0aGVcbiAgICAgIC8vIGNoYXJhY3RlcnMgaW4gdGhlIHBhcnQncyByYW5nZVxuICAgICAgYmVnaW4gPSBsdHIgPyBwYXJ0LmZyb20gOiBwYXJ0LnRvIC0gMTtcbiAgICAgIGVuZCA9IGx0ciA/IHBhcnQudG8gOiBwYXJ0LmZyb20gLSAxO1xuICAgIH1cblxuICAgIC8vIEEgYmluYXJ5IHNlYXJjaCB0byBmaW5kIHRoZSBmaXJzdCBjaGFyYWN0ZXIgd2hvc2UgYm91bmRpbmcgYm94XG4gICAgLy8gc3RhcnRzIGFmdGVyIHRoZSBjb29yZGluYXRlcy4gSWYgd2UgcnVuIGFjcm9zcyBhbnkgd2hvc2UgYm94IHdyYXBcbiAgICAvLyB0aGUgY29vcmRpbmF0ZXMsIHN0b3JlIHRoYXQuXG4gICAgdmFyIGNoQXJvdW5kID0gbnVsbCwgYm94QXJvdW5kID0gbnVsbDtcbiAgICB2YXIgY2ggPSBmaW5kRmlyc3QoZnVuY3Rpb24gKGNoKSB7XG4gICAgICB2YXIgYm94ID0gbWVhc3VyZUNoYXJQcmVwYXJlZChjbSwgcHJlcGFyZWRNZWFzdXJlLCBjaCk7XG4gICAgICBib3gudG9wICs9IHdpZGdldEhlaWdodDsgYm94LmJvdHRvbSArPSB3aWRnZXRIZWlnaHQ7XG4gICAgICBpZiAoIWJveElzQWZ0ZXIoYm94LCB4LCB5LCBmYWxzZSkpIHsgcmV0dXJuIGZhbHNlIH1cbiAgICAgIGlmIChib3gudG9wIDw9IHkgJiYgYm94LmxlZnQgPD0geCkge1xuICAgICAgICBjaEFyb3VuZCA9IGNoO1xuICAgICAgICBib3hBcm91bmQgPSBib3g7XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH0sIGJlZ2luLCBlbmQpO1xuXG4gICAgdmFyIGJhc2VYLCBzdGlja3ksIG91dHNpZGUgPSBmYWxzZTtcbiAgICAvLyBJZiBhIGJveCBhcm91bmQgdGhlIGNvb3JkaW5hdGVzIHdhcyBmb3VuZCwgdXNlIHRoYXRcbiAgICBpZiAoYm94QXJvdW5kKSB7XG4gICAgICAvLyBEaXN0aW5ndWlzaCBjb29yZGluYXRlcyBuZWFyZXIgdG8gdGhlIGxlZnQgb3IgcmlnaHQgc2lkZSBvZiB0aGUgYm94XG4gICAgICB2YXIgYXRMZWZ0ID0geCAtIGJveEFyb3VuZC5sZWZ0IDwgYm94QXJvdW5kLnJpZ2h0IC0geCwgYXRTdGFydCA9IGF0TGVmdCA9PSBsdHI7XG4gICAgICBjaCA9IGNoQXJvdW5kICsgKGF0U3RhcnQgPyAwIDogMSk7XG4gICAgICBzdGlja3kgPSBhdFN0YXJ0ID8gXCJhZnRlclwiIDogXCJiZWZvcmVcIjtcbiAgICAgIGJhc2VYID0gYXRMZWZ0ID8gYm94QXJvdW5kLmxlZnQgOiBib3hBcm91bmQucmlnaHQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIChBZGp1c3QgZm9yIGV4dGVuZGVkIGJvdW5kLCBpZiBuZWNlc3NhcnkuKVxuICAgICAgaWYgKCFsdHIgJiYgKGNoID09IGVuZCB8fCBjaCA9PSBiZWdpbikpIHsgY2grKzsgfVxuICAgICAgLy8gVG8gZGV0ZXJtaW5lIHdoaWNoIHNpZGUgdG8gYXNzb2NpYXRlIHdpdGgsIGdldCB0aGUgYm94IHRvIHRoZVxuICAgICAgLy8gbGVmdCBvZiB0aGUgY2hhcmFjdGVyIGFuZCBjb21wYXJlIGl0J3MgdmVydGljYWwgcG9zaXRpb24gdG8gdGhlXG4gICAgICAvLyBjb29yZGluYXRlc1xuICAgICAgc3RpY2t5ID0gY2ggPT0gMCA/IFwiYWZ0ZXJcIiA6IGNoID09IGxpbmVPYmoudGV4dC5sZW5ndGggPyBcImJlZm9yZVwiIDpcbiAgICAgICAgKG1lYXN1cmVDaGFyUHJlcGFyZWQoY20sIHByZXBhcmVkTWVhc3VyZSwgY2ggLSAobHRyID8gMSA6IDApKS5ib3R0b20gKyB3aWRnZXRIZWlnaHQgPD0geSkgPT0gbHRyID9cbiAgICAgICAgXCJhZnRlclwiIDogXCJiZWZvcmVcIjtcbiAgICAgIC8vIE5vdyBnZXQgYWNjdXJhdGUgY29vcmRpbmF0ZXMgZm9yIHRoaXMgcGxhY2UsIGluIG9yZGVyIHRvIGdldCBhXG4gICAgICAvLyBiYXNlIFggcG9zaXRpb25cbiAgICAgIHZhciBjb29yZHMgPSBjdXJzb3JDb29yZHMoY20sIFBvcyhsaW5lTm8sIGNoLCBzdGlja3kpLCBcImxpbmVcIiwgbGluZU9iaiwgcHJlcGFyZWRNZWFzdXJlKTtcbiAgICAgIGJhc2VYID0gY29vcmRzLmxlZnQ7XG4gICAgICBvdXRzaWRlID0geSA8IGNvb3Jkcy50b3AgPyAtMSA6IHkgPj0gY29vcmRzLmJvdHRvbSA/IDEgOiAwO1xuICAgIH1cblxuICAgIGNoID0gc2tpcEV4dGVuZGluZ0NoYXJzKGxpbmVPYmoudGV4dCwgY2gsIDEpO1xuICAgIHJldHVybiBQb3NXaXRoSW5mbyhsaW5lTm8sIGNoLCBzdGlja3ksIG91dHNpZGUsIHggLSBiYXNlWClcbiAgfVxuXG4gIGZ1bmN0aW9uIGNvb3Jkc0JpZGlQYXJ0KGNtLCBsaW5lT2JqLCBsaW5lTm8sIHByZXBhcmVkTWVhc3VyZSwgb3JkZXIsIHgsIHkpIHtcbiAgICAvLyBCaWRpIHBhcnRzIGFyZSBzb3J0ZWQgbGVmdC10by1yaWdodCwgYW5kIGluIGEgbm9uLWxpbmUtd3JhcHBpbmdcbiAgICAvLyBzaXR1YXRpb24sIHdlIGNhbiB0YWtlIHRoaXMgb3JkZXJpbmcgdG8gY29ycmVzcG9uZCB0byB0aGUgdmlzdWFsXG4gICAgLy8gb3JkZXJpbmcuIFRoaXMgZmluZHMgdGhlIGZpcnN0IHBhcnQgd2hvc2UgZW5kIGlzIGFmdGVyIHRoZSBnaXZlblxuICAgIC8vIGNvb3JkaW5hdGVzLlxuICAgIHZhciBpbmRleCA9IGZpbmRGaXJzdChmdW5jdGlvbiAoaSkge1xuICAgICAgdmFyIHBhcnQgPSBvcmRlcltpXSwgbHRyID0gcGFydC5sZXZlbCAhPSAxO1xuICAgICAgcmV0dXJuIGJveElzQWZ0ZXIoY3Vyc29yQ29vcmRzKGNtLCBQb3MobGluZU5vLCBsdHIgPyBwYXJ0LnRvIDogcGFydC5mcm9tLCBsdHIgPyBcImJlZm9yZVwiIDogXCJhZnRlclwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImxpbmVcIiwgbGluZU9iaiwgcHJlcGFyZWRNZWFzdXJlKSwgeCwgeSwgdHJ1ZSlcbiAgICB9LCAwLCBvcmRlci5sZW5ndGggLSAxKTtcbiAgICB2YXIgcGFydCA9IG9yZGVyW2luZGV4XTtcbiAgICAvLyBJZiB0aGlzIGlzbid0IHRoZSBmaXJzdCBwYXJ0LCB0aGUgcGFydCdzIHN0YXJ0IGlzIGFsc28gYWZ0ZXJcbiAgICAvLyB0aGUgY29vcmRpbmF0ZXMsIGFuZCB0aGUgY29vcmRpbmF0ZXMgYXJlbid0IG9uIHRoZSBzYW1lIGxpbmUgYXNcbiAgICAvLyB0aGF0IHN0YXJ0LCBtb3ZlIG9uZSBwYXJ0IGJhY2suXG4gICAgaWYgKGluZGV4ID4gMCkge1xuICAgICAgdmFyIGx0ciA9IHBhcnQubGV2ZWwgIT0gMTtcbiAgICAgIHZhciBzdGFydCA9IGN1cnNvckNvb3JkcyhjbSwgUG9zKGxpbmVObywgbHRyID8gcGFydC5mcm9tIDogcGFydC50bywgbHRyID8gXCJhZnRlclwiIDogXCJiZWZvcmVcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJsaW5lXCIsIGxpbmVPYmosIHByZXBhcmVkTWVhc3VyZSk7XG4gICAgICBpZiAoYm94SXNBZnRlcihzdGFydCwgeCwgeSwgdHJ1ZSkgJiYgc3RhcnQudG9wID4geSlcbiAgICAgICAgeyBwYXJ0ID0gb3JkZXJbaW5kZXggLSAxXTsgfVxuICAgIH1cbiAgICByZXR1cm4gcGFydFxuICB9XG5cbiAgZnVuY3Rpb24gY29vcmRzQmlkaVBhcnRXcmFwcGVkKGNtLCBsaW5lT2JqLCBfbGluZU5vLCBwcmVwYXJlZE1lYXN1cmUsIG9yZGVyLCB4LCB5KSB7XG4gICAgLy8gSW4gYSB3cmFwcGVkIGxpbmUsIHJ0bCB0ZXh0IG9uIHdyYXBwaW5nIGJvdW5kYXJpZXMgY2FuIGRvIHRoaW5nc1xuICAgIC8vIHRoYXQgZG9uJ3QgY29ycmVzcG9uZCB0byB0aGUgb3JkZXJpbmcgaW4gb3VyIGBvcmRlcmAgYXJyYXkgYXRcbiAgICAvLyBhbGwsIHNvIGEgYmluYXJ5IHNlYXJjaCBkb2Vzbid0IHdvcmssIGFuZCB3ZSB3YW50IHRvIHJldHVybiBhXG4gICAgLy8gcGFydCB0aGF0IG9ubHkgc3BhbnMgb25lIGxpbmUgc28gdGhhdCB0aGUgYmluYXJ5IHNlYXJjaCBpblxuICAgIC8vIGNvb3Jkc0NoYXJJbm5lciBpcyBzYWZlLiBBcyBzdWNoLCB3ZSBmaXJzdCBmaW5kIHRoZSBleHRlbnQgb2YgdGhlXG4gICAgLy8gd3JhcHBlZCBsaW5lLCBhbmQgdGhlbiBkbyBhIGZsYXQgc2VhcmNoIGluIHdoaWNoIHdlIGRpc2NhcmQgYW55XG4gICAgLy8gc3BhbnMgdGhhdCBhcmVuJ3Qgb24gdGhlIGxpbmUuXG4gICAgdmFyIHJlZiA9IHdyYXBwZWRMaW5lRXh0ZW50KGNtLCBsaW5lT2JqLCBwcmVwYXJlZE1lYXN1cmUsIHkpO1xuICAgIHZhciBiZWdpbiA9IHJlZi5iZWdpbjtcbiAgICB2YXIgZW5kID0gcmVmLmVuZDtcbiAgICBpZiAoL1xccy8udGVzdChsaW5lT2JqLnRleHQuY2hhckF0KGVuZCAtIDEpKSkgeyBlbmQtLTsgfVxuICAgIHZhciBwYXJ0ID0gbnVsbCwgY2xvc2VzdERpc3QgPSBudWxsO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3JkZXIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBwID0gb3JkZXJbaV07XG4gICAgICBpZiAocC5mcm9tID49IGVuZCB8fCBwLnRvIDw9IGJlZ2luKSB7IGNvbnRpbnVlIH1cbiAgICAgIHZhciBsdHIgPSBwLmxldmVsICE9IDE7XG4gICAgICB2YXIgZW5kWCA9IG1lYXN1cmVDaGFyUHJlcGFyZWQoY20sIHByZXBhcmVkTWVhc3VyZSwgbHRyID8gTWF0aC5taW4oZW5kLCBwLnRvKSAtIDEgOiBNYXRoLm1heChiZWdpbiwgcC5mcm9tKSkucmlnaHQ7XG4gICAgICAvLyBXZWlnaCBhZ2FpbnN0IHNwYW5zIGVuZGluZyBiZWZvcmUgdGhpcywgc28gdGhhdCB0aGV5IGFyZSBvbmx5XG4gICAgICAvLyBwaWNrZWQgaWYgbm90aGluZyBlbmRzIGFmdGVyXG4gICAgICB2YXIgZGlzdCA9IGVuZFggPCB4ID8geCAtIGVuZFggKyAxZTkgOiBlbmRYIC0geDtcbiAgICAgIGlmICghcGFydCB8fCBjbG9zZXN0RGlzdCA+IGRpc3QpIHtcbiAgICAgICAgcGFydCA9IHA7XG4gICAgICAgIGNsb3Nlc3REaXN0ID0gZGlzdDtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFwYXJ0KSB7IHBhcnQgPSBvcmRlcltvcmRlci5sZW5ndGggLSAxXTsgfVxuICAgIC8vIENsaXAgdGhlIHBhcnQgdG8gdGhlIHdyYXBwZWQgbGluZS5cbiAgICBpZiAocGFydC5mcm9tIDwgYmVnaW4pIHsgcGFydCA9IHtmcm9tOiBiZWdpbiwgdG86IHBhcnQudG8sIGxldmVsOiBwYXJ0LmxldmVsfTsgfVxuICAgIGlmIChwYXJ0LnRvID4gZW5kKSB7IHBhcnQgPSB7ZnJvbTogcGFydC5mcm9tLCB0bzogZW5kLCBsZXZlbDogcGFydC5sZXZlbH07IH1cbiAgICByZXR1cm4gcGFydFxuICB9XG5cbiAgdmFyIG1lYXN1cmVUZXh0O1xuICAvLyBDb21wdXRlIHRoZSBkZWZhdWx0IHRleHQgaGVpZ2h0LlxuICBmdW5jdGlvbiB0ZXh0SGVpZ2h0KGRpc3BsYXkpIHtcbiAgICBpZiAoZGlzcGxheS5jYWNoZWRUZXh0SGVpZ2h0ICE9IG51bGwpIHsgcmV0dXJuIGRpc3BsYXkuY2FjaGVkVGV4dEhlaWdodCB9XG4gICAgaWYgKG1lYXN1cmVUZXh0ID09IG51bGwpIHtcbiAgICAgIG1lYXN1cmVUZXh0ID0gZWx0KFwicHJlXCIsIG51bGwsIFwiQ29kZU1pcnJvci1saW5lLWxpa2VcIik7XG4gICAgICAvLyBNZWFzdXJlIGEgYnVuY2ggb2YgbGluZXMsIGZvciBicm93c2VycyB0aGF0IGNvbXB1dGVcbiAgICAgIC8vIGZyYWN0aW9uYWwgaGVpZ2h0cy5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgNDk7ICsraSkge1xuICAgICAgICBtZWFzdXJlVGV4dC5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShcInhcIikpO1xuICAgICAgICBtZWFzdXJlVGV4dC5hcHBlbmRDaGlsZChlbHQoXCJiclwiKSk7XG4gICAgICB9XG4gICAgICBtZWFzdXJlVGV4dC5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShcInhcIikpO1xuICAgIH1cbiAgICByZW1vdmVDaGlsZHJlbkFuZEFkZChkaXNwbGF5Lm1lYXN1cmUsIG1lYXN1cmVUZXh0KTtcbiAgICB2YXIgaGVpZ2h0ID0gbWVhc3VyZVRleHQub2Zmc2V0SGVpZ2h0IC8gNTA7XG4gICAgaWYgKGhlaWdodCA+IDMpIHsgZGlzcGxheS5jYWNoZWRUZXh0SGVpZ2h0ID0gaGVpZ2h0OyB9XG4gICAgcmVtb3ZlQ2hpbGRyZW4oZGlzcGxheS5tZWFzdXJlKTtcbiAgICByZXR1cm4gaGVpZ2h0IHx8IDFcbiAgfVxuXG4gIC8vIENvbXB1dGUgdGhlIGRlZmF1bHQgY2hhcmFjdGVyIHdpZHRoLlxuICBmdW5jdGlvbiBjaGFyV2lkdGgoZGlzcGxheSkge1xuICAgIGlmIChkaXNwbGF5LmNhY2hlZENoYXJXaWR0aCAhPSBudWxsKSB7IHJldHVybiBkaXNwbGF5LmNhY2hlZENoYXJXaWR0aCB9XG4gICAgdmFyIGFuY2hvciA9IGVsdChcInNwYW5cIiwgXCJ4eHh4eHh4eHh4XCIpO1xuICAgIHZhciBwcmUgPSBlbHQoXCJwcmVcIiwgW2FuY2hvcl0sIFwiQ29kZU1pcnJvci1saW5lLWxpa2VcIik7XG4gICAgcmVtb3ZlQ2hpbGRyZW5BbmRBZGQoZGlzcGxheS5tZWFzdXJlLCBwcmUpO1xuICAgIHZhciByZWN0ID0gYW5jaG9yLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLCB3aWR0aCA9IChyZWN0LnJpZ2h0IC0gcmVjdC5sZWZ0KSAvIDEwO1xuICAgIGlmICh3aWR0aCA+IDIpIHsgZGlzcGxheS5jYWNoZWRDaGFyV2lkdGggPSB3aWR0aDsgfVxuICAgIHJldHVybiB3aWR0aCB8fCAxMFxuICB9XG5cbiAgLy8gRG8gYSBidWxrLXJlYWQgb2YgdGhlIERPTSBwb3NpdGlvbnMgYW5kIHNpemVzIG5lZWRlZCB0byBkcmF3IHRoZVxuICAvLyB2aWV3LCBzbyB0aGF0IHdlIGRvbid0IGludGVybGVhdmUgcmVhZGluZyBhbmQgd3JpdGluZyB0byB0aGUgRE9NLlxuICBmdW5jdGlvbiBnZXREaW1lbnNpb25zKGNtKSB7XG4gICAgdmFyIGQgPSBjbS5kaXNwbGF5LCBsZWZ0ID0ge30sIHdpZHRoID0ge307XG4gICAgdmFyIGd1dHRlckxlZnQgPSBkLmd1dHRlcnMuY2xpZW50TGVmdDtcbiAgICBmb3IgKHZhciBuID0gZC5ndXR0ZXJzLmZpcnN0Q2hpbGQsIGkgPSAwOyBuOyBuID0gbi5uZXh0U2libGluZywgKytpKSB7XG4gICAgICB2YXIgaWQgPSBjbS5kaXNwbGF5Lmd1dHRlclNwZWNzW2ldLmNsYXNzTmFtZTtcbiAgICAgIGxlZnRbaWRdID0gbi5vZmZzZXRMZWZ0ICsgbi5jbGllbnRMZWZ0ICsgZ3V0dGVyTGVmdDtcbiAgICAgIHdpZHRoW2lkXSA9IG4uY2xpZW50V2lkdGg7XG4gICAgfVxuICAgIHJldHVybiB7Zml4ZWRQb3M6IGNvbXBlbnNhdGVGb3JIU2Nyb2xsKGQpLFxuICAgICAgICAgICAgZ3V0dGVyVG90YWxXaWR0aDogZC5ndXR0ZXJzLm9mZnNldFdpZHRoLFxuICAgICAgICAgICAgZ3V0dGVyTGVmdDogbGVmdCxcbiAgICAgICAgICAgIGd1dHRlcldpZHRoOiB3aWR0aCxcbiAgICAgICAgICAgIHdyYXBwZXJXaWR0aDogZC53cmFwcGVyLmNsaWVudFdpZHRofVxuICB9XG5cbiAgLy8gQ29tcHV0ZXMgZGlzcGxheS5zY3JvbGxlci5zY3JvbGxMZWZ0ICsgZGlzcGxheS5ndXR0ZXJzLm9mZnNldFdpZHRoLFxuICAvLyBidXQgdXNpbmcgZ2V0Qm91bmRpbmdDbGllbnRSZWN0IHRvIGdldCBhIHN1Yi1waXhlbC1hY2N1cmF0ZVxuICAvLyByZXN1bHQuXG4gIGZ1bmN0aW9uIGNvbXBlbnNhdGVGb3JIU2Nyb2xsKGRpc3BsYXkpIHtcbiAgICByZXR1cm4gZGlzcGxheS5zY3JvbGxlci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0IC0gZGlzcGxheS5zaXplci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0XG4gIH1cblxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCBlc3RpbWF0ZXMgdGhlIGhlaWdodCBvZiBhIGxpbmUsIHRvIHVzZSBhc1xuICAvLyBmaXJzdCBhcHByb3hpbWF0aW9uIHVudGlsIHRoZSBsaW5lIGJlY29tZXMgdmlzaWJsZSAoYW5kIGlzIHRodXNcbiAgLy8gcHJvcGVybHkgbWVhc3VyYWJsZSkuXG4gIGZ1bmN0aW9uIGVzdGltYXRlSGVpZ2h0KGNtKSB7XG4gICAgdmFyIHRoID0gdGV4dEhlaWdodChjbS5kaXNwbGF5KSwgd3JhcHBpbmcgPSBjbS5vcHRpb25zLmxpbmVXcmFwcGluZztcbiAgICB2YXIgcGVyTGluZSA9IHdyYXBwaW5nICYmIE1hdGgubWF4KDUsIGNtLmRpc3BsYXkuc2Nyb2xsZXIuY2xpZW50V2lkdGggLyBjaGFyV2lkdGgoY20uZGlzcGxheSkgLSAzKTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGxpbmUpIHtcbiAgICAgIGlmIChsaW5lSXNIaWRkZW4oY20uZG9jLCBsaW5lKSkgeyByZXR1cm4gMCB9XG5cbiAgICAgIHZhciB3aWRnZXRzSGVpZ2h0ID0gMDtcbiAgICAgIGlmIChsaW5lLndpZGdldHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lLndpZGdldHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKGxpbmUud2lkZ2V0c1tpXS5oZWlnaHQpIHsgd2lkZ2V0c0hlaWdodCArPSBsaW5lLndpZGdldHNbaV0uaGVpZ2h0OyB9XG4gICAgICB9IH1cblxuICAgICAgaWYgKHdyYXBwaW5nKVxuICAgICAgICB7IHJldHVybiB3aWRnZXRzSGVpZ2h0ICsgKE1hdGguY2VpbChsaW5lLnRleHQubGVuZ3RoIC8gcGVyTGluZSkgfHwgMSkgKiB0aCB9XG4gICAgICBlbHNlXG4gICAgICAgIHsgcmV0dXJuIHdpZGdldHNIZWlnaHQgKyB0aCB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gZXN0aW1hdGVMaW5lSGVpZ2h0cyhjbSkge1xuICAgIHZhciBkb2MgPSBjbS5kb2MsIGVzdCA9IGVzdGltYXRlSGVpZ2h0KGNtKTtcbiAgICBkb2MuaXRlcihmdW5jdGlvbiAobGluZSkge1xuICAgICAgdmFyIGVzdEhlaWdodCA9IGVzdChsaW5lKTtcbiAgICAgIGlmIChlc3RIZWlnaHQgIT0gbGluZS5oZWlnaHQpIHsgdXBkYXRlTGluZUhlaWdodChsaW5lLCBlc3RIZWlnaHQpOyB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBHaXZlbiBhIG1vdXNlIGV2ZW50LCBmaW5kIHRoZSBjb3JyZXNwb25kaW5nIHBvc2l0aW9uLiBJZiBsaWJlcmFsXG4gIC8vIGlzIGZhbHNlLCBpdCBjaGVja3Mgd2hldGhlciBhIGd1dHRlciBvciBzY3JvbGxiYXIgd2FzIGNsaWNrZWQsXG4gIC8vIGFuZCByZXR1cm5zIG51bGwgaWYgaXQgd2FzLiBmb3JSZWN0IGlzIHVzZWQgYnkgcmVjdGFuZ3VsYXJcbiAgLy8gc2VsZWN0aW9ucywgYW5kIHRyaWVzIHRvIGVzdGltYXRlIGEgY2hhcmFjdGVyIHBvc2l0aW9uIGV2ZW4gZm9yXG4gIC8vIGNvb3JkaW5hdGVzIGJleW9uZCB0aGUgcmlnaHQgb2YgdGhlIHRleHQuXG4gIGZ1bmN0aW9uIHBvc0Zyb21Nb3VzZShjbSwgZSwgbGliZXJhbCwgZm9yUmVjdCkge1xuICAgIHZhciBkaXNwbGF5ID0gY20uZGlzcGxheTtcbiAgICBpZiAoIWxpYmVyYWwgJiYgZV90YXJnZXQoZSkuZ2V0QXR0cmlidXRlKFwiY20tbm90LWNvbnRlbnRcIikgPT0gXCJ0cnVlXCIpIHsgcmV0dXJuIG51bGwgfVxuXG4gICAgdmFyIHgsIHksIHNwYWNlID0gZGlzcGxheS5saW5lU3BhY2UuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgLy8gRmFpbHMgdW5wcmVkaWN0YWJseSBvbiBJRVs2N10gd2hlbiBtb3VzZSBpcyBkcmFnZ2VkIGFyb3VuZCBxdWlja2x5LlxuICAgIHRyeSB7IHggPSBlLmNsaWVudFggLSBzcGFjZS5sZWZ0OyB5ID0gZS5jbGllbnRZIC0gc3BhY2UudG9wOyB9XG4gICAgY2F0Y2ggKGUkMSkgeyByZXR1cm4gbnVsbCB9XG4gICAgdmFyIGNvb3JkcyA9IGNvb3Jkc0NoYXIoY20sIHgsIHkpLCBsaW5lO1xuICAgIGlmIChmb3JSZWN0ICYmIGNvb3Jkcy54UmVsID4gMCAmJiAobGluZSA9IGdldExpbmUoY20uZG9jLCBjb29yZHMubGluZSkudGV4dCkubGVuZ3RoID09IGNvb3Jkcy5jaCkge1xuICAgICAgdmFyIGNvbERpZmYgPSBjb3VudENvbHVtbihsaW5lLCBsaW5lLmxlbmd0aCwgY20ub3B0aW9ucy50YWJTaXplKSAtIGxpbmUubGVuZ3RoO1xuICAgICAgY29vcmRzID0gUG9zKGNvb3Jkcy5saW5lLCBNYXRoLm1heCgwLCBNYXRoLnJvdW5kKCh4IC0gcGFkZGluZ0goY20uZGlzcGxheSkubGVmdCkgLyBjaGFyV2lkdGgoY20uZGlzcGxheSkpIC0gY29sRGlmZikpO1xuICAgIH1cbiAgICByZXR1cm4gY29vcmRzXG4gIH1cblxuICAvLyBGaW5kIHRoZSB2aWV3IGVsZW1lbnQgY29ycmVzcG9uZGluZyB0byBhIGdpdmVuIGxpbmUuIFJldHVybiBudWxsXG4gIC8vIHdoZW4gdGhlIGxpbmUgaXNuJ3QgdmlzaWJsZS5cbiAgZnVuY3Rpb24gZmluZFZpZXdJbmRleChjbSwgbikge1xuICAgIGlmIChuID49IGNtLmRpc3BsYXkudmlld1RvKSB7IHJldHVybiBudWxsIH1cbiAgICBuIC09IGNtLmRpc3BsYXkudmlld0Zyb207XG4gICAgaWYgKG4gPCAwKSB7IHJldHVybiBudWxsIH1cbiAgICB2YXIgdmlldyA9IGNtLmRpc3BsYXkudmlldztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHZpZXcubGVuZ3RoOyBpKyspIHtcbiAgICAgIG4gLT0gdmlld1tpXS5zaXplO1xuICAgICAgaWYgKG4gPCAwKSB7IHJldHVybiBpIH1cbiAgICB9XG4gIH1cblxuICAvLyBVcGRhdGVzIHRoZSBkaXNwbGF5LnZpZXcgZGF0YSBzdHJ1Y3R1cmUgZm9yIGEgZ2l2ZW4gY2hhbmdlIHRvIHRoZVxuICAvLyBkb2N1bWVudC4gRnJvbSBhbmQgdG8gYXJlIGluIHByZS1jaGFuZ2UgY29vcmRpbmF0ZXMuIExlbmRpZmYgaXNcbiAgLy8gdGhlIGFtb3VudCBvZiBsaW5lcyBhZGRlZCBvciBzdWJ0cmFjdGVkIGJ5IHRoZSBjaGFuZ2UuIFRoaXMgaXNcbiAgLy8gdXNlZCBmb3IgY2hhbmdlcyB0aGF0IHNwYW4gbXVsdGlwbGUgbGluZXMsIG9yIGNoYW5nZSB0aGUgd2F5XG4gIC8vIGxpbmVzIGFyZSBkaXZpZGVkIGludG8gdmlzdWFsIGxpbmVzLiByZWdMaW5lQ2hhbmdlIChiZWxvdylcbiAgLy8gcmVnaXN0ZXJzIHNpbmdsZS1saW5lIGNoYW5nZXMuXG4gIGZ1bmN0aW9uIHJlZ0NoYW5nZShjbSwgZnJvbSwgdG8sIGxlbmRpZmYpIHtcbiAgICBpZiAoZnJvbSA9PSBudWxsKSB7IGZyb20gPSBjbS5kb2MuZmlyc3Q7IH1cbiAgICBpZiAodG8gPT0gbnVsbCkgeyB0byA9IGNtLmRvYy5maXJzdCArIGNtLmRvYy5zaXplOyB9XG4gICAgaWYgKCFsZW5kaWZmKSB7IGxlbmRpZmYgPSAwOyB9XG5cbiAgICB2YXIgZGlzcGxheSA9IGNtLmRpc3BsYXk7XG4gICAgaWYgKGxlbmRpZmYgJiYgdG8gPCBkaXNwbGF5LnZpZXdUbyAmJlxuICAgICAgICAoZGlzcGxheS51cGRhdGVMaW5lTnVtYmVycyA9PSBudWxsIHx8IGRpc3BsYXkudXBkYXRlTGluZU51bWJlcnMgPiBmcm9tKSlcbiAgICAgIHsgZGlzcGxheS51cGRhdGVMaW5lTnVtYmVycyA9IGZyb207IH1cblxuICAgIGNtLmN1ck9wLnZpZXdDaGFuZ2VkID0gdHJ1ZTtcblxuICAgIGlmIChmcm9tID49IGRpc3BsYXkudmlld1RvKSB7IC8vIENoYW5nZSBhZnRlclxuICAgICAgaWYgKHNhd0NvbGxhcHNlZFNwYW5zICYmIHZpc3VhbExpbmVObyhjbS5kb2MsIGZyb20pIDwgZGlzcGxheS52aWV3VG8pXG4gICAgICAgIHsgcmVzZXRWaWV3KGNtKTsgfVxuICAgIH0gZWxzZSBpZiAodG8gPD0gZGlzcGxheS52aWV3RnJvbSkgeyAvLyBDaGFuZ2UgYmVmb3JlXG4gICAgICBpZiAoc2F3Q29sbGFwc2VkU3BhbnMgJiYgdmlzdWFsTGluZUVuZE5vKGNtLmRvYywgdG8gKyBsZW5kaWZmKSA+IGRpc3BsYXkudmlld0Zyb20pIHtcbiAgICAgICAgcmVzZXRWaWV3KGNtKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRpc3BsYXkudmlld0Zyb20gKz0gbGVuZGlmZjtcbiAgICAgICAgZGlzcGxheS52aWV3VG8gKz0gbGVuZGlmZjtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGZyb20gPD0gZGlzcGxheS52aWV3RnJvbSAmJiB0byA+PSBkaXNwbGF5LnZpZXdUbykgeyAvLyBGdWxsIG92ZXJsYXBcbiAgICAgIHJlc2V0VmlldyhjbSk7XG4gICAgfSBlbHNlIGlmIChmcm9tIDw9IGRpc3BsYXkudmlld0Zyb20pIHsgLy8gVG9wIG92ZXJsYXBcbiAgICAgIHZhciBjdXQgPSB2aWV3Q3V0dGluZ1BvaW50KGNtLCB0bywgdG8gKyBsZW5kaWZmLCAxKTtcbiAgICAgIGlmIChjdXQpIHtcbiAgICAgICAgZGlzcGxheS52aWV3ID0gZGlzcGxheS52aWV3LnNsaWNlKGN1dC5pbmRleCk7XG4gICAgICAgIGRpc3BsYXkudmlld0Zyb20gPSBjdXQubGluZU47XG4gICAgICAgIGRpc3BsYXkudmlld1RvICs9IGxlbmRpZmY7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNldFZpZXcoY20pO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodG8gPj0gZGlzcGxheS52aWV3VG8pIHsgLy8gQm90dG9tIG92ZXJsYXBcbiAgICAgIHZhciBjdXQkMSA9IHZpZXdDdXR0aW5nUG9pbnQoY20sIGZyb20sIGZyb20sIC0xKTtcbiAgICAgIGlmIChjdXQkMSkge1xuICAgICAgICBkaXNwbGF5LnZpZXcgPSBkaXNwbGF5LnZpZXcuc2xpY2UoMCwgY3V0JDEuaW5kZXgpO1xuICAgICAgICBkaXNwbGF5LnZpZXdUbyA9IGN1dCQxLmxpbmVOO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzZXRWaWV3KGNtKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgeyAvLyBHYXAgaW4gdGhlIG1pZGRsZVxuICAgICAgdmFyIGN1dFRvcCA9IHZpZXdDdXR0aW5nUG9pbnQoY20sIGZyb20sIGZyb20sIC0xKTtcbiAgICAgIHZhciBjdXRCb3QgPSB2aWV3Q3V0dGluZ1BvaW50KGNtLCB0bywgdG8gKyBsZW5kaWZmLCAxKTtcbiAgICAgIGlmIChjdXRUb3AgJiYgY3V0Qm90KSB7XG4gICAgICAgIGRpc3BsYXkudmlldyA9IGRpc3BsYXkudmlldy5zbGljZSgwLCBjdXRUb3AuaW5kZXgpXG4gICAgICAgICAgLmNvbmNhdChidWlsZFZpZXdBcnJheShjbSwgY3V0VG9wLmxpbmVOLCBjdXRCb3QubGluZU4pKVxuICAgICAgICAgIC5jb25jYXQoZGlzcGxheS52aWV3LnNsaWNlKGN1dEJvdC5pbmRleCkpO1xuICAgICAgICBkaXNwbGF5LnZpZXdUbyArPSBsZW5kaWZmO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzZXRWaWV3KGNtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgZXh0ID0gZGlzcGxheS5leHRlcm5hbE1lYXN1cmVkO1xuICAgIGlmIChleHQpIHtcbiAgICAgIGlmICh0byA8IGV4dC5saW5lTilcbiAgICAgICAgeyBleHQubGluZU4gKz0gbGVuZGlmZjsgfVxuICAgICAgZWxzZSBpZiAoZnJvbSA8IGV4dC5saW5lTiArIGV4dC5zaXplKVxuICAgICAgICB7IGRpc3BsYXkuZXh0ZXJuYWxNZWFzdXJlZCA9IG51bGw7IH1cbiAgICB9XG4gIH1cblxuICAvLyBSZWdpc3RlciBhIGNoYW5nZSB0byBhIHNpbmdsZSBsaW5lLiBUeXBlIG11c3QgYmUgb25lIG9mIFwidGV4dFwiLFxuICAvLyBcImd1dHRlclwiLCBcImNsYXNzXCIsIFwid2lkZ2V0XCJcbiAgZnVuY3Rpb24gcmVnTGluZUNoYW5nZShjbSwgbGluZSwgdHlwZSkge1xuICAgIGNtLmN1ck9wLnZpZXdDaGFuZ2VkID0gdHJ1ZTtcbiAgICB2YXIgZGlzcGxheSA9IGNtLmRpc3BsYXksIGV4dCA9IGNtLmRpc3BsYXkuZXh0ZXJuYWxNZWFzdXJlZDtcbiAgICBpZiAoZXh0ICYmIGxpbmUgPj0gZXh0LmxpbmVOICYmIGxpbmUgPCBleHQubGluZU4gKyBleHQuc2l6ZSlcbiAgICAgIHsgZGlzcGxheS5leHRlcm5hbE1lYXN1cmVkID0gbnVsbDsgfVxuXG4gICAgaWYgKGxpbmUgPCBkaXNwbGF5LnZpZXdGcm9tIHx8IGxpbmUgPj0gZGlzcGxheS52aWV3VG8pIHsgcmV0dXJuIH1cbiAgICB2YXIgbGluZVZpZXcgPSBkaXNwbGF5LnZpZXdbZmluZFZpZXdJbmRleChjbSwgbGluZSldO1xuICAgIGlmIChsaW5lVmlldy5ub2RlID09IG51bGwpIHsgcmV0dXJuIH1cbiAgICB2YXIgYXJyID0gbGluZVZpZXcuY2hhbmdlcyB8fCAobGluZVZpZXcuY2hhbmdlcyA9IFtdKTtcbiAgICBpZiAoaW5kZXhPZihhcnIsIHR5cGUpID09IC0xKSB7IGFyci5wdXNoKHR5cGUpOyB9XG4gIH1cblxuICAvLyBDbGVhciB0aGUgdmlldy5cbiAgZnVuY3Rpb24gcmVzZXRWaWV3KGNtKSB7XG4gICAgY20uZGlzcGxheS52aWV3RnJvbSA9IGNtLmRpc3BsYXkudmlld1RvID0gY20uZG9jLmZpcnN0O1xuICAgIGNtLmRpc3BsYXkudmlldyA9IFtdO1xuICAgIGNtLmRpc3BsYXkudmlld09mZnNldCA9IDA7XG4gIH1cblxuICBmdW5jdGlvbiB2aWV3Q3V0dGluZ1BvaW50KGNtLCBvbGROLCBuZXdOLCBkaXIpIHtcbiAgICB2YXIgaW5kZXggPSBmaW5kVmlld0luZGV4KGNtLCBvbGROKSwgZGlmZiwgdmlldyA9IGNtLmRpc3BsYXkudmlldztcbiAgICBpZiAoIXNhd0NvbGxhcHNlZFNwYW5zIHx8IG5ld04gPT0gY20uZG9jLmZpcnN0ICsgY20uZG9jLnNpemUpXG4gICAgICB7IHJldHVybiB7aW5kZXg6IGluZGV4LCBsaW5lTjogbmV3Tn0gfVxuICAgIHZhciBuID0gY20uZGlzcGxheS52aWV3RnJvbTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluZGV4OyBpKyspXG4gICAgICB7IG4gKz0gdmlld1tpXS5zaXplOyB9XG4gICAgaWYgKG4gIT0gb2xkTikge1xuICAgICAgaWYgKGRpciA+IDApIHtcbiAgICAgICAgaWYgKGluZGV4ID09IHZpZXcubGVuZ3RoIC0gMSkgeyByZXR1cm4gbnVsbCB9XG4gICAgICAgIGRpZmYgPSAobiArIHZpZXdbaW5kZXhdLnNpemUpIC0gb2xkTjtcbiAgICAgICAgaW5kZXgrKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRpZmYgPSBuIC0gb2xkTjtcbiAgICAgIH1cbiAgICAgIG9sZE4gKz0gZGlmZjsgbmV3TiArPSBkaWZmO1xuICAgIH1cbiAgICB3aGlsZSAodmlzdWFsTGluZU5vKGNtLmRvYywgbmV3TikgIT0gbmV3Tikge1xuICAgICAgaWYgKGluZGV4ID09IChkaXIgPCAwID8gMCA6IHZpZXcubGVuZ3RoIC0gMSkpIHsgcmV0dXJuIG51bGwgfVxuICAgICAgbmV3TiArPSBkaXIgKiB2aWV3W2luZGV4IC0gKGRpciA8IDAgPyAxIDogMCldLnNpemU7XG4gICAgICBpbmRleCArPSBkaXI7XG4gICAgfVxuICAgIHJldHVybiB7aW5kZXg6IGluZGV4LCBsaW5lTjogbmV3Tn1cbiAgfVxuXG4gIC8vIEZvcmNlIHRoZSB2aWV3IHRvIGNvdmVyIGEgZ2l2ZW4gcmFuZ2UsIGFkZGluZyBlbXB0eSB2aWV3IGVsZW1lbnRcbiAgLy8gb3IgY2xpcHBpbmcgb2ZmIGV4aXN0aW5nIG9uZXMgYXMgbmVlZGVkLlxuICBmdW5jdGlvbiBhZGp1c3RWaWV3KGNtLCBmcm9tLCB0bykge1xuICAgIHZhciBkaXNwbGF5ID0gY20uZGlzcGxheSwgdmlldyA9IGRpc3BsYXkudmlldztcbiAgICBpZiAodmlldy5sZW5ndGggPT0gMCB8fCBmcm9tID49IGRpc3BsYXkudmlld1RvIHx8IHRvIDw9IGRpc3BsYXkudmlld0Zyb20pIHtcbiAgICAgIGRpc3BsYXkudmlldyA9IGJ1aWxkVmlld0FycmF5KGNtLCBmcm9tLCB0byk7XG4gICAgICBkaXNwbGF5LnZpZXdGcm9tID0gZnJvbTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGRpc3BsYXkudmlld0Zyb20gPiBmcm9tKVxuICAgICAgICB7IGRpc3BsYXkudmlldyA9IGJ1aWxkVmlld0FycmF5KGNtLCBmcm9tLCBkaXNwbGF5LnZpZXdGcm9tKS5jb25jYXQoZGlzcGxheS52aWV3KTsgfVxuICAgICAgZWxzZSBpZiAoZGlzcGxheS52aWV3RnJvbSA8IGZyb20pXG4gICAgICAgIHsgZGlzcGxheS52aWV3ID0gZGlzcGxheS52aWV3LnNsaWNlKGZpbmRWaWV3SW5kZXgoY20sIGZyb20pKTsgfVxuICAgICAgZGlzcGxheS52aWV3RnJvbSA9IGZyb207XG4gICAgICBpZiAoZGlzcGxheS52aWV3VG8gPCB0bylcbiAgICAgICAgeyBkaXNwbGF5LnZpZXcgPSBkaXNwbGF5LnZpZXcuY29uY2F0KGJ1aWxkVmlld0FycmF5KGNtLCBkaXNwbGF5LnZpZXdUbywgdG8pKTsgfVxuICAgICAgZWxzZSBpZiAoZGlzcGxheS52aWV3VG8gPiB0bylcbiAgICAgICAgeyBkaXNwbGF5LnZpZXcgPSBkaXNwbGF5LnZpZXcuc2xpY2UoMCwgZmluZFZpZXdJbmRleChjbSwgdG8pKTsgfVxuICAgIH1cbiAgICBkaXNwbGF5LnZpZXdUbyA9IHRvO1xuICB9XG5cbiAgLy8gQ291bnQgdGhlIG51bWJlciBvZiBsaW5lcyBpbiB0aGUgdmlldyB3aG9zZSBET00gcmVwcmVzZW50YXRpb24gaXNcbiAgLy8gb3V0IG9mIGRhdGUgKG9yIG5vbmV4aXN0ZW50KS5cbiAgZnVuY3Rpb24gY291bnREaXJ0eVZpZXcoY20pIHtcbiAgICB2YXIgdmlldyA9IGNtLmRpc3BsYXkudmlldywgZGlydHkgPSAwO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmlldy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGxpbmVWaWV3ID0gdmlld1tpXTtcbiAgICAgIGlmICghbGluZVZpZXcuaGlkZGVuICYmICghbGluZVZpZXcubm9kZSB8fCBsaW5lVmlldy5jaGFuZ2VzKSkgeyArK2RpcnR5OyB9XG4gICAgfVxuICAgIHJldHVybiBkaXJ0eVxuICB9XG5cbiAgZnVuY3Rpb24gdXBkYXRlU2VsZWN0aW9uKGNtKSB7XG4gICAgY20uZGlzcGxheS5pbnB1dC5zaG93U2VsZWN0aW9uKGNtLmRpc3BsYXkuaW5wdXQucHJlcGFyZVNlbGVjdGlvbigpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHByZXBhcmVTZWxlY3Rpb24oY20sIHByaW1hcnkpIHtcbiAgICBpZiAoIHByaW1hcnkgPT09IHZvaWQgMCApIHByaW1hcnkgPSB0cnVlO1xuXG4gICAgdmFyIGRvYyA9IGNtLmRvYywgcmVzdWx0ID0ge307XG4gICAgdmFyIGN1ckZyYWdtZW50ID0gcmVzdWx0LmN1cnNvcnMgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG4gICAgdmFyIHNlbEZyYWdtZW50ID0gcmVzdWx0LnNlbGVjdGlvbiA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtcblxuICAgIHZhciBjdXN0b21DdXJzb3IgPSBjbS5vcHRpb25zLiRjdXN0b21DdXJzb3I7XG4gICAgaWYgKGN1c3RvbUN1cnNvcikgeyBwcmltYXJ5ID0gdHJ1ZTsgfVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZG9jLnNlbC5yYW5nZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmICghcHJpbWFyeSAmJiBpID09IGRvYy5zZWwucHJpbUluZGV4KSB7IGNvbnRpbnVlIH1cbiAgICAgIHZhciByYW5nZSA9IGRvYy5zZWwucmFuZ2VzW2ldO1xuICAgICAgaWYgKHJhbmdlLmZyb20oKS5saW5lID49IGNtLmRpc3BsYXkudmlld1RvIHx8IHJhbmdlLnRvKCkubGluZSA8IGNtLmRpc3BsYXkudmlld0Zyb20pIHsgY29udGludWUgfVxuICAgICAgdmFyIGNvbGxhcHNlZCA9IHJhbmdlLmVtcHR5KCk7XG4gICAgICBpZiAoY3VzdG9tQ3Vyc29yKSB7XG4gICAgICAgIHZhciBoZWFkID0gY3VzdG9tQ3Vyc29yKGNtLCByYW5nZSk7XG4gICAgICAgIGlmIChoZWFkKSB7IGRyYXdTZWxlY3Rpb25DdXJzb3IoY20sIGhlYWQsIGN1ckZyYWdtZW50KTsgfVxuICAgICAgfSBlbHNlIGlmIChjb2xsYXBzZWQgfHwgY20ub3B0aW9ucy5zaG93Q3Vyc29yV2hlblNlbGVjdGluZykge1xuICAgICAgICBkcmF3U2VsZWN0aW9uQ3Vyc29yKGNtLCByYW5nZS5oZWFkLCBjdXJGcmFnbWVudCk7XG4gICAgICB9XG4gICAgICBpZiAoIWNvbGxhcHNlZClcbiAgICAgICAgeyBkcmF3U2VsZWN0aW9uUmFuZ2UoY20sIHJhbmdlLCBzZWxGcmFnbWVudCk7IH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG5cbiAgLy8gRHJhd3MgYSBjdXJzb3IgZm9yIHRoZSBnaXZlbiByYW5nZVxuICBmdW5jdGlvbiBkcmF3U2VsZWN0aW9uQ3Vyc29yKGNtLCBoZWFkLCBvdXRwdXQpIHtcbiAgICB2YXIgcG9zID0gY3Vyc29yQ29vcmRzKGNtLCBoZWFkLCBcImRpdlwiLCBudWxsLCBudWxsLCAhY20ub3B0aW9ucy5zaW5nbGVDdXJzb3JIZWlnaHRQZXJMaW5lKTtcblxuICAgIHZhciBjdXJzb3IgPSBvdXRwdXQuYXBwZW5kQ2hpbGQoZWx0KFwiZGl2XCIsIFwiXFx1MDBhMFwiLCBcIkNvZGVNaXJyb3ItY3Vyc29yXCIpKTtcbiAgICBjdXJzb3Iuc3R5bGUubGVmdCA9IHBvcy5sZWZ0ICsgXCJweFwiO1xuICAgIGN1cnNvci5zdHlsZS50b3AgPSBwb3MudG9wICsgXCJweFwiO1xuICAgIGN1cnNvci5zdHlsZS5oZWlnaHQgPSBNYXRoLm1heCgwLCBwb3MuYm90dG9tIC0gcG9zLnRvcCkgKiBjbS5vcHRpb25zLmN1cnNvckhlaWdodCArIFwicHhcIjtcblxuICAgIGlmICgvXFxiY20tZmF0LWN1cnNvclxcYi8udGVzdChjbS5nZXRXcmFwcGVyRWxlbWVudCgpLmNsYXNzTmFtZSkpIHtcbiAgICAgIHZhciBjaGFyUG9zID0gY2hhckNvb3JkcyhjbSwgaGVhZCwgXCJkaXZcIiwgbnVsbCwgbnVsbCk7XG4gICAgICB2YXIgd2lkdGggPSBjaGFyUG9zLnJpZ2h0IC0gY2hhclBvcy5sZWZ0O1xuICAgICAgY3Vyc29yLnN0eWxlLndpZHRoID0gKHdpZHRoID4gMCA/IHdpZHRoIDogY20uZGVmYXVsdENoYXJXaWR0aCgpKSArIFwicHhcIjtcbiAgICB9XG5cbiAgICBpZiAocG9zLm90aGVyKSB7XG4gICAgICAvLyBTZWNvbmRhcnkgY3Vyc29yLCBzaG93biB3aGVuIG9uIGEgJ2p1bXAnIGluIGJpLWRpcmVjdGlvbmFsIHRleHRcbiAgICAgIHZhciBvdGhlckN1cnNvciA9IG91dHB1dC5hcHBlbmRDaGlsZChlbHQoXCJkaXZcIiwgXCJcXHUwMGEwXCIsIFwiQ29kZU1pcnJvci1jdXJzb3IgQ29kZU1pcnJvci1zZWNvbmRhcnljdXJzb3JcIikpO1xuICAgICAgb3RoZXJDdXJzb3Iuc3R5bGUuZGlzcGxheSA9IFwiXCI7XG4gICAgICBvdGhlckN1cnNvci5zdHlsZS5sZWZ0ID0gcG9zLm90aGVyLmxlZnQgKyBcInB4XCI7XG4gICAgICBvdGhlckN1cnNvci5zdHlsZS50b3AgPSBwb3Mub3RoZXIudG9wICsgXCJweFwiO1xuICAgICAgb3RoZXJDdXJzb3Iuc3R5bGUuaGVpZ2h0ID0gKHBvcy5vdGhlci5ib3R0b20gLSBwb3Mub3RoZXIudG9wKSAqIC44NSArIFwicHhcIjtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBjbXBDb29yZHMoYSwgYikgeyByZXR1cm4gYS50b3AgLSBiLnRvcCB8fCBhLmxlZnQgLSBiLmxlZnQgfVxuXG4gIC8vIERyYXdzIHRoZSBnaXZlbiByYW5nZSBhcyBhIGhpZ2hsaWdodGVkIHNlbGVjdGlvblxuICBmdW5jdGlvbiBkcmF3U2VsZWN0aW9uUmFuZ2UoY20sIHJhbmdlLCBvdXRwdXQpIHtcbiAgICB2YXIgZGlzcGxheSA9IGNtLmRpc3BsYXksIGRvYyA9IGNtLmRvYztcbiAgICB2YXIgZnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG4gICAgdmFyIHBhZGRpbmcgPSBwYWRkaW5nSChjbS5kaXNwbGF5KSwgbGVmdFNpZGUgPSBwYWRkaW5nLmxlZnQ7XG4gICAgdmFyIHJpZ2h0U2lkZSA9IE1hdGgubWF4KGRpc3BsYXkuc2l6ZXJXaWR0aCwgZGlzcGxheVdpZHRoKGNtKSAtIGRpc3BsYXkuc2l6ZXIub2Zmc2V0TGVmdCkgLSBwYWRkaW5nLnJpZ2h0O1xuICAgIHZhciBkb2NMVFIgPSBkb2MuZGlyZWN0aW9uID09IFwibHRyXCI7XG5cbiAgICBmdW5jdGlvbiBhZGQobGVmdCwgdG9wLCB3aWR0aCwgYm90dG9tKSB7XG4gICAgICBpZiAodG9wIDwgMCkgeyB0b3AgPSAwOyB9XG4gICAgICB0b3AgPSBNYXRoLnJvdW5kKHRvcCk7XG4gICAgICBib3R0b20gPSBNYXRoLnJvdW5kKGJvdHRvbSk7XG4gICAgICBmcmFnbWVudC5hcHBlbmRDaGlsZChlbHQoXCJkaXZcIiwgbnVsbCwgXCJDb2RlTWlycm9yLXNlbGVjdGVkXCIsIChcInBvc2l0aW9uOiBhYnNvbHV0ZTsgbGVmdDogXCIgKyBsZWZ0ICsgXCJweDtcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvcDogXCIgKyB0b3AgKyBcInB4OyB3aWR0aDogXCIgKyAod2lkdGggPT0gbnVsbCA/IHJpZ2h0U2lkZSAtIGxlZnQgOiB3aWR0aCkgKyBcInB4O1xcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBcIiArIChib3R0b20gLSB0b3ApICsgXCJweFwiKSkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRyYXdGb3JMaW5lKGxpbmUsIGZyb21BcmcsIHRvQXJnKSB7XG4gICAgICB2YXIgbGluZU9iaiA9IGdldExpbmUoZG9jLCBsaW5lKTtcbiAgICAgIHZhciBsaW5lTGVuID0gbGluZU9iai50ZXh0Lmxlbmd0aDtcbiAgICAgIHZhciBzdGFydCwgZW5kO1xuICAgICAgZnVuY3Rpb24gY29vcmRzKGNoLCBiaWFzKSB7XG4gICAgICAgIHJldHVybiBjaGFyQ29vcmRzKGNtLCBQb3MobGluZSwgY2gpLCBcImRpdlwiLCBsaW5lT2JqLCBiaWFzKVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiB3cmFwWChwb3MsIGRpciwgc2lkZSkge1xuICAgICAgICB2YXIgZXh0ZW50ID0gd3JhcHBlZExpbmVFeHRlbnRDaGFyKGNtLCBsaW5lT2JqLCBudWxsLCBwb3MpO1xuICAgICAgICB2YXIgcHJvcCA9IChkaXIgPT0gXCJsdHJcIikgPT0gKHNpZGUgPT0gXCJhZnRlclwiKSA/IFwibGVmdFwiIDogXCJyaWdodFwiO1xuICAgICAgICB2YXIgY2ggPSBzaWRlID09IFwiYWZ0ZXJcIiA/IGV4dGVudC5iZWdpbiA6IGV4dGVudC5lbmQgLSAoL1xccy8udGVzdChsaW5lT2JqLnRleHQuY2hhckF0KGV4dGVudC5lbmQgLSAxKSkgPyAyIDogMSk7XG4gICAgICAgIHJldHVybiBjb29yZHMoY2gsIHByb3ApW3Byb3BdXG4gICAgICB9XG5cbiAgICAgIHZhciBvcmRlciA9IGdldE9yZGVyKGxpbmVPYmosIGRvYy5kaXJlY3Rpb24pO1xuICAgICAgaXRlcmF0ZUJpZGlTZWN0aW9ucyhvcmRlciwgZnJvbUFyZyB8fCAwLCB0b0FyZyA9PSBudWxsID8gbGluZUxlbiA6IHRvQXJnLCBmdW5jdGlvbiAoZnJvbSwgdG8sIGRpciwgaSkge1xuICAgICAgICB2YXIgbHRyID0gZGlyID09IFwibHRyXCI7XG4gICAgICAgIHZhciBmcm9tUG9zID0gY29vcmRzKGZyb20sIGx0ciA/IFwibGVmdFwiIDogXCJyaWdodFwiKTtcbiAgICAgICAgdmFyIHRvUG9zID0gY29vcmRzKHRvIC0gMSwgbHRyID8gXCJyaWdodFwiIDogXCJsZWZ0XCIpO1xuXG4gICAgICAgIHZhciBvcGVuU3RhcnQgPSBmcm9tQXJnID09IG51bGwgJiYgZnJvbSA9PSAwLCBvcGVuRW5kID0gdG9BcmcgPT0gbnVsbCAmJiB0byA9PSBsaW5lTGVuO1xuICAgICAgICB2YXIgZmlyc3QgPSBpID09IDAsIGxhc3QgPSAhb3JkZXIgfHwgaSA9PSBvcmRlci5sZW5ndGggLSAxO1xuICAgICAgICBpZiAodG9Qb3MudG9wIC0gZnJvbVBvcy50b3AgPD0gMykgeyAvLyBTaW5nbGUgbGluZVxuICAgICAgICAgIHZhciBvcGVuTGVmdCA9IChkb2NMVFIgPyBvcGVuU3RhcnQgOiBvcGVuRW5kKSAmJiBmaXJzdDtcbiAgICAgICAgICB2YXIgb3BlblJpZ2h0ID0gKGRvY0xUUiA/IG9wZW5FbmQgOiBvcGVuU3RhcnQpICYmIGxhc3Q7XG4gICAgICAgICAgdmFyIGxlZnQgPSBvcGVuTGVmdCA/IGxlZnRTaWRlIDogKGx0ciA/IGZyb21Qb3MgOiB0b1BvcykubGVmdDtcbiAgICAgICAgICB2YXIgcmlnaHQgPSBvcGVuUmlnaHQgPyByaWdodFNpZGUgOiAobHRyID8gdG9Qb3MgOiBmcm9tUG9zKS5yaWdodDtcbiAgICAgICAgICBhZGQobGVmdCwgZnJvbVBvcy50b3AsIHJpZ2h0IC0gbGVmdCwgZnJvbVBvcy5ib3R0b20pO1xuICAgICAgICB9IGVsc2UgeyAvLyBNdWx0aXBsZSBsaW5lc1xuICAgICAgICAgIHZhciB0b3BMZWZ0LCB0b3BSaWdodCwgYm90TGVmdCwgYm90UmlnaHQ7XG4gICAgICAgICAgaWYgKGx0cikge1xuICAgICAgICAgICAgdG9wTGVmdCA9IGRvY0xUUiAmJiBvcGVuU3RhcnQgJiYgZmlyc3QgPyBsZWZ0U2lkZSA6IGZyb21Qb3MubGVmdDtcbiAgICAgICAgICAgIHRvcFJpZ2h0ID0gZG9jTFRSID8gcmlnaHRTaWRlIDogd3JhcFgoZnJvbSwgZGlyLCBcImJlZm9yZVwiKTtcbiAgICAgICAgICAgIGJvdExlZnQgPSBkb2NMVFIgPyBsZWZ0U2lkZSA6IHdyYXBYKHRvLCBkaXIsIFwiYWZ0ZXJcIik7XG4gICAgICAgICAgICBib3RSaWdodCA9IGRvY0xUUiAmJiBvcGVuRW5kICYmIGxhc3QgPyByaWdodFNpZGUgOiB0b1Bvcy5yaWdodDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdG9wTGVmdCA9ICFkb2NMVFIgPyBsZWZ0U2lkZSA6IHdyYXBYKGZyb20sIGRpciwgXCJiZWZvcmVcIik7XG4gICAgICAgICAgICB0b3BSaWdodCA9ICFkb2NMVFIgJiYgb3BlblN0YXJ0ICYmIGZpcnN0ID8gcmlnaHRTaWRlIDogZnJvbVBvcy5yaWdodDtcbiAgICAgICAgICAgIGJvdExlZnQgPSAhZG9jTFRSICYmIG9wZW5FbmQgJiYgbGFzdCA/IGxlZnRTaWRlIDogdG9Qb3MubGVmdDtcbiAgICAgICAgICAgIGJvdFJpZ2h0ID0gIWRvY0xUUiA/IHJpZ2h0U2lkZSA6IHdyYXBYKHRvLCBkaXIsIFwiYWZ0ZXJcIik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGFkZCh0b3BMZWZ0LCBmcm9tUG9zLnRvcCwgdG9wUmlnaHQgLSB0b3BMZWZ0LCBmcm9tUG9zLmJvdHRvbSk7XG4gICAgICAgICAgaWYgKGZyb21Qb3MuYm90dG9tIDwgdG9Qb3MudG9wKSB7IGFkZChsZWZ0U2lkZSwgZnJvbVBvcy5ib3R0b20sIG51bGwsIHRvUG9zLnRvcCk7IH1cbiAgICAgICAgICBhZGQoYm90TGVmdCwgdG9Qb3MudG9wLCBib3RSaWdodCAtIGJvdExlZnQsIHRvUG9zLmJvdHRvbSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXN0YXJ0IHx8IGNtcENvb3Jkcyhmcm9tUG9zLCBzdGFydCkgPCAwKSB7IHN0YXJ0ID0gZnJvbVBvczsgfVxuICAgICAgICBpZiAoY21wQ29vcmRzKHRvUG9zLCBzdGFydCkgPCAwKSB7IHN0YXJ0ID0gdG9Qb3M7IH1cbiAgICAgICAgaWYgKCFlbmQgfHwgY21wQ29vcmRzKGZyb21Qb3MsIGVuZCkgPCAwKSB7IGVuZCA9IGZyb21Qb3M7IH1cbiAgICAgICAgaWYgKGNtcENvb3Jkcyh0b1BvcywgZW5kKSA8IDApIHsgZW5kID0gdG9Qb3M7IH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHtzdGFydDogc3RhcnQsIGVuZDogZW5kfVxuICAgIH1cblxuICAgIHZhciBzRnJvbSA9IHJhbmdlLmZyb20oKSwgc1RvID0gcmFuZ2UudG8oKTtcbiAgICBpZiAoc0Zyb20ubGluZSA9PSBzVG8ubGluZSkge1xuICAgICAgZHJhd0ZvckxpbmUoc0Zyb20ubGluZSwgc0Zyb20uY2gsIHNUby5jaCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBmcm9tTGluZSA9IGdldExpbmUoZG9jLCBzRnJvbS5saW5lKSwgdG9MaW5lID0gZ2V0TGluZShkb2MsIHNUby5saW5lKTtcbiAgICAgIHZhciBzaW5nbGVWTGluZSA9IHZpc3VhbExpbmUoZnJvbUxpbmUpID09IHZpc3VhbExpbmUodG9MaW5lKTtcbiAgICAgIHZhciBsZWZ0RW5kID0gZHJhd0ZvckxpbmUoc0Zyb20ubGluZSwgc0Zyb20uY2gsIHNpbmdsZVZMaW5lID8gZnJvbUxpbmUudGV4dC5sZW5ndGggKyAxIDogbnVsbCkuZW5kO1xuICAgICAgdmFyIHJpZ2h0U3RhcnQgPSBkcmF3Rm9yTGluZShzVG8ubGluZSwgc2luZ2xlVkxpbmUgPyAwIDogbnVsbCwgc1RvLmNoKS5zdGFydDtcbiAgICAgIGlmIChzaW5nbGVWTGluZSkge1xuICAgICAgICBpZiAobGVmdEVuZC50b3AgPCByaWdodFN0YXJ0LnRvcCAtIDIpIHtcbiAgICAgICAgICBhZGQobGVmdEVuZC5yaWdodCwgbGVmdEVuZC50b3AsIG51bGwsIGxlZnRFbmQuYm90dG9tKTtcbiAgICAgICAgICBhZGQobGVmdFNpZGUsIHJpZ2h0U3RhcnQudG9wLCByaWdodFN0YXJ0LmxlZnQsIHJpZ2h0U3RhcnQuYm90dG9tKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhZGQobGVmdEVuZC5yaWdodCwgbGVmdEVuZC50b3AsIHJpZ2h0U3RhcnQubGVmdCAtIGxlZnRFbmQucmlnaHQsIGxlZnRFbmQuYm90dG9tKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGxlZnRFbmQuYm90dG9tIDwgcmlnaHRTdGFydC50b3ApXG4gICAgICAgIHsgYWRkKGxlZnRTaWRlLCBsZWZ0RW5kLmJvdHRvbSwgbnVsbCwgcmlnaHRTdGFydC50b3ApOyB9XG4gICAgfVxuXG4gICAgb3V0cHV0LmFwcGVuZENoaWxkKGZyYWdtZW50KTtcbiAgfVxuXG4gIC8vIEN1cnNvci1ibGlua2luZ1xuICBmdW5jdGlvbiByZXN0YXJ0QmxpbmsoY20pIHtcbiAgICBpZiAoIWNtLnN0YXRlLmZvY3VzZWQpIHsgcmV0dXJuIH1cbiAgICB2YXIgZGlzcGxheSA9IGNtLmRpc3BsYXk7XG4gICAgY2xlYXJJbnRlcnZhbChkaXNwbGF5LmJsaW5rZXIpO1xuICAgIHZhciBvbiA9IHRydWU7XG4gICAgZGlzcGxheS5jdXJzb3JEaXYuc3R5bGUudmlzaWJpbGl0eSA9IFwiXCI7XG4gICAgaWYgKGNtLm9wdGlvbnMuY3Vyc29yQmxpbmtSYXRlID4gMClcbiAgICAgIHsgZGlzcGxheS5ibGlua2VyID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIWNtLmhhc0ZvY3VzKCkpIHsgb25CbHVyKGNtKTsgfVxuICAgICAgICBkaXNwbGF5LmN1cnNvckRpdi5zdHlsZS52aXNpYmlsaXR5ID0gKG9uID0gIW9uKSA/IFwiXCIgOiBcImhpZGRlblwiO1xuICAgICAgfSwgY20ub3B0aW9ucy5jdXJzb3JCbGlua1JhdGUpOyB9XG4gICAgZWxzZSBpZiAoY20ub3B0aW9ucy5jdXJzb3JCbGlua1JhdGUgPCAwKVxuICAgICAgeyBkaXNwbGF5LmN1cnNvckRpdi5zdHlsZS52aXNpYmlsaXR5ID0gXCJoaWRkZW5cIjsgfVxuICB9XG5cbiAgZnVuY3Rpb24gZW5zdXJlRm9jdXMoY20pIHtcbiAgICBpZiAoIWNtLmhhc0ZvY3VzKCkpIHtcbiAgICAgIGNtLmRpc3BsYXkuaW5wdXQuZm9jdXMoKTtcbiAgICAgIGlmICghY20uc3RhdGUuZm9jdXNlZCkgeyBvbkZvY3VzKGNtKTsgfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGRlbGF5Qmx1ckV2ZW50KGNtKSB7XG4gICAgY20uc3RhdGUuZGVsYXlpbmdCbHVyRXZlbnQgPSB0cnVlO1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyBpZiAoY20uc3RhdGUuZGVsYXlpbmdCbHVyRXZlbnQpIHtcbiAgICAgIGNtLnN0YXRlLmRlbGF5aW5nQmx1ckV2ZW50ID0gZmFsc2U7XG4gICAgICBpZiAoY20uc3RhdGUuZm9jdXNlZCkgeyBvbkJsdXIoY20pOyB9XG4gICAgfSB9LCAxMDApO1xuICB9XG5cbiAgZnVuY3Rpb24gb25Gb2N1cyhjbSwgZSkge1xuICAgIGlmIChjbS5zdGF0ZS5kZWxheWluZ0JsdXJFdmVudCAmJiAhY20uc3RhdGUuZHJhZ2dpbmdUZXh0KSB7IGNtLnN0YXRlLmRlbGF5aW5nQmx1ckV2ZW50ID0gZmFsc2U7IH1cblxuICAgIGlmIChjbS5vcHRpb25zLnJlYWRPbmx5ID09IFwibm9jdXJzb3JcIikgeyByZXR1cm4gfVxuICAgIGlmICghY20uc3RhdGUuZm9jdXNlZCkge1xuICAgICAgc2lnbmFsKGNtLCBcImZvY3VzXCIsIGNtLCBlKTtcbiAgICAgIGNtLnN0YXRlLmZvY3VzZWQgPSB0cnVlO1xuICAgICAgYWRkQ2xhc3MoY20uZGlzcGxheS53cmFwcGVyLCBcIkNvZGVNaXJyb3ItZm9jdXNlZFwiKTtcbiAgICAgIC8vIFRoaXMgdGVzdCBwcmV2ZW50cyB0aGlzIGZyb20gZmlyaW5nIHdoZW4gYSBjb250ZXh0XG4gICAgICAvLyBtZW51IGlzIGNsb3NlZCAoc2luY2UgdGhlIGlucHV0IHJlc2V0IHdvdWxkIGtpbGwgdGhlXG4gICAgICAvLyBzZWxlY3QtYWxsIGRldGVjdGlvbiBoYWNrKVxuICAgICAgaWYgKCFjbS5jdXJPcCAmJiBjbS5kaXNwbGF5LnNlbEZvckNvbnRleHRNZW51ICE9IGNtLmRvYy5zZWwpIHtcbiAgICAgICAgY20uZGlzcGxheS5pbnB1dC5yZXNldCgpO1xuICAgICAgICBpZiAod2Via2l0KSB7IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gY20uZGlzcGxheS5pbnB1dC5yZXNldCh0cnVlKTsgfSwgMjApOyB9IC8vIElzc3VlICMxNzMwXG4gICAgICB9XG4gICAgICBjbS5kaXNwbGF5LmlucHV0LnJlY2VpdmVkRm9jdXMoKTtcbiAgICB9XG4gICAgcmVzdGFydEJsaW5rKGNtKTtcbiAgfVxuICBmdW5jdGlvbiBvbkJsdXIoY20sIGUpIHtcbiAgICBpZiAoY20uc3RhdGUuZGVsYXlpbmdCbHVyRXZlbnQpIHsgcmV0dXJuIH1cblxuICAgIGlmIChjbS5zdGF0ZS5mb2N1c2VkKSB7XG4gICAgICBzaWduYWwoY20sIFwiYmx1clwiLCBjbSwgZSk7XG4gICAgICBjbS5zdGF0ZS5mb2N1c2VkID0gZmFsc2U7XG4gICAgICBybUNsYXNzKGNtLmRpc3BsYXkud3JhcHBlciwgXCJDb2RlTWlycm9yLWZvY3VzZWRcIik7XG4gICAgfVxuICAgIGNsZWFySW50ZXJ2YWwoY20uZGlzcGxheS5ibGlua2VyKTtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHsgaWYgKCFjbS5zdGF0ZS5mb2N1c2VkKSB7IGNtLmRpc3BsYXkuc2hpZnQgPSBmYWxzZTsgfSB9LCAxNTApO1xuICB9XG5cbiAgLy8gUmVhZCB0aGUgYWN0dWFsIGhlaWdodHMgb2YgdGhlIHJlbmRlcmVkIGxpbmVzLCBhbmQgdXBkYXRlIHRoZWlyXG4gIC8vIHN0b3JlZCBoZWlnaHRzIHRvIG1hdGNoLlxuICBmdW5jdGlvbiB1cGRhdGVIZWlnaHRzSW5WaWV3cG9ydChjbSkge1xuICAgIHZhciBkaXNwbGF5ID0gY20uZGlzcGxheTtcbiAgICB2YXIgcHJldkJvdHRvbSA9IGRpc3BsYXkubGluZURpdi5vZmZzZXRUb3A7XG4gICAgdmFyIHZpZXdUb3AgPSBNYXRoLm1heCgwLCBkaXNwbGF5LnNjcm9sbGVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcCk7XG4gICAgdmFyIG9sZEhlaWdodCA9IGRpc3BsYXkubGluZURpdi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3A7XG4gICAgdmFyIG11c3RTY3JvbGwgPSAwO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGlzcGxheS52aWV3Lmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY3VyID0gZGlzcGxheS52aWV3W2ldLCB3cmFwcGluZyA9IGNtLm9wdGlvbnMubGluZVdyYXBwaW5nO1xuICAgICAgdmFyIGhlaWdodCA9ICh2b2lkIDApLCB3aWR0aCA9IDA7XG4gICAgICBpZiAoY3VyLmhpZGRlbikgeyBjb250aW51ZSB9XG4gICAgICBvbGRIZWlnaHQgKz0gY3VyLmxpbmUuaGVpZ2h0O1xuICAgICAgaWYgKGllICYmIGllX3ZlcnNpb24gPCA4KSB7XG4gICAgICAgIHZhciBib3QgPSBjdXIubm9kZS5vZmZzZXRUb3AgKyBjdXIubm9kZS5vZmZzZXRIZWlnaHQ7XG4gICAgICAgIGhlaWdodCA9IGJvdCAtIHByZXZCb3R0b207XG4gICAgICAgIHByZXZCb3R0b20gPSBib3Q7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgYm94ID0gY3VyLm5vZGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGhlaWdodCA9IGJveC5ib3R0b20gLSBib3gudG9wO1xuICAgICAgICAvLyBDaGVjayB0aGF0IGxpbmVzIGRvbid0IGV4dGVuZCBwYXN0IHRoZSByaWdodCBvZiB0aGUgY3VycmVudFxuICAgICAgICAvLyBlZGl0b3Igd2lkdGhcbiAgICAgICAgaWYgKCF3cmFwcGluZyAmJiBjdXIudGV4dC5maXJzdENoaWxkKVxuICAgICAgICAgIHsgd2lkdGggPSBjdXIudGV4dC5maXJzdENoaWxkLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnJpZ2h0IC0gYm94LmxlZnQgLSAxOyB9XG4gICAgICB9XG4gICAgICB2YXIgZGlmZiA9IGN1ci5saW5lLmhlaWdodCAtIGhlaWdodDtcbiAgICAgIGlmIChkaWZmID4gLjAwNSB8fCBkaWZmIDwgLS4wMDUpIHtcbiAgICAgICAgaWYgKG9sZEhlaWdodCA8IHZpZXdUb3ApIHsgbXVzdFNjcm9sbCAtPSBkaWZmOyB9XG4gICAgICAgIHVwZGF0ZUxpbmVIZWlnaHQoY3VyLmxpbmUsIGhlaWdodCk7XG4gICAgICAgIHVwZGF0ZVdpZGdldEhlaWdodChjdXIubGluZSk7XG4gICAgICAgIGlmIChjdXIucmVzdCkgeyBmb3IgKHZhciBqID0gMDsgaiA8IGN1ci5yZXN0Lmxlbmd0aDsgaisrKVxuICAgICAgICAgIHsgdXBkYXRlV2lkZ2V0SGVpZ2h0KGN1ci5yZXN0W2pdKTsgfSB9XG4gICAgICB9XG4gICAgICBpZiAod2lkdGggPiBjbS5kaXNwbGF5LnNpemVyV2lkdGgpIHtcbiAgICAgICAgdmFyIGNoV2lkdGggPSBNYXRoLmNlaWwod2lkdGggLyBjaGFyV2lkdGgoY20uZGlzcGxheSkpO1xuICAgICAgICBpZiAoY2hXaWR0aCA+IGNtLmRpc3BsYXkubWF4TGluZUxlbmd0aCkge1xuICAgICAgICAgIGNtLmRpc3BsYXkubWF4TGluZUxlbmd0aCA9IGNoV2lkdGg7XG4gICAgICAgICAgY20uZGlzcGxheS5tYXhMaW5lID0gY3VyLmxpbmU7XG4gICAgICAgICAgY20uZGlzcGxheS5tYXhMaW5lQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKE1hdGguYWJzKG11c3RTY3JvbGwpID4gMikgeyBkaXNwbGF5LnNjcm9sbGVyLnNjcm9sbFRvcCArPSBtdXN0U2Nyb2xsOyB9XG4gIH1cblxuICAvLyBSZWFkIGFuZCBzdG9yZSB0aGUgaGVpZ2h0IG9mIGxpbmUgd2lkZ2V0cyBhc3NvY2lhdGVkIHdpdGggdGhlXG4gIC8vIGdpdmVuIGxpbmUuXG4gIGZ1bmN0aW9uIHVwZGF0ZVdpZGdldEhlaWdodChsaW5lKSB7XG4gICAgaWYgKGxpbmUud2lkZ2V0cykgeyBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmUud2lkZ2V0cy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIHcgPSBsaW5lLndpZGdldHNbaV0sIHBhcmVudCA9IHcubm9kZS5wYXJlbnROb2RlO1xuICAgICAgaWYgKHBhcmVudCkgeyB3LmhlaWdodCA9IHBhcmVudC5vZmZzZXRIZWlnaHQ7IH1cbiAgICB9IH1cbiAgfVxuXG4gIC8vIENvbXB1dGUgdGhlIGxpbmVzIHRoYXQgYXJlIHZpc2libGUgaW4gYSBnaXZlbiB2aWV3cG9ydCAoZGVmYXVsdHNcbiAgLy8gdGhlIHRoZSBjdXJyZW50IHNjcm9sbCBwb3NpdGlvbikuIHZpZXdwb3J0IG1heSBjb250YWluIHRvcCxcbiAgLy8gaGVpZ2h0LCBhbmQgZW5zdXJlIChzZWUgb3Auc2Nyb2xsVG9Qb3MpIHByb3BlcnRpZXMuXG4gIGZ1bmN0aW9uIHZpc2libGVMaW5lcyhkaXNwbGF5LCBkb2MsIHZpZXdwb3J0KSB7XG4gICAgdmFyIHRvcCA9IHZpZXdwb3J0ICYmIHZpZXdwb3J0LnRvcCAhPSBudWxsID8gTWF0aC5tYXgoMCwgdmlld3BvcnQudG9wKSA6IGRpc3BsYXkuc2Nyb2xsZXIuc2Nyb2xsVG9wO1xuICAgIHRvcCA9IE1hdGguZmxvb3IodG9wIC0gcGFkZGluZ1RvcChkaXNwbGF5KSk7XG4gICAgdmFyIGJvdHRvbSA9IHZpZXdwb3J0ICYmIHZpZXdwb3J0LmJvdHRvbSAhPSBudWxsID8gdmlld3BvcnQuYm90dG9tIDogdG9wICsgZGlzcGxheS53cmFwcGVyLmNsaWVudEhlaWdodDtcblxuICAgIHZhciBmcm9tID0gbGluZUF0SGVpZ2h0KGRvYywgdG9wKSwgdG8gPSBsaW5lQXRIZWlnaHQoZG9jLCBib3R0b20pO1xuICAgIC8vIEVuc3VyZSBpcyBhIHtmcm9tOiB7bGluZSwgY2h9LCB0bzoge2xpbmUsIGNofX0gb2JqZWN0LCBhbmRcbiAgICAvLyBmb3JjZXMgdGhvc2UgbGluZXMgaW50byB0aGUgdmlld3BvcnQgKGlmIHBvc3NpYmxlKS5cbiAgICBpZiAodmlld3BvcnQgJiYgdmlld3BvcnQuZW5zdXJlKSB7XG4gICAgICB2YXIgZW5zdXJlRnJvbSA9IHZpZXdwb3J0LmVuc3VyZS5mcm9tLmxpbmUsIGVuc3VyZVRvID0gdmlld3BvcnQuZW5zdXJlLnRvLmxpbmU7XG4gICAgICBpZiAoZW5zdXJlRnJvbSA8IGZyb20pIHtcbiAgICAgICAgZnJvbSA9IGVuc3VyZUZyb207XG4gICAgICAgIHRvID0gbGluZUF0SGVpZ2h0KGRvYywgaGVpZ2h0QXRMaW5lKGdldExpbmUoZG9jLCBlbnN1cmVGcm9tKSkgKyBkaXNwbGF5LndyYXBwZXIuY2xpZW50SGVpZ2h0KTtcbiAgICAgIH0gZWxzZSBpZiAoTWF0aC5taW4oZW5zdXJlVG8sIGRvYy5sYXN0TGluZSgpKSA+PSB0bykge1xuICAgICAgICBmcm9tID0gbGluZUF0SGVpZ2h0KGRvYywgaGVpZ2h0QXRMaW5lKGdldExpbmUoZG9jLCBlbnN1cmVUbykpIC0gZGlzcGxheS53cmFwcGVyLmNsaWVudEhlaWdodCk7XG4gICAgICAgIHRvID0gZW5zdXJlVG87XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7ZnJvbTogZnJvbSwgdG86IE1hdGgubWF4KHRvLCBmcm9tICsgMSl9XG4gIH1cblxuICAvLyBTQ1JPTExJTkcgVEhJTkdTIElOVE8gVklFV1xuXG4gIC8vIElmIGFuIGVkaXRvciBzaXRzIG9uIHRoZSB0b3Agb3IgYm90dG9tIG9mIHRoZSB3aW5kb3csIHBhcnRpYWxseVxuICAvLyBzY3JvbGxlZCBvdXQgb2YgdmlldywgdGhpcyBlbnN1cmVzIHRoYXQgdGhlIGN1cnNvciBpcyB2aXNpYmxlLlxuICBmdW5jdGlvbiBtYXliZVNjcm9sbFdpbmRvdyhjbSwgcmVjdCkge1xuICAgIGlmIChzaWduYWxET01FdmVudChjbSwgXCJzY3JvbGxDdXJzb3JJbnRvVmlld1wiKSkgeyByZXR1cm4gfVxuXG4gICAgdmFyIGRpc3BsYXkgPSBjbS5kaXNwbGF5LCBib3ggPSBkaXNwbGF5LnNpemVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLCBkb1Njcm9sbCA9IG51bGw7XG4gICAgaWYgKHJlY3QudG9wICsgYm94LnRvcCA8IDApIHsgZG9TY3JvbGwgPSB0cnVlOyB9XG4gICAgZWxzZSBpZiAocmVjdC5ib3R0b20gKyBib3gudG9wID4gKHdpbmRvdy5pbm5lckhlaWdodCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0KSkgeyBkb1Njcm9sbCA9IGZhbHNlOyB9XG4gICAgaWYgKGRvU2Nyb2xsICE9IG51bGwgJiYgIXBoYW50b20pIHtcbiAgICAgIHZhciBzY3JvbGxOb2RlID0gZWx0KFwiZGl2XCIsIFwiXFx1MjAwYlwiLCBudWxsLCAoXCJwb3NpdGlvbjogYWJzb2x1dGU7XFxuICAgICAgICAgICAgICAgICAgICAgICAgIHRvcDogXCIgKyAocmVjdC50b3AgLSBkaXNwbGF5LnZpZXdPZmZzZXQgLSBwYWRkaW5nVG9wKGNtLmRpc3BsYXkpKSArIFwicHg7XFxuICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogXCIgKyAocmVjdC5ib3R0b20gLSByZWN0LnRvcCArIHNjcm9sbEdhcChjbSkgKyBkaXNwbGF5LmJhckhlaWdodCkgKyBcInB4O1xcbiAgICAgICAgICAgICAgICAgICAgICAgICBsZWZ0OiBcIiArIChyZWN0LmxlZnQpICsgXCJweDsgd2lkdGg6IFwiICsgKE1hdGgubWF4KDIsIHJlY3QucmlnaHQgLSByZWN0LmxlZnQpKSArIFwicHg7XCIpKTtcbiAgICAgIGNtLmRpc3BsYXkubGluZVNwYWNlLmFwcGVuZENoaWxkKHNjcm9sbE5vZGUpO1xuICAgICAgc2Nyb2xsTm9kZS5zY3JvbGxJbnRvVmlldyhkb1Njcm9sbCk7XG4gICAgICBjbS5kaXNwbGF5LmxpbmVTcGFjZS5yZW1vdmVDaGlsZChzY3JvbGxOb2RlKTtcbiAgICB9XG4gIH1cblxuICAvLyBTY3JvbGwgYSBnaXZlbiBwb3NpdGlvbiBpbnRvIHZpZXcgKGltbWVkaWF0ZWx5KSwgdmVyaWZ5aW5nIHRoYXRcbiAgLy8gaXQgYWN0dWFsbHkgYmVjYW1lIHZpc2libGUgKGFzIGxpbmUgaGVpZ2h0cyBhcmUgYWNjdXJhdGVseVxuICAvLyBtZWFzdXJlZCwgdGhlIHBvc2l0aW9uIG9mIHNvbWV0aGluZyBtYXkgJ2RyaWZ0JyBkdXJpbmcgZHJhd2luZykuXG4gIGZ1bmN0aW9uIHNjcm9sbFBvc0ludG9WaWV3KGNtLCBwb3MsIGVuZCwgbWFyZ2luKSB7XG4gICAgaWYgKG1hcmdpbiA9PSBudWxsKSB7IG1hcmdpbiA9IDA7IH1cbiAgICB2YXIgcmVjdDtcbiAgICBpZiAoIWNtLm9wdGlvbnMubGluZVdyYXBwaW5nICYmIHBvcyA9PSBlbmQpIHtcbiAgICAgIC8vIFNldCBwb3MgYW5kIGVuZCB0byB0aGUgY3Vyc29yIHBvc2l0aW9ucyBhcm91bmQgdGhlIGNoYXJhY3RlciBwb3Mgc3RpY2tzIHRvXG4gICAgICAvLyBJZiBwb3Muc3RpY2t5ID09IFwiYmVmb3JlXCIsIHRoYXQgaXMgYXJvdW5kIHBvcy5jaCAtIDEsIG90aGVyd2lzZSBhcm91bmQgcG9zLmNoXG4gICAgICAvLyBJZiBwb3MgPT0gUG9zKF8sIDAsIFwiYmVmb3JlXCIpLCBwb3MgYW5kIGVuZCBhcmUgdW5jaGFuZ2VkXG4gICAgICBlbmQgPSBwb3Muc3RpY2t5ID09IFwiYmVmb3JlXCIgPyBQb3MocG9zLmxpbmUsIHBvcy5jaCArIDEsIFwiYmVmb3JlXCIpIDogcG9zO1xuICAgICAgcG9zID0gcG9zLmNoID8gUG9zKHBvcy5saW5lLCBwb3Muc3RpY2t5ID09IFwiYmVmb3JlXCIgPyBwb3MuY2ggLSAxIDogcG9zLmNoLCBcImFmdGVyXCIpIDogcG9zO1xuICAgIH1cbiAgICBmb3IgKHZhciBsaW1pdCA9IDA7IGxpbWl0IDwgNTsgbGltaXQrKykge1xuICAgICAgdmFyIGNoYW5nZWQgPSBmYWxzZTtcbiAgICAgIHZhciBjb29yZHMgPSBjdXJzb3JDb29yZHMoY20sIHBvcyk7XG4gICAgICB2YXIgZW5kQ29vcmRzID0gIWVuZCB8fCBlbmQgPT0gcG9zID8gY29vcmRzIDogY3Vyc29yQ29vcmRzKGNtLCBlbmQpO1xuICAgICAgcmVjdCA9IHtsZWZ0OiBNYXRoLm1pbihjb29yZHMubGVmdCwgZW5kQ29vcmRzLmxlZnQpLFxuICAgICAgICAgICAgICB0b3A6IE1hdGgubWluKGNvb3Jkcy50b3AsIGVuZENvb3Jkcy50b3ApIC0gbWFyZ2luLFxuICAgICAgICAgICAgICByaWdodDogTWF0aC5tYXgoY29vcmRzLmxlZnQsIGVuZENvb3Jkcy5sZWZ0KSxcbiAgICAgICAgICAgICAgYm90dG9tOiBNYXRoLm1heChjb29yZHMuYm90dG9tLCBlbmRDb29yZHMuYm90dG9tKSArIG1hcmdpbn07XG4gICAgICB2YXIgc2Nyb2xsUG9zID0gY2FsY3VsYXRlU2Nyb2xsUG9zKGNtLCByZWN0KTtcbiAgICAgIHZhciBzdGFydFRvcCA9IGNtLmRvYy5zY3JvbGxUb3AsIHN0YXJ0TGVmdCA9IGNtLmRvYy5zY3JvbGxMZWZ0O1xuICAgICAgaWYgKHNjcm9sbFBvcy5zY3JvbGxUb3AgIT0gbnVsbCkge1xuICAgICAgICB1cGRhdGVTY3JvbGxUb3AoY20sIHNjcm9sbFBvcy5zY3JvbGxUb3ApO1xuICAgICAgICBpZiAoTWF0aC5hYnMoY20uZG9jLnNjcm9sbFRvcCAtIHN0YXJ0VG9wKSA+IDEpIHsgY2hhbmdlZCA9IHRydWU7IH1cbiAgICAgIH1cbiAgICAgIGlmIChzY3JvbGxQb3Muc2Nyb2xsTGVmdCAhPSBudWxsKSB7XG4gICAgICAgIHNldFNjcm9sbExlZnQoY20sIHNjcm9sbFBvcy5zY3JvbGxMZWZ0KTtcbiAgICAgICAgaWYgKE1hdGguYWJzKGNtLmRvYy5zY3JvbGxMZWZ0IC0gc3RhcnRMZWZ0KSA+IDEpIHsgY2hhbmdlZCA9IHRydWU7IH1cbiAgICAgIH1cbiAgICAgIGlmICghY2hhbmdlZCkgeyBicmVhayB9XG4gICAgfVxuICAgIHJldHVybiByZWN0XG4gIH1cblxuICAvLyBTY3JvbGwgYSBnaXZlbiBzZXQgb2YgY29vcmRpbmF0ZXMgaW50byB2aWV3IChpbW1lZGlhdGVseSkuXG4gIGZ1bmN0aW9uIHNjcm9sbEludG9WaWV3KGNtLCByZWN0KSB7XG4gICAgdmFyIHNjcm9sbFBvcyA9IGNhbGN1bGF0ZVNjcm9sbFBvcyhjbSwgcmVjdCk7XG4gICAgaWYgKHNjcm9sbFBvcy5zY3JvbGxUb3AgIT0gbnVsbCkgeyB1cGRhdGVTY3JvbGxUb3AoY20sIHNjcm9sbFBvcy5zY3JvbGxUb3ApOyB9XG4gICAgaWYgKHNjcm9sbFBvcy5zY3JvbGxMZWZ0ICE9IG51bGwpIHsgc2V0U2Nyb2xsTGVmdChjbSwgc2Nyb2xsUG9zLnNjcm9sbExlZnQpOyB9XG4gIH1cblxuICAvLyBDYWxjdWxhdGUgYSBuZXcgc2Nyb2xsIHBvc2l0aW9uIG5lZWRlZCB0byBzY3JvbGwgdGhlIGdpdmVuXG4gIC8vIHJlY3RhbmdsZSBpbnRvIHZpZXcuIFJldHVybnMgYW4gb2JqZWN0IHdpdGggc2Nyb2xsVG9wIGFuZFxuICAvLyBzY3JvbGxMZWZ0IHByb3BlcnRpZXMuIFdoZW4gdGhlc2UgYXJlIHVuZGVmaW5lZCwgdGhlXG4gIC8vIHZlcnRpY2FsL2hvcml6b250YWwgcG9zaXRpb24gZG9lcyBub3QgbmVlZCB0byBiZSBhZGp1c3RlZC5cbiAgZnVuY3Rpb24gY2FsY3VsYXRlU2Nyb2xsUG9zKGNtLCByZWN0KSB7XG4gICAgdmFyIGRpc3BsYXkgPSBjbS5kaXNwbGF5LCBzbmFwTWFyZ2luID0gdGV4dEhlaWdodChjbS5kaXNwbGF5KTtcbiAgICBpZiAocmVjdC50b3AgPCAwKSB7IHJlY3QudG9wID0gMDsgfVxuICAgIHZhciBzY3JlZW50b3AgPSBjbS5jdXJPcCAmJiBjbS5jdXJPcC5zY3JvbGxUb3AgIT0gbnVsbCA/IGNtLmN1ck9wLnNjcm9sbFRvcCA6IGRpc3BsYXkuc2Nyb2xsZXIuc2Nyb2xsVG9wO1xuICAgIHZhciBzY3JlZW4gPSBkaXNwbGF5SGVpZ2h0KGNtKSwgcmVzdWx0ID0ge307XG4gICAgaWYgKHJlY3QuYm90dG9tIC0gcmVjdC50b3AgPiBzY3JlZW4pIHsgcmVjdC5ib3R0b20gPSByZWN0LnRvcCArIHNjcmVlbjsgfVxuICAgIHZhciBkb2NCb3R0b20gPSBjbS5kb2MuaGVpZ2h0ICsgcGFkZGluZ1ZlcnQoZGlzcGxheSk7XG4gICAgdmFyIGF0VG9wID0gcmVjdC50b3AgPCBzbmFwTWFyZ2luLCBhdEJvdHRvbSA9IHJlY3QuYm90dG9tID4gZG9jQm90dG9tIC0gc25hcE1hcmdpbjtcbiAgICBpZiAocmVjdC50b3AgPCBzY3JlZW50b3ApIHtcbiAgICAgIHJlc3VsdC5zY3JvbGxUb3AgPSBhdFRvcCA/IDAgOiByZWN0LnRvcDtcbiAgICB9IGVsc2UgaWYgKHJlY3QuYm90dG9tID4gc2NyZWVudG9wICsgc2NyZWVuKSB7XG4gICAgICB2YXIgbmV3VG9wID0gTWF0aC5taW4ocmVjdC50b3AsIChhdEJvdHRvbSA/IGRvY0JvdHRvbSA6IHJlY3QuYm90dG9tKSAtIHNjcmVlbik7XG4gICAgICBpZiAobmV3VG9wICE9IHNjcmVlbnRvcCkgeyByZXN1bHQuc2Nyb2xsVG9wID0gbmV3VG9wOyB9XG4gICAgfVxuXG4gICAgdmFyIGd1dHRlclNwYWNlID0gY20ub3B0aW9ucy5maXhlZEd1dHRlciA/IDAgOiBkaXNwbGF5Lmd1dHRlcnMub2Zmc2V0V2lkdGg7XG4gICAgdmFyIHNjcmVlbmxlZnQgPSBjbS5jdXJPcCAmJiBjbS5jdXJPcC5zY3JvbGxMZWZ0ICE9IG51bGwgPyBjbS5jdXJPcC5zY3JvbGxMZWZ0IDogZGlzcGxheS5zY3JvbGxlci5zY3JvbGxMZWZ0IC0gZ3V0dGVyU3BhY2U7XG4gICAgdmFyIHNjcmVlbncgPSBkaXNwbGF5V2lkdGgoY20pIC0gZGlzcGxheS5ndXR0ZXJzLm9mZnNldFdpZHRoO1xuICAgIHZhciB0b29XaWRlID0gcmVjdC5yaWdodCAtIHJlY3QubGVmdCA+IHNjcmVlbnc7XG4gICAgaWYgKHRvb1dpZGUpIHsgcmVjdC5yaWdodCA9IHJlY3QubGVmdCArIHNjcmVlbnc7IH1cbiAgICBpZiAocmVjdC5sZWZ0IDwgMTApXG4gICAgICB7IHJlc3VsdC5zY3JvbGxMZWZ0ID0gMDsgfVxuICAgIGVsc2UgaWYgKHJlY3QubGVmdCA8IHNjcmVlbmxlZnQpXG4gICAgICB7IHJlc3VsdC5zY3JvbGxMZWZ0ID0gTWF0aC5tYXgoMCwgcmVjdC5sZWZ0ICsgZ3V0dGVyU3BhY2UgLSAodG9vV2lkZSA/IDAgOiAxMCkpOyB9XG4gICAgZWxzZSBpZiAocmVjdC5yaWdodCA+IHNjcmVlbncgKyBzY3JlZW5sZWZ0IC0gMylcbiAgICAgIHsgcmVzdWx0LnNjcm9sbExlZnQgPSByZWN0LnJpZ2h0ICsgKHRvb1dpZGUgPyAwIDogMTApIC0gc2NyZWVudzsgfVxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIC8vIFN0b3JlIGEgcmVsYXRpdmUgYWRqdXN0bWVudCB0byB0aGUgc2Nyb2xsIHBvc2l0aW9uIGluIHRoZSBjdXJyZW50XG4gIC8vIG9wZXJhdGlvbiAodG8gYmUgYXBwbGllZCB3aGVuIHRoZSBvcGVyYXRpb24gZmluaXNoZXMpLlxuICBmdW5jdGlvbiBhZGRUb1Njcm9sbFRvcChjbSwgdG9wKSB7XG4gICAgaWYgKHRvcCA9PSBudWxsKSB7IHJldHVybiB9XG4gICAgcmVzb2x2ZVNjcm9sbFRvUG9zKGNtKTtcbiAgICBjbS5jdXJPcC5zY3JvbGxUb3AgPSAoY20uY3VyT3Auc2Nyb2xsVG9wID09IG51bGwgPyBjbS5kb2Muc2Nyb2xsVG9wIDogY20uY3VyT3Auc2Nyb2xsVG9wKSArIHRvcDtcbiAgfVxuXG4gIC8vIE1ha2Ugc3VyZSB0aGF0IGF0IHRoZSBlbmQgb2YgdGhlIG9wZXJhdGlvbiB0aGUgY3VycmVudCBjdXJzb3IgaXNcbiAgLy8gc2hvd24uXG4gIGZ1bmN0aW9uIGVuc3VyZUN1cnNvclZpc2libGUoY20pIHtcbiAgICByZXNvbHZlU2Nyb2xsVG9Qb3MoY20pO1xuICAgIHZhciBjdXIgPSBjbS5nZXRDdXJzb3IoKTtcbiAgICBjbS5jdXJPcC5zY3JvbGxUb1BvcyA9IHtmcm9tOiBjdXIsIHRvOiBjdXIsIG1hcmdpbjogY20ub3B0aW9ucy5jdXJzb3JTY3JvbGxNYXJnaW59O1xuICB9XG5cbiAgZnVuY3Rpb24gc2Nyb2xsVG9Db29yZHMoY20sIHgsIHkpIHtcbiAgICBpZiAoeCAhPSBudWxsIHx8IHkgIT0gbnVsbCkgeyByZXNvbHZlU2Nyb2xsVG9Qb3MoY20pOyB9XG4gICAgaWYgKHggIT0gbnVsbCkgeyBjbS5jdXJPcC5zY3JvbGxMZWZ0ID0geDsgfVxuICAgIGlmICh5ICE9IG51bGwpIHsgY20uY3VyT3Auc2Nyb2xsVG9wID0geTsgfVxuICB9XG5cbiAgZnVuY3Rpb24gc2Nyb2xsVG9SYW5nZShjbSwgcmFuZ2UpIHtcbiAgICByZXNvbHZlU2Nyb2xsVG9Qb3MoY20pO1xuICAgIGNtLmN1ck9wLnNjcm9sbFRvUG9zID0gcmFuZ2U7XG4gIH1cblxuICAvLyBXaGVuIGFuIG9wZXJhdGlvbiBoYXMgaXRzIHNjcm9sbFRvUG9zIHByb3BlcnR5IHNldCwgYW5kIGFub3RoZXJcbiAgLy8gc2Nyb2xsIGFjdGlvbiBpcyBhcHBsaWVkIGJlZm9yZSB0aGUgZW5kIG9mIHRoZSBvcGVyYXRpb24sIHRoaXNcbiAgLy8gJ3NpbXVsYXRlcycgc2Nyb2xsaW5nIHRoYXQgcG9zaXRpb24gaW50byB2aWV3IGluIGEgY2hlYXAgd2F5LCBzb1xuICAvLyB0aGF0IHRoZSBlZmZlY3Qgb2YgaW50ZXJtZWRpYXRlIHNjcm9sbCBjb21tYW5kcyBpcyBub3QgaWdub3JlZC5cbiAgZnVuY3Rpb24gcmVzb2x2ZVNjcm9sbFRvUG9zKGNtKSB7XG4gICAgdmFyIHJhbmdlID0gY20uY3VyT3Auc2Nyb2xsVG9Qb3M7XG4gICAgaWYgKHJhbmdlKSB7XG4gICAgICBjbS5jdXJPcC5zY3JvbGxUb1BvcyA9IG51bGw7XG4gICAgICB2YXIgZnJvbSA9IGVzdGltYXRlQ29vcmRzKGNtLCByYW5nZS5mcm9tKSwgdG8gPSBlc3RpbWF0ZUNvb3JkcyhjbSwgcmFuZ2UudG8pO1xuICAgICAgc2Nyb2xsVG9Db29yZHNSYW5nZShjbSwgZnJvbSwgdG8sIHJhbmdlLm1hcmdpbik7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gc2Nyb2xsVG9Db29yZHNSYW5nZShjbSwgZnJvbSwgdG8sIG1hcmdpbikge1xuICAgIHZhciBzUG9zID0gY2FsY3VsYXRlU2Nyb2xsUG9zKGNtLCB7XG4gICAgICBsZWZ0OiBNYXRoLm1pbihmcm9tLmxlZnQsIHRvLmxlZnQpLFxuICAgICAgdG9wOiBNYXRoLm1pbihmcm9tLnRvcCwgdG8udG9wKSAtIG1hcmdpbixcbiAgICAgIHJpZ2h0OiBNYXRoLm1heChmcm9tLnJpZ2h0LCB0by5yaWdodCksXG4gICAgICBib3R0b206IE1hdGgubWF4KGZyb20uYm90dG9tLCB0by5ib3R0b20pICsgbWFyZ2luXG4gICAgfSk7XG4gICAgc2Nyb2xsVG9Db29yZHMoY20sIHNQb3Muc2Nyb2xsTGVmdCwgc1Bvcy5zY3JvbGxUb3ApO1xuICB9XG5cbiAgLy8gU3luYyB0aGUgc2Nyb2xsYWJsZSBhcmVhIGFuZCBzY3JvbGxiYXJzLCBlbnN1cmUgdGhlIHZpZXdwb3J0XG4gIC8vIGNvdmVycyB0aGUgdmlzaWJsZSBhcmVhLlxuICBmdW5jdGlvbiB1cGRhdGVTY3JvbGxUb3AoY20sIHZhbCkge1xuICAgIGlmIChNYXRoLmFicyhjbS5kb2Muc2Nyb2xsVG9wIC0gdmFsKSA8IDIpIHsgcmV0dXJuIH1cbiAgICBpZiAoIWdlY2tvKSB7IHVwZGF0ZURpc3BsYXlTaW1wbGUoY20sIHt0b3A6IHZhbH0pOyB9XG4gICAgc2V0U2Nyb2xsVG9wKGNtLCB2YWwsIHRydWUpO1xuICAgIGlmIChnZWNrbykgeyB1cGRhdGVEaXNwbGF5U2ltcGxlKGNtKTsgfVxuICAgIHN0YXJ0V29ya2VyKGNtLCAxMDApO1xuICB9XG5cbiAgZnVuY3Rpb24gc2V0U2Nyb2xsVG9wKGNtLCB2YWwsIGZvcmNlU2Nyb2xsKSB7XG4gICAgdmFsID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oY20uZGlzcGxheS5zY3JvbGxlci5zY3JvbGxIZWlnaHQgLSBjbS5kaXNwbGF5LnNjcm9sbGVyLmNsaWVudEhlaWdodCwgdmFsKSk7XG4gICAgaWYgKGNtLmRpc3BsYXkuc2Nyb2xsZXIuc2Nyb2xsVG9wID09IHZhbCAmJiAhZm9yY2VTY3JvbGwpIHsgcmV0dXJuIH1cbiAgICBjbS5kb2Muc2Nyb2xsVG9wID0gdmFsO1xuICAgIGNtLmRpc3BsYXkuc2Nyb2xsYmFycy5zZXRTY3JvbGxUb3AodmFsKTtcbiAgICBpZiAoY20uZGlzcGxheS5zY3JvbGxlci5zY3JvbGxUb3AgIT0gdmFsKSB7IGNtLmRpc3BsYXkuc2Nyb2xsZXIuc2Nyb2xsVG9wID0gdmFsOyB9XG4gIH1cblxuICAvLyBTeW5jIHNjcm9sbGVyIGFuZCBzY3JvbGxiYXIsIGVuc3VyZSB0aGUgZ3V0dGVyIGVsZW1lbnRzIGFyZVxuICAvLyBhbGlnbmVkLlxuICBmdW5jdGlvbiBzZXRTY3JvbGxMZWZ0KGNtLCB2YWwsIGlzU2Nyb2xsZXIsIGZvcmNlU2Nyb2xsKSB7XG4gICAgdmFsID0gTWF0aC5tYXgoMCwgTWF0aC5taW4odmFsLCBjbS5kaXNwbGF5LnNjcm9sbGVyLnNjcm9sbFdpZHRoIC0gY20uZGlzcGxheS5zY3JvbGxlci5jbGllbnRXaWR0aCkpO1xuICAgIGlmICgoaXNTY3JvbGxlciA/IHZhbCA9PSBjbS5kb2Muc2Nyb2xsTGVmdCA6IE1hdGguYWJzKGNtLmRvYy5zY3JvbGxMZWZ0IC0gdmFsKSA8IDIpICYmICFmb3JjZVNjcm9sbCkgeyByZXR1cm4gfVxuICAgIGNtLmRvYy5zY3JvbGxMZWZ0ID0gdmFsO1xuICAgIGFsaWduSG9yaXpvbnRhbGx5KGNtKTtcbiAgICBpZiAoY20uZGlzcGxheS5zY3JvbGxlci5zY3JvbGxMZWZ0ICE9IHZhbCkgeyBjbS5kaXNwbGF5LnNjcm9sbGVyLnNjcm9sbExlZnQgPSB2YWw7IH1cbiAgICBjbS5kaXNwbGF5LnNjcm9sbGJhcnMuc2V0U2Nyb2xsTGVmdCh2YWwpO1xuICB9XG5cbiAgLy8gU0NST0xMQkFSU1xuXG4gIC8vIFByZXBhcmUgRE9NIHJlYWRzIG5lZWRlZCB0byB1cGRhdGUgdGhlIHNjcm9sbGJhcnMuIERvbmUgaW4gb25lXG4gIC8vIHNob3QgdG8gbWluaW1pemUgdXBkYXRlL21lYXN1cmUgcm91bmR0cmlwcy5cbiAgZnVuY3Rpb24gbWVhc3VyZUZvclNjcm9sbGJhcnMoY20pIHtcbiAgICB2YXIgZCA9IGNtLmRpc3BsYXksIGd1dHRlclcgPSBkLmd1dHRlcnMub2Zmc2V0V2lkdGg7XG4gICAgdmFyIGRvY0ggPSBNYXRoLnJvdW5kKGNtLmRvYy5oZWlnaHQgKyBwYWRkaW5nVmVydChjbS5kaXNwbGF5KSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNsaWVudEhlaWdodDogZC5zY3JvbGxlci5jbGllbnRIZWlnaHQsXG4gICAgICB2aWV3SGVpZ2h0OiBkLndyYXBwZXIuY2xpZW50SGVpZ2h0LFxuICAgICAgc2Nyb2xsV2lkdGg6IGQuc2Nyb2xsZXIuc2Nyb2xsV2lkdGgsIGNsaWVudFdpZHRoOiBkLnNjcm9sbGVyLmNsaWVudFdpZHRoLFxuICAgICAgdmlld1dpZHRoOiBkLndyYXBwZXIuY2xpZW50V2lkdGgsXG4gICAgICBiYXJMZWZ0OiBjbS5vcHRpb25zLmZpeGVkR3V0dGVyID8gZ3V0dGVyVyA6IDAsXG4gICAgICBkb2NIZWlnaHQ6IGRvY0gsXG4gICAgICBzY3JvbGxIZWlnaHQ6IGRvY0ggKyBzY3JvbGxHYXAoY20pICsgZC5iYXJIZWlnaHQsXG4gICAgICBuYXRpdmVCYXJXaWR0aDogZC5uYXRpdmVCYXJXaWR0aCxcbiAgICAgIGd1dHRlcldpZHRoOiBndXR0ZXJXXG4gICAgfVxuICB9XG5cbiAgdmFyIE5hdGl2ZVNjcm9sbGJhcnMgPSBmdW5jdGlvbihwbGFjZSwgc2Nyb2xsLCBjbSkge1xuICAgIHRoaXMuY20gPSBjbTtcbiAgICB2YXIgdmVydCA9IHRoaXMudmVydCA9IGVsdChcImRpdlwiLCBbZWx0KFwiZGl2XCIsIG51bGwsIG51bGwsIFwibWluLXdpZHRoOiAxcHhcIildLCBcIkNvZGVNaXJyb3ItdnNjcm9sbGJhclwiKTtcbiAgICB2YXIgaG9yaXogPSB0aGlzLmhvcml6ID0gZWx0KFwiZGl2XCIsIFtlbHQoXCJkaXZcIiwgbnVsbCwgbnVsbCwgXCJoZWlnaHQ6IDEwMCU7IG1pbi1oZWlnaHQ6IDFweFwiKV0sIFwiQ29kZU1pcnJvci1oc2Nyb2xsYmFyXCIpO1xuICAgIHZlcnQudGFiSW5kZXggPSBob3Jpei50YWJJbmRleCA9IC0xO1xuICAgIHBsYWNlKHZlcnQpOyBwbGFjZShob3Jpeik7XG5cbiAgICBvbih2ZXJ0LCBcInNjcm9sbFwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAodmVydC5jbGllbnRIZWlnaHQpIHsgc2Nyb2xsKHZlcnQuc2Nyb2xsVG9wLCBcInZlcnRpY2FsXCIpOyB9XG4gICAgfSk7XG4gICAgb24oaG9yaXosIFwic2Nyb2xsXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmIChob3Jpei5jbGllbnRXaWR0aCkgeyBzY3JvbGwoaG9yaXouc2Nyb2xsTGVmdCwgXCJob3Jpem9udGFsXCIpOyB9XG4gICAgfSk7XG5cbiAgICB0aGlzLmNoZWNrZWRaZXJvV2lkdGggPSBmYWxzZTtcbiAgICAvLyBOZWVkIHRvIHNldCBhIG1pbmltdW0gd2lkdGggdG8gc2VlIHRoZSBzY3JvbGxiYXIgb24gSUU3IChidXQgbXVzdCBub3Qgc2V0IGl0IG9uIElFOCkuXG4gICAgaWYgKGllICYmIGllX3ZlcnNpb24gPCA4KSB7IHRoaXMuaG9yaXouc3R5bGUubWluSGVpZ2h0ID0gdGhpcy52ZXJ0LnN0eWxlLm1pbldpZHRoID0gXCIxOHB4XCI7IH1cbiAgfTtcblxuICBOYXRpdmVTY3JvbGxiYXJzLnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbiAobWVhc3VyZSkge1xuICAgIHZhciBuZWVkc0ggPSBtZWFzdXJlLnNjcm9sbFdpZHRoID4gbWVhc3VyZS5jbGllbnRXaWR0aCArIDE7XG4gICAgdmFyIG5lZWRzViA9IG1lYXN1cmUuc2Nyb2xsSGVpZ2h0ID4gbWVhc3VyZS5jbGllbnRIZWlnaHQgKyAxO1xuICAgIHZhciBzV2lkdGggPSBtZWFzdXJlLm5hdGl2ZUJhcldpZHRoO1xuXG4gICAgaWYgKG5lZWRzVikge1xuICAgICAgdGhpcy52ZXJ0LnN0eWxlLmRpc3BsYXkgPSBcImJsb2NrXCI7XG4gICAgICB0aGlzLnZlcnQuc3R5bGUuYm90dG9tID0gbmVlZHNIID8gc1dpZHRoICsgXCJweFwiIDogXCIwXCI7XG4gICAgICB2YXIgdG90YWxIZWlnaHQgPSBtZWFzdXJlLnZpZXdIZWlnaHQgLSAobmVlZHNIID8gc1dpZHRoIDogMCk7XG4gICAgICAvLyBBIGJ1ZyBpbiBJRTggY2FuIGNhdXNlIHRoaXMgdmFsdWUgdG8gYmUgbmVnYXRpdmUsIHNvIGd1YXJkIGl0LlxuICAgICAgdGhpcy52ZXJ0LmZpcnN0Q2hpbGQuc3R5bGUuaGVpZ2h0ID1cbiAgICAgICAgTWF0aC5tYXgoMCwgbWVhc3VyZS5zY3JvbGxIZWlnaHQgLSBtZWFzdXJlLmNsaWVudEhlaWdodCArIHRvdGFsSGVpZ2h0KSArIFwicHhcIjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy52ZXJ0LnNjcm9sbFRvcCA9IDA7XG4gICAgICB0aGlzLnZlcnQuc3R5bGUuZGlzcGxheSA9IFwiXCI7XG4gICAgICB0aGlzLnZlcnQuZmlyc3RDaGlsZC5zdHlsZS5oZWlnaHQgPSBcIjBcIjtcbiAgICB9XG5cbiAgICBpZiAobmVlZHNIKSB7XG4gICAgICB0aGlzLmhvcml6LnN0eWxlLmRpc3BsYXkgPSBcImJsb2NrXCI7XG4gICAgICB0aGlzLmhvcml6LnN0eWxlLnJpZ2h0ID0gbmVlZHNWID8gc1dpZHRoICsgXCJweFwiIDogXCIwXCI7XG4gICAgICB0aGlzLmhvcml6LnN0eWxlLmxlZnQgPSBtZWFzdXJlLmJhckxlZnQgKyBcInB4XCI7XG4gICAgICB2YXIgdG90YWxXaWR0aCA9IG1lYXN1cmUudmlld1dpZHRoIC0gbWVhc3VyZS5iYXJMZWZ0IC0gKG5lZWRzViA/IHNXaWR0aCA6IDApO1xuICAgICAgdGhpcy5ob3Jpei5maXJzdENoaWxkLnN0eWxlLndpZHRoID1cbiAgICAgICAgTWF0aC5tYXgoMCwgbWVhc3VyZS5zY3JvbGxXaWR0aCAtIG1lYXN1cmUuY2xpZW50V2lkdGggKyB0b3RhbFdpZHRoKSArIFwicHhcIjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5ob3Jpei5zdHlsZS5kaXNwbGF5ID0gXCJcIjtcbiAgICAgIHRoaXMuaG9yaXouZmlyc3RDaGlsZC5zdHlsZS53aWR0aCA9IFwiMFwiO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5jaGVja2VkWmVyb1dpZHRoICYmIG1lYXN1cmUuY2xpZW50SGVpZ2h0ID4gMCkge1xuICAgICAgaWYgKHNXaWR0aCA9PSAwKSB7IHRoaXMuemVyb1dpZHRoSGFjaygpOyB9XG4gICAgICB0aGlzLmNoZWNrZWRaZXJvV2lkdGggPSB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiB7cmlnaHQ6IG5lZWRzViA/IHNXaWR0aCA6IDAsIGJvdHRvbTogbmVlZHNIID8gc1dpZHRoIDogMH1cbiAgfTtcblxuICBOYXRpdmVTY3JvbGxiYXJzLnByb3RvdHlwZS5zZXRTY3JvbGxMZWZ0ID0gZnVuY3Rpb24gKHBvcykge1xuICAgIGlmICh0aGlzLmhvcml6LnNjcm9sbExlZnQgIT0gcG9zKSB7IHRoaXMuaG9yaXouc2Nyb2xsTGVmdCA9IHBvczsgfVxuICAgIGlmICh0aGlzLmRpc2FibGVIb3JpeikgeyB0aGlzLmVuYWJsZVplcm9XaWR0aEJhcih0aGlzLmhvcml6LCB0aGlzLmRpc2FibGVIb3JpeiwgXCJob3JpelwiKTsgfVxuICB9O1xuXG4gIE5hdGl2ZVNjcm9sbGJhcnMucHJvdG90eXBlLnNldFNjcm9sbFRvcCA9IGZ1bmN0aW9uIChwb3MpIHtcbiAgICBpZiAodGhpcy52ZXJ0LnNjcm9sbFRvcCAhPSBwb3MpIHsgdGhpcy52ZXJ0LnNjcm9sbFRvcCA9IHBvczsgfVxuICAgIGlmICh0aGlzLmRpc2FibGVWZXJ0KSB7IHRoaXMuZW5hYmxlWmVyb1dpZHRoQmFyKHRoaXMudmVydCwgdGhpcy5kaXNhYmxlVmVydCwgXCJ2ZXJ0XCIpOyB9XG4gIH07XG5cbiAgTmF0aXZlU2Nyb2xsYmFycy5wcm90b3R5cGUuemVyb1dpZHRoSGFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgdyA9IG1hYyAmJiAhbWFjX2dlTW91bnRhaW5MaW9uID8gXCIxMnB4XCIgOiBcIjE4cHhcIjtcbiAgICB0aGlzLmhvcml6LnN0eWxlLmhlaWdodCA9IHRoaXMudmVydC5zdHlsZS53aWR0aCA9IHc7XG4gICAgdGhpcy5ob3Jpei5zdHlsZS5wb2ludGVyRXZlbnRzID0gdGhpcy52ZXJ0LnN0eWxlLnBvaW50ZXJFdmVudHMgPSBcIm5vbmVcIjtcbiAgICB0aGlzLmRpc2FibGVIb3JpeiA9IG5ldyBEZWxheWVkO1xuICAgIHRoaXMuZGlzYWJsZVZlcnQgPSBuZXcgRGVsYXllZDtcbiAgfTtcblxuICBOYXRpdmVTY3JvbGxiYXJzLnByb3RvdHlwZS5lbmFibGVaZXJvV2lkdGhCYXIgPSBmdW5jdGlvbiAoYmFyLCBkZWxheSwgdHlwZSkge1xuICAgIGJhci5zdHlsZS5wb2ludGVyRXZlbnRzID0gXCJhdXRvXCI7XG4gICAgZnVuY3Rpb24gbWF5YmVEaXNhYmxlKCkge1xuICAgICAgLy8gVG8gZmluZCBvdXQgd2hldGhlciB0aGUgc2Nyb2xsYmFyIGlzIHN0aWxsIHZpc2libGUsIHdlXG4gICAgICAvLyBjaGVjayB3aGV0aGVyIHRoZSBlbGVtZW50IHVuZGVyIHRoZSBwaXhlbCBpbiB0aGUgYm90dG9tXG4gICAgICAvLyByaWdodCBjb3JuZXIgb2YgdGhlIHNjcm9sbGJhciBib3ggaXMgdGhlIHNjcm9sbGJhciBib3hcbiAgICAgIC8vIGl0c2VsZiAod2hlbiB0aGUgYmFyIGlzIHN0aWxsIHZpc2libGUpIG9yIGl0cyBmaWxsZXIgY2hpbGRcbiAgICAgIC8vICh3aGVuIHRoZSBiYXIgaXMgaGlkZGVuKS4gSWYgaXQgaXMgc3RpbGwgdmlzaWJsZSwgd2Uga2VlcFxuICAgICAgLy8gaXQgZW5hYmxlZCwgaWYgaXQncyBoaWRkZW4sIHdlIGRpc2FibGUgcG9pbnRlciBldmVudHMuXG4gICAgICB2YXIgYm94ID0gYmFyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgdmFyIGVsdCA9IHR5cGUgPT0gXCJ2ZXJ0XCIgPyBkb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KGJveC5yaWdodCAtIDEsIChib3gudG9wICsgYm94LmJvdHRvbSkgLyAyKVxuICAgICAgICAgIDogZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludCgoYm94LnJpZ2h0ICsgYm94LmxlZnQpIC8gMiwgYm94LmJvdHRvbSAtIDEpO1xuICAgICAgaWYgKGVsdCAhPSBiYXIpIHsgYmFyLnN0eWxlLnBvaW50ZXJFdmVudHMgPSBcIm5vbmVcIjsgfVxuICAgICAgZWxzZSB7IGRlbGF5LnNldCgxMDAwLCBtYXliZURpc2FibGUpOyB9XG4gICAgfVxuICAgIGRlbGF5LnNldCgxMDAwLCBtYXliZURpc2FibGUpO1xuICB9O1xuXG4gIE5hdGl2ZVNjcm9sbGJhcnMucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBwYXJlbnQgPSB0aGlzLmhvcml6LnBhcmVudE5vZGU7XG4gICAgcGFyZW50LnJlbW92ZUNoaWxkKHRoaXMuaG9yaXopO1xuICAgIHBhcmVudC5yZW1vdmVDaGlsZCh0aGlzLnZlcnQpO1xuICB9O1xuXG4gIHZhciBOdWxsU2Nyb2xsYmFycyA9IGZ1bmN0aW9uICgpIHt9O1xuXG4gIE51bGxTY3JvbGxiYXJzLnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbiAoKSB7IHJldHVybiB7Ym90dG9tOiAwLCByaWdodDogMH0gfTtcbiAgTnVsbFNjcm9sbGJhcnMucHJvdG90eXBlLnNldFNjcm9sbExlZnQgPSBmdW5jdGlvbiAoKSB7fTtcbiAgTnVsbFNjcm9sbGJhcnMucHJvdG90eXBlLnNldFNjcm9sbFRvcCA9IGZ1bmN0aW9uICgpIHt9O1xuICBOdWxsU2Nyb2xsYmFycy5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbiAoKSB7fTtcblxuICBmdW5jdGlvbiB1cGRhdGVTY3JvbGxiYXJzKGNtLCBtZWFzdXJlKSB7XG4gICAgaWYgKCFtZWFzdXJlKSB7IG1lYXN1cmUgPSBtZWFzdXJlRm9yU2Nyb2xsYmFycyhjbSk7IH1cbiAgICB2YXIgc3RhcnRXaWR0aCA9IGNtLmRpc3BsYXkuYmFyV2lkdGgsIHN0YXJ0SGVpZ2h0ID0gY20uZGlzcGxheS5iYXJIZWlnaHQ7XG4gICAgdXBkYXRlU2Nyb2xsYmFyc0lubmVyKGNtLCBtZWFzdXJlKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IDQgJiYgc3RhcnRXaWR0aCAhPSBjbS5kaXNwbGF5LmJhcldpZHRoIHx8IHN0YXJ0SGVpZ2h0ICE9IGNtLmRpc3BsYXkuYmFySGVpZ2h0OyBpKyspIHtcbiAgICAgIGlmIChzdGFydFdpZHRoICE9IGNtLmRpc3BsYXkuYmFyV2lkdGggJiYgY20ub3B0aW9ucy5saW5lV3JhcHBpbmcpXG4gICAgICAgIHsgdXBkYXRlSGVpZ2h0c0luVmlld3BvcnQoY20pOyB9XG4gICAgICB1cGRhdGVTY3JvbGxiYXJzSW5uZXIoY20sIG1lYXN1cmVGb3JTY3JvbGxiYXJzKGNtKSk7XG4gICAgICBzdGFydFdpZHRoID0gY20uZGlzcGxheS5iYXJXaWR0aDsgc3RhcnRIZWlnaHQgPSBjbS5kaXNwbGF5LmJhckhlaWdodDtcbiAgICB9XG4gIH1cblxuICAvLyBSZS1zeW5jaHJvbml6ZSB0aGUgZmFrZSBzY3JvbGxiYXJzIHdpdGggdGhlIGFjdHVhbCBzaXplIG9mIHRoZVxuICAvLyBjb250ZW50LlxuICBmdW5jdGlvbiB1cGRhdGVTY3JvbGxiYXJzSW5uZXIoY20sIG1lYXN1cmUpIHtcbiAgICB2YXIgZCA9IGNtLmRpc3BsYXk7XG4gICAgdmFyIHNpemVzID0gZC5zY3JvbGxiYXJzLnVwZGF0ZShtZWFzdXJlKTtcblxuICAgIGQuc2l6ZXIuc3R5bGUucGFkZGluZ1JpZ2h0ID0gKGQuYmFyV2lkdGggPSBzaXplcy5yaWdodCkgKyBcInB4XCI7XG4gICAgZC5zaXplci5zdHlsZS5wYWRkaW5nQm90dG9tID0gKGQuYmFySGVpZ2h0ID0gc2l6ZXMuYm90dG9tKSArIFwicHhcIjtcbiAgICBkLmhlaWdodEZvcmNlci5zdHlsZS5ib3JkZXJCb3R0b20gPSBzaXplcy5ib3R0b20gKyBcInB4IHNvbGlkIHRyYW5zcGFyZW50XCI7XG5cbiAgICBpZiAoc2l6ZXMucmlnaHQgJiYgc2l6ZXMuYm90dG9tKSB7XG4gICAgICBkLnNjcm9sbGJhckZpbGxlci5zdHlsZS5kaXNwbGF5ID0gXCJibG9ja1wiO1xuICAgICAgZC5zY3JvbGxiYXJGaWxsZXIuc3R5bGUuaGVpZ2h0ID0gc2l6ZXMuYm90dG9tICsgXCJweFwiO1xuICAgICAgZC5zY3JvbGxiYXJGaWxsZXIuc3R5bGUud2lkdGggPSBzaXplcy5yaWdodCArIFwicHhcIjtcbiAgICB9IGVsc2UgeyBkLnNjcm9sbGJhckZpbGxlci5zdHlsZS5kaXNwbGF5ID0gXCJcIjsgfVxuICAgIGlmIChzaXplcy5ib3R0b20gJiYgY20ub3B0aW9ucy5jb3Zlckd1dHRlck5leHRUb1Njcm9sbGJhciAmJiBjbS5vcHRpb25zLmZpeGVkR3V0dGVyKSB7XG4gICAgICBkLmd1dHRlckZpbGxlci5zdHlsZS5kaXNwbGF5ID0gXCJibG9ja1wiO1xuICAgICAgZC5ndXR0ZXJGaWxsZXIuc3R5bGUuaGVpZ2h0ID0gc2l6ZXMuYm90dG9tICsgXCJweFwiO1xuICAgICAgZC5ndXR0ZXJGaWxsZXIuc3R5bGUud2lkdGggPSBtZWFzdXJlLmd1dHRlcldpZHRoICsgXCJweFwiO1xuICAgIH0gZWxzZSB7IGQuZ3V0dGVyRmlsbGVyLnN0eWxlLmRpc3BsYXkgPSBcIlwiOyB9XG4gIH1cblxuICB2YXIgc2Nyb2xsYmFyTW9kZWwgPSB7XCJuYXRpdmVcIjogTmF0aXZlU2Nyb2xsYmFycywgXCJudWxsXCI6IE51bGxTY3JvbGxiYXJzfTtcblxuICBmdW5jdGlvbiBpbml0U2Nyb2xsYmFycyhjbSkge1xuICAgIGlmIChjbS5kaXNwbGF5LnNjcm9sbGJhcnMpIHtcbiAgICAgIGNtLmRpc3BsYXkuc2Nyb2xsYmFycy5jbGVhcigpO1xuICAgICAgaWYgKGNtLmRpc3BsYXkuc2Nyb2xsYmFycy5hZGRDbGFzcylcbiAgICAgICAgeyBybUNsYXNzKGNtLmRpc3BsYXkud3JhcHBlciwgY20uZGlzcGxheS5zY3JvbGxiYXJzLmFkZENsYXNzKTsgfVxuICAgIH1cblxuICAgIGNtLmRpc3BsYXkuc2Nyb2xsYmFycyA9IG5ldyBzY3JvbGxiYXJNb2RlbFtjbS5vcHRpb25zLnNjcm9sbGJhclN0eWxlXShmdW5jdGlvbiAobm9kZSkge1xuICAgICAgY20uZGlzcGxheS53cmFwcGVyLmluc2VydEJlZm9yZShub2RlLCBjbS5kaXNwbGF5LnNjcm9sbGJhckZpbGxlcik7XG4gICAgICAvLyBQcmV2ZW50IGNsaWNrcyBpbiB0aGUgc2Nyb2xsYmFycyBmcm9tIGtpbGxpbmcgZm9jdXNcbiAgICAgIG9uKG5vZGUsIFwibW91c2Vkb3duXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGNtLnN0YXRlLmZvY3VzZWQpIHsgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7IHJldHVybiBjbS5kaXNwbGF5LmlucHV0LmZvY3VzKCk7IH0sIDApOyB9XG4gICAgICB9KTtcbiAgICAgIG5vZGUuc2V0QXR0cmlidXRlKFwiY20tbm90LWNvbnRlbnRcIiwgXCJ0cnVlXCIpO1xuICAgIH0sIGZ1bmN0aW9uIChwb3MsIGF4aXMpIHtcbiAgICAgIGlmIChheGlzID09IFwiaG9yaXpvbnRhbFwiKSB7IHNldFNjcm9sbExlZnQoY20sIHBvcyk7IH1cbiAgICAgIGVsc2UgeyB1cGRhdGVTY3JvbGxUb3AoY20sIHBvcyk7IH1cbiAgICB9LCBjbSk7XG4gICAgaWYgKGNtLmRpc3BsYXkuc2Nyb2xsYmFycy5hZGRDbGFzcylcbiAgICAgIHsgYWRkQ2xhc3MoY20uZGlzcGxheS53cmFwcGVyLCBjbS5kaXNwbGF5LnNjcm9sbGJhcnMuYWRkQ2xhc3MpOyB9XG4gIH1cblxuICAvLyBPcGVyYXRpb25zIGFyZSB1c2VkIHRvIHdyYXAgYSBzZXJpZXMgb2YgY2hhbmdlcyB0byB0aGUgZWRpdG9yXG4gIC8vIHN0YXRlIGluIHN1Y2ggYSB3YXkgdGhhdCBlYWNoIGNoYW5nZSB3b24ndCBoYXZlIHRvIHVwZGF0ZSB0aGVcbiAgLy8gY3Vyc29yIGFuZCBkaXNwbGF5ICh3aGljaCB3b3VsZCBiZSBhd2t3YXJkLCBzbG93LCBhbmRcbiAgLy8gZXJyb3ItcHJvbmUpLiBJbnN0ZWFkLCBkaXNwbGF5IHVwZGF0ZXMgYXJlIGJhdGNoZWQgYW5kIHRoZW4gYWxsXG4gIC8vIGNvbWJpbmVkIGFuZCBleGVjdXRlZCBhdCBvbmNlLlxuXG4gIHZhciBuZXh0T3BJZCA9IDA7XG4gIC8vIFN0YXJ0IGEgbmV3IG9wZXJhdGlvbi5cbiAgZnVuY3Rpb24gc3RhcnRPcGVyYXRpb24oY20pIHtcbiAgICBjbS5jdXJPcCA9IHtcbiAgICAgIGNtOiBjbSxcbiAgICAgIHZpZXdDaGFuZ2VkOiBmYWxzZSwgICAgICAvLyBGbGFnIHRoYXQgaW5kaWNhdGVzIHRoYXQgbGluZXMgbWlnaHQgbmVlZCB0byBiZSByZWRyYXduXG4gICAgICBzdGFydEhlaWdodDogY20uZG9jLmhlaWdodCwgLy8gVXNlZCB0byBkZXRlY3QgbmVlZCB0byB1cGRhdGUgc2Nyb2xsYmFyXG4gICAgICBmb3JjZVVwZGF0ZTogZmFsc2UsICAgICAgLy8gVXNlZCB0byBmb3JjZSBhIHJlZHJhd1xuICAgICAgdXBkYXRlSW5wdXQ6IDAsICAgICAgIC8vIFdoZXRoZXIgdG8gcmVzZXQgdGhlIGlucHV0IHRleHRhcmVhXG4gICAgICB0eXBpbmc6IGZhbHNlLCAgICAgICAgICAgLy8gV2hldGhlciB0aGlzIHJlc2V0IHNob3VsZCBiZSBjYXJlZnVsIHRvIGxlYXZlIGV4aXN0aW5nIHRleHQgKGZvciBjb21wb3NpdGluZylcbiAgICAgIGNoYW5nZU9ianM6IG51bGwsICAgICAgICAvLyBBY2N1bXVsYXRlZCBjaGFuZ2VzLCBmb3IgZmlyaW5nIGNoYW5nZSBldmVudHNcbiAgICAgIGN1cnNvckFjdGl2aXR5SGFuZGxlcnM6IG51bGwsIC8vIFNldCBvZiBoYW5kbGVycyB0byBmaXJlIGN1cnNvckFjdGl2aXR5IG9uXG4gICAgICBjdXJzb3JBY3Rpdml0eUNhbGxlZDogMCwgLy8gVHJhY2tzIHdoaWNoIGN1cnNvckFjdGl2aXR5IGhhbmRsZXJzIGhhdmUgYmVlbiBjYWxsZWQgYWxyZWFkeVxuICAgICAgc2VsZWN0aW9uQ2hhbmdlZDogZmFsc2UsIC8vIFdoZXRoZXIgdGhlIHNlbGVjdGlvbiBuZWVkcyB0byBiZSByZWRyYXduXG4gICAgICB1cGRhdGVNYXhMaW5lOiBmYWxzZSwgICAgLy8gU2V0IHdoZW4gdGhlIHdpZGVzdCBsaW5lIG5lZWRzIHRvIGJlIGRldGVybWluZWQgYW5ld1xuICAgICAgc2Nyb2xsTGVmdDogbnVsbCwgc2Nyb2xsVG9wOiBudWxsLCAvLyBJbnRlcm1lZGlhdGUgc2Nyb2xsIHBvc2l0aW9uLCBub3QgcHVzaGVkIHRvIERPTSB5ZXRcbiAgICAgIHNjcm9sbFRvUG9zOiBudWxsLCAgICAgICAvLyBVc2VkIHRvIHNjcm9sbCB0byBhIHNwZWNpZmljIHBvc2l0aW9uXG4gICAgICBmb2N1czogZmFsc2UsXG4gICAgICBpZDogKytuZXh0T3BJZCwgICAgICAgICAgLy8gVW5pcXVlIElEXG4gICAgICBtYXJrQXJyYXlzOiBudWxsICAgICAgICAgLy8gVXNlZCBieSBhZGRNYXJrZWRTcGFuXG4gICAgfTtcbiAgICBwdXNoT3BlcmF0aW9uKGNtLmN1ck9wKTtcbiAgfVxuXG4gIC8vIEZpbmlzaCBhbiBvcGVyYXRpb24sIHVwZGF0aW5nIHRoZSBkaXNwbGF5IGFuZCBzaWduYWxsaW5nIGRlbGF5ZWQgZXZlbnRzXG4gIGZ1bmN0aW9uIGVuZE9wZXJhdGlvbihjbSkge1xuICAgIHZhciBvcCA9IGNtLmN1ck9wO1xuICAgIGlmIChvcCkgeyBmaW5pc2hPcGVyYXRpb24ob3AsIGZ1bmN0aW9uIChncm91cCkge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBncm91cC5vcHMubGVuZ3RoOyBpKyspXG4gICAgICAgIHsgZ3JvdXAub3BzW2ldLmNtLmN1ck9wID0gbnVsbDsgfVxuICAgICAgZW5kT3BlcmF0aW9ucyhncm91cCk7XG4gICAgfSk7IH1cbiAgfVxuXG4gIC8vIFRoZSBET00gdXBkYXRlcyBkb25lIHdoZW4gYW4gb3BlcmF0aW9uIGZpbmlzaGVzIGFyZSBiYXRjaGVkIHNvXG4gIC8vIHRoYXQgdGhlIG1pbmltdW0gbnVtYmVyIG9mIHJlbGF5b3V0cyBhcmUgcmVxdWlyZWQuXG4gIGZ1bmN0aW9uIGVuZE9wZXJhdGlvbnMoZ3JvdXApIHtcbiAgICB2YXIgb3BzID0gZ3JvdXAub3BzO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3BzLmxlbmd0aDsgaSsrKSAvLyBSZWFkIERPTVxuICAgICAgeyBlbmRPcGVyYXRpb25fUjEob3BzW2ldKTsgfVxuICAgIGZvciAodmFyIGkkMSA9IDA7IGkkMSA8IG9wcy5sZW5ndGg7IGkkMSsrKSAvLyBXcml0ZSBET00gKG1heWJlKVxuICAgICAgeyBlbmRPcGVyYXRpb25fVzEob3BzW2kkMV0pOyB9XG4gICAgZm9yICh2YXIgaSQyID0gMDsgaSQyIDwgb3BzLmxlbmd0aDsgaSQyKyspIC8vIFJlYWQgRE9NXG4gICAgICB7IGVuZE9wZXJhdGlvbl9SMihvcHNbaSQyXSk7IH1cbiAgICBmb3IgKHZhciBpJDMgPSAwOyBpJDMgPCBvcHMubGVuZ3RoOyBpJDMrKykgLy8gV3JpdGUgRE9NIChtYXliZSlcbiAgICAgIHsgZW5kT3BlcmF0aW9uX1cyKG9wc1tpJDNdKTsgfVxuICAgIGZvciAodmFyIGkkNCA9IDA7IGkkNCA8IG9wcy5sZW5ndGg7IGkkNCsrKSAvLyBSZWFkIERPTVxuICAgICAgeyBlbmRPcGVyYXRpb25fZmluaXNoKG9wc1tpJDRdKTsgfVxuICB9XG5cbiAgZnVuY3Rpb24gZW5kT3BlcmF0aW9uX1IxKG9wKSB7XG4gICAgdmFyIGNtID0gb3AuY20sIGRpc3BsYXkgPSBjbS5kaXNwbGF5O1xuICAgIG1heWJlQ2xpcFNjcm9sbGJhcnMoY20pO1xuICAgIGlmIChvcC51cGRhdGVNYXhMaW5lKSB7IGZpbmRNYXhMaW5lKGNtKTsgfVxuXG4gICAgb3AubXVzdFVwZGF0ZSA9IG9wLnZpZXdDaGFuZ2VkIHx8IG9wLmZvcmNlVXBkYXRlIHx8IG9wLnNjcm9sbFRvcCAhPSBudWxsIHx8XG4gICAgICBvcC5zY3JvbGxUb1BvcyAmJiAob3Auc2Nyb2xsVG9Qb3MuZnJvbS5saW5lIDwgZGlzcGxheS52aWV3RnJvbSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgIG9wLnNjcm9sbFRvUG9zLnRvLmxpbmUgPj0gZGlzcGxheS52aWV3VG8pIHx8XG4gICAgICBkaXNwbGF5Lm1heExpbmVDaGFuZ2VkICYmIGNtLm9wdGlvbnMubGluZVdyYXBwaW5nO1xuICAgIG9wLnVwZGF0ZSA9IG9wLm11c3RVcGRhdGUgJiZcbiAgICAgIG5ldyBEaXNwbGF5VXBkYXRlKGNtLCBvcC5tdXN0VXBkYXRlICYmIHt0b3A6IG9wLnNjcm9sbFRvcCwgZW5zdXJlOiBvcC5zY3JvbGxUb1Bvc30sIG9wLmZvcmNlVXBkYXRlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGVuZE9wZXJhdGlvbl9XMShvcCkge1xuICAgIG9wLnVwZGF0ZWREaXNwbGF5ID0gb3AubXVzdFVwZGF0ZSAmJiB1cGRhdGVEaXNwbGF5SWZOZWVkZWQob3AuY20sIG9wLnVwZGF0ZSk7XG4gIH1cblxuICBmdW5jdGlvbiBlbmRPcGVyYXRpb25fUjIob3ApIHtcbiAgICB2YXIgY20gPSBvcC5jbSwgZGlzcGxheSA9IGNtLmRpc3BsYXk7XG4gICAgaWYgKG9wLnVwZGF0ZWREaXNwbGF5KSB7IHVwZGF0ZUhlaWdodHNJblZpZXdwb3J0KGNtKTsgfVxuXG4gICAgb3AuYmFyTWVhc3VyZSA9IG1lYXN1cmVGb3JTY3JvbGxiYXJzKGNtKTtcblxuICAgIC8vIElmIHRoZSBtYXggbGluZSBjaGFuZ2VkIHNpbmNlIGl0IHdhcyBsYXN0IG1lYXN1cmVkLCBtZWFzdXJlIGl0LFxuICAgIC8vIGFuZCBlbnN1cmUgdGhlIGRvY3VtZW50J3Mgd2lkdGggbWF0Y2hlcyBpdC5cbiAgICAvLyB1cGRhdGVEaXNwbGF5X1cyIHdpbGwgdXNlIHRoZXNlIHByb3BlcnRpZXMgdG8gZG8gdGhlIGFjdHVhbCByZXNpemluZ1xuICAgIGlmIChkaXNwbGF5Lm1heExpbmVDaGFuZ2VkICYmICFjbS5vcHRpb25zLmxpbmVXcmFwcGluZykge1xuICAgICAgb3AuYWRqdXN0V2lkdGhUbyA9IG1lYXN1cmVDaGFyKGNtLCBkaXNwbGF5Lm1heExpbmUsIGRpc3BsYXkubWF4TGluZS50ZXh0Lmxlbmd0aCkubGVmdCArIDM7XG4gICAgICBjbS5kaXNwbGF5LnNpemVyV2lkdGggPSBvcC5hZGp1c3RXaWR0aFRvO1xuICAgICAgb3AuYmFyTWVhc3VyZS5zY3JvbGxXaWR0aCA9XG4gICAgICAgIE1hdGgubWF4KGRpc3BsYXkuc2Nyb2xsZXIuY2xpZW50V2lkdGgsIGRpc3BsYXkuc2l6ZXIub2Zmc2V0TGVmdCArIG9wLmFkanVzdFdpZHRoVG8gKyBzY3JvbGxHYXAoY20pICsgY20uZGlzcGxheS5iYXJXaWR0aCk7XG4gICAgICBvcC5tYXhTY3JvbGxMZWZ0ID0gTWF0aC5tYXgoMCwgZGlzcGxheS5zaXplci5vZmZzZXRMZWZ0ICsgb3AuYWRqdXN0V2lkdGhUbyAtIGRpc3BsYXlXaWR0aChjbSkpO1xuICAgIH1cblxuICAgIGlmIChvcC51cGRhdGVkRGlzcGxheSB8fCBvcC5zZWxlY3Rpb25DaGFuZ2VkKVxuICAgICAgeyBvcC5wcmVwYXJlZFNlbGVjdGlvbiA9IGRpc3BsYXkuaW5wdXQucHJlcGFyZVNlbGVjdGlvbigpOyB9XG4gIH1cblxuICBmdW5jdGlvbiBlbmRPcGVyYXRpb25fVzIob3ApIHtcbiAgICB2YXIgY20gPSBvcC5jbTtcblxuICAgIGlmIChvcC5hZGp1c3RXaWR0aFRvICE9IG51bGwpIHtcbiAgICAgIGNtLmRpc3BsYXkuc2l6ZXIuc3R5bGUubWluV2lkdGggPSBvcC5hZGp1c3RXaWR0aFRvICsgXCJweFwiO1xuICAgICAgaWYgKG9wLm1heFNjcm9sbExlZnQgPCBjbS5kb2Muc2Nyb2xsTGVmdClcbiAgICAgICAgeyBzZXRTY3JvbGxMZWZ0KGNtLCBNYXRoLm1pbihjbS5kaXNwbGF5LnNjcm9sbGVyLnNjcm9sbExlZnQsIG9wLm1heFNjcm9sbExlZnQpLCB0cnVlKTsgfVxuICAgICAgY20uZGlzcGxheS5tYXhMaW5lQ2hhbmdlZCA9IGZhbHNlO1xuICAgIH1cblxuICAgIHZhciB0YWtlRm9jdXMgPSBvcC5mb2N1cyAmJiBvcC5mb2N1cyA9PSBhY3RpdmVFbHQoKTtcbiAgICBpZiAob3AucHJlcGFyZWRTZWxlY3Rpb24pXG4gICAgICB7IGNtLmRpc3BsYXkuaW5wdXQuc2hvd1NlbGVjdGlvbihvcC5wcmVwYXJlZFNlbGVjdGlvbiwgdGFrZUZvY3VzKTsgfVxuICAgIGlmIChvcC51cGRhdGVkRGlzcGxheSB8fCBvcC5zdGFydEhlaWdodCAhPSBjbS5kb2MuaGVpZ2h0KVxuICAgICAgeyB1cGRhdGVTY3JvbGxiYXJzKGNtLCBvcC5iYXJNZWFzdXJlKTsgfVxuICAgIGlmIChvcC51cGRhdGVkRGlzcGxheSlcbiAgICAgIHsgc2V0RG9jdW1lbnRIZWlnaHQoY20sIG9wLmJhck1lYXN1cmUpOyB9XG5cbiAgICBpZiAob3Auc2VsZWN0aW9uQ2hhbmdlZCkgeyByZXN0YXJ0QmxpbmsoY20pOyB9XG5cbiAgICBpZiAoY20uc3RhdGUuZm9jdXNlZCAmJiBvcC51cGRhdGVJbnB1dClcbiAgICAgIHsgY20uZGlzcGxheS5pbnB1dC5yZXNldChvcC50eXBpbmcpOyB9XG4gICAgaWYgKHRha2VGb2N1cykgeyBlbnN1cmVGb2N1cyhvcC5jbSk7IH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGVuZE9wZXJhdGlvbl9maW5pc2gob3ApIHtcbiAgICB2YXIgY20gPSBvcC5jbSwgZGlzcGxheSA9IGNtLmRpc3BsYXksIGRvYyA9IGNtLmRvYztcblxuICAgIGlmIChvcC51cGRhdGVkRGlzcGxheSkgeyBwb3N0VXBkYXRlRGlzcGxheShjbSwgb3AudXBkYXRlKTsgfVxuXG4gICAgLy8gQWJvcnQgbW91c2Ugd2hlZWwgZGVsdGEgbWVhc3VyZW1lbnQsIHdoZW4gc2Nyb2xsaW5nIGV4cGxpY2l0bHlcbiAgICBpZiAoZGlzcGxheS53aGVlbFN0YXJ0WCAhPSBudWxsICYmIChvcC5zY3JvbGxUb3AgIT0gbnVsbCB8fCBvcC5zY3JvbGxMZWZ0ICE9IG51bGwgfHwgb3Auc2Nyb2xsVG9Qb3MpKVxuICAgICAgeyBkaXNwbGF5LndoZWVsU3RhcnRYID0gZGlzcGxheS53aGVlbFN0YXJ0WSA9IG51bGw7IH1cblxuICAgIC8vIFByb3BhZ2F0ZSB0aGUgc2Nyb2xsIHBvc2l0aW9uIHRvIHRoZSBhY3R1YWwgRE9NIHNjcm9sbGVyXG4gICAgaWYgKG9wLnNjcm9sbFRvcCAhPSBudWxsKSB7IHNldFNjcm9sbFRvcChjbSwgb3Auc2Nyb2xsVG9wLCBvcC5mb3JjZVNjcm9sbCk7IH1cblxuICAgIGlmIChvcC5zY3JvbGxMZWZ0ICE9IG51bGwpIHsgc2V0U2Nyb2xsTGVmdChjbSwgb3Auc2Nyb2xsTGVmdCwgdHJ1ZSwgdHJ1ZSk7IH1cbiAgICAvLyBJZiB3ZSBuZWVkIHRvIHNjcm9sbCBhIHNwZWNpZmljIHBvc2l0aW9uIGludG8gdmlldywgZG8gc28uXG4gICAgaWYgKG9wLnNjcm9sbFRvUG9zKSB7XG4gICAgICB2YXIgcmVjdCA9IHNjcm9sbFBvc0ludG9WaWV3KGNtLCBjbGlwUG9zKGRvYywgb3Auc2Nyb2xsVG9Qb3MuZnJvbSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsaXBQb3MoZG9jLCBvcC5zY3JvbGxUb1Bvcy50byksIG9wLnNjcm9sbFRvUG9zLm1hcmdpbik7XG4gICAgICBtYXliZVNjcm9sbFdpbmRvdyhjbSwgcmVjdCk7XG4gICAgfVxuXG4gICAgLy8gRmlyZSBldmVudHMgZm9yIG1hcmtlcnMgdGhhdCBhcmUgaGlkZGVuL3VuaWRkZW4gYnkgZWRpdGluZyBvclxuICAgIC8vIHVuZG9pbmdcbiAgICB2YXIgaGlkZGVuID0gb3AubWF5YmVIaWRkZW5NYXJrZXJzLCB1bmhpZGRlbiA9IG9wLm1heWJlVW5oaWRkZW5NYXJrZXJzO1xuICAgIGlmIChoaWRkZW4pIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBoaWRkZW4ubGVuZ3RoOyArK2kpXG4gICAgICB7IGlmICghaGlkZGVuW2ldLmxpbmVzLmxlbmd0aCkgeyBzaWduYWwoaGlkZGVuW2ldLCBcImhpZGVcIik7IH0gfSB9XG4gICAgaWYgKHVuaGlkZGVuKSB7IGZvciAodmFyIGkkMSA9IDA7IGkkMSA8IHVuaGlkZGVuLmxlbmd0aDsgKytpJDEpXG4gICAgICB7IGlmICh1bmhpZGRlbltpJDFdLmxpbmVzLmxlbmd0aCkgeyBzaWduYWwodW5oaWRkZW5baSQxXSwgXCJ1bmhpZGVcIik7IH0gfSB9XG5cbiAgICBpZiAoZGlzcGxheS53cmFwcGVyLm9mZnNldEhlaWdodClcbiAgICAgIHsgZG9jLnNjcm9sbFRvcCA9IGNtLmRpc3BsYXkuc2Nyb2xsZXIuc2Nyb2xsVG9wOyB9XG5cbiAgICAvLyBGaXJlIGNoYW5nZSBldmVudHMsIGFuZCBkZWxheWVkIGV2ZW50IGhhbmRsZXJzXG4gICAgaWYgKG9wLmNoYW5nZU9ianMpXG4gICAgICB7IHNpZ25hbChjbSwgXCJjaGFuZ2VzXCIsIGNtLCBvcC5jaGFuZ2VPYmpzKTsgfVxuICAgIGlmIChvcC51cGRhdGUpXG4gICAgICB7IG9wLnVwZGF0ZS5maW5pc2goKTsgfVxuICB9XG5cbiAgLy8gUnVuIHRoZSBnaXZlbiBmdW5jdGlvbiBpbiBhbiBvcGVyYXRpb25cbiAgZnVuY3Rpb24gcnVuSW5PcChjbSwgZikge1xuICAgIGlmIChjbS5jdXJPcCkgeyByZXR1cm4gZigpIH1cbiAgICBzdGFydE9wZXJhdGlvbihjbSk7XG4gICAgdHJ5IHsgcmV0dXJuIGYoKSB9XG4gICAgZmluYWxseSB7IGVuZE9wZXJhdGlvbihjbSk7IH1cbiAgfVxuICAvLyBXcmFwcyBhIGZ1bmN0aW9uIGluIGFuIG9wZXJhdGlvbi4gUmV0dXJucyB0aGUgd3JhcHBlZCBmdW5jdGlvbi5cbiAgZnVuY3Rpb24gb3BlcmF0aW9uKGNtLCBmKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKGNtLmN1ck9wKSB7IHJldHVybiBmLmFwcGx5KGNtLCBhcmd1bWVudHMpIH1cbiAgICAgIHN0YXJ0T3BlcmF0aW9uKGNtKTtcbiAgICAgIHRyeSB7IHJldHVybiBmLmFwcGx5KGNtLCBhcmd1bWVudHMpIH1cbiAgICAgIGZpbmFsbHkgeyBlbmRPcGVyYXRpb24oY20pOyB9XG4gICAgfVxuICB9XG4gIC8vIFVzZWQgdG8gYWRkIG1ldGhvZHMgdG8gZWRpdG9yIGFuZCBkb2MgaW5zdGFuY2VzLCB3cmFwcGluZyB0aGVtIGluXG4gIC8vIG9wZXJhdGlvbnMuXG4gIGZ1bmN0aW9uIG1ldGhvZE9wKGYpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICBpZiAodGhpcy5jdXJPcCkgeyByZXR1cm4gZi5hcHBseSh0aGlzLCBhcmd1bWVudHMpIH1cbiAgICAgIHN0YXJ0T3BlcmF0aW9uKHRoaXMpO1xuICAgICAgdHJ5IHsgcmV0dXJuIGYuYXBwbHkodGhpcywgYXJndW1lbnRzKSB9XG4gICAgICBmaW5hbGx5IHsgZW5kT3BlcmF0aW9uKHRoaXMpOyB9XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGRvY01ldGhvZE9wKGYpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgY20gPSB0aGlzLmNtO1xuICAgICAgaWYgKCFjbSB8fCBjbS5jdXJPcCkgeyByZXR1cm4gZi5hcHBseSh0aGlzLCBhcmd1bWVudHMpIH1cbiAgICAgIHN0YXJ0T3BlcmF0aW9uKGNtKTtcbiAgICAgIHRyeSB7IHJldHVybiBmLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfVxuICAgICAgZmluYWxseSB7IGVuZE9wZXJhdGlvbihjbSk7IH1cbiAgICB9XG4gIH1cblxuICAvLyBISUdITElHSFQgV09SS0VSXG5cbiAgZnVuY3Rpb24gc3RhcnRXb3JrZXIoY20sIHRpbWUpIHtcbiAgICBpZiAoY20uZG9jLmhpZ2hsaWdodEZyb250aWVyIDwgY20uZGlzcGxheS52aWV3VG8pXG4gICAgICB7IGNtLnN0YXRlLmhpZ2hsaWdodC5zZXQodGltZSwgYmluZChoaWdobGlnaHRXb3JrZXIsIGNtKSk7IH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGhpZ2hsaWdodFdvcmtlcihjbSkge1xuICAgIHZhciBkb2MgPSBjbS5kb2M7XG4gICAgaWYgKGRvYy5oaWdobGlnaHRGcm9udGllciA+PSBjbS5kaXNwbGF5LnZpZXdUbykgeyByZXR1cm4gfVxuICAgIHZhciBlbmQgPSArbmV3IERhdGUgKyBjbS5vcHRpb25zLndvcmtUaW1lO1xuICAgIHZhciBjb250ZXh0ID0gZ2V0Q29udGV4dEJlZm9yZShjbSwgZG9jLmhpZ2hsaWdodEZyb250aWVyKTtcbiAgICB2YXIgY2hhbmdlZExpbmVzID0gW107XG5cbiAgICBkb2MuaXRlcihjb250ZXh0LmxpbmUsIE1hdGgubWluKGRvYy5maXJzdCArIGRvYy5zaXplLCBjbS5kaXNwbGF5LnZpZXdUbyArIDUwMCksIGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICBpZiAoY29udGV4dC5saW5lID49IGNtLmRpc3BsYXkudmlld0Zyb20pIHsgLy8gVmlzaWJsZVxuICAgICAgICB2YXIgb2xkU3R5bGVzID0gbGluZS5zdHlsZXM7XG4gICAgICAgIHZhciByZXNldFN0YXRlID0gbGluZS50ZXh0Lmxlbmd0aCA+IGNtLm9wdGlvbnMubWF4SGlnaGxpZ2h0TGVuZ3RoID8gY29weVN0YXRlKGRvYy5tb2RlLCBjb250ZXh0LnN0YXRlKSA6IG51bGw7XG4gICAgICAgIHZhciBoaWdobGlnaHRlZCA9IGhpZ2hsaWdodExpbmUoY20sIGxpbmUsIGNvbnRleHQsIHRydWUpO1xuICAgICAgICBpZiAocmVzZXRTdGF0ZSkgeyBjb250ZXh0LnN0YXRlID0gcmVzZXRTdGF0ZTsgfVxuICAgICAgICBsaW5lLnN0eWxlcyA9IGhpZ2hsaWdodGVkLnN0eWxlcztcbiAgICAgICAgdmFyIG9sZENscyA9IGxpbmUuc3R5bGVDbGFzc2VzLCBuZXdDbHMgPSBoaWdobGlnaHRlZC5jbGFzc2VzO1xuICAgICAgICBpZiAobmV3Q2xzKSB7IGxpbmUuc3R5bGVDbGFzc2VzID0gbmV3Q2xzOyB9XG4gICAgICAgIGVsc2UgaWYgKG9sZENscykgeyBsaW5lLnN0eWxlQ2xhc3NlcyA9IG51bGw7IH1cbiAgICAgICAgdmFyIGlzY2hhbmdlID0gIW9sZFN0eWxlcyB8fCBvbGRTdHlsZXMubGVuZ3RoICE9IGxpbmUuc3R5bGVzLmxlbmd0aCB8fFxuICAgICAgICAgIG9sZENscyAhPSBuZXdDbHMgJiYgKCFvbGRDbHMgfHwgIW5ld0NscyB8fCBvbGRDbHMuYmdDbGFzcyAhPSBuZXdDbHMuYmdDbGFzcyB8fCBvbGRDbHMudGV4dENsYXNzICE9IG5ld0Nscy50ZXh0Q2xhc3MpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgIWlzY2hhbmdlICYmIGkgPCBvbGRTdHlsZXMubGVuZ3RoOyArK2kpIHsgaXNjaGFuZ2UgPSBvbGRTdHlsZXNbaV0gIT0gbGluZS5zdHlsZXNbaV07IH1cbiAgICAgICAgaWYgKGlzY2hhbmdlKSB7IGNoYW5nZWRMaW5lcy5wdXNoKGNvbnRleHQubGluZSk7IH1cbiAgICAgICAgbGluZS5zdGF0ZUFmdGVyID0gY29udGV4dC5zYXZlKCk7XG4gICAgICAgIGNvbnRleHQubmV4dExpbmUoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChsaW5lLnRleHQubGVuZ3RoIDw9IGNtLm9wdGlvbnMubWF4SGlnaGxpZ2h0TGVuZ3RoKVxuICAgICAgICAgIHsgcHJvY2Vzc0xpbmUoY20sIGxpbmUudGV4dCwgY29udGV4dCk7IH1cbiAgICAgICAgbGluZS5zdGF0ZUFmdGVyID0gY29udGV4dC5saW5lICUgNSA9PSAwID8gY29udGV4dC5zYXZlKCkgOiBudWxsO1xuICAgICAgICBjb250ZXh0Lm5leHRMaW5lKCk7XG4gICAgICB9XG4gICAgICBpZiAoK25ldyBEYXRlID4gZW5kKSB7XG4gICAgICAgIHN0YXJ0V29ya2VyKGNtLCBjbS5vcHRpb25zLndvcmtEZWxheSk7XG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgICB9XG4gICAgfSk7XG4gICAgZG9jLmhpZ2hsaWdodEZyb250aWVyID0gY29udGV4dC5saW5lO1xuICAgIGRvYy5tb2RlRnJvbnRpZXIgPSBNYXRoLm1heChkb2MubW9kZUZyb250aWVyLCBjb250ZXh0LmxpbmUpO1xuICAgIGlmIChjaGFuZ2VkTGluZXMubGVuZ3RoKSB7IHJ1bkluT3AoY20sIGZ1bmN0aW9uICgpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hhbmdlZExpbmVzLmxlbmd0aDsgaSsrKVxuICAgICAgICB7IHJlZ0xpbmVDaGFuZ2UoY20sIGNoYW5nZWRMaW5lc1tpXSwgXCJ0ZXh0XCIpOyB9XG4gICAgfSk7IH1cbiAgfVxuXG4gIC8vIERJU1BMQVkgRFJBV0lOR1xuXG4gIHZhciBEaXNwbGF5VXBkYXRlID0gZnVuY3Rpb24oY20sIHZpZXdwb3J0LCBmb3JjZSkge1xuICAgIHZhciBkaXNwbGF5ID0gY20uZGlzcGxheTtcblxuICAgIHRoaXMudmlld3BvcnQgPSB2aWV3cG9ydDtcbiAgICAvLyBTdG9yZSBzb21lIHZhbHVlcyB0aGF0IHdlJ2xsIG5lZWQgbGF0ZXIgKGJ1dCBkb24ndCB3YW50IHRvIGZvcmNlIGEgcmVsYXlvdXQgZm9yKVxuICAgIHRoaXMudmlzaWJsZSA9IHZpc2libGVMaW5lcyhkaXNwbGF5LCBjbS5kb2MsIHZpZXdwb3J0KTtcbiAgICB0aGlzLmVkaXRvcklzSGlkZGVuID0gIWRpc3BsYXkud3JhcHBlci5vZmZzZXRXaWR0aDtcbiAgICB0aGlzLndyYXBwZXJIZWlnaHQgPSBkaXNwbGF5LndyYXBwZXIuY2xpZW50SGVpZ2h0O1xuICAgIHRoaXMud3JhcHBlcldpZHRoID0gZGlzcGxheS53cmFwcGVyLmNsaWVudFdpZHRoO1xuICAgIHRoaXMub2xkRGlzcGxheVdpZHRoID0gZGlzcGxheVdpZHRoKGNtKTtcbiAgICB0aGlzLmZvcmNlID0gZm9yY2U7XG4gICAgdGhpcy5kaW1zID0gZ2V0RGltZW5zaW9ucyhjbSk7XG4gICAgdGhpcy5ldmVudHMgPSBbXTtcbiAgfTtcblxuICBEaXNwbGF5VXBkYXRlLnByb3RvdHlwZS5zaWduYWwgPSBmdW5jdGlvbiAoZW1pdHRlciwgdHlwZSkge1xuICAgIGlmIChoYXNIYW5kbGVyKGVtaXR0ZXIsIHR5cGUpKVxuICAgICAgeyB0aGlzLmV2ZW50cy5wdXNoKGFyZ3VtZW50cyk7IH1cbiAgfTtcbiAgRGlzcGxheVVwZGF0ZS5wcm90b3R5cGUuZmluaXNoID0gZnVuY3Rpb24gKCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5ldmVudHMubGVuZ3RoOyBpKyspXG4gICAgICB7IHNpZ25hbC5hcHBseShudWxsLCB0aGlzLmV2ZW50c1tpXSk7IH1cbiAgfTtcblxuICBmdW5jdGlvbiBtYXliZUNsaXBTY3JvbGxiYXJzKGNtKSB7XG4gICAgdmFyIGRpc3BsYXkgPSBjbS5kaXNwbGF5O1xuICAgIGlmICghZGlzcGxheS5zY3JvbGxiYXJzQ2xpcHBlZCAmJiBkaXNwbGF5LnNjcm9sbGVyLm9mZnNldFdpZHRoKSB7XG4gICAgICBkaXNwbGF5Lm5hdGl2ZUJhcldpZHRoID0gZGlzcGxheS5zY3JvbGxlci5vZmZzZXRXaWR0aCAtIGRpc3BsYXkuc2Nyb2xsZXIuY2xpZW50V2lkdGg7XG4gICAgICBkaXNwbGF5LmhlaWdodEZvcmNlci5zdHlsZS5oZWlnaHQgPSBzY3JvbGxHYXAoY20pICsgXCJweFwiO1xuICAgICAgZGlzcGxheS5zaXplci5zdHlsZS5tYXJnaW5Cb3R0b20gPSAtZGlzcGxheS5uYXRpdmVCYXJXaWR0aCArIFwicHhcIjtcbiAgICAgIGRpc3BsYXkuc2l6ZXIuc3R5bGUuYm9yZGVyUmlnaHRXaWR0aCA9IHNjcm9sbEdhcChjbSkgKyBcInB4XCI7XG4gICAgICBkaXNwbGF5LnNjcm9sbGJhcnNDbGlwcGVkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBzZWxlY3Rpb25TbmFwc2hvdChjbSkge1xuICAgIGlmIChjbS5oYXNGb2N1cygpKSB7IHJldHVybiBudWxsIH1cbiAgICB2YXIgYWN0aXZlID0gYWN0aXZlRWx0KCk7XG4gICAgaWYgKCFhY3RpdmUgfHwgIWNvbnRhaW5zKGNtLmRpc3BsYXkubGluZURpdiwgYWN0aXZlKSkgeyByZXR1cm4gbnVsbCB9XG4gICAgdmFyIHJlc3VsdCA9IHthY3RpdmVFbHQ6IGFjdGl2ZX07XG4gICAgaWYgKHdpbmRvdy5nZXRTZWxlY3Rpb24pIHtcbiAgICAgIHZhciBzZWwgPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XG4gICAgICBpZiAoc2VsLmFuY2hvck5vZGUgJiYgc2VsLmV4dGVuZCAmJiBjb250YWlucyhjbS5kaXNwbGF5LmxpbmVEaXYsIHNlbC5hbmNob3JOb2RlKSkge1xuICAgICAgICByZXN1bHQuYW5jaG9yTm9kZSA9IHNlbC5hbmNob3JOb2RlO1xuICAgICAgICByZXN1bHQuYW5jaG9yT2Zmc2V0ID0gc2VsLmFuY2hvck9mZnNldDtcbiAgICAgICAgcmVzdWx0LmZvY3VzTm9kZSA9IHNlbC5mb2N1c05vZGU7XG4gICAgICAgIHJlc3VsdC5mb2N1c09mZnNldCA9IHNlbC5mb2N1c09mZnNldDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG5cbiAgZnVuY3Rpb24gcmVzdG9yZVNlbGVjdGlvbihzbmFwc2hvdCkge1xuICAgIGlmICghc25hcHNob3QgfHwgIXNuYXBzaG90LmFjdGl2ZUVsdCB8fCBzbmFwc2hvdC5hY3RpdmVFbHQgPT0gYWN0aXZlRWx0KCkpIHsgcmV0dXJuIH1cbiAgICBzbmFwc2hvdC5hY3RpdmVFbHQuZm9jdXMoKTtcbiAgICBpZiAoIS9eKElOUFVUfFRFWFRBUkVBKSQvLnRlc3Qoc25hcHNob3QuYWN0aXZlRWx0Lm5vZGVOYW1lKSAmJlxuICAgICAgICBzbmFwc2hvdC5hbmNob3JOb2RlICYmIGNvbnRhaW5zKGRvY3VtZW50LmJvZHksIHNuYXBzaG90LmFuY2hvck5vZGUpICYmIGNvbnRhaW5zKGRvY3VtZW50LmJvZHksIHNuYXBzaG90LmZvY3VzTm9kZSkpIHtcbiAgICAgIHZhciBzZWwgPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCksIHJhbmdlID0gZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTtcbiAgICAgIHJhbmdlLnNldEVuZChzbmFwc2hvdC5hbmNob3JOb2RlLCBzbmFwc2hvdC5hbmNob3JPZmZzZXQpO1xuICAgICAgcmFuZ2UuY29sbGFwc2UoZmFsc2UpO1xuICAgICAgc2VsLnJlbW92ZUFsbFJhbmdlcygpO1xuICAgICAgc2VsLmFkZFJhbmdlKHJhbmdlKTtcbiAgICAgIHNlbC5leHRlbmQoc25hcHNob3QuZm9jdXNOb2RlLCBzbmFwc2hvdC5mb2N1c09mZnNldCk7XG4gICAgfVxuICB9XG5cbiAgLy8gRG9lcyB0aGUgYWN0dWFsIHVwZGF0aW5nIG9mIHRoZSBsaW5lIGRpc3BsYXkuIEJhaWxzIG91dFxuICAvLyAocmV0dXJuaW5nIGZhbHNlKSB3aGVuIHRoZXJlIGlzIG5vdGhpbmcgdG8gYmUgZG9uZSBhbmQgZm9yY2VkIGlzXG4gIC8vIGZhbHNlLlxuICBmdW5jdGlvbiB1cGRhdGVEaXNwbGF5SWZOZWVkZWQoY20sIHVwZGF0ZSkge1xuICAgIHZhciBkaXNwbGF5ID0gY20uZGlzcGxheSwgZG9jID0gY20uZG9jO1xuXG4gICAgaWYgKHVwZGF0ZS5lZGl0b3JJc0hpZGRlbikge1xuICAgICAgcmVzZXRWaWV3KGNtKTtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cblxuICAgIC8vIEJhaWwgb3V0IGlmIHRoZSB2aXNpYmxlIGFyZWEgaXMgYWxyZWFkeSByZW5kZXJlZCBhbmQgbm90aGluZyBjaGFuZ2VkLlxuICAgIGlmICghdXBkYXRlLmZvcmNlICYmXG4gICAgICAgIHVwZGF0ZS52aXNpYmxlLmZyb20gPj0gZGlzcGxheS52aWV3RnJvbSAmJiB1cGRhdGUudmlzaWJsZS50byA8PSBkaXNwbGF5LnZpZXdUbyAmJlxuICAgICAgICAoZGlzcGxheS51cGRhdGVMaW5lTnVtYmVycyA9PSBudWxsIHx8IGRpc3BsYXkudXBkYXRlTGluZU51bWJlcnMgPj0gZGlzcGxheS52aWV3VG8pICYmXG4gICAgICAgIGRpc3BsYXkucmVuZGVyZWRWaWV3ID09IGRpc3BsYXkudmlldyAmJiBjb3VudERpcnR5VmlldyhjbSkgPT0gMClcbiAgICAgIHsgcmV0dXJuIGZhbHNlIH1cblxuICAgIGlmIChtYXliZVVwZGF0ZUxpbmVOdW1iZXJXaWR0aChjbSkpIHtcbiAgICAgIHJlc2V0VmlldyhjbSk7XG4gICAgICB1cGRhdGUuZGltcyA9IGdldERpbWVuc2lvbnMoY20pO1xuICAgIH1cblxuICAgIC8vIENvbXB1dGUgYSBzdWl0YWJsZSBuZXcgdmlld3BvcnQgKGZyb20gJiB0bylcbiAgICB2YXIgZW5kID0gZG9jLmZpcnN0ICsgZG9jLnNpemU7XG4gICAgdmFyIGZyb20gPSBNYXRoLm1heCh1cGRhdGUudmlzaWJsZS5mcm9tIC0gY20ub3B0aW9ucy52aWV3cG9ydE1hcmdpbiwgZG9jLmZpcnN0KTtcbiAgICB2YXIgdG8gPSBNYXRoLm1pbihlbmQsIHVwZGF0ZS52aXNpYmxlLnRvICsgY20ub3B0aW9ucy52aWV3cG9ydE1hcmdpbik7XG4gICAgaWYgKGRpc3BsYXkudmlld0Zyb20gPCBmcm9tICYmIGZyb20gLSBkaXNwbGF5LnZpZXdGcm9tIDwgMjApIHsgZnJvbSA9IE1hdGgubWF4KGRvYy5maXJzdCwgZGlzcGxheS52aWV3RnJvbSk7IH1cbiAgICBpZiAoZGlzcGxheS52aWV3VG8gPiB0byAmJiBkaXNwbGF5LnZpZXdUbyAtIHRvIDwgMjApIHsgdG8gPSBNYXRoLm1pbihlbmQsIGRpc3BsYXkudmlld1RvKTsgfVxuICAgIGlmIChzYXdDb2xsYXBzZWRTcGFucykge1xuICAgICAgZnJvbSA9IHZpc3VhbExpbmVObyhjbS5kb2MsIGZyb20pO1xuICAgICAgdG8gPSB2aXN1YWxMaW5lRW5kTm8oY20uZG9jLCB0byk7XG4gICAgfVxuXG4gICAgdmFyIGRpZmZlcmVudCA9IGZyb20gIT0gZGlzcGxheS52aWV3RnJvbSB8fCB0byAhPSBkaXNwbGF5LnZpZXdUbyB8fFxuICAgICAgZGlzcGxheS5sYXN0V3JhcEhlaWdodCAhPSB1cGRhdGUud3JhcHBlckhlaWdodCB8fCBkaXNwbGF5Lmxhc3RXcmFwV2lkdGggIT0gdXBkYXRlLndyYXBwZXJXaWR0aDtcbiAgICBhZGp1c3RWaWV3KGNtLCBmcm9tLCB0byk7XG5cbiAgICBkaXNwbGF5LnZpZXdPZmZzZXQgPSBoZWlnaHRBdExpbmUoZ2V0TGluZShjbS5kb2MsIGRpc3BsYXkudmlld0Zyb20pKTtcbiAgICAvLyBQb3NpdGlvbiB0aGUgbW92ZXIgZGl2IHRvIGFsaWduIHdpdGggdGhlIGN1cnJlbnQgc2Nyb2xsIHBvc2l0aW9uXG4gICAgY20uZGlzcGxheS5tb3Zlci5zdHlsZS50b3AgPSBkaXNwbGF5LnZpZXdPZmZzZXQgKyBcInB4XCI7XG5cbiAgICB2YXIgdG9VcGRhdGUgPSBjb3VudERpcnR5VmlldyhjbSk7XG4gICAgaWYgKCFkaWZmZXJlbnQgJiYgdG9VcGRhdGUgPT0gMCAmJiAhdXBkYXRlLmZvcmNlICYmIGRpc3BsYXkucmVuZGVyZWRWaWV3ID09IGRpc3BsYXkudmlldyAmJlxuICAgICAgICAoZGlzcGxheS51cGRhdGVMaW5lTnVtYmVycyA9PSBudWxsIHx8IGRpc3BsYXkudXBkYXRlTGluZU51bWJlcnMgPj0gZGlzcGxheS52aWV3VG8pKVxuICAgICAgeyByZXR1cm4gZmFsc2UgfVxuXG4gICAgLy8gRm9yIGJpZyBjaGFuZ2VzLCB3ZSBoaWRlIHRoZSBlbmNsb3NpbmcgZWxlbWVudCBkdXJpbmcgdGhlXG4gICAgLy8gdXBkYXRlLCBzaW5jZSB0aGF0IHNwZWVkcyB1cCB0aGUgb3BlcmF0aW9ucyBvbiBtb3N0IGJyb3dzZXJzLlxuICAgIHZhciBzZWxTbmFwc2hvdCA9IHNlbGVjdGlvblNuYXBzaG90KGNtKTtcbiAgICBpZiAodG9VcGRhdGUgPiA0KSB7IGRpc3BsYXkubGluZURpdi5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7IH1cbiAgICBwYXRjaERpc3BsYXkoY20sIGRpc3BsYXkudXBkYXRlTGluZU51bWJlcnMsIHVwZGF0ZS5kaW1zKTtcbiAgICBpZiAodG9VcGRhdGUgPiA0KSB7IGRpc3BsYXkubGluZURpdi5zdHlsZS5kaXNwbGF5ID0gXCJcIjsgfVxuICAgIGRpc3BsYXkucmVuZGVyZWRWaWV3ID0gZGlzcGxheS52aWV3O1xuICAgIC8vIFRoZXJlIG1pZ2h0IGhhdmUgYmVlbiBhIHdpZGdldCB3aXRoIGEgZm9jdXNlZCBlbGVtZW50IHRoYXQgZ290XG4gICAgLy8gaGlkZGVuIG9yIHVwZGF0ZWQsIGlmIHNvIHJlLWZvY3VzIGl0LlxuICAgIHJlc3RvcmVTZWxlY3Rpb24oc2VsU25hcHNob3QpO1xuXG4gICAgLy8gUHJldmVudCBzZWxlY3Rpb24gYW5kIGN1cnNvcnMgZnJvbSBpbnRlcmZlcmluZyB3aXRoIHRoZSBzY3JvbGxcbiAgICAvLyB3aWR0aCBhbmQgaGVpZ2h0LlxuICAgIHJlbW92ZUNoaWxkcmVuKGRpc3BsYXkuY3Vyc29yRGl2KTtcbiAgICByZW1vdmVDaGlsZHJlbihkaXNwbGF5LnNlbGVjdGlvbkRpdik7XG4gICAgZGlzcGxheS5ndXR0ZXJzLnN0eWxlLmhlaWdodCA9IGRpc3BsYXkuc2l6ZXIuc3R5bGUubWluSGVpZ2h0ID0gMDtcblxuICAgIGlmIChkaWZmZXJlbnQpIHtcbiAgICAgIGRpc3BsYXkubGFzdFdyYXBIZWlnaHQgPSB1cGRhdGUud3JhcHBlckhlaWdodDtcbiAgICAgIGRpc3BsYXkubGFzdFdyYXBXaWR0aCA9IHVwZGF0ZS53cmFwcGVyV2lkdGg7XG4gICAgICBzdGFydFdvcmtlcihjbSwgNDAwKTtcbiAgICB9XG5cbiAgICBkaXNwbGF5LnVwZGF0ZUxpbmVOdW1iZXJzID0gbnVsbDtcblxuICAgIHJldHVybiB0cnVlXG4gIH1cblxuICBmdW5jdGlvbiBwb3N0VXBkYXRlRGlzcGxheShjbSwgdXBkYXRlKSB7XG4gICAgdmFyIHZpZXdwb3J0ID0gdXBkYXRlLnZpZXdwb3J0O1xuXG4gICAgZm9yICh2YXIgZmlyc3QgPSB0cnVlOzsgZmlyc3QgPSBmYWxzZSkge1xuICAgICAgaWYgKCFmaXJzdCB8fCAhY20ub3B0aW9ucy5saW5lV3JhcHBpbmcgfHwgdXBkYXRlLm9sZERpc3BsYXlXaWR0aCA9PSBkaXNwbGF5V2lkdGgoY20pKSB7XG4gICAgICAgIC8vIENsaXAgZm9yY2VkIHZpZXdwb3J0IHRvIGFjdHVhbCBzY3JvbGxhYmxlIGFyZWEuXG4gICAgICAgIGlmICh2aWV3cG9ydCAmJiB2aWV3cG9ydC50b3AgIT0gbnVsbClcbiAgICAgICAgICB7IHZpZXdwb3J0ID0ge3RvcDogTWF0aC5taW4oY20uZG9jLmhlaWdodCArIHBhZGRpbmdWZXJ0KGNtLmRpc3BsYXkpIC0gZGlzcGxheUhlaWdodChjbSksIHZpZXdwb3J0LnRvcCl9OyB9XG4gICAgICAgIC8vIFVwZGF0ZWQgbGluZSBoZWlnaHRzIG1pZ2h0IHJlc3VsdCBpbiB0aGUgZHJhd24gYXJlYSBub3RcbiAgICAgICAgLy8gYWN0dWFsbHkgY292ZXJpbmcgdGhlIHZpZXdwb3J0LiBLZWVwIGxvb3BpbmcgdW50aWwgaXQgZG9lcy5cbiAgICAgICAgdXBkYXRlLnZpc2libGUgPSB2aXNpYmxlTGluZXMoY20uZGlzcGxheSwgY20uZG9jLCB2aWV3cG9ydCk7XG4gICAgICAgIGlmICh1cGRhdGUudmlzaWJsZS5mcm9tID49IGNtLmRpc3BsYXkudmlld0Zyb20gJiYgdXBkYXRlLnZpc2libGUudG8gPD0gY20uZGlzcGxheS52aWV3VG8pXG4gICAgICAgICAgeyBicmVhayB9XG4gICAgICB9IGVsc2UgaWYgKGZpcnN0KSB7XG4gICAgICAgIHVwZGF0ZS52aXNpYmxlID0gdmlzaWJsZUxpbmVzKGNtLmRpc3BsYXksIGNtLmRvYywgdmlld3BvcnQpO1xuICAgICAgfVxuICAgICAgaWYgKCF1cGRhdGVEaXNwbGF5SWZOZWVkZWQoY20sIHVwZGF0ZSkpIHsgYnJlYWsgfVxuICAgICAgdXBkYXRlSGVpZ2h0c0luVmlld3BvcnQoY20pO1xuICAgICAgdmFyIGJhck1lYXN1cmUgPSBtZWFzdXJlRm9yU2Nyb2xsYmFycyhjbSk7XG4gICAgICB1cGRhdGVTZWxlY3Rpb24oY20pO1xuICAgICAgdXBkYXRlU2Nyb2xsYmFycyhjbSwgYmFyTWVhc3VyZSk7XG4gICAgICBzZXREb2N1bWVudEhlaWdodChjbSwgYmFyTWVhc3VyZSk7XG4gICAgICB1cGRhdGUuZm9yY2UgPSBmYWxzZTtcbiAgICB9XG5cbiAgICB1cGRhdGUuc2lnbmFsKGNtLCBcInVwZGF0ZVwiLCBjbSk7XG4gICAgaWYgKGNtLmRpc3BsYXkudmlld0Zyb20gIT0gY20uZGlzcGxheS5yZXBvcnRlZFZpZXdGcm9tIHx8IGNtLmRpc3BsYXkudmlld1RvICE9IGNtLmRpc3BsYXkucmVwb3J0ZWRWaWV3VG8pIHtcbiAgICAgIHVwZGF0ZS5zaWduYWwoY20sIFwidmlld3BvcnRDaGFuZ2VcIiwgY20sIGNtLmRpc3BsYXkudmlld0Zyb20sIGNtLmRpc3BsYXkudmlld1RvKTtcbiAgICAgIGNtLmRpc3BsYXkucmVwb3J0ZWRWaWV3RnJvbSA9IGNtLmRpc3BsYXkudmlld0Zyb207IGNtLmRpc3BsYXkucmVwb3J0ZWRWaWV3VG8gPSBjbS5kaXNwbGF5LnZpZXdUbztcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGVEaXNwbGF5U2ltcGxlKGNtLCB2aWV3cG9ydCkge1xuICAgIHZhciB1cGRhdGUgPSBuZXcgRGlzcGxheVVwZGF0ZShjbSwgdmlld3BvcnQpO1xuICAgIGlmICh1cGRhdGVEaXNwbGF5SWZOZWVkZWQoY20sIHVwZGF0ZSkpIHtcbiAgICAgIHVwZGF0ZUhlaWdodHNJblZpZXdwb3J0KGNtKTtcbiAgICAgIHBvc3RVcGRhdGVEaXNwbGF5KGNtLCB1cGRhdGUpO1xuICAgICAgdmFyIGJhck1lYXN1cmUgPSBtZWFzdXJlRm9yU2Nyb2xsYmFycyhjbSk7XG4gICAgICB1cGRhdGVTZWxlY3Rpb24oY20pO1xuICAgICAgdXBkYXRlU2Nyb2xsYmFycyhjbSwgYmFyTWVhc3VyZSk7XG4gICAgICBzZXREb2N1bWVudEhlaWdodChjbSwgYmFyTWVhc3VyZSk7XG4gICAgICB1cGRhdGUuZmluaXNoKCk7XG4gICAgfVxuICB9XG5cbiAgLy8gU3luYyB0aGUgYWN0dWFsIGRpc3BsYXkgRE9NIHN0cnVjdHVyZSB3aXRoIGRpc3BsYXkudmlldywgcmVtb3ZpbmdcbiAgLy8gbm9kZXMgZm9yIGxpbmVzIHRoYXQgYXJlIG5vIGxvbmdlciBpbiB2aWV3LCBhbmQgY3JlYXRpbmcgdGhlIG9uZXNcbiAgLy8gdGhhdCBhcmUgbm90IHRoZXJlIHlldCwgYW5kIHVwZGF0aW5nIHRoZSBvbmVzIHRoYXQgYXJlIG91dCBvZlxuICAvLyBkYXRlLlxuICBmdW5jdGlvbiBwYXRjaERpc3BsYXkoY20sIHVwZGF0ZU51bWJlcnNGcm9tLCBkaW1zKSB7XG4gICAgdmFyIGRpc3BsYXkgPSBjbS5kaXNwbGF5LCBsaW5lTnVtYmVycyA9IGNtLm9wdGlvbnMubGluZU51bWJlcnM7XG4gICAgdmFyIGNvbnRhaW5lciA9IGRpc3BsYXkubGluZURpdiwgY3VyID0gY29udGFpbmVyLmZpcnN0Q2hpbGQ7XG5cbiAgICBmdW5jdGlvbiBybShub2RlKSB7XG4gICAgICB2YXIgbmV4dCA9IG5vZGUubmV4dFNpYmxpbmc7XG4gICAgICAvLyBXb3JrcyBhcm91bmQgYSB0aHJvdy1zY3JvbGwgYnVnIGluIE9TIFggV2Via2l0XG4gICAgICBpZiAod2Via2l0ICYmIG1hYyAmJiBjbS5kaXNwbGF5LmN1cnJlbnRXaGVlbFRhcmdldCA9PSBub2RlKVxuICAgICAgICB7IG5vZGUuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiOyB9XG4gICAgICBlbHNlXG4gICAgICAgIHsgbm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG5vZGUpOyB9XG4gICAgICByZXR1cm4gbmV4dFxuICAgIH1cblxuICAgIHZhciB2aWV3ID0gZGlzcGxheS52aWV3LCBsaW5lTiA9IGRpc3BsYXkudmlld0Zyb207XG4gICAgLy8gTG9vcCBvdmVyIHRoZSBlbGVtZW50cyBpbiB0aGUgdmlldywgc3luY2luZyBjdXIgKHRoZSBET00gbm9kZXNcbiAgICAvLyBpbiBkaXNwbGF5LmxpbmVEaXYpIHdpdGggdGhlIHZpZXcgYXMgd2UgZ28uXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2aWV3Lmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgbGluZVZpZXcgPSB2aWV3W2ldO1xuICAgICAgaWYgKGxpbmVWaWV3LmhpZGRlbikgOyBlbHNlIGlmICghbGluZVZpZXcubm9kZSB8fCBsaW5lVmlldy5ub2RlLnBhcmVudE5vZGUgIT0gY29udGFpbmVyKSB7IC8vIE5vdCBkcmF3biB5ZXRcbiAgICAgICAgdmFyIG5vZGUgPSBidWlsZExpbmVFbGVtZW50KGNtLCBsaW5lVmlldywgbGluZU4sIGRpbXMpO1xuICAgICAgICBjb250YWluZXIuaW5zZXJ0QmVmb3JlKG5vZGUsIGN1cik7XG4gICAgICB9IGVsc2UgeyAvLyBBbHJlYWR5IGRyYXduXG4gICAgICAgIHdoaWxlIChjdXIgIT0gbGluZVZpZXcubm9kZSkgeyBjdXIgPSBybShjdXIpOyB9XG4gICAgICAgIHZhciB1cGRhdGVOdW1iZXIgPSBsaW5lTnVtYmVycyAmJiB1cGRhdGVOdW1iZXJzRnJvbSAhPSBudWxsICYmXG4gICAgICAgICAgdXBkYXRlTnVtYmVyc0Zyb20gPD0gbGluZU4gJiYgbGluZVZpZXcubGluZU51bWJlcjtcbiAgICAgICAgaWYgKGxpbmVWaWV3LmNoYW5nZXMpIHtcbiAgICAgICAgICBpZiAoaW5kZXhPZihsaW5lVmlldy5jaGFuZ2VzLCBcImd1dHRlclwiKSA+IC0xKSB7IHVwZGF0ZU51bWJlciA9IGZhbHNlOyB9XG4gICAgICAgICAgdXBkYXRlTGluZUZvckNoYW5nZXMoY20sIGxpbmVWaWV3LCBsaW5lTiwgZGltcyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHVwZGF0ZU51bWJlcikge1xuICAgICAgICAgIHJlbW92ZUNoaWxkcmVuKGxpbmVWaWV3LmxpbmVOdW1iZXIpO1xuICAgICAgICAgIGxpbmVWaWV3LmxpbmVOdW1iZXIuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUobGluZU51bWJlckZvcihjbS5vcHRpb25zLCBsaW5lTikpKTtcbiAgICAgICAgfVxuICAgICAgICBjdXIgPSBsaW5lVmlldy5ub2RlLm5leHRTaWJsaW5nO1xuICAgICAgfVxuICAgICAgbGluZU4gKz0gbGluZVZpZXcuc2l6ZTtcbiAgICB9XG4gICAgd2hpbGUgKGN1cikgeyBjdXIgPSBybShjdXIpOyB9XG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGVHdXR0ZXJTcGFjZShkaXNwbGF5KSB7XG4gICAgdmFyIHdpZHRoID0gZGlzcGxheS5ndXR0ZXJzLm9mZnNldFdpZHRoO1xuICAgIGRpc3BsYXkuc2l6ZXIuc3R5bGUubWFyZ2luTGVmdCA9IHdpZHRoICsgXCJweFwiO1xuICAgIC8vIFNlbmQgYW4gZXZlbnQgdG8gY29uc3VtZXJzIHJlc3BvbmRpbmcgdG8gY2hhbmdlcyBpbiBndXR0ZXIgd2lkdGguXG4gICAgc2lnbmFsTGF0ZXIoZGlzcGxheSwgXCJndXR0ZXJDaGFuZ2VkXCIsIGRpc3BsYXkpO1xuICB9XG5cbiAgZnVuY3Rpb24gc2V0RG9jdW1lbnRIZWlnaHQoY20sIG1lYXN1cmUpIHtcbiAgICBjbS5kaXNwbGF5LnNpemVyLnN0eWxlLm1pbkhlaWdodCA9IG1lYXN1cmUuZG9jSGVpZ2h0ICsgXCJweFwiO1xuICAgIGNtLmRpc3BsYXkuaGVpZ2h0Rm9yY2VyLnN0eWxlLnRvcCA9IG1lYXN1cmUuZG9jSGVpZ2h0ICsgXCJweFwiO1xuICAgIGNtLmRpc3BsYXkuZ3V0dGVycy5zdHlsZS5oZWlnaHQgPSAobWVhc3VyZS5kb2NIZWlnaHQgKyBjbS5kaXNwbGF5LmJhckhlaWdodCArIHNjcm9sbEdhcChjbSkpICsgXCJweFwiO1xuICB9XG5cbiAgLy8gUmUtYWxpZ24gbGluZSBudW1iZXJzIGFuZCBndXR0ZXIgbWFya3MgdG8gY29tcGVuc2F0ZSBmb3JcbiAgLy8gaG9yaXpvbnRhbCBzY3JvbGxpbmcuXG4gIGZ1bmN0aW9uIGFsaWduSG9yaXpvbnRhbGx5KGNtKSB7XG4gICAgdmFyIGRpc3BsYXkgPSBjbS5kaXNwbGF5LCB2aWV3ID0gZGlzcGxheS52aWV3O1xuICAgIGlmICghZGlzcGxheS5hbGlnbldpZGdldHMgJiYgKCFkaXNwbGF5Lmd1dHRlcnMuZmlyc3RDaGlsZCB8fCAhY20ub3B0aW9ucy5maXhlZEd1dHRlcikpIHsgcmV0dXJuIH1cbiAgICB2YXIgY29tcCA9IGNvbXBlbnNhdGVGb3JIU2Nyb2xsKGRpc3BsYXkpIC0gZGlzcGxheS5zY3JvbGxlci5zY3JvbGxMZWZ0ICsgY20uZG9jLnNjcm9sbExlZnQ7XG4gICAgdmFyIGd1dHRlclcgPSBkaXNwbGF5Lmd1dHRlcnMub2Zmc2V0V2lkdGgsIGxlZnQgPSBjb21wICsgXCJweFwiO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmlldy5sZW5ndGg7IGkrKykgeyBpZiAoIXZpZXdbaV0uaGlkZGVuKSB7XG4gICAgICBpZiAoY20ub3B0aW9ucy5maXhlZEd1dHRlcikge1xuICAgICAgICBpZiAodmlld1tpXS5ndXR0ZXIpXG4gICAgICAgICAgeyB2aWV3W2ldLmd1dHRlci5zdHlsZS5sZWZ0ID0gbGVmdDsgfVxuICAgICAgICBpZiAodmlld1tpXS5ndXR0ZXJCYWNrZ3JvdW5kKVxuICAgICAgICAgIHsgdmlld1tpXS5ndXR0ZXJCYWNrZ3JvdW5kLnN0eWxlLmxlZnQgPSBsZWZ0OyB9XG4gICAgICB9XG4gICAgICB2YXIgYWxpZ24gPSB2aWV3W2ldLmFsaWduYWJsZTtcbiAgICAgIGlmIChhbGlnbikgeyBmb3IgKHZhciBqID0gMDsgaiA8IGFsaWduLmxlbmd0aDsgaisrKVxuICAgICAgICB7IGFsaWduW2pdLnN0eWxlLmxlZnQgPSBsZWZ0OyB9IH1cbiAgICB9IH1cbiAgICBpZiAoY20ub3B0aW9ucy5maXhlZEd1dHRlcilcbiAgICAgIHsgZGlzcGxheS5ndXR0ZXJzLnN0eWxlLmxlZnQgPSAoY29tcCArIGd1dHRlclcpICsgXCJweFwiOyB9XG4gIH1cblxuICAvLyBVc2VkIHRvIGVuc3VyZSB0aGF0IHRoZSBsaW5lIG51bWJlciBndXR0ZXIgaXMgc3RpbGwgdGhlIHJpZ2h0XG4gIC8vIHNpemUgZm9yIHRoZSBjdXJyZW50IGRvY3VtZW50IHNpemUuIFJldHVybnMgdHJ1ZSB3aGVuIGFuIHVwZGF0ZVxuICAvLyBpcyBuZWVkZWQuXG4gIGZ1bmN0aW9uIG1heWJlVXBkYXRlTGluZU51bWJlcldpZHRoKGNtKSB7XG4gICAgaWYgKCFjbS5vcHRpb25zLmxpbmVOdW1iZXJzKSB7IHJldHVybiBmYWxzZSB9XG4gICAgdmFyIGRvYyA9IGNtLmRvYywgbGFzdCA9IGxpbmVOdW1iZXJGb3IoY20ub3B0aW9ucywgZG9jLmZpcnN0ICsgZG9jLnNpemUgLSAxKSwgZGlzcGxheSA9IGNtLmRpc3BsYXk7XG4gICAgaWYgKGxhc3QubGVuZ3RoICE9IGRpc3BsYXkubGluZU51bUNoYXJzKSB7XG4gICAgICB2YXIgdGVzdCA9IGRpc3BsYXkubWVhc3VyZS5hcHBlbmRDaGlsZChlbHQoXCJkaXZcIiwgW2VsdChcImRpdlwiLCBsYXN0KV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJDb2RlTWlycm9yLWxpbmVudW1iZXIgQ29kZU1pcnJvci1ndXR0ZXItZWx0XCIpKTtcbiAgICAgIHZhciBpbm5lclcgPSB0ZXN0LmZpcnN0Q2hpbGQub2Zmc2V0V2lkdGgsIHBhZGRpbmcgPSB0ZXN0Lm9mZnNldFdpZHRoIC0gaW5uZXJXO1xuICAgICAgZGlzcGxheS5saW5lR3V0dGVyLnN0eWxlLndpZHRoID0gXCJcIjtcbiAgICAgIGRpc3BsYXkubGluZU51bUlubmVyV2lkdGggPSBNYXRoLm1heChpbm5lclcsIGRpc3BsYXkubGluZUd1dHRlci5vZmZzZXRXaWR0aCAtIHBhZGRpbmcpICsgMTtcbiAgICAgIGRpc3BsYXkubGluZU51bVdpZHRoID0gZGlzcGxheS5saW5lTnVtSW5uZXJXaWR0aCArIHBhZGRpbmc7XG4gICAgICBkaXNwbGF5LmxpbmVOdW1DaGFycyA9IGRpc3BsYXkubGluZU51bUlubmVyV2lkdGggPyBsYXN0Lmxlbmd0aCA6IC0xO1xuICAgICAgZGlzcGxheS5saW5lR3V0dGVyLnN0eWxlLndpZHRoID0gZGlzcGxheS5saW5lTnVtV2lkdGggKyBcInB4XCI7XG4gICAgICB1cGRhdGVHdXR0ZXJTcGFjZShjbS5kaXNwbGF5KTtcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgZnVuY3Rpb24gZ2V0R3V0dGVycyhndXR0ZXJzLCBsaW5lTnVtYmVycykge1xuICAgIHZhciByZXN1bHQgPSBbXSwgc2F3TGluZU51bWJlcnMgPSBmYWxzZTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGd1dHRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBuYW1lID0gZ3V0dGVyc1tpXSwgc3R5bGUgPSBudWxsO1xuICAgICAgaWYgKHR5cGVvZiBuYW1lICE9IFwic3RyaW5nXCIpIHsgc3R5bGUgPSBuYW1lLnN0eWxlOyBuYW1lID0gbmFtZS5jbGFzc05hbWU7IH1cbiAgICAgIGlmIChuYW1lID09IFwiQ29kZU1pcnJvci1saW5lbnVtYmVyc1wiKSB7XG4gICAgICAgIGlmICghbGluZU51bWJlcnMpIHsgY29udGludWUgfVxuICAgICAgICBlbHNlIHsgc2F3TGluZU51bWJlcnMgPSB0cnVlOyB9XG4gICAgICB9XG4gICAgICByZXN1bHQucHVzaCh7Y2xhc3NOYW1lOiBuYW1lLCBzdHlsZTogc3R5bGV9KTtcbiAgICB9XG4gICAgaWYgKGxpbmVOdW1iZXJzICYmICFzYXdMaW5lTnVtYmVycykgeyByZXN1bHQucHVzaCh7Y2xhc3NOYW1lOiBcIkNvZGVNaXJyb3ItbGluZW51bWJlcnNcIiwgc3R5bGU6IG51bGx9KTsgfVxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIC8vIFJlYnVpbGQgdGhlIGd1dHRlciBlbGVtZW50cywgZW5zdXJlIHRoZSBtYXJnaW4gdG8gdGhlIGxlZnQgb2YgdGhlXG4gIC8vIGNvZGUgbWF0Y2hlcyB0aGVpciB3aWR0aC5cbiAgZnVuY3Rpb24gcmVuZGVyR3V0dGVycyhkaXNwbGF5KSB7XG4gICAgdmFyIGd1dHRlcnMgPSBkaXNwbGF5Lmd1dHRlcnMsIHNwZWNzID0gZGlzcGxheS5ndXR0ZXJTcGVjcztcbiAgICByZW1vdmVDaGlsZHJlbihndXR0ZXJzKTtcbiAgICBkaXNwbGF5LmxpbmVHdXR0ZXIgPSBudWxsO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3BlY3MubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciByZWYgPSBzcGVjc1tpXTtcbiAgICAgIHZhciBjbGFzc05hbWUgPSByZWYuY2xhc3NOYW1lO1xuICAgICAgdmFyIHN0eWxlID0gcmVmLnN0eWxlO1xuICAgICAgdmFyIGdFbHQgPSBndXR0ZXJzLmFwcGVuZENoaWxkKGVsdChcImRpdlwiLCBudWxsLCBcIkNvZGVNaXJyb3ItZ3V0dGVyIFwiICsgY2xhc3NOYW1lKSk7XG4gICAgICBpZiAoc3R5bGUpIHsgZ0VsdC5zdHlsZS5jc3NUZXh0ID0gc3R5bGU7IH1cbiAgICAgIGlmIChjbGFzc05hbWUgPT0gXCJDb2RlTWlycm9yLWxpbmVudW1iZXJzXCIpIHtcbiAgICAgICAgZGlzcGxheS5saW5lR3V0dGVyID0gZ0VsdDtcbiAgICAgICAgZ0VsdC5zdHlsZS53aWR0aCA9IChkaXNwbGF5LmxpbmVOdW1XaWR0aCB8fCAxKSArIFwicHhcIjtcbiAgICAgIH1cbiAgICB9XG4gICAgZ3V0dGVycy5zdHlsZS5kaXNwbGF5ID0gc3BlY3MubGVuZ3RoID8gXCJcIiA6IFwibm9uZVwiO1xuICAgIHVwZGF0ZUd1dHRlclNwYWNlKGRpc3BsYXkpO1xuICB9XG5cbiAgZnVuY3Rpb24gdXBkYXRlR3V0dGVycyhjbSkge1xuICAgIHJlbmRlckd1dHRlcnMoY20uZGlzcGxheSk7XG4gICAgcmVnQ2hhbmdlKGNtKTtcbiAgICBhbGlnbkhvcml6b250YWxseShjbSk7XG4gIH1cblxuICAvLyBUaGUgZGlzcGxheSBoYW5kbGVzIHRoZSBET00gaW50ZWdyYXRpb24sIGJvdGggZm9yIGlucHV0IHJlYWRpbmdcbiAgLy8gYW5kIGNvbnRlbnQgZHJhd2luZy4gSXQgaG9sZHMgcmVmZXJlbmNlcyB0byBET00gbm9kZXMgYW5kXG4gIC8vIGRpc3BsYXktcmVsYXRlZCBzdGF0ZS5cblxuICBmdW5jdGlvbiBEaXNwbGF5KHBsYWNlLCBkb2MsIGlucHV0LCBvcHRpb25zKSB7XG4gICAgdmFyIGQgPSB0aGlzO1xuICAgIHRoaXMuaW5wdXQgPSBpbnB1dDtcblxuICAgIC8vIENvdmVycyBib3R0b20tcmlnaHQgc3F1YXJlIHdoZW4gYm90aCBzY3JvbGxiYXJzIGFyZSBwcmVzZW50LlxuICAgIGQuc2Nyb2xsYmFyRmlsbGVyID0gZWx0KFwiZGl2XCIsIG51bGwsIFwiQ29kZU1pcnJvci1zY3JvbGxiYXItZmlsbGVyXCIpO1xuICAgIGQuc2Nyb2xsYmFyRmlsbGVyLnNldEF0dHJpYnV0ZShcImNtLW5vdC1jb250ZW50XCIsIFwidHJ1ZVwiKTtcbiAgICAvLyBDb3ZlcnMgYm90dG9tIG9mIGd1dHRlciB3aGVuIGNvdmVyR3V0dGVyTmV4dFRvU2Nyb2xsYmFyIGlzIG9uXG4gICAgLy8gYW5kIGggc2Nyb2xsYmFyIGlzIHByZXNlbnQuXG4gICAgZC5ndXR0ZXJGaWxsZXIgPSBlbHQoXCJkaXZcIiwgbnVsbCwgXCJDb2RlTWlycm9yLWd1dHRlci1maWxsZXJcIik7XG4gICAgZC5ndXR0ZXJGaWxsZXIuc2V0QXR0cmlidXRlKFwiY20tbm90LWNvbnRlbnRcIiwgXCJ0cnVlXCIpO1xuICAgIC8vIFdpbGwgY29udGFpbiB0aGUgYWN0dWFsIGNvZGUsIHBvc2l0aW9uZWQgdG8gY292ZXIgdGhlIHZpZXdwb3J0LlxuICAgIGQubGluZURpdiA9IGVsdFAoXCJkaXZcIiwgbnVsbCwgXCJDb2RlTWlycm9yLWNvZGVcIik7XG4gICAgLy8gRWxlbWVudHMgYXJlIGFkZGVkIHRvIHRoZXNlIHRvIHJlcHJlc2VudCBzZWxlY3Rpb24gYW5kIGN1cnNvcnMuXG4gICAgZC5zZWxlY3Rpb25EaXYgPSBlbHQoXCJkaXZcIiwgbnVsbCwgbnVsbCwgXCJwb3NpdGlvbjogcmVsYXRpdmU7IHotaW5kZXg6IDFcIik7XG4gICAgZC5jdXJzb3JEaXYgPSBlbHQoXCJkaXZcIiwgbnVsbCwgXCJDb2RlTWlycm9yLWN1cnNvcnNcIik7XG4gICAgLy8gQSB2aXNpYmlsaXR5OiBoaWRkZW4gZWxlbWVudCB1c2VkIHRvIGZpbmQgdGhlIHNpemUgb2YgdGhpbmdzLlxuICAgIGQubWVhc3VyZSA9IGVsdChcImRpdlwiLCBudWxsLCBcIkNvZGVNaXJyb3ItbWVhc3VyZVwiKTtcbiAgICAvLyBXaGVuIGxpbmVzIG91dHNpZGUgb2YgdGhlIHZpZXdwb3J0IGFyZSBtZWFzdXJlZCwgdGhleSBhcmUgZHJhd24gaW4gdGhpcy5cbiAgICBkLmxpbmVNZWFzdXJlID0gZWx0KFwiZGl2XCIsIG51bGwsIFwiQ29kZU1pcnJvci1tZWFzdXJlXCIpO1xuICAgIC8vIFdyYXBzIGV2ZXJ5dGhpbmcgdGhhdCBuZWVkcyB0byBleGlzdCBpbnNpZGUgdGhlIHZlcnRpY2FsbHktcGFkZGVkIGNvb3JkaW5hdGUgc3lzdGVtXG4gICAgZC5saW5lU3BhY2UgPSBlbHRQKFwiZGl2XCIsIFtkLm1lYXN1cmUsIGQubGluZU1lYXN1cmUsIGQuc2VsZWN0aW9uRGl2LCBkLmN1cnNvckRpdiwgZC5saW5lRGl2XSxcbiAgICAgICAgICAgICAgICAgICAgICBudWxsLCBcInBvc2l0aW9uOiByZWxhdGl2ZTsgb3V0bGluZTogbm9uZVwiKTtcbiAgICB2YXIgbGluZXMgPSBlbHRQKFwiZGl2XCIsIFtkLmxpbmVTcGFjZV0sIFwiQ29kZU1pcnJvci1saW5lc1wiKTtcbiAgICAvLyBNb3ZlZCBhcm91bmQgaXRzIHBhcmVudCB0byBjb3ZlciB2aXNpYmxlIHZpZXcuXG4gICAgZC5tb3ZlciA9IGVsdChcImRpdlwiLCBbbGluZXNdLCBudWxsLCBcInBvc2l0aW9uOiByZWxhdGl2ZVwiKTtcbiAgICAvLyBTZXQgdG8gdGhlIGhlaWdodCBvZiB0aGUgZG9jdW1lbnQsIGFsbG93aW5nIHNjcm9sbGluZy5cbiAgICBkLnNpemVyID0gZWx0KFwiZGl2XCIsIFtkLm1vdmVyXSwgXCJDb2RlTWlycm9yLXNpemVyXCIpO1xuICAgIGQuc2l6ZXJXaWR0aCA9IG51bGw7XG4gICAgLy8gQmVoYXZpb3Igb2YgZWx0cyB3aXRoIG92ZXJmbG93OiBhdXRvIGFuZCBwYWRkaW5nIGlzXG4gICAgLy8gaW5jb25zaXN0ZW50IGFjcm9zcyBicm93c2Vycy4gVGhpcyBpcyB1c2VkIHRvIGVuc3VyZSB0aGVcbiAgICAvLyBzY3JvbGxhYmxlIGFyZWEgaXMgYmlnIGVub3VnaC5cbiAgICBkLmhlaWdodEZvcmNlciA9IGVsdChcImRpdlwiLCBudWxsLCBudWxsLCBcInBvc2l0aW9uOiBhYnNvbHV0ZTsgaGVpZ2h0OiBcIiArIHNjcm9sbGVyR2FwICsgXCJweDsgd2lkdGg6IDFweDtcIik7XG4gICAgLy8gV2lsbCBjb250YWluIHRoZSBndXR0ZXJzLCBpZiBhbnkuXG4gICAgZC5ndXR0ZXJzID0gZWx0KFwiZGl2XCIsIG51bGwsIFwiQ29kZU1pcnJvci1ndXR0ZXJzXCIpO1xuICAgIGQubGluZUd1dHRlciA9IG51bGw7XG4gICAgLy8gQWN0dWFsIHNjcm9sbGFibGUgZWxlbWVudC5cbiAgICBkLnNjcm9sbGVyID0gZWx0KFwiZGl2XCIsIFtkLnNpemVyLCBkLmhlaWdodEZvcmNlciwgZC5ndXR0ZXJzXSwgXCJDb2RlTWlycm9yLXNjcm9sbFwiKTtcbiAgICBkLnNjcm9sbGVyLnNldEF0dHJpYnV0ZShcInRhYkluZGV4XCIsIFwiLTFcIik7XG4gICAgLy8gVGhlIGVsZW1lbnQgaW4gd2hpY2ggdGhlIGVkaXRvciBsaXZlcy5cbiAgICBkLndyYXBwZXIgPSBlbHQoXCJkaXZcIiwgW2Quc2Nyb2xsYmFyRmlsbGVyLCBkLmd1dHRlckZpbGxlciwgZC5zY3JvbGxlcl0sIFwiQ29kZU1pcnJvclwiKTtcblxuICAgIC8vIFRoaXMgYXR0cmlidXRlIGlzIHJlc3BlY3RlZCBieSBhdXRvbWF0aWMgdHJhbnNsYXRpb24gc3lzdGVtcyBzdWNoIGFzIEdvb2dsZSBUcmFuc2xhdGUsXG4gICAgLy8gYW5kIG1heSBhbHNvIGJlIHJlc3BlY3RlZCBieSB0b29scyB1c2VkIGJ5IGh1bWFuIHRyYW5zbGF0b3JzLlxuICAgIGQud3JhcHBlci5zZXRBdHRyaWJ1dGUoJ3RyYW5zbGF0ZScsICdubycpO1xuXG4gICAgLy8gV29yayBhcm91bmQgSUU3IHotaW5kZXggYnVnIChub3QgcGVyZmVjdCwgaGVuY2UgSUU3IG5vdCByZWFsbHkgYmVpbmcgc3VwcG9ydGVkKVxuICAgIGlmIChpZSAmJiBpZV92ZXJzaW9uIDwgOCkgeyBkLmd1dHRlcnMuc3R5bGUuekluZGV4ID0gLTE7IGQuc2Nyb2xsZXIuc3R5bGUucGFkZGluZ1JpZ2h0ID0gMDsgfVxuICAgIGlmICghd2Via2l0ICYmICEoZ2Vja28gJiYgbW9iaWxlKSkgeyBkLnNjcm9sbGVyLmRyYWdnYWJsZSA9IHRydWU7IH1cblxuICAgIGlmIChwbGFjZSkge1xuICAgICAgaWYgKHBsYWNlLmFwcGVuZENoaWxkKSB7IHBsYWNlLmFwcGVuZENoaWxkKGQud3JhcHBlcik7IH1cbiAgICAgIGVsc2UgeyBwbGFjZShkLndyYXBwZXIpOyB9XG4gICAgfVxuXG4gICAgLy8gQ3VycmVudCByZW5kZXJlZCByYW5nZSAobWF5IGJlIGJpZ2dlciB0aGFuIHRoZSB2aWV3IHdpbmRvdykuXG4gICAgZC52aWV3RnJvbSA9IGQudmlld1RvID0gZG9jLmZpcnN0O1xuICAgIGQucmVwb3J0ZWRWaWV3RnJvbSA9IGQucmVwb3J0ZWRWaWV3VG8gPSBkb2MuZmlyc3Q7XG4gICAgLy8gSW5mb3JtYXRpb24gYWJvdXQgdGhlIHJlbmRlcmVkIGxpbmVzLlxuICAgIGQudmlldyA9IFtdO1xuICAgIGQucmVuZGVyZWRWaWV3ID0gbnVsbDtcbiAgICAvLyBIb2xkcyBpbmZvIGFib3V0IGEgc2luZ2xlIHJlbmRlcmVkIGxpbmUgd2hlbiBpdCB3YXMgcmVuZGVyZWRcbiAgICAvLyBmb3IgbWVhc3VyZW1lbnQsIHdoaWxlIG5vdCBpbiB2aWV3LlxuICAgIGQuZXh0ZXJuYWxNZWFzdXJlZCA9IG51bGw7XG4gICAgLy8gRW1wdHkgc3BhY2UgKGluIHBpeGVscykgYWJvdmUgdGhlIHZpZXdcbiAgICBkLnZpZXdPZmZzZXQgPSAwO1xuICAgIGQubGFzdFdyYXBIZWlnaHQgPSBkLmxhc3RXcmFwV2lkdGggPSAwO1xuICAgIGQudXBkYXRlTGluZU51bWJlcnMgPSBudWxsO1xuXG4gICAgZC5uYXRpdmVCYXJXaWR0aCA9IGQuYmFySGVpZ2h0ID0gZC5iYXJXaWR0aCA9IDA7XG4gICAgZC5zY3JvbGxiYXJzQ2xpcHBlZCA9IGZhbHNlO1xuXG4gICAgLy8gVXNlZCB0byBvbmx5IHJlc2l6ZSB0aGUgbGluZSBudW1iZXIgZ3V0dGVyIHdoZW4gbmVjZXNzYXJ5ICh3aGVuXG4gICAgLy8gdGhlIGFtb3VudCBvZiBsaW5lcyBjcm9zc2VzIGEgYm91bmRhcnkgdGhhdCBtYWtlcyBpdHMgd2lkdGggY2hhbmdlKVxuICAgIGQubGluZU51bVdpZHRoID0gZC5saW5lTnVtSW5uZXJXaWR0aCA9IGQubGluZU51bUNoYXJzID0gbnVsbDtcbiAgICAvLyBTZXQgdG8gdHJ1ZSB3aGVuIGEgbm9uLWhvcml6b250YWwtc2Nyb2xsaW5nIGxpbmUgd2lkZ2V0IGlzXG4gICAgLy8gYWRkZWQuIEFzIGFuIG9wdGltaXphdGlvbiwgbGluZSB3aWRnZXQgYWxpZ25pbmcgaXMgc2tpcHBlZCB3aGVuXG4gICAgLy8gdGhpcyBpcyBmYWxzZS5cbiAgICBkLmFsaWduV2lkZ2V0cyA9IGZhbHNlO1xuXG4gICAgZC5jYWNoZWRDaGFyV2lkdGggPSBkLmNhY2hlZFRleHRIZWlnaHQgPSBkLmNhY2hlZFBhZGRpbmdIID0gbnVsbDtcblxuICAgIC8vIFRyYWNrcyB0aGUgbWF4aW11bSBsaW5lIGxlbmd0aCBzbyB0aGF0IHRoZSBob3Jpem9udGFsIHNjcm9sbGJhclxuICAgIC8vIGNhbiBiZSBrZXB0IHN0YXRpYyB3aGVuIHNjcm9sbGluZy5cbiAgICBkLm1heExpbmUgPSBudWxsO1xuICAgIGQubWF4TGluZUxlbmd0aCA9IDA7XG4gICAgZC5tYXhMaW5lQ2hhbmdlZCA9IGZhbHNlO1xuXG4gICAgLy8gVXNlZCBmb3IgbWVhc3VyaW5nIHdoZWVsIHNjcm9sbGluZyBncmFudWxhcml0eVxuICAgIGQud2hlZWxEWCA9IGQud2hlZWxEWSA9IGQud2hlZWxTdGFydFggPSBkLndoZWVsU3RhcnRZID0gbnVsbDtcblxuICAgIC8vIFRydWUgd2hlbiBzaGlmdCBpcyBoZWxkIGRvd24uXG4gICAgZC5zaGlmdCA9IGZhbHNlO1xuXG4gICAgLy8gVXNlZCB0byB0cmFjayB3aGV0aGVyIGFueXRoaW5nIGhhcHBlbmVkIHNpbmNlIHRoZSBjb250ZXh0IG1lbnVcbiAgICAvLyB3YXMgb3BlbmVkLlxuICAgIGQuc2VsRm9yQ29udGV4dE1lbnUgPSBudWxsO1xuXG4gICAgZC5hY3RpdmVUb3VjaCA9IG51bGw7XG5cbiAgICBkLmd1dHRlclNwZWNzID0gZ2V0R3V0dGVycyhvcHRpb25zLmd1dHRlcnMsIG9wdGlvbnMubGluZU51bWJlcnMpO1xuICAgIHJlbmRlckd1dHRlcnMoZCk7XG5cbiAgICBpbnB1dC5pbml0KGQpO1xuICB9XG5cbiAgLy8gU2luY2UgdGhlIGRlbHRhIHZhbHVlcyByZXBvcnRlZCBvbiBtb3VzZSB3aGVlbCBldmVudHMgYXJlXG4gIC8vIHVuc3RhbmRhcmRpemVkIGJldHdlZW4gYnJvd3NlcnMgYW5kIGV2ZW4gYnJvd3NlciB2ZXJzaW9ucywgYW5kXG4gIC8vIGdlbmVyYWxseSBob3JyaWJseSB1bnByZWRpY3RhYmxlLCB0aGlzIGNvZGUgc3RhcnRzIGJ5IG1lYXN1cmluZ1xuICAvLyB0aGUgc2Nyb2xsIGVmZmVjdCB0aGF0IHRoZSBmaXJzdCBmZXcgbW91c2Ugd2hlZWwgZXZlbnRzIGhhdmUsXG4gIC8vIGFuZCwgZnJvbSB0aGF0LCBkZXRlY3RzIHRoZSB3YXkgaXQgY2FuIGNvbnZlcnQgZGVsdGFzIHRvIHBpeGVsXG4gIC8vIG9mZnNldHMgYWZ0ZXJ3YXJkcy5cbiAgLy9cbiAgLy8gVGhlIHJlYXNvbiB3ZSB3YW50IHRvIGtub3cgdGhlIGFtb3VudCBhIHdoZWVsIGV2ZW50IHdpbGwgc2Nyb2xsXG4gIC8vIGlzIHRoYXQgaXQgZ2l2ZXMgdXMgYSBjaGFuY2UgdG8gdXBkYXRlIHRoZSBkaXNwbGF5IGJlZm9yZSB0aGVcbiAgLy8gYWN0dWFsIHNjcm9sbGluZyBoYXBwZW5zLCByZWR1Y2luZyBmbGlja2VyaW5nLlxuXG4gIHZhciB3aGVlbFNhbXBsZXMgPSAwLCB3aGVlbFBpeGVsc1BlclVuaXQgPSBudWxsO1xuICAvLyBGaWxsIGluIGEgYnJvd3Nlci1kZXRlY3RlZCBzdGFydGluZyB2YWx1ZSBvbiBicm93c2VycyB3aGVyZSB3ZVxuICAvLyBrbm93IG9uZS4gVGhlc2UgZG9uJ3QgaGF2ZSB0byBiZSBhY2N1cmF0ZSAtLSB0aGUgcmVzdWx0IG9mIHRoZW1cbiAgLy8gYmVpbmcgd3Jvbmcgd291bGQganVzdCBiZSBhIHNsaWdodCBmbGlja2VyIG9uIHRoZSBmaXJzdCB3aGVlbFxuICAvLyBzY3JvbGwgKGlmIGl0IGlzIGxhcmdlIGVub3VnaCkuXG4gIGlmIChpZSkgeyB3aGVlbFBpeGVsc1BlclVuaXQgPSAtLjUzOyB9XG4gIGVsc2UgaWYgKGdlY2tvKSB7IHdoZWVsUGl4ZWxzUGVyVW5pdCA9IDE1OyB9XG4gIGVsc2UgaWYgKGNocm9tZSkgeyB3aGVlbFBpeGVsc1BlclVuaXQgPSAtLjc7IH1cbiAgZWxzZSBpZiAoc2FmYXJpKSB7IHdoZWVsUGl4ZWxzUGVyVW5pdCA9IC0xLzM7IH1cblxuICBmdW5jdGlvbiB3aGVlbEV2ZW50RGVsdGEoZSkge1xuICAgIHZhciBkeCA9IGUud2hlZWxEZWx0YVgsIGR5ID0gZS53aGVlbERlbHRhWTtcbiAgICBpZiAoZHggPT0gbnVsbCAmJiBlLmRldGFpbCAmJiBlLmF4aXMgPT0gZS5IT1JJWk9OVEFMX0FYSVMpIHsgZHggPSBlLmRldGFpbDsgfVxuICAgIGlmIChkeSA9PSBudWxsICYmIGUuZGV0YWlsICYmIGUuYXhpcyA9PSBlLlZFUlRJQ0FMX0FYSVMpIHsgZHkgPSBlLmRldGFpbDsgfVxuICAgIGVsc2UgaWYgKGR5ID09IG51bGwpIHsgZHkgPSBlLndoZWVsRGVsdGE7IH1cbiAgICByZXR1cm4ge3g6IGR4LCB5OiBkeX1cbiAgfVxuICBmdW5jdGlvbiB3aGVlbEV2ZW50UGl4ZWxzKGUpIHtcbiAgICB2YXIgZGVsdGEgPSB3aGVlbEV2ZW50RGVsdGEoZSk7XG4gICAgZGVsdGEueCAqPSB3aGVlbFBpeGVsc1BlclVuaXQ7XG4gICAgZGVsdGEueSAqPSB3aGVlbFBpeGVsc1BlclVuaXQ7XG4gICAgcmV0dXJuIGRlbHRhXG4gIH1cblxuICBmdW5jdGlvbiBvblNjcm9sbFdoZWVsKGNtLCBlKSB7XG4gICAgLy8gT24gQ2hyb21lIDEwMiwgdmlld3BvcnQgdXBkYXRlcyBzb21laG93IHN0b3Agd2hlZWwtYmFzZWRcbiAgICAvLyBzY3JvbGxpbmcuIFR1cm5pbmcgb2ZmIHBvaW50ZXIgZXZlbnRzIGR1cmluZyB0aGUgc2Nyb2xsIHNlZW1zXG4gICAgLy8gdG8gYXZvaWQgdGhlIGlzc3VlLlxuICAgIGlmIChjaHJvbWUgJiYgY2hyb21lX3ZlcnNpb24gPj0gMTAyKSB7XG4gICAgICBpZiAoY20uZGlzcGxheS5jaHJvbWVTY3JvbGxIYWNrID09IG51bGwpIHsgY20uZGlzcGxheS5zaXplci5zdHlsZS5wb2ludGVyRXZlbnRzID0gXCJub25lXCI7IH1cbiAgICAgIGVsc2UgeyBjbGVhclRpbWVvdXQoY20uZGlzcGxheS5jaHJvbWVTY3JvbGxIYWNrKTsgfVxuICAgICAgY20uZGlzcGxheS5jaHJvbWVTY3JvbGxIYWNrID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNtLmRpc3BsYXkuY2hyb21lU2Nyb2xsSGFjayA9IG51bGw7XG4gICAgICAgIGNtLmRpc3BsYXkuc2l6ZXIuc3R5bGUucG9pbnRlckV2ZW50cyA9IFwiXCI7XG4gICAgICB9LCAxMDApO1xuICAgIH1cbiAgICB2YXIgZGVsdGEgPSB3aGVlbEV2ZW50RGVsdGEoZSksIGR4ID0gZGVsdGEueCwgZHkgPSBkZWx0YS55O1xuICAgIHZhciBwaXhlbHNQZXJVbml0ID0gd2hlZWxQaXhlbHNQZXJVbml0O1xuICAgIGlmIChlLmRlbHRhTW9kZSA9PT0gMCkge1xuICAgICAgZHggPSBlLmRlbHRhWDtcbiAgICAgIGR5ID0gZS5kZWx0YVk7XG4gICAgICBwaXhlbHNQZXJVbml0ID0gMTtcbiAgICB9XG5cbiAgICB2YXIgZGlzcGxheSA9IGNtLmRpc3BsYXksIHNjcm9sbCA9IGRpc3BsYXkuc2Nyb2xsZXI7XG4gICAgLy8gUXVpdCBpZiB0aGVyZSdzIG5vdGhpbmcgdG8gc2Nyb2xsIGhlcmVcbiAgICB2YXIgY2FuU2Nyb2xsWCA9IHNjcm9sbC5zY3JvbGxXaWR0aCA+IHNjcm9sbC5jbGllbnRXaWR0aDtcbiAgICB2YXIgY2FuU2Nyb2xsWSA9IHNjcm9sbC5zY3JvbGxIZWlnaHQgPiBzY3JvbGwuY2xpZW50SGVpZ2h0O1xuICAgIGlmICghKGR4ICYmIGNhblNjcm9sbFggfHwgZHkgJiYgY2FuU2Nyb2xsWSkpIHsgcmV0dXJuIH1cblxuICAgIC8vIFdlYmtpdCBicm93c2VycyBvbiBPUyBYIGFib3J0IG1vbWVudHVtIHNjcm9sbHMgd2hlbiB0aGUgdGFyZ2V0XG4gICAgLy8gb2YgdGhlIHNjcm9sbCBldmVudCBpcyByZW1vdmVkIGZyb20gdGhlIHNjcm9sbGFibGUgZWxlbWVudC5cbiAgICAvLyBUaGlzIGhhY2sgKHNlZSByZWxhdGVkIGNvZGUgaW4gcGF0Y2hEaXNwbGF5KSBtYWtlcyBzdXJlIHRoZVxuICAgIC8vIGVsZW1lbnQgaXMga2VwdCBhcm91bmQuXG4gICAgaWYgKGR5ICYmIG1hYyAmJiB3ZWJraXQpIHtcbiAgICAgIG91dGVyOiBmb3IgKHZhciBjdXIgPSBlLnRhcmdldCwgdmlldyA9IGRpc3BsYXkudmlldzsgY3VyICE9IHNjcm9sbDsgY3VyID0gY3VyLnBhcmVudE5vZGUpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2aWV3Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaWYgKHZpZXdbaV0ubm9kZSA9PSBjdXIpIHtcbiAgICAgICAgICAgIGNtLmRpc3BsYXkuY3VycmVudFdoZWVsVGFyZ2V0ID0gY3VyO1xuICAgICAgICAgICAgYnJlYWsgb3V0ZXJcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBPbiBzb21lIGJyb3dzZXJzLCBob3Jpem9udGFsIHNjcm9sbGluZyB3aWxsIGNhdXNlIHJlZHJhd3MgdG9cbiAgICAvLyBoYXBwZW4gYmVmb3JlIHRoZSBndXR0ZXIgaGFzIGJlZW4gcmVhbGlnbmVkLCBjYXVzaW5nIGl0IHRvXG4gICAgLy8gd3JpZ2dsZSBhcm91bmQgaW4gYSBtb3N0IHVuc2VlbWx5IHdheS4gV2hlbiB3ZSBoYXZlIGFuXG4gICAgLy8gZXN0aW1hdGVkIHBpeGVscy9kZWx0YSB2YWx1ZSwgd2UganVzdCBoYW5kbGUgaG9yaXpvbnRhbFxuICAgIC8vIHNjcm9sbGluZyBlbnRpcmVseSBoZXJlLiBJdCdsbCBiZSBzbGlnaHRseSBvZmYgZnJvbSBuYXRpdmUsIGJ1dFxuICAgIC8vIGJldHRlciB0aGFuIGdsaXRjaGluZyBvdXQuXG4gICAgaWYgKGR4ICYmICFnZWNrbyAmJiAhcHJlc3RvICYmIHBpeGVsc1BlclVuaXQgIT0gbnVsbCkge1xuICAgICAgaWYgKGR5ICYmIGNhblNjcm9sbFkpXG4gICAgICAgIHsgdXBkYXRlU2Nyb2xsVG9wKGNtLCBNYXRoLm1heCgwLCBzY3JvbGwuc2Nyb2xsVG9wICsgZHkgKiBwaXhlbHNQZXJVbml0KSk7IH1cbiAgICAgIHNldFNjcm9sbExlZnQoY20sIE1hdGgubWF4KDAsIHNjcm9sbC5zY3JvbGxMZWZ0ICsgZHggKiBwaXhlbHNQZXJVbml0KSk7XG4gICAgICAvLyBPbmx5IHByZXZlbnQgZGVmYXVsdCBzY3JvbGxpbmcgaWYgdmVydGljYWwgc2Nyb2xsaW5nIGlzXG4gICAgICAvLyBhY3R1YWxseSBwb3NzaWJsZS4gT3RoZXJ3aXNlLCBpdCBjYXVzZXMgdmVydGljYWwgc2Nyb2xsXG4gICAgICAvLyBqaXR0ZXIgb24gT1NYIHRyYWNrcGFkcyB3aGVuIGRlbHRhWCBpcyBzbWFsbCBhbmQgZGVsdGFZXG4gICAgICAvLyBpcyBsYXJnZSAoaXNzdWUgIzM1NzkpXG4gICAgICBpZiAoIWR5IHx8IChkeSAmJiBjYW5TY3JvbGxZKSlcbiAgICAgICAgeyBlX3ByZXZlbnREZWZhdWx0KGUpOyB9XG4gICAgICBkaXNwbGF5LndoZWVsU3RhcnRYID0gbnVsbDsgLy8gQWJvcnQgbWVhc3VyZW1lbnQsIGlmIGluIHByb2dyZXNzXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyAnUHJvamVjdCcgdGhlIHZpc2libGUgdmlld3BvcnQgdG8gY292ZXIgdGhlIGFyZWEgdGhhdCBpcyBiZWluZ1xuICAgIC8vIHNjcm9sbGVkIGludG8gdmlldyAoaWYgd2Uga25vdyBlbm91Z2ggdG8gZXN0aW1hdGUgaXQpLlxuICAgIGlmIChkeSAmJiBwaXhlbHNQZXJVbml0ICE9IG51bGwpIHtcbiAgICAgIHZhciBwaXhlbHMgPSBkeSAqIHBpeGVsc1BlclVuaXQ7XG4gICAgICB2YXIgdG9wID0gY20uZG9jLnNjcm9sbFRvcCwgYm90ID0gdG9wICsgZGlzcGxheS53cmFwcGVyLmNsaWVudEhlaWdodDtcbiAgICAgIGlmIChwaXhlbHMgPCAwKSB7IHRvcCA9IE1hdGgubWF4KDAsIHRvcCArIHBpeGVscyAtIDUwKTsgfVxuICAgICAgZWxzZSB7IGJvdCA9IE1hdGgubWluKGNtLmRvYy5oZWlnaHQsIGJvdCArIHBpeGVscyArIDUwKTsgfVxuICAgICAgdXBkYXRlRGlzcGxheVNpbXBsZShjbSwge3RvcDogdG9wLCBib3R0b206IGJvdH0pO1xuICAgIH1cblxuICAgIGlmICh3aGVlbFNhbXBsZXMgPCAyMCAmJiBlLmRlbHRhTW9kZSAhPT0gMCkge1xuICAgICAgaWYgKGRpc3BsYXkud2hlZWxTdGFydFggPT0gbnVsbCkge1xuICAgICAgICBkaXNwbGF5LndoZWVsU3RhcnRYID0gc2Nyb2xsLnNjcm9sbExlZnQ7IGRpc3BsYXkud2hlZWxTdGFydFkgPSBzY3JvbGwuc2Nyb2xsVG9wO1xuICAgICAgICBkaXNwbGF5LndoZWVsRFggPSBkeDsgZGlzcGxheS53aGVlbERZID0gZHk7XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGlmIChkaXNwbGF5LndoZWVsU3RhcnRYID09IG51bGwpIHsgcmV0dXJuIH1cbiAgICAgICAgICB2YXIgbW92ZWRYID0gc2Nyb2xsLnNjcm9sbExlZnQgLSBkaXNwbGF5LndoZWVsU3RhcnRYO1xuICAgICAgICAgIHZhciBtb3ZlZFkgPSBzY3JvbGwuc2Nyb2xsVG9wIC0gZGlzcGxheS53aGVlbFN0YXJ0WTtcbiAgICAgICAgICB2YXIgc2FtcGxlID0gKG1vdmVkWSAmJiBkaXNwbGF5LndoZWVsRFkgJiYgbW92ZWRZIC8gZGlzcGxheS53aGVlbERZKSB8fFxuICAgICAgICAgICAgKG1vdmVkWCAmJiBkaXNwbGF5LndoZWVsRFggJiYgbW92ZWRYIC8gZGlzcGxheS53aGVlbERYKTtcbiAgICAgICAgICBkaXNwbGF5LndoZWVsU3RhcnRYID0gZGlzcGxheS53aGVlbFN0YXJ0WSA9IG51bGw7XG4gICAgICAgICAgaWYgKCFzYW1wbGUpIHsgcmV0dXJuIH1cbiAgICAgICAgICB3aGVlbFBpeGVsc1BlclVuaXQgPSAod2hlZWxQaXhlbHNQZXJVbml0ICogd2hlZWxTYW1wbGVzICsgc2FtcGxlKSAvICh3aGVlbFNhbXBsZXMgKyAxKTtcbiAgICAgICAgICArK3doZWVsU2FtcGxlcztcbiAgICAgICAgfSwgMjAwKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRpc3BsYXkud2hlZWxEWCArPSBkeDsgZGlzcGxheS53aGVlbERZICs9IGR5O1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIFNlbGVjdGlvbiBvYmplY3RzIGFyZSBpbW11dGFibGUuIEEgbmV3IG9uZSBpcyBjcmVhdGVkIGV2ZXJ5IHRpbWVcbiAgLy8gdGhlIHNlbGVjdGlvbiBjaGFuZ2VzLiBBIHNlbGVjdGlvbiBpcyBvbmUgb3IgbW9yZSBub24tb3ZlcmxhcHBpbmdcbiAgLy8gKGFuZCBub24tdG91Y2hpbmcpIHJhbmdlcywgc29ydGVkLCBhbmQgYW4gaW50ZWdlciB0aGF0IGluZGljYXRlc1xuICAvLyB3aGljaCBvbmUgaXMgdGhlIHByaW1hcnkgc2VsZWN0aW9uICh0aGUgb25lIHRoYXQncyBzY3JvbGxlZCBpbnRvXG4gIC8vIHZpZXcsIHRoYXQgZ2V0Q3Vyc29yIHJldHVybnMsIGV0YykuXG4gIHZhciBTZWxlY3Rpb24gPSBmdW5jdGlvbihyYW5nZXMsIHByaW1JbmRleCkge1xuICAgIHRoaXMucmFuZ2VzID0gcmFuZ2VzO1xuICAgIHRoaXMucHJpbUluZGV4ID0gcHJpbUluZGV4O1xuICB9O1xuXG4gIFNlbGVjdGlvbi5wcm90b3R5cGUucHJpbWFyeSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMucmFuZ2VzW3RoaXMucHJpbUluZGV4XSB9O1xuXG4gIFNlbGVjdGlvbi5wcm90b3R5cGUuZXF1YWxzID0gZnVuY3Rpb24gKG90aGVyKSB7XG4gICAgaWYgKG90aGVyID09IHRoaXMpIHsgcmV0dXJuIHRydWUgfVxuICAgIGlmIChvdGhlci5wcmltSW5kZXggIT0gdGhpcy5wcmltSW5kZXggfHwgb3RoZXIucmFuZ2VzLmxlbmd0aCAhPSB0aGlzLnJhbmdlcy5sZW5ndGgpIHsgcmV0dXJuIGZhbHNlIH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgaGVyZSA9IHRoaXMucmFuZ2VzW2ldLCB0aGVyZSA9IG90aGVyLnJhbmdlc1tpXTtcbiAgICAgIGlmICghZXF1YWxDdXJzb3JQb3MoaGVyZS5hbmNob3IsIHRoZXJlLmFuY2hvcikgfHwgIWVxdWFsQ3Vyc29yUG9zKGhlcmUuaGVhZCwgdGhlcmUuaGVhZCkpIHsgcmV0dXJuIGZhbHNlIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWVcbiAgfTtcblxuICBTZWxlY3Rpb24ucHJvdG90eXBlLmRlZXBDb3B5ID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBvdXQgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucmFuZ2VzLmxlbmd0aDsgaSsrKVxuICAgICAgeyBvdXRbaV0gPSBuZXcgUmFuZ2UoY29weVBvcyh0aGlzLnJhbmdlc1tpXS5hbmNob3IpLCBjb3B5UG9zKHRoaXMucmFuZ2VzW2ldLmhlYWQpKTsgfVxuICAgIHJldHVybiBuZXcgU2VsZWN0aW9uKG91dCwgdGhpcy5wcmltSW5kZXgpXG4gIH07XG5cbiAgU2VsZWN0aW9uLnByb3RvdHlwZS5zb21ldGhpbmdTZWxlY3RlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucmFuZ2VzLmxlbmd0aDsgaSsrKVxuICAgICAgeyBpZiAoIXRoaXMucmFuZ2VzW2ldLmVtcHR5KCkpIHsgcmV0dXJuIHRydWUgfSB9XG4gICAgcmV0dXJuIGZhbHNlXG4gIH07XG5cbiAgU2VsZWN0aW9uLnByb3RvdHlwZS5jb250YWlucyA9IGZ1bmN0aW9uIChwb3MsIGVuZCkge1xuICAgIGlmICghZW5kKSB7IGVuZCA9IHBvczsgfVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5yYW5nZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciByYW5nZSA9IHRoaXMucmFuZ2VzW2ldO1xuICAgICAgaWYgKGNtcChlbmQsIHJhbmdlLmZyb20oKSkgPj0gMCAmJiBjbXAocG9zLCByYW5nZS50bygpKSA8PSAwKVxuICAgICAgICB7IHJldHVybiBpIH1cbiAgICB9XG4gICAgcmV0dXJuIC0xXG4gIH07XG5cbiAgdmFyIFJhbmdlID0gZnVuY3Rpb24oYW5jaG9yLCBoZWFkKSB7XG4gICAgdGhpcy5hbmNob3IgPSBhbmNob3I7IHRoaXMuaGVhZCA9IGhlYWQ7XG4gIH07XG5cbiAgUmFuZ2UucHJvdG90eXBlLmZyb20gPSBmdW5jdGlvbiAoKSB7IHJldHVybiBtaW5Qb3ModGhpcy5hbmNob3IsIHRoaXMuaGVhZCkgfTtcbiAgUmFuZ2UucHJvdG90eXBlLnRvID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gbWF4UG9zKHRoaXMuYW5jaG9yLCB0aGlzLmhlYWQpIH07XG4gIFJhbmdlLnByb3RvdHlwZS5lbXB0eSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuaGVhZC5saW5lID09IHRoaXMuYW5jaG9yLmxpbmUgJiYgdGhpcy5oZWFkLmNoID09IHRoaXMuYW5jaG9yLmNoIH07XG5cbiAgLy8gVGFrZSBhbiB1bnNvcnRlZCwgcG90ZW50aWFsbHkgb3ZlcmxhcHBpbmcgc2V0IG9mIHJhbmdlcywgYW5kXG4gIC8vIGJ1aWxkIGEgc2VsZWN0aW9uIG91dCBvZiBpdC4gJ0NvbnN1bWVzJyByYW5nZXMgYXJyYXkgKG1vZGlmeWluZ1xuICAvLyBpdCkuXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZVNlbGVjdGlvbihjbSwgcmFuZ2VzLCBwcmltSW5kZXgpIHtcbiAgICB2YXIgbWF5VG91Y2ggPSBjbSAmJiBjbS5vcHRpb25zLnNlbGVjdGlvbnNNYXlUb3VjaDtcbiAgICB2YXIgcHJpbSA9IHJhbmdlc1twcmltSW5kZXhdO1xuICAgIHJhbmdlcy5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBjbXAoYS5mcm9tKCksIGIuZnJvbSgpKTsgfSk7XG4gICAgcHJpbUluZGV4ID0gaW5kZXhPZihyYW5nZXMsIHByaW0pO1xuICAgIGZvciAodmFyIGkgPSAxOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY3VyID0gcmFuZ2VzW2ldLCBwcmV2ID0gcmFuZ2VzW2kgLSAxXTtcbiAgICAgIHZhciBkaWZmID0gY21wKHByZXYudG8oKSwgY3VyLmZyb20oKSk7XG4gICAgICBpZiAobWF5VG91Y2ggJiYgIWN1ci5lbXB0eSgpID8gZGlmZiA+IDAgOiBkaWZmID49IDApIHtcbiAgICAgICAgdmFyIGZyb20gPSBtaW5Qb3MocHJldi5mcm9tKCksIGN1ci5mcm9tKCkpLCB0byA9IG1heFBvcyhwcmV2LnRvKCksIGN1ci50bygpKTtcbiAgICAgICAgdmFyIGludiA9IHByZXYuZW1wdHkoKSA/IGN1ci5mcm9tKCkgPT0gY3VyLmhlYWQgOiBwcmV2LmZyb20oKSA9PSBwcmV2LmhlYWQ7XG4gICAgICAgIGlmIChpIDw9IHByaW1JbmRleCkgeyAtLXByaW1JbmRleDsgfVxuICAgICAgICByYW5nZXMuc3BsaWNlKC0taSwgMiwgbmV3IFJhbmdlKGludiA/IHRvIDogZnJvbSwgaW52ID8gZnJvbSA6IHRvKSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBuZXcgU2VsZWN0aW9uKHJhbmdlcywgcHJpbUluZGV4KVxuICB9XG5cbiAgZnVuY3Rpb24gc2ltcGxlU2VsZWN0aW9uKGFuY2hvciwgaGVhZCkge1xuICAgIHJldHVybiBuZXcgU2VsZWN0aW9uKFtuZXcgUmFuZ2UoYW5jaG9yLCBoZWFkIHx8IGFuY2hvcildLCAwKVxuICB9XG5cbiAgLy8gQ29tcHV0ZSB0aGUgcG9zaXRpb24gb2YgdGhlIGVuZCBvZiBhIGNoYW5nZSAoaXRzICd0bycgcHJvcGVydHlcbiAgLy8gcmVmZXJzIHRvIHRoZSBwcmUtY2hhbmdlIGVuZCkuXG4gIGZ1bmN0aW9uIGNoYW5nZUVuZChjaGFuZ2UpIHtcbiAgICBpZiAoIWNoYW5nZS50ZXh0KSB7IHJldHVybiBjaGFuZ2UudG8gfVxuICAgIHJldHVybiBQb3MoY2hhbmdlLmZyb20ubGluZSArIGNoYW5nZS50ZXh0Lmxlbmd0aCAtIDEsXG4gICAgICAgICAgICAgICBsc3QoY2hhbmdlLnRleHQpLmxlbmd0aCArIChjaGFuZ2UudGV4dC5sZW5ndGggPT0gMSA/IGNoYW5nZS5mcm9tLmNoIDogMCkpXG4gIH1cblxuICAvLyBBZGp1c3QgYSBwb3NpdGlvbiB0byByZWZlciB0byB0aGUgcG9zdC1jaGFuZ2UgcG9zaXRpb24gb2YgdGhlXG4gIC8vIHNhbWUgdGV4dCwgb3IgdGhlIGVuZCBvZiB0aGUgY2hhbmdlIGlmIHRoZSBjaGFuZ2UgY292ZXJzIGl0LlxuICBmdW5jdGlvbiBhZGp1c3RGb3JDaGFuZ2UocG9zLCBjaGFuZ2UpIHtcbiAgICBpZiAoY21wKHBvcywgY2hhbmdlLmZyb20pIDwgMCkgeyByZXR1cm4gcG9zIH1cbiAgICBpZiAoY21wKHBvcywgY2hhbmdlLnRvKSA8PSAwKSB7IHJldHVybiBjaGFuZ2VFbmQoY2hhbmdlKSB9XG5cbiAgICB2YXIgbGluZSA9IHBvcy5saW5lICsgY2hhbmdlLnRleHQubGVuZ3RoIC0gKGNoYW5nZS50by5saW5lIC0gY2hhbmdlLmZyb20ubGluZSkgLSAxLCBjaCA9IHBvcy5jaDtcbiAgICBpZiAocG9zLmxpbmUgPT0gY2hhbmdlLnRvLmxpbmUpIHsgY2ggKz0gY2hhbmdlRW5kKGNoYW5nZSkuY2ggLSBjaGFuZ2UudG8uY2g7IH1cbiAgICByZXR1cm4gUG9zKGxpbmUsIGNoKVxuICB9XG5cbiAgZnVuY3Rpb24gY29tcHV0ZVNlbEFmdGVyQ2hhbmdlKGRvYywgY2hhbmdlKSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZG9jLnNlbC5yYW5nZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciByYW5nZSA9IGRvYy5zZWwucmFuZ2VzW2ldO1xuICAgICAgb3V0LnB1c2gobmV3IFJhbmdlKGFkanVzdEZvckNoYW5nZShyYW5nZS5hbmNob3IsIGNoYW5nZSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgYWRqdXN0Rm9yQ2hhbmdlKHJhbmdlLmhlYWQsIGNoYW5nZSkpKTtcbiAgICB9XG4gICAgcmV0dXJuIG5vcm1hbGl6ZVNlbGVjdGlvbihkb2MuY20sIG91dCwgZG9jLnNlbC5wcmltSW5kZXgpXG4gIH1cblxuICBmdW5jdGlvbiBvZmZzZXRQb3MocG9zLCBvbGQsIG53KSB7XG4gICAgaWYgKHBvcy5saW5lID09IG9sZC5saW5lKVxuICAgICAgeyByZXR1cm4gUG9zKG53LmxpbmUsIHBvcy5jaCAtIG9sZC5jaCArIG53LmNoKSB9XG4gICAgZWxzZVxuICAgICAgeyByZXR1cm4gUG9zKG53LmxpbmUgKyAocG9zLmxpbmUgLSBvbGQubGluZSksIHBvcy5jaCkgfVxuICB9XG5cbiAgLy8gVXNlZCBieSByZXBsYWNlU2VsZWN0aW9ucyB0byBhbGxvdyBtb3ZpbmcgdGhlIHNlbGVjdGlvbiB0byB0aGVcbiAgLy8gc3RhcnQgb3IgYXJvdW5kIHRoZSByZXBsYWNlZCB0ZXN0LiBIaW50IG1heSBiZSBcInN0YXJ0XCIgb3IgXCJhcm91bmRcIi5cbiAgZnVuY3Rpb24gY29tcHV0ZVJlcGxhY2VkU2VsKGRvYywgY2hhbmdlcywgaGludCkge1xuICAgIHZhciBvdXQgPSBbXTtcbiAgICB2YXIgb2xkUHJldiA9IFBvcyhkb2MuZmlyc3QsIDApLCBuZXdQcmV2ID0gb2xkUHJldjtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoYW5nZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjaGFuZ2UgPSBjaGFuZ2VzW2ldO1xuICAgICAgdmFyIGZyb20gPSBvZmZzZXRQb3MoY2hhbmdlLmZyb20sIG9sZFByZXYsIG5ld1ByZXYpO1xuICAgICAgdmFyIHRvID0gb2Zmc2V0UG9zKGNoYW5nZUVuZChjaGFuZ2UpLCBvbGRQcmV2LCBuZXdQcmV2KTtcbiAgICAgIG9sZFByZXYgPSBjaGFuZ2UudG87XG4gICAgICBuZXdQcmV2ID0gdG87XG4gICAgICBpZiAoaGludCA9PSBcImFyb3VuZFwiKSB7XG4gICAgICAgIHZhciByYW5nZSA9IGRvYy5zZWwucmFuZ2VzW2ldLCBpbnYgPSBjbXAocmFuZ2UuaGVhZCwgcmFuZ2UuYW5jaG9yKSA8IDA7XG4gICAgICAgIG91dFtpXSA9IG5ldyBSYW5nZShpbnYgPyB0byA6IGZyb20sIGludiA/IGZyb20gOiB0byk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvdXRbaV0gPSBuZXcgUmFuZ2UoZnJvbSwgZnJvbSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBuZXcgU2VsZWN0aW9uKG91dCwgZG9jLnNlbC5wcmltSW5kZXgpXG4gIH1cblxuICAvLyBVc2VkIHRvIGdldCB0aGUgZWRpdG9yIGludG8gYSBjb25zaXN0ZW50IHN0YXRlIGFnYWluIHdoZW4gb3B0aW9ucyBjaGFuZ2UuXG5cbiAgZnVuY3Rpb24gbG9hZE1vZGUoY20pIHtcbiAgICBjbS5kb2MubW9kZSA9IGdldE1vZGUoY20ub3B0aW9ucywgY20uZG9jLm1vZGVPcHRpb24pO1xuICAgIHJlc2V0TW9kZVN0YXRlKGNtKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlc2V0TW9kZVN0YXRlKGNtKSB7XG4gICAgY20uZG9jLml0ZXIoZnVuY3Rpb24gKGxpbmUpIHtcbiAgICAgIGlmIChsaW5lLnN0YXRlQWZ0ZXIpIHsgbGluZS5zdGF0ZUFmdGVyID0gbnVsbDsgfVxuICAgICAgaWYgKGxpbmUuc3R5bGVzKSB7IGxpbmUuc3R5bGVzID0gbnVsbDsgfVxuICAgIH0pO1xuICAgIGNtLmRvYy5tb2RlRnJvbnRpZXIgPSBjbS5kb2MuaGlnaGxpZ2h0RnJvbnRpZXIgPSBjbS5kb2MuZmlyc3Q7XG4gICAgc3RhcnRXb3JrZXIoY20sIDEwMCk7XG4gICAgY20uc3RhdGUubW9kZUdlbisrO1xuICAgIGlmIChjbS5jdXJPcCkgeyByZWdDaGFuZ2UoY20pOyB9XG4gIH1cblxuICAvLyBET0NVTUVOVCBEQVRBIFNUUlVDVFVSRVxuXG4gIC8vIEJ5IGRlZmF1bHQsIHVwZGF0ZXMgdGhhdCBzdGFydCBhbmQgZW5kIGF0IHRoZSBiZWdpbm5pbmcgb2YgYSBsaW5lXG4gIC8vIGFyZSB0cmVhdGVkIHNwZWNpYWxseSwgaW4gb3JkZXIgdG8gbWFrZSB0aGUgYXNzb2NpYXRpb24gb2YgbGluZVxuICAvLyB3aWRnZXRzIGFuZCBtYXJrZXIgZWxlbWVudHMgd2l0aCB0aGUgdGV4dCBiZWhhdmUgbW9yZSBpbnR1aXRpdmUuXG4gIGZ1bmN0aW9uIGlzV2hvbGVMaW5lVXBkYXRlKGRvYywgY2hhbmdlKSB7XG4gICAgcmV0dXJuIGNoYW5nZS5mcm9tLmNoID09IDAgJiYgY2hhbmdlLnRvLmNoID09IDAgJiYgbHN0KGNoYW5nZS50ZXh0KSA9PSBcIlwiICYmXG4gICAgICAoIWRvYy5jbSB8fCBkb2MuY20ub3B0aW9ucy53aG9sZUxpbmVVcGRhdGVCZWZvcmUpXG4gIH1cblxuICAvLyBQZXJmb3JtIGEgY2hhbmdlIG9uIHRoZSBkb2N1bWVudCBkYXRhIHN0cnVjdHVyZS5cbiAgZnVuY3Rpb24gdXBkYXRlRG9jKGRvYywgY2hhbmdlLCBtYXJrZWRTcGFucywgZXN0aW1hdGVIZWlnaHQpIHtcbiAgICBmdW5jdGlvbiBzcGFuc0ZvcihuKSB7cmV0dXJuIG1hcmtlZFNwYW5zID8gbWFya2VkU3BhbnNbbl0gOiBudWxsfVxuICAgIGZ1bmN0aW9uIHVwZGF0ZShsaW5lLCB0ZXh0LCBzcGFucykge1xuICAgICAgdXBkYXRlTGluZShsaW5lLCB0ZXh0LCBzcGFucywgZXN0aW1hdGVIZWlnaHQpO1xuICAgICAgc2lnbmFsTGF0ZXIobGluZSwgXCJjaGFuZ2VcIiwgbGluZSwgY2hhbmdlKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gbGluZXNGb3Ioc3RhcnQsIGVuZCkge1xuICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyArK2kpXG4gICAgICAgIHsgcmVzdWx0LnB1c2gobmV3IExpbmUodGV4dFtpXSwgc3BhbnNGb3IoaSksIGVzdGltYXRlSGVpZ2h0KSk7IH1cbiAgICAgIHJldHVybiByZXN1bHRcbiAgICB9XG5cbiAgICB2YXIgZnJvbSA9IGNoYW5nZS5mcm9tLCB0byA9IGNoYW5nZS50bywgdGV4dCA9IGNoYW5nZS50ZXh0O1xuICAgIHZhciBmaXJzdExpbmUgPSBnZXRMaW5lKGRvYywgZnJvbS5saW5lKSwgbGFzdExpbmUgPSBnZXRMaW5lKGRvYywgdG8ubGluZSk7XG4gICAgdmFyIGxhc3RUZXh0ID0gbHN0KHRleHQpLCBsYXN0U3BhbnMgPSBzcGFuc0Zvcih0ZXh0Lmxlbmd0aCAtIDEpLCBubGluZXMgPSB0by5saW5lIC0gZnJvbS5saW5lO1xuXG4gICAgLy8gQWRqdXN0IHRoZSBsaW5lIHN0cnVjdHVyZVxuICAgIGlmIChjaGFuZ2UuZnVsbCkge1xuICAgICAgZG9jLmluc2VydCgwLCBsaW5lc0ZvcigwLCB0ZXh0Lmxlbmd0aCkpO1xuICAgICAgZG9jLnJlbW92ZSh0ZXh0Lmxlbmd0aCwgZG9jLnNpemUgLSB0ZXh0Lmxlbmd0aCk7XG4gICAgfSBlbHNlIGlmIChpc1dob2xlTGluZVVwZGF0ZShkb2MsIGNoYW5nZSkpIHtcbiAgICAgIC8vIFRoaXMgaXMgYSB3aG9sZS1saW5lIHJlcGxhY2UuIFRyZWF0ZWQgc3BlY2lhbGx5IHRvIG1ha2VcbiAgICAgIC8vIHN1cmUgbGluZSBvYmplY3RzIG1vdmUgdGhlIHdheSB0aGV5IGFyZSBzdXBwb3NlZCB0by5cbiAgICAgIHZhciBhZGRlZCA9IGxpbmVzRm9yKDAsIHRleHQubGVuZ3RoIC0gMSk7XG4gICAgICB1cGRhdGUobGFzdExpbmUsIGxhc3RMaW5lLnRleHQsIGxhc3RTcGFucyk7XG4gICAgICBpZiAobmxpbmVzKSB7IGRvYy5yZW1vdmUoZnJvbS5saW5lLCBubGluZXMpOyB9XG4gICAgICBpZiAoYWRkZWQubGVuZ3RoKSB7IGRvYy5pbnNlcnQoZnJvbS5saW5lLCBhZGRlZCk7IH1cbiAgICB9IGVsc2UgaWYgKGZpcnN0TGluZSA9PSBsYXN0TGluZSkge1xuICAgICAgaWYgKHRleHQubGVuZ3RoID09IDEpIHtcbiAgICAgICAgdXBkYXRlKGZpcnN0TGluZSwgZmlyc3RMaW5lLnRleHQuc2xpY2UoMCwgZnJvbS5jaCkgKyBsYXN0VGV4dCArIGZpcnN0TGluZS50ZXh0LnNsaWNlKHRvLmNoKSwgbGFzdFNwYW5zKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBhZGRlZCQxID0gbGluZXNGb3IoMSwgdGV4dC5sZW5ndGggLSAxKTtcbiAgICAgICAgYWRkZWQkMS5wdXNoKG5ldyBMaW5lKGxhc3RUZXh0ICsgZmlyc3RMaW5lLnRleHQuc2xpY2UodG8uY2gpLCBsYXN0U3BhbnMsIGVzdGltYXRlSGVpZ2h0KSk7XG4gICAgICAgIHVwZGF0ZShmaXJzdExpbmUsIGZpcnN0TGluZS50ZXh0LnNsaWNlKDAsIGZyb20uY2gpICsgdGV4dFswXSwgc3BhbnNGb3IoMCkpO1xuICAgICAgICBkb2MuaW5zZXJ0KGZyb20ubGluZSArIDEsIGFkZGVkJDEpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGV4dC5sZW5ndGggPT0gMSkge1xuICAgICAgdXBkYXRlKGZpcnN0TGluZSwgZmlyc3RMaW5lLnRleHQuc2xpY2UoMCwgZnJvbS5jaCkgKyB0ZXh0WzBdICsgbGFzdExpbmUudGV4dC5zbGljZSh0by5jaCksIHNwYW5zRm9yKDApKTtcbiAgICAgIGRvYy5yZW1vdmUoZnJvbS5saW5lICsgMSwgbmxpbmVzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdXBkYXRlKGZpcnN0TGluZSwgZmlyc3RMaW5lLnRleHQuc2xpY2UoMCwgZnJvbS5jaCkgKyB0ZXh0WzBdLCBzcGFuc0ZvcigwKSk7XG4gICAgICB1cGRhdGUobGFzdExpbmUsIGxhc3RUZXh0ICsgbGFzdExpbmUudGV4dC5zbGljZSh0by5jaCksIGxhc3RTcGFucyk7XG4gICAgICB2YXIgYWRkZWQkMiA9IGxpbmVzRm9yKDEsIHRleHQubGVuZ3RoIC0gMSk7XG4gICAgICBpZiAobmxpbmVzID4gMSkgeyBkb2MucmVtb3ZlKGZyb20ubGluZSArIDEsIG5saW5lcyAtIDEpOyB9XG4gICAgICBkb2MuaW5zZXJ0KGZyb20ubGluZSArIDEsIGFkZGVkJDIpO1xuICAgIH1cblxuICAgIHNpZ25hbExhdGVyKGRvYywgXCJjaGFuZ2VcIiwgZG9jLCBjaGFuZ2UpO1xuICB9XG5cbiAgLy8gQ2FsbCBmIGZvciBhbGwgbGlua2VkIGRvY3VtZW50cy5cbiAgZnVuY3Rpb24gbGlua2VkRG9jcyhkb2MsIGYsIHNoYXJlZEhpc3RPbmx5KSB7XG4gICAgZnVuY3Rpb24gcHJvcGFnYXRlKGRvYywgc2tpcCwgc2hhcmVkSGlzdCkge1xuICAgICAgaWYgKGRvYy5saW5rZWQpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBkb2MubGlua2VkLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHZhciByZWwgPSBkb2MubGlua2VkW2ldO1xuICAgICAgICBpZiAocmVsLmRvYyA9PSBza2lwKSB7IGNvbnRpbnVlIH1cbiAgICAgICAgdmFyIHNoYXJlZCA9IHNoYXJlZEhpc3QgJiYgcmVsLnNoYXJlZEhpc3Q7XG4gICAgICAgIGlmIChzaGFyZWRIaXN0T25seSAmJiAhc2hhcmVkKSB7IGNvbnRpbnVlIH1cbiAgICAgICAgZihyZWwuZG9jLCBzaGFyZWQpO1xuICAgICAgICBwcm9wYWdhdGUocmVsLmRvYywgZG9jLCBzaGFyZWQpO1xuICAgICAgfSB9XG4gICAgfVxuICAgIHByb3BhZ2F0ZShkb2MsIG51bGwsIHRydWUpO1xuICB9XG5cbiAgLy8gQXR0YWNoIGEgZG9jdW1lbnQgdG8gYW4gZWRpdG9yLlxuICBmdW5jdGlvbiBhdHRhY2hEb2MoY20sIGRvYykge1xuICAgIGlmIChkb2MuY20pIHsgdGhyb3cgbmV3IEVycm9yKFwiVGhpcyBkb2N1bWVudCBpcyBhbHJlYWR5IGluIHVzZS5cIikgfVxuICAgIGNtLmRvYyA9IGRvYztcbiAgICBkb2MuY20gPSBjbTtcbiAgICBlc3RpbWF0ZUxpbmVIZWlnaHRzKGNtKTtcbiAgICBsb2FkTW9kZShjbSk7XG4gICAgc2V0RGlyZWN0aW9uQ2xhc3MoY20pO1xuICAgIGNtLm9wdGlvbnMuZGlyZWN0aW9uID0gZG9jLmRpcmVjdGlvbjtcbiAgICBpZiAoIWNtLm9wdGlvbnMubGluZVdyYXBwaW5nKSB7IGZpbmRNYXhMaW5lKGNtKTsgfVxuICAgIGNtLm9wdGlvbnMubW9kZSA9IGRvYy5tb2RlT3B0aW9uO1xuICAgIHJlZ0NoYW5nZShjbSk7XG4gIH1cblxuICBmdW5jdGlvbiBzZXREaXJlY3Rpb25DbGFzcyhjbSkge1xuICAoY20uZG9jLmRpcmVjdGlvbiA9PSBcInJ0bFwiID8gYWRkQ2xhc3MgOiBybUNsYXNzKShjbS5kaXNwbGF5LmxpbmVEaXYsIFwiQ29kZU1pcnJvci1ydGxcIik7XG4gIH1cblxuICBmdW5jdGlvbiBkaXJlY3Rpb25DaGFuZ2VkKGNtKSB7XG4gICAgcnVuSW5PcChjbSwgZnVuY3Rpb24gKCkge1xuICAgICAgc2V0RGlyZWN0aW9uQ2xhc3MoY20pO1xuICAgICAgcmVnQ2hhbmdlKGNtKTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIEhpc3RvcnkocHJldikge1xuICAgIC8vIEFycmF5cyBvZiBjaGFuZ2UgZXZlbnRzIGFuZCBzZWxlY3Rpb25zLiBEb2luZyBzb21ldGhpbmcgYWRkcyBhblxuICAgIC8vIGV2ZW50IHRvIGRvbmUgYW5kIGNsZWFycyB1bmRvLiBVbmRvaW5nIG1vdmVzIGV2ZW50cyBmcm9tIGRvbmVcbiAgICAvLyB0byB1bmRvbmUsIHJlZG9pbmcgbW92ZXMgdGhlbSBpbiB0aGUgb3RoZXIgZGlyZWN0aW9uLlxuICAgIHRoaXMuZG9uZSA9IFtdOyB0aGlzLnVuZG9uZSA9IFtdO1xuICAgIHRoaXMudW5kb0RlcHRoID0gcHJldiA/IHByZXYudW5kb0RlcHRoIDogSW5maW5pdHk7XG4gICAgLy8gVXNlZCB0byB0cmFjayB3aGVuIGNoYW5nZXMgY2FuIGJlIG1lcmdlZCBpbnRvIGEgc2luZ2xlIHVuZG9cbiAgICAvLyBldmVudFxuICAgIHRoaXMubGFzdE1vZFRpbWUgPSB0aGlzLmxhc3RTZWxUaW1lID0gMDtcbiAgICB0aGlzLmxhc3RPcCA9IHRoaXMubGFzdFNlbE9wID0gbnVsbDtcbiAgICB0aGlzLmxhc3RPcmlnaW4gPSB0aGlzLmxhc3RTZWxPcmlnaW4gPSBudWxsO1xuICAgIC8vIFVzZWQgYnkgdGhlIGlzQ2xlYW4oKSBtZXRob2RcbiAgICB0aGlzLmdlbmVyYXRpb24gPSB0aGlzLm1heEdlbmVyYXRpb24gPSBwcmV2ID8gcHJldi5tYXhHZW5lcmF0aW9uIDogMTtcbiAgfVxuXG4gIC8vIENyZWF0ZSBhIGhpc3RvcnkgY2hhbmdlIGV2ZW50IGZyb20gYW4gdXBkYXRlRG9jLXN0eWxlIGNoYW5nZVxuICAvLyBvYmplY3QuXG4gIGZ1bmN0aW9uIGhpc3RvcnlDaGFuZ2VGcm9tQ2hhbmdlKGRvYywgY2hhbmdlKSB7XG4gICAgdmFyIGhpc3RDaGFuZ2UgPSB7ZnJvbTogY29weVBvcyhjaGFuZ2UuZnJvbSksIHRvOiBjaGFuZ2VFbmQoY2hhbmdlKSwgdGV4dDogZ2V0QmV0d2Vlbihkb2MsIGNoYW5nZS5mcm9tLCBjaGFuZ2UudG8pfTtcbiAgICBhdHRhY2hMb2NhbFNwYW5zKGRvYywgaGlzdENoYW5nZSwgY2hhbmdlLmZyb20ubGluZSwgY2hhbmdlLnRvLmxpbmUgKyAxKTtcbiAgICBsaW5rZWREb2NzKGRvYywgZnVuY3Rpb24gKGRvYykgeyByZXR1cm4gYXR0YWNoTG9jYWxTcGFucyhkb2MsIGhpc3RDaGFuZ2UsIGNoYW5nZS5mcm9tLmxpbmUsIGNoYW5nZS50by5saW5lICsgMSk7IH0sIHRydWUpO1xuICAgIHJldHVybiBoaXN0Q2hhbmdlXG4gIH1cblxuICAvLyBQb3AgYWxsIHNlbGVjdGlvbiBldmVudHMgb2ZmIHRoZSBlbmQgb2YgYSBoaXN0b3J5IGFycmF5LiBTdG9wIGF0XG4gIC8vIGEgY2hhbmdlIGV2ZW50LlxuICBmdW5jdGlvbiBjbGVhclNlbGVjdGlvbkV2ZW50cyhhcnJheSkge1xuICAgIHdoaWxlIChhcnJheS5sZW5ndGgpIHtcbiAgICAgIHZhciBsYXN0ID0gbHN0KGFycmF5KTtcbiAgICAgIGlmIChsYXN0LnJhbmdlcykgeyBhcnJheS5wb3AoKTsgfVxuICAgICAgZWxzZSB7IGJyZWFrIH1cbiAgICB9XG4gIH1cblxuICAvLyBGaW5kIHRoZSB0b3AgY2hhbmdlIGV2ZW50IGluIHRoZSBoaXN0b3J5LiBQb3Agb2ZmIHNlbGVjdGlvblxuICAvLyBldmVudHMgdGhhdCBhcmUgaW4gdGhlIHdheS5cbiAgZnVuY3Rpb24gbGFzdENoYW5nZUV2ZW50KGhpc3QsIGZvcmNlKSB7XG4gICAgaWYgKGZvcmNlKSB7XG4gICAgICBjbGVhclNlbGVjdGlvbkV2ZW50cyhoaXN0LmRvbmUpO1xuICAgICAgcmV0dXJuIGxzdChoaXN0LmRvbmUpXG4gICAgfSBlbHNlIGlmIChoaXN0LmRvbmUubGVuZ3RoICYmICFsc3QoaGlzdC5kb25lKS5yYW5nZXMpIHtcbiAgICAgIHJldHVybiBsc3QoaGlzdC5kb25lKVxuICAgIH0gZWxzZSBpZiAoaGlzdC5kb25lLmxlbmd0aCA+IDEgJiYgIWhpc3QuZG9uZVtoaXN0LmRvbmUubGVuZ3RoIC0gMl0ucmFuZ2VzKSB7XG4gICAgICBoaXN0LmRvbmUucG9wKCk7XG4gICAgICByZXR1cm4gbHN0KGhpc3QuZG9uZSlcbiAgICB9XG4gIH1cblxuICAvLyBSZWdpc3RlciBhIGNoYW5nZSBpbiB0aGUgaGlzdG9yeS4gTWVyZ2VzIGNoYW5nZXMgdGhhdCBhcmUgd2l0aGluXG4gIC8vIGEgc2luZ2xlIG9wZXJhdGlvbiwgb3IgYXJlIGNsb3NlIHRvZ2V0aGVyIHdpdGggYW4gb3JpZ2luIHRoYXRcbiAgLy8gYWxsb3dzIG1lcmdpbmcgKHN0YXJ0aW5nIHdpdGggXCIrXCIpIGludG8gYSBzaW5nbGUgZXZlbnQuXG4gIGZ1bmN0aW9uIGFkZENoYW5nZVRvSGlzdG9yeShkb2MsIGNoYW5nZSwgc2VsQWZ0ZXIsIG9wSWQpIHtcbiAgICB2YXIgaGlzdCA9IGRvYy5oaXN0b3J5O1xuICAgIGhpc3QudW5kb25lLmxlbmd0aCA9IDA7XG4gICAgdmFyIHRpbWUgPSArbmV3IERhdGUsIGN1cjtcbiAgICB2YXIgbGFzdDtcblxuICAgIGlmICgoaGlzdC5sYXN0T3AgPT0gb3BJZCB8fFxuICAgICAgICAgaGlzdC5sYXN0T3JpZ2luID09IGNoYW5nZS5vcmlnaW4gJiYgY2hhbmdlLm9yaWdpbiAmJlxuICAgICAgICAgKChjaGFuZ2Uub3JpZ2luLmNoYXJBdCgwKSA9PSBcIitcIiAmJiBoaXN0Lmxhc3RNb2RUaW1lID4gdGltZSAtIChkb2MuY20gPyBkb2MuY20ub3B0aW9ucy5oaXN0b3J5RXZlbnREZWxheSA6IDUwMCkpIHx8XG4gICAgICAgICAgY2hhbmdlLm9yaWdpbi5jaGFyQXQoMCkgPT0gXCIqXCIpKSAmJlxuICAgICAgICAoY3VyID0gbGFzdENoYW5nZUV2ZW50KGhpc3QsIGhpc3QubGFzdE9wID09IG9wSWQpKSkge1xuICAgICAgLy8gTWVyZ2UgdGhpcyBjaGFuZ2UgaW50byB0aGUgbGFzdCBldmVudFxuICAgICAgbGFzdCA9IGxzdChjdXIuY2hhbmdlcyk7XG4gICAgICBpZiAoY21wKGNoYW5nZS5mcm9tLCBjaGFuZ2UudG8pID09IDAgJiYgY21wKGNoYW5nZS5mcm9tLCBsYXN0LnRvKSA9PSAwKSB7XG4gICAgICAgIC8vIE9wdGltaXplZCBjYXNlIGZvciBzaW1wbGUgaW5zZXJ0aW9uIC0tIGRvbid0IHdhbnQgdG8gYWRkXG4gICAgICAgIC8vIG5ldyBjaGFuZ2VzZXRzIGZvciBldmVyeSBjaGFyYWN0ZXIgdHlwZWRcbiAgICAgICAgbGFzdC50byA9IGNoYW5nZUVuZChjaGFuZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQWRkIG5ldyBzdWItZXZlbnRcbiAgICAgICAgY3VyLmNoYW5nZXMucHVzaChoaXN0b3J5Q2hhbmdlRnJvbUNoYW5nZShkb2MsIGNoYW5nZSkpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBDYW4gbm90IGJlIG1lcmdlZCwgc3RhcnQgYSBuZXcgZXZlbnQuXG4gICAgICB2YXIgYmVmb3JlID0gbHN0KGhpc3QuZG9uZSk7XG4gICAgICBpZiAoIWJlZm9yZSB8fCAhYmVmb3JlLnJhbmdlcylcbiAgICAgICAgeyBwdXNoU2VsZWN0aW9uVG9IaXN0b3J5KGRvYy5zZWwsIGhpc3QuZG9uZSk7IH1cbiAgICAgIGN1ciA9IHtjaGFuZ2VzOiBbaGlzdG9yeUNoYW5nZUZyb21DaGFuZ2UoZG9jLCBjaGFuZ2UpXSxcbiAgICAgICAgICAgICBnZW5lcmF0aW9uOiBoaXN0LmdlbmVyYXRpb259O1xuICAgICAgaGlzdC5kb25lLnB1c2goY3VyKTtcbiAgICAgIHdoaWxlIChoaXN0LmRvbmUubGVuZ3RoID4gaGlzdC51bmRvRGVwdGgpIHtcbiAgICAgICAgaGlzdC5kb25lLnNoaWZ0KCk7XG4gICAgICAgIGlmICghaGlzdC5kb25lWzBdLnJhbmdlcykgeyBoaXN0LmRvbmUuc2hpZnQoKTsgfVxuICAgICAgfVxuICAgIH1cbiAgICBoaXN0LmRvbmUucHVzaChzZWxBZnRlcik7XG4gICAgaGlzdC5nZW5lcmF0aW9uID0gKytoaXN0Lm1heEdlbmVyYXRpb247XG4gICAgaGlzdC5sYXN0TW9kVGltZSA9IGhpc3QubGFzdFNlbFRpbWUgPSB0aW1lO1xuICAgIGhpc3QubGFzdE9wID0gaGlzdC5sYXN0U2VsT3AgPSBvcElkO1xuICAgIGhpc3QubGFzdE9yaWdpbiA9IGhpc3QubGFzdFNlbE9yaWdpbiA9IGNoYW5nZS5vcmlnaW47XG5cbiAgICBpZiAoIWxhc3QpIHsgc2lnbmFsKGRvYywgXCJoaXN0b3J5QWRkZWRcIik7IH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHNlbGVjdGlvbkV2ZW50Q2FuQmVNZXJnZWQoZG9jLCBvcmlnaW4sIHByZXYsIHNlbCkge1xuICAgIHZhciBjaCA9IG9yaWdpbi5jaGFyQXQoMCk7XG4gICAgcmV0dXJuIGNoID09IFwiKlwiIHx8XG4gICAgICBjaCA9PSBcIitcIiAmJlxuICAgICAgcHJldi5yYW5nZXMubGVuZ3RoID09IHNlbC5yYW5nZXMubGVuZ3RoICYmXG4gICAgICBwcmV2LnNvbWV0aGluZ1NlbGVjdGVkKCkgPT0gc2VsLnNvbWV0aGluZ1NlbGVjdGVkKCkgJiZcbiAgICAgIG5ldyBEYXRlIC0gZG9jLmhpc3RvcnkubGFzdFNlbFRpbWUgPD0gKGRvYy5jbSA/IGRvYy5jbS5vcHRpb25zLmhpc3RvcnlFdmVudERlbGF5IDogNTAwKVxuICB9XG5cbiAgLy8gQ2FsbGVkIHdoZW5ldmVyIHRoZSBzZWxlY3Rpb24gY2hhbmdlcywgc2V0cyB0aGUgbmV3IHNlbGVjdGlvbiBhc1xuICAvLyB0aGUgcGVuZGluZyBzZWxlY3Rpb24gaW4gdGhlIGhpc3RvcnksIGFuZCBwdXNoZXMgdGhlIG9sZCBwZW5kaW5nXG4gIC8vIHNlbGVjdGlvbiBpbnRvIHRoZSAnZG9uZScgYXJyYXkgd2hlbiBpdCB3YXMgc2lnbmlmaWNhbnRseVxuICAvLyBkaWZmZXJlbnQgKGluIG51bWJlciBvZiBzZWxlY3RlZCByYW5nZXMsIGVtcHRpbmVzcywgb3IgdGltZSkuXG4gIGZ1bmN0aW9uIGFkZFNlbGVjdGlvblRvSGlzdG9yeShkb2MsIHNlbCwgb3BJZCwgb3B0aW9ucykge1xuICAgIHZhciBoaXN0ID0gZG9jLmhpc3RvcnksIG9yaWdpbiA9IG9wdGlvbnMgJiYgb3B0aW9ucy5vcmlnaW47XG5cbiAgICAvLyBBIG5ldyBldmVudCBpcyBzdGFydGVkIHdoZW4gdGhlIHByZXZpb3VzIG9yaWdpbiBkb2VzIG5vdCBtYXRjaFxuICAgIC8vIHRoZSBjdXJyZW50LCBvciB0aGUgb3JpZ2lucyBkb24ndCBhbGxvdyBtYXRjaGluZy4gT3JpZ2luc1xuICAgIC8vIHN0YXJ0aW5nIHdpdGggKiBhcmUgYWx3YXlzIG1lcmdlZCwgdGhvc2Ugc3RhcnRpbmcgd2l0aCArIGFyZVxuICAgIC8vIG1lcmdlZCB3aGVuIHNpbWlsYXIgYW5kIGNsb3NlIHRvZ2V0aGVyIGluIHRpbWUuXG4gICAgaWYgKG9wSWQgPT0gaGlzdC5sYXN0U2VsT3AgfHxcbiAgICAgICAgKG9yaWdpbiAmJiBoaXN0Lmxhc3RTZWxPcmlnaW4gPT0gb3JpZ2luICYmXG4gICAgICAgICAoaGlzdC5sYXN0TW9kVGltZSA9PSBoaXN0Lmxhc3RTZWxUaW1lICYmIGhpc3QubGFzdE9yaWdpbiA9PSBvcmlnaW4gfHxcbiAgICAgICAgICBzZWxlY3Rpb25FdmVudENhbkJlTWVyZ2VkKGRvYywgb3JpZ2luLCBsc3QoaGlzdC5kb25lKSwgc2VsKSkpKVxuICAgICAgeyBoaXN0LmRvbmVbaGlzdC5kb25lLmxlbmd0aCAtIDFdID0gc2VsOyB9XG4gICAgZWxzZVxuICAgICAgeyBwdXNoU2VsZWN0aW9uVG9IaXN0b3J5KHNlbCwgaGlzdC5kb25lKTsgfVxuXG4gICAgaGlzdC5sYXN0U2VsVGltZSA9ICtuZXcgRGF0ZTtcbiAgICBoaXN0Lmxhc3RTZWxPcmlnaW4gPSBvcmlnaW47XG4gICAgaGlzdC5sYXN0U2VsT3AgPSBvcElkO1xuICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMuY2xlYXJSZWRvICE9PSBmYWxzZSlcbiAgICAgIHsgY2xlYXJTZWxlY3Rpb25FdmVudHMoaGlzdC51bmRvbmUpOyB9XG4gIH1cblxuICBmdW5jdGlvbiBwdXNoU2VsZWN0aW9uVG9IaXN0b3J5KHNlbCwgZGVzdCkge1xuICAgIHZhciB0b3AgPSBsc3QoZGVzdCk7XG4gICAgaWYgKCEodG9wICYmIHRvcC5yYW5nZXMgJiYgdG9wLmVxdWFscyhzZWwpKSlcbiAgICAgIHsgZGVzdC5wdXNoKHNlbCk7IH1cbiAgfVxuXG4gIC8vIFVzZWQgdG8gc3RvcmUgbWFya2VkIHNwYW4gaW5mb3JtYXRpb24gaW4gdGhlIGhpc3RvcnkuXG4gIGZ1bmN0aW9uIGF0dGFjaExvY2FsU3BhbnMoZG9jLCBjaGFuZ2UsIGZyb20sIHRvKSB7XG4gICAgdmFyIGV4aXN0aW5nID0gY2hhbmdlW1wic3BhbnNfXCIgKyBkb2MuaWRdLCBuID0gMDtcbiAgICBkb2MuaXRlcihNYXRoLm1heChkb2MuZmlyc3QsIGZyb20pLCBNYXRoLm1pbihkb2MuZmlyc3QgKyBkb2Muc2l6ZSwgdG8pLCBmdW5jdGlvbiAobGluZSkge1xuICAgICAgaWYgKGxpbmUubWFya2VkU3BhbnMpXG4gICAgICAgIHsgKGV4aXN0aW5nIHx8IChleGlzdGluZyA9IGNoYW5nZVtcInNwYW5zX1wiICsgZG9jLmlkXSA9IHt9KSlbbl0gPSBsaW5lLm1hcmtlZFNwYW5zOyB9XG4gICAgICArK247XG4gICAgfSk7XG4gIH1cblxuICAvLyBXaGVuIHVuL3JlLWRvaW5nIHJlc3RvcmVzIHRleHQgY29udGFpbmluZyBtYXJrZWQgc3BhbnMsIHRob3NlXG4gIC8vIHRoYXQgaGF2ZSBiZWVuIGV4cGxpY2l0bHkgY2xlYXJlZCBzaG91bGQgbm90IGJlIHJlc3RvcmVkLlxuICBmdW5jdGlvbiByZW1vdmVDbGVhcmVkU3BhbnMoc3BhbnMpIHtcbiAgICBpZiAoIXNwYW5zKSB7IHJldHVybiBudWxsIH1cbiAgICB2YXIgb3V0O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3BhbnMubGVuZ3RoOyArK2kpIHtcbiAgICAgIGlmIChzcGFuc1tpXS5tYXJrZXIuZXhwbGljaXRseUNsZWFyZWQpIHsgaWYgKCFvdXQpIHsgb3V0ID0gc3BhbnMuc2xpY2UoMCwgaSk7IH0gfVxuICAgICAgZWxzZSBpZiAob3V0KSB7IG91dC5wdXNoKHNwYW5zW2ldKTsgfVxuICAgIH1cbiAgICByZXR1cm4gIW91dCA/IHNwYW5zIDogb3V0Lmxlbmd0aCA/IG91dCA6IG51bGxcbiAgfVxuXG4gIC8vIFJldHJpZXZlIGFuZCBmaWx0ZXIgdGhlIG9sZCBtYXJrZWQgc3BhbnMgc3RvcmVkIGluIGEgY2hhbmdlIGV2ZW50LlxuICBmdW5jdGlvbiBnZXRPbGRTcGFucyhkb2MsIGNoYW5nZSkge1xuICAgIHZhciBmb3VuZCA9IGNoYW5nZVtcInNwYW5zX1wiICsgZG9jLmlkXTtcbiAgICBpZiAoIWZvdW5kKSB7IHJldHVybiBudWxsIH1cbiAgICB2YXIgbncgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoYW5nZS50ZXh0Lmxlbmd0aDsgKytpKVxuICAgICAgeyBudy5wdXNoKHJlbW92ZUNsZWFyZWRTcGFucyhmb3VuZFtpXSkpOyB9XG4gICAgcmV0dXJuIG53XG4gIH1cblxuICAvLyBVc2VkIGZvciB1bi9yZS1kb2luZyBjaGFuZ2VzIGZyb20gdGhlIGhpc3RvcnkuIENvbWJpbmVzIHRoZVxuICAvLyByZXN1bHQgb2YgY29tcHV0aW5nIHRoZSBleGlzdGluZyBzcGFucyB3aXRoIHRoZSBzZXQgb2Ygc3BhbnMgdGhhdFxuICAvLyBleGlzdGVkIGluIHRoZSBoaXN0b3J5IChzbyB0aGF0IGRlbGV0aW5nIGFyb3VuZCBhIHNwYW4gYW5kIHRoZW5cbiAgLy8gdW5kb2luZyBicmluZ3MgYmFjayB0aGUgc3BhbikuXG4gIGZ1bmN0aW9uIG1lcmdlT2xkU3BhbnMoZG9jLCBjaGFuZ2UpIHtcbiAgICB2YXIgb2xkID0gZ2V0T2xkU3BhbnMoZG9jLCBjaGFuZ2UpO1xuICAgIHZhciBzdHJldGNoZWQgPSBzdHJldGNoU3BhbnNPdmVyQ2hhbmdlKGRvYywgY2hhbmdlKTtcbiAgICBpZiAoIW9sZCkgeyByZXR1cm4gc3RyZXRjaGVkIH1cbiAgICBpZiAoIXN0cmV0Y2hlZCkgeyByZXR1cm4gb2xkIH1cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2xkLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgb2xkQ3VyID0gb2xkW2ldLCBzdHJldGNoQ3VyID0gc3RyZXRjaGVkW2ldO1xuICAgICAgaWYgKG9sZEN1ciAmJiBzdHJldGNoQ3VyKSB7XG4gICAgICAgIHNwYW5zOiBmb3IgKHZhciBqID0gMDsgaiA8IHN0cmV0Y2hDdXIubGVuZ3RoOyArK2opIHtcbiAgICAgICAgICB2YXIgc3BhbiA9IHN0cmV0Y2hDdXJbal07XG4gICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBvbGRDdXIubGVuZ3RoOyArK2spXG4gICAgICAgICAgICB7IGlmIChvbGRDdXJba10ubWFya2VyID09IHNwYW4ubWFya2VyKSB7IGNvbnRpbnVlIHNwYW5zIH0gfVxuICAgICAgICAgIG9sZEN1ci5wdXNoKHNwYW4pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHN0cmV0Y2hDdXIpIHtcbiAgICAgICAgb2xkW2ldID0gc3RyZXRjaEN1cjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG9sZFxuICB9XG5cbiAgLy8gVXNlZCBib3RoIHRvIHByb3ZpZGUgYSBKU09OLXNhZmUgb2JqZWN0IGluIC5nZXRIaXN0b3J5LCBhbmQsIHdoZW5cbiAgLy8gZGV0YWNoaW5nIGEgZG9jdW1lbnQsIHRvIHNwbGl0IHRoZSBoaXN0b3J5IGluIHR3b1xuICBmdW5jdGlvbiBjb3B5SGlzdG9yeUFycmF5KGV2ZW50cywgbmV3R3JvdXAsIGluc3RhbnRpYXRlU2VsKSB7XG4gICAgdmFyIGNvcHkgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGV2ZW50cy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGV2ZW50ID0gZXZlbnRzW2ldO1xuICAgICAgaWYgKGV2ZW50LnJhbmdlcykge1xuICAgICAgICBjb3B5LnB1c2goaW5zdGFudGlhdGVTZWwgPyBTZWxlY3Rpb24ucHJvdG90eXBlLmRlZXBDb3B5LmNhbGwoZXZlbnQpIDogZXZlbnQpO1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgdmFyIGNoYW5nZXMgPSBldmVudC5jaGFuZ2VzLCBuZXdDaGFuZ2VzID0gW107XG4gICAgICBjb3B5LnB1c2goe2NoYW5nZXM6IG5ld0NoYW5nZXN9KTtcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgY2hhbmdlcy5sZW5ndGg7ICsraikge1xuICAgICAgICB2YXIgY2hhbmdlID0gY2hhbmdlc1tqXSwgbSA9ICh2b2lkIDApO1xuICAgICAgICBuZXdDaGFuZ2VzLnB1c2goe2Zyb206IGNoYW5nZS5mcm9tLCB0bzogY2hhbmdlLnRvLCB0ZXh0OiBjaGFuZ2UudGV4dH0pO1xuICAgICAgICBpZiAobmV3R3JvdXApIHsgZm9yICh2YXIgcHJvcCBpbiBjaGFuZ2UpIHsgaWYgKG0gPSBwcm9wLm1hdGNoKC9ec3BhbnNfKFxcZCspJC8pKSB7XG4gICAgICAgICAgaWYgKGluZGV4T2YobmV3R3JvdXAsIE51bWJlcihtWzFdKSkgPiAtMSkge1xuICAgICAgICAgICAgbHN0KG5ld0NoYW5nZXMpW3Byb3BdID0gY2hhbmdlW3Byb3BdO1xuICAgICAgICAgICAgZGVsZXRlIGNoYW5nZVtwcm9wXTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gfSB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjb3B5XG4gIH1cblxuICAvLyBUaGUgJ3Njcm9sbCcgcGFyYW1ldGVyIGdpdmVuIHRvIG1hbnkgb2YgdGhlc2UgaW5kaWNhdGVkIHdoZXRoZXJcbiAgLy8gdGhlIG5ldyBjdXJzb3IgcG9zaXRpb24gc2hvdWxkIGJlIHNjcm9sbGVkIGludG8gdmlldyBhZnRlclxuICAvLyBtb2RpZnlpbmcgdGhlIHNlbGVjdGlvbi5cblxuICAvLyBJZiBzaGlmdCBpcyBoZWxkIG9yIHRoZSBleHRlbmQgZmxhZyBpcyBzZXQsIGV4dGVuZHMgYSByYW5nZSB0b1xuICAvLyBpbmNsdWRlIGEgZ2l2ZW4gcG9zaXRpb24gKGFuZCBvcHRpb25hbGx5IGEgc2Vjb25kIHBvc2l0aW9uKS5cbiAgLy8gT3RoZXJ3aXNlLCBzaW1wbHkgcmV0dXJucyB0aGUgcmFuZ2UgYmV0d2VlbiB0aGUgZ2l2ZW4gcG9zaXRpb25zLlxuICAvLyBVc2VkIGZvciBjdXJzb3IgbW90aW9uIGFuZCBzdWNoLlxuICBmdW5jdGlvbiBleHRlbmRSYW5nZShyYW5nZSwgaGVhZCwgb3RoZXIsIGV4dGVuZCkge1xuICAgIGlmIChleHRlbmQpIHtcbiAgICAgIHZhciBhbmNob3IgPSByYW5nZS5hbmNob3I7XG4gICAgICBpZiAob3RoZXIpIHtcbiAgICAgICAgdmFyIHBvc0JlZm9yZSA9IGNtcChoZWFkLCBhbmNob3IpIDwgMDtcbiAgICAgICAgaWYgKHBvc0JlZm9yZSAhPSAoY21wKG90aGVyLCBhbmNob3IpIDwgMCkpIHtcbiAgICAgICAgICBhbmNob3IgPSBoZWFkO1xuICAgICAgICAgIGhlYWQgPSBvdGhlcjtcbiAgICAgICAgfSBlbHNlIGlmIChwb3NCZWZvcmUgIT0gKGNtcChoZWFkLCBvdGhlcikgPCAwKSkge1xuICAgICAgICAgIGhlYWQgPSBvdGhlcjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG5ldyBSYW5nZShhbmNob3IsIGhlYWQpXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBuZXcgUmFuZ2Uob3RoZXIgfHwgaGVhZCwgaGVhZClcbiAgICB9XG4gIH1cblxuICAvLyBFeHRlbmQgdGhlIHByaW1hcnkgc2VsZWN0aW9uIHJhbmdlLCBkaXNjYXJkIHRoZSByZXN0LlxuICBmdW5jdGlvbiBleHRlbmRTZWxlY3Rpb24oZG9jLCBoZWFkLCBvdGhlciwgb3B0aW9ucywgZXh0ZW5kKSB7XG4gICAgaWYgKGV4dGVuZCA9PSBudWxsKSB7IGV4dGVuZCA9IGRvYy5jbSAmJiAoZG9jLmNtLmRpc3BsYXkuc2hpZnQgfHwgZG9jLmV4dGVuZCk7IH1cbiAgICBzZXRTZWxlY3Rpb24oZG9jLCBuZXcgU2VsZWN0aW9uKFtleHRlbmRSYW5nZShkb2Muc2VsLnByaW1hcnkoKSwgaGVhZCwgb3RoZXIsIGV4dGVuZCldLCAwKSwgb3B0aW9ucyk7XG4gIH1cblxuICAvLyBFeHRlbmQgYWxsIHNlbGVjdGlvbnMgKHBvcyBpcyBhbiBhcnJheSBvZiBzZWxlY3Rpb25zIHdpdGggbGVuZ3RoXG4gIC8vIGVxdWFsIHRoZSBudW1iZXIgb2Ygc2VsZWN0aW9ucylcbiAgZnVuY3Rpb24gZXh0ZW5kU2VsZWN0aW9ucyhkb2MsIGhlYWRzLCBvcHRpb25zKSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBleHRlbmQgPSBkb2MuY20gJiYgKGRvYy5jbS5kaXNwbGF5LnNoaWZ0IHx8IGRvYy5leHRlbmQpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZG9jLnNlbC5yYW5nZXMubGVuZ3RoOyBpKyspXG4gICAgICB7IG91dFtpXSA9IGV4dGVuZFJhbmdlKGRvYy5zZWwucmFuZ2VzW2ldLCBoZWFkc1tpXSwgbnVsbCwgZXh0ZW5kKTsgfVxuICAgIHZhciBuZXdTZWwgPSBub3JtYWxpemVTZWxlY3Rpb24oZG9jLmNtLCBvdXQsIGRvYy5zZWwucHJpbUluZGV4KTtcbiAgICBzZXRTZWxlY3Rpb24oZG9jLCBuZXdTZWwsIG9wdGlvbnMpO1xuICB9XG5cbiAgLy8gVXBkYXRlcyBhIHNpbmdsZSByYW5nZSBpbiB0aGUgc2VsZWN0aW9uLlxuICBmdW5jdGlvbiByZXBsYWNlT25lU2VsZWN0aW9uKGRvYywgaSwgcmFuZ2UsIG9wdGlvbnMpIHtcbiAgICB2YXIgcmFuZ2VzID0gZG9jLnNlbC5yYW5nZXMuc2xpY2UoMCk7XG4gICAgcmFuZ2VzW2ldID0gcmFuZ2U7XG4gICAgc2V0U2VsZWN0aW9uKGRvYywgbm9ybWFsaXplU2VsZWN0aW9uKGRvYy5jbSwgcmFuZ2VzLCBkb2Muc2VsLnByaW1JbmRleCksIG9wdGlvbnMpO1xuICB9XG5cbiAgLy8gUmVzZXQgdGhlIHNlbGVjdGlvbiB0byBhIHNpbmdsZSByYW5nZS5cbiAgZnVuY3Rpb24gc2V0U2ltcGxlU2VsZWN0aW9uKGRvYywgYW5jaG9yLCBoZWFkLCBvcHRpb25zKSB7XG4gICAgc2V0U2VsZWN0aW9uKGRvYywgc2ltcGxlU2VsZWN0aW9uKGFuY2hvciwgaGVhZCksIG9wdGlvbnMpO1xuICB9XG5cbiAgLy8gR2l2ZSBiZWZvcmVTZWxlY3Rpb25DaGFuZ2UgaGFuZGxlcnMgYSBjaGFuZ2UgdG8gaW5mbHVlbmNlIGFcbiAgLy8gc2VsZWN0aW9uIHVwZGF0ZS5cbiAgZnVuY3Rpb24gZmlsdGVyU2VsZWN0aW9uQ2hhbmdlKGRvYywgc2VsLCBvcHRpb25zKSB7XG4gICAgdmFyIG9iaiA9IHtcbiAgICAgIHJhbmdlczogc2VsLnJhbmdlcyxcbiAgICAgIHVwZGF0ZTogZnVuY3Rpb24ocmFuZ2VzKSB7XG4gICAgICAgIHRoaXMucmFuZ2VzID0gW107XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKVxuICAgICAgICAgIHsgdGhpcy5yYW5nZXNbaV0gPSBuZXcgUmFuZ2UoY2xpcFBvcyhkb2MsIHJhbmdlc1tpXS5hbmNob3IpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsaXBQb3MoZG9jLCByYW5nZXNbaV0uaGVhZCkpOyB9XG4gICAgICB9LFxuICAgICAgb3JpZ2luOiBvcHRpb25zICYmIG9wdGlvbnMub3JpZ2luXG4gICAgfTtcbiAgICBzaWduYWwoZG9jLCBcImJlZm9yZVNlbGVjdGlvbkNoYW5nZVwiLCBkb2MsIG9iaik7XG4gICAgaWYgKGRvYy5jbSkgeyBzaWduYWwoZG9jLmNtLCBcImJlZm9yZVNlbGVjdGlvbkNoYW5nZVwiLCBkb2MuY20sIG9iaik7IH1cbiAgICBpZiAob2JqLnJhbmdlcyAhPSBzZWwucmFuZ2VzKSB7IHJldHVybiBub3JtYWxpemVTZWxlY3Rpb24oZG9jLmNtLCBvYmoucmFuZ2VzLCBvYmoucmFuZ2VzLmxlbmd0aCAtIDEpIH1cbiAgICBlbHNlIHsgcmV0dXJuIHNlbCB9XG4gIH1cblxuICBmdW5jdGlvbiBzZXRTZWxlY3Rpb25SZXBsYWNlSGlzdG9yeShkb2MsIHNlbCwgb3B0aW9ucykge1xuICAgIHZhciBkb25lID0gZG9jLmhpc3RvcnkuZG9uZSwgbGFzdCA9IGxzdChkb25lKTtcbiAgICBpZiAobGFzdCAmJiBsYXN0LnJhbmdlcykge1xuICAgICAgZG9uZVtkb25lLmxlbmd0aCAtIDFdID0gc2VsO1xuICAgICAgc2V0U2VsZWN0aW9uTm9VbmRvKGRvYywgc2VsLCBvcHRpb25zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2V0U2VsZWN0aW9uKGRvYywgc2VsLCBvcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICAvLyBTZXQgYSBuZXcgc2VsZWN0aW9uLlxuICBmdW5jdGlvbiBzZXRTZWxlY3Rpb24oZG9jLCBzZWwsIG9wdGlvbnMpIHtcbiAgICBzZXRTZWxlY3Rpb25Ob1VuZG8oZG9jLCBzZWwsIG9wdGlvbnMpO1xuICAgIGFkZFNlbGVjdGlvblRvSGlzdG9yeShkb2MsIGRvYy5zZWwsIGRvYy5jbSA/IGRvYy5jbS5jdXJPcC5pZCA6IE5hTiwgb3B0aW9ucyk7XG4gIH1cblxuICBmdW5jdGlvbiBzZXRTZWxlY3Rpb25Ob1VuZG8oZG9jLCBzZWwsIG9wdGlvbnMpIHtcbiAgICBpZiAoaGFzSGFuZGxlcihkb2MsIFwiYmVmb3JlU2VsZWN0aW9uQ2hhbmdlXCIpIHx8IGRvYy5jbSAmJiBoYXNIYW5kbGVyKGRvYy5jbSwgXCJiZWZvcmVTZWxlY3Rpb25DaGFuZ2VcIikpXG4gICAgICB7IHNlbCA9IGZpbHRlclNlbGVjdGlvbkNoYW5nZShkb2MsIHNlbCwgb3B0aW9ucyk7IH1cblxuICAgIHZhciBiaWFzID0gb3B0aW9ucyAmJiBvcHRpb25zLmJpYXMgfHxcbiAgICAgIChjbXAoc2VsLnByaW1hcnkoKS5oZWFkLCBkb2Muc2VsLnByaW1hcnkoKS5oZWFkKSA8IDAgPyAtMSA6IDEpO1xuICAgIHNldFNlbGVjdGlvbklubmVyKGRvYywgc2tpcEF0b21pY0luU2VsZWN0aW9uKGRvYywgc2VsLCBiaWFzLCB0cnVlKSk7XG5cbiAgICBpZiAoIShvcHRpb25zICYmIG9wdGlvbnMuc2Nyb2xsID09PSBmYWxzZSkgJiYgZG9jLmNtICYmIGRvYy5jbS5nZXRPcHRpb24oXCJyZWFkT25seVwiKSAhPSBcIm5vY3Vyc29yXCIpXG4gICAgICB7IGVuc3VyZUN1cnNvclZpc2libGUoZG9jLmNtKTsgfVxuICB9XG5cbiAgZnVuY3Rpb24gc2V0U2VsZWN0aW9uSW5uZXIoZG9jLCBzZWwpIHtcbiAgICBpZiAoc2VsLmVxdWFscyhkb2Muc2VsKSkgeyByZXR1cm4gfVxuXG4gICAgZG9jLnNlbCA9IHNlbDtcblxuICAgIGlmIChkb2MuY20pIHtcbiAgICAgIGRvYy5jbS5jdXJPcC51cGRhdGVJbnB1dCA9IDE7XG4gICAgICBkb2MuY20uY3VyT3Auc2VsZWN0aW9uQ2hhbmdlZCA9IHRydWU7XG4gICAgICBzaWduYWxDdXJzb3JBY3Rpdml0eShkb2MuY20pO1xuICAgIH1cbiAgICBzaWduYWxMYXRlcihkb2MsIFwiY3Vyc29yQWN0aXZpdHlcIiwgZG9jKTtcbiAgfVxuXG4gIC8vIFZlcmlmeSB0aGF0IHRoZSBzZWxlY3Rpb24gZG9lcyBub3QgcGFydGlhbGx5IHNlbGVjdCBhbnkgYXRvbWljXG4gIC8vIG1hcmtlZCByYW5nZXMuXG4gIGZ1bmN0aW9uIHJlQ2hlY2tTZWxlY3Rpb24oZG9jKSB7XG4gICAgc2V0U2VsZWN0aW9uSW5uZXIoZG9jLCBza2lwQXRvbWljSW5TZWxlY3Rpb24oZG9jLCBkb2Muc2VsLCBudWxsLCBmYWxzZSkpO1xuICB9XG5cbiAgLy8gUmV0dXJuIGEgc2VsZWN0aW9uIHRoYXQgZG9lcyBub3QgcGFydGlhbGx5IHNlbGVjdCBhbnkgYXRvbWljXG4gIC8vIHJhbmdlcy5cbiAgZnVuY3Rpb24gc2tpcEF0b21pY0luU2VsZWN0aW9uKGRvYywgc2VsLCBiaWFzLCBtYXlDbGVhcikge1xuICAgIHZhciBvdXQ7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZWwucmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgcmFuZ2UgPSBzZWwucmFuZ2VzW2ldO1xuICAgICAgdmFyIG9sZCA9IHNlbC5yYW5nZXMubGVuZ3RoID09IGRvYy5zZWwucmFuZ2VzLmxlbmd0aCAmJiBkb2Muc2VsLnJhbmdlc1tpXTtcbiAgICAgIHZhciBuZXdBbmNob3IgPSBza2lwQXRvbWljKGRvYywgcmFuZ2UuYW5jaG9yLCBvbGQgJiYgb2xkLmFuY2hvciwgYmlhcywgbWF5Q2xlYXIpO1xuICAgICAgdmFyIG5ld0hlYWQgPSBza2lwQXRvbWljKGRvYywgcmFuZ2UuaGVhZCwgb2xkICYmIG9sZC5oZWFkLCBiaWFzLCBtYXlDbGVhcik7XG4gICAgICBpZiAob3V0IHx8IG5ld0FuY2hvciAhPSByYW5nZS5hbmNob3IgfHwgbmV3SGVhZCAhPSByYW5nZS5oZWFkKSB7XG4gICAgICAgIGlmICghb3V0KSB7IG91dCA9IHNlbC5yYW5nZXMuc2xpY2UoMCwgaSk7IH1cbiAgICAgICAgb3V0W2ldID0gbmV3IFJhbmdlKG5ld0FuY2hvciwgbmV3SGVhZCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBvdXQgPyBub3JtYWxpemVTZWxlY3Rpb24oZG9jLmNtLCBvdXQsIHNlbC5wcmltSW5kZXgpIDogc2VsXG4gIH1cblxuICBmdW5jdGlvbiBza2lwQXRvbWljSW5uZXIoZG9jLCBwb3MsIG9sZFBvcywgZGlyLCBtYXlDbGVhcikge1xuICAgIHZhciBsaW5lID0gZ2V0TGluZShkb2MsIHBvcy5saW5lKTtcbiAgICBpZiAobGluZS5tYXJrZWRTcGFucykgeyBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmUubWFya2VkU3BhbnMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBzcCA9IGxpbmUubWFya2VkU3BhbnNbaV0sIG0gPSBzcC5tYXJrZXI7XG5cbiAgICAgIC8vIERldGVybWluZSBpZiB3ZSBzaG91bGQgcHJldmVudCB0aGUgY3Vyc29yIGJlaW5nIHBsYWNlZCB0byB0aGUgbGVmdC9yaWdodCBvZiBhbiBhdG9taWMgbWFya2VyXG4gICAgICAvLyBIaXN0b3JpY2FsbHkgdGhpcyB3YXMgZGV0ZXJtaW5lZCB1c2luZyB0aGUgaW5jbHVzaXZlTGVmdC9SaWdodCBvcHRpb24sIGJ1dCB0aGUgbmV3IHdheSB0byBjb250cm9sIGl0XG4gICAgICAvLyBpcyB3aXRoIHNlbGVjdExlZnQvUmlnaHRcbiAgICAgIHZhciBwcmV2ZW50Q3Vyc29yTGVmdCA9IChcInNlbGVjdExlZnRcIiBpbiBtKSA/ICFtLnNlbGVjdExlZnQgOiBtLmluY2x1c2l2ZUxlZnQ7XG4gICAgICB2YXIgcHJldmVudEN1cnNvclJpZ2h0ID0gKFwic2VsZWN0UmlnaHRcIiBpbiBtKSA/ICFtLnNlbGVjdFJpZ2h0IDogbS5pbmNsdXNpdmVSaWdodDtcblxuICAgICAgaWYgKChzcC5mcm9tID09IG51bGwgfHwgKHByZXZlbnRDdXJzb3JMZWZ0ID8gc3AuZnJvbSA8PSBwb3MuY2ggOiBzcC5mcm9tIDwgcG9zLmNoKSkgJiZcbiAgICAgICAgICAoc3AudG8gPT0gbnVsbCB8fCAocHJldmVudEN1cnNvclJpZ2h0ID8gc3AudG8gPj0gcG9zLmNoIDogc3AudG8gPiBwb3MuY2gpKSkge1xuICAgICAgICBpZiAobWF5Q2xlYXIpIHtcbiAgICAgICAgICBzaWduYWwobSwgXCJiZWZvcmVDdXJzb3JFbnRlclwiKTtcbiAgICAgICAgICBpZiAobS5leHBsaWNpdGx5Q2xlYXJlZCkge1xuICAgICAgICAgICAgaWYgKCFsaW5lLm1hcmtlZFNwYW5zKSB7IGJyZWFrIH1cbiAgICAgICAgICAgIGVsc2Ugey0taTsgY29udGludWV9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICghbS5hdG9taWMpIHsgY29udGludWUgfVxuXG4gICAgICAgIGlmIChvbGRQb3MpIHtcbiAgICAgICAgICB2YXIgbmVhciA9IG0uZmluZChkaXIgPCAwID8gMSA6IC0xKSwgZGlmZiA9ICh2b2lkIDApO1xuICAgICAgICAgIGlmIChkaXIgPCAwID8gcHJldmVudEN1cnNvclJpZ2h0IDogcHJldmVudEN1cnNvckxlZnQpXG4gICAgICAgICAgICB7IG5lYXIgPSBtb3ZlUG9zKGRvYywgbmVhciwgLWRpciwgbmVhciAmJiBuZWFyLmxpbmUgPT0gcG9zLmxpbmUgPyBsaW5lIDogbnVsbCk7IH1cbiAgICAgICAgICBpZiAobmVhciAmJiBuZWFyLmxpbmUgPT0gcG9zLmxpbmUgJiYgKGRpZmYgPSBjbXAobmVhciwgb2xkUG9zKSkgJiYgKGRpciA8IDAgPyBkaWZmIDwgMCA6IGRpZmYgPiAwKSlcbiAgICAgICAgICAgIHsgcmV0dXJuIHNraXBBdG9taWNJbm5lcihkb2MsIG5lYXIsIHBvcywgZGlyLCBtYXlDbGVhcikgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGZhciA9IG0uZmluZChkaXIgPCAwID8gLTEgOiAxKTtcbiAgICAgICAgaWYgKGRpciA8IDAgPyBwcmV2ZW50Q3Vyc29yTGVmdCA6IHByZXZlbnRDdXJzb3JSaWdodClcbiAgICAgICAgICB7IGZhciA9IG1vdmVQb3MoZG9jLCBmYXIsIGRpciwgZmFyLmxpbmUgPT0gcG9zLmxpbmUgPyBsaW5lIDogbnVsbCk7IH1cbiAgICAgICAgcmV0dXJuIGZhciA/IHNraXBBdG9taWNJbm5lcihkb2MsIGZhciwgcG9zLCBkaXIsIG1heUNsZWFyKSA6IG51bGxcbiAgICAgIH1cbiAgICB9IH1cbiAgICByZXR1cm4gcG9zXG4gIH1cblxuICAvLyBFbnN1cmUgYSBnaXZlbiBwb3NpdGlvbiBpcyBub3QgaW5zaWRlIGFuIGF0b21pYyByYW5nZS5cbiAgZnVuY3Rpb24gc2tpcEF0b21pYyhkb2MsIHBvcywgb2xkUG9zLCBiaWFzLCBtYXlDbGVhcikge1xuICAgIHZhciBkaXIgPSBiaWFzIHx8IDE7XG4gICAgdmFyIGZvdW5kID0gc2tpcEF0b21pY0lubmVyKGRvYywgcG9zLCBvbGRQb3MsIGRpciwgbWF5Q2xlYXIpIHx8XG4gICAgICAgICghbWF5Q2xlYXIgJiYgc2tpcEF0b21pY0lubmVyKGRvYywgcG9zLCBvbGRQb3MsIGRpciwgdHJ1ZSkpIHx8XG4gICAgICAgIHNraXBBdG9taWNJbm5lcihkb2MsIHBvcywgb2xkUG9zLCAtZGlyLCBtYXlDbGVhcikgfHxcbiAgICAgICAgKCFtYXlDbGVhciAmJiBza2lwQXRvbWljSW5uZXIoZG9jLCBwb3MsIG9sZFBvcywgLWRpciwgdHJ1ZSkpO1xuICAgIGlmICghZm91bmQpIHtcbiAgICAgIGRvYy5jYW50RWRpdCA9IHRydWU7XG4gICAgICByZXR1cm4gUG9zKGRvYy5maXJzdCwgMClcbiAgICB9XG4gICAgcmV0dXJuIGZvdW5kXG4gIH1cblxuICBmdW5jdGlvbiBtb3ZlUG9zKGRvYywgcG9zLCBkaXIsIGxpbmUpIHtcbiAgICBpZiAoZGlyIDwgMCAmJiBwb3MuY2ggPT0gMCkge1xuICAgICAgaWYgKHBvcy5saW5lID4gZG9jLmZpcnN0KSB7IHJldHVybiBjbGlwUG9zKGRvYywgUG9zKHBvcy5saW5lIC0gMSkpIH1cbiAgICAgIGVsc2UgeyByZXR1cm4gbnVsbCB9XG4gICAgfSBlbHNlIGlmIChkaXIgPiAwICYmIHBvcy5jaCA9PSAobGluZSB8fCBnZXRMaW5lKGRvYywgcG9zLmxpbmUpKS50ZXh0Lmxlbmd0aCkge1xuICAgICAgaWYgKHBvcy5saW5lIDwgZG9jLmZpcnN0ICsgZG9jLnNpemUgLSAxKSB7IHJldHVybiBQb3MocG9zLmxpbmUgKyAxLCAwKSB9XG4gICAgICBlbHNlIHsgcmV0dXJuIG51bGwgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbmV3IFBvcyhwb3MubGluZSwgcG9zLmNoICsgZGlyKVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHNlbGVjdEFsbChjbSkge1xuICAgIGNtLnNldFNlbGVjdGlvbihQb3MoY20uZmlyc3RMaW5lKCksIDApLCBQb3MoY20ubGFzdExpbmUoKSksIHNlbF9kb250U2Nyb2xsKTtcbiAgfVxuXG4gIC8vIFVQREFUSU5HXG5cbiAgLy8gQWxsb3cgXCJiZWZvcmVDaGFuZ2VcIiBldmVudCBoYW5kbGVycyB0byBpbmZsdWVuY2UgYSBjaGFuZ2VcbiAgZnVuY3Rpb24gZmlsdGVyQ2hhbmdlKGRvYywgY2hhbmdlLCB1cGRhdGUpIHtcbiAgICB2YXIgb2JqID0ge1xuICAgICAgY2FuY2VsZWQ6IGZhbHNlLFxuICAgICAgZnJvbTogY2hhbmdlLmZyb20sXG4gICAgICB0bzogY2hhbmdlLnRvLFxuICAgICAgdGV4dDogY2hhbmdlLnRleHQsXG4gICAgICBvcmlnaW46IGNoYW5nZS5vcmlnaW4sXG4gICAgICBjYW5jZWw6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIG9iai5jYW5jZWxlZCA9IHRydWU7IH1cbiAgICB9O1xuICAgIGlmICh1cGRhdGUpIHsgb2JqLnVwZGF0ZSA9IGZ1bmN0aW9uIChmcm9tLCB0bywgdGV4dCwgb3JpZ2luKSB7XG4gICAgICBpZiAoZnJvbSkgeyBvYmouZnJvbSA9IGNsaXBQb3MoZG9jLCBmcm9tKTsgfVxuICAgICAgaWYgKHRvKSB7IG9iai50byA9IGNsaXBQb3MoZG9jLCB0byk7IH1cbiAgICAgIGlmICh0ZXh0KSB7IG9iai50ZXh0ID0gdGV4dDsgfVxuICAgICAgaWYgKG9yaWdpbiAhPT0gdW5kZWZpbmVkKSB7IG9iai5vcmlnaW4gPSBvcmlnaW47IH1cbiAgICB9OyB9XG4gICAgc2lnbmFsKGRvYywgXCJiZWZvcmVDaGFuZ2VcIiwgZG9jLCBvYmopO1xuICAgIGlmIChkb2MuY20pIHsgc2lnbmFsKGRvYy5jbSwgXCJiZWZvcmVDaGFuZ2VcIiwgZG9jLmNtLCBvYmopOyB9XG5cbiAgICBpZiAob2JqLmNhbmNlbGVkKSB7XG4gICAgICBpZiAoZG9jLmNtKSB7IGRvYy5jbS5jdXJPcC51cGRhdGVJbnB1dCA9IDI7IH1cbiAgICAgIHJldHVybiBudWxsXG4gICAgfVxuICAgIHJldHVybiB7ZnJvbTogb2JqLmZyb20sIHRvOiBvYmoudG8sIHRleHQ6IG9iai50ZXh0LCBvcmlnaW46IG9iai5vcmlnaW59XG4gIH1cblxuICAvLyBBcHBseSBhIGNoYW5nZSB0byBhIGRvY3VtZW50LCBhbmQgYWRkIGl0IHRvIHRoZSBkb2N1bWVudCdzXG4gIC8vIGhpc3RvcnksIGFuZCBwcm9wYWdhdGluZyBpdCB0byBhbGwgbGlua2VkIGRvY3VtZW50cy5cbiAgZnVuY3Rpb24gbWFrZUNoYW5nZShkb2MsIGNoYW5nZSwgaWdub3JlUmVhZE9ubHkpIHtcbiAgICBpZiAoZG9jLmNtKSB7XG4gICAgICBpZiAoIWRvYy5jbS5jdXJPcCkgeyByZXR1cm4gb3BlcmF0aW9uKGRvYy5jbSwgbWFrZUNoYW5nZSkoZG9jLCBjaGFuZ2UsIGlnbm9yZVJlYWRPbmx5KSB9XG4gICAgICBpZiAoZG9jLmNtLnN0YXRlLnN1cHByZXNzRWRpdHMpIHsgcmV0dXJuIH1cbiAgICB9XG5cbiAgICBpZiAoaGFzSGFuZGxlcihkb2MsIFwiYmVmb3JlQ2hhbmdlXCIpIHx8IGRvYy5jbSAmJiBoYXNIYW5kbGVyKGRvYy5jbSwgXCJiZWZvcmVDaGFuZ2VcIikpIHtcbiAgICAgIGNoYW5nZSA9IGZpbHRlckNoYW5nZShkb2MsIGNoYW5nZSwgdHJ1ZSk7XG4gICAgICBpZiAoIWNoYW5nZSkgeyByZXR1cm4gfVxuICAgIH1cblxuICAgIC8vIFBvc3NpYmx5IHNwbGl0IG9yIHN1cHByZXNzIHRoZSB1cGRhdGUgYmFzZWQgb24gdGhlIHByZXNlbmNlXG4gICAgLy8gb2YgcmVhZC1vbmx5IHNwYW5zIGluIGl0cyByYW5nZS5cbiAgICB2YXIgc3BsaXQgPSBzYXdSZWFkT25seVNwYW5zICYmICFpZ25vcmVSZWFkT25seSAmJiByZW1vdmVSZWFkT25seVJhbmdlcyhkb2MsIGNoYW5nZS5mcm9tLCBjaGFuZ2UudG8pO1xuICAgIGlmIChzcGxpdCkge1xuICAgICAgZm9yICh2YXIgaSA9IHNwbGl0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKVxuICAgICAgICB7IG1ha2VDaGFuZ2VJbm5lcihkb2MsIHtmcm9tOiBzcGxpdFtpXS5mcm9tLCB0bzogc3BsaXRbaV0udG8sIHRleHQ6IGkgPyBbXCJcIl0gOiBjaGFuZ2UudGV4dCwgb3JpZ2luOiBjaGFuZ2Uub3JpZ2lufSk7IH1cbiAgICB9IGVsc2Uge1xuICAgICAgbWFrZUNoYW5nZUlubmVyKGRvYywgY2hhbmdlKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBtYWtlQ2hhbmdlSW5uZXIoZG9jLCBjaGFuZ2UpIHtcbiAgICBpZiAoY2hhbmdlLnRleHQubGVuZ3RoID09IDEgJiYgY2hhbmdlLnRleHRbMF0gPT0gXCJcIiAmJiBjbXAoY2hhbmdlLmZyb20sIGNoYW5nZS50bykgPT0gMCkgeyByZXR1cm4gfVxuICAgIHZhciBzZWxBZnRlciA9IGNvbXB1dGVTZWxBZnRlckNoYW5nZShkb2MsIGNoYW5nZSk7XG4gICAgYWRkQ2hhbmdlVG9IaXN0b3J5KGRvYywgY2hhbmdlLCBzZWxBZnRlciwgZG9jLmNtID8gZG9jLmNtLmN1ck9wLmlkIDogTmFOKTtcblxuICAgIG1ha2VDaGFuZ2VTaW5nbGVEb2MoZG9jLCBjaGFuZ2UsIHNlbEFmdGVyLCBzdHJldGNoU3BhbnNPdmVyQ2hhbmdlKGRvYywgY2hhbmdlKSk7XG4gICAgdmFyIHJlYmFzZWQgPSBbXTtcblxuICAgIGxpbmtlZERvY3MoZG9jLCBmdW5jdGlvbiAoZG9jLCBzaGFyZWRIaXN0KSB7XG4gICAgICBpZiAoIXNoYXJlZEhpc3QgJiYgaW5kZXhPZihyZWJhc2VkLCBkb2MuaGlzdG9yeSkgPT0gLTEpIHtcbiAgICAgICAgcmViYXNlSGlzdChkb2MuaGlzdG9yeSwgY2hhbmdlKTtcbiAgICAgICAgcmViYXNlZC5wdXNoKGRvYy5oaXN0b3J5KTtcbiAgICAgIH1cbiAgICAgIG1ha2VDaGFuZ2VTaW5nbGVEb2MoZG9jLCBjaGFuZ2UsIG51bGwsIHN0cmV0Y2hTcGFuc092ZXJDaGFuZ2UoZG9jLCBjaGFuZ2UpKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFJldmVydCBhIGNoYW5nZSBzdG9yZWQgaW4gYSBkb2N1bWVudCdzIGhpc3RvcnkuXG4gIGZ1bmN0aW9uIG1ha2VDaGFuZ2VGcm9tSGlzdG9yeShkb2MsIHR5cGUsIGFsbG93U2VsZWN0aW9uT25seSkge1xuICAgIHZhciBzdXBwcmVzcyA9IGRvYy5jbSAmJiBkb2MuY20uc3RhdGUuc3VwcHJlc3NFZGl0cztcbiAgICBpZiAoc3VwcHJlc3MgJiYgIWFsbG93U2VsZWN0aW9uT25seSkgeyByZXR1cm4gfVxuXG4gICAgdmFyIGhpc3QgPSBkb2MuaGlzdG9yeSwgZXZlbnQsIHNlbEFmdGVyID0gZG9jLnNlbDtcbiAgICB2YXIgc291cmNlID0gdHlwZSA9PSBcInVuZG9cIiA/IGhpc3QuZG9uZSA6IGhpc3QudW5kb25lLCBkZXN0ID0gdHlwZSA9PSBcInVuZG9cIiA/IGhpc3QudW5kb25lIDogaGlzdC5kb25lO1xuXG4gICAgLy8gVmVyaWZ5IHRoYXQgdGhlcmUgaXMgYSB1c2VhYmxlIGV2ZW50IChzbyB0aGF0IGN0cmwteiB3b24ndFxuICAgIC8vIG5lZWRsZXNzbHkgY2xlYXIgc2VsZWN0aW9uIGV2ZW50cylcbiAgICB2YXIgaSA9IDA7XG4gICAgZm9yICg7IGkgPCBzb3VyY2UubGVuZ3RoOyBpKyspIHtcbiAgICAgIGV2ZW50ID0gc291cmNlW2ldO1xuICAgICAgaWYgKGFsbG93U2VsZWN0aW9uT25seSA/IGV2ZW50LnJhbmdlcyAmJiAhZXZlbnQuZXF1YWxzKGRvYy5zZWwpIDogIWV2ZW50LnJhbmdlcylcbiAgICAgICAgeyBicmVhayB9XG4gICAgfVxuICAgIGlmIChpID09IHNvdXJjZS5sZW5ndGgpIHsgcmV0dXJuIH1cbiAgICBoaXN0Lmxhc3RPcmlnaW4gPSBoaXN0Lmxhc3RTZWxPcmlnaW4gPSBudWxsO1xuXG4gICAgZm9yICg7Oykge1xuICAgICAgZXZlbnQgPSBzb3VyY2UucG9wKCk7XG4gICAgICBpZiAoZXZlbnQucmFuZ2VzKSB7XG4gICAgICAgIHB1c2hTZWxlY3Rpb25Ub0hpc3RvcnkoZXZlbnQsIGRlc3QpO1xuICAgICAgICBpZiAoYWxsb3dTZWxlY3Rpb25Pbmx5ICYmICFldmVudC5lcXVhbHMoZG9jLnNlbCkpIHtcbiAgICAgICAgICBzZXRTZWxlY3Rpb24oZG9jLCBldmVudCwge2NsZWFyUmVkbzogZmFsc2V9KTtcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuICAgICAgICBzZWxBZnRlciA9IGV2ZW50O1xuICAgICAgfSBlbHNlIGlmIChzdXBwcmVzcykge1xuICAgICAgICBzb3VyY2UucHVzaChldmVudCk7XG4gICAgICAgIHJldHVyblxuICAgICAgfSBlbHNlIHsgYnJlYWsgfVxuICAgIH1cblxuICAgIC8vIEJ1aWxkIHVwIGEgcmV2ZXJzZSBjaGFuZ2Ugb2JqZWN0IHRvIGFkZCB0byB0aGUgb3Bwb3NpdGUgaGlzdG9yeVxuICAgIC8vIHN0YWNrIChyZWRvIHdoZW4gdW5kb2luZywgYW5kIHZpY2UgdmVyc2EpLlxuICAgIHZhciBhbnRpQ2hhbmdlcyA9IFtdO1xuICAgIHB1c2hTZWxlY3Rpb25Ub0hpc3Rvcnkoc2VsQWZ0ZXIsIGRlc3QpO1xuICAgIGRlc3QucHVzaCh7Y2hhbmdlczogYW50aUNoYW5nZXMsIGdlbmVyYXRpb246IGhpc3QuZ2VuZXJhdGlvbn0pO1xuICAgIGhpc3QuZ2VuZXJhdGlvbiA9IGV2ZW50LmdlbmVyYXRpb24gfHwgKytoaXN0Lm1heEdlbmVyYXRpb247XG5cbiAgICB2YXIgZmlsdGVyID0gaGFzSGFuZGxlcihkb2MsIFwiYmVmb3JlQ2hhbmdlXCIpIHx8IGRvYy5jbSAmJiBoYXNIYW5kbGVyKGRvYy5jbSwgXCJiZWZvcmVDaGFuZ2VcIik7XG5cbiAgICB2YXIgbG9vcCA9IGZ1bmN0aW9uICggaSApIHtcbiAgICAgIHZhciBjaGFuZ2UgPSBldmVudC5jaGFuZ2VzW2ldO1xuICAgICAgY2hhbmdlLm9yaWdpbiA9IHR5cGU7XG4gICAgICBpZiAoZmlsdGVyICYmICFmaWx0ZXJDaGFuZ2UoZG9jLCBjaGFuZ2UsIGZhbHNlKSkge1xuICAgICAgICBzb3VyY2UubGVuZ3RoID0gMDtcbiAgICAgICAgcmV0dXJuIHt9XG4gICAgICB9XG5cbiAgICAgIGFudGlDaGFuZ2VzLnB1c2goaGlzdG9yeUNoYW5nZUZyb21DaGFuZ2UoZG9jLCBjaGFuZ2UpKTtcblxuICAgICAgdmFyIGFmdGVyID0gaSA/IGNvbXB1dGVTZWxBZnRlckNoYW5nZShkb2MsIGNoYW5nZSkgOiBsc3Qoc291cmNlKTtcbiAgICAgIG1ha2VDaGFuZ2VTaW5nbGVEb2MoZG9jLCBjaGFuZ2UsIGFmdGVyLCBtZXJnZU9sZFNwYW5zKGRvYywgY2hhbmdlKSk7XG4gICAgICBpZiAoIWkgJiYgZG9jLmNtKSB7IGRvYy5jbS5zY3JvbGxJbnRvVmlldyh7ZnJvbTogY2hhbmdlLmZyb20sIHRvOiBjaGFuZ2VFbmQoY2hhbmdlKX0pOyB9XG4gICAgICB2YXIgcmViYXNlZCA9IFtdO1xuXG4gICAgICAvLyBQcm9wYWdhdGUgdG8gdGhlIGxpbmtlZCBkb2N1bWVudHNcbiAgICAgIGxpbmtlZERvY3MoZG9jLCBmdW5jdGlvbiAoZG9jLCBzaGFyZWRIaXN0KSB7XG4gICAgICAgIGlmICghc2hhcmVkSGlzdCAmJiBpbmRleE9mKHJlYmFzZWQsIGRvYy5oaXN0b3J5KSA9PSAtMSkge1xuICAgICAgICAgIHJlYmFzZUhpc3QoZG9jLmhpc3RvcnksIGNoYW5nZSk7XG4gICAgICAgICAgcmViYXNlZC5wdXNoKGRvYy5oaXN0b3J5KTtcbiAgICAgICAgfVxuICAgICAgICBtYWtlQ2hhbmdlU2luZ2xlRG9jKGRvYywgY2hhbmdlLCBudWxsLCBtZXJnZU9sZFNwYW5zKGRvYywgY2hhbmdlKSk7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgZm9yICh2YXIgaSQxID0gZXZlbnQuY2hhbmdlcy5sZW5ndGggLSAxOyBpJDEgPj0gMDsgLS1pJDEpIHtcbiAgICAgIHZhciByZXR1cm5lZCA9IGxvb3AoIGkkMSApO1xuXG4gICAgICBpZiAoIHJldHVybmVkICkgcmV0dXJuIHJldHVybmVkLnY7XG4gICAgfVxuICB9XG5cbiAgLy8gU3ViLXZpZXdzIG5lZWQgdGhlaXIgbGluZSBudW1iZXJzIHNoaWZ0ZWQgd2hlbiB0ZXh0IGlzIGFkZGVkXG4gIC8vIGFib3ZlIG9yIGJlbG93IHRoZW0gaW4gdGhlIHBhcmVudCBkb2N1bWVudC5cbiAgZnVuY3Rpb24gc2hpZnREb2MoZG9jLCBkaXN0YW5jZSkge1xuICAgIGlmIChkaXN0YW5jZSA9PSAwKSB7IHJldHVybiB9XG4gICAgZG9jLmZpcnN0ICs9IGRpc3RhbmNlO1xuICAgIGRvYy5zZWwgPSBuZXcgU2VsZWN0aW9uKG1hcChkb2Muc2VsLnJhbmdlcywgZnVuY3Rpb24gKHJhbmdlKSB7IHJldHVybiBuZXcgUmFuZ2UoXG4gICAgICBQb3MocmFuZ2UuYW5jaG9yLmxpbmUgKyBkaXN0YW5jZSwgcmFuZ2UuYW5jaG9yLmNoKSxcbiAgICAgIFBvcyhyYW5nZS5oZWFkLmxpbmUgKyBkaXN0YW5jZSwgcmFuZ2UuaGVhZC5jaClcbiAgICApOyB9KSwgZG9jLnNlbC5wcmltSW5kZXgpO1xuICAgIGlmIChkb2MuY20pIHtcbiAgICAgIHJlZ0NoYW5nZShkb2MuY20sIGRvYy5maXJzdCwgZG9jLmZpcnN0IC0gZGlzdGFuY2UsIGRpc3RhbmNlKTtcbiAgICAgIGZvciAodmFyIGQgPSBkb2MuY20uZGlzcGxheSwgbCA9IGQudmlld0Zyb207IGwgPCBkLnZpZXdUbzsgbCsrKVxuICAgICAgICB7IHJlZ0xpbmVDaGFuZ2UoZG9jLmNtLCBsLCBcImd1dHRlclwiKTsgfVxuICAgIH1cbiAgfVxuXG4gIC8vIE1vcmUgbG93ZXItbGV2ZWwgY2hhbmdlIGZ1bmN0aW9uLCBoYW5kbGluZyBvbmx5IGEgc2luZ2xlIGRvY3VtZW50XG4gIC8vIChub3QgbGlua2VkIG9uZXMpLlxuICBmdW5jdGlvbiBtYWtlQ2hhbmdlU2luZ2xlRG9jKGRvYywgY2hhbmdlLCBzZWxBZnRlciwgc3BhbnMpIHtcbiAgICBpZiAoZG9jLmNtICYmICFkb2MuY20uY3VyT3ApXG4gICAgICB7IHJldHVybiBvcGVyYXRpb24oZG9jLmNtLCBtYWtlQ2hhbmdlU2luZ2xlRG9jKShkb2MsIGNoYW5nZSwgc2VsQWZ0ZXIsIHNwYW5zKSB9XG5cbiAgICBpZiAoY2hhbmdlLnRvLmxpbmUgPCBkb2MuZmlyc3QpIHtcbiAgICAgIHNoaWZ0RG9jKGRvYywgY2hhbmdlLnRleHQubGVuZ3RoIC0gMSAtIChjaGFuZ2UudG8ubGluZSAtIGNoYW5nZS5mcm9tLmxpbmUpKTtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBpZiAoY2hhbmdlLmZyb20ubGluZSA+IGRvYy5sYXN0TGluZSgpKSB7IHJldHVybiB9XG5cbiAgICAvLyBDbGlwIHRoZSBjaGFuZ2UgdG8gdGhlIHNpemUgb2YgdGhpcyBkb2NcbiAgICBpZiAoY2hhbmdlLmZyb20ubGluZSA8IGRvYy5maXJzdCkge1xuICAgICAgdmFyIHNoaWZ0ID0gY2hhbmdlLnRleHQubGVuZ3RoIC0gMSAtIChkb2MuZmlyc3QgLSBjaGFuZ2UuZnJvbS5saW5lKTtcbiAgICAgIHNoaWZ0RG9jKGRvYywgc2hpZnQpO1xuICAgICAgY2hhbmdlID0ge2Zyb206IFBvcyhkb2MuZmlyc3QsIDApLCB0bzogUG9zKGNoYW5nZS50by5saW5lICsgc2hpZnQsIGNoYW5nZS50by5jaCksXG4gICAgICAgICAgICAgICAgdGV4dDogW2xzdChjaGFuZ2UudGV4dCldLCBvcmlnaW46IGNoYW5nZS5vcmlnaW59O1xuICAgIH1cbiAgICB2YXIgbGFzdCA9IGRvYy5sYXN0TGluZSgpO1xuICAgIGlmIChjaGFuZ2UudG8ubGluZSA+IGxhc3QpIHtcbiAgICAgIGNoYW5nZSA9IHtmcm9tOiBjaGFuZ2UuZnJvbSwgdG86IFBvcyhsYXN0LCBnZXRMaW5lKGRvYywgbGFzdCkudGV4dC5sZW5ndGgpLFxuICAgICAgICAgICAgICAgIHRleHQ6IFtjaGFuZ2UudGV4dFswXV0sIG9yaWdpbjogY2hhbmdlLm9yaWdpbn07XG4gICAgfVxuXG4gICAgY2hhbmdlLnJlbW92ZWQgPSBnZXRCZXR3ZWVuKGRvYywgY2hhbmdlLmZyb20sIGNoYW5nZS50byk7XG5cbiAgICBpZiAoIXNlbEFmdGVyKSB7IHNlbEFmdGVyID0gY29tcHV0ZVNlbEFmdGVyQ2hhbmdlKGRvYywgY2hhbmdlKTsgfVxuICAgIGlmIChkb2MuY20pIHsgbWFrZUNoYW5nZVNpbmdsZURvY0luRWRpdG9yKGRvYy5jbSwgY2hhbmdlLCBzcGFucyk7IH1cbiAgICBlbHNlIHsgdXBkYXRlRG9jKGRvYywgY2hhbmdlLCBzcGFucyk7IH1cbiAgICBzZXRTZWxlY3Rpb25Ob1VuZG8oZG9jLCBzZWxBZnRlciwgc2VsX2RvbnRTY3JvbGwpO1xuXG4gICAgaWYgKGRvYy5jYW50RWRpdCAmJiBza2lwQXRvbWljKGRvYywgUG9zKGRvYy5maXJzdExpbmUoKSwgMCkpKVxuICAgICAgeyBkb2MuY2FudEVkaXQgPSBmYWxzZTsgfVxuICB9XG5cbiAgLy8gSGFuZGxlIHRoZSBpbnRlcmFjdGlvbiBvZiBhIGNoYW5nZSB0byBhIGRvY3VtZW50IHdpdGggdGhlIGVkaXRvclxuICAvLyB0aGF0IHRoaXMgZG9jdW1lbnQgaXMgcGFydCBvZi5cbiAgZnVuY3Rpb24gbWFrZUNoYW5nZVNpbmdsZURvY0luRWRpdG9yKGNtLCBjaGFuZ2UsIHNwYW5zKSB7XG4gICAgdmFyIGRvYyA9IGNtLmRvYywgZGlzcGxheSA9IGNtLmRpc3BsYXksIGZyb20gPSBjaGFuZ2UuZnJvbSwgdG8gPSBjaGFuZ2UudG87XG5cbiAgICB2YXIgcmVjb21wdXRlTWF4TGVuZ3RoID0gZmFsc2UsIGNoZWNrV2lkdGhTdGFydCA9IGZyb20ubGluZTtcbiAgICBpZiAoIWNtLm9wdGlvbnMubGluZVdyYXBwaW5nKSB7XG4gICAgICBjaGVja1dpZHRoU3RhcnQgPSBsaW5lTm8odmlzdWFsTGluZShnZXRMaW5lKGRvYywgZnJvbS5saW5lKSkpO1xuICAgICAgZG9jLml0ZXIoY2hlY2tXaWR0aFN0YXJ0LCB0by5saW5lICsgMSwgZnVuY3Rpb24gKGxpbmUpIHtcbiAgICAgICAgaWYgKGxpbmUgPT0gZGlzcGxheS5tYXhMaW5lKSB7XG4gICAgICAgICAgcmVjb21wdXRlTWF4TGVuZ3RoID0gdHJ1ZTtcbiAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAoZG9jLnNlbC5jb250YWlucyhjaGFuZ2UuZnJvbSwgY2hhbmdlLnRvKSA+IC0xKVxuICAgICAgeyBzaWduYWxDdXJzb3JBY3Rpdml0eShjbSk7IH1cblxuICAgIHVwZGF0ZURvYyhkb2MsIGNoYW5nZSwgc3BhbnMsIGVzdGltYXRlSGVpZ2h0KGNtKSk7XG5cbiAgICBpZiAoIWNtLm9wdGlvbnMubGluZVdyYXBwaW5nKSB7XG4gICAgICBkb2MuaXRlcihjaGVja1dpZHRoU3RhcnQsIGZyb20ubGluZSArIGNoYW5nZS50ZXh0Lmxlbmd0aCwgZnVuY3Rpb24gKGxpbmUpIHtcbiAgICAgICAgdmFyIGxlbiA9IGxpbmVMZW5ndGgobGluZSk7XG4gICAgICAgIGlmIChsZW4gPiBkaXNwbGF5Lm1heExpbmVMZW5ndGgpIHtcbiAgICAgICAgICBkaXNwbGF5Lm1heExpbmUgPSBsaW5lO1xuICAgICAgICAgIGRpc3BsYXkubWF4TGluZUxlbmd0aCA9IGxlbjtcbiAgICAgICAgICBkaXNwbGF5Lm1heExpbmVDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgICByZWNvbXB1dGVNYXhMZW5ndGggPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBpZiAocmVjb21wdXRlTWF4TGVuZ3RoKSB7IGNtLmN1ck9wLnVwZGF0ZU1heExpbmUgPSB0cnVlOyB9XG4gICAgfVxuXG4gICAgcmV0cmVhdEZyb250aWVyKGRvYywgZnJvbS5saW5lKTtcbiAgICBzdGFydFdvcmtlcihjbSwgNDAwKTtcblxuICAgIHZhciBsZW5kaWZmID0gY2hhbmdlLnRleHQubGVuZ3RoIC0gKHRvLmxpbmUgLSBmcm9tLmxpbmUpIC0gMTtcbiAgICAvLyBSZW1lbWJlciB0aGF0IHRoZXNlIGxpbmVzIGNoYW5nZWQsIGZvciB1cGRhdGluZyB0aGUgZGlzcGxheVxuICAgIGlmIChjaGFuZ2UuZnVsbClcbiAgICAgIHsgcmVnQ2hhbmdlKGNtKTsgfVxuICAgIGVsc2UgaWYgKGZyb20ubGluZSA9PSB0by5saW5lICYmIGNoYW5nZS50ZXh0Lmxlbmd0aCA9PSAxICYmICFpc1dob2xlTGluZVVwZGF0ZShjbS5kb2MsIGNoYW5nZSkpXG4gICAgICB7IHJlZ0xpbmVDaGFuZ2UoY20sIGZyb20ubGluZSwgXCJ0ZXh0XCIpOyB9XG4gICAgZWxzZVxuICAgICAgeyByZWdDaGFuZ2UoY20sIGZyb20ubGluZSwgdG8ubGluZSArIDEsIGxlbmRpZmYpOyB9XG5cbiAgICB2YXIgY2hhbmdlc0hhbmRsZXIgPSBoYXNIYW5kbGVyKGNtLCBcImNoYW5nZXNcIiksIGNoYW5nZUhhbmRsZXIgPSBoYXNIYW5kbGVyKGNtLCBcImNoYW5nZVwiKTtcbiAgICBpZiAoY2hhbmdlSGFuZGxlciB8fCBjaGFuZ2VzSGFuZGxlcikge1xuICAgICAgdmFyIG9iaiA9IHtcbiAgICAgICAgZnJvbTogZnJvbSwgdG86IHRvLFxuICAgICAgICB0ZXh0OiBjaGFuZ2UudGV4dCxcbiAgICAgICAgcmVtb3ZlZDogY2hhbmdlLnJlbW92ZWQsXG4gICAgICAgIG9yaWdpbjogY2hhbmdlLm9yaWdpblxuICAgICAgfTtcbiAgICAgIGlmIChjaGFuZ2VIYW5kbGVyKSB7IHNpZ25hbExhdGVyKGNtLCBcImNoYW5nZVwiLCBjbSwgb2JqKTsgfVxuICAgICAgaWYgKGNoYW5nZXNIYW5kbGVyKSB7IChjbS5jdXJPcC5jaGFuZ2VPYmpzIHx8IChjbS5jdXJPcC5jaGFuZ2VPYmpzID0gW10pKS5wdXNoKG9iaik7IH1cbiAgICB9XG4gICAgY20uZGlzcGxheS5zZWxGb3JDb250ZXh0TWVudSA9IG51bGw7XG4gIH1cblxuICBmdW5jdGlvbiByZXBsYWNlUmFuZ2UoZG9jLCBjb2RlLCBmcm9tLCB0bywgb3JpZ2luKSB7XG4gICAgdmFyIGFzc2lnbjtcblxuICAgIGlmICghdG8pIHsgdG8gPSBmcm9tOyB9XG4gICAgaWYgKGNtcCh0bywgZnJvbSkgPCAwKSB7IChhc3NpZ24gPSBbdG8sIGZyb21dLCBmcm9tID0gYXNzaWduWzBdLCB0byA9IGFzc2lnblsxXSk7IH1cbiAgICBpZiAodHlwZW9mIGNvZGUgPT0gXCJzdHJpbmdcIikgeyBjb2RlID0gZG9jLnNwbGl0TGluZXMoY29kZSk7IH1cbiAgICBtYWtlQ2hhbmdlKGRvYywge2Zyb206IGZyb20sIHRvOiB0bywgdGV4dDogY29kZSwgb3JpZ2luOiBvcmlnaW59KTtcbiAgfVxuXG4gIC8vIFJlYmFzaW5nL3Jlc2V0dGluZyBoaXN0b3J5IHRvIGRlYWwgd2l0aCBleHRlcm5hbGx5LXNvdXJjZWQgY2hhbmdlc1xuXG4gIGZ1bmN0aW9uIHJlYmFzZUhpc3RTZWxTaW5nbGUocG9zLCBmcm9tLCB0bywgZGlmZikge1xuICAgIGlmICh0byA8IHBvcy5saW5lKSB7XG4gICAgICBwb3MubGluZSArPSBkaWZmO1xuICAgIH0gZWxzZSBpZiAoZnJvbSA8IHBvcy5saW5lKSB7XG4gICAgICBwb3MubGluZSA9IGZyb207XG4gICAgICBwb3MuY2ggPSAwO1xuICAgIH1cbiAgfVxuXG4gIC8vIFRyaWVzIHRvIHJlYmFzZSBhbiBhcnJheSBvZiBoaXN0b3J5IGV2ZW50cyBnaXZlbiBhIGNoYW5nZSBpbiB0aGVcbiAgLy8gZG9jdW1lbnQuIElmIHRoZSBjaGFuZ2UgdG91Y2hlcyB0aGUgc2FtZSBsaW5lcyBhcyB0aGUgZXZlbnQsIHRoZVxuICAvLyBldmVudCwgYW5kIGV2ZXJ5dGhpbmcgJ2JlaGluZCcgaXQsIGlzIGRpc2NhcmRlZC4gSWYgdGhlIGNoYW5nZSBpc1xuICAvLyBiZWZvcmUgdGhlIGV2ZW50LCB0aGUgZXZlbnQncyBwb3NpdGlvbnMgYXJlIHVwZGF0ZWQuIFVzZXMgYVxuICAvLyBjb3B5LW9uLXdyaXRlIHNjaGVtZSBmb3IgdGhlIHBvc2l0aW9ucywgdG8gYXZvaWQgaGF2aW5nIHRvXG4gIC8vIHJlYWxsb2NhdGUgdGhlbSBhbGwgb24gZXZlcnkgcmViYXNlLCBidXQgYWxzbyBhdm9pZCBwcm9ibGVtcyB3aXRoXG4gIC8vIHNoYXJlZCBwb3NpdGlvbiBvYmplY3RzIGJlaW5nIHVuc2FmZWx5IHVwZGF0ZWQuXG4gIGZ1bmN0aW9uIHJlYmFzZUhpc3RBcnJheShhcnJheSwgZnJvbSwgdG8sIGRpZmYpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgc3ViID0gYXJyYXlbaV0sIG9rID0gdHJ1ZTtcbiAgICAgIGlmIChzdWIucmFuZ2VzKSB7XG4gICAgICAgIGlmICghc3ViLmNvcGllZCkgeyBzdWIgPSBhcnJheVtpXSA9IHN1Yi5kZWVwQ29weSgpOyBzdWIuY29waWVkID0gdHJ1ZTsgfVxuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHN1Yi5yYW5nZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICByZWJhc2VIaXN0U2VsU2luZ2xlKHN1Yi5yYW5nZXNbal0uYW5jaG9yLCBmcm9tLCB0bywgZGlmZik7XG4gICAgICAgICAgcmViYXNlSGlzdFNlbFNpbmdsZShzdWIucmFuZ2VzW2pdLmhlYWQsIGZyb20sIHRvLCBkaWZmKTtcbiAgICAgICAgfVxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgZm9yICh2YXIgaiQxID0gMDsgaiQxIDwgc3ViLmNoYW5nZXMubGVuZ3RoOyArK2okMSkge1xuICAgICAgICB2YXIgY3VyID0gc3ViLmNoYW5nZXNbaiQxXTtcbiAgICAgICAgaWYgKHRvIDwgY3VyLmZyb20ubGluZSkge1xuICAgICAgICAgIGN1ci5mcm9tID0gUG9zKGN1ci5mcm9tLmxpbmUgKyBkaWZmLCBjdXIuZnJvbS5jaCk7XG4gICAgICAgICAgY3VyLnRvID0gUG9zKGN1ci50by5saW5lICsgZGlmZiwgY3VyLnRvLmNoKTtcbiAgICAgICAgfSBlbHNlIGlmIChmcm9tIDw9IGN1ci50by5saW5lKSB7XG4gICAgICAgICAgb2sgPSBmYWxzZTtcbiAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoIW9rKSB7XG4gICAgICAgIGFycmF5LnNwbGljZSgwLCBpICsgMSk7XG4gICAgICAgIGkgPSAwO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHJlYmFzZUhpc3QoaGlzdCwgY2hhbmdlKSB7XG4gICAgdmFyIGZyb20gPSBjaGFuZ2UuZnJvbS5saW5lLCB0byA9IGNoYW5nZS50by5saW5lLCBkaWZmID0gY2hhbmdlLnRleHQubGVuZ3RoIC0gKHRvIC0gZnJvbSkgLSAxO1xuICAgIHJlYmFzZUhpc3RBcnJheShoaXN0LmRvbmUsIGZyb20sIHRvLCBkaWZmKTtcbiAgICByZWJhc2VIaXN0QXJyYXkoaGlzdC51bmRvbmUsIGZyb20sIHRvLCBkaWZmKTtcbiAgfVxuXG4gIC8vIFV0aWxpdHkgZm9yIGFwcGx5aW5nIGEgY2hhbmdlIHRvIGEgbGluZSBieSBoYW5kbGUgb3IgbnVtYmVyLFxuICAvLyByZXR1cm5pbmcgdGhlIG51bWJlciBhbmQgb3B0aW9uYWxseSByZWdpc3RlcmluZyB0aGUgbGluZSBhc1xuICAvLyBjaGFuZ2VkLlxuICBmdW5jdGlvbiBjaGFuZ2VMaW5lKGRvYywgaGFuZGxlLCBjaGFuZ2VUeXBlLCBvcCkge1xuICAgIHZhciBubyA9IGhhbmRsZSwgbGluZSA9IGhhbmRsZTtcbiAgICBpZiAodHlwZW9mIGhhbmRsZSA9PSBcIm51bWJlclwiKSB7IGxpbmUgPSBnZXRMaW5lKGRvYywgY2xpcExpbmUoZG9jLCBoYW5kbGUpKTsgfVxuICAgIGVsc2UgeyBubyA9IGxpbmVObyhoYW5kbGUpOyB9XG4gICAgaWYgKG5vID09IG51bGwpIHsgcmV0dXJuIG51bGwgfVxuICAgIGlmIChvcChsaW5lLCBubykgJiYgZG9jLmNtKSB7IHJlZ0xpbmVDaGFuZ2UoZG9jLmNtLCBubywgY2hhbmdlVHlwZSk7IH1cbiAgICByZXR1cm4gbGluZVxuICB9XG5cbiAgLy8gVGhlIGRvY3VtZW50IGlzIHJlcHJlc2VudGVkIGFzIGEgQlRyZWUgY29uc2lzdGluZyBvZiBsZWF2ZXMsIHdpdGhcbiAgLy8gY2h1bmsgb2YgbGluZXMgaW4gdGhlbSwgYW5kIGJyYW5jaGVzLCB3aXRoIHVwIHRvIHRlbiBsZWF2ZXMgb3JcbiAgLy8gb3RoZXIgYnJhbmNoIG5vZGVzIGJlbG93IHRoZW0uIFRoZSB0b3Agbm9kZSBpcyBhbHdheXMgYSBicmFuY2hcbiAgLy8gbm9kZSwgYW5kIGlzIHRoZSBkb2N1bWVudCBvYmplY3QgaXRzZWxmIChtZWFuaW5nIGl0IGhhc1xuICAvLyBhZGRpdGlvbmFsIG1ldGhvZHMgYW5kIHByb3BlcnRpZXMpLlxuICAvL1xuICAvLyBBbGwgbm9kZXMgaGF2ZSBwYXJlbnQgbGlua3MuIFRoZSB0cmVlIGlzIHVzZWQgYm90aCB0byBnbyBmcm9tXG4gIC8vIGxpbmUgbnVtYmVycyB0byBsaW5lIG9iamVjdHMsIGFuZCB0byBnbyBmcm9tIG9iamVjdHMgdG8gbnVtYmVycy5cbiAgLy8gSXQgYWxzbyBpbmRleGVzIGJ5IGhlaWdodCwgYW5kIGlzIHVzZWQgdG8gY29udmVydCBiZXR3ZWVuIGhlaWdodFxuICAvLyBhbmQgbGluZSBvYmplY3QsIGFuZCB0byBmaW5kIHRoZSB0b3RhbCBoZWlnaHQgb2YgdGhlIGRvY3VtZW50LlxuICAvL1xuICAvLyBTZWUgYWxzbyBodHRwOi8vbWFyaWpuaGF2ZXJiZWtlLm5sL2Jsb2cvY29kZW1pcnJvci1saW5lLXRyZWUuaHRtbFxuXG4gIGZ1bmN0aW9uIExlYWZDaHVuayhsaW5lcykge1xuICAgIHRoaXMubGluZXMgPSBsaW5lcztcbiAgICB0aGlzLnBhcmVudCA9IG51bGw7XG4gICAgdmFyIGhlaWdodCA9IDA7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7ICsraSkge1xuICAgICAgbGluZXNbaV0ucGFyZW50ID0gdGhpcztcbiAgICAgIGhlaWdodCArPSBsaW5lc1tpXS5oZWlnaHQ7XG4gICAgfVxuICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICB9XG5cbiAgTGVhZkNodW5rLnByb3RvdHlwZSA9IHtcbiAgICBjaHVua1NpemU6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5saW5lcy5sZW5ndGggfSxcblxuICAgIC8vIFJlbW92ZSB0aGUgbiBsaW5lcyBhdCBvZmZzZXQgJ2F0Jy5cbiAgICByZW1vdmVJbm5lcjogZnVuY3Rpb24oYXQsIG4pIHtcbiAgICAgIGZvciAodmFyIGkgPSBhdCwgZSA9IGF0ICsgbjsgaSA8IGU7ICsraSkge1xuICAgICAgICB2YXIgbGluZSA9IHRoaXMubGluZXNbaV07XG4gICAgICAgIHRoaXMuaGVpZ2h0IC09IGxpbmUuaGVpZ2h0O1xuICAgICAgICBjbGVhblVwTGluZShsaW5lKTtcbiAgICAgICAgc2lnbmFsTGF0ZXIobGluZSwgXCJkZWxldGVcIik7XG4gICAgICB9XG4gICAgICB0aGlzLmxpbmVzLnNwbGljZShhdCwgbik7XG4gICAgfSxcblxuICAgIC8vIEhlbHBlciB1c2VkIHRvIGNvbGxhcHNlIGEgc21hbGwgYnJhbmNoIGludG8gYSBzaW5nbGUgbGVhZi5cbiAgICBjb2xsYXBzZTogZnVuY3Rpb24obGluZXMpIHtcbiAgICAgIGxpbmVzLnB1c2guYXBwbHkobGluZXMsIHRoaXMubGluZXMpO1xuICAgIH0sXG5cbiAgICAvLyBJbnNlcnQgdGhlIGdpdmVuIGFycmF5IG9mIGxpbmVzIGF0IG9mZnNldCAnYXQnLCBjb3VudCB0aGVtIGFzXG4gICAgLy8gaGF2aW5nIHRoZSBnaXZlbiBoZWlnaHQuXG4gICAgaW5zZXJ0SW5uZXI6IGZ1bmN0aW9uKGF0LCBsaW5lcywgaGVpZ2h0KSB7XG4gICAgICB0aGlzLmhlaWdodCArPSBoZWlnaHQ7XG4gICAgICB0aGlzLmxpbmVzID0gdGhpcy5saW5lcy5zbGljZSgwLCBhdCkuY29uY2F0KGxpbmVzKS5jb25jYXQodGhpcy5saW5lcy5zbGljZShhdCkpO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7ICsraSkgeyBsaW5lc1tpXS5wYXJlbnQgPSB0aGlzOyB9XG4gICAgfSxcblxuICAgIC8vIFVzZWQgdG8gaXRlcmF0ZSBvdmVyIGEgcGFydCBvZiB0aGUgdHJlZS5cbiAgICBpdGVyTjogZnVuY3Rpb24oYXQsIG4sIG9wKSB7XG4gICAgICBmb3IgKHZhciBlID0gYXQgKyBuOyBhdCA8IGU7ICsrYXQpXG4gICAgICAgIHsgaWYgKG9wKHRoaXMubGluZXNbYXRdKSkgeyByZXR1cm4gdHJ1ZSB9IH1cbiAgICB9XG4gIH07XG5cbiAgZnVuY3Rpb24gQnJhbmNoQ2h1bmsoY2hpbGRyZW4pIHtcbiAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gICAgdmFyIHNpemUgPSAwLCBoZWlnaHQgPSAwO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBjaCA9IGNoaWxkcmVuW2ldO1xuICAgICAgc2l6ZSArPSBjaC5jaHVua1NpemUoKTsgaGVpZ2h0ICs9IGNoLmhlaWdodDtcbiAgICAgIGNoLnBhcmVudCA9IHRoaXM7XG4gICAgfVxuICAgIHRoaXMuc2l6ZSA9IHNpemU7XG4gICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgdGhpcy5wYXJlbnQgPSBudWxsO1xuICB9XG5cbiAgQnJhbmNoQ2h1bmsucHJvdG90eXBlID0ge1xuICAgIGNodW5rU2l6ZTogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLnNpemUgfSxcblxuICAgIHJlbW92ZUlubmVyOiBmdW5jdGlvbihhdCwgbikge1xuICAgICAgdGhpcy5zaXplIC09IG47XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY2hpbGRyZW4ubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIGNoaWxkID0gdGhpcy5jaGlsZHJlbltpXSwgc3ogPSBjaGlsZC5jaHVua1NpemUoKTtcbiAgICAgICAgaWYgKGF0IDwgc3opIHtcbiAgICAgICAgICB2YXIgcm0gPSBNYXRoLm1pbihuLCBzeiAtIGF0KSwgb2xkSGVpZ2h0ID0gY2hpbGQuaGVpZ2h0O1xuICAgICAgICAgIGNoaWxkLnJlbW92ZUlubmVyKGF0LCBybSk7XG4gICAgICAgICAgdGhpcy5oZWlnaHQgLT0gb2xkSGVpZ2h0IC0gY2hpbGQuaGVpZ2h0O1xuICAgICAgICAgIGlmIChzeiA9PSBybSkgeyB0aGlzLmNoaWxkcmVuLnNwbGljZShpLS0sIDEpOyBjaGlsZC5wYXJlbnQgPSBudWxsOyB9XG4gICAgICAgICAgaWYgKChuIC09IHJtKSA9PSAwKSB7IGJyZWFrIH1cbiAgICAgICAgICBhdCA9IDA7XG4gICAgICAgIH0gZWxzZSB7IGF0IC09IHN6OyB9XG4gICAgICB9XG4gICAgICAvLyBJZiB0aGUgcmVzdWx0IGlzIHNtYWxsZXIgdGhhbiAyNSBsaW5lcywgZW5zdXJlIHRoYXQgaXQgaXMgYVxuICAgICAgLy8gc2luZ2xlIGxlYWYgbm9kZS5cbiAgICAgIGlmICh0aGlzLnNpemUgLSBuIDwgMjUgJiZcbiAgICAgICAgICAodGhpcy5jaGlsZHJlbi5sZW5ndGggPiAxIHx8ICEodGhpcy5jaGlsZHJlblswXSBpbnN0YW5jZW9mIExlYWZDaHVuaykpKSB7XG4gICAgICAgIHZhciBsaW5lcyA9IFtdO1xuICAgICAgICB0aGlzLmNvbGxhcHNlKGxpbmVzKTtcbiAgICAgICAgdGhpcy5jaGlsZHJlbiA9IFtuZXcgTGVhZkNodW5rKGxpbmVzKV07XG4gICAgICAgIHRoaXMuY2hpbGRyZW5bMF0ucGFyZW50ID0gdGhpcztcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgY29sbGFwc2U6IGZ1bmN0aW9uKGxpbmVzKSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY2hpbGRyZW4ubGVuZ3RoOyArK2kpIHsgdGhpcy5jaGlsZHJlbltpXS5jb2xsYXBzZShsaW5lcyk7IH1cbiAgICB9LFxuXG4gICAgaW5zZXJ0SW5uZXI6IGZ1bmN0aW9uKGF0LCBsaW5lcywgaGVpZ2h0KSB7XG4gICAgICB0aGlzLnNpemUgKz0gbGluZXMubGVuZ3RoO1xuICAgICAgdGhpcy5oZWlnaHQgKz0gaGVpZ2h0O1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNoaWxkcmVuLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHZhciBjaGlsZCA9IHRoaXMuY2hpbGRyZW5baV0sIHN6ID0gY2hpbGQuY2h1bmtTaXplKCk7XG4gICAgICAgIGlmIChhdCA8PSBzeikge1xuICAgICAgICAgIGNoaWxkLmluc2VydElubmVyKGF0LCBsaW5lcywgaGVpZ2h0KTtcbiAgICAgICAgICBpZiAoY2hpbGQubGluZXMgJiYgY2hpbGQubGluZXMubGVuZ3RoID4gNTApIHtcbiAgICAgICAgICAgIC8vIFRvIGF2b2lkIG1lbW9yeSB0aHJhc2hpbmcgd2hlbiBjaGlsZC5saW5lcyBpcyBodWdlIChlLmcuIGZpcnN0IHZpZXcgb2YgYSBsYXJnZSBmaWxlKSwgaXQncyBuZXZlciBzcGxpY2VkLlxuICAgICAgICAgICAgLy8gSW5zdGVhZCwgc21hbGwgc2xpY2VzIGFyZSB0YWtlbi4gVGhleSdyZSB0YWtlbiBpbiBvcmRlciBiZWNhdXNlIHNlcXVlbnRpYWwgbWVtb3J5IGFjY2Vzc2VzIGFyZSBmYXN0ZXN0LlxuICAgICAgICAgICAgdmFyIHJlbWFpbmluZyA9IGNoaWxkLmxpbmVzLmxlbmd0aCAlIDI1ICsgMjU7XG4gICAgICAgICAgICBmb3IgKHZhciBwb3MgPSByZW1haW5pbmc7IHBvcyA8IGNoaWxkLmxpbmVzLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgdmFyIGxlYWYgPSBuZXcgTGVhZkNodW5rKGNoaWxkLmxpbmVzLnNsaWNlKHBvcywgcG9zICs9IDI1KSk7XG4gICAgICAgICAgICAgIGNoaWxkLmhlaWdodCAtPSBsZWFmLmhlaWdodDtcbiAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbi5zcGxpY2UoKytpLCAwLCBsZWFmKTtcbiAgICAgICAgICAgICAgbGVhZi5wYXJlbnQgPSB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2hpbGQubGluZXMgPSBjaGlsZC5saW5lcy5zbGljZSgwLCByZW1haW5pbmcpO1xuICAgICAgICAgICAgdGhpcy5tYXliZVNwaWxsKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIH1cbiAgICAgICAgYXQgLT0gc3o7XG4gICAgICB9XG4gICAgfSxcblxuICAgIC8vIFdoZW4gYSBub2RlIGhhcyBncm93biwgY2hlY2sgd2hldGhlciBpdCBzaG91bGQgYmUgc3BsaXQuXG4gICAgbWF5YmVTcGlsbDogZnVuY3Rpb24oKSB7XG4gICAgICBpZiAodGhpcy5jaGlsZHJlbi5sZW5ndGggPD0gMTApIHsgcmV0dXJuIH1cbiAgICAgIHZhciBtZSA9IHRoaXM7XG4gICAgICBkbyB7XG4gICAgICAgIHZhciBzcGlsbGVkID0gbWUuY2hpbGRyZW4uc3BsaWNlKG1lLmNoaWxkcmVuLmxlbmd0aCAtIDUsIDUpO1xuICAgICAgICB2YXIgc2libGluZyA9IG5ldyBCcmFuY2hDaHVuayhzcGlsbGVkKTtcbiAgICAgICAgaWYgKCFtZS5wYXJlbnQpIHsgLy8gQmVjb21lIHRoZSBwYXJlbnQgbm9kZVxuICAgICAgICAgIHZhciBjb3B5ID0gbmV3IEJyYW5jaENodW5rKG1lLmNoaWxkcmVuKTtcbiAgICAgICAgICBjb3B5LnBhcmVudCA9IG1lO1xuICAgICAgICAgIG1lLmNoaWxkcmVuID0gW2NvcHksIHNpYmxpbmddO1xuICAgICAgICAgIG1lID0gY29weTtcbiAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG1lLnNpemUgLT0gc2libGluZy5zaXplO1xuICAgICAgICAgIG1lLmhlaWdodCAtPSBzaWJsaW5nLmhlaWdodDtcbiAgICAgICAgICB2YXIgbXlJbmRleCA9IGluZGV4T2YobWUucGFyZW50LmNoaWxkcmVuLCBtZSk7XG4gICAgICAgICAgbWUucGFyZW50LmNoaWxkcmVuLnNwbGljZShteUluZGV4ICsgMSwgMCwgc2libGluZyk7XG4gICAgICAgIH1cbiAgICAgICAgc2libGluZy5wYXJlbnQgPSBtZS5wYXJlbnQ7XG4gICAgICB9IHdoaWxlIChtZS5jaGlsZHJlbi5sZW5ndGggPiAxMClcbiAgICAgIG1lLnBhcmVudC5tYXliZVNwaWxsKCk7XG4gICAgfSxcblxuICAgIGl0ZXJOOiBmdW5jdGlvbihhdCwgbiwgb3ApIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jaGlsZHJlbi5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgY2hpbGQgPSB0aGlzLmNoaWxkcmVuW2ldLCBzeiA9IGNoaWxkLmNodW5rU2l6ZSgpO1xuICAgICAgICBpZiAoYXQgPCBzeikge1xuICAgICAgICAgIHZhciB1c2VkID0gTWF0aC5taW4obiwgc3ogLSBhdCk7XG4gICAgICAgICAgaWYgKGNoaWxkLml0ZXJOKGF0LCB1c2VkLCBvcCkpIHsgcmV0dXJuIHRydWUgfVxuICAgICAgICAgIGlmICgobiAtPSB1c2VkKSA9PSAwKSB7IGJyZWFrIH1cbiAgICAgICAgICBhdCA9IDA7XG4gICAgICAgIH0gZWxzZSB7IGF0IC09IHN6OyB9XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIC8vIExpbmUgd2lkZ2V0cyBhcmUgYmxvY2sgZWxlbWVudHMgZGlzcGxheWVkIGFib3ZlIG9yIGJlbG93IGEgbGluZS5cblxuICB2YXIgTGluZVdpZGdldCA9IGZ1bmN0aW9uKGRvYywgbm9kZSwgb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zKSB7IGZvciAodmFyIG9wdCBpbiBvcHRpb25zKSB7IGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KG9wdCkpXG4gICAgICB7IHRoaXNbb3B0XSA9IG9wdGlvbnNbb3B0XTsgfSB9IH1cbiAgICB0aGlzLmRvYyA9IGRvYztcbiAgICB0aGlzLm5vZGUgPSBub2RlO1xuICB9O1xuXG4gIExpbmVXaWRnZXQucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBjbSA9IHRoaXMuZG9jLmNtLCB3cyA9IHRoaXMubGluZS53aWRnZXRzLCBsaW5lID0gdGhpcy5saW5lLCBubyA9IGxpbmVObyhsaW5lKTtcbiAgICBpZiAobm8gPT0gbnVsbCB8fCAhd3MpIHsgcmV0dXJuIH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHdzLmxlbmd0aDsgKytpKSB7IGlmICh3c1tpXSA9PSB0aGlzKSB7IHdzLnNwbGljZShpLS0sIDEpOyB9IH1cbiAgICBpZiAoIXdzLmxlbmd0aCkgeyBsaW5lLndpZGdldHMgPSBudWxsOyB9XG4gICAgdmFyIGhlaWdodCA9IHdpZGdldEhlaWdodCh0aGlzKTtcbiAgICB1cGRhdGVMaW5lSGVpZ2h0KGxpbmUsIE1hdGgubWF4KDAsIGxpbmUuaGVpZ2h0IC0gaGVpZ2h0KSk7XG4gICAgaWYgKGNtKSB7XG4gICAgICBydW5Jbk9wKGNtLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGFkanVzdFNjcm9sbFdoZW5BYm92ZVZpc2libGUoY20sIGxpbmUsIC1oZWlnaHQpO1xuICAgICAgICByZWdMaW5lQ2hhbmdlKGNtLCBubywgXCJ3aWRnZXRcIik7XG4gICAgICB9KTtcbiAgICAgIHNpZ25hbExhdGVyKGNtLCBcImxpbmVXaWRnZXRDbGVhcmVkXCIsIGNtLCB0aGlzLCBubyk7XG4gICAgfVxuICB9O1xuXG4gIExpbmVXaWRnZXQucHJvdG90eXBlLmNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgdGhpcyQxID0gdGhpcztcblxuICAgIHZhciBvbGRIID0gdGhpcy5oZWlnaHQsIGNtID0gdGhpcy5kb2MuY20sIGxpbmUgPSB0aGlzLmxpbmU7XG4gICAgdGhpcy5oZWlnaHQgPSBudWxsO1xuICAgIHZhciBkaWZmID0gd2lkZ2V0SGVpZ2h0KHRoaXMpIC0gb2xkSDtcbiAgICBpZiAoIWRpZmYpIHsgcmV0dXJuIH1cbiAgICBpZiAoIWxpbmVJc0hpZGRlbih0aGlzLmRvYywgbGluZSkpIHsgdXBkYXRlTGluZUhlaWdodChsaW5lLCBsaW5lLmhlaWdodCArIGRpZmYpOyB9XG4gICAgaWYgKGNtKSB7XG4gICAgICBydW5Jbk9wKGNtLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNtLmN1ck9wLmZvcmNlVXBkYXRlID0gdHJ1ZTtcbiAgICAgICAgYWRqdXN0U2Nyb2xsV2hlbkFib3ZlVmlzaWJsZShjbSwgbGluZSwgZGlmZik7XG4gICAgICAgIHNpZ25hbExhdGVyKGNtLCBcImxpbmVXaWRnZXRDaGFuZ2VkXCIsIGNtLCB0aGlzJDEsIGxpbmVObyhsaW5lKSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH07XG4gIGV2ZW50TWl4aW4oTGluZVdpZGdldCk7XG5cbiAgZnVuY3Rpb24gYWRqdXN0U2Nyb2xsV2hlbkFib3ZlVmlzaWJsZShjbSwgbGluZSwgZGlmZikge1xuICAgIGlmIChoZWlnaHRBdExpbmUobGluZSkgPCAoKGNtLmN1ck9wICYmIGNtLmN1ck9wLnNjcm9sbFRvcCkgfHwgY20uZG9jLnNjcm9sbFRvcCkpXG4gICAgICB7IGFkZFRvU2Nyb2xsVG9wKGNtLCBkaWZmKTsgfVxuICB9XG5cbiAgZnVuY3Rpb24gYWRkTGluZVdpZGdldChkb2MsIGhhbmRsZSwgbm9kZSwgb3B0aW9ucykge1xuICAgIHZhciB3aWRnZXQgPSBuZXcgTGluZVdpZGdldChkb2MsIG5vZGUsIG9wdGlvbnMpO1xuICAgIHZhciBjbSA9IGRvYy5jbTtcbiAgICBpZiAoY20gJiYgd2lkZ2V0Lm5vSFNjcm9sbCkgeyBjbS5kaXNwbGF5LmFsaWduV2lkZ2V0cyA9IHRydWU7IH1cbiAgICBjaGFuZ2VMaW5lKGRvYywgaGFuZGxlLCBcIndpZGdldFwiLCBmdW5jdGlvbiAobGluZSkge1xuICAgICAgdmFyIHdpZGdldHMgPSBsaW5lLndpZGdldHMgfHwgKGxpbmUud2lkZ2V0cyA9IFtdKTtcbiAgICAgIGlmICh3aWRnZXQuaW5zZXJ0QXQgPT0gbnVsbCkgeyB3aWRnZXRzLnB1c2god2lkZ2V0KTsgfVxuICAgICAgZWxzZSB7IHdpZGdldHMuc3BsaWNlKE1hdGgubWluKHdpZGdldHMubGVuZ3RoLCBNYXRoLm1heCgwLCB3aWRnZXQuaW5zZXJ0QXQpKSwgMCwgd2lkZ2V0KTsgfVxuICAgICAgd2lkZ2V0LmxpbmUgPSBsaW5lO1xuICAgICAgaWYgKGNtICYmICFsaW5lSXNIaWRkZW4oZG9jLCBsaW5lKSkge1xuICAgICAgICB2YXIgYWJvdmVWaXNpYmxlID0gaGVpZ2h0QXRMaW5lKGxpbmUpIDwgZG9jLnNjcm9sbFRvcDtcbiAgICAgICAgdXBkYXRlTGluZUhlaWdodChsaW5lLCBsaW5lLmhlaWdodCArIHdpZGdldEhlaWdodCh3aWRnZXQpKTtcbiAgICAgICAgaWYgKGFib3ZlVmlzaWJsZSkgeyBhZGRUb1Njcm9sbFRvcChjbSwgd2lkZ2V0LmhlaWdodCk7IH1cbiAgICAgICAgY20uY3VyT3AuZm9yY2VVcGRhdGUgPSB0cnVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWVcbiAgICB9KTtcbiAgICBpZiAoY20pIHsgc2lnbmFsTGF0ZXIoY20sIFwibGluZVdpZGdldEFkZGVkXCIsIGNtLCB3aWRnZXQsIHR5cGVvZiBoYW5kbGUgPT0gXCJudW1iZXJcIiA/IGhhbmRsZSA6IGxpbmVObyhoYW5kbGUpKTsgfVxuICAgIHJldHVybiB3aWRnZXRcbiAgfVxuXG4gIC8vIFRFWFRNQVJLRVJTXG5cbiAgLy8gQ3JlYXRlZCB3aXRoIG1hcmtUZXh0IGFuZCBzZXRCb29rbWFyayBtZXRob2RzLiBBIFRleHRNYXJrZXIgaXMgYVxuICAvLyBoYW5kbGUgdGhhdCBjYW4gYmUgdXNlZCB0byBjbGVhciBvciBmaW5kIGEgbWFya2VkIHBvc2l0aW9uIGluIHRoZVxuICAvLyBkb2N1bWVudC4gTGluZSBvYmplY3RzIGhvbGQgYXJyYXlzIChtYXJrZWRTcGFucykgY29udGFpbmluZ1xuICAvLyB7ZnJvbSwgdG8sIG1hcmtlcn0gb2JqZWN0IHBvaW50aW5nIHRvIHN1Y2ggbWFya2VyIG9iamVjdHMsIGFuZFxuICAvLyBpbmRpY2F0aW5nIHRoYXQgc3VjaCBhIG1hcmtlciBpcyBwcmVzZW50IG9uIHRoYXQgbGluZS4gTXVsdGlwbGVcbiAgLy8gbGluZXMgbWF5IHBvaW50IHRvIHRoZSBzYW1lIG1hcmtlciB3aGVuIGl0IHNwYW5zIGFjcm9zcyBsaW5lcy5cbiAgLy8gVGhlIHNwYW5zIHdpbGwgaGF2ZSBudWxsIGZvciB0aGVpciBmcm9tL3RvIHByb3BlcnRpZXMgd2hlbiB0aGVcbiAgLy8gbWFya2VyIGNvbnRpbnVlcyBiZXlvbmQgdGhlIHN0YXJ0L2VuZCBvZiB0aGUgbGluZS4gTWFya2VycyBoYXZlXG4gIC8vIGxpbmtzIGJhY2sgdG8gdGhlIGxpbmVzIHRoZXkgY3VycmVudGx5IHRvdWNoLlxuXG4gIC8vIENvbGxhcHNlZCBtYXJrZXJzIGhhdmUgdW5pcXVlIGlkcywgaW4gb3JkZXIgdG8gYmUgYWJsZSB0byBvcmRlclxuICAvLyB0aGVtLCB3aGljaCBpcyBuZWVkZWQgZm9yIHVuaXF1ZWx5IGRldGVybWluaW5nIGFuIG91dGVyIG1hcmtlclxuICAvLyB3aGVuIHRoZXkgb3ZlcmxhcCAodGhleSBtYXkgbmVzdCwgYnV0IG5vdCBwYXJ0aWFsbHkgb3ZlcmxhcCkuXG4gIHZhciBuZXh0TWFya2VySWQgPSAwO1xuXG4gIHZhciBUZXh0TWFya2VyID0gZnVuY3Rpb24oZG9jLCB0eXBlKSB7XG4gICAgdGhpcy5saW5lcyA9IFtdO1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5kb2MgPSBkb2M7XG4gICAgdGhpcy5pZCA9ICsrbmV4dE1hcmtlcklkO1xuICB9O1xuXG4gIC8vIENsZWFyIHRoZSBtYXJrZXIuXG4gIFRleHRNYXJrZXIucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLmV4cGxpY2l0bHlDbGVhcmVkKSB7IHJldHVybiB9XG4gICAgdmFyIGNtID0gdGhpcy5kb2MuY20sIHdpdGhPcCA9IGNtICYmICFjbS5jdXJPcDtcbiAgICBpZiAod2l0aE9wKSB7IHN0YXJ0T3BlcmF0aW9uKGNtKTsgfVxuICAgIGlmIChoYXNIYW5kbGVyKHRoaXMsIFwiY2xlYXJcIikpIHtcbiAgICAgIHZhciBmb3VuZCA9IHRoaXMuZmluZCgpO1xuICAgICAgaWYgKGZvdW5kKSB7IHNpZ25hbExhdGVyKHRoaXMsIFwiY2xlYXJcIiwgZm91bmQuZnJvbSwgZm91bmQudG8pOyB9XG4gICAgfVxuICAgIHZhciBtaW4gPSBudWxsLCBtYXggPSBudWxsO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5saW5lcy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGxpbmUgPSB0aGlzLmxpbmVzW2ldO1xuICAgICAgdmFyIHNwYW4gPSBnZXRNYXJrZWRTcGFuRm9yKGxpbmUubWFya2VkU3BhbnMsIHRoaXMpO1xuICAgICAgaWYgKGNtICYmICF0aGlzLmNvbGxhcHNlZCkgeyByZWdMaW5lQ2hhbmdlKGNtLCBsaW5lTm8obGluZSksIFwidGV4dFwiKTsgfVxuICAgICAgZWxzZSBpZiAoY20pIHtcbiAgICAgICAgaWYgKHNwYW4udG8gIT0gbnVsbCkgeyBtYXggPSBsaW5lTm8obGluZSk7IH1cbiAgICAgICAgaWYgKHNwYW4uZnJvbSAhPSBudWxsKSB7IG1pbiA9IGxpbmVObyhsaW5lKTsgfVxuICAgICAgfVxuICAgICAgbGluZS5tYXJrZWRTcGFucyA9IHJlbW92ZU1hcmtlZFNwYW4obGluZS5tYXJrZWRTcGFucywgc3Bhbik7XG4gICAgICBpZiAoc3Bhbi5mcm9tID09IG51bGwgJiYgdGhpcy5jb2xsYXBzZWQgJiYgIWxpbmVJc0hpZGRlbih0aGlzLmRvYywgbGluZSkgJiYgY20pXG4gICAgICAgIHsgdXBkYXRlTGluZUhlaWdodChsaW5lLCB0ZXh0SGVpZ2h0KGNtLmRpc3BsYXkpKTsgfVxuICAgIH1cbiAgICBpZiAoY20gJiYgdGhpcy5jb2xsYXBzZWQgJiYgIWNtLm9wdGlvbnMubGluZVdyYXBwaW5nKSB7IGZvciAodmFyIGkkMSA9IDA7IGkkMSA8IHRoaXMubGluZXMubGVuZ3RoOyArK2kkMSkge1xuICAgICAgdmFyIHZpc3VhbCA9IHZpc3VhbExpbmUodGhpcy5saW5lc1tpJDFdKSwgbGVuID0gbGluZUxlbmd0aCh2aXN1YWwpO1xuICAgICAgaWYgKGxlbiA+IGNtLmRpc3BsYXkubWF4TGluZUxlbmd0aCkge1xuICAgICAgICBjbS5kaXNwbGF5Lm1heExpbmUgPSB2aXN1YWw7XG4gICAgICAgIGNtLmRpc3BsYXkubWF4TGluZUxlbmd0aCA9IGxlbjtcbiAgICAgICAgY20uZGlzcGxheS5tYXhMaW5lQ2hhbmdlZCA9IHRydWU7XG4gICAgICB9XG4gICAgfSB9XG5cbiAgICBpZiAobWluICE9IG51bGwgJiYgY20gJiYgdGhpcy5jb2xsYXBzZWQpIHsgcmVnQ2hhbmdlKGNtLCBtaW4sIG1heCArIDEpOyB9XG4gICAgdGhpcy5saW5lcy5sZW5ndGggPSAwO1xuICAgIHRoaXMuZXhwbGljaXRseUNsZWFyZWQgPSB0cnVlO1xuICAgIGlmICh0aGlzLmF0b21pYyAmJiB0aGlzLmRvYy5jYW50RWRpdCkge1xuICAgICAgdGhpcy5kb2MuY2FudEVkaXQgPSBmYWxzZTtcbiAgICAgIGlmIChjbSkgeyByZUNoZWNrU2VsZWN0aW9uKGNtLmRvYyk7IH1cbiAgICB9XG4gICAgaWYgKGNtKSB7IHNpZ25hbExhdGVyKGNtLCBcIm1hcmtlckNsZWFyZWRcIiwgY20sIHRoaXMsIG1pbiwgbWF4KTsgfVxuICAgIGlmICh3aXRoT3ApIHsgZW5kT3BlcmF0aW9uKGNtKTsgfVxuICAgIGlmICh0aGlzLnBhcmVudCkgeyB0aGlzLnBhcmVudC5jbGVhcigpOyB9XG4gIH07XG5cbiAgLy8gRmluZCB0aGUgcG9zaXRpb24gb2YgdGhlIG1hcmtlciBpbiB0aGUgZG9jdW1lbnQuIFJldHVybnMgYSB7ZnJvbSxcbiAgLy8gdG99IG9iamVjdCBieSBkZWZhdWx0LiBTaWRlIGNhbiBiZSBwYXNzZWQgdG8gZ2V0IGEgc3BlY2lmaWMgc2lkZVxuICAvLyAtLSAwIChib3RoKSwgLTEgKGxlZnQpLCBvciAxIChyaWdodCkuIFdoZW4gbGluZU9iaiBpcyB0cnVlLCB0aGVcbiAgLy8gUG9zIG9iamVjdHMgcmV0dXJuZWQgY29udGFpbiBhIGxpbmUgb2JqZWN0LCByYXRoZXIgdGhhbiBhIGxpbmVcbiAgLy8gbnVtYmVyICh1c2VkIHRvIHByZXZlbnQgbG9va2luZyB1cCB0aGUgc2FtZSBsaW5lIHR3aWNlKS5cbiAgVGV4dE1hcmtlci5wcm90b3R5cGUuZmluZCA9IGZ1bmN0aW9uIChzaWRlLCBsaW5lT2JqKSB7XG4gICAgaWYgKHNpZGUgPT0gbnVsbCAmJiB0aGlzLnR5cGUgPT0gXCJib29rbWFya1wiKSB7IHNpZGUgPSAxOyB9XG4gICAgdmFyIGZyb20sIHRvO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5saW5lcy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGxpbmUgPSB0aGlzLmxpbmVzW2ldO1xuICAgICAgdmFyIHNwYW4gPSBnZXRNYXJrZWRTcGFuRm9yKGxpbmUubWFya2VkU3BhbnMsIHRoaXMpO1xuICAgICAgaWYgKHNwYW4uZnJvbSAhPSBudWxsKSB7XG4gICAgICAgIGZyb20gPSBQb3MobGluZU9iaiA/IGxpbmUgOiBsaW5lTm8obGluZSksIHNwYW4uZnJvbSk7XG4gICAgICAgIGlmIChzaWRlID09IC0xKSB7IHJldHVybiBmcm9tIH1cbiAgICAgIH1cbiAgICAgIGlmIChzcGFuLnRvICE9IG51bGwpIHtcbiAgICAgICAgdG8gPSBQb3MobGluZU9iaiA/IGxpbmUgOiBsaW5lTm8obGluZSksIHNwYW4udG8pO1xuICAgICAgICBpZiAoc2lkZSA9PSAxKSB7IHJldHVybiB0byB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmcm9tICYmIHtmcm9tOiBmcm9tLCB0bzogdG99XG4gIH07XG5cbiAgLy8gU2lnbmFscyB0aGF0IHRoZSBtYXJrZXIncyB3aWRnZXQgY2hhbmdlZCwgYW5kIHN1cnJvdW5kaW5nIGxheW91dFxuICAvLyBzaG91bGQgYmUgcmVjb21wdXRlZC5cbiAgVGV4dE1hcmtlci5wcm90b3R5cGUuY2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciB0aGlzJDEgPSB0aGlzO1xuXG4gICAgdmFyIHBvcyA9IHRoaXMuZmluZCgtMSwgdHJ1ZSksIHdpZGdldCA9IHRoaXMsIGNtID0gdGhpcy5kb2MuY207XG4gICAgaWYgKCFwb3MgfHwgIWNtKSB7IHJldHVybiB9XG4gICAgcnVuSW5PcChjbSwgZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIGxpbmUgPSBwb3MubGluZSwgbGluZU4gPSBsaW5lTm8ocG9zLmxpbmUpO1xuICAgICAgdmFyIHZpZXcgPSBmaW5kVmlld0ZvckxpbmUoY20sIGxpbmVOKTtcbiAgICAgIGlmICh2aWV3KSB7XG4gICAgICAgIGNsZWFyTGluZU1lYXN1cmVtZW50Q2FjaGVGb3Iodmlldyk7XG4gICAgICAgIGNtLmN1ck9wLnNlbGVjdGlvbkNoYW5nZWQgPSBjbS5jdXJPcC5mb3JjZVVwZGF0ZSA9IHRydWU7XG4gICAgICB9XG4gICAgICBjbS5jdXJPcC51cGRhdGVNYXhMaW5lID0gdHJ1ZTtcbiAgICAgIGlmICghbGluZUlzSGlkZGVuKHdpZGdldC5kb2MsIGxpbmUpICYmIHdpZGdldC5oZWlnaHQgIT0gbnVsbCkge1xuICAgICAgICB2YXIgb2xkSGVpZ2h0ID0gd2lkZ2V0LmhlaWdodDtcbiAgICAgICAgd2lkZ2V0LmhlaWdodCA9IG51bGw7XG4gICAgICAgIHZhciBkSGVpZ2h0ID0gd2lkZ2V0SGVpZ2h0KHdpZGdldCkgLSBvbGRIZWlnaHQ7XG4gICAgICAgIGlmIChkSGVpZ2h0KVxuICAgICAgICAgIHsgdXBkYXRlTGluZUhlaWdodChsaW5lLCBsaW5lLmhlaWdodCArIGRIZWlnaHQpOyB9XG4gICAgICB9XG4gICAgICBzaWduYWxMYXRlcihjbSwgXCJtYXJrZXJDaGFuZ2VkXCIsIGNtLCB0aGlzJDEpO1xuICAgIH0pO1xuICB9O1xuXG4gIFRleHRNYXJrZXIucHJvdG90eXBlLmF0dGFjaExpbmUgPSBmdW5jdGlvbiAobGluZSkge1xuICAgIGlmICghdGhpcy5saW5lcy5sZW5ndGggJiYgdGhpcy5kb2MuY20pIHtcbiAgICAgIHZhciBvcCA9IHRoaXMuZG9jLmNtLmN1ck9wO1xuICAgICAgaWYgKCFvcC5tYXliZUhpZGRlbk1hcmtlcnMgfHwgaW5kZXhPZihvcC5tYXliZUhpZGRlbk1hcmtlcnMsIHRoaXMpID09IC0xKVxuICAgICAgICB7IChvcC5tYXliZVVuaGlkZGVuTWFya2VycyB8fCAob3AubWF5YmVVbmhpZGRlbk1hcmtlcnMgPSBbXSkpLnB1c2godGhpcyk7IH1cbiAgICB9XG4gICAgdGhpcy5saW5lcy5wdXNoKGxpbmUpO1xuICB9O1xuXG4gIFRleHRNYXJrZXIucHJvdG90eXBlLmRldGFjaExpbmUgPSBmdW5jdGlvbiAobGluZSkge1xuICAgIHRoaXMubGluZXMuc3BsaWNlKGluZGV4T2YodGhpcy5saW5lcywgbGluZSksIDEpO1xuICAgIGlmICghdGhpcy5saW5lcy5sZW5ndGggJiYgdGhpcy5kb2MuY20pIHtcbiAgICAgIHZhciBvcCA9IHRoaXMuZG9jLmNtLmN1ck9wXG4gICAgICA7KG9wLm1heWJlSGlkZGVuTWFya2VycyB8fCAob3AubWF5YmVIaWRkZW5NYXJrZXJzID0gW10pKS5wdXNoKHRoaXMpO1xuICAgIH1cbiAgfTtcbiAgZXZlbnRNaXhpbihUZXh0TWFya2VyKTtcblxuICAvLyBDcmVhdGUgYSBtYXJrZXIsIHdpcmUgaXQgdXAgdG8gdGhlIHJpZ2h0IGxpbmVzLCBhbmRcbiAgZnVuY3Rpb24gbWFya1RleHQoZG9jLCBmcm9tLCB0bywgb3B0aW9ucywgdHlwZSkge1xuICAgIC8vIFNoYXJlZCBtYXJrZXJzIChhY3Jvc3MgbGlua2VkIGRvY3VtZW50cykgYXJlIGhhbmRsZWQgc2VwYXJhdGVseVxuICAgIC8vIChtYXJrVGV4dFNoYXJlZCB3aWxsIGNhbGwgb3V0IHRvIHRoaXMgYWdhaW4sIG9uY2UgcGVyXG4gICAgLy8gZG9jdW1lbnQpLlxuICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMuc2hhcmVkKSB7IHJldHVybiBtYXJrVGV4dFNoYXJlZChkb2MsIGZyb20sIHRvLCBvcHRpb25zLCB0eXBlKSB9XG4gICAgLy8gRW5zdXJlIHdlIGFyZSBpbiBhbiBvcGVyYXRpb24uXG4gICAgaWYgKGRvYy5jbSAmJiAhZG9jLmNtLmN1ck9wKSB7IHJldHVybiBvcGVyYXRpb24oZG9jLmNtLCBtYXJrVGV4dCkoZG9jLCBmcm9tLCB0bywgb3B0aW9ucywgdHlwZSkgfVxuXG4gICAgdmFyIG1hcmtlciA9IG5ldyBUZXh0TWFya2VyKGRvYywgdHlwZSksIGRpZmYgPSBjbXAoZnJvbSwgdG8pO1xuICAgIGlmIChvcHRpb25zKSB7IGNvcHlPYmoob3B0aW9ucywgbWFya2VyLCBmYWxzZSk7IH1cbiAgICAvLyBEb24ndCBjb25uZWN0IGVtcHR5IG1hcmtlcnMgdW5sZXNzIGNsZWFyV2hlbkVtcHR5IGlzIGZhbHNlXG4gICAgaWYgKGRpZmYgPiAwIHx8IGRpZmYgPT0gMCAmJiBtYXJrZXIuY2xlYXJXaGVuRW1wdHkgIT09IGZhbHNlKVxuICAgICAgeyByZXR1cm4gbWFya2VyIH1cbiAgICBpZiAobWFya2VyLnJlcGxhY2VkV2l0aCkge1xuICAgICAgLy8gU2hvd2luZyB1cCBhcyBhIHdpZGdldCBpbXBsaWVzIGNvbGxhcHNlZCAod2lkZ2V0IHJlcGxhY2VzIHRleHQpXG4gICAgICBtYXJrZXIuY29sbGFwc2VkID0gdHJ1ZTtcbiAgICAgIG1hcmtlci53aWRnZXROb2RlID0gZWx0UChcInNwYW5cIiwgW21hcmtlci5yZXBsYWNlZFdpdGhdLCBcIkNvZGVNaXJyb3Itd2lkZ2V0XCIpO1xuICAgICAgaWYgKCFvcHRpb25zLmhhbmRsZU1vdXNlRXZlbnRzKSB7IG1hcmtlci53aWRnZXROb2RlLnNldEF0dHJpYnV0ZShcImNtLWlnbm9yZS1ldmVudHNcIiwgXCJ0cnVlXCIpOyB9XG4gICAgICBpZiAob3B0aW9ucy5pbnNlcnRMZWZ0KSB7IG1hcmtlci53aWRnZXROb2RlLmluc2VydExlZnQgPSB0cnVlOyB9XG4gICAgfVxuICAgIGlmIChtYXJrZXIuY29sbGFwc2VkKSB7XG4gICAgICBpZiAoY29uZmxpY3RpbmdDb2xsYXBzZWRSYW5nZShkb2MsIGZyb20ubGluZSwgZnJvbSwgdG8sIG1hcmtlcikgfHxcbiAgICAgICAgICBmcm9tLmxpbmUgIT0gdG8ubGluZSAmJiBjb25mbGljdGluZ0NvbGxhcHNlZFJhbmdlKGRvYywgdG8ubGluZSwgZnJvbSwgdG8sIG1hcmtlcikpXG4gICAgICAgIHsgdGhyb3cgbmV3IEVycm9yKFwiSW5zZXJ0aW5nIGNvbGxhcHNlZCBtYXJrZXIgcGFydGlhbGx5IG92ZXJsYXBwaW5nIGFuIGV4aXN0aW5nIG9uZVwiKSB9XG4gICAgICBzZWVDb2xsYXBzZWRTcGFucygpO1xuICAgIH1cblxuICAgIGlmIChtYXJrZXIuYWRkVG9IaXN0b3J5KVxuICAgICAgeyBhZGRDaGFuZ2VUb0hpc3RvcnkoZG9jLCB7ZnJvbTogZnJvbSwgdG86IHRvLCBvcmlnaW46IFwibWFya1RleHRcIn0sIGRvYy5zZWwsIE5hTik7IH1cblxuICAgIHZhciBjdXJMaW5lID0gZnJvbS5saW5lLCBjbSA9IGRvYy5jbSwgdXBkYXRlTWF4TGluZTtcbiAgICBkb2MuaXRlcihjdXJMaW5lLCB0by5saW5lICsgMSwgZnVuY3Rpb24gKGxpbmUpIHtcbiAgICAgIGlmIChjbSAmJiBtYXJrZXIuY29sbGFwc2VkICYmICFjbS5vcHRpb25zLmxpbmVXcmFwcGluZyAmJiB2aXN1YWxMaW5lKGxpbmUpID09IGNtLmRpc3BsYXkubWF4TGluZSlcbiAgICAgICAgeyB1cGRhdGVNYXhMaW5lID0gdHJ1ZTsgfVxuICAgICAgaWYgKG1hcmtlci5jb2xsYXBzZWQgJiYgY3VyTGluZSAhPSBmcm9tLmxpbmUpIHsgdXBkYXRlTGluZUhlaWdodChsaW5lLCAwKTsgfVxuICAgICAgYWRkTWFya2VkU3BhbihsaW5lLCBuZXcgTWFya2VkU3BhbihtYXJrZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1ckxpbmUgPT0gZnJvbS5saW5lID8gZnJvbS5jaCA6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1ckxpbmUgPT0gdG8ubGluZSA/IHRvLmNoIDogbnVsbCksIGRvYy5jbSAmJiBkb2MuY20uY3VyT3ApO1xuICAgICAgKytjdXJMaW5lO1xuICAgIH0pO1xuICAgIC8vIGxpbmVJc0hpZGRlbiBkZXBlbmRzIG9uIHRoZSBwcmVzZW5jZSBvZiB0aGUgc3BhbnMsIHNvIG5lZWRzIGEgc2Vjb25kIHBhc3NcbiAgICBpZiAobWFya2VyLmNvbGxhcHNlZCkgeyBkb2MuaXRlcihmcm9tLmxpbmUsIHRvLmxpbmUgKyAxLCBmdW5jdGlvbiAobGluZSkge1xuICAgICAgaWYgKGxpbmVJc0hpZGRlbihkb2MsIGxpbmUpKSB7IHVwZGF0ZUxpbmVIZWlnaHQobGluZSwgMCk7IH1cbiAgICB9KTsgfVxuXG4gICAgaWYgKG1hcmtlci5jbGVhck9uRW50ZXIpIHsgb24obWFya2VyLCBcImJlZm9yZUN1cnNvckVudGVyXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIG1hcmtlci5jbGVhcigpOyB9KTsgfVxuXG4gICAgaWYgKG1hcmtlci5yZWFkT25seSkge1xuICAgICAgc2VlUmVhZE9ubHlTcGFucygpO1xuICAgICAgaWYgKGRvYy5oaXN0b3J5LmRvbmUubGVuZ3RoIHx8IGRvYy5oaXN0b3J5LnVuZG9uZS5sZW5ndGgpXG4gICAgICAgIHsgZG9jLmNsZWFySGlzdG9yeSgpOyB9XG4gICAgfVxuICAgIGlmIChtYXJrZXIuY29sbGFwc2VkKSB7XG4gICAgICBtYXJrZXIuaWQgPSArK25leHRNYXJrZXJJZDtcbiAgICAgIG1hcmtlci5hdG9taWMgPSB0cnVlO1xuICAgIH1cbiAgICBpZiAoY20pIHtcbiAgICAgIC8vIFN5bmMgZWRpdG9yIHN0YXRlXG4gICAgICBpZiAodXBkYXRlTWF4TGluZSkgeyBjbS5jdXJPcC51cGRhdGVNYXhMaW5lID0gdHJ1ZTsgfVxuICAgICAgaWYgKG1hcmtlci5jb2xsYXBzZWQpXG4gICAgICAgIHsgcmVnQ2hhbmdlKGNtLCBmcm9tLmxpbmUsIHRvLmxpbmUgKyAxKTsgfVxuICAgICAgZWxzZSBpZiAobWFya2VyLmNsYXNzTmFtZSB8fCBtYXJrZXIuc3RhcnRTdHlsZSB8fCBtYXJrZXIuZW5kU3R5bGUgfHwgbWFya2VyLmNzcyB8fFxuICAgICAgICAgICAgICAgbWFya2VyLmF0dHJpYnV0ZXMgfHwgbWFya2VyLnRpdGxlKVxuICAgICAgICB7IGZvciAodmFyIGkgPSBmcm9tLmxpbmU7IGkgPD0gdG8ubGluZTsgaSsrKSB7IHJlZ0xpbmVDaGFuZ2UoY20sIGksIFwidGV4dFwiKTsgfSB9XG4gICAgICBpZiAobWFya2VyLmF0b21pYykgeyByZUNoZWNrU2VsZWN0aW9uKGNtLmRvYyk7IH1cbiAgICAgIHNpZ25hbExhdGVyKGNtLCBcIm1hcmtlckFkZGVkXCIsIGNtLCBtYXJrZXIpO1xuICAgIH1cbiAgICByZXR1cm4gbWFya2VyXG4gIH1cblxuICAvLyBTSEFSRUQgVEVYVE1BUktFUlNcblxuICAvLyBBIHNoYXJlZCBtYXJrZXIgc3BhbnMgbXVsdGlwbGUgbGlua2VkIGRvY3VtZW50cy4gSXQgaXNcbiAgLy8gaW1wbGVtZW50ZWQgYXMgYSBtZXRhLW1hcmtlci1vYmplY3QgY29udHJvbGxpbmcgbXVsdGlwbGUgbm9ybWFsXG4gIC8vIG1hcmtlcnMuXG4gIHZhciBTaGFyZWRUZXh0TWFya2VyID0gZnVuY3Rpb24obWFya2VycywgcHJpbWFyeSkge1xuICAgIHRoaXMubWFya2VycyA9IG1hcmtlcnM7XG4gICAgdGhpcy5wcmltYXJ5ID0gcHJpbWFyeTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1hcmtlcnMubGVuZ3RoOyArK2kpXG4gICAgICB7IG1hcmtlcnNbaV0ucGFyZW50ID0gdGhpczsgfVxuICB9O1xuXG4gIFNoYXJlZFRleHRNYXJrZXIucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLmV4cGxpY2l0bHlDbGVhcmVkKSB7IHJldHVybiB9XG4gICAgdGhpcy5leHBsaWNpdGx5Q2xlYXJlZCA9IHRydWU7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLm1hcmtlcnMubGVuZ3RoOyArK2kpXG4gICAgICB7IHRoaXMubWFya2Vyc1tpXS5jbGVhcigpOyB9XG4gICAgc2lnbmFsTGF0ZXIodGhpcywgXCJjbGVhclwiKTtcbiAgfTtcblxuICBTaGFyZWRUZXh0TWFya2VyLnByb3RvdHlwZS5maW5kID0gZnVuY3Rpb24gKHNpZGUsIGxpbmVPYmopIHtcbiAgICByZXR1cm4gdGhpcy5wcmltYXJ5LmZpbmQoc2lkZSwgbGluZU9iailcbiAgfTtcbiAgZXZlbnRNaXhpbihTaGFyZWRUZXh0TWFya2VyKTtcblxuICBmdW5jdGlvbiBtYXJrVGV4dFNoYXJlZChkb2MsIGZyb20sIHRvLCBvcHRpb25zLCB0eXBlKSB7XG4gICAgb3B0aW9ucyA9IGNvcHlPYmoob3B0aW9ucyk7XG4gICAgb3B0aW9ucy5zaGFyZWQgPSBmYWxzZTtcbiAgICB2YXIgbWFya2VycyA9IFttYXJrVGV4dChkb2MsIGZyb20sIHRvLCBvcHRpb25zLCB0eXBlKV0sIHByaW1hcnkgPSBtYXJrZXJzWzBdO1xuICAgIHZhciB3aWRnZXQgPSBvcHRpb25zLndpZGdldE5vZGU7XG4gICAgbGlua2VkRG9jcyhkb2MsIGZ1bmN0aW9uIChkb2MpIHtcbiAgICAgIGlmICh3aWRnZXQpIHsgb3B0aW9ucy53aWRnZXROb2RlID0gd2lkZ2V0LmNsb25lTm9kZSh0cnVlKTsgfVxuICAgICAgbWFya2Vycy5wdXNoKG1hcmtUZXh0KGRvYywgY2xpcFBvcyhkb2MsIGZyb20pLCBjbGlwUG9zKGRvYywgdG8pLCBvcHRpb25zLCB0eXBlKSk7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRvYy5saW5rZWQubGVuZ3RoOyArK2kpXG4gICAgICAgIHsgaWYgKGRvYy5saW5rZWRbaV0uaXNQYXJlbnQpIHsgcmV0dXJuIH0gfVxuICAgICAgcHJpbWFyeSA9IGxzdChtYXJrZXJzKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IFNoYXJlZFRleHRNYXJrZXIobWFya2VycywgcHJpbWFyeSlcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpbmRTaGFyZWRNYXJrZXJzKGRvYykge1xuICAgIHJldHVybiBkb2MuZmluZE1hcmtzKFBvcyhkb2MuZmlyc3QsIDApLCBkb2MuY2xpcFBvcyhQb3MoZG9jLmxhc3RMaW5lKCkpKSwgZnVuY3Rpb24gKG0pIHsgcmV0dXJuIG0ucGFyZW50OyB9KVxuICB9XG5cbiAgZnVuY3Rpb24gY29weVNoYXJlZE1hcmtlcnMoZG9jLCBtYXJrZXJzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtYXJrZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgbWFya2VyID0gbWFya2Vyc1tpXSwgcG9zID0gbWFya2VyLmZpbmQoKTtcbiAgICAgIHZhciBtRnJvbSA9IGRvYy5jbGlwUG9zKHBvcy5mcm9tKSwgbVRvID0gZG9jLmNsaXBQb3MocG9zLnRvKTtcbiAgICAgIGlmIChjbXAobUZyb20sIG1UbykpIHtcbiAgICAgICAgdmFyIHN1Yk1hcmsgPSBtYXJrVGV4dChkb2MsIG1Gcm9tLCBtVG8sIG1hcmtlci5wcmltYXJ5LCBtYXJrZXIucHJpbWFyeS50eXBlKTtcbiAgICAgICAgbWFya2VyLm1hcmtlcnMucHVzaChzdWJNYXJrKTtcbiAgICAgICAgc3ViTWFyay5wYXJlbnQgPSBtYXJrZXI7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gZGV0YWNoU2hhcmVkTWFya2VycyhtYXJrZXJzKSB7XG4gICAgdmFyIGxvb3AgPSBmdW5jdGlvbiAoIGkgKSB7XG4gICAgICB2YXIgbWFya2VyID0gbWFya2Vyc1tpXSwgbGlua2VkID0gW21hcmtlci5wcmltYXJ5LmRvY107XG4gICAgICBsaW5rZWREb2NzKG1hcmtlci5wcmltYXJ5LmRvYywgZnVuY3Rpb24gKGQpIHsgcmV0dXJuIGxpbmtlZC5wdXNoKGQpOyB9KTtcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWFya2VyLm1hcmtlcnMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgdmFyIHN1Yk1hcmtlciA9IG1hcmtlci5tYXJrZXJzW2pdO1xuICAgICAgICBpZiAoaW5kZXhPZihsaW5rZWQsIHN1Yk1hcmtlci5kb2MpID09IC0xKSB7XG4gICAgICAgICAgc3ViTWFya2VyLnBhcmVudCA9IG51bGw7XG4gICAgICAgICAgbWFya2VyLm1hcmtlcnMuc3BsaWNlKGotLSwgMSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtYXJrZXJzLmxlbmd0aDsgaSsrKSBsb29wKCBpICk7XG4gIH1cblxuICB2YXIgbmV4dERvY0lkID0gMDtcbiAgdmFyIERvYyA9IGZ1bmN0aW9uKHRleHQsIG1vZGUsIGZpcnN0TGluZSwgbGluZVNlcCwgZGlyZWN0aW9uKSB7XG4gICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIERvYykpIHsgcmV0dXJuIG5ldyBEb2ModGV4dCwgbW9kZSwgZmlyc3RMaW5lLCBsaW5lU2VwLCBkaXJlY3Rpb24pIH1cbiAgICBpZiAoZmlyc3RMaW5lID09IG51bGwpIHsgZmlyc3RMaW5lID0gMDsgfVxuXG4gICAgQnJhbmNoQ2h1bmsuY2FsbCh0aGlzLCBbbmV3IExlYWZDaHVuayhbbmV3IExpbmUoXCJcIiwgbnVsbCldKV0pO1xuICAgIHRoaXMuZmlyc3QgPSBmaXJzdExpbmU7XG4gICAgdGhpcy5zY3JvbGxUb3AgPSB0aGlzLnNjcm9sbExlZnQgPSAwO1xuICAgIHRoaXMuY2FudEVkaXQgPSBmYWxzZTtcbiAgICB0aGlzLmNsZWFuR2VuZXJhdGlvbiA9IDE7XG4gICAgdGhpcy5tb2RlRnJvbnRpZXIgPSB0aGlzLmhpZ2hsaWdodEZyb250aWVyID0gZmlyc3RMaW5lO1xuICAgIHZhciBzdGFydCA9IFBvcyhmaXJzdExpbmUsIDApO1xuICAgIHRoaXMuc2VsID0gc2ltcGxlU2VsZWN0aW9uKHN0YXJ0KTtcbiAgICB0aGlzLmhpc3RvcnkgPSBuZXcgSGlzdG9yeShudWxsKTtcbiAgICB0aGlzLmlkID0gKytuZXh0RG9jSWQ7XG4gICAgdGhpcy5tb2RlT3B0aW9uID0gbW9kZTtcbiAgICB0aGlzLmxpbmVTZXAgPSBsaW5lU2VwO1xuICAgIHRoaXMuZGlyZWN0aW9uID0gKGRpcmVjdGlvbiA9PSBcInJ0bFwiKSA/IFwicnRsXCIgOiBcImx0clwiO1xuICAgIHRoaXMuZXh0ZW5kID0gZmFsc2U7XG5cbiAgICBpZiAodHlwZW9mIHRleHQgPT0gXCJzdHJpbmdcIikgeyB0ZXh0ID0gdGhpcy5zcGxpdExpbmVzKHRleHQpOyB9XG4gICAgdXBkYXRlRG9jKHRoaXMsIHtmcm9tOiBzdGFydCwgdG86IHN0YXJ0LCB0ZXh0OiB0ZXh0fSk7XG4gICAgc2V0U2VsZWN0aW9uKHRoaXMsIHNpbXBsZVNlbGVjdGlvbihzdGFydCksIHNlbF9kb250U2Nyb2xsKTtcbiAgfTtcblxuICBEb2MucHJvdG90eXBlID0gY3JlYXRlT2JqKEJyYW5jaENodW5rLnByb3RvdHlwZSwge1xuICAgIGNvbnN0cnVjdG9yOiBEb2MsXG4gICAgLy8gSXRlcmF0ZSBvdmVyIHRoZSBkb2N1bWVudC4gU3VwcG9ydHMgdHdvIGZvcm1zIC0tIHdpdGggb25seSBvbmVcbiAgICAvLyBhcmd1bWVudCwgaXQgY2FsbHMgdGhhdCBmb3IgZWFjaCBsaW5lIGluIHRoZSBkb2N1bWVudC4gV2l0aFxuICAgIC8vIHRocmVlLCBpdCBpdGVyYXRlcyBvdmVyIHRoZSByYW5nZSBnaXZlbiBieSB0aGUgZmlyc3QgdHdvICh3aXRoXG4gICAgLy8gdGhlIHNlY29uZCBiZWluZyBub24taW5jbHVzaXZlKS5cbiAgICBpdGVyOiBmdW5jdGlvbihmcm9tLCB0bywgb3ApIHtcbiAgICAgIGlmIChvcCkgeyB0aGlzLml0ZXJOKGZyb20gLSB0aGlzLmZpcnN0LCB0byAtIGZyb20sIG9wKTsgfVxuICAgICAgZWxzZSB7IHRoaXMuaXRlck4odGhpcy5maXJzdCwgdGhpcy5maXJzdCArIHRoaXMuc2l6ZSwgZnJvbSk7IH1cbiAgICB9LFxuXG4gICAgLy8gTm9uLXB1YmxpYyBpbnRlcmZhY2UgZm9yIGFkZGluZyBhbmQgcmVtb3ZpbmcgbGluZXMuXG4gICAgaW5zZXJ0OiBmdW5jdGlvbihhdCwgbGluZXMpIHtcbiAgICAgIHZhciBoZWlnaHQgPSAwO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7ICsraSkgeyBoZWlnaHQgKz0gbGluZXNbaV0uaGVpZ2h0OyB9XG4gICAgICB0aGlzLmluc2VydElubmVyKGF0IC0gdGhpcy5maXJzdCwgbGluZXMsIGhlaWdodCk7XG4gICAgfSxcbiAgICByZW1vdmU6IGZ1bmN0aW9uKGF0LCBuKSB7IHRoaXMucmVtb3ZlSW5uZXIoYXQgLSB0aGlzLmZpcnN0LCBuKTsgfSxcblxuICAgIC8vIEZyb20gaGVyZSwgdGhlIG1ldGhvZHMgYXJlIHBhcnQgb2YgdGhlIHB1YmxpYyBpbnRlcmZhY2UuIE1vc3RcbiAgICAvLyBhcmUgYWxzbyBhdmFpbGFibGUgZnJvbSBDb2RlTWlycm9yIChlZGl0b3IpIGluc3RhbmNlcy5cblxuICAgIGdldFZhbHVlOiBmdW5jdGlvbihsaW5lU2VwKSB7XG4gICAgICB2YXIgbGluZXMgPSBnZXRMaW5lcyh0aGlzLCB0aGlzLmZpcnN0LCB0aGlzLmZpcnN0ICsgdGhpcy5zaXplKTtcbiAgICAgIGlmIChsaW5lU2VwID09PSBmYWxzZSkgeyByZXR1cm4gbGluZXMgfVxuICAgICAgcmV0dXJuIGxpbmVzLmpvaW4obGluZVNlcCB8fCB0aGlzLmxpbmVTZXBhcmF0b3IoKSlcbiAgICB9LFxuICAgIHNldFZhbHVlOiBkb2NNZXRob2RPcChmdW5jdGlvbihjb2RlKSB7XG4gICAgICB2YXIgdG9wID0gUG9zKHRoaXMuZmlyc3QsIDApLCBsYXN0ID0gdGhpcy5maXJzdCArIHRoaXMuc2l6ZSAtIDE7XG4gICAgICBtYWtlQ2hhbmdlKHRoaXMsIHtmcm9tOiB0b3AsIHRvOiBQb3MobGFzdCwgZ2V0TGluZSh0aGlzLCBsYXN0KS50ZXh0Lmxlbmd0aCksXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0OiB0aGlzLnNwbGl0TGluZXMoY29kZSksIG9yaWdpbjogXCJzZXRWYWx1ZVwiLCBmdWxsOiB0cnVlfSwgdHJ1ZSk7XG4gICAgICBpZiAodGhpcy5jbSkgeyBzY3JvbGxUb0Nvb3Jkcyh0aGlzLmNtLCAwLCAwKTsgfVxuICAgICAgc2V0U2VsZWN0aW9uKHRoaXMsIHNpbXBsZVNlbGVjdGlvbih0b3ApLCBzZWxfZG9udFNjcm9sbCk7XG4gICAgfSksXG4gICAgcmVwbGFjZVJhbmdlOiBmdW5jdGlvbihjb2RlLCBmcm9tLCB0bywgb3JpZ2luKSB7XG4gICAgICBmcm9tID0gY2xpcFBvcyh0aGlzLCBmcm9tKTtcbiAgICAgIHRvID0gdG8gPyBjbGlwUG9zKHRoaXMsIHRvKSA6IGZyb207XG4gICAgICByZXBsYWNlUmFuZ2UodGhpcywgY29kZSwgZnJvbSwgdG8sIG9yaWdpbik7XG4gICAgfSxcbiAgICBnZXRSYW5nZTogZnVuY3Rpb24oZnJvbSwgdG8sIGxpbmVTZXApIHtcbiAgICAgIHZhciBsaW5lcyA9IGdldEJldHdlZW4odGhpcywgY2xpcFBvcyh0aGlzLCBmcm9tKSwgY2xpcFBvcyh0aGlzLCB0bykpO1xuICAgICAgaWYgKGxpbmVTZXAgPT09IGZhbHNlKSB7IHJldHVybiBsaW5lcyB9XG4gICAgICBpZiAobGluZVNlcCA9PT0gJycpIHsgcmV0dXJuIGxpbmVzLmpvaW4oJycpIH1cbiAgICAgIHJldHVybiBsaW5lcy5qb2luKGxpbmVTZXAgfHwgdGhpcy5saW5lU2VwYXJhdG9yKCkpXG4gICAgfSxcblxuICAgIGdldExpbmU6IGZ1bmN0aW9uKGxpbmUpIHt2YXIgbCA9IHRoaXMuZ2V0TGluZUhhbmRsZShsaW5lKTsgcmV0dXJuIGwgJiYgbC50ZXh0fSxcblxuICAgIGdldExpbmVIYW5kbGU6IGZ1bmN0aW9uKGxpbmUpIHtpZiAoaXNMaW5lKHRoaXMsIGxpbmUpKSB7IHJldHVybiBnZXRMaW5lKHRoaXMsIGxpbmUpIH19LFxuICAgIGdldExpbmVOdW1iZXI6IGZ1bmN0aW9uKGxpbmUpIHtyZXR1cm4gbGluZU5vKGxpbmUpfSxcblxuICAgIGdldExpbmVIYW5kbGVWaXN1YWxTdGFydDogZnVuY3Rpb24obGluZSkge1xuICAgICAgaWYgKHR5cGVvZiBsaW5lID09IFwibnVtYmVyXCIpIHsgbGluZSA9IGdldExpbmUodGhpcywgbGluZSk7IH1cbiAgICAgIHJldHVybiB2aXN1YWxMaW5lKGxpbmUpXG4gICAgfSxcblxuICAgIGxpbmVDb3VudDogZnVuY3Rpb24oKSB7cmV0dXJuIHRoaXMuc2l6ZX0sXG4gICAgZmlyc3RMaW5lOiBmdW5jdGlvbigpIHtyZXR1cm4gdGhpcy5maXJzdH0sXG4gICAgbGFzdExpbmU6IGZ1bmN0aW9uKCkge3JldHVybiB0aGlzLmZpcnN0ICsgdGhpcy5zaXplIC0gMX0sXG5cbiAgICBjbGlwUG9zOiBmdW5jdGlvbihwb3MpIHtyZXR1cm4gY2xpcFBvcyh0aGlzLCBwb3MpfSxcblxuICAgIGdldEN1cnNvcjogZnVuY3Rpb24oc3RhcnQpIHtcbiAgICAgIHZhciByYW5nZSA9IHRoaXMuc2VsLnByaW1hcnkoKSwgcG9zO1xuICAgICAgaWYgKHN0YXJ0ID09IG51bGwgfHwgc3RhcnQgPT0gXCJoZWFkXCIpIHsgcG9zID0gcmFuZ2UuaGVhZDsgfVxuICAgICAgZWxzZSBpZiAoc3RhcnQgPT0gXCJhbmNob3JcIikgeyBwb3MgPSByYW5nZS5hbmNob3I7IH1cbiAgICAgIGVsc2UgaWYgKHN0YXJ0ID09IFwiZW5kXCIgfHwgc3RhcnQgPT0gXCJ0b1wiIHx8IHN0YXJ0ID09PSBmYWxzZSkgeyBwb3MgPSByYW5nZS50bygpOyB9XG4gICAgICBlbHNlIHsgcG9zID0gcmFuZ2UuZnJvbSgpOyB9XG4gICAgICByZXR1cm4gcG9zXG4gICAgfSxcbiAgICBsaXN0U2VsZWN0aW9uczogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLnNlbC5yYW5nZXMgfSxcbiAgICBzb21ldGhpbmdTZWxlY3RlZDogZnVuY3Rpb24oKSB7cmV0dXJuIHRoaXMuc2VsLnNvbWV0aGluZ1NlbGVjdGVkKCl9LFxuXG4gICAgc2V0Q3Vyc29yOiBkb2NNZXRob2RPcChmdW5jdGlvbihsaW5lLCBjaCwgb3B0aW9ucykge1xuICAgICAgc2V0U2ltcGxlU2VsZWN0aW9uKHRoaXMsIGNsaXBQb3ModGhpcywgdHlwZW9mIGxpbmUgPT0gXCJudW1iZXJcIiA/IFBvcyhsaW5lLCBjaCB8fCAwKSA6IGxpbmUpLCBudWxsLCBvcHRpb25zKTtcbiAgICB9KSxcbiAgICBzZXRTZWxlY3Rpb246IGRvY01ldGhvZE9wKGZ1bmN0aW9uKGFuY2hvciwgaGVhZCwgb3B0aW9ucykge1xuICAgICAgc2V0U2ltcGxlU2VsZWN0aW9uKHRoaXMsIGNsaXBQb3ModGhpcywgYW5jaG9yKSwgY2xpcFBvcyh0aGlzLCBoZWFkIHx8IGFuY2hvciksIG9wdGlvbnMpO1xuICAgIH0pLFxuICAgIGV4dGVuZFNlbGVjdGlvbjogZG9jTWV0aG9kT3AoZnVuY3Rpb24oaGVhZCwgb3RoZXIsIG9wdGlvbnMpIHtcbiAgICAgIGV4dGVuZFNlbGVjdGlvbih0aGlzLCBjbGlwUG9zKHRoaXMsIGhlYWQpLCBvdGhlciAmJiBjbGlwUG9zKHRoaXMsIG90aGVyKSwgb3B0aW9ucyk7XG4gICAgfSksXG4gICAgZXh0ZW5kU2VsZWN0aW9uczogZG9jTWV0aG9kT3AoZnVuY3Rpb24oaGVhZHMsIG9wdGlvbnMpIHtcbiAgICAgIGV4dGVuZFNlbGVjdGlvbnModGhpcywgY2xpcFBvc0FycmF5KHRoaXMsIGhlYWRzKSwgb3B0aW9ucyk7XG4gICAgfSksXG4gICAgZXh0ZW5kU2VsZWN0aW9uc0J5OiBkb2NNZXRob2RPcChmdW5jdGlvbihmLCBvcHRpb25zKSB7XG4gICAgICB2YXIgaGVhZHMgPSBtYXAodGhpcy5zZWwucmFuZ2VzLCBmKTtcbiAgICAgIGV4dGVuZFNlbGVjdGlvbnModGhpcywgY2xpcFBvc0FycmF5KHRoaXMsIGhlYWRzKSwgb3B0aW9ucyk7XG4gICAgfSksXG4gICAgc2V0U2VsZWN0aW9uczogZG9jTWV0aG9kT3AoZnVuY3Rpb24ocmFuZ2VzLCBwcmltYXJ5LCBvcHRpb25zKSB7XG4gICAgICBpZiAoIXJhbmdlcy5sZW5ndGgpIHsgcmV0dXJuIH1cbiAgICAgIHZhciBvdXQgPSBbXTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKVxuICAgICAgICB7IG91dFtpXSA9IG5ldyBSYW5nZShjbGlwUG9zKHRoaXMsIHJhbmdlc1tpXS5hbmNob3IpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpcFBvcyh0aGlzLCByYW5nZXNbaV0uaGVhZCB8fCByYW5nZXNbaV0uYW5jaG9yKSk7IH1cbiAgICAgIGlmIChwcmltYXJ5ID09IG51bGwpIHsgcHJpbWFyeSA9IE1hdGgubWluKHJhbmdlcy5sZW5ndGggLSAxLCB0aGlzLnNlbC5wcmltSW5kZXgpOyB9XG4gICAgICBzZXRTZWxlY3Rpb24odGhpcywgbm9ybWFsaXplU2VsZWN0aW9uKHRoaXMuY20sIG91dCwgcHJpbWFyeSksIG9wdGlvbnMpO1xuICAgIH0pLFxuICAgIGFkZFNlbGVjdGlvbjogZG9jTWV0aG9kT3AoZnVuY3Rpb24oYW5jaG9yLCBoZWFkLCBvcHRpb25zKSB7XG4gICAgICB2YXIgcmFuZ2VzID0gdGhpcy5zZWwucmFuZ2VzLnNsaWNlKDApO1xuICAgICAgcmFuZ2VzLnB1c2gobmV3IFJhbmdlKGNsaXBQb3ModGhpcywgYW5jaG9yKSwgY2xpcFBvcyh0aGlzLCBoZWFkIHx8IGFuY2hvcikpKTtcbiAgICAgIHNldFNlbGVjdGlvbih0aGlzLCBub3JtYWxpemVTZWxlY3Rpb24odGhpcy5jbSwgcmFuZ2VzLCByYW5nZXMubGVuZ3RoIC0gMSksIG9wdGlvbnMpO1xuICAgIH0pLFxuXG4gICAgZ2V0U2VsZWN0aW9uOiBmdW5jdGlvbihsaW5lU2VwKSB7XG4gICAgICB2YXIgcmFuZ2VzID0gdGhpcy5zZWwucmFuZ2VzLCBsaW5lcztcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBzZWwgPSBnZXRCZXR3ZWVuKHRoaXMsIHJhbmdlc1tpXS5mcm9tKCksIHJhbmdlc1tpXS50bygpKTtcbiAgICAgICAgbGluZXMgPSBsaW5lcyA/IGxpbmVzLmNvbmNhdChzZWwpIDogc2VsO1xuICAgICAgfVxuICAgICAgaWYgKGxpbmVTZXAgPT09IGZhbHNlKSB7IHJldHVybiBsaW5lcyB9XG4gICAgICBlbHNlIHsgcmV0dXJuIGxpbmVzLmpvaW4obGluZVNlcCB8fCB0aGlzLmxpbmVTZXBhcmF0b3IoKSkgfVxuICAgIH0sXG4gICAgZ2V0U2VsZWN0aW9uczogZnVuY3Rpb24obGluZVNlcCkge1xuICAgICAgdmFyIHBhcnRzID0gW10sIHJhbmdlcyA9IHRoaXMuc2VsLnJhbmdlcztcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBzZWwgPSBnZXRCZXR3ZWVuKHRoaXMsIHJhbmdlc1tpXS5mcm9tKCksIHJhbmdlc1tpXS50bygpKTtcbiAgICAgICAgaWYgKGxpbmVTZXAgIT09IGZhbHNlKSB7IHNlbCA9IHNlbC5qb2luKGxpbmVTZXAgfHwgdGhpcy5saW5lU2VwYXJhdG9yKCkpOyB9XG4gICAgICAgIHBhcnRzW2ldID0gc2VsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHBhcnRzXG4gICAgfSxcbiAgICByZXBsYWNlU2VsZWN0aW9uOiBmdW5jdGlvbihjb2RlLCBjb2xsYXBzZSwgb3JpZ2luKSB7XG4gICAgICB2YXIgZHVwID0gW107XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuc2VsLnJhbmdlcy5sZW5ndGg7IGkrKylcbiAgICAgICAgeyBkdXBbaV0gPSBjb2RlOyB9XG4gICAgICB0aGlzLnJlcGxhY2VTZWxlY3Rpb25zKGR1cCwgY29sbGFwc2UsIG9yaWdpbiB8fCBcIitpbnB1dFwiKTtcbiAgICB9LFxuICAgIHJlcGxhY2VTZWxlY3Rpb25zOiBkb2NNZXRob2RPcChmdW5jdGlvbihjb2RlLCBjb2xsYXBzZSwgb3JpZ2luKSB7XG4gICAgICB2YXIgY2hhbmdlcyA9IFtdLCBzZWwgPSB0aGlzLnNlbDtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2VsLnJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcmFuZ2UgPSBzZWwucmFuZ2VzW2ldO1xuICAgICAgICBjaGFuZ2VzW2ldID0ge2Zyb206IHJhbmdlLmZyb20oKSwgdG86IHJhbmdlLnRvKCksIHRleHQ6IHRoaXMuc3BsaXRMaW5lcyhjb2RlW2ldKSwgb3JpZ2luOiBvcmlnaW59O1xuICAgICAgfVxuICAgICAgdmFyIG5ld1NlbCA9IGNvbGxhcHNlICYmIGNvbGxhcHNlICE9IFwiZW5kXCIgJiYgY29tcHV0ZVJlcGxhY2VkU2VsKHRoaXMsIGNoYW5nZXMsIGNvbGxhcHNlKTtcbiAgICAgIGZvciAodmFyIGkkMSA9IGNoYW5nZXMubGVuZ3RoIC0gMTsgaSQxID49IDA7IGkkMS0tKVxuICAgICAgICB7IG1ha2VDaGFuZ2UodGhpcywgY2hhbmdlc1tpJDFdKTsgfVxuICAgICAgaWYgKG5ld1NlbCkgeyBzZXRTZWxlY3Rpb25SZXBsYWNlSGlzdG9yeSh0aGlzLCBuZXdTZWwpOyB9XG4gICAgICBlbHNlIGlmICh0aGlzLmNtKSB7IGVuc3VyZUN1cnNvclZpc2libGUodGhpcy5jbSk7IH1cbiAgICB9KSxcbiAgICB1bmRvOiBkb2NNZXRob2RPcChmdW5jdGlvbigpIHttYWtlQ2hhbmdlRnJvbUhpc3RvcnkodGhpcywgXCJ1bmRvXCIpO30pLFxuICAgIHJlZG86IGRvY01ldGhvZE9wKGZ1bmN0aW9uKCkge21ha2VDaGFuZ2VGcm9tSGlzdG9yeSh0aGlzLCBcInJlZG9cIik7fSksXG4gICAgdW5kb1NlbGVjdGlvbjogZG9jTWV0aG9kT3AoZnVuY3Rpb24oKSB7bWFrZUNoYW5nZUZyb21IaXN0b3J5KHRoaXMsIFwidW5kb1wiLCB0cnVlKTt9KSxcbiAgICByZWRvU2VsZWN0aW9uOiBkb2NNZXRob2RPcChmdW5jdGlvbigpIHttYWtlQ2hhbmdlRnJvbUhpc3RvcnkodGhpcywgXCJyZWRvXCIsIHRydWUpO30pLFxuXG4gICAgc2V0RXh0ZW5kaW5nOiBmdW5jdGlvbih2YWwpIHt0aGlzLmV4dGVuZCA9IHZhbDt9LFxuICAgIGdldEV4dGVuZGluZzogZnVuY3Rpb24oKSB7cmV0dXJuIHRoaXMuZXh0ZW5kfSxcblxuICAgIGhpc3RvcnlTaXplOiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBoaXN0ID0gdGhpcy5oaXN0b3J5LCBkb25lID0gMCwgdW5kb25lID0gMDtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaGlzdC5kb25lLmxlbmd0aDsgaSsrKSB7IGlmICghaGlzdC5kb25lW2ldLnJhbmdlcykgeyArK2RvbmU7IH0gfVxuICAgICAgZm9yICh2YXIgaSQxID0gMDsgaSQxIDwgaGlzdC51bmRvbmUubGVuZ3RoOyBpJDErKykgeyBpZiAoIWhpc3QudW5kb25lW2kkMV0ucmFuZ2VzKSB7ICsrdW5kb25lOyB9IH1cbiAgICAgIHJldHVybiB7dW5kbzogZG9uZSwgcmVkbzogdW5kb25lfVxuICAgIH0sXG4gICAgY2xlYXJIaXN0b3J5OiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciB0aGlzJDEgPSB0aGlzO1xuXG4gICAgICB0aGlzLmhpc3RvcnkgPSBuZXcgSGlzdG9yeSh0aGlzLmhpc3RvcnkpO1xuICAgICAgbGlua2VkRG9jcyh0aGlzLCBmdW5jdGlvbiAoZG9jKSB7IHJldHVybiBkb2MuaGlzdG9yeSA9IHRoaXMkMS5oaXN0b3J5OyB9LCB0cnVlKTtcbiAgICB9LFxuXG4gICAgbWFya0NsZWFuOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuY2xlYW5HZW5lcmF0aW9uID0gdGhpcy5jaGFuZ2VHZW5lcmF0aW9uKHRydWUpO1xuICAgIH0sXG4gICAgY2hhbmdlR2VuZXJhdGlvbjogZnVuY3Rpb24oZm9yY2VTcGxpdCkge1xuICAgICAgaWYgKGZvcmNlU3BsaXQpXG4gICAgICAgIHsgdGhpcy5oaXN0b3J5Lmxhc3RPcCA9IHRoaXMuaGlzdG9yeS5sYXN0U2VsT3AgPSB0aGlzLmhpc3RvcnkubGFzdE9yaWdpbiA9IG51bGw7IH1cbiAgICAgIHJldHVybiB0aGlzLmhpc3RvcnkuZ2VuZXJhdGlvblxuICAgIH0sXG4gICAgaXNDbGVhbjogZnVuY3Rpb24gKGdlbikge1xuICAgICAgcmV0dXJuIHRoaXMuaGlzdG9yeS5nZW5lcmF0aW9uID09IChnZW4gfHwgdGhpcy5jbGVhbkdlbmVyYXRpb24pXG4gICAgfSxcblxuICAgIGdldEhpc3Rvcnk6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHtkb25lOiBjb3B5SGlzdG9yeUFycmF5KHRoaXMuaGlzdG9yeS5kb25lKSxcbiAgICAgICAgICAgICAgdW5kb25lOiBjb3B5SGlzdG9yeUFycmF5KHRoaXMuaGlzdG9yeS51bmRvbmUpfVxuICAgIH0sXG4gICAgc2V0SGlzdG9yeTogZnVuY3Rpb24oaGlzdERhdGEpIHtcbiAgICAgIHZhciBoaXN0ID0gdGhpcy5oaXN0b3J5ID0gbmV3IEhpc3RvcnkodGhpcy5oaXN0b3J5KTtcbiAgICAgIGhpc3QuZG9uZSA9IGNvcHlIaXN0b3J5QXJyYXkoaGlzdERhdGEuZG9uZS5zbGljZSgwKSwgbnVsbCwgdHJ1ZSk7XG4gICAgICBoaXN0LnVuZG9uZSA9IGNvcHlIaXN0b3J5QXJyYXkoaGlzdERhdGEudW5kb25lLnNsaWNlKDApLCBudWxsLCB0cnVlKTtcbiAgICB9LFxuXG4gICAgc2V0R3V0dGVyTWFya2VyOiBkb2NNZXRob2RPcChmdW5jdGlvbihsaW5lLCBndXR0ZXJJRCwgdmFsdWUpIHtcbiAgICAgIHJldHVybiBjaGFuZ2VMaW5lKHRoaXMsIGxpbmUsIFwiZ3V0dGVyXCIsIGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgIHZhciBtYXJrZXJzID0gbGluZS5ndXR0ZXJNYXJrZXJzIHx8IChsaW5lLmd1dHRlck1hcmtlcnMgPSB7fSk7XG4gICAgICAgIG1hcmtlcnNbZ3V0dGVySURdID0gdmFsdWU7XG4gICAgICAgIGlmICghdmFsdWUgJiYgaXNFbXB0eShtYXJrZXJzKSkgeyBsaW5lLmd1dHRlck1hcmtlcnMgPSBudWxsOyB9XG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgICB9KVxuICAgIH0pLFxuXG4gICAgY2xlYXJHdXR0ZXI6IGRvY01ldGhvZE9wKGZ1bmN0aW9uKGd1dHRlcklEKSB7XG4gICAgICB2YXIgdGhpcyQxID0gdGhpcztcblxuICAgICAgdGhpcy5pdGVyKGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgIGlmIChsaW5lLmd1dHRlck1hcmtlcnMgJiYgbGluZS5ndXR0ZXJNYXJrZXJzW2d1dHRlcklEXSkge1xuICAgICAgICAgIGNoYW5nZUxpbmUodGhpcyQxLCBsaW5lLCBcImd1dHRlclwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBsaW5lLmd1dHRlck1hcmtlcnNbZ3V0dGVySURdID0gbnVsbDtcbiAgICAgICAgICAgIGlmIChpc0VtcHR5KGxpbmUuZ3V0dGVyTWFya2VycykpIHsgbGluZS5ndXR0ZXJNYXJrZXJzID0gbnVsbDsgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSksXG5cbiAgICBsaW5lSW5mbzogZnVuY3Rpb24obGluZSkge1xuICAgICAgdmFyIG47XG4gICAgICBpZiAodHlwZW9mIGxpbmUgPT0gXCJudW1iZXJcIikge1xuICAgICAgICBpZiAoIWlzTGluZSh0aGlzLCBsaW5lKSkgeyByZXR1cm4gbnVsbCB9XG4gICAgICAgIG4gPSBsaW5lO1xuICAgICAgICBsaW5lID0gZ2V0TGluZSh0aGlzLCBsaW5lKTtcbiAgICAgICAgaWYgKCFsaW5lKSB7IHJldHVybiBudWxsIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG4gPSBsaW5lTm8obGluZSk7XG4gICAgICAgIGlmIChuID09IG51bGwpIHsgcmV0dXJuIG51bGwgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHtsaW5lOiBuLCBoYW5kbGU6IGxpbmUsIHRleHQ6IGxpbmUudGV4dCwgZ3V0dGVyTWFya2VyczogbGluZS5ndXR0ZXJNYXJrZXJzLFxuICAgICAgICAgICAgICB0ZXh0Q2xhc3M6IGxpbmUudGV4dENsYXNzLCBiZ0NsYXNzOiBsaW5lLmJnQ2xhc3MsIHdyYXBDbGFzczogbGluZS53cmFwQ2xhc3MsXG4gICAgICAgICAgICAgIHdpZGdldHM6IGxpbmUud2lkZ2V0c31cbiAgICB9LFxuXG4gICAgYWRkTGluZUNsYXNzOiBkb2NNZXRob2RPcChmdW5jdGlvbihoYW5kbGUsIHdoZXJlLCBjbHMpIHtcbiAgICAgIHJldHVybiBjaGFuZ2VMaW5lKHRoaXMsIGhhbmRsZSwgd2hlcmUgPT0gXCJndXR0ZXJcIiA/IFwiZ3V0dGVyXCIgOiBcImNsYXNzXCIsIGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgIHZhciBwcm9wID0gd2hlcmUgPT0gXCJ0ZXh0XCIgPyBcInRleHRDbGFzc1wiXG4gICAgICAgICAgICAgICAgIDogd2hlcmUgPT0gXCJiYWNrZ3JvdW5kXCIgPyBcImJnQ2xhc3NcIlxuICAgICAgICAgICAgICAgICA6IHdoZXJlID09IFwiZ3V0dGVyXCIgPyBcImd1dHRlckNsYXNzXCIgOiBcIndyYXBDbGFzc1wiO1xuICAgICAgICBpZiAoIWxpbmVbcHJvcF0pIHsgbGluZVtwcm9wXSA9IGNsczsgfVxuICAgICAgICBlbHNlIGlmIChjbGFzc1Rlc3QoY2xzKS50ZXN0KGxpbmVbcHJvcF0pKSB7IHJldHVybiBmYWxzZSB9XG4gICAgICAgIGVsc2UgeyBsaW5lW3Byb3BdICs9IFwiIFwiICsgY2xzOyB9XG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgICB9KVxuICAgIH0pLFxuICAgIHJlbW92ZUxpbmVDbGFzczogZG9jTWV0aG9kT3AoZnVuY3Rpb24oaGFuZGxlLCB3aGVyZSwgY2xzKSB7XG4gICAgICByZXR1cm4gY2hhbmdlTGluZSh0aGlzLCBoYW5kbGUsIHdoZXJlID09IFwiZ3V0dGVyXCIgPyBcImd1dHRlclwiIDogXCJjbGFzc1wiLCBmdW5jdGlvbiAobGluZSkge1xuICAgICAgICB2YXIgcHJvcCA9IHdoZXJlID09IFwidGV4dFwiID8gXCJ0ZXh0Q2xhc3NcIlxuICAgICAgICAgICAgICAgICA6IHdoZXJlID09IFwiYmFja2dyb3VuZFwiID8gXCJiZ0NsYXNzXCJcbiAgICAgICAgICAgICAgICAgOiB3aGVyZSA9PSBcImd1dHRlclwiID8gXCJndXR0ZXJDbGFzc1wiIDogXCJ3cmFwQ2xhc3NcIjtcbiAgICAgICAgdmFyIGN1ciA9IGxpbmVbcHJvcF07XG4gICAgICAgIGlmICghY3VyKSB7IHJldHVybiBmYWxzZSB9XG4gICAgICAgIGVsc2UgaWYgKGNscyA9PSBudWxsKSB7IGxpbmVbcHJvcF0gPSBudWxsOyB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHZhciBmb3VuZCA9IGN1ci5tYXRjaChjbGFzc1Rlc3QoY2xzKSk7XG4gICAgICAgICAgaWYgKCFmb3VuZCkgeyByZXR1cm4gZmFsc2UgfVxuICAgICAgICAgIHZhciBlbmQgPSBmb3VuZC5pbmRleCArIGZvdW5kWzBdLmxlbmd0aDtcbiAgICAgICAgICBsaW5lW3Byb3BdID0gY3VyLnNsaWNlKDAsIGZvdW5kLmluZGV4KSArICghZm91bmQuaW5kZXggfHwgZW5kID09IGN1ci5sZW5ndGggPyBcIlwiIDogXCIgXCIpICsgY3VyLnNsaWNlKGVuZCkgfHwgbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgfSlcbiAgICB9KSxcblxuICAgIGFkZExpbmVXaWRnZXQ6IGRvY01ldGhvZE9wKGZ1bmN0aW9uKGhhbmRsZSwgbm9kZSwgb3B0aW9ucykge1xuICAgICAgcmV0dXJuIGFkZExpbmVXaWRnZXQodGhpcywgaGFuZGxlLCBub2RlLCBvcHRpb25zKVxuICAgIH0pLFxuICAgIHJlbW92ZUxpbmVXaWRnZXQ6IGZ1bmN0aW9uKHdpZGdldCkgeyB3aWRnZXQuY2xlYXIoKTsgfSxcblxuICAgIG1hcmtUZXh0OiBmdW5jdGlvbihmcm9tLCB0bywgb3B0aW9ucykge1xuICAgICAgcmV0dXJuIG1hcmtUZXh0KHRoaXMsIGNsaXBQb3ModGhpcywgZnJvbSksIGNsaXBQb3ModGhpcywgdG8pLCBvcHRpb25zLCBvcHRpb25zICYmIG9wdGlvbnMudHlwZSB8fCBcInJhbmdlXCIpXG4gICAgfSxcbiAgICBzZXRCb29rbWFyazogZnVuY3Rpb24ocG9zLCBvcHRpb25zKSB7XG4gICAgICB2YXIgcmVhbE9wdHMgPSB7cmVwbGFjZWRXaXRoOiBvcHRpb25zICYmIChvcHRpb25zLm5vZGVUeXBlID09IG51bGwgPyBvcHRpb25zLndpZGdldCA6IG9wdGlvbnMpLFxuICAgICAgICAgICAgICAgICAgICAgIGluc2VydExlZnQ6IG9wdGlvbnMgJiYgb3B0aW9ucy5pbnNlcnRMZWZ0LFxuICAgICAgICAgICAgICAgICAgICAgIGNsZWFyV2hlbkVtcHR5OiBmYWxzZSwgc2hhcmVkOiBvcHRpb25zICYmIG9wdGlvbnMuc2hhcmVkLFxuICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZU1vdXNlRXZlbnRzOiBvcHRpb25zICYmIG9wdGlvbnMuaGFuZGxlTW91c2VFdmVudHN9O1xuICAgICAgcG9zID0gY2xpcFBvcyh0aGlzLCBwb3MpO1xuICAgICAgcmV0dXJuIG1hcmtUZXh0KHRoaXMsIHBvcywgcG9zLCByZWFsT3B0cywgXCJib29rbWFya1wiKVxuICAgIH0sXG4gICAgZmluZE1hcmtzQXQ6IGZ1bmN0aW9uKHBvcykge1xuICAgICAgcG9zID0gY2xpcFBvcyh0aGlzLCBwb3MpO1xuICAgICAgdmFyIG1hcmtlcnMgPSBbXSwgc3BhbnMgPSBnZXRMaW5lKHRoaXMsIHBvcy5saW5lKS5tYXJrZWRTcGFucztcbiAgICAgIGlmIChzcGFucykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHNwYW5zLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHZhciBzcGFuID0gc3BhbnNbaV07XG4gICAgICAgIGlmICgoc3Bhbi5mcm9tID09IG51bGwgfHwgc3Bhbi5mcm9tIDw9IHBvcy5jaCkgJiZcbiAgICAgICAgICAgIChzcGFuLnRvID09IG51bGwgfHwgc3Bhbi50byA+PSBwb3MuY2gpKVxuICAgICAgICAgIHsgbWFya2Vycy5wdXNoKHNwYW4ubWFya2VyLnBhcmVudCB8fCBzcGFuLm1hcmtlcik7IH1cbiAgICAgIH0gfVxuICAgICAgcmV0dXJuIG1hcmtlcnNcbiAgICB9LFxuICAgIGZpbmRNYXJrczogZnVuY3Rpb24oZnJvbSwgdG8sIGZpbHRlcikge1xuICAgICAgZnJvbSA9IGNsaXBQb3ModGhpcywgZnJvbSk7IHRvID0gY2xpcFBvcyh0aGlzLCB0byk7XG4gICAgICB2YXIgZm91bmQgPSBbXSwgbGluZU5vID0gZnJvbS5saW5lO1xuICAgICAgdGhpcy5pdGVyKGZyb20ubGluZSwgdG8ubGluZSArIDEsIGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgIHZhciBzcGFucyA9IGxpbmUubWFya2VkU3BhbnM7XG4gICAgICAgIGlmIChzcGFucykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHNwYW5zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIHNwYW4gPSBzcGFuc1tpXTtcbiAgICAgICAgICBpZiAoIShzcGFuLnRvICE9IG51bGwgJiYgbGluZU5vID09IGZyb20ubGluZSAmJiBmcm9tLmNoID49IHNwYW4udG8gfHxcbiAgICAgICAgICAgICAgICBzcGFuLmZyb20gPT0gbnVsbCAmJiBsaW5lTm8gIT0gZnJvbS5saW5lIHx8XG4gICAgICAgICAgICAgICAgc3Bhbi5mcm9tICE9IG51bGwgJiYgbGluZU5vID09IHRvLmxpbmUgJiYgc3Bhbi5mcm9tID49IHRvLmNoKSAmJlxuICAgICAgICAgICAgICAoIWZpbHRlciB8fCBmaWx0ZXIoc3Bhbi5tYXJrZXIpKSlcbiAgICAgICAgICAgIHsgZm91bmQucHVzaChzcGFuLm1hcmtlci5wYXJlbnQgfHwgc3Bhbi5tYXJrZXIpOyB9XG4gICAgICAgIH0gfVxuICAgICAgICArK2xpbmVObztcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGZvdW5kXG4gICAgfSxcbiAgICBnZXRBbGxNYXJrczogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbWFya2VycyA9IFtdO1xuICAgICAgdGhpcy5pdGVyKGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgIHZhciBzcHMgPSBsaW5lLm1hcmtlZFNwYW5zO1xuICAgICAgICBpZiAoc3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgc3BzLmxlbmd0aDsgKytpKVxuICAgICAgICAgIHsgaWYgKHNwc1tpXS5mcm9tICE9IG51bGwpIHsgbWFya2Vycy5wdXNoKHNwc1tpXS5tYXJrZXIpOyB9IH0gfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gbWFya2Vyc1xuICAgIH0sXG5cbiAgICBwb3NGcm9tSW5kZXg6IGZ1bmN0aW9uKG9mZikge1xuICAgICAgdmFyIGNoLCBsaW5lTm8gPSB0aGlzLmZpcnN0LCBzZXBTaXplID0gdGhpcy5saW5lU2VwYXJhdG9yKCkubGVuZ3RoO1xuICAgICAgdGhpcy5pdGVyKGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgIHZhciBzeiA9IGxpbmUudGV4dC5sZW5ndGggKyBzZXBTaXplO1xuICAgICAgICBpZiAoc3ogPiBvZmYpIHsgY2ggPSBvZmY7IHJldHVybiB0cnVlIH1cbiAgICAgICAgb2ZmIC09IHN6O1xuICAgICAgICArK2xpbmVObztcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGNsaXBQb3ModGhpcywgUG9zKGxpbmVObywgY2gpKVxuICAgIH0sXG4gICAgaW5kZXhGcm9tUG9zOiBmdW5jdGlvbiAoY29vcmRzKSB7XG4gICAgICBjb29yZHMgPSBjbGlwUG9zKHRoaXMsIGNvb3Jkcyk7XG4gICAgICB2YXIgaW5kZXggPSBjb29yZHMuY2g7XG4gICAgICBpZiAoY29vcmRzLmxpbmUgPCB0aGlzLmZpcnN0IHx8IGNvb3Jkcy5jaCA8IDApIHsgcmV0dXJuIDAgfVxuICAgICAgdmFyIHNlcFNpemUgPSB0aGlzLmxpbmVTZXBhcmF0b3IoKS5sZW5ndGg7XG4gICAgICB0aGlzLml0ZXIodGhpcy5maXJzdCwgY29vcmRzLmxpbmUsIGZ1bmN0aW9uIChsaW5lKSB7IC8vIGl0ZXIgYWJvcnRzIHdoZW4gY2FsbGJhY2sgcmV0dXJucyBhIHRydXRoeSB2YWx1ZVxuICAgICAgICBpbmRleCArPSBsaW5lLnRleHQubGVuZ3RoICsgc2VwU2l6ZTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGluZGV4XG4gICAgfSxcblxuICAgIGNvcHk6IGZ1bmN0aW9uKGNvcHlIaXN0b3J5KSB7XG4gICAgICB2YXIgZG9jID0gbmV3IERvYyhnZXRMaW5lcyh0aGlzLCB0aGlzLmZpcnN0LCB0aGlzLmZpcnN0ICsgdGhpcy5zaXplKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubW9kZU9wdGlvbiwgdGhpcy5maXJzdCwgdGhpcy5saW5lU2VwLCB0aGlzLmRpcmVjdGlvbik7XG4gICAgICBkb2Muc2Nyb2xsVG9wID0gdGhpcy5zY3JvbGxUb3A7IGRvYy5zY3JvbGxMZWZ0ID0gdGhpcy5zY3JvbGxMZWZ0O1xuICAgICAgZG9jLnNlbCA9IHRoaXMuc2VsO1xuICAgICAgZG9jLmV4dGVuZCA9IGZhbHNlO1xuICAgICAgaWYgKGNvcHlIaXN0b3J5KSB7XG4gICAgICAgIGRvYy5oaXN0b3J5LnVuZG9EZXB0aCA9IHRoaXMuaGlzdG9yeS51bmRvRGVwdGg7XG4gICAgICAgIGRvYy5zZXRIaXN0b3J5KHRoaXMuZ2V0SGlzdG9yeSgpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBkb2NcbiAgICB9LFxuXG4gICAgbGlua2VkRG9jOiBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICBpZiAoIW9wdGlvbnMpIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgICB2YXIgZnJvbSA9IHRoaXMuZmlyc3QsIHRvID0gdGhpcy5maXJzdCArIHRoaXMuc2l6ZTtcbiAgICAgIGlmIChvcHRpb25zLmZyb20gIT0gbnVsbCAmJiBvcHRpb25zLmZyb20gPiBmcm9tKSB7IGZyb20gPSBvcHRpb25zLmZyb207IH1cbiAgICAgIGlmIChvcHRpb25zLnRvICE9IG51bGwgJiYgb3B0aW9ucy50byA8IHRvKSB7IHRvID0gb3B0aW9ucy50bzsgfVxuICAgICAgdmFyIGNvcHkgPSBuZXcgRG9jKGdldExpbmVzKHRoaXMsIGZyb20sIHRvKSwgb3B0aW9ucy5tb2RlIHx8IHRoaXMubW9kZU9wdGlvbiwgZnJvbSwgdGhpcy5saW5lU2VwLCB0aGlzLmRpcmVjdGlvbik7XG4gICAgICBpZiAob3B0aW9ucy5zaGFyZWRIaXN0KSB7IGNvcHkuaGlzdG9yeSA9IHRoaXMuaGlzdG9yeVxuICAgICAgOyB9KHRoaXMubGlua2VkIHx8ICh0aGlzLmxpbmtlZCA9IFtdKSkucHVzaCh7ZG9jOiBjb3B5LCBzaGFyZWRIaXN0OiBvcHRpb25zLnNoYXJlZEhpc3R9KTtcbiAgICAgIGNvcHkubGlua2VkID0gW3tkb2M6IHRoaXMsIGlzUGFyZW50OiB0cnVlLCBzaGFyZWRIaXN0OiBvcHRpb25zLnNoYXJlZEhpc3R9XTtcbiAgICAgIGNvcHlTaGFyZWRNYXJrZXJzKGNvcHksIGZpbmRTaGFyZWRNYXJrZXJzKHRoaXMpKTtcbiAgICAgIHJldHVybiBjb3B5XG4gICAgfSxcbiAgICB1bmxpbmtEb2M6IGZ1bmN0aW9uKG90aGVyKSB7XG4gICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBDb2RlTWlycm9yKSB7IG90aGVyID0gb3RoZXIuZG9jOyB9XG4gICAgICBpZiAodGhpcy5saW5rZWQpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxpbmtlZC5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgbGluayA9IHRoaXMubGlua2VkW2ldO1xuICAgICAgICBpZiAobGluay5kb2MgIT0gb3RoZXIpIHsgY29udGludWUgfVxuICAgICAgICB0aGlzLmxpbmtlZC5zcGxpY2UoaSwgMSk7XG4gICAgICAgIG90aGVyLnVubGlua0RvYyh0aGlzKTtcbiAgICAgICAgZGV0YWNoU2hhcmVkTWFya2VycyhmaW5kU2hhcmVkTWFya2Vycyh0aGlzKSk7XG4gICAgICAgIGJyZWFrXG4gICAgICB9IH1cbiAgICAgIC8vIElmIHRoZSBoaXN0b3JpZXMgd2VyZSBzaGFyZWQsIHNwbGl0IHRoZW0gYWdhaW5cbiAgICAgIGlmIChvdGhlci5oaXN0b3J5ID09IHRoaXMuaGlzdG9yeSkge1xuICAgICAgICB2YXIgc3BsaXRJZHMgPSBbb3RoZXIuaWRdO1xuICAgICAgICBsaW5rZWREb2NzKG90aGVyLCBmdW5jdGlvbiAoZG9jKSB7IHJldHVybiBzcGxpdElkcy5wdXNoKGRvYy5pZCk7IH0sIHRydWUpO1xuICAgICAgICBvdGhlci5oaXN0b3J5ID0gbmV3IEhpc3RvcnkobnVsbCk7XG4gICAgICAgIG90aGVyLmhpc3RvcnkuZG9uZSA9IGNvcHlIaXN0b3J5QXJyYXkodGhpcy5oaXN0b3J5LmRvbmUsIHNwbGl0SWRzKTtcbiAgICAgICAgb3RoZXIuaGlzdG9yeS51bmRvbmUgPSBjb3B5SGlzdG9yeUFycmF5KHRoaXMuaGlzdG9yeS51bmRvbmUsIHNwbGl0SWRzKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGl0ZXJMaW5rZWREb2NzOiBmdW5jdGlvbihmKSB7bGlua2VkRG9jcyh0aGlzLCBmKTt9LFxuXG4gICAgZ2V0TW9kZTogZnVuY3Rpb24oKSB7cmV0dXJuIHRoaXMubW9kZX0sXG4gICAgZ2V0RWRpdG9yOiBmdW5jdGlvbigpIHtyZXR1cm4gdGhpcy5jbX0sXG5cbiAgICBzcGxpdExpbmVzOiBmdW5jdGlvbihzdHIpIHtcbiAgICAgIGlmICh0aGlzLmxpbmVTZXApIHsgcmV0dXJuIHN0ci5zcGxpdCh0aGlzLmxpbmVTZXApIH1cbiAgICAgIHJldHVybiBzcGxpdExpbmVzQXV0byhzdHIpXG4gICAgfSxcbiAgICBsaW5lU2VwYXJhdG9yOiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMubGluZVNlcCB8fCBcIlxcblwiIH0sXG5cbiAgICBzZXREaXJlY3Rpb246IGRvY01ldGhvZE9wKGZ1bmN0aW9uIChkaXIpIHtcbiAgICAgIGlmIChkaXIgIT0gXCJydGxcIikgeyBkaXIgPSBcImx0clwiOyB9XG4gICAgICBpZiAoZGlyID09IHRoaXMuZGlyZWN0aW9uKSB7IHJldHVybiB9XG4gICAgICB0aGlzLmRpcmVjdGlvbiA9IGRpcjtcbiAgICAgIHRoaXMuaXRlcihmdW5jdGlvbiAobGluZSkgeyByZXR1cm4gbGluZS5vcmRlciA9IG51bGw7IH0pO1xuICAgICAgaWYgKHRoaXMuY20pIHsgZGlyZWN0aW9uQ2hhbmdlZCh0aGlzLmNtKTsgfVxuICAgIH0pXG4gIH0pO1xuXG4gIC8vIFB1YmxpYyBhbGlhcy5cbiAgRG9jLnByb3RvdHlwZS5lYWNoTGluZSA9IERvYy5wcm90b3R5cGUuaXRlcjtcblxuICAvLyBLbHVkZ2UgdG8gd29yayBhcm91bmQgc3RyYW5nZSBJRSBiZWhhdmlvciB3aGVyZSBpdCdsbCBzb21ldGltZXNcbiAgLy8gcmUtZmlyZSBhIHNlcmllcyBvZiBkcmFnLXJlbGF0ZWQgZXZlbnRzIHJpZ2h0IGFmdGVyIHRoZSBkcm9wICgjMTU1MSlcbiAgdmFyIGxhc3REcm9wID0gMDtcblxuICBmdW5jdGlvbiBvbkRyb3AoZSkge1xuICAgIHZhciBjbSA9IHRoaXM7XG4gICAgY2xlYXJEcmFnQ3Vyc29yKGNtKTtcbiAgICBpZiAoc2lnbmFsRE9NRXZlbnQoY20sIGUpIHx8IGV2ZW50SW5XaWRnZXQoY20uZGlzcGxheSwgZSkpXG4gICAgICB7IHJldHVybiB9XG4gICAgZV9wcmV2ZW50RGVmYXVsdChlKTtcbiAgICBpZiAoaWUpIHsgbGFzdERyb3AgPSArbmV3IERhdGU7IH1cbiAgICB2YXIgcG9zID0gcG9zRnJvbU1vdXNlKGNtLCBlLCB0cnVlKSwgZmlsZXMgPSBlLmRhdGFUcmFuc2Zlci5maWxlcztcbiAgICBpZiAoIXBvcyB8fCBjbS5pc1JlYWRPbmx5KCkpIHsgcmV0dXJuIH1cbiAgICAvLyBNaWdodCBiZSBhIGZpbGUgZHJvcCwgaW4gd2hpY2ggY2FzZSB3ZSBzaW1wbHkgZXh0cmFjdCB0aGUgdGV4dFxuICAgIC8vIGFuZCBpbnNlcnQgaXQuXG4gICAgaWYgKGZpbGVzICYmIGZpbGVzLmxlbmd0aCAmJiB3aW5kb3cuRmlsZVJlYWRlciAmJiB3aW5kb3cuRmlsZSkge1xuICAgICAgdmFyIG4gPSBmaWxlcy5sZW5ndGgsIHRleHQgPSBBcnJheShuKSwgcmVhZCA9IDA7XG4gICAgICB2YXIgbWFya0FzUmVhZEFuZFBhc3RlSWZBbGxGaWxlc0FyZVJlYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICgrK3JlYWQgPT0gbikge1xuICAgICAgICAgIG9wZXJhdGlvbihjbSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zID0gY2xpcFBvcyhjbS5kb2MsIHBvcyk7XG4gICAgICAgICAgICB2YXIgY2hhbmdlID0ge2Zyb206IHBvcywgdG86IHBvcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dDogY20uZG9jLnNwbGl0TGluZXMoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0LmZpbHRlcihmdW5jdGlvbiAodCkgeyByZXR1cm4gdCAhPSBudWxsOyB9KS5qb2luKGNtLmRvYy5saW5lU2VwYXJhdG9yKCkpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZ2luOiBcInBhc3RlXCJ9O1xuICAgICAgICAgICAgbWFrZUNoYW5nZShjbS5kb2MsIGNoYW5nZSk7XG4gICAgICAgICAgICBzZXRTZWxlY3Rpb25SZXBsYWNlSGlzdG9yeShjbS5kb2MsIHNpbXBsZVNlbGVjdGlvbihjbGlwUG9zKGNtLmRvYywgcG9zKSwgY2xpcFBvcyhjbS5kb2MsIGNoYW5nZUVuZChjaGFuZ2UpKSkpO1xuICAgICAgICAgIH0pKCk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICB2YXIgcmVhZFRleHRGcm9tRmlsZSA9IGZ1bmN0aW9uIChmaWxlLCBpKSB7XG4gICAgICAgIGlmIChjbS5vcHRpb25zLmFsbG93RHJvcEZpbGVUeXBlcyAmJlxuICAgICAgICAgICAgaW5kZXhPZihjbS5vcHRpb25zLmFsbG93RHJvcEZpbGVUeXBlcywgZmlsZS50eXBlKSA9PSAtMSkge1xuICAgICAgICAgIG1hcmtBc1JlYWRBbmRQYXN0ZUlmQWxsRmlsZXNBcmVSZWFkKCk7XG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyO1xuICAgICAgICByZWFkZXIub25lcnJvciA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIG1hcmtBc1JlYWRBbmRQYXN0ZUlmQWxsRmlsZXNBcmVSZWFkKCk7IH07XG4gICAgICAgIHJlYWRlci5vbmxvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdmFyIGNvbnRlbnQgPSByZWFkZXIucmVzdWx0O1xuICAgICAgICAgIGlmICgvW1xceDAwLVxceDA4XFx4MGUtXFx4MWZdezJ9Ly50ZXN0KGNvbnRlbnQpKSB7XG4gICAgICAgICAgICBtYXJrQXNSZWFkQW5kUGFzdGVJZkFsbEZpbGVzQXJlUmVhZCgpO1xuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgfVxuICAgICAgICAgIHRleHRbaV0gPSBjb250ZW50O1xuICAgICAgICAgIG1hcmtBc1JlYWRBbmRQYXN0ZUlmQWxsRmlsZXNBcmVSZWFkKCk7XG4gICAgICAgIH07XG4gICAgICAgIHJlYWRlci5yZWFkQXNUZXh0KGZpbGUpO1xuICAgICAgfTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmlsZXMubGVuZ3RoOyBpKyspIHsgcmVhZFRleHRGcm9tRmlsZShmaWxlc1tpXSwgaSk7IH1cbiAgICB9IGVsc2UgeyAvLyBOb3JtYWwgZHJvcFxuICAgICAgLy8gRG9uJ3QgZG8gYSByZXBsYWNlIGlmIHRoZSBkcm9wIGhhcHBlbmVkIGluc2lkZSBvZiB0aGUgc2VsZWN0ZWQgdGV4dC5cbiAgICAgIGlmIChjbS5zdGF0ZS5kcmFnZ2luZ1RleHQgJiYgY20uZG9jLnNlbC5jb250YWlucyhwb3MpID4gLTEpIHtcbiAgICAgICAgY20uc3RhdGUuZHJhZ2dpbmdUZXh0KGUpO1xuICAgICAgICAvLyBFbnN1cmUgdGhlIGVkaXRvciBpcyByZS1mb2N1c2VkXG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gY20uZGlzcGxheS5pbnB1dC5mb2N1cygpOyB9LCAyMCk7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgICAgdHJ5IHtcbiAgICAgICAgdmFyIHRleHQkMSA9IGUuZGF0YVRyYW5zZmVyLmdldERhdGEoXCJUZXh0XCIpO1xuICAgICAgICBpZiAodGV4dCQxKSB7XG4gICAgICAgICAgdmFyIHNlbGVjdGVkO1xuICAgICAgICAgIGlmIChjbS5zdGF0ZS5kcmFnZ2luZ1RleHQgJiYgIWNtLnN0YXRlLmRyYWdnaW5nVGV4dC5jb3B5KVxuICAgICAgICAgICAgeyBzZWxlY3RlZCA9IGNtLmxpc3RTZWxlY3Rpb25zKCk7IH1cbiAgICAgICAgICBzZXRTZWxlY3Rpb25Ob1VuZG8oY20uZG9jLCBzaW1wbGVTZWxlY3Rpb24ocG9zLCBwb3MpKTtcbiAgICAgICAgICBpZiAoc2VsZWN0ZWQpIHsgZm9yICh2YXIgaSQxID0gMDsgaSQxIDwgc2VsZWN0ZWQubGVuZ3RoOyArK2kkMSlcbiAgICAgICAgICAgIHsgcmVwbGFjZVJhbmdlKGNtLmRvYywgXCJcIiwgc2VsZWN0ZWRbaSQxXS5hbmNob3IsIHNlbGVjdGVkW2kkMV0uaGVhZCwgXCJkcmFnXCIpOyB9IH1cbiAgICAgICAgICBjbS5yZXBsYWNlU2VsZWN0aW9uKHRleHQkMSwgXCJhcm91bmRcIiwgXCJwYXN0ZVwiKTtcbiAgICAgICAgICBjbS5kaXNwbGF5LmlucHV0LmZvY3VzKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNhdGNoKGUkMSl7fVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIG9uRHJhZ1N0YXJ0KGNtLCBlKSB7XG4gICAgaWYgKGllICYmICghY20uc3RhdGUuZHJhZ2dpbmdUZXh0IHx8ICtuZXcgRGF0ZSAtIGxhc3REcm9wIDwgMTAwKSkgeyBlX3N0b3AoZSk7IHJldHVybiB9XG4gICAgaWYgKHNpZ25hbERPTUV2ZW50KGNtLCBlKSB8fCBldmVudEluV2lkZ2V0KGNtLmRpc3BsYXksIGUpKSB7IHJldHVybiB9XG5cbiAgICBlLmRhdGFUcmFuc2Zlci5zZXREYXRhKFwiVGV4dFwiLCBjbS5nZXRTZWxlY3Rpb24oKSk7XG4gICAgZS5kYXRhVHJhbnNmZXIuZWZmZWN0QWxsb3dlZCA9IFwiY29weU1vdmVcIjtcblxuICAgIC8vIFVzZSBkdW1teSBpbWFnZSBpbnN0ZWFkIG9mIGRlZmF1bHQgYnJvd3NlcnMgaW1hZ2UuXG4gICAgLy8gUmVjZW50IFNhZmFyaSAofjYuMC4yKSBoYXZlIGEgdGVuZGVuY3kgdG8gc2VnZmF1bHQgd2hlbiB0aGlzIGhhcHBlbnMsIHNvIHdlIGRvbid0IGRvIGl0IHRoZXJlLlxuICAgIGlmIChlLmRhdGFUcmFuc2Zlci5zZXREcmFnSW1hZ2UgJiYgIXNhZmFyaSkge1xuICAgICAgdmFyIGltZyA9IGVsdChcImltZ1wiLCBudWxsLCBudWxsLCBcInBvc2l0aW9uOiBmaXhlZDsgbGVmdDogMDsgdG9wOiAwO1wiKTtcbiAgICAgIGltZy5zcmMgPSBcImRhdGE6aW1hZ2UvZ2lmO2Jhc2U2NCxSMGxHT0RsaEFRQUJBQUFBQUNINUJBRUtBQUVBTEFBQUFBQUJBQUVBQUFJQ1RBRUFPdz09XCI7XG4gICAgICBpZiAocHJlc3RvKSB7XG4gICAgICAgIGltZy53aWR0aCA9IGltZy5oZWlnaHQgPSAxO1xuICAgICAgICBjbS5kaXNwbGF5LndyYXBwZXIuYXBwZW5kQ2hpbGQoaW1nKTtcbiAgICAgICAgLy8gRm9yY2UgYSByZWxheW91dCwgb3IgT3BlcmEgd29uJ3QgdXNlIG91ciBpbWFnZSBmb3Igc29tZSBvYnNjdXJlIHJlYXNvblxuICAgICAgICBpbWcuX3RvcCA9IGltZy5vZmZzZXRUb3A7XG4gICAgICB9XG4gICAgICBlLmRhdGFUcmFuc2Zlci5zZXREcmFnSW1hZ2UoaW1nLCAwLCAwKTtcbiAgICAgIGlmIChwcmVzdG8pIHsgaW1nLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoaW1nKTsgfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIG9uRHJhZ092ZXIoY20sIGUpIHtcbiAgICB2YXIgcG9zID0gcG9zRnJvbU1vdXNlKGNtLCBlKTtcbiAgICBpZiAoIXBvcykgeyByZXR1cm4gfVxuICAgIHZhciBmcmFnID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO1xuICAgIGRyYXdTZWxlY3Rpb25DdXJzb3IoY20sIHBvcywgZnJhZyk7XG4gICAgaWYgKCFjbS5kaXNwbGF5LmRyYWdDdXJzb3IpIHtcbiAgICAgIGNtLmRpc3BsYXkuZHJhZ0N1cnNvciA9IGVsdChcImRpdlwiLCBudWxsLCBcIkNvZGVNaXJyb3ItY3Vyc29ycyBDb2RlTWlycm9yLWRyYWdjdXJzb3JzXCIpO1xuICAgICAgY20uZGlzcGxheS5saW5lU3BhY2UuaW5zZXJ0QmVmb3JlKGNtLmRpc3BsYXkuZHJhZ0N1cnNvciwgY20uZGlzcGxheS5jdXJzb3JEaXYpO1xuICAgIH1cbiAgICByZW1vdmVDaGlsZHJlbkFuZEFkZChjbS5kaXNwbGF5LmRyYWdDdXJzb3IsIGZyYWcpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2xlYXJEcmFnQ3Vyc29yKGNtKSB7XG4gICAgaWYgKGNtLmRpc3BsYXkuZHJhZ0N1cnNvcikge1xuICAgICAgY20uZGlzcGxheS5saW5lU3BhY2UucmVtb3ZlQ2hpbGQoY20uZGlzcGxheS5kcmFnQ3Vyc29yKTtcbiAgICAgIGNtLmRpc3BsYXkuZHJhZ0N1cnNvciA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgLy8gVGhlc2UgbXVzdCBiZSBoYW5kbGVkIGNhcmVmdWxseSwgYmVjYXVzZSBuYWl2ZWx5IHJlZ2lzdGVyaW5nIGFcbiAgLy8gaGFuZGxlciBmb3IgZWFjaCBlZGl0b3Igd2lsbCBjYXVzZSB0aGUgZWRpdG9ycyB0byBuZXZlciBiZVxuICAvLyBnYXJiYWdlIGNvbGxlY3RlZC5cblxuICBmdW5jdGlvbiBmb3JFYWNoQ29kZU1pcnJvcihmKSB7XG4gICAgaWYgKCFkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKSB7IHJldHVybiB9XG4gICAgdmFyIGJ5Q2xhc3MgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiQ29kZU1pcnJvclwiKSwgZWRpdG9ycyA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYnlDbGFzcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNtID0gYnlDbGFzc1tpXS5Db2RlTWlycm9yO1xuICAgICAgaWYgKGNtKSB7IGVkaXRvcnMucHVzaChjbSk7IH1cbiAgICB9XG4gICAgaWYgKGVkaXRvcnMubGVuZ3RoKSB7IGVkaXRvcnNbMF0ub3BlcmF0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWRpdG9ycy5sZW5ndGg7IGkrKykgeyBmKGVkaXRvcnNbaV0pOyB9XG4gICAgfSk7IH1cbiAgfVxuXG4gIHZhciBnbG9iYWxzUmVnaXN0ZXJlZCA9IGZhbHNlO1xuICBmdW5jdGlvbiBlbnN1cmVHbG9iYWxIYW5kbGVycygpIHtcbiAgICBpZiAoZ2xvYmFsc1JlZ2lzdGVyZWQpIHsgcmV0dXJuIH1cbiAgICByZWdpc3Rlckdsb2JhbEhhbmRsZXJzKCk7XG4gICAgZ2xvYmFsc1JlZ2lzdGVyZWQgPSB0cnVlO1xuICB9XG4gIGZ1bmN0aW9uIHJlZ2lzdGVyR2xvYmFsSGFuZGxlcnMoKSB7XG4gICAgLy8gV2hlbiB0aGUgd2luZG93IHJlc2l6ZXMsIHdlIG5lZWQgdG8gcmVmcmVzaCBhY3RpdmUgZWRpdG9ycy5cbiAgICB2YXIgcmVzaXplVGltZXI7XG4gICAgb24od2luZG93LCBcInJlc2l6ZVwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAocmVzaXplVGltZXIgPT0gbnVsbCkgeyByZXNpemVUaW1lciA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICByZXNpemVUaW1lciA9IG51bGw7XG4gICAgICAgIGZvckVhY2hDb2RlTWlycm9yKG9uUmVzaXplKTtcbiAgICAgIH0sIDEwMCk7IH1cbiAgICB9KTtcbiAgICAvLyBXaGVuIHRoZSB3aW5kb3cgbG9zZXMgZm9jdXMsIHdlIHdhbnQgdG8gc2hvdyB0aGUgZWRpdG9yIGFzIGJsdXJyZWRcbiAgICBvbih3aW5kb3csIFwiYmx1clwiLCBmdW5jdGlvbiAoKSB7IHJldHVybiBmb3JFYWNoQ29kZU1pcnJvcihvbkJsdXIpOyB9KTtcbiAgfVxuICAvLyBDYWxsZWQgd2hlbiB0aGUgd2luZG93IHJlc2l6ZXNcbiAgZnVuY3Rpb24gb25SZXNpemUoY20pIHtcbiAgICB2YXIgZCA9IGNtLmRpc3BsYXk7XG4gICAgLy8gTWlnaHQgYmUgYSB0ZXh0IHNjYWxpbmcgb3BlcmF0aW9uLCBjbGVhciBzaXplIGNhY2hlcy5cbiAgICBkLmNhY2hlZENoYXJXaWR0aCA9IGQuY2FjaGVkVGV4dEhlaWdodCA9IGQuY2FjaGVkUGFkZGluZ0ggPSBudWxsO1xuICAgIGQuc2Nyb2xsYmFyc0NsaXBwZWQgPSBmYWxzZTtcbiAgICBjbS5zZXRTaXplKCk7XG4gIH1cblxuICB2YXIga2V5TmFtZXMgPSB7XG4gICAgMzogXCJQYXVzZVwiLCA4OiBcIkJhY2tzcGFjZVwiLCA5OiBcIlRhYlwiLCAxMzogXCJFbnRlclwiLCAxNjogXCJTaGlmdFwiLCAxNzogXCJDdHJsXCIsIDE4OiBcIkFsdFwiLFxuICAgIDE5OiBcIlBhdXNlXCIsIDIwOiBcIkNhcHNMb2NrXCIsIDI3OiBcIkVzY1wiLCAzMjogXCJTcGFjZVwiLCAzMzogXCJQYWdlVXBcIiwgMzQ6IFwiUGFnZURvd25cIiwgMzU6IFwiRW5kXCIsXG4gICAgMzY6IFwiSG9tZVwiLCAzNzogXCJMZWZ0XCIsIDM4OiBcIlVwXCIsIDM5OiBcIlJpZ2h0XCIsIDQwOiBcIkRvd25cIiwgNDQ6IFwiUHJpbnRTY3JuXCIsIDQ1OiBcIkluc2VydFwiLFxuICAgIDQ2OiBcIkRlbGV0ZVwiLCA1OTogXCI7XCIsIDYxOiBcIj1cIiwgOTE6IFwiTW9kXCIsIDkyOiBcIk1vZFwiLCA5MzogXCJNb2RcIixcbiAgICAxMDY6IFwiKlwiLCAxMDc6IFwiPVwiLCAxMDk6IFwiLVwiLCAxMTA6IFwiLlwiLCAxMTE6IFwiL1wiLCAxNDU6IFwiU2Nyb2xsTG9ja1wiLFxuICAgIDE3MzogXCItXCIsIDE4NjogXCI7XCIsIDE4NzogXCI9XCIsIDE4ODogXCIsXCIsIDE4OTogXCItXCIsIDE5MDogXCIuXCIsIDE5MTogXCIvXCIsIDE5MjogXCJgXCIsIDIxOTogXCJbXCIsIDIyMDogXCJcXFxcXCIsXG4gICAgMjIxOiBcIl1cIiwgMjIyOiBcIidcIiwgMjI0OiBcIk1vZFwiLCA2MzIzMjogXCJVcFwiLCA2MzIzMzogXCJEb3duXCIsIDYzMjM0OiBcIkxlZnRcIiwgNjMyMzU6IFwiUmlnaHRcIiwgNjMyNzI6IFwiRGVsZXRlXCIsXG4gICAgNjMyNzM6IFwiSG9tZVwiLCA2MzI3NTogXCJFbmRcIiwgNjMyNzY6IFwiUGFnZVVwXCIsIDYzMjc3OiBcIlBhZ2VEb3duXCIsIDYzMzAyOiBcIkluc2VydFwiXG4gIH07XG5cbiAgLy8gTnVtYmVyIGtleXNcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAxMDsgaSsrKSB7IGtleU5hbWVzW2kgKyA0OF0gPSBrZXlOYW1lc1tpICsgOTZdID0gU3RyaW5nKGkpOyB9XG4gIC8vIEFscGhhYmV0aWMga2V5c1xuICBmb3IgKHZhciBpJDEgPSA2NTsgaSQxIDw9IDkwOyBpJDErKykgeyBrZXlOYW1lc1tpJDFdID0gU3RyaW5nLmZyb21DaGFyQ29kZShpJDEpOyB9XG4gIC8vIEZ1bmN0aW9uIGtleXNcbiAgZm9yICh2YXIgaSQyID0gMTsgaSQyIDw9IDEyOyBpJDIrKykgeyBrZXlOYW1lc1tpJDIgKyAxMTFdID0ga2V5TmFtZXNbaSQyICsgNjMyMzVdID0gXCJGXCIgKyBpJDI7IH1cblxuICB2YXIga2V5TWFwID0ge307XG5cbiAga2V5TWFwLmJhc2ljID0ge1xuICAgIFwiTGVmdFwiOiBcImdvQ2hhckxlZnRcIiwgXCJSaWdodFwiOiBcImdvQ2hhclJpZ2h0XCIsIFwiVXBcIjogXCJnb0xpbmVVcFwiLCBcIkRvd25cIjogXCJnb0xpbmVEb3duXCIsXG4gICAgXCJFbmRcIjogXCJnb0xpbmVFbmRcIiwgXCJIb21lXCI6IFwiZ29MaW5lU3RhcnRTbWFydFwiLCBcIlBhZ2VVcFwiOiBcImdvUGFnZVVwXCIsIFwiUGFnZURvd25cIjogXCJnb1BhZ2VEb3duXCIsXG4gICAgXCJEZWxldGVcIjogXCJkZWxDaGFyQWZ0ZXJcIiwgXCJCYWNrc3BhY2VcIjogXCJkZWxDaGFyQmVmb3JlXCIsIFwiU2hpZnQtQmFja3NwYWNlXCI6IFwiZGVsQ2hhckJlZm9yZVwiLFxuICAgIFwiVGFiXCI6IFwiZGVmYXVsdFRhYlwiLCBcIlNoaWZ0LVRhYlwiOiBcImluZGVudEF1dG9cIixcbiAgICBcIkVudGVyXCI6IFwibmV3bGluZUFuZEluZGVudFwiLCBcIkluc2VydFwiOiBcInRvZ2dsZU92ZXJ3cml0ZVwiLFxuICAgIFwiRXNjXCI6IFwic2luZ2xlU2VsZWN0aW9uXCJcbiAgfTtcbiAgLy8gTm90ZSB0aGF0IHRoZSBzYXZlIGFuZCBmaW5kLXJlbGF0ZWQgY29tbWFuZHMgYXJlbid0IGRlZmluZWQgYnlcbiAgLy8gZGVmYXVsdC4gVXNlciBjb2RlIG9yIGFkZG9ucyBjYW4gZGVmaW5lIHRoZW0uIFVua25vd24gY29tbWFuZHNcbiAgLy8gYXJlIHNpbXBseSBpZ25vcmVkLlxuICBrZXlNYXAucGNEZWZhdWx0ID0ge1xuICAgIFwiQ3RybC1BXCI6IFwic2VsZWN0QWxsXCIsIFwiQ3RybC1EXCI6IFwiZGVsZXRlTGluZVwiLCBcIkN0cmwtWlwiOiBcInVuZG9cIiwgXCJTaGlmdC1DdHJsLVpcIjogXCJyZWRvXCIsIFwiQ3RybC1ZXCI6IFwicmVkb1wiLFxuICAgIFwiQ3RybC1Ib21lXCI6IFwiZ29Eb2NTdGFydFwiLCBcIkN0cmwtRW5kXCI6IFwiZ29Eb2NFbmRcIiwgXCJDdHJsLVVwXCI6IFwiZ29MaW5lVXBcIiwgXCJDdHJsLURvd25cIjogXCJnb0xpbmVEb3duXCIsXG4gICAgXCJDdHJsLUxlZnRcIjogXCJnb0dyb3VwTGVmdFwiLCBcIkN0cmwtUmlnaHRcIjogXCJnb0dyb3VwUmlnaHRcIiwgXCJBbHQtTGVmdFwiOiBcImdvTGluZVN0YXJ0XCIsIFwiQWx0LVJpZ2h0XCI6IFwiZ29MaW5lRW5kXCIsXG4gICAgXCJDdHJsLUJhY2tzcGFjZVwiOiBcImRlbEdyb3VwQmVmb3JlXCIsIFwiQ3RybC1EZWxldGVcIjogXCJkZWxHcm91cEFmdGVyXCIsIFwiQ3RybC1TXCI6IFwic2F2ZVwiLCBcIkN0cmwtRlwiOiBcImZpbmRcIixcbiAgICBcIkN0cmwtR1wiOiBcImZpbmROZXh0XCIsIFwiU2hpZnQtQ3RybC1HXCI6IFwiZmluZFByZXZcIiwgXCJTaGlmdC1DdHJsLUZcIjogXCJyZXBsYWNlXCIsIFwiU2hpZnQtQ3RybC1SXCI6IFwicmVwbGFjZUFsbFwiLFxuICAgIFwiQ3RybC1bXCI6IFwiaW5kZW50TGVzc1wiLCBcIkN0cmwtXVwiOiBcImluZGVudE1vcmVcIixcbiAgICBcIkN0cmwtVVwiOiBcInVuZG9TZWxlY3Rpb25cIiwgXCJTaGlmdC1DdHJsLVVcIjogXCJyZWRvU2VsZWN0aW9uXCIsIFwiQWx0LVVcIjogXCJyZWRvU2VsZWN0aW9uXCIsXG4gICAgXCJmYWxsdGhyb3VnaFwiOiBcImJhc2ljXCJcbiAgfTtcbiAgLy8gVmVyeSBiYXNpYyByZWFkbGluZS9lbWFjcy1zdHlsZSBiaW5kaW5ncywgd2hpY2ggYXJlIHN0YW5kYXJkIG9uIE1hYy5cbiAga2V5TWFwLmVtYWNzeSA9IHtcbiAgICBcIkN0cmwtRlwiOiBcImdvQ2hhclJpZ2h0XCIsIFwiQ3RybC1CXCI6IFwiZ29DaGFyTGVmdFwiLCBcIkN0cmwtUFwiOiBcImdvTGluZVVwXCIsIFwiQ3RybC1OXCI6IFwiZ29MaW5lRG93blwiLFxuICAgIFwiQ3RybC1BXCI6IFwiZ29MaW5lU3RhcnRcIiwgXCJDdHJsLUVcIjogXCJnb0xpbmVFbmRcIiwgXCJDdHJsLVZcIjogXCJnb1BhZ2VEb3duXCIsIFwiU2hpZnQtQ3RybC1WXCI6IFwiZ29QYWdlVXBcIixcbiAgICBcIkN0cmwtRFwiOiBcImRlbENoYXJBZnRlclwiLCBcIkN0cmwtSFwiOiBcImRlbENoYXJCZWZvcmVcIiwgXCJBbHQtQmFja3NwYWNlXCI6IFwiZGVsV29yZEJlZm9yZVwiLCBcIkN0cmwtS1wiOiBcImtpbGxMaW5lXCIsXG4gICAgXCJDdHJsLVRcIjogXCJ0cmFuc3Bvc2VDaGFyc1wiLCBcIkN0cmwtT1wiOiBcIm9wZW5MaW5lXCJcbiAgfTtcbiAga2V5TWFwLm1hY0RlZmF1bHQgPSB7XG4gICAgXCJDbWQtQVwiOiBcInNlbGVjdEFsbFwiLCBcIkNtZC1EXCI6IFwiZGVsZXRlTGluZVwiLCBcIkNtZC1aXCI6IFwidW5kb1wiLCBcIlNoaWZ0LUNtZC1aXCI6IFwicmVkb1wiLCBcIkNtZC1ZXCI6IFwicmVkb1wiLFxuICAgIFwiQ21kLUhvbWVcIjogXCJnb0RvY1N0YXJ0XCIsIFwiQ21kLVVwXCI6IFwiZ29Eb2NTdGFydFwiLCBcIkNtZC1FbmRcIjogXCJnb0RvY0VuZFwiLCBcIkNtZC1Eb3duXCI6IFwiZ29Eb2NFbmRcIiwgXCJBbHQtTGVmdFwiOiBcImdvR3JvdXBMZWZ0XCIsXG4gICAgXCJBbHQtUmlnaHRcIjogXCJnb0dyb3VwUmlnaHRcIiwgXCJDbWQtTGVmdFwiOiBcImdvTGluZUxlZnRcIiwgXCJDbWQtUmlnaHRcIjogXCJnb0xpbmVSaWdodFwiLCBcIkFsdC1CYWNrc3BhY2VcIjogXCJkZWxHcm91cEJlZm9yZVwiLFxuICAgIFwiQ3RybC1BbHQtQmFja3NwYWNlXCI6IFwiZGVsR3JvdXBBZnRlclwiLCBcIkFsdC1EZWxldGVcIjogXCJkZWxHcm91cEFmdGVyXCIsIFwiQ21kLVNcIjogXCJzYXZlXCIsIFwiQ21kLUZcIjogXCJmaW5kXCIsXG4gICAgXCJDbWQtR1wiOiBcImZpbmROZXh0XCIsIFwiU2hpZnQtQ21kLUdcIjogXCJmaW5kUHJldlwiLCBcIkNtZC1BbHQtRlwiOiBcInJlcGxhY2VcIiwgXCJTaGlmdC1DbWQtQWx0LUZcIjogXCJyZXBsYWNlQWxsXCIsXG4gICAgXCJDbWQtW1wiOiBcImluZGVudExlc3NcIiwgXCJDbWQtXVwiOiBcImluZGVudE1vcmVcIiwgXCJDbWQtQmFja3NwYWNlXCI6IFwiZGVsV3JhcHBlZExpbmVMZWZ0XCIsIFwiQ21kLURlbGV0ZVwiOiBcImRlbFdyYXBwZWRMaW5lUmlnaHRcIixcbiAgICBcIkNtZC1VXCI6IFwidW5kb1NlbGVjdGlvblwiLCBcIlNoaWZ0LUNtZC1VXCI6IFwicmVkb1NlbGVjdGlvblwiLCBcIkN0cmwtVXBcIjogXCJnb0RvY1N0YXJ0XCIsIFwiQ3RybC1Eb3duXCI6IFwiZ29Eb2NFbmRcIixcbiAgICBcImZhbGx0aHJvdWdoXCI6IFtcImJhc2ljXCIsIFwiZW1hY3N5XCJdXG4gIH07XG4gIGtleU1hcFtcImRlZmF1bHRcIl0gPSBtYWMgPyBrZXlNYXAubWFjRGVmYXVsdCA6IGtleU1hcC5wY0RlZmF1bHQ7XG5cbiAgLy8gS0VZTUFQIERJU1BBVENIXG5cbiAgZnVuY3Rpb24gbm9ybWFsaXplS2V5TmFtZShuYW1lKSB7XG4gICAgdmFyIHBhcnRzID0gbmFtZS5zcGxpdCgvLSg/ISQpLyk7XG4gICAgbmFtZSA9IHBhcnRzW3BhcnRzLmxlbmd0aCAtIDFdO1xuICAgIHZhciBhbHQsIGN0cmwsIHNoaWZ0LCBjbWQ7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgIHZhciBtb2QgPSBwYXJ0c1tpXTtcbiAgICAgIGlmICgvXihjbWR8bWV0YXxtKSQvaS50ZXN0KG1vZCkpIHsgY21kID0gdHJ1ZTsgfVxuICAgICAgZWxzZSBpZiAoL15hKGx0KT8kL2kudGVzdChtb2QpKSB7IGFsdCA9IHRydWU7IH1cbiAgICAgIGVsc2UgaWYgKC9eKGN8Y3RybHxjb250cm9sKSQvaS50ZXN0KG1vZCkpIHsgY3RybCA9IHRydWU7IH1cbiAgICAgIGVsc2UgaWYgKC9ecyhoaWZ0KT8kL2kudGVzdChtb2QpKSB7IHNoaWZ0ID0gdHJ1ZTsgfVxuICAgICAgZWxzZSB7IHRocm93IG5ldyBFcnJvcihcIlVucmVjb2duaXplZCBtb2RpZmllciBuYW1lOiBcIiArIG1vZCkgfVxuICAgIH1cbiAgICBpZiAoYWx0KSB7IG5hbWUgPSBcIkFsdC1cIiArIG5hbWU7IH1cbiAgICBpZiAoY3RybCkgeyBuYW1lID0gXCJDdHJsLVwiICsgbmFtZTsgfVxuICAgIGlmIChjbWQpIHsgbmFtZSA9IFwiQ21kLVwiICsgbmFtZTsgfVxuICAgIGlmIChzaGlmdCkgeyBuYW1lID0gXCJTaGlmdC1cIiArIG5hbWU7IH1cbiAgICByZXR1cm4gbmFtZVxuICB9XG5cbiAgLy8gVGhpcyBpcyBhIGtsdWRnZSB0byBrZWVwIGtleW1hcHMgbW9zdGx5IHdvcmtpbmcgYXMgcmF3IG9iamVjdHNcbiAgLy8gKGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5KSB3aGlsZSBhdCB0aGUgc2FtZSB0aW1lIHN1cHBvcnQgZmVhdHVyZXNcbiAgLy8gbGlrZSBub3JtYWxpemF0aW9uIGFuZCBtdWx0aS1zdHJva2Uga2V5IGJpbmRpbmdzLiBJdCBjb21waWxlcyBhXG4gIC8vIG5ldyBub3JtYWxpemVkIGtleW1hcCwgYW5kIHRoZW4gdXBkYXRlcyB0aGUgb2xkIG9iamVjdCB0byByZWZsZWN0XG4gIC8vIHRoaXMuXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZUtleU1hcChrZXltYXApIHtcbiAgICB2YXIgY29weSA9IHt9O1xuICAgIGZvciAodmFyIGtleW5hbWUgaW4ga2V5bWFwKSB7IGlmIChrZXltYXAuaGFzT3duUHJvcGVydHkoa2V5bmFtZSkpIHtcbiAgICAgIHZhciB2YWx1ZSA9IGtleW1hcFtrZXluYW1lXTtcbiAgICAgIGlmICgvXihuYW1lfGZhbGx0aHJvdWdofChkZXxhdCl0YWNoKSQvLnRlc3Qoa2V5bmFtZSkpIHsgY29udGludWUgfVxuICAgICAgaWYgKHZhbHVlID09IFwiLi4uXCIpIHsgZGVsZXRlIGtleW1hcFtrZXluYW1lXTsgY29udGludWUgfVxuXG4gICAgICB2YXIga2V5cyA9IG1hcChrZXluYW1lLnNwbGl0KFwiIFwiKSwgbm9ybWFsaXplS2V5TmFtZSk7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHZhbCA9ICh2b2lkIDApLCBuYW1lID0gKHZvaWQgMCk7XG4gICAgICAgIGlmIChpID09IGtleXMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgIG5hbWUgPSBrZXlzLmpvaW4oXCIgXCIpO1xuICAgICAgICAgIHZhbCA9IHZhbHVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5hbWUgPSBrZXlzLnNsaWNlKDAsIGkgKyAxKS5qb2luKFwiIFwiKTtcbiAgICAgICAgICB2YWwgPSBcIi4uLlwiO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwcmV2ID0gY29weVtuYW1lXTtcbiAgICAgICAgaWYgKCFwcmV2KSB7IGNvcHlbbmFtZV0gPSB2YWw7IH1cbiAgICAgICAgZWxzZSBpZiAocHJldiAhPSB2YWwpIHsgdGhyb3cgbmV3IEVycm9yKFwiSW5jb25zaXN0ZW50IGJpbmRpbmdzIGZvciBcIiArIG5hbWUpIH1cbiAgICAgIH1cbiAgICAgIGRlbGV0ZSBrZXltYXBba2V5bmFtZV07XG4gICAgfSB9XG4gICAgZm9yICh2YXIgcHJvcCBpbiBjb3B5KSB7IGtleW1hcFtwcm9wXSA9IGNvcHlbcHJvcF07IH1cbiAgICByZXR1cm4ga2V5bWFwXG4gIH1cblxuICBmdW5jdGlvbiBsb29rdXBLZXkoa2V5LCBtYXAsIGhhbmRsZSwgY29udGV4dCkge1xuICAgIG1hcCA9IGdldEtleU1hcChtYXApO1xuICAgIHZhciBmb3VuZCA9IG1hcC5jYWxsID8gbWFwLmNhbGwoa2V5LCBjb250ZXh0KSA6IG1hcFtrZXldO1xuICAgIGlmIChmb3VuZCA9PT0gZmFsc2UpIHsgcmV0dXJuIFwibm90aGluZ1wiIH1cbiAgICBpZiAoZm91bmQgPT09IFwiLi4uXCIpIHsgcmV0dXJuIFwibXVsdGlcIiB9XG4gICAgaWYgKGZvdW5kICE9IG51bGwgJiYgaGFuZGxlKGZvdW5kKSkgeyByZXR1cm4gXCJoYW5kbGVkXCIgfVxuXG4gICAgaWYgKG1hcC5mYWxsdGhyb3VnaCkge1xuICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChtYXAuZmFsbHRocm91Z2gpICE9IFwiW29iamVjdCBBcnJheV1cIilcbiAgICAgICAgeyByZXR1cm4gbG9va3VwS2V5KGtleSwgbWFwLmZhbGx0aHJvdWdoLCBoYW5kbGUsIGNvbnRleHQpIH1cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWFwLmZhbGx0aHJvdWdoLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBsb29rdXBLZXkoa2V5LCBtYXAuZmFsbHRocm91Z2hbaV0sIGhhbmRsZSwgY29udGV4dCk7XG4gICAgICAgIGlmIChyZXN1bHQpIHsgcmV0dXJuIHJlc3VsdCB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gTW9kaWZpZXIga2V5IHByZXNzZXMgZG9uJ3QgY291bnQgYXMgJ3JlYWwnIGtleSBwcmVzc2VzIGZvciB0aGVcbiAgLy8gcHVycG9zZSBvZiBrZXltYXAgZmFsbHRocm91Z2guXG4gIGZ1bmN0aW9uIGlzTW9kaWZpZXJLZXkodmFsdWUpIHtcbiAgICB2YXIgbmFtZSA9IHR5cGVvZiB2YWx1ZSA9PSBcInN0cmluZ1wiID8gdmFsdWUgOiBrZXlOYW1lc1t2YWx1ZS5rZXlDb2RlXTtcbiAgICByZXR1cm4gbmFtZSA9PSBcIkN0cmxcIiB8fCBuYW1lID09IFwiQWx0XCIgfHwgbmFtZSA9PSBcIlNoaWZ0XCIgfHwgbmFtZSA9PSBcIk1vZFwiXG4gIH1cblxuICBmdW5jdGlvbiBhZGRNb2RpZmllck5hbWVzKG5hbWUsIGV2ZW50LCBub1NoaWZ0KSB7XG4gICAgdmFyIGJhc2UgPSBuYW1lO1xuICAgIGlmIChldmVudC5hbHRLZXkgJiYgYmFzZSAhPSBcIkFsdFwiKSB7IG5hbWUgPSBcIkFsdC1cIiArIG5hbWU7IH1cbiAgICBpZiAoKGZsaXBDdHJsQ21kID8gZXZlbnQubWV0YUtleSA6IGV2ZW50LmN0cmxLZXkpICYmIGJhc2UgIT0gXCJDdHJsXCIpIHsgbmFtZSA9IFwiQ3RybC1cIiArIG5hbWU7IH1cbiAgICBpZiAoKGZsaXBDdHJsQ21kID8gZXZlbnQuY3RybEtleSA6IGV2ZW50Lm1ldGFLZXkpICYmIGJhc2UgIT0gXCJNb2RcIikgeyBuYW1lID0gXCJDbWQtXCIgKyBuYW1lOyB9XG4gICAgaWYgKCFub1NoaWZ0ICYmIGV2ZW50LnNoaWZ0S2V5ICYmIGJhc2UgIT0gXCJTaGlmdFwiKSB7IG5hbWUgPSBcIlNoaWZ0LVwiICsgbmFtZTsgfVxuICAgIHJldHVybiBuYW1lXG4gIH1cblxuICAvLyBMb29rIHVwIHRoZSBuYW1lIG9mIGEga2V5IGFzIGluZGljYXRlZCBieSBhbiBldmVudCBvYmplY3QuXG4gIGZ1bmN0aW9uIGtleU5hbWUoZXZlbnQsIG5vU2hpZnQpIHtcbiAgICBpZiAocHJlc3RvICYmIGV2ZW50LmtleUNvZGUgPT0gMzQgJiYgZXZlbnRbXCJjaGFyXCJdKSB7IHJldHVybiBmYWxzZSB9XG4gICAgdmFyIG5hbWUgPSBrZXlOYW1lc1tldmVudC5rZXlDb2RlXTtcbiAgICBpZiAobmFtZSA9PSBudWxsIHx8IGV2ZW50LmFsdEdyYXBoS2V5KSB7IHJldHVybiBmYWxzZSB9XG4gICAgLy8gQ3RybC1TY3JvbGxMb2NrIGhhcyBrZXlDb2RlIDMsIHNhbWUgYXMgQ3RybC1QYXVzZSxcbiAgICAvLyBzbyB3ZSdsbCB1c2UgZXZlbnQuY29kZSB3aGVuIGF2YWlsYWJsZSAoQ2hyb21lIDQ4KywgRkYgMzgrLCBTYWZhcmkgMTAuMSspXG4gICAgaWYgKGV2ZW50LmtleUNvZGUgPT0gMyAmJiBldmVudC5jb2RlKSB7IG5hbWUgPSBldmVudC5jb2RlOyB9XG4gICAgcmV0dXJuIGFkZE1vZGlmaWVyTmFtZXMobmFtZSwgZXZlbnQsIG5vU2hpZnQpXG4gIH1cblxuICBmdW5jdGlvbiBnZXRLZXlNYXAodmFsKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB2YWwgPT0gXCJzdHJpbmdcIiA/IGtleU1hcFt2YWxdIDogdmFsXG4gIH1cblxuICAvLyBIZWxwZXIgZm9yIGRlbGV0aW5nIHRleHQgbmVhciB0aGUgc2VsZWN0aW9uKHMpLCB1c2VkIHRvIGltcGxlbWVudFxuICAvLyBiYWNrc3BhY2UsIGRlbGV0ZSwgYW5kIHNpbWlsYXIgZnVuY3Rpb25hbGl0eS5cbiAgZnVuY3Rpb24gZGVsZXRlTmVhclNlbGVjdGlvbihjbSwgY29tcHV0ZSkge1xuICAgIHZhciByYW5nZXMgPSBjbS5kb2Muc2VsLnJhbmdlcywga2lsbCA9IFtdO1xuICAgIC8vIEJ1aWxkIHVwIGEgc2V0IG9mIHJhbmdlcyB0byBraWxsIGZpcnN0LCBtZXJnaW5nIG92ZXJsYXBwaW5nXG4gICAgLy8gcmFuZ2VzLlxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgdG9LaWxsID0gY29tcHV0ZShyYW5nZXNbaV0pO1xuICAgICAgd2hpbGUgKGtpbGwubGVuZ3RoICYmIGNtcCh0b0tpbGwuZnJvbSwgbHN0KGtpbGwpLnRvKSA8PSAwKSB7XG4gICAgICAgIHZhciByZXBsYWNlZCA9IGtpbGwucG9wKCk7XG4gICAgICAgIGlmIChjbXAocmVwbGFjZWQuZnJvbSwgdG9LaWxsLmZyb20pIDwgMCkge1xuICAgICAgICAgIHRvS2lsbC5mcm9tID0gcmVwbGFjZWQuZnJvbTtcbiAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBraWxsLnB1c2godG9LaWxsKTtcbiAgICB9XG4gICAgLy8gTmV4dCwgcmVtb3ZlIHRob3NlIGFjdHVhbCByYW5nZXMuXG4gICAgcnVuSW5PcChjbSwgZnVuY3Rpb24gKCkge1xuICAgICAgZm9yICh2YXIgaSA9IGtpbGwubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pXG4gICAgICAgIHsgcmVwbGFjZVJhbmdlKGNtLmRvYywgXCJcIiwga2lsbFtpXS5mcm9tLCBraWxsW2ldLnRvLCBcIitkZWxldGVcIik7IH1cbiAgICAgIGVuc3VyZUN1cnNvclZpc2libGUoY20pO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gbW92ZUNoYXJMb2dpY2FsbHkobGluZSwgY2gsIGRpcikge1xuICAgIHZhciB0YXJnZXQgPSBza2lwRXh0ZW5kaW5nQ2hhcnMobGluZS50ZXh0LCBjaCArIGRpciwgZGlyKTtcbiAgICByZXR1cm4gdGFyZ2V0IDwgMCB8fCB0YXJnZXQgPiBsaW5lLnRleHQubGVuZ3RoID8gbnVsbCA6IHRhcmdldFxuICB9XG5cbiAgZnVuY3Rpb24gbW92ZUxvZ2ljYWxseShsaW5lLCBzdGFydCwgZGlyKSB7XG4gICAgdmFyIGNoID0gbW92ZUNoYXJMb2dpY2FsbHkobGluZSwgc3RhcnQuY2gsIGRpcik7XG4gICAgcmV0dXJuIGNoID09IG51bGwgPyBudWxsIDogbmV3IFBvcyhzdGFydC5saW5lLCBjaCwgZGlyIDwgMCA/IFwiYWZ0ZXJcIiA6IFwiYmVmb3JlXCIpXG4gIH1cblxuICBmdW5jdGlvbiBlbmRPZkxpbmUodmlzdWFsbHksIGNtLCBsaW5lT2JqLCBsaW5lTm8sIGRpcikge1xuICAgIGlmICh2aXN1YWxseSkge1xuICAgICAgaWYgKGNtLmRvYy5kaXJlY3Rpb24gPT0gXCJydGxcIikgeyBkaXIgPSAtZGlyOyB9XG4gICAgICB2YXIgb3JkZXIgPSBnZXRPcmRlcihsaW5lT2JqLCBjbS5kb2MuZGlyZWN0aW9uKTtcbiAgICAgIGlmIChvcmRlcikge1xuICAgICAgICB2YXIgcGFydCA9IGRpciA8IDAgPyBsc3Qob3JkZXIpIDogb3JkZXJbMF07XG4gICAgICAgIHZhciBtb3ZlSW5TdG9yYWdlT3JkZXIgPSAoZGlyIDwgMCkgPT0gKHBhcnQubGV2ZWwgPT0gMSk7XG4gICAgICAgIHZhciBzdGlja3kgPSBtb3ZlSW5TdG9yYWdlT3JkZXIgPyBcImFmdGVyXCIgOiBcImJlZm9yZVwiO1xuICAgICAgICB2YXIgY2g7XG4gICAgICAgIC8vIFdpdGggYSB3cmFwcGVkIHJ0bCBjaHVuayAocG9zc2libHkgc3Bhbm5pbmcgbXVsdGlwbGUgYmlkaSBwYXJ0cyksXG4gICAgICAgIC8vIGl0IGNvdWxkIGJlIHRoYXQgdGhlIGxhc3QgYmlkaSBwYXJ0IGlzIG5vdCBvbiB0aGUgbGFzdCB2aXN1YWwgbGluZSxcbiAgICAgICAgLy8gc2luY2UgdmlzdWFsIGxpbmVzIGNvbnRhaW4gY29udGVudCBvcmRlci1jb25zZWN1dGl2ZSBjaHVua3MuXG4gICAgICAgIC8vIFRodXMsIGluIHJ0bCwgd2UgYXJlIGxvb2tpbmcgZm9yIHRoZSBmaXJzdCAoY29udGVudC1vcmRlcikgY2hhcmFjdGVyXG4gICAgICAgIC8vIGluIHRoZSBydGwgY2h1bmsgdGhhdCBpcyBvbiB0aGUgbGFzdCBsaW5lICh0aGF0IGlzLCB0aGUgc2FtZSBsaW5lXG4gICAgICAgIC8vIGFzIHRoZSBsYXN0IChjb250ZW50LW9yZGVyKSBjaGFyYWN0ZXIpLlxuICAgICAgICBpZiAocGFydC5sZXZlbCA+IDAgfHwgY20uZG9jLmRpcmVjdGlvbiA9PSBcInJ0bFwiKSB7XG4gICAgICAgICAgdmFyIHByZXAgPSBwcmVwYXJlTWVhc3VyZUZvckxpbmUoY20sIGxpbmVPYmopO1xuICAgICAgICAgIGNoID0gZGlyIDwgMCA/IGxpbmVPYmoudGV4dC5sZW5ndGggLSAxIDogMDtcbiAgICAgICAgICB2YXIgdGFyZ2V0VG9wID0gbWVhc3VyZUNoYXJQcmVwYXJlZChjbSwgcHJlcCwgY2gpLnRvcDtcbiAgICAgICAgICBjaCA9IGZpbmRGaXJzdChmdW5jdGlvbiAoY2gpIHsgcmV0dXJuIG1lYXN1cmVDaGFyUHJlcGFyZWQoY20sIHByZXAsIGNoKS50b3AgPT0gdGFyZ2V0VG9wOyB9LCAoZGlyIDwgMCkgPT0gKHBhcnQubGV2ZWwgPT0gMSkgPyBwYXJ0LmZyb20gOiBwYXJ0LnRvIC0gMSwgY2gpO1xuICAgICAgICAgIGlmIChzdGlja3kgPT0gXCJiZWZvcmVcIikgeyBjaCA9IG1vdmVDaGFyTG9naWNhbGx5KGxpbmVPYmosIGNoLCAxKTsgfVxuICAgICAgICB9IGVsc2UgeyBjaCA9IGRpciA8IDAgPyBwYXJ0LnRvIDogcGFydC5mcm9tOyB9XG4gICAgICAgIHJldHVybiBuZXcgUG9zKGxpbmVObywgY2gsIHN0aWNreSlcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG5ldyBQb3MobGluZU5vLCBkaXIgPCAwID8gbGluZU9iai50ZXh0Lmxlbmd0aCA6IDAsIGRpciA8IDAgPyBcImJlZm9yZVwiIDogXCJhZnRlclwiKVxuICB9XG5cbiAgZnVuY3Rpb24gbW92ZVZpc3VhbGx5KGNtLCBsaW5lLCBzdGFydCwgZGlyKSB7XG4gICAgdmFyIGJpZGkgPSBnZXRPcmRlcihsaW5lLCBjbS5kb2MuZGlyZWN0aW9uKTtcbiAgICBpZiAoIWJpZGkpIHsgcmV0dXJuIG1vdmVMb2dpY2FsbHkobGluZSwgc3RhcnQsIGRpcikgfVxuICAgIGlmIChzdGFydC5jaCA+PSBsaW5lLnRleHQubGVuZ3RoKSB7XG4gICAgICBzdGFydC5jaCA9IGxpbmUudGV4dC5sZW5ndGg7XG4gICAgICBzdGFydC5zdGlja3kgPSBcImJlZm9yZVwiO1xuICAgIH0gZWxzZSBpZiAoc3RhcnQuY2ggPD0gMCkge1xuICAgICAgc3RhcnQuY2ggPSAwO1xuICAgICAgc3RhcnQuc3RpY2t5ID0gXCJhZnRlclwiO1xuICAgIH1cbiAgICB2YXIgcGFydFBvcyA9IGdldEJpZGlQYXJ0QXQoYmlkaSwgc3RhcnQuY2gsIHN0YXJ0LnN0aWNreSksIHBhcnQgPSBiaWRpW3BhcnRQb3NdO1xuICAgIGlmIChjbS5kb2MuZGlyZWN0aW9uID09IFwibHRyXCIgJiYgcGFydC5sZXZlbCAlIDIgPT0gMCAmJiAoZGlyID4gMCA/IHBhcnQudG8gPiBzdGFydC5jaCA6IHBhcnQuZnJvbSA8IHN0YXJ0LmNoKSkge1xuICAgICAgLy8gQ2FzZSAxOiBXZSBtb3ZlIHdpdGhpbiBhbiBsdHIgcGFydCBpbiBhbiBsdHIgZWRpdG9yLiBFdmVuIHdpdGggd3JhcHBlZCBsaW5lcyxcbiAgICAgIC8vIG5vdGhpbmcgaW50ZXJlc3RpbmcgaGFwcGVucy5cbiAgICAgIHJldHVybiBtb3ZlTG9naWNhbGx5KGxpbmUsIHN0YXJ0LCBkaXIpXG4gICAgfVxuXG4gICAgdmFyIG12ID0gZnVuY3Rpb24gKHBvcywgZGlyKSB7IHJldHVybiBtb3ZlQ2hhckxvZ2ljYWxseShsaW5lLCBwb3MgaW5zdGFuY2VvZiBQb3MgPyBwb3MuY2ggOiBwb3MsIGRpcik7IH07XG4gICAgdmFyIHByZXA7XG4gICAgdmFyIGdldFdyYXBwZWRMaW5lRXh0ZW50ID0gZnVuY3Rpb24gKGNoKSB7XG4gICAgICBpZiAoIWNtLm9wdGlvbnMubGluZVdyYXBwaW5nKSB7IHJldHVybiB7YmVnaW46IDAsIGVuZDogbGluZS50ZXh0Lmxlbmd0aH0gfVxuICAgICAgcHJlcCA9IHByZXAgfHwgcHJlcGFyZU1lYXN1cmVGb3JMaW5lKGNtLCBsaW5lKTtcbiAgICAgIHJldHVybiB3cmFwcGVkTGluZUV4dGVudENoYXIoY20sIGxpbmUsIHByZXAsIGNoKVxuICAgIH07XG4gICAgdmFyIHdyYXBwZWRMaW5lRXh0ZW50ID0gZ2V0V3JhcHBlZExpbmVFeHRlbnQoc3RhcnQuc3RpY2t5ID09IFwiYmVmb3JlXCIgPyBtdihzdGFydCwgLTEpIDogc3RhcnQuY2gpO1xuXG4gICAgaWYgKGNtLmRvYy5kaXJlY3Rpb24gPT0gXCJydGxcIiB8fCBwYXJ0LmxldmVsID09IDEpIHtcbiAgICAgIHZhciBtb3ZlSW5TdG9yYWdlT3JkZXIgPSAocGFydC5sZXZlbCA9PSAxKSA9PSAoZGlyIDwgMCk7XG4gICAgICB2YXIgY2ggPSBtdihzdGFydCwgbW92ZUluU3RvcmFnZU9yZGVyID8gMSA6IC0xKTtcbiAgICAgIGlmIChjaCAhPSBudWxsICYmICghbW92ZUluU3RvcmFnZU9yZGVyID8gY2ggPj0gcGFydC5mcm9tICYmIGNoID49IHdyYXBwZWRMaW5lRXh0ZW50LmJlZ2luIDogY2ggPD0gcGFydC50byAmJiBjaCA8PSB3cmFwcGVkTGluZUV4dGVudC5lbmQpKSB7XG4gICAgICAgIC8vIENhc2UgMjogV2UgbW92ZSB3aXRoaW4gYW4gcnRsIHBhcnQgb3IgaW4gYW4gcnRsIGVkaXRvciBvbiB0aGUgc2FtZSB2aXN1YWwgbGluZVxuICAgICAgICB2YXIgc3RpY2t5ID0gbW92ZUluU3RvcmFnZU9yZGVyID8gXCJiZWZvcmVcIiA6IFwiYWZ0ZXJcIjtcbiAgICAgICAgcmV0dXJuIG5ldyBQb3Moc3RhcnQubGluZSwgY2gsIHN0aWNreSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBDYXNlIDM6IENvdWxkIG5vdCBtb3ZlIHdpdGhpbiB0aGlzIGJpZGkgcGFydCBpbiB0aGlzIHZpc3VhbCBsaW5lLCBzbyBsZWF2ZVxuICAgIC8vIHRoZSBjdXJyZW50IGJpZGkgcGFydFxuXG4gICAgdmFyIHNlYXJjaEluVmlzdWFsTGluZSA9IGZ1bmN0aW9uIChwYXJ0UG9zLCBkaXIsIHdyYXBwZWRMaW5lRXh0ZW50KSB7XG4gICAgICB2YXIgZ2V0UmVzID0gZnVuY3Rpb24gKGNoLCBtb3ZlSW5TdG9yYWdlT3JkZXIpIHsgcmV0dXJuIG1vdmVJblN0b3JhZ2VPcmRlclxuICAgICAgICA/IG5ldyBQb3Moc3RhcnQubGluZSwgbXYoY2gsIDEpLCBcImJlZm9yZVwiKVxuICAgICAgICA6IG5ldyBQb3Moc3RhcnQubGluZSwgY2gsIFwiYWZ0ZXJcIik7IH07XG5cbiAgICAgIGZvciAoOyBwYXJ0UG9zID49IDAgJiYgcGFydFBvcyA8IGJpZGkubGVuZ3RoOyBwYXJ0UG9zICs9IGRpcikge1xuICAgICAgICB2YXIgcGFydCA9IGJpZGlbcGFydFBvc107XG4gICAgICAgIHZhciBtb3ZlSW5TdG9yYWdlT3JkZXIgPSAoZGlyID4gMCkgPT0gKHBhcnQubGV2ZWwgIT0gMSk7XG4gICAgICAgIHZhciBjaCA9IG1vdmVJblN0b3JhZ2VPcmRlciA/IHdyYXBwZWRMaW5lRXh0ZW50LmJlZ2luIDogbXYod3JhcHBlZExpbmVFeHRlbnQuZW5kLCAtMSk7XG4gICAgICAgIGlmIChwYXJ0LmZyb20gPD0gY2ggJiYgY2ggPCBwYXJ0LnRvKSB7IHJldHVybiBnZXRSZXMoY2gsIG1vdmVJblN0b3JhZ2VPcmRlcikgfVxuICAgICAgICBjaCA9IG1vdmVJblN0b3JhZ2VPcmRlciA/IHBhcnQuZnJvbSA6IG12KHBhcnQudG8sIC0xKTtcbiAgICAgICAgaWYgKHdyYXBwZWRMaW5lRXh0ZW50LmJlZ2luIDw9IGNoICYmIGNoIDwgd3JhcHBlZExpbmVFeHRlbnQuZW5kKSB7IHJldHVybiBnZXRSZXMoY2gsIG1vdmVJblN0b3JhZ2VPcmRlcikgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICAvLyBDYXNlIDNhOiBMb29rIGZvciBvdGhlciBiaWRpIHBhcnRzIG9uIHRoZSBzYW1lIHZpc3VhbCBsaW5lXG4gICAgdmFyIHJlcyA9IHNlYXJjaEluVmlzdWFsTGluZShwYXJ0UG9zICsgZGlyLCBkaXIsIHdyYXBwZWRMaW5lRXh0ZW50KTtcbiAgICBpZiAocmVzKSB7IHJldHVybiByZXMgfVxuXG4gICAgLy8gQ2FzZSAzYjogTG9vayBmb3Igb3RoZXIgYmlkaSBwYXJ0cyBvbiB0aGUgbmV4dCB2aXN1YWwgbGluZVxuICAgIHZhciBuZXh0Q2ggPSBkaXIgPiAwID8gd3JhcHBlZExpbmVFeHRlbnQuZW5kIDogbXYod3JhcHBlZExpbmVFeHRlbnQuYmVnaW4sIC0xKTtcbiAgICBpZiAobmV4dENoICE9IG51bGwgJiYgIShkaXIgPiAwICYmIG5leHRDaCA9PSBsaW5lLnRleHQubGVuZ3RoKSkge1xuICAgICAgcmVzID0gc2VhcmNoSW5WaXN1YWxMaW5lKGRpciA+IDAgPyAwIDogYmlkaS5sZW5ndGggLSAxLCBkaXIsIGdldFdyYXBwZWRMaW5lRXh0ZW50KG5leHRDaCkpO1xuICAgICAgaWYgKHJlcykgeyByZXR1cm4gcmVzIH1cbiAgICB9XG5cbiAgICAvLyBDYXNlIDQ6IE5vd2hlcmUgdG8gbW92ZVxuICAgIHJldHVybiBudWxsXG4gIH1cblxuICAvLyBDb21tYW5kcyBhcmUgcGFyYW1ldGVyLWxlc3MgYWN0aW9ucyB0aGF0IGNhbiBiZSBwZXJmb3JtZWQgb24gYW5cbiAgLy8gZWRpdG9yLCBtb3N0bHkgdXNlZCBmb3Iga2V5YmluZGluZ3MuXG4gIHZhciBjb21tYW5kcyA9IHtcbiAgICBzZWxlY3RBbGw6IHNlbGVjdEFsbCxcbiAgICBzaW5nbGVTZWxlY3Rpb246IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20uc2V0U2VsZWN0aW9uKGNtLmdldEN1cnNvcihcImFuY2hvclwiKSwgY20uZ2V0Q3Vyc29yKFwiaGVhZFwiKSwgc2VsX2RvbnRTY3JvbGwpOyB9LFxuICAgIGtpbGxMaW5lOiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGRlbGV0ZU5lYXJTZWxlY3Rpb24oY20sIGZ1bmN0aW9uIChyYW5nZSkge1xuICAgICAgaWYgKHJhbmdlLmVtcHR5KCkpIHtcbiAgICAgICAgdmFyIGxlbiA9IGdldExpbmUoY20uZG9jLCByYW5nZS5oZWFkLmxpbmUpLnRleHQubGVuZ3RoO1xuICAgICAgICBpZiAocmFuZ2UuaGVhZC5jaCA9PSBsZW4gJiYgcmFuZ2UuaGVhZC5saW5lIDwgY20ubGFzdExpbmUoKSlcbiAgICAgICAgICB7IHJldHVybiB7ZnJvbTogcmFuZ2UuaGVhZCwgdG86IFBvcyhyYW5nZS5oZWFkLmxpbmUgKyAxLCAwKX0gfVxuICAgICAgICBlbHNlXG4gICAgICAgICAgeyByZXR1cm4ge2Zyb206IHJhbmdlLmhlYWQsIHRvOiBQb3MocmFuZ2UuaGVhZC5saW5lLCBsZW4pfSB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4ge2Zyb206IHJhbmdlLmZyb20oKSwgdG86IHJhbmdlLnRvKCl9XG4gICAgICB9XG4gICAgfSk7IH0sXG4gICAgZGVsZXRlTGluZTogZnVuY3Rpb24gKGNtKSB7IHJldHVybiBkZWxldGVOZWFyU2VsZWN0aW9uKGNtLCBmdW5jdGlvbiAocmFuZ2UpIHsgcmV0dXJuICh7XG4gICAgICBmcm9tOiBQb3MocmFuZ2UuZnJvbSgpLmxpbmUsIDApLFxuICAgICAgdG86IGNsaXBQb3MoY20uZG9jLCBQb3MocmFuZ2UudG8oKS5saW5lICsgMSwgMCkpXG4gICAgfSk7IH0pOyB9LFxuICAgIGRlbExpbmVMZWZ0OiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGRlbGV0ZU5lYXJTZWxlY3Rpb24oY20sIGZ1bmN0aW9uIChyYW5nZSkgeyByZXR1cm4gKHtcbiAgICAgIGZyb206IFBvcyhyYW5nZS5mcm9tKCkubGluZSwgMCksIHRvOiByYW5nZS5mcm9tKClcbiAgICB9KTsgfSk7IH0sXG4gICAgZGVsV3JhcHBlZExpbmVMZWZ0OiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGRlbGV0ZU5lYXJTZWxlY3Rpb24oY20sIGZ1bmN0aW9uIChyYW5nZSkge1xuICAgICAgdmFyIHRvcCA9IGNtLmNoYXJDb29yZHMocmFuZ2UuaGVhZCwgXCJkaXZcIikudG9wICsgNTtcbiAgICAgIHZhciBsZWZ0UG9zID0gY20uY29vcmRzQ2hhcih7bGVmdDogMCwgdG9wOiB0b3B9LCBcImRpdlwiKTtcbiAgICAgIHJldHVybiB7ZnJvbTogbGVmdFBvcywgdG86IHJhbmdlLmZyb20oKX1cbiAgICB9KTsgfSxcbiAgICBkZWxXcmFwcGVkTGluZVJpZ2h0OiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGRlbGV0ZU5lYXJTZWxlY3Rpb24oY20sIGZ1bmN0aW9uIChyYW5nZSkge1xuICAgICAgdmFyIHRvcCA9IGNtLmNoYXJDb29yZHMocmFuZ2UuaGVhZCwgXCJkaXZcIikudG9wICsgNTtcbiAgICAgIHZhciByaWdodFBvcyA9IGNtLmNvb3Jkc0NoYXIoe2xlZnQ6IGNtLmRpc3BsYXkubGluZURpdi5vZmZzZXRXaWR0aCArIDEwMCwgdG9wOiB0b3B9LCBcImRpdlwiKTtcbiAgICAgIHJldHVybiB7ZnJvbTogcmFuZ2UuZnJvbSgpLCB0bzogcmlnaHRQb3MgfVxuICAgIH0pOyB9LFxuICAgIHVuZG86IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20udW5kbygpOyB9LFxuICAgIHJlZG86IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20ucmVkbygpOyB9LFxuICAgIHVuZG9TZWxlY3Rpb246IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20udW5kb1NlbGVjdGlvbigpOyB9LFxuICAgIHJlZG9TZWxlY3Rpb246IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20ucmVkb1NlbGVjdGlvbigpOyB9LFxuICAgIGdvRG9jU3RhcnQ6IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20uZXh0ZW5kU2VsZWN0aW9uKFBvcyhjbS5maXJzdExpbmUoKSwgMCkpOyB9LFxuICAgIGdvRG9jRW5kOiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGNtLmV4dGVuZFNlbGVjdGlvbihQb3MoY20ubGFzdExpbmUoKSkpOyB9LFxuICAgIGdvTGluZVN0YXJ0OiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGNtLmV4dGVuZFNlbGVjdGlvbnNCeShmdW5jdGlvbiAocmFuZ2UpIHsgcmV0dXJuIGxpbmVTdGFydChjbSwgcmFuZ2UuaGVhZC5saW5lKTsgfSxcbiAgICAgIHtvcmlnaW46IFwiK21vdmVcIiwgYmlhczogMX1cbiAgICApOyB9LFxuICAgIGdvTGluZVN0YXJ0U21hcnQ6IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20uZXh0ZW5kU2VsZWN0aW9uc0J5KGZ1bmN0aW9uIChyYW5nZSkgeyByZXR1cm4gbGluZVN0YXJ0U21hcnQoY20sIHJhbmdlLmhlYWQpOyB9LFxuICAgICAge29yaWdpbjogXCIrbW92ZVwiLCBiaWFzOiAxfVxuICAgICk7IH0sXG4gICAgZ29MaW5lRW5kOiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGNtLmV4dGVuZFNlbGVjdGlvbnNCeShmdW5jdGlvbiAocmFuZ2UpIHsgcmV0dXJuIGxpbmVFbmQoY20sIHJhbmdlLmhlYWQubGluZSk7IH0sXG4gICAgICB7b3JpZ2luOiBcIittb3ZlXCIsIGJpYXM6IC0xfVxuICAgICk7IH0sXG4gICAgZ29MaW5lUmlnaHQ6IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20uZXh0ZW5kU2VsZWN0aW9uc0J5KGZ1bmN0aW9uIChyYW5nZSkge1xuICAgICAgdmFyIHRvcCA9IGNtLmN1cnNvckNvb3JkcyhyYW5nZS5oZWFkLCBcImRpdlwiKS50b3AgKyA1O1xuICAgICAgcmV0dXJuIGNtLmNvb3Jkc0NoYXIoe2xlZnQ6IGNtLmRpc3BsYXkubGluZURpdi5vZmZzZXRXaWR0aCArIDEwMCwgdG9wOiB0b3B9LCBcImRpdlwiKVxuICAgIH0sIHNlbF9tb3ZlKTsgfSxcbiAgICBnb0xpbmVMZWZ0OiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGNtLmV4dGVuZFNlbGVjdGlvbnNCeShmdW5jdGlvbiAocmFuZ2UpIHtcbiAgICAgIHZhciB0b3AgPSBjbS5jdXJzb3JDb29yZHMocmFuZ2UuaGVhZCwgXCJkaXZcIikudG9wICsgNTtcbiAgICAgIHJldHVybiBjbS5jb29yZHNDaGFyKHtsZWZ0OiAwLCB0b3A6IHRvcH0sIFwiZGl2XCIpXG4gICAgfSwgc2VsX21vdmUpOyB9LFxuICAgIGdvTGluZUxlZnRTbWFydDogZnVuY3Rpb24gKGNtKSB7IHJldHVybiBjbS5leHRlbmRTZWxlY3Rpb25zQnkoZnVuY3Rpb24gKHJhbmdlKSB7XG4gICAgICB2YXIgdG9wID0gY20uY3Vyc29yQ29vcmRzKHJhbmdlLmhlYWQsIFwiZGl2XCIpLnRvcCArIDU7XG4gICAgICB2YXIgcG9zID0gY20uY29vcmRzQ2hhcih7bGVmdDogMCwgdG9wOiB0b3B9LCBcImRpdlwiKTtcbiAgICAgIGlmIChwb3MuY2ggPCBjbS5nZXRMaW5lKHBvcy5saW5lKS5zZWFyY2goL1xcUy8pKSB7IHJldHVybiBsaW5lU3RhcnRTbWFydChjbSwgcmFuZ2UuaGVhZCkgfVxuICAgICAgcmV0dXJuIHBvc1xuICAgIH0sIHNlbF9tb3ZlKTsgfSxcbiAgICBnb0xpbmVVcDogZnVuY3Rpb24gKGNtKSB7IHJldHVybiBjbS5tb3ZlVigtMSwgXCJsaW5lXCIpOyB9LFxuICAgIGdvTGluZURvd246IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20ubW92ZVYoMSwgXCJsaW5lXCIpOyB9LFxuICAgIGdvUGFnZVVwOiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGNtLm1vdmVWKC0xLCBcInBhZ2VcIik7IH0sXG4gICAgZ29QYWdlRG93bjogZnVuY3Rpb24gKGNtKSB7IHJldHVybiBjbS5tb3ZlVigxLCBcInBhZ2VcIik7IH0sXG4gICAgZ29DaGFyTGVmdDogZnVuY3Rpb24gKGNtKSB7IHJldHVybiBjbS5tb3ZlSCgtMSwgXCJjaGFyXCIpOyB9LFxuICAgIGdvQ2hhclJpZ2h0OiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGNtLm1vdmVIKDEsIFwiY2hhclwiKTsgfSxcbiAgICBnb0NvbHVtbkxlZnQ6IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20ubW92ZUgoLTEsIFwiY29sdW1uXCIpOyB9LFxuICAgIGdvQ29sdW1uUmlnaHQ6IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20ubW92ZUgoMSwgXCJjb2x1bW5cIik7IH0sXG4gICAgZ29Xb3JkTGVmdDogZnVuY3Rpb24gKGNtKSB7IHJldHVybiBjbS5tb3ZlSCgtMSwgXCJ3b3JkXCIpOyB9LFxuICAgIGdvR3JvdXBSaWdodDogZnVuY3Rpb24gKGNtKSB7IHJldHVybiBjbS5tb3ZlSCgxLCBcImdyb3VwXCIpOyB9LFxuICAgIGdvR3JvdXBMZWZ0OiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGNtLm1vdmVIKC0xLCBcImdyb3VwXCIpOyB9LFxuICAgIGdvV29yZFJpZ2h0OiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGNtLm1vdmVIKDEsIFwid29yZFwiKTsgfSxcbiAgICBkZWxDaGFyQmVmb3JlOiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGNtLmRlbGV0ZUgoLTEsIFwiY29kZXBvaW50XCIpOyB9LFxuICAgIGRlbENoYXJBZnRlcjogZnVuY3Rpb24gKGNtKSB7IHJldHVybiBjbS5kZWxldGVIKDEsIFwiY2hhclwiKTsgfSxcbiAgICBkZWxXb3JkQmVmb3JlOiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGNtLmRlbGV0ZUgoLTEsIFwid29yZFwiKTsgfSxcbiAgICBkZWxXb3JkQWZ0ZXI6IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20uZGVsZXRlSCgxLCBcIndvcmRcIik7IH0sXG4gICAgZGVsR3JvdXBCZWZvcmU6IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20uZGVsZXRlSCgtMSwgXCJncm91cFwiKTsgfSxcbiAgICBkZWxHcm91cEFmdGVyOiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGNtLmRlbGV0ZUgoMSwgXCJncm91cFwiKTsgfSxcbiAgICBpbmRlbnRBdXRvOiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGNtLmluZGVudFNlbGVjdGlvbihcInNtYXJ0XCIpOyB9LFxuICAgIGluZGVudE1vcmU6IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20uaW5kZW50U2VsZWN0aW9uKFwiYWRkXCIpOyB9LFxuICAgIGluZGVudExlc3M6IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20uaW5kZW50U2VsZWN0aW9uKFwic3VidHJhY3RcIik7IH0sXG4gICAgaW5zZXJ0VGFiOiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGNtLnJlcGxhY2VTZWxlY3Rpb24oXCJcXHRcIik7IH0sXG4gICAgaW5zZXJ0U29mdFRhYjogZnVuY3Rpb24gKGNtKSB7XG4gICAgICB2YXIgc3BhY2VzID0gW10sIHJhbmdlcyA9IGNtLmxpc3RTZWxlY3Rpb25zKCksIHRhYlNpemUgPSBjbS5vcHRpb25zLnRhYlNpemU7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcG9zID0gcmFuZ2VzW2ldLmZyb20oKTtcbiAgICAgICAgdmFyIGNvbCA9IGNvdW50Q29sdW1uKGNtLmdldExpbmUocG9zLmxpbmUpLCBwb3MuY2gsIHRhYlNpemUpO1xuICAgICAgICBzcGFjZXMucHVzaChzcGFjZVN0cih0YWJTaXplIC0gY29sICUgdGFiU2l6ZSkpO1xuICAgICAgfVxuICAgICAgY20ucmVwbGFjZVNlbGVjdGlvbnMoc3BhY2VzKTtcbiAgICB9LFxuICAgIGRlZmF1bHRUYWI6IGZ1bmN0aW9uIChjbSkge1xuICAgICAgaWYgKGNtLnNvbWV0aGluZ1NlbGVjdGVkKCkpIHsgY20uaW5kZW50U2VsZWN0aW9uKFwiYWRkXCIpOyB9XG4gICAgICBlbHNlIHsgY20uZXhlY0NvbW1hbmQoXCJpbnNlcnRUYWJcIik7IH1cbiAgICB9LFxuICAgIC8vIFN3YXAgdGhlIHR3byBjaGFycyBsZWZ0IGFuZCByaWdodCBvZiBlYWNoIHNlbGVjdGlvbidzIGhlYWQuXG4gICAgLy8gTW92ZSBjdXJzb3IgYmVoaW5kIHRoZSB0d28gc3dhcHBlZCBjaGFyYWN0ZXJzIGFmdGVyd2FyZHMuXG4gICAgLy9cbiAgICAvLyBEb2Vzbid0IGNvbnNpZGVyIGxpbmUgZmVlZHMgYSBjaGFyYWN0ZXIuXG4gICAgLy8gRG9lc24ndCBzY2FuIG1vcmUgdGhhbiBvbmUgbGluZSBhYm92ZSB0byBmaW5kIGEgY2hhcmFjdGVyLlxuICAgIC8vIERvZXNuJ3QgZG8gYW55dGhpbmcgb24gYW4gZW1wdHkgbGluZS5cbiAgICAvLyBEb2Vzbid0IGRvIGFueXRoaW5nIHdpdGggbm9uLWVtcHR5IHNlbGVjdGlvbnMuXG4gICAgdHJhbnNwb3NlQ2hhcnM6IGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gcnVuSW5PcChjbSwgZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIHJhbmdlcyA9IGNtLmxpc3RTZWxlY3Rpb25zKCksIG5ld1NlbCA9IFtdO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByYW5nZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKCFyYW5nZXNbaV0uZW1wdHkoKSkgeyBjb250aW51ZSB9XG4gICAgICAgIHZhciBjdXIgPSByYW5nZXNbaV0uaGVhZCwgbGluZSA9IGdldExpbmUoY20uZG9jLCBjdXIubGluZSkudGV4dDtcbiAgICAgICAgaWYgKGxpbmUpIHtcbiAgICAgICAgICBpZiAoY3VyLmNoID09IGxpbmUubGVuZ3RoKSB7IGN1ciA9IG5ldyBQb3MoY3VyLmxpbmUsIGN1ci5jaCAtIDEpOyB9XG4gICAgICAgICAgaWYgKGN1ci5jaCA+IDApIHtcbiAgICAgICAgICAgIGN1ciA9IG5ldyBQb3MoY3VyLmxpbmUsIGN1ci5jaCArIDEpO1xuICAgICAgICAgICAgY20ucmVwbGFjZVJhbmdlKGxpbmUuY2hhckF0KGN1ci5jaCAtIDEpICsgbGluZS5jaGFyQXQoY3VyLmNoIC0gMiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgUG9zKGN1ci5saW5lLCBjdXIuY2ggLSAyKSwgY3VyLCBcIit0cmFuc3Bvc2VcIik7XG4gICAgICAgICAgfSBlbHNlIGlmIChjdXIubGluZSA+IGNtLmRvYy5maXJzdCkge1xuICAgICAgICAgICAgdmFyIHByZXYgPSBnZXRMaW5lKGNtLmRvYywgY3VyLmxpbmUgLSAxKS50ZXh0O1xuICAgICAgICAgICAgaWYgKHByZXYpIHtcbiAgICAgICAgICAgICAgY3VyID0gbmV3IFBvcyhjdXIubGluZSwgMSk7XG4gICAgICAgICAgICAgIGNtLnJlcGxhY2VSYW5nZShsaW5lLmNoYXJBdCgwKSArIGNtLmRvYy5saW5lU2VwYXJhdG9yKCkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldi5jaGFyQXQocHJldi5sZW5ndGggLSAxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBvcyhjdXIubGluZSAtIDEsIHByZXYubGVuZ3RoIC0gMSksIGN1ciwgXCIrdHJhbnNwb3NlXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBuZXdTZWwucHVzaChuZXcgUmFuZ2UoY3VyLCBjdXIpKTtcbiAgICAgIH1cbiAgICAgIGNtLnNldFNlbGVjdGlvbnMobmV3U2VsKTtcbiAgICB9KTsgfSxcbiAgICBuZXdsaW5lQW5kSW5kZW50OiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIHJ1bkluT3AoY20sIGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBzZWxzID0gY20ubGlzdFNlbGVjdGlvbnMoKTtcbiAgICAgIGZvciAodmFyIGkgPSBzZWxzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKVxuICAgICAgICB7IGNtLnJlcGxhY2VSYW5nZShjbS5kb2MubGluZVNlcGFyYXRvcigpLCBzZWxzW2ldLmFuY2hvciwgc2Vsc1tpXS5oZWFkLCBcIitpbnB1dFwiKTsgfVxuICAgICAgc2VscyA9IGNtLmxpc3RTZWxlY3Rpb25zKCk7XG4gICAgICBmb3IgKHZhciBpJDEgPSAwOyBpJDEgPCBzZWxzLmxlbmd0aDsgaSQxKyspXG4gICAgICAgIHsgY20uaW5kZW50TGluZShzZWxzW2kkMV0uZnJvbSgpLmxpbmUsIG51bGwsIHRydWUpOyB9XG4gICAgICBlbnN1cmVDdXJzb3JWaXNpYmxlKGNtKTtcbiAgICB9KTsgfSxcbiAgICBvcGVuTGluZTogZnVuY3Rpb24gKGNtKSB7IHJldHVybiBjbS5yZXBsYWNlU2VsZWN0aW9uKFwiXFxuXCIsIFwic3RhcnRcIik7IH0sXG4gICAgdG9nZ2xlT3ZlcndyaXRlOiBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIGNtLnRvZ2dsZU92ZXJ3cml0ZSgpOyB9XG4gIH07XG5cblxuICBmdW5jdGlvbiBsaW5lU3RhcnQoY20sIGxpbmVOKSB7XG4gICAgdmFyIGxpbmUgPSBnZXRMaW5lKGNtLmRvYywgbGluZU4pO1xuICAgIHZhciB2aXN1YWwgPSB2aXN1YWxMaW5lKGxpbmUpO1xuICAgIGlmICh2aXN1YWwgIT0gbGluZSkgeyBsaW5lTiA9IGxpbmVObyh2aXN1YWwpOyB9XG4gICAgcmV0dXJuIGVuZE9mTGluZSh0cnVlLCBjbSwgdmlzdWFsLCBsaW5lTiwgMSlcbiAgfVxuICBmdW5jdGlvbiBsaW5lRW5kKGNtLCBsaW5lTikge1xuICAgIHZhciBsaW5lID0gZ2V0TGluZShjbS5kb2MsIGxpbmVOKTtcbiAgICB2YXIgdmlzdWFsID0gdmlzdWFsTGluZUVuZChsaW5lKTtcbiAgICBpZiAodmlzdWFsICE9IGxpbmUpIHsgbGluZU4gPSBsaW5lTm8odmlzdWFsKTsgfVxuICAgIHJldHVybiBlbmRPZkxpbmUodHJ1ZSwgY20sIGxpbmUsIGxpbmVOLCAtMSlcbiAgfVxuICBmdW5jdGlvbiBsaW5lU3RhcnRTbWFydChjbSwgcG9zKSB7XG4gICAgdmFyIHN0YXJ0ID0gbGluZVN0YXJ0KGNtLCBwb3MubGluZSk7XG4gICAgdmFyIGxpbmUgPSBnZXRMaW5lKGNtLmRvYywgc3RhcnQubGluZSk7XG4gICAgdmFyIG9yZGVyID0gZ2V0T3JkZXIobGluZSwgY20uZG9jLmRpcmVjdGlvbik7XG4gICAgaWYgKCFvcmRlciB8fCBvcmRlclswXS5sZXZlbCA9PSAwKSB7XG4gICAgICB2YXIgZmlyc3ROb25XUyA9IE1hdGgubWF4KHN0YXJ0LmNoLCBsaW5lLnRleHQuc2VhcmNoKC9cXFMvKSk7XG4gICAgICB2YXIgaW5XUyA9IHBvcy5saW5lID09IHN0YXJ0LmxpbmUgJiYgcG9zLmNoIDw9IGZpcnN0Tm9uV1MgJiYgcG9zLmNoO1xuICAgICAgcmV0dXJuIFBvcyhzdGFydC5saW5lLCBpbldTID8gMCA6IGZpcnN0Tm9uV1MsIHN0YXJ0LnN0aWNreSlcbiAgICB9XG4gICAgcmV0dXJuIHN0YXJ0XG4gIH1cblxuICAvLyBSdW4gYSBoYW5kbGVyIHRoYXQgd2FzIGJvdW5kIHRvIGEga2V5LlxuICBmdW5jdGlvbiBkb0hhbmRsZUJpbmRpbmcoY20sIGJvdW5kLCBkcm9wU2hpZnQpIHtcbiAgICBpZiAodHlwZW9mIGJvdW5kID09IFwic3RyaW5nXCIpIHtcbiAgICAgIGJvdW5kID0gY29tbWFuZHNbYm91bmRdO1xuICAgICAgaWYgKCFib3VuZCkgeyByZXR1cm4gZmFsc2UgfVxuICAgIH1cbiAgICAvLyBFbnN1cmUgcHJldmlvdXMgaW5wdXQgaGFzIGJlZW4gcmVhZCwgc28gdGhhdCB0aGUgaGFuZGxlciBzZWVzIGFcbiAgICAvLyBjb25zaXN0ZW50IHZpZXcgb2YgdGhlIGRvY3VtZW50XG4gICAgY20uZGlzcGxheS5pbnB1dC5lbnN1cmVQb2xsZWQoKTtcbiAgICB2YXIgcHJldlNoaWZ0ID0gY20uZGlzcGxheS5zaGlmdCwgZG9uZSA9IGZhbHNlO1xuICAgIHRyeSB7XG4gICAgICBpZiAoY20uaXNSZWFkT25seSgpKSB7IGNtLnN0YXRlLnN1cHByZXNzRWRpdHMgPSB0cnVlOyB9XG4gICAgICBpZiAoZHJvcFNoaWZ0KSB7IGNtLmRpc3BsYXkuc2hpZnQgPSBmYWxzZTsgfVxuICAgICAgZG9uZSA9IGJvdW5kKGNtKSAhPSBQYXNzO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBjbS5kaXNwbGF5LnNoaWZ0ID0gcHJldlNoaWZ0O1xuICAgICAgY20uc3RhdGUuc3VwcHJlc3NFZGl0cyA9IGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gZG9uZVxuICB9XG5cbiAgZnVuY3Rpb24gbG9va3VwS2V5Rm9yRWRpdG9yKGNtLCBuYW1lLCBoYW5kbGUpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNtLnN0YXRlLmtleU1hcHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciByZXN1bHQgPSBsb29rdXBLZXkobmFtZSwgY20uc3RhdGUua2V5TWFwc1tpXSwgaGFuZGxlLCBjbSk7XG4gICAgICBpZiAocmVzdWx0KSB7IHJldHVybiByZXN1bHQgfVxuICAgIH1cbiAgICByZXR1cm4gKGNtLm9wdGlvbnMuZXh0cmFLZXlzICYmIGxvb2t1cEtleShuYW1lLCBjbS5vcHRpb25zLmV4dHJhS2V5cywgaGFuZGxlLCBjbSkpXG4gICAgICB8fCBsb29rdXBLZXkobmFtZSwgY20ub3B0aW9ucy5rZXlNYXAsIGhhbmRsZSwgY20pXG4gIH1cblxuICAvLyBOb3RlIHRoYXQsIGRlc3BpdGUgdGhlIG5hbWUsIHRoaXMgZnVuY3Rpb24gaXMgYWxzbyB1c2VkIHRvIGNoZWNrXG4gIC8vIGZvciBib3VuZCBtb3VzZSBjbGlja3MuXG5cbiAgdmFyIHN0b3BTZXEgPSBuZXcgRGVsYXllZDtcblxuICBmdW5jdGlvbiBkaXNwYXRjaEtleShjbSwgbmFtZSwgZSwgaGFuZGxlKSB7XG4gICAgdmFyIHNlcSA9IGNtLnN0YXRlLmtleVNlcTtcbiAgICBpZiAoc2VxKSB7XG4gICAgICBpZiAoaXNNb2RpZmllcktleShuYW1lKSkgeyByZXR1cm4gXCJoYW5kbGVkXCIgfVxuICAgICAgaWYgKC9cXCckLy50ZXN0KG5hbWUpKVxuICAgICAgICB7IGNtLnN0YXRlLmtleVNlcSA9IG51bGw7IH1cbiAgICAgIGVsc2VcbiAgICAgICAgeyBzdG9wU2VxLnNldCg1MCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGlmIChjbS5zdGF0ZS5rZXlTZXEgPT0gc2VxKSB7XG4gICAgICAgICAgICBjbS5zdGF0ZS5rZXlTZXEgPSBudWxsO1xuICAgICAgICAgICAgY20uZGlzcGxheS5pbnB1dC5yZXNldCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7IH1cbiAgICAgIGlmIChkaXNwYXRjaEtleUlubmVyKGNtLCBzZXEgKyBcIiBcIiArIG5hbWUsIGUsIGhhbmRsZSkpIHsgcmV0dXJuIHRydWUgfVxuICAgIH1cbiAgICByZXR1cm4gZGlzcGF0Y2hLZXlJbm5lcihjbSwgbmFtZSwgZSwgaGFuZGxlKVxuICB9XG5cbiAgZnVuY3Rpb24gZGlzcGF0Y2hLZXlJbm5lcihjbSwgbmFtZSwgZSwgaGFuZGxlKSB7XG4gICAgdmFyIHJlc3VsdCA9IGxvb2t1cEtleUZvckVkaXRvcihjbSwgbmFtZSwgaGFuZGxlKTtcblxuICAgIGlmIChyZXN1bHQgPT0gXCJtdWx0aVwiKVxuICAgICAgeyBjbS5zdGF0ZS5rZXlTZXEgPSBuYW1lOyB9XG4gICAgaWYgKHJlc3VsdCA9PSBcImhhbmRsZWRcIilcbiAgICAgIHsgc2lnbmFsTGF0ZXIoY20sIFwia2V5SGFuZGxlZFwiLCBjbSwgbmFtZSwgZSk7IH1cblxuICAgIGlmIChyZXN1bHQgPT0gXCJoYW5kbGVkXCIgfHwgcmVzdWx0ID09IFwibXVsdGlcIikge1xuICAgICAgZV9wcmV2ZW50RGVmYXVsdChlKTtcbiAgICAgIHJlc3RhcnRCbGluayhjbSk7XG4gICAgfVxuXG4gICAgcmV0dXJuICEhcmVzdWx0XG4gIH1cblxuICAvLyBIYW5kbGUgYSBrZXkgZnJvbSB0aGUga2V5ZG93biBldmVudC5cbiAgZnVuY3Rpb24gaGFuZGxlS2V5QmluZGluZyhjbSwgZSkge1xuICAgIHZhciBuYW1lID0ga2V5TmFtZShlLCB0cnVlKTtcbiAgICBpZiAoIW5hbWUpIHsgcmV0dXJuIGZhbHNlIH1cblxuICAgIGlmIChlLnNoaWZ0S2V5ICYmICFjbS5zdGF0ZS5rZXlTZXEpIHtcbiAgICAgIC8vIEZpcnN0IHRyeSB0byByZXNvbHZlIGZ1bGwgbmFtZSAoaW5jbHVkaW5nICdTaGlmdC0nKS4gRmFpbGluZ1xuICAgICAgLy8gdGhhdCwgc2VlIGlmIHRoZXJlIGlzIGEgY3Vyc29yLW1vdGlvbiBjb21tYW5kIChzdGFydGluZyB3aXRoXG4gICAgICAvLyAnZ28nKSBib3VuZCB0byB0aGUga2V5bmFtZSB3aXRob3V0ICdTaGlmdC0nLlxuICAgICAgcmV0dXJuIGRpc3BhdGNoS2V5KGNtLCBcIlNoaWZ0LVwiICsgbmFtZSwgZSwgZnVuY3Rpb24gKGIpIHsgcmV0dXJuIGRvSGFuZGxlQmluZGluZyhjbSwgYiwgdHJ1ZSk7IH0pXG4gICAgICAgICAgfHwgZGlzcGF0Y2hLZXkoY20sIG5hbWUsIGUsIGZ1bmN0aW9uIChiKSB7XG4gICAgICAgICAgICAgICBpZiAodHlwZW9mIGIgPT0gXCJzdHJpbmdcIiA/IC9eZ29bQS1aXS8udGVzdChiKSA6IGIubW90aW9uKVxuICAgICAgICAgICAgICAgICB7IHJldHVybiBkb0hhbmRsZUJpbmRpbmcoY20sIGIpIH1cbiAgICAgICAgICAgICB9KVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZGlzcGF0Y2hLZXkoY20sIG5hbWUsIGUsIGZ1bmN0aW9uIChiKSB7IHJldHVybiBkb0hhbmRsZUJpbmRpbmcoY20sIGIpOyB9KVxuICAgIH1cbiAgfVxuXG4gIC8vIEhhbmRsZSBhIGtleSBmcm9tIHRoZSBrZXlwcmVzcyBldmVudFxuICBmdW5jdGlvbiBoYW5kbGVDaGFyQmluZGluZyhjbSwgZSwgY2gpIHtcbiAgICByZXR1cm4gZGlzcGF0Y2hLZXkoY20sIFwiJ1wiICsgY2ggKyBcIidcIiwgZSwgZnVuY3Rpb24gKGIpIHsgcmV0dXJuIGRvSGFuZGxlQmluZGluZyhjbSwgYiwgdHJ1ZSk7IH0pXG4gIH1cblxuICB2YXIgbGFzdFN0b3BwZWRLZXkgPSBudWxsO1xuICBmdW5jdGlvbiBvbktleURvd24oZSkge1xuICAgIHZhciBjbSA9IHRoaXM7XG4gICAgaWYgKGUudGFyZ2V0ICYmIGUudGFyZ2V0ICE9IGNtLmRpc3BsYXkuaW5wdXQuZ2V0RmllbGQoKSkgeyByZXR1cm4gfVxuICAgIGNtLmN1ck9wLmZvY3VzID0gYWN0aXZlRWx0KCk7XG4gICAgaWYgKHNpZ25hbERPTUV2ZW50KGNtLCBlKSkgeyByZXR1cm4gfVxuICAgIC8vIElFIGRvZXMgc3RyYW5nZSB0aGluZ3Mgd2l0aCBlc2NhcGUuXG4gICAgaWYgKGllICYmIGllX3ZlcnNpb24gPCAxMSAmJiBlLmtleUNvZGUgPT0gMjcpIHsgZS5yZXR1cm5WYWx1ZSA9IGZhbHNlOyB9XG4gICAgdmFyIGNvZGUgPSBlLmtleUNvZGU7XG4gICAgY20uZGlzcGxheS5zaGlmdCA9IGNvZGUgPT0gMTYgfHwgZS5zaGlmdEtleTtcbiAgICB2YXIgaGFuZGxlZCA9IGhhbmRsZUtleUJpbmRpbmcoY20sIGUpO1xuICAgIGlmIChwcmVzdG8pIHtcbiAgICAgIGxhc3RTdG9wcGVkS2V5ID0gaGFuZGxlZCA/IGNvZGUgOiBudWxsO1xuICAgICAgLy8gT3BlcmEgaGFzIG5vIGN1dCBldmVudC4uLiB3ZSB0cnkgdG8gYXQgbGVhc3QgY2F0Y2ggdGhlIGtleSBjb21ib1xuICAgICAgaWYgKCFoYW5kbGVkICYmIGNvZGUgPT0gODggJiYgIWhhc0NvcHlFdmVudCAmJiAobWFjID8gZS5tZXRhS2V5IDogZS5jdHJsS2V5KSlcbiAgICAgICAgeyBjbS5yZXBsYWNlU2VsZWN0aW9uKFwiXCIsIG51bGwsIFwiY3V0XCIpOyB9XG4gICAgfVxuICAgIGlmIChnZWNrbyAmJiAhbWFjICYmICFoYW5kbGVkICYmIGNvZGUgPT0gNDYgJiYgZS5zaGlmdEtleSAmJiAhZS5jdHJsS2V5ICYmIGRvY3VtZW50LmV4ZWNDb21tYW5kKVxuICAgICAgeyBkb2N1bWVudC5leGVjQ29tbWFuZChcImN1dFwiKTsgfVxuXG4gICAgLy8gVHVybiBtb3VzZSBpbnRvIGNyb3NzaGFpciB3aGVuIEFsdCBpcyBoZWxkIG9uIE1hYy5cbiAgICBpZiAoY29kZSA9PSAxOCAmJiAhL1xcYkNvZGVNaXJyb3ItY3Jvc3NoYWlyXFxiLy50ZXN0KGNtLmRpc3BsYXkubGluZURpdi5jbGFzc05hbWUpKVxuICAgICAgeyBzaG93Q3Jvc3NIYWlyKGNtKTsgfVxuICB9XG5cbiAgZnVuY3Rpb24gc2hvd0Nyb3NzSGFpcihjbSkge1xuICAgIHZhciBsaW5lRGl2ID0gY20uZGlzcGxheS5saW5lRGl2O1xuICAgIGFkZENsYXNzKGxpbmVEaXYsIFwiQ29kZU1pcnJvci1jcm9zc2hhaXJcIik7XG5cbiAgICBmdW5jdGlvbiB1cChlKSB7XG4gICAgICBpZiAoZS5rZXlDb2RlID09IDE4IHx8ICFlLmFsdEtleSkge1xuICAgICAgICBybUNsYXNzKGxpbmVEaXYsIFwiQ29kZU1pcnJvci1jcm9zc2hhaXJcIik7XG4gICAgICAgIG9mZihkb2N1bWVudCwgXCJrZXl1cFwiLCB1cCk7XG4gICAgICAgIG9mZihkb2N1bWVudCwgXCJtb3VzZW92ZXJcIiwgdXApO1xuICAgICAgfVxuICAgIH1cbiAgICBvbihkb2N1bWVudCwgXCJrZXl1cFwiLCB1cCk7XG4gICAgb24oZG9jdW1lbnQsIFwibW91c2VvdmVyXCIsIHVwKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG9uS2V5VXAoZSkge1xuICAgIGlmIChlLmtleUNvZGUgPT0gMTYpIHsgdGhpcy5kb2Muc2VsLnNoaWZ0ID0gZmFsc2U7IH1cbiAgICBzaWduYWxET01FdmVudCh0aGlzLCBlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG9uS2V5UHJlc3MoZSkge1xuICAgIHZhciBjbSA9IHRoaXM7XG4gICAgaWYgKGUudGFyZ2V0ICYmIGUudGFyZ2V0ICE9IGNtLmRpc3BsYXkuaW5wdXQuZ2V0RmllbGQoKSkgeyByZXR1cm4gfVxuICAgIGlmIChldmVudEluV2lkZ2V0KGNtLmRpc3BsYXksIGUpIHx8IHNpZ25hbERPTUV2ZW50KGNtLCBlKSB8fCBlLmN0cmxLZXkgJiYgIWUuYWx0S2V5IHx8IG1hYyAmJiBlLm1ldGFLZXkpIHsgcmV0dXJuIH1cbiAgICB2YXIga2V5Q29kZSA9IGUua2V5Q29kZSwgY2hhckNvZGUgPSBlLmNoYXJDb2RlO1xuICAgIGlmIChwcmVzdG8gJiYga2V5Q29kZSA9PSBsYXN0U3RvcHBlZEtleSkge2xhc3RTdG9wcGVkS2V5ID0gbnVsbDsgZV9wcmV2ZW50RGVmYXVsdChlKTsgcmV0dXJufVxuICAgIGlmICgocHJlc3RvICYmICghZS53aGljaCB8fCBlLndoaWNoIDwgMTApKSAmJiBoYW5kbGVLZXlCaW5kaW5nKGNtLCBlKSkgeyByZXR1cm4gfVxuICAgIHZhciBjaCA9IFN0cmluZy5mcm9tQ2hhckNvZGUoY2hhckNvZGUgPT0gbnVsbCA/IGtleUNvZGUgOiBjaGFyQ29kZSk7XG4gICAgLy8gU29tZSBicm93c2VycyBmaXJlIGtleXByZXNzIGV2ZW50cyBmb3IgYmFja3NwYWNlXG4gICAgaWYgKGNoID09IFwiXFx4MDhcIikgeyByZXR1cm4gfVxuICAgIGlmIChoYW5kbGVDaGFyQmluZGluZyhjbSwgZSwgY2gpKSB7IHJldHVybiB9XG4gICAgY20uZGlzcGxheS5pbnB1dC5vbktleVByZXNzKGUpO1xuICB9XG5cbiAgdmFyIERPVUJMRUNMSUNLX0RFTEFZID0gNDAwO1xuXG4gIHZhciBQYXN0Q2xpY2sgPSBmdW5jdGlvbih0aW1lLCBwb3MsIGJ1dHRvbikge1xuICAgIHRoaXMudGltZSA9IHRpbWU7XG4gICAgdGhpcy5wb3MgPSBwb3M7XG4gICAgdGhpcy5idXR0b24gPSBidXR0b247XG4gIH07XG5cbiAgUGFzdENsaWNrLnByb3RvdHlwZS5jb21wYXJlID0gZnVuY3Rpb24gKHRpbWUsIHBvcywgYnV0dG9uKSB7XG4gICAgcmV0dXJuIHRoaXMudGltZSArIERPVUJMRUNMSUNLX0RFTEFZID4gdGltZSAmJlxuICAgICAgY21wKHBvcywgdGhpcy5wb3MpID09IDAgJiYgYnV0dG9uID09IHRoaXMuYnV0dG9uXG4gIH07XG5cbiAgdmFyIGxhc3RDbGljaywgbGFzdERvdWJsZUNsaWNrO1xuICBmdW5jdGlvbiBjbGlja1JlcGVhdChwb3MsIGJ1dHRvbikge1xuICAgIHZhciBub3cgPSArbmV3IERhdGU7XG4gICAgaWYgKGxhc3REb3VibGVDbGljayAmJiBsYXN0RG91YmxlQ2xpY2suY29tcGFyZShub3csIHBvcywgYnV0dG9uKSkge1xuICAgICAgbGFzdENsaWNrID0gbGFzdERvdWJsZUNsaWNrID0gbnVsbDtcbiAgICAgIHJldHVybiBcInRyaXBsZVwiXG4gICAgfSBlbHNlIGlmIChsYXN0Q2xpY2sgJiYgbGFzdENsaWNrLmNvbXBhcmUobm93LCBwb3MsIGJ1dHRvbikpIHtcbiAgICAgIGxhc3REb3VibGVDbGljayA9IG5ldyBQYXN0Q2xpY2sobm93LCBwb3MsIGJ1dHRvbik7XG4gICAgICBsYXN0Q2xpY2sgPSBudWxsO1xuICAgICAgcmV0dXJuIFwiZG91YmxlXCJcbiAgICB9IGVsc2Uge1xuICAgICAgbGFzdENsaWNrID0gbmV3IFBhc3RDbGljayhub3csIHBvcywgYnV0dG9uKTtcbiAgICAgIGxhc3REb3VibGVDbGljayA9IG51bGw7XG4gICAgICByZXR1cm4gXCJzaW5nbGVcIlxuICAgIH1cbiAgfVxuXG4gIC8vIEEgbW91c2UgZG93biBjYW4gYmUgYSBzaW5nbGUgY2xpY2ssIGRvdWJsZSBjbGljaywgdHJpcGxlIGNsaWNrLFxuICAvLyBzdGFydCBvZiBzZWxlY3Rpb24gZHJhZywgc3RhcnQgb2YgdGV4dCBkcmFnLCBuZXcgY3Vyc29yXG4gIC8vIChjdHJsLWNsaWNrKSwgcmVjdGFuZ2xlIGRyYWcgKGFsdC1kcmFnKSwgb3IgeHdpblxuICAvLyBtaWRkbGUtY2xpY2stcGFzdGUuIE9yIGl0IG1pZ2h0IGJlIGEgY2xpY2sgb24gc29tZXRoaW5nIHdlIHNob3VsZFxuICAvLyBub3QgaW50ZXJmZXJlIHdpdGgsIHN1Y2ggYXMgYSBzY3JvbGxiYXIgb3Igd2lkZ2V0LlxuICBmdW5jdGlvbiBvbk1vdXNlRG93bihlKSB7XG4gICAgdmFyIGNtID0gdGhpcywgZGlzcGxheSA9IGNtLmRpc3BsYXk7XG4gICAgaWYgKHNpZ25hbERPTUV2ZW50KGNtLCBlKSB8fCBkaXNwbGF5LmFjdGl2ZVRvdWNoICYmIGRpc3BsYXkuaW5wdXQuc3VwcG9ydHNUb3VjaCgpKSB7IHJldHVybiB9XG4gICAgZGlzcGxheS5pbnB1dC5lbnN1cmVQb2xsZWQoKTtcbiAgICBkaXNwbGF5LnNoaWZ0ID0gZS5zaGlmdEtleTtcblxuICAgIGlmIChldmVudEluV2lkZ2V0KGRpc3BsYXksIGUpKSB7XG4gICAgICBpZiAoIXdlYmtpdCkge1xuICAgICAgICAvLyBCcmllZmx5IHR1cm4gb2ZmIGRyYWdnYWJpbGl0eSwgdG8gYWxsb3cgd2lkZ2V0cyB0byBkb1xuICAgICAgICAvLyBub3JtYWwgZHJhZ2dpbmcgdGhpbmdzLlxuICAgICAgICBkaXNwbGF5LnNjcm9sbGVyLmRyYWdnYWJsZSA9IGZhbHNlO1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHsgcmV0dXJuIGRpc3BsYXkuc2Nyb2xsZXIuZHJhZ2dhYmxlID0gdHJ1ZTsgfSwgMTAwKTtcbiAgICAgIH1cbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBpZiAoY2xpY2tJbkd1dHRlcihjbSwgZSkpIHsgcmV0dXJuIH1cbiAgICB2YXIgcG9zID0gcG9zRnJvbU1vdXNlKGNtLCBlKSwgYnV0dG9uID0gZV9idXR0b24oZSksIHJlcGVhdCA9IHBvcyA/IGNsaWNrUmVwZWF0KHBvcywgYnV0dG9uKSA6IFwic2luZ2xlXCI7XG4gICAgd2luZG93LmZvY3VzKCk7XG5cbiAgICAvLyAjMzI2MTogbWFrZSBzdXJlLCB0aGF0IHdlJ3JlIG5vdCBzdGFydGluZyBhIHNlY29uZCBzZWxlY3Rpb25cbiAgICBpZiAoYnV0dG9uID09IDEgJiYgY20uc3RhdGUuc2VsZWN0aW5nVGV4dClcbiAgICAgIHsgY20uc3RhdGUuc2VsZWN0aW5nVGV4dChlKTsgfVxuXG4gICAgaWYgKHBvcyAmJiBoYW5kbGVNYXBwZWRCdXR0b24oY20sIGJ1dHRvbiwgcG9zLCByZXBlYXQsIGUpKSB7IHJldHVybiB9XG5cbiAgICBpZiAoYnV0dG9uID09IDEpIHtcbiAgICAgIGlmIChwb3MpIHsgbGVmdEJ1dHRvbkRvd24oY20sIHBvcywgcmVwZWF0LCBlKTsgfVxuICAgICAgZWxzZSBpZiAoZV90YXJnZXQoZSkgPT0gZGlzcGxheS5zY3JvbGxlcikgeyBlX3ByZXZlbnREZWZhdWx0KGUpOyB9XG4gICAgfSBlbHNlIGlmIChidXR0b24gPT0gMikge1xuICAgICAgaWYgKHBvcykgeyBleHRlbmRTZWxlY3Rpb24oY20uZG9jLCBwb3MpOyB9XG4gICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHsgcmV0dXJuIGRpc3BsYXkuaW5wdXQuZm9jdXMoKTsgfSwgMjApO1xuICAgIH0gZWxzZSBpZiAoYnV0dG9uID09IDMpIHtcbiAgICAgIGlmIChjYXB0dXJlUmlnaHRDbGljaykgeyBjbS5kaXNwbGF5LmlucHV0Lm9uQ29udGV4dE1lbnUoZSk7IH1cbiAgICAgIGVsc2UgeyBkZWxheUJsdXJFdmVudChjbSk7IH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBoYW5kbGVNYXBwZWRCdXR0b24oY20sIGJ1dHRvbiwgcG9zLCByZXBlYXQsIGV2ZW50KSB7XG4gICAgdmFyIG5hbWUgPSBcIkNsaWNrXCI7XG4gICAgaWYgKHJlcGVhdCA9PSBcImRvdWJsZVwiKSB7IG5hbWUgPSBcIkRvdWJsZVwiICsgbmFtZTsgfVxuICAgIGVsc2UgaWYgKHJlcGVhdCA9PSBcInRyaXBsZVwiKSB7IG5hbWUgPSBcIlRyaXBsZVwiICsgbmFtZTsgfVxuICAgIG5hbWUgPSAoYnV0dG9uID09IDEgPyBcIkxlZnRcIiA6IGJ1dHRvbiA9PSAyID8gXCJNaWRkbGVcIiA6IFwiUmlnaHRcIikgKyBuYW1lO1xuXG4gICAgcmV0dXJuIGRpc3BhdGNoS2V5KGNtLCAgYWRkTW9kaWZpZXJOYW1lcyhuYW1lLCBldmVudCksIGV2ZW50LCBmdW5jdGlvbiAoYm91bmQpIHtcbiAgICAgIGlmICh0eXBlb2YgYm91bmQgPT0gXCJzdHJpbmdcIikgeyBib3VuZCA9IGNvbW1hbmRzW2JvdW5kXTsgfVxuICAgICAgaWYgKCFib3VuZCkgeyByZXR1cm4gZmFsc2UgfVxuICAgICAgdmFyIGRvbmUgPSBmYWxzZTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGlmIChjbS5pc1JlYWRPbmx5KCkpIHsgY20uc3RhdGUuc3VwcHJlc3NFZGl0cyA9IHRydWU7IH1cbiAgICAgICAgZG9uZSA9IGJvdW5kKGNtLCBwb3MpICE9IFBhc3M7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBjbS5zdGF0ZS5zdXBwcmVzc0VkaXRzID0gZmFsc2U7XG4gICAgICB9XG4gICAgICByZXR1cm4gZG9uZVxuICAgIH0pXG4gIH1cblxuICBmdW5jdGlvbiBjb25maWd1cmVNb3VzZShjbSwgcmVwZWF0LCBldmVudCkge1xuICAgIHZhciBvcHRpb24gPSBjbS5nZXRPcHRpb24oXCJjb25maWd1cmVNb3VzZVwiKTtcbiAgICB2YXIgdmFsdWUgPSBvcHRpb24gPyBvcHRpb24oY20sIHJlcGVhdCwgZXZlbnQpIDoge307XG4gICAgaWYgKHZhbHVlLnVuaXQgPT0gbnVsbCkge1xuICAgICAgdmFyIHJlY3QgPSBjaHJvbWVPUyA/IGV2ZW50LnNoaWZ0S2V5ICYmIGV2ZW50Lm1ldGFLZXkgOiBldmVudC5hbHRLZXk7XG4gICAgICB2YWx1ZS51bml0ID0gcmVjdCA/IFwicmVjdGFuZ2xlXCIgOiByZXBlYXQgPT0gXCJzaW5nbGVcIiA/IFwiY2hhclwiIDogcmVwZWF0ID09IFwiZG91YmxlXCIgPyBcIndvcmRcIiA6IFwibGluZVwiO1xuICAgIH1cbiAgICBpZiAodmFsdWUuZXh0ZW5kID09IG51bGwgfHwgY20uZG9jLmV4dGVuZCkgeyB2YWx1ZS5leHRlbmQgPSBjbS5kb2MuZXh0ZW5kIHx8IGV2ZW50LnNoaWZ0S2V5OyB9XG4gICAgaWYgKHZhbHVlLmFkZE5ldyA9PSBudWxsKSB7IHZhbHVlLmFkZE5ldyA9IG1hYyA/IGV2ZW50Lm1ldGFLZXkgOiBldmVudC5jdHJsS2V5OyB9XG4gICAgaWYgKHZhbHVlLm1vdmVPbkRyYWcgPT0gbnVsbCkgeyB2YWx1ZS5tb3ZlT25EcmFnID0gIShtYWMgPyBldmVudC5hbHRLZXkgOiBldmVudC5jdHJsS2V5KTsgfVxuICAgIHJldHVybiB2YWx1ZVxuICB9XG5cbiAgZnVuY3Rpb24gbGVmdEJ1dHRvbkRvd24oY20sIHBvcywgcmVwZWF0LCBldmVudCkge1xuICAgIGlmIChpZSkgeyBzZXRUaW1lb3V0KGJpbmQoZW5zdXJlRm9jdXMsIGNtKSwgMCk7IH1cbiAgICBlbHNlIHsgY20uY3VyT3AuZm9jdXMgPSBhY3RpdmVFbHQoKTsgfVxuXG4gICAgdmFyIGJlaGF2aW9yID0gY29uZmlndXJlTW91c2UoY20sIHJlcGVhdCwgZXZlbnQpO1xuXG4gICAgdmFyIHNlbCA9IGNtLmRvYy5zZWwsIGNvbnRhaW5lZDtcbiAgICBpZiAoY20ub3B0aW9ucy5kcmFnRHJvcCAmJiBkcmFnQW5kRHJvcCAmJiAhY20uaXNSZWFkT25seSgpICYmXG4gICAgICAgIHJlcGVhdCA9PSBcInNpbmdsZVwiICYmIChjb250YWluZWQgPSBzZWwuY29udGFpbnMocG9zKSkgPiAtMSAmJlxuICAgICAgICAoY21wKChjb250YWluZWQgPSBzZWwucmFuZ2VzW2NvbnRhaW5lZF0pLmZyb20oKSwgcG9zKSA8IDAgfHwgcG9zLnhSZWwgPiAwKSAmJlxuICAgICAgICAoY21wKGNvbnRhaW5lZC50bygpLCBwb3MpID4gMCB8fCBwb3MueFJlbCA8IDApKVxuICAgICAgeyBsZWZ0QnV0dG9uU3RhcnREcmFnKGNtLCBldmVudCwgcG9zLCBiZWhhdmlvcik7IH1cbiAgICBlbHNlXG4gICAgICB7IGxlZnRCdXR0b25TZWxlY3QoY20sIGV2ZW50LCBwb3MsIGJlaGF2aW9yKTsgfVxuICB9XG5cbiAgLy8gU3RhcnQgYSB0ZXh0IGRyYWcuIFdoZW4gaXQgZW5kcywgc2VlIGlmIGFueSBkcmFnZ2luZyBhY3R1YWxseVxuICAvLyBoYXBwZW4sIGFuZCB0cmVhdCBhcyBhIGNsaWNrIGlmIGl0IGRpZG4ndC5cbiAgZnVuY3Rpb24gbGVmdEJ1dHRvblN0YXJ0RHJhZyhjbSwgZXZlbnQsIHBvcywgYmVoYXZpb3IpIHtcbiAgICB2YXIgZGlzcGxheSA9IGNtLmRpc3BsYXksIG1vdmVkID0gZmFsc2U7XG4gICAgdmFyIGRyYWdFbmQgPSBvcGVyYXRpb24oY20sIGZ1bmN0aW9uIChlKSB7XG4gICAgICBpZiAod2Via2l0KSB7IGRpc3BsYXkuc2Nyb2xsZXIuZHJhZ2dhYmxlID0gZmFsc2U7IH1cbiAgICAgIGNtLnN0YXRlLmRyYWdnaW5nVGV4dCA9IGZhbHNlO1xuICAgICAgaWYgKGNtLnN0YXRlLmRlbGF5aW5nQmx1ckV2ZW50KSB7XG4gICAgICAgIGlmIChjbS5oYXNGb2N1cygpKSB7IGNtLnN0YXRlLmRlbGF5aW5nQmx1ckV2ZW50ID0gZmFsc2U7IH1cbiAgICAgICAgZWxzZSB7IGRlbGF5Qmx1ckV2ZW50KGNtKTsgfVxuICAgICAgfVxuICAgICAgb2ZmKGRpc3BsYXkud3JhcHBlci5vd25lckRvY3VtZW50LCBcIm1vdXNldXBcIiwgZHJhZ0VuZCk7XG4gICAgICBvZmYoZGlzcGxheS53cmFwcGVyLm93bmVyRG9jdW1lbnQsIFwibW91c2Vtb3ZlXCIsIG1vdXNlTW92ZSk7XG4gICAgICBvZmYoZGlzcGxheS5zY3JvbGxlciwgXCJkcmFnc3RhcnRcIiwgZHJhZ1N0YXJ0KTtcbiAgICAgIG9mZihkaXNwbGF5LnNjcm9sbGVyLCBcImRyb3BcIiwgZHJhZ0VuZCk7XG4gICAgICBpZiAoIW1vdmVkKSB7XG4gICAgICAgIGVfcHJldmVudERlZmF1bHQoZSk7XG4gICAgICAgIGlmICghYmVoYXZpb3IuYWRkTmV3KVxuICAgICAgICAgIHsgZXh0ZW5kU2VsZWN0aW9uKGNtLmRvYywgcG9zLCBudWxsLCBudWxsLCBiZWhhdmlvci5leHRlbmQpOyB9XG4gICAgICAgIC8vIFdvcmsgYXJvdW5kIHVuZXhwbGFpbmFibGUgZm9jdXMgcHJvYmxlbSBpbiBJRTkgKCMyMTI3KSBhbmQgQ2hyb21lICgjMzA4MSlcbiAgICAgICAgaWYgKCh3ZWJraXQgJiYgIXNhZmFyaSkgfHwgaWUgJiYgaWVfdmVyc2lvbiA9PSA5KVxuICAgICAgICAgIHsgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7ZGlzcGxheS53cmFwcGVyLm93bmVyRG9jdW1lbnQuYm9keS5mb2N1cyh7cHJldmVudFNjcm9sbDogdHJ1ZX0pOyBkaXNwbGF5LmlucHV0LmZvY3VzKCk7fSwgMjApOyB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICB7IGRpc3BsYXkuaW5wdXQuZm9jdXMoKTsgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIHZhciBtb3VzZU1vdmUgPSBmdW5jdGlvbihlMikge1xuICAgICAgbW92ZWQgPSBtb3ZlZCB8fCBNYXRoLmFicyhldmVudC5jbGllbnRYIC0gZTIuY2xpZW50WCkgKyBNYXRoLmFicyhldmVudC5jbGllbnRZIC0gZTIuY2xpZW50WSkgPj0gMTA7XG4gICAgfTtcbiAgICB2YXIgZHJhZ1N0YXJ0ID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gbW92ZWQgPSB0cnVlOyB9O1xuICAgIC8vIExldCB0aGUgZHJhZyBoYW5kbGVyIGhhbmRsZSB0aGlzLlxuICAgIGlmICh3ZWJraXQpIHsgZGlzcGxheS5zY3JvbGxlci5kcmFnZ2FibGUgPSB0cnVlOyB9XG4gICAgY20uc3RhdGUuZHJhZ2dpbmdUZXh0ID0gZHJhZ0VuZDtcbiAgICBkcmFnRW5kLmNvcHkgPSAhYmVoYXZpb3IubW92ZU9uRHJhZztcbiAgICBvbihkaXNwbGF5LndyYXBwZXIub3duZXJEb2N1bWVudCwgXCJtb3VzZXVwXCIsIGRyYWdFbmQpO1xuICAgIG9uKGRpc3BsYXkud3JhcHBlci5vd25lckRvY3VtZW50LCBcIm1vdXNlbW92ZVwiLCBtb3VzZU1vdmUpO1xuICAgIG9uKGRpc3BsYXkuc2Nyb2xsZXIsIFwiZHJhZ3N0YXJ0XCIsIGRyYWdTdGFydCk7XG4gICAgb24oZGlzcGxheS5zY3JvbGxlciwgXCJkcm9wXCIsIGRyYWdFbmQpO1xuXG4gICAgY20uc3RhdGUuZGVsYXlpbmdCbHVyRXZlbnQgPSB0cnVlO1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gZGlzcGxheS5pbnB1dC5mb2N1cygpOyB9LCAyMCk7XG4gICAgLy8gSUUncyBhcHByb2FjaCB0byBkcmFnZ2FibGVcbiAgICBpZiAoZGlzcGxheS5zY3JvbGxlci5kcmFnRHJvcCkgeyBkaXNwbGF5LnNjcm9sbGVyLmRyYWdEcm9wKCk7IH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHJhbmdlRm9yVW5pdChjbSwgcG9zLCB1bml0KSB7XG4gICAgaWYgKHVuaXQgPT0gXCJjaGFyXCIpIHsgcmV0dXJuIG5ldyBSYW5nZShwb3MsIHBvcykgfVxuICAgIGlmICh1bml0ID09IFwid29yZFwiKSB7IHJldHVybiBjbS5maW5kV29yZEF0KHBvcykgfVxuICAgIGlmICh1bml0ID09IFwibGluZVwiKSB7IHJldHVybiBuZXcgUmFuZ2UoUG9zKHBvcy5saW5lLCAwKSwgY2xpcFBvcyhjbS5kb2MsIFBvcyhwb3MubGluZSArIDEsIDApKSkgfVxuICAgIHZhciByZXN1bHQgPSB1bml0KGNtLCBwb3MpO1xuICAgIHJldHVybiBuZXcgUmFuZ2UocmVzdWx0LmZyb20sIHJlc3VsdC50bylcbiAgfVxuXG4gIC8vIE5vcm1hbCBzZWxlY3Rpb24sIGFzIG9wcG9zZWQgdG8gdGV4dCBkcmFnZ2luZy5cbiAgZnVuY3Rpb24gbGVmdEJ1dHRvblNlbGVjdChjbSwgZXZlbnQsIHN0YXJ0LCBiZWhhdmlvcikge1xuICAgIGlmIChpZSkgeyBkZWxheUJsdXJFdmVudChjbSk7IH1cbiAgICB2YXIgZGlzcGxheSA9IGNtLmRpc3BsYXksIGRvYyA9IGNtLmRvYztcbiAgICBlX3ByZXZlbnREZWZhdWx0KGV2ZW50KTtcblxuICAgIHZhciBvdXJSYW5nZSwgb3VySW5kZXgsIHN0YXJ0U2VsID0gZG9jLnNlbCwgcmFuZ2VzID0gc3RhcnRTZWwucmFuZ2VzO1xuICAgIGlmIChiZWhhdmlvci5hZGROZXcgJiYgIWJlaGF2aW9yLmV4dGVuZCkge1xuICAgICAgb3VySW5kZXggPSBkb2Muc2VsLmNvbnRhaW5zKHN0YXJ0KTtcbiAgICAgIGlmIChvdXJJbmRleCA+IC0xKVxuICAgICAgICB7IG91clJhbmdlID0gcmFuZ2VzW291ckluZGV4XTsgfVxuICAgICAgZWxzZVxuICAgICAgICB7IG91clJhbmdlID0gbmV3IFJhbmdlKHN0YXJ0LCBzdGFydCk7IH1cbiAgICB9IGVsc2Uge1xuICAgICAgb3VyUmFuZ2UgPSBkb2Muc2VsLnByaW1hcnkoKTtcbiAgICAgIG91ckluZGV4ID0gZG9jLnNlbC5wcmltSW5kZXg7XG4gICAgfVxuXG4gICAgaWYgKGJlaGF2aW9yLnVuaXQgPT0gXCJyZWN0YW5nbGVcIikge1xuICAgICAgaWYgKCFiZWhhdmlvci5hZGROZXcpIHsgb3VyUmFuZ2UgPSBuZXcgUmFuZ2Uoc3RhcnQsIHN0YXJ0KTsgfVxuICAgICAgc3RhcnQgPSBwb3NGcm9tTW91c2UoY20sIGV2ZW50LCB0cnVlLCB0cnVlKTtcbiAgICAgIG91ckluZGV4ID0gLTE7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciByYW5nZSA9IHJhbmdlRm9yVW5pdChjbSwgc3RhcnQsIGJlaGF2aW9yLnVuaXQpO1xuICAgICAgaWYgKGJlaGF2aW9yLmV4dGVuZClcbiAgICAgICAgeyBvdXJSYW5nZSA9IGV4dGVuZFJhbmdlKG91clJhbmdlLCByYW5nZS5hbmNob3IsIHJhbmdlLmhlYWQsIGJlaGF2aW9yLmV4dGVuZCk7IH1cbiAgICAgIGVsc2VcbiAgICAgICAgeyBvdXJSYW5nZSA9IHJhbmdlOyB9XG4gICAgfVxuXG4gICAgaWYgKCFiZWhhdmlvci5hZGROZXcpIHtcbiAgICAgIG91ckluZGV4ID0gMDtcbiAgICAgIHNldFNlbGVjdGlvbihkb2MsIG5ldyBTZWxlY3Rpb24oW291clJhbmdlXSwgMCksIHNlbF9tb3VzZSk7XG4gICAgICBzdGFydFNlbCA9IGRvYy5zZWw7XG4gICAgfSBlbHNlIGlmIChvdXJJbmRleCA9PSAtMSkge1xuICAgICAgb3VySW5kZXggPSByYW5nZXMubGVuZ3RoO1xuICAgICAgc2V0U2VsZWN0aW9uKGRvYywgbm9ybWFsaXplU2VsZWN0aW9uKGNtLCByYW5nZXMuY29uY2F0KFtvdXJSYW5nZV0pLCBvdXJJbmRleCksXG4gICAgICAgICAgICAgICAgICAge3Njcm9sbDogZmFsc2UsIG9yaWdpbjogXCIqbW91c2VcIn0pO1xuICAgIH0gZWxzZSBpZiAocmFuZ2VzLmxlbmd0aCA+IDEgJiYgcmFuZ2VzW291ckluZGV4XS5lbXB0eSgpICYmIGJlaGF2aW9yLnVuaXQgPT0gXCJjaGFyXCIgJiYgIWJlaGF2aW9yLmV4dGVuZCkge1xuICAgICAgc2V0U2VsZWN0aW9uKGRvYywgbm9ybWFsaXplU2VsZWN0aW9uKGNtLCByYW5nZXMuc2xpY2UoMCwgb3VySW5kZXgpLmNvbmNhdChyYW5nZXMuc2xpY2Uob3VySW5kZXggKyAxKSksIDApLFxuICAgICAgICAgICAgICAgICAgIHtzY3JvbGw6IGZhbHNlLCBvcmlnaW46IFwiKm1vdXNlXCJ9KTtcbiAgICAgIHN0YXJ0U2VsID0gZG9jLnNlbDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVwbGFjZU9uZVNlbGVjdGlvbihkb2MsIG91ckluZGV4LCBvdXJSYW5nZSwgc2VsX21vdXNlKTtcbiAgICB9XG5cbiAgICB2YXIgbGFzdFBvcyA9IHN0YXJ0O1xuICAgIGZ1bmN0aW9uIGV4dGVuZFRvKHBvcykge1xuICAgICAgaWYgKGNtcChsYXN0UG9zLCBwb3MpID09IDApIHsgcmV0dXJuIH1cbiAgICAgIGxhc3RQb3MgPSBwb3M7XG5cbiAgICAgIGlmIChiZWhhdmlvci51bml0ID09IFwicmVjdGFuZ2xlXCIpIHtcbiAgICAgICAgdmFyIHJhbmdlcyA9IFtdLCB0YWJTaXplID0gY20ub3B0aW9ucy50YWJTaXplO1xuICAgICAgICB2YXIgc3RhcnRDb2wgPSBjb3VudENvbHVtbihnZXRMaW5lKGRvYywgc3RhcnQubGluZSkudGV4dCwgc3RhcnQuY2gsIHRhYlNpemUpO1xuICAgICAgICB2YXIgcG9zQ29sID0gY291bnRDb2x1bW4oZ2V0TGluZShkb2MsIHBvcy5saW5lKS50ZXh0LCBwb3MuY2gsIHRhYlNpemUpO1xuICAgICAgICB2YXIgbGVmdCA9IE1hdGgubWluKHN0YXJ0Q29sLCBwb3NDb2wpLCByaWdodCA9IE1hdGgubWF4KHN0YXJ0Q29sLCBwb3NDb2wpO1xuICAgICAgICBmb3IgKHZhciBsaW5lID0gTWF0aC5taW4oc3RhcnQubGluZSwgcG9zLmxpbmUpLCBlbmQgPSBNYXRoLm1pbihjbS5sYXN0TGluZSgpLCBNYXRoLm1heChzdGFydC5saW5lLCBwb3MubGluZSkpO1xuICAgICAgICAgICAgIGxpbmUgPD0gZW5kOyBsaW5lKyspIHtcbiAgICAgICAgICB2YXIgdGV4dCA9IGdldExpbmUoZG9jLCBsaW5lKS50ZXh0LCBsZWZ0UG9zID0gZmluZENvbHVtbih0ZXh0LCBsZWZ0LCB0YWJTaXplKTtcbiAgICAgICAgICBpZiAobGVmdCA9PSByaWdodClcbiAgICAgICAgICAgIHsgcmFuZ2VzLnB1c2gobmV3IFJhbmdlKFBvcyhsaW5lLCBsZWZ0UG9zKSwgUG9zKGxpbmUsIGxlZnRQb3MpKSk7IH1cbiAgICAgICAgICBlbHNlIGlmICh0ZXh0Lmxlbmd0aCA+IGxlZnRQb3MpXG4gICAgICAgICAgICB7IHJhbmdlcy5wdXNoKG5ldyBSYW5nZShQb3MobGluZSwgbGVmdFBvcyksIFBvcyhsaW5lLCBmaW5kQ29sdW1uKHRleHQsIHJpZ2h0LCB0YWJTaXplKSkpKTsgfVxuICAgICAgICB9XG4gICAgICAgIGlmICghcmFuZ2VzLmxlbmd0aCkgeyByYW5nZXMucHVzaChuZXcgUmFuZ2Uoc3RhcnQsIHN0YXJ0KSk7IH1cbiAgICAgICAgc2V0U2VsZWN0aW9uKGRvYywgbm9ybWFsaXplU2VsZWN0aW9uKGNtLCBzdGFydFNlbC5yYW5nZXMuc2xpY2UoMCwgb3VySW5kZXgpLmNvbmNhdChyYW5nZXMpLCBvdXJJbmRleCksXG4gICAgICAgICAgICAgICAgICAgICB7b3JpZ2luOiBcIiptb3VzZVwiLCBzY3JvbGw6IGZhbHNlfSk7XG4gICAgICAgIGNtLnNjcm9sbEludG9WaWV3KHBvcyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgb2xkUmFuZ2UgPSBvdXJSYW5nZTtcbiAgICAgICAgdmFyIHJhbmdlID0gcmFuZ2VGb3JVbml0KGNtLCBwb3MsIGJlaGF2aW9yLnVuaXQpO1xuICAgICAgICB2YXIgYW5jaG9yID0gb2xkUmFuZ2UuYW5jaG9yLCBoZWFkO1xuICAgICAgICBpZiAoY21wKHJhbmdlLmFuY2hvciwgYW5jaG9yKSA+IDApIHtcbiAgICAgICAgICBoZWFkID0gcmFuZ2UuaGVhZDtcbiAgICAgICAgICBhbmNob3IgPSBtaW5Qb3Mob2xkUmFuZ2UuZnJvbSgpLCByYW5nZS5hbmNob3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGhlYWQgPSByYW5nZS5hbmNob3I7XG4gICAgICAgICAgYW5jaG9yID0gbWF4UG9zKG9sZFJhbmdlLnRvKCksIHJhbmdlLmhlYWQpO1xuICAgICAgICB9XG4gICAgICAgIHZhciByYW5nZXMkMSA9IHN0YXJ0U2VsLnJhbmdlcy5zbGljZSgwKTtcbiAgICAgICAgcmFuZ2VzJDFbb3VySW5kZXhdID0gYmlkaVNpbXBsaWZ5KGNtLCBuZXcgUmFuZ2UoY2xpcFBvcyhkb2MsIGFuY2hvciksIGhlYWQpKTtcbiAgICAgICAgc2V0U2VsZWN0aW9uKGRvYywgbm9ybWFsaXplU2VsZWN0aW9uKGNtLCByYW5nZXMkMSwgb3VySW5kZXgpLCBzZWxfbW91c2UpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBlZGl0b3JTaXplID0gZGlzcGxheS53cmFwcGVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIC8vIFVzZWQgdG8gZW5zdXJlIHRpbWVvdXQgcmUtdHJpZXMgZG9uJ3QgZmlyZSB3aGVuIGFub3RoZXIgZXh0ZW5kXG4gICAgLy8gaGFwcGVuZWQgaW4gdGhlIG1lYW50aW1lIChjbGVhclRpbWVvdXQgaXNuJ3QgcmVsaWFibGUgLS0gYXRcbiAgICAvLyBsZWFzdCBvbiBDaHJvbWUsIHRoZSB0aW1lb3V0cyBzdGlsbCBoYXBwZW4gZXZlbiB3aGVuIGNsZWFyZWQsXG4gICAgLy8gaWYgdGhlIGNsZWFyIGhhcHBlbnMgYWZ0ZXIgdGhlaXIgc2NoZWR1bGVkIGZpcmluZyB0aW1lKS5cbiAgICB2YXIgY291bnRlciA9IDA7XG5cbiAgICBmdW5jdGlvbiBleHRlbmQoZSkge1xuICAgICAgdmFyIGN1ckNvdW50ID0gKytjb3VudGVyO1xuICAgICAgdmFyIGN1ciA9IHBvc0Zyb21Nb3VzZShjbSwgZSwgdHJ1ZSwgYmVoYXZpb3IudW5pdCA9PSBcInJlY3RhbmdsZVwiKTtcbiAgICAgIGlmICghY3VyKSB7IHJldHVybiB9XG4gICAgICBpZiAoY21wKGN1ciwgbGFzdFBvcykgIT0gMCkge1xuICAgICAgICBjbS5jdXJPcC5mb2N1cyA9IGFjdGl2ZUVsdCgpO1xuICAgICAgICBleHRlbmRUbyhjdXIpO1xuICAgICAgICB2YXIgdmlzaWJsZSA9IHZpc2libGVMaW5lcyhkaXNwbGF5LCBkb2MpO1xuICAgICAgICBpZiAoY3VyLmxpbmUgPj0gdmlzaWJsZS50byB8fCBjdXIubGluZSA8IHZpc2libGUuZnJvbSlcbiAgICAgICAgICB7IHNldFRpbWVvdXQob3BlcmF0aW9uKGNtLCBmdW5jdGlvbiAoKSB7aWYgKGNvdW50ZXIgPT0gY3VyQ291bnQpIHsgZXh0ZW5kKGUpOyB9fSksIDE1MCk7IH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBvdXRzaWRlID0gZS5jbGllbnRZIDwgZWRpdG9yU2l6ZS50b3AgPyAtMjAgOiBlLmNsaWVudFkgPiBlZGl0b3JTaXplLmJvdHRvbSA/IDIwIDogMDtcbiAgICAgICAgaWYgKG91dHNpZGUpIHsgc2V0VGltZW91dChvcGVyYXRpb24oY20sIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBpZiAoY291bnRlciAhPSBjdXJDb3VudCkgeyByZXR1cm4gfVxuICAgICAgICAgIGRpc3BsYXkuc2Nyb2xsZXIuc2Nyb2xsVG9wICs9IG91dHNpZGU7XG4gICAgICAgICAgZXh0ZW5kKGUpO1xuICAgICAgICB9KSwgNTApOyB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZG9uZShlKSB7XG4gICAgICBjbS5zdGF0ZS5zZWxlY3RpbmdUZXh0ID0gZmFsc2U7XG4gICAgICBjb3VudGVyID0gSW5maW5pdHk7XG4gICAgICAvLyBJZiBlIGlzIG51bGwgb3IgdW5kZWZpbmVkIHdlIGludGVycHJldCB0aGlzIGFzIHNvbWVvbmUgdHJ5aW5nXG4gICAgICAvLyB0byBleHBsaWNpdGx5IGNhbmNlbCB0aGUgc2VsZWN0aW9uIHJhdGhlciB0aGFuIHRoZSB1c2VyXG4gICAgICAvLyBsZXR0aW5nIGdvIG9mIHRoZSBtb3VzZSBidXR0b24uXG4gICAgICBpZiAoZSkge1xuICAgICAgICBlX3ByZXZlbnREZWZhdWx0KGUpO1xuICAgICAgICBkaXNwbGF5LmlucHV0LmZvY3VzKCk7XG4gICAgICB9XG4gICAgICBvZmYoZGlzcGxheS53cmFwcGVyLm93bmVyRG9jdW1lbnQsIFwibW91c2Vtb3ZlXCIsIG1vdmUpO1xuICAgICAgb2ZmKGRpc3BsYXkud3JhcHBlci5vd25lckRvY3VtZW50LCBcIm1vdXNldXBcIiwgdXApO1xuICAgICAgZG9jLmhpc3RvcnkubGFzdFNlbE9yaWdpbiA9IG51bGw7XG4gICAgfVxuXG4gICAgdmFyIG1vdmUgPSBvcGVyYXRpb24oY20sIGZ1bmN0aW9uIChlKSB7XG4gICAgICBpZiAoZS5idXR0b25zID09PSAwIHx8ICFlX2J1dHRvbihlKSkgeyBkb25lKGUpOyB9XG4gICAgICBlbHNlIHsgZXh0ZW5kKGUpOyB9XG4gICAgfSk7XG4gICAgdmFyIHVwID0gb3BlcmF0aW9uKGNtLCBkb25lKTtcbiAgICBjbS5zdGF0ZS5zZWxlY3RpbmdUZXh0ID0gdXA7XG4gICAgb24oZGlzcGxheS53cmFwcGVyLm93bmVyRG9jdW1lbnQsIFwibW91c2Vtb3ZlXCIsIG1vdmUpO1xuICAgIG9uKGRpc3BsYXkud3JhcHBlci5vd25lckRvY3VtZW50LCBcIm1vdXNldXBcIiwgdXApO1xuICB9XG5cbiAgLy8gVXNlZCB3aGVuIG1vdXNlLXNlbGVjdGluZyB0byBhZGp1c3QgdGhlIGFuY2hvciB0byB0aGUgcHJvcGVyIHNpZGVcbiAgLy8gb2YgYSBiaWRpIGp1bXAgZGVwZW5kaW5nIG9uIHRoZSB2aXN1YWwgcG9zaXRpb24gb2YgdGhlIGhlYWQuXG4gIGZ1bmN0aW9uIGJpZGlTaW1wbGlmeShjbSwgcmFuZ2UpIHtcbiAgICB2YXIgYW5jaG9yID0gcmFuZ2UuYW5jaG9yO1xuICAgIHZhciBoZWFkID0gcmFuZ2UuaGVhZDtcbiAgICB2YXIgYW5jaG9yTGluZSA9IGdldExpbmUoY20uZG9jLCBhbmNob3IubGluZSk7XG4gICAgaWYgKGNtcChhbmNob3IsIGhlYWQpID09IDAgJiYgYW5jaG9yLnN0aWNreSA9PSBoZWFkLnN0aWNreSkgeyByZXR1cm4gcmFuZ2UgfVxuICAgIHZhciBvcmRlciA9IGdldE9yZGVyKGFuY2hvckxpbmUpO1xuICAgIGlmICghb3JkZXIpIHsgcmV0dXJuIHJhbmdlIH1cbiAgICB2YXIgaW5kZXggPSBnZXRCaWRpUGFydEF0KG9yZGVyLCBhbmNob3IuY2gsIGFuY2hvci5zdGlja3kpLCBwYXJ0ID0gb3JkZXJbaW5kZXhdO1xuICAgIGlmIChwYXJ0LmZyb20gIT0gYW5jaG9yLmNoICYmIHBhcnQudG8gIT0gYW5jaG9yLmNoKSB7IHJldHVybiByYW5nZSB9XG4gICAgdmFyIGJvdW5kYXJ5ID0gaW5kZXggKyAoKHBhcnQuZnJvbSA9PSBhbmNob3IuY2gpID09IChwYXJ0LmxldmVsICE9IDEpID8gMCA6IDEpO1xuICAgIGlmIChib3VuZGFyeSA9PSAwIHx8IGJvdW5kYXJ5ID09IG9yZGVyLmxlbmd0aCkgeyByZXR1cm4gcmFuZ2UgfVxuXG4gICAgLy8gQ29tcHV0ZSB0aGUgcmVsYXRpdmUgdmlzdWFsIHBvc2l0aW9uIG9mIHRoZSBoZWFkIGNvbXBhcmVkIHRvIHRoZVxuICAgIC8vIGFuY2hvciAoPDAgaXMgdG8gdGhlIGxlZnQsID4wIHRvIHRoZSByaWdodClcbiAgICB2YXIgbGVmdFNpZGU7XG4gICAgaWYgKGhlYWQubGluZSAhPSBhbmNob3IubGluZSkge1xuICAgICAgbGVmdFNpZGUgPSAoaGVhZC5saW5lIC0gYW5jaG9yLmxpbmUpICogKGNtLmRvYy5kaXJlY3Rpb24gPT0gXCJsdHJcIiA/IDEgOiAtMSkgPiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgaGVhZEluZGV4ID0gZ2V0QmlkaVBhcnRBdChvcmRlciwgaGVhZC5jaCwgaGVhZC5zdGlja3kpO1xuICAgICAgdmFyIGRpciA9IGhlYWRJbmRleCAtIGluZGV4IHx8IChoZWFkLmNoIC0gYW5jaG9yLmNoKSAqIChwYXJ0LmxldmVsID09IDEgPyAtMSA6IDEpO1xuICAgICAgaWYgKGhlYWRJbmRleCA9PSBib3VuZGFyeSAtIDEgfHwgaGVhZEluZGV4ID09IGJvdW5kYXJ5KVxuICAgICAgICB7IGxlZnRTaWRlID0gZGlyIDwgMDsgfVxuICAgICAgZWxzZVxuICAgICAgICB7IGxlZnRTaWRlID0gZGlyID4gMDsgfVxuICAgIH1cblxuICAgIHZhciB1c2VQYXJ0ID0gb3JkZXJbYm91bmRhcnkgKyAobGVmdFNpZGUgPyAtMSA6IDApXTtcbiAgICB2YXIgZnJvbSA9IGxlZnRTaWRlID09ICh1c2VQYXJ0LmxldmVsID09IDEpO1xuICAgIHZhciBjaCA9IGZyb20gPyB1c2VQYXJ0LmZyb20gOiB1c2VQYXJ0LnRvLCBzdGlja3kgPSBmcm9tID8gXCJhZnRlclwiIDogXCJiZWZvcmVcIjtcbiAgICByZXR1cm4gYW5jaG9yLmNoID09IGNoICYmIGFuY2hvci5zdGlja3kgPT0gc3RpY2t5ID8gcmFuZ2UgOiBuZXcgUmFuZ2UobmV3IFBvcyhhbmNob3IubGluZSwgY2gsIHN0aWNreSksIGhlYWQpXG4gIH1cblxuXG4gIC8vIERldGVybWluZXMgd2hldGhlciBhbiBldmVudCBoYXBwZW5lZCBpbiB0aGUgZ3V0dGVyLCBhbmQgZmlyZXMgdGhlXG4gIC8vIGhhbmRsZXJzIGZvciB0aGUgY29ycmVzcG9uZGluZyBldmVudC5cbiAgZnVuY3Rpb24gZ3V0dGVyRXZlbnQoY20sIGUsIHR5cGUsIHByZXZlbnQpIHtcbiAgICB2YXIgbVgsIG1ZO1xuICAgIGlmIChlLnRvdWNoZXMpIHtcbiAgICAgIG1YID0gZS50b3VjaGVzWzBdLmNsaWVudFg7XG4gICAgICBtWSA9IGUudG91Y2hlc1swXS5jbGllbnRZO1xuICAgIH0gZWxzZSB7XG4gICAgICB0cnkgeyBtWCA9IGUuY2xpZW50WDsgbVkgPSBlLmNsaWVudFk7IH1cbiAgICAgIGNhdGNoKGUkMSkgeyByZXR1cm4gZmFsc2UgfVxuICAgIH1cbiAgICBpZiAobVggPj0gTWF0aC5mbG9vcihjbS5kaXNwbGF5Lmd1dHRlcnMuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkucmlnaHQpKSB7IHJldHVybiBmYWxzZSB9XG4gICAgaWYgKHByZXZlbnQpIHsgZV9wcmV2ZW50RGVmYXVsdChlKTsgfVxuXG4gICAgdmFyIGRpc3BsYXkgPSBjbS5kaXNwbGF5O1xuICAgIHZhciBsaW5lQm94ID0gZGlzcGxheS5saW5lRGl2LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgaWYgKG1ZID4gbGluZUJveC5ib3R0b20gfHwgIWhhc0hhbmRsZXIoY20sIHR5cGUpKSB7IHJldHVybiBlX2RlZmF1bHRQcmV2ZW50ZWQoZSkgfVxuICAgIG1ZIC09IGxpbmVCb3gudG9wIC0gZGlzcGxheS52aWV3T2Zmc2V0O1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjbS5kaXNwbGF5Lmd1dHRlclNwZWNzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgZyA9IGRpc3BsYXkuZ3V0dGVycy5jaGlsZE5vZGVzW2ldO1xuICAgICAgaWYgKGcgJiYgZy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5yaWdodCA+PSBtWCkge1xuICAgICAgICB2YXIgbGluZSA9IGxpbmVBdEhlaWdodChjbS5kb2MsIG1ZKTtcbiAgICAgICAgdmFyIGd1dHRlciA9IGNtLmRpc3BsYXkuZ3V0dGVyU3BlY3NbaV07XG4gICAgICAgIHNpZ25hbChjbSwgdHlwZSwgY20sIGxpbmUsIGd1dHRlci5jbGFzc05hbWUsIGUpO1xuICAgICAgICByZXR1cm4gZV9kZWZhdWx0UHJldmVudGVkKGUpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gY2xpY2tJbkd1dHRlcihjbSwgZSkge1xuICAgIHJldHVybiBndXR0ZXJFdmVudChjbSwgZSwgXCJndXR0ZXJDbGlja1wiLCB0cnVlKVxuICB9XG5cbiAgLy8gQ09OVEVYVCBNRU5VIEhBTkRMSU5HXG5cbiAgLy8gVG8gbWFrZSB0aGUgY29udGV4dCBtZW51IHdvcmssIHdlIG5lZWQgdG8gYnJpZWZseSB1bmhpZGUgdGhlXG4gIC8vIHRleHRhcmVhIChtYWtpbmcgaXQgYXMgdW5vYnRydXNpdmUgYXMgcG9zc2libGUpIHRvIGxldCB0aGVcbiAgLy8gcmlnaHQtY2xpY2sgdGFrZSBlZmZlY3Qgb24gaXQuXG4gIGZ1bmN0aW9uIG9uQ29udGV4dE1lbnUoY20sIGUpIHtcbiAgICBpZiAoZXZlbnRJbldpZGdldChjbS5kaXNwbGF5LCBlKSB8fCBjb250ZXh0TWVudUluR3V0dGVyKGNtLCBlKSkgeyByZXR1cm4gfVxuICAgIGlmIChzaWduYWxET01FdmVudChjbSwgZSwgXCJjb250ZXh0bWVudVwiKSkgeyByZXR1cm4gfVxuICAgIGlmICghY2FwdHVyZVJpZ2h0Q2xpY2spIHsgY20uZGlzcGxheS5pbnB1dC5vbkNvbnRleHRNZW51KGUpOyB9XG4gIH1cblxuICBmdW5jdGlvbiBjb250ZXh0TWVudUluR3V0dGVyKGNtLCBlKSB7XG4gICAgaWYgKCFoYXNIYW5kbGVyKGNtLCBcImd1dHRlckNvbnRleHRNZW51XCIpKSB7IHJldHVybiBmYWxzZSB9XG4gICAgcmV0dXJuIGd1dHRlckV2ZW50KGNtLCBlLCBcImd1dHRlckNvbnRleHRNZW51XCIsIGZhbHNlKVxuICB9XG5cbiAgZnVuY3Rpb24gdGhlbWVDaGFuZ2VkKGNtKSB7XG4gICAgY20uZGlzcGxheS53cmFwcGVyLmNsYXNzTmFtZSA9IGNtLmRpc3BsYXkud3JhcHBlci5jbGFzc05hbWUucmVwbGFjZSgvXFxzKmNtLXMtXFxTKy9nLCBcIlwiKSArXG4gICAgICBjbS5vcHRpb25zLnRoZW1lLnJlcGxhY2UoLyhefFxccylcXHMqL2csIFwiIGNtLXMtXCIpO1xuICAgIGNsZWFyQ2FjaGVzKGNtKTtcbiAgfVxuXG4gIHZhciBJbml0ID0ge3RvU3RyaW5nOiBmdW5jdGlvbigpe3JldHVybiBcIkNvZGVNaXJyb3IuSW5pdFwifX07XG5cbiAgdmFyIGRlZmF1bHRzID0ge307XG4gIHZhciBvcHRpb25IYW5kbGVycyA9IHt9O1xuXG4gIGZ1bmN0aW9uIGRlZmluZU9wdGlvbnMoQ29kZU1pcnJvcikge1xuICAgIHZhciBvcHRpb25IYW5kbGVycyA9IENvZGVNaXJyb3Iub3B0aW9uSGFuZGxlcnM7XG5cbiAgICBmdW5jdGlvbiBvcHRpb24obmFtZSwgZGVmbHQsIGhhbmRsZSwgbm90T25Jbml0KSB7XG4gICAgICBDb2RlTWlycm9yLmRlZmF1bHRzW25hbWVdID0gZGVmbHQ7XG4gICAgICBpZiAoaGFuZGxlKSB7IG9wdGlvbkhhbmRsZXJzW25hbWVdID1cbiAgICAgICAgbm90T25Jbml0ID8gZnVuY3Rpb24gKGNtLCB2YWwsIG9sZCkge2lmIChvbGQgIT0gSW5pdCkgeyBoYW5kbGUoY20sIHZhbCwgb2xkKTsgfX0gOiBoYW5kbGU7IH1cbiAgICB9XG5cbiAgICBDb2RlTWlycm9yLmRlZmluZU9wdGlvbiA9IG9wdGlvbjtcblxuICAgIC8vIFBhc3NlZCB0byBvcHRpb24gaGFuZGxlcnMgd2hlbiB0aGVyZSBpcyBubyBvbGQgdmFsdWUuXG4gICAgQ29kZU1pcnJvci5Jbml0ID0gSW5pdDtcblxuICAgIC8vIFRoZXNlIHR3byBhcmUsIG9uIGluaXQsIGNhbGxlZCBmcm9tIHRoZSBjb25zdHJ1Y3RvciBiZWNhdXNlIHRoZXlcbiAgICAvLyBoYXZlIHRvIGJlIGluaXRpYWxpemVkIGJlZm9yZSB0aGUgZWRpdG9yIGNhbiBzdGFydCBhdCBhbGwuXG4gICAgb3B0aW9uKFwidmFsdWVcIiwgXCJcIiwgZnVuY3Rpb24gKGNtLCB2YWwpIHsgcmV0dXJuIGNtLnNldFZhbHVlKHZhbCk7IH0sIHRydWUpO1xuICAgIG9wdGlvbihcIm1vZGVcIiwgbnVsbCwgZnVuY3Rpb24gKGNtLCB2YWwpIHtcbiAgICAgIGNtLmRvYy5tb2RlT3B0aW9uID0gdmFsO1xuICAgICAgbG9hZE1vZGUoY20pO1xuICAgIH0sIHRydWUpO1xuXG4gICAgb3B0aW9uKFwiaW5kZW50VW5pdFwiLCAyLCBsb2FkTW9kZSwgdHJ1ZSk7XG4gICAgb3B0aW9uKFwiaW5kZW50V2l0aFRhYnNcIiwgZmFsc2UpO1xuICAgIG9wdGlvbihcInNtYXJ0SW5kZW50XCIsIHRydWUpO1xuICAgIG9wdGlvbihcInRhYlNpemVcIiwgNCwgZnVuY3Rpb24gKGNtKSB7XG4gICAgICByZXNldE1vZGVTdGF0ZShjbSk7XG4gICAgICBjbGVhckNhY2hlcyhjbSk7XG4gICAgICByZWdDaGFuZ2UoY20pO1xuICAgIH0sIHRydWUpO1xuXG4gICAgb3B0aW9uKFwibGluZVNlcGFyYXRvclwiLCBudWxsLCBmdW5jdGlvbiAoY20sIHZhbCkge1xuICAgICAgY20uZG9jLmxpbmVTZXAgPSB2YWw7XG4gICAgICBpZiAoIXZhbCkgeyByZXR1cm4gfVxuICAgICAgdmFyIG5ld0JyZWFrcyA9IFtdLCBsaW5lTm8gPSBjbS5kb2MuZmlyc3Q7XG4gICAgICBjbS5kb2MuaXRlcihmdW5jdGlvbiAobGluZSkge1xuICAgICAgICBmb3IgKHZhciBwb3MgPSAwOzspIHtcbiAgICAgICAgICB2YXIgZm91bmQgPSBsaW5lLnRleHQuaW5kZXhPZih2YWwsIHBvcyk7XG4gICAgICAgICAgaWYgKGZvdW5kID09IC0xKSB7IGJyZWFrIH1cbiAgICAgICAgICBwb3MgPSBmb3VuZCArIHZhbC5sZW5ndGg7XG4gICAgICAgICAgbmV3QnJlYWtzLnB1c2goUG9zKGxpbmVObywgZm91bmQpKTtcbiAgICAgICAgfVxuICAgICAgICBsaW5lTm8rKztcbiAgICAgIH0pO1xuICAgICAgZm9yICh2YXIgaSA9IG5ld0JyZWFrcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSlcbiAgICAgICAgeyByZXBsYWNlUmFuZ2UoY20uZG9jLCB2YWwsIG5ld0JyZWFrc1tpXSwgUG9zKG5ld0JyZWFrc1tpXS5saW5lLCBuZXdCcmVha3NbaV0uY2ggKyB2YWwubGVuZ3RoKSk7IH1cbiAgICB9KTtcbiAgICBvcHRpb24oXCJzcGVjaWFsQ2hhcnNcIiwgL1tcXHUwMDAwLVxcdTAwMWZcXHUwMDdmLVxcdTAwOWZcXHUwMGFkXFx1MDYxY1xcdTIwMGJcXHUyMDBlXFx1MjAwZlxcdTIwMjhcXHUyMDI5XFx1ZmVmZlxcdWZmZjktXFx1ZmZmY10vZywgZnVuY3Rpb24gKGNtLCB2YWwsIG9sZCkge1xuICAgICAgY20uc3RhdGUuc3BlY2lhbENoYXJzID0gbmV3IFJlZ0V4cCh2YWwuc291cmNlICsgKHZhbC50ZXN0KFwiXFx0XCIpID8gXCJcIiA6IFwifFxcdFwiKSwgXCJnXCIpO1xuICAgICAgaWYgKG9sZCAhPSBJbml0KSB7IGNtLnJlZnJlc2goKTsgfVxuICAgIH0pO1xuICAgIG9wdGlvbihcInNwZWNpYWxDaGFyUGxhY2Vob2xkZXJcIiwgZGVmYXVsdFNwZWNpYWxDaGFyUGxhY2Vob2xkZXIsIGZ1bmN0aW9uIChjbSkgeyByZXR1cm4gY20ucmVmcmVzaCgpOyB9LCB0cnVlKTtcbiAgICBvcHRpb24oXCJlbGVjdHJpY0NoYXJzXCIsIHRydWUpO1xuICAgIG9wdGlvbihcImlucHV0U3R5bGVcIiwgbW9iaWxlID8gXCJjb250ZW50ZWRpdGFibGVcIiA6IFwidGV4dGFyZWFcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiaW5wdXRTdHlsZSBjYW4gbm90ICh5ZXQpIGJlIGNoYW5nZWQgaW4gYSBydW5uaW5nIGVkaXRvclwiKSAvLyBGSVhNRVxuICAgIH0sIHRydWUpO1xuICAgIG9wdGlvbihcInNwZWxsY2hlY2tcIiwgZmFsc2UsIGZ1bmN0aW9uIChjbSwgdmFsKSB7IHJldHVybiBjbS5nZXRJbnB1dEZpZWxkKCkuc3BlbGxjaGVjayA9IHZhbDsgfSwgdHJ1ZSk7XG4gICAgb3B0aW9uKFwiYXV0b2NvcnJlY3RcIiwgZmFsc2UsIGZ1bmN0aW9uIChjbSwgdmFsKSB7IHJldHVybiBjbS5nZXRJbnB1dEZpZWxkKCkuYXV0b2NvcnJlY3QgPSB2YWw7IH0sIHRydWUpO1xuICAgIG9wdGlvbihcImF1dG9jYXBpdGFsaXplXCIsIGZhbHNlLCBmdW5jdGlvbiAoY20sIHZhbCkgeyByZXR1cm4gY20uZ2V0SW5wdXRGaWVsZCgpLmF1dG9jYXBpdGFsaXplID0gdmFsOyB9LCB0cnVlKTtcbiAgICBvcHRpb24oXCJydGxNb3ZlVmlzdWFsbHlcIiwgIXdpbmRvd3MpO1xuICAgIG9wdGlvbihcIndob2xlTGluZVVwZGF0ZUJlZm9yZVwiLCB0cnVlKTtcblxuICAgIG9wdGlvbihcInRoZW1lXCIsIFwiZGVmYXVsdFwiLCBmdW5jdGlvbiAoY20pIHtcbiAgICAgIHRoZW1lQ2hhbmdlZChjbSk7XG4gICAgICB1cGRhdGVHdXR0ZXJzKGNtKTtcbiAgICB9LCB0cnVlKTtcbiAgICBvcHRpb24oXCJrZXlNYXBcIiwgXCJkZWZhdWx0XCIsIGZ1bmN0aW9uIChjbSwgdmFsLCBvbGQpIHtcbiAgICAgIHZhciBuZXh0ID0gZ2V0S2V5TWFwKHZhbCk7XG4gICAgICB2YXIgcHJldiA9IG9sZCAhPSBJbml0ICYmIGdldEtleU1hcChvbGQpO1xuICAgICAgaWYgKHByZXYgJiYgcHJldi5kZXRhY2gpIHsgcHJldi5kZXRhY2goY20sIG5leHQpOyB9XG4gICAgICBpZiAobmV4dC5hdHRhY2gpIHsgbmV4dC5hdHRhY2goY20sIHByZXYgfHwgbnVsbCk7IH1cbiAgICB9KTtcbiAgICBvcHRpb24oXCJleHRyYUtleXNcIiwgbnVsbCk7XG4gICAgb3B0aW9uKFwiY29uZmlndXJlTW91c2VcIiwgbnVsbCk7XG5cbiAgICBvcHRpb24oXCJsaW5lV3JhcHBpbmdcIiwgZmFsc2UsIHdyYXBwaW5nQ2hhbmdlZCwgdHJ1ZSk7XG4gICAgb3B0aW9uKFwiZ3V0dGVyc1wiLCBbXSwgZnVuY3Rpb24gKGNtLCB2YWwpIHtcbiAgICAgIGNtLmRpc3BsYXkuZ3V0dGVyU3BlY3MgPSBnZXRHdXR0ZXJzKHZhbCwgY20ub3B0aW9ucy5saW5lTnVtYmVycyk7XG4gICAgICB1cGRhdGVHdXR0ZXJzKGNtKTtcbiAgICB9LCB0cnVlKTtcbiAgICBvcHRpb24oXCJmaXhlZEd1dHRlclwiLCB0cnVlLCBmdW5jdGlvbiAoY20sIHZhbCkge1xuICAgICAgY20uZGlzcGxheS5ndXR0ZXJzLnN0eWxlLmxlZnQgPSB2YWwgPyBjb21wZW5zYXRlRm9ySFNjcm9sbChjbS5kaXNwbGF5KSArIFwicHhcIiA6IFwiMFwiO1xuICAgICAgY20ucmVmcmVzaCgpO1xuICAgIH0sIHRydWUpO1xuICAgIG9wdGlvbihcImNvdmVyR3V0dGVyTmV4dFRvU2Nyb2xsYmFyXCIsIGZhbHNlLCBmdW5jdGlvbiAoY20pIHsgcmV0dXJuIHVwZGF0ZVNjcm9sbGJhcnMoY20pOyB9LCB0cnVlKTtcbiAgICBvcHRpb24oXCJzY3JvbGxiYXJTdHlsZVwiLCBcIm5hdGl2ZVwiLCBmdW5jdGlvbiAoY20pIHtcbiAgICAgIGluaXRTY3JvbGxiYXJzKGNtKTtcbiAgICAgIHVwZGF0ZVNjcm9sbGJhcnMoY20pO1xuICAgICAgY20uZGlzcGxheS5zY3JvbGxiYXJzLnNldFNjcm9sbFRvcChjbS5kb2Muc2Nyb2xsVG9wKTtcbiAgICAgIGNtLmRpc3BsYXkuc2Nyb2xsYmFycy5zZXRTY3JvbGxMZWZ0KGNtLmRvYy5zY3JvbGxMZWZ0KTtcbiAgICB9LCB0cnVlKTtcbiAgICBvcHRpb24oXCJsaW5lTnVtYmVyc1wiLCBmYWxzZSwgZnVuY3Rpb24gKGNtLCB2YWwpIHtcbiAgICAgIGNtLmRpc3BsYXkuZ3V0dGVyU3BlY3MgPSBnZXRHdXR0ZXJzKGNtLm9wdGlvbnMuZ3V0dGVycywgdmFsKTtcbiAgICAgIHVwZGF0ZUd1dHRlcnMoY20pO1xuICAgIH0sIHRydWUpO1xuICAgIG9wdGlvbihcImZpcnN0TGluZU51bWJlclwiLCAxLCB1cGRhdGVHdXR0ZXJzLCB0cnVlKTtcbiAgICBvcHRpb24oXCJsaW5lTnVtYmVyRm9ybWF0dGVyXCIsIGZ1bmN0aW9uIChpbnRlZ2VyKSB7IHJldHVybiBpbnRlZ2VyOyB9LCB1cGRhdGVHdXR0ZXJzLCB0cnVlKTtcbiAgICBvcHRpb24oXCJzaG93Q3Vyc29yV2hlblNlbGVjdGluZ1wiLCBmYWxzZSwgdXBkYXRlU2VsZWN0aW9uLCB0cnVlKTtcblxuICAgIG9wdGlvbihcInJlc2V0U2VsZWN0aW9uT25Db250ZXh0TWVudVwiLCB0cnVlKTtcbiAgICBvcHRpb24oXCJsaW5lV2lzZUNvcHlDdXRcIiwgdHJ1ZSk7XG4gICAgb3B0aW9uKFwicGFzdGVMaW5lc1BlclNlbGVjdGlvblwiLCB0cnVlKTtcbiAgICBvcHRpb24oXCJzZWxlY3Rpb25zTWF5VG91Y2hcIiwgZmFsc2UpO1xuXG4gICAgb3B0aW9uKFwicmVhZE9ubHlcIiwgZmFsc2UsIGZ1bmN0aW9uIChjbSwgdmFsKSB7XG4gICAgICBpZiAodmFsID09IFwibm9jdXJzb3JcIikge1xuICAgICAgICBvbkJsdXIoY20pO1xuICAgICAgICBjbS5kaXNwbGF5LmlucHV0LmJsdXIoKTtcbiAgICAgIH1cbiAgICAgIGNtLmRpc3BsYXkuaW5wdXQucmVhZE9ubHlDaGFuZ2VkKHZhbCk7XG4gICAgfSk7XG5cbiAgICBvcHRpb24oXCJzY3JlZW5SZWFkZXJMYWJlbFwiLCBudWxsLCBmdW5jdGlvbiAoY20sIHZhbCkge1xuICAgICAgdmFsID0gKHZhbCA9PT0gJycpID8gbnVsbCA6IHZhbDtcbiAgICAgIGNtLmRpc3BsYXkuaW5wdXQuc2NyZWVuUmVhZGVyTGFiZWxDaGFuZ2VkKHZhbCk7XG4gICAgfSk7XG5cbiAgICBvcHRpb24oXCJkaXNhYmxlSW5wdXRcIiwgZmFsc2UsIGZ1bmN0aW9uIChjbSwgdmFsKSB7aWYgKCF2YWwpIHsgY20uZGlzcGxheS5pbnB1dC5yZXNldCgpOyB9fSwgdHJ1ZSk7XG4gICAgb3B0aW9uKFwiZHJhZ0Ryb3BcIiwgdHJ1ZSwgZHJhZ0Ryb3BDaGFuZ2VkKTtcbiAgICBvcHRpb24oXCJhbGxvd0Ryb3BGaWxlVHlwZXNcIiwgbnVsbCk7XG5cbiAgICBvcHRpb24oXCJjdXJzb3JCbGlua1JhdGVcIiwgNTMwKTtcbiAgICBvcHRpb24oXCJjdXJzb3JTY3JvbGxNYXJnaW5cIiwgMCk7XG4gICAgb3B0aW9uKFwiY3Vyc29ySGVpZ2h0XCIsIDEsIHVwZGF0ZVNlbGVjdGlvbiwgdHJ1ZSk7XG4gICAgb3B0aW9uKFwic2luZ2xlQ3Vyc29ySGVpZ2h0UGVyTGluZVwiLCB0cnVlLCB1cGRhdGVTZWxlY3Rpb24sIHRydWUpO1xuICAgIG9wdGlvbihcIndvcmtUaW1lXCIsIDEwMCk7XG4gICAgb3B0aW9uKFwid29ya0RlbGF5XCIsIDEwMCk7XG4gICAgb3B0aW9uKFwiZmxhdHRlblNwYW5zXCIsIHRydWUsIHJlc2V0TW9kZVN0YXRlLCB0cnVlKTtcbiAgICBvcHRpb24oXCJhZGRNb2RlQ2xhc3NcIiwgZmFsc2UsIHJlc2V0TW9kZVN0YXRlLCB0cnVlKTtcbiAgICBvcHRpb24oXCJwb2xsSW50ZXJ2YWxcIiwgMTAwKTtcbiAgICBvcHRpb24oXCJ1bmRvRGVwdGhcIiwgMjAwLCBmdW5jdGlvbiAoY20sIHZhbCkgeyByZXR1cm4gY20uZG9jLmhpc3RvcnkudW5kb0RlcHRoID0gdmFsOyB9KTtcbiAgICBvcHRpb24oXCJoaXN0b3J5RXZlbnREZWxheVwiLCAxMjUwKTtcbiAgICBvcHRpb24oXCJ2aWV3cG9ydE1hcmdpblwiLCAxMCwgZnVuY3Rpb24gKGNtKSB7IHJldHVybiBjbS5yZWZyZXNoKCk7IH0sIHRydWUpO1xuICAgIG9wdGlvbihcIm1heEhpZ2hsaWdodExlbmd0aFwiLCAxMDAwMCwgcmVzZXRNb2RlU3RhdGUsIHRydWUpO1xuICAgIG9wdGlvbihcIm1vdmVJbnB1dFdpdGhDdXJzb3JcIiwgdHJ1ZSwgZnVuY3Rpb24gKGNtLCB2YWwpIHtcbiAgICAgIGlmICghdmFsKSB7IGNtLmRpc3BsYXkuaW5wdXQucmVzZXRQb3NpdGlvbigpOyB9XG4gICAgfSk7XG5cbiAgICBvcHRpb24oXCJ0YWJpbmRleFwiLCBudWxsLCBmdW5jdGlvbiAoY20sIHZhbCkgeyByZXR1cm4gY20uZGlzcGxheS5pbnB1dC5nZXRGaWVsZCgpLnRhYkluZGV4ID0gdmFsIHx8IFwiXCI7IH0pO1xuICAgIG9wdGlvbihcImF1dG9mb2N1c1wiLCBudWxsKTtcbiAgICBvcHRpb24oXCJkaXJlY3Rpb25cIiwgXCJsdHJcIiwgZnVuY3Rpb24gKGNtLCB2YWwpIHsgcmV0dXJuIGNtLmRvYy5zZXREaXJlY3Rpb24odmFsKTsgfSwgdHJ1ZSk7XG4gICAgb3B0aW9uKFwicGhyYXNlc1wiLCBudWxsKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRyYWdEcm9wQ2hhbmdlZChjbSwgdmFsdWUsIG9sZCkge1xuICAgIHZhciB3YXNPbiA9IG9sZCAmJiBvbGQgIT0gSW5pdDtcbiAgICBpZiAoIXZhbHVlICE9ICF3YXNPbikge1xuICAgICAgdmFyIGZ1bmNzID0gY20uZGlzcGxheS5kcmFnRnVuY3Rpb25zO1xuICAgICAgdmFyIHRvZ2dsZSA9IHZhbHVlID8gb24gOiBvZmY7XG4gICAgICB0b2dnbGUoY20uZGlzcGxheS5zY3JvbGxlciwgXCJkcmFnc3RhcnRcIiwgZnVuY3Muc3RhcnQpO1xuICAgICAgdG9nZ2xlKGNtLmRpc3BsYXkuc2Nyb2xsZXIsIFwiZHJhZ2VudGVyXCIsIGZ1bmNzLmVudGVyKTtcbiAgICAgIHRvZ2dsZShjbS5kaXNwbGF5LnNjcm9sbGVyLCBcImRyYWdvdmVyXCIsIGZ1bmNzLm92ZXIpO1xuICAgICAgdG9nZ2xlKGNtLmRpc3BsYXkuc2Nyb2xsZXIsIFwiZHJhZ2xlYXZlXCIsIGZ1bmNzLmxlYXZlKTtcbiAgICAgIHRvZ2dsZShjbS5kaXNwbGF5LnNjcm9sbGVyLCBcImRyb3BcIiwgZnVuY3MuZHJvcCk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gd3JhcHBpbmdDaGFuZ2VkKGNtKSB7XG4gICAgaWYgKGNtLm9wdGlvbnMubGluZVdyYXBwaW5nKSB7XG4gICAgICBhZGRDbGFzcyhjbS5kaXNwbGF5LndyYXBwZXIsIFwiQ29kZU1pcnJvci13cmFwXCIpO1xuICAgICAgY20uZGlzcGxheS5zaXplci5zdHlsZS5taW5XaWR0aCA9IFwiXCI7XG4gICAgICBjbS5kaXNwbGF5LnNpemVyV2lkdGggPSBudWxsO1xuICAgIH0gZWxzZSB7XG4gICAgICBybUNsYXNzKGNtLmRpc3BsYXkud3JhcHBlciwgXCJDb2RlTWlycm9yLXdyYXBcIik7XG4gICAgICBmaW5kTWF4TGluZShjbSk7XG4gICAgfVxuICAgIGVzdGltYXRlTGluZUhlaWdodHMoY20pO1xuICAgIHJlZ0NoYW5nZShjbSk7XG4gICAgY2xlYXJDYWNoZXMoY20pO1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gdXBkYXRlU2Nyb2xsYmFycyhjbSk7IH0sIDEwMCk7XG4gIH1cblxuICAvLyBBIENvZGVNaXJyb3IgaW5zdGFuY2UgcmVwcmVzZW50cyBhbiBlZGl0b3IuIFRoaXMgaXMgdGhlIG9iamVjdFxuICAvLyB0aGF0IHVzZXIgY29kZSBpcyB1c3VhbGx5IGRlYWxpbmcgd2l0aC5cblxuICBmdW5jdGlvbiBDb2RlTWlycm9yKHBsYWNlLCBvcHRpb25zKSB7XG4gICAgdmFyIHRoaXMkMSA9IHRoaXM7XG5cbiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgQ29kZU1pcnJvcikpIHsgcmV0dXJuIG5ldyBDb2RlTWlycm9yKHBsYWNlLCBvcHRpb25zKSB9XG5cbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zID0gb3B0aW9ucyA/IGNvcHlPYmoob3B0aW9ucykgOiB7fTtcbiAgICAvLyBEZXRlcm1pbmUgZWZmZWN0aXZlIG9wdGlvbnMgYmFzZWQgb24gZ2l2ZW4gdmFsdWVzIGFuZCBkZWZhdWx0cy5cbiAgICBjb3B5T2JqKGRlZmF1bHRzLCBvcHRpb25zLCBmYWxzZSk7XG5cbiAgICB2YXIgZG9jID0gb3B0aW9ucy52YWx1ZTtcbiAgICBpZiAodHlwZW9mIGRvYyA9PSBcInN0cmluZ1wiKSB7IGRvYyA9IG5ldyBEb2MoZG9jLCBvcHRpb25zLm1vZGUsIG51bGwsIG9wdGlvbnMubGluZVNlcGFyYXRvciwgb3B0aW9ucy5kaXJlY3Rpb24pOyB9XG4gICAgZWxzZSBpZiAob3B0aW9ucy5tb2RlKSB7IGRvYy5tb2RlT3B0aW9uID0gb3B0aW9ucy5tb2RlOyB9XG4gICAgdGhpcy5kb2MgPSBkb2M7XG5cbiAgICB2YXIgaW5wdXQgPSBuZXcgQ29kZU1pcnJvci5pbnB1dFN0eWxlc1tvcHRpb25zLmlucHV0U3R5bGVdKHRoaXMpO1xuICAgIHZhciBkaXNwbGF5ID0gdGhpcy5kaXNwbGF5ID0gbmV3IERpc3BsYXkocGxhY2UsIGRvYywgaW5wdXQsIG9wdGlvbnMpO1xuICAgIGRpc3BsYXkud3JhcHBlci5Db2RlTWlycm9yID0gdGhpcztcbiAgICB0aGVtZUNoYW5nZWQodGhpcyk7XG4gICAgaWYgKG9wdGlvbnMubGluZVdyYXBwaW5nKVxuICAgICAgeyB0aGlzLmRpc3BsYXkud3JhcHBlci5jbGFzc05hbWUgKz0gXCIgQ29kZU1pcnJvci13cmFwXCI7IH1cbiAgICBpbml0U2Nyb2xsYmFycyh0aGlzKTtcblxuICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICBrZXlNYXBzOiBbXSwgIC8vIHN0b3JlcyBtYXBzIGFkZGVkIGJ5IGFkZEtleU1hcFxuICAgICAgb3ZlcmxheXM6IFtdLCAvLyBoaWdobGlnaHRpbmcgb3ZlcmxheXMsIGFzIGFkZGVkIGJ5IGFkZE92ZXJsYXlcbiAgICAgIG1vZGVHZW46IDAsICAgLy8gYnVtcGVkIHdoZW4gbW9kZS9vdmVybGF5IGNoYW5nZXMsIHVzZWQgdG8gaW52YWxpZGF0ZSBoaWdobGlnaHRpbmcgaW5mb1xuICAgICAgb3ZlcndyaXRlOiBmYWxzZSxcbiAgICAgIGRlbGF5aW5nQmx1ckV2ZW50OiBmYWxzZSxcbiAgICAgIGZvY3VzZWQ6IGZhbHNlLFxuICAgICAgc3VwcHJlc3NFZGl0czogZmFsc2UsIC8vIHVzZWQgdG8gZGlzYWJsZSBlZGl0aW5nIGR1cmluZyBrZXkgaGFuZGxlcnMgd2hlbiBpbiByZWFkT25seSBtb2RlXG4gICAgICBwYXN0ZUluY29taW5nOiAtMSwgY3V0SW5jb21pbmc6IC0xLCAvLyBoZWxwIHJlY29nbml6ZSBwYXN0ZS9jdXQgZWRpdHMgaW4gaW5wdXQucG9sbFxuICAgICAgc2VsZWN0aW5nVGV4dDogZmFsc2UsXG4gICAgICBkcmFnZ2luZ1RleHQ6IGZhbHNlLFxuICAgICAgaGlnaGxpZ2h0OiBuZXcgRGVsYXllZCgpLCAvLyBzdG9yZXMgaGlnaGxpZ2h0IHdvcmtlciB0aW1lb3V0XG4gICAgICBrZXlTZXE6IG51bGwsICAvLyBVbmZpbmlzaGVkIGtleSBzZXF1ZW5jZVxuICAgICAgc3BlY2lhbENoYXJzOiBudWxsXG4gICAgfTtcblxuICAgIGlmIChvcHRpb25zLmF1dG9mb2N1cyAmJiAhbW9iaWxlKSB7IGRpc3BsYXkuaW5wdXQuZm9jdXMoKTsgfVxuXG4gICAgLy8gT3ZlcnJpZGUgbWFnaWMgdGV4dGFyZWEgY29udGVudCByZXN0b3JlIHRoYXQgSUUgc29tZXRpbWVzIGRvZXNcbiAgICAvLyBvbiBvdXIgaGlkZGVuIHRleHRhcmVhIG9uIHJlbG9hZFxuICAgIGlmIChpZSAmJiBpZV92ZXJzaW9uIDwgMTEpIHsgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzJDEuZGlzcGxheS5pbnB1dC5yZXNldCh0cnVlKTsgfSwgMjApOyB9XG5cbiAgICByZWdpc3RlckV2ZW50SGFuZGxlcnModGhpcyk7XG4gICAgZW5zdXJlR2xvYmFsSGFuZGxlcnMoKTtcblxuICAgIHN0YXJ0T3BlcmF0aW9uKHRoaXMpO1xuICAgIHRoaXMuY3VyT3AuZm9yY2VVcGRhdGUgPSB0cnVlO1xuICAgIGF0dGFjaERvYyh0aGlzLCBkb2MpO1xuXG4gICAgaWYgKChvcHRpb25zLmF1dG9mb2N1cyAmJiAhbW9iaWxlKSB8fCB0aGlzLmhhc0ZvY3VzKCkpXG4gICAgICB7IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcyQxLmhhc0ZvY3VzKCkgJiYgIXRoaXMkMS5zdGF0ZS5mb2N1c2VkKSB7IG9uRm9jdXModGhpcyQxKTsgfVxuICAgICAgfSwgMjApOyB9XG4gICAgZWxzZVxuICAgICAgeyBvbkJsdXIodGhpcyk7IH1cblxuICAgIGZvciAodmFyIG9wdCBpbiBvcHRpb25IYW5kbGVycykgeyBpZiAob3B0aW9uSGFuZGxlcnMuaGFzT3duUHJvcGVydHkob3B0KSlcbiAgICAgIHsgb3B0aW9uSGFuZGxlcnNbb3B0XSh0aGlzLCBvcHRpb25zW29wdF0sIEluaXQpOyB9IH1cbiAgICBtYXliZVVwZGF0ZUxpbmVOdW1iZXJXaWR0aCh0aGlzKTtcbiAgICBpZiAob3B0aW9ucy5maW5pc2hJbml0KSB7IG9wdGlvbnMuZmluaXNoSW5pdCh0aGlzKTsgfVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW5pdEhvb2tzLmxlbmd0aDsgKytpKSB7IGluaXRIb29rc1tpXSh0aGlzKTsgfVxuICAgIGVuZE9wZXJhdGlvbih0aGlzKTtcbiAgICAvLyBTdXBwcmVzcyBvcHRpbWl6ZWxlZ2liaWxpdHkgaW4gV2Via2l0LCBzaW5jZSBpdCBicmVha3MgdGV4dFxuICAgIC8vIG1lYXN1cmluZyBvbiBsaW5lIHdyYXBwaW5nIGJvdW5kYXJpZXMuXG4gICAgaWYgKHdlYmtpdCAmJiBvcHRpb25zLmxpbmVXcmFwcGluZyAmJlxuICAgICAgICBnZXRDb21wdXRlZFN0eWxlKGRpc3BsYXkubGluZURpdikudGV4dFJlbmRlcmluZyA9PSBcIm9wdGltaXplbGVnaWJpbGl0eVwiKVxuICAgICAgeyBkaXNwbGF5LmxpbmVEaXYuc3R5bGUudGV4dFJlbmRlcmluZyA9IFwiYXV0b1wiOyB9XG4gIH1cblxuICAvLyBUaGUgZGVmYXVsdCBjb25maWd1cmF0aW9uIG9wdGlvbnMuXG4gIENvZGVNaXJyb3IuZGVmYXVsdHMgPSBkZWZhdWx0cztcbiAgLy8gRnVuY3Rpb25zIHRvIHJ1biB3aGVuIG9wdGlvbnMgYXJlIGNoYW5nZWQuXG4gIENvZGVNaXJyb3Iub3B0aW9uSGFuZGxlcnMgPSBvcHRpb25IYW5kbGVycztcblxuICAvLyBBdHRhY2ggdGhlIG5lY2Vzc2FyeSBldmVudCBoYW5kbGVycyB3aGVuIGluaXRpYWxpemluZyB0aGUgZWRpdG9yXG4gIGZ1bmN0aW9uIHJlZ2lzdGVyRXZlbnRIYW5kbGVycyhjbSkge1xuICAgIHZhciBkID0gY20uZGlzcGxheTtcbiAgICBvbihkLnNjcm9sbGVyLCBcIm1vdXNlZG93blwiLCBvcGVyYXRpb24oY20sIG9uTW91c2VEb3duKSk7XG4gICAgLy8gT2xkZXIgSUUncyB3aWxsIG5vdCBmaXJlIGEgc2Vjb25kIG1vdXNlZG93biBmb3IgYSBkb3VibGUgY2xpY2tcbiAgICBpZiAoaWUgJiYgaWVfdmVyc2lvbiA8IDExKVxuICAgICAgeyBvbihkLnNjcm9sbGVyLCBcImRibGNsaWNrXCIsIG9wZXJhdGlvbihjbSwgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKHNpZ25hbERPTUV2ZW50KGNtLCBlKSkgeyByZXR1cm4gfVxuICAgICAgICB2YXIgcG9zID0gcG9zRnJvbU1vdXNlKGNtLCBlKTtcbiAgICAgICAgaWYgKCFwb3MgfHwgY2xpY2tJbkd1dHRlcihjbSwgZSkgfHwgZXZlbnRJbldpZGdldChjbS5kaXNwbGF5LCBlKSkgeyByZXR1cm4gfVxuICAgICAgICBlX3ByZXZlbnREZWZhdWx0KGUpO1xuICAgICAgICB2YXIgd29yZCA9IGNtLmZpbmRXb3JkQXQocG9zKTtcbiAgICAgICAgZXh0ZW5kU2VsZWN0aW9uKGNtLmRvYywgd29yZC5hbmNob3IsIHdvcmQuaGVhZCk7XG4gICAgICB9KSk7IH1cbiAgICBlbHNlXG4gICAgICB7IG9uKGQuc2Nyb2xsZXIsIFwiZGJsY2xpY2tcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIHNpZ25hbERPTUV2ZW50KGNtLCBlKSB8fCBlX3ByZXZlbnREZWZhdWx0KGUpOyB9KTsgfVxuICAgIC8vIFNvbWUgYnJvd3NlcnMgZmlyZSBjb250ZXh0bWVudSAqYWZ0ZXIqIG9wZW5pbmcgdGhlIG1lbnUsIGF0XG4gICAgLy8gd2hpY2ggcG9pbnQgd2UgY2FuJ3QgbWVzcyB3aXRoIGl0IGFueW1vcmUuIENvbnRleHQgbWVudSBpc1xuICAgIC8vIGhhbmRsZWQgaW4gb25Nb3VzZURvd24gZm9yIHRoZXNlIGJyb3dzZXJzLlxuICAgIG9uKGQuc2Nyb2xsZXIsIFwiY29udGV4dG1lbnVcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIG9uQ29udGV4dE1lbnUoY20sIGUpOyB9KTtcbiAgICBvbihkLmlucHV0LmdldEZpZWxkKCksIFwiY29udGV4dG1lbnVcIiwgZnVuY3Rpb24gKGUpIHtcbiAgICAgIGlmICghZC5zY3JvbGxlci5jb250YWlucyhlLnRhcmdldCkpIHsgb25Db250ZXh0TWVudShjbSwgZSk7IH1cbiAgICB9KTtcblxuICAgIC8vIFVzZWQgdG8gc3VwcHJlc3MgbW91c2UgZXZlbnQgaGFuZGxpbmcgd2hlbiBhIHRvdWNoIGhhcHBlbnNcbiAgICB2YXIgdG91Y2hGaW5pc2hlZCwgcHJldlRvdWNoID0ge2VuZDogMH07XG4gICAgZnVuY3Rpb24gZmluaXNoVG91Y2goKSB7XG4gICAgICBpZiAoZC5hY3RpdmVUb3VjaCkge1xuICAgICAgICB0b3VjaEZpbmlzaGVkID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7IHJldHVybiBkLmFjdGl2ZVRvdWNoID0gbnVsbDsgfSwgMTAwMCk7XG4gICAgICAgIHByZXZUb3VjaCA9IGQuYWN0aXZlVG91Y2g7XG4gICAgICAgIHByZXZUb3VjaC5lbmQgPSArbmV3IERhdGU7XG4gICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIGlzTW91c2VMaWtlVG91Y2hFdmVudChlKSB7XG4gICAgICBpZiAoZS50b3VjaGVzLmxlbmd0aCAhPSAxKSB7IHJldHVybiBmYWxzZSB9XG4gICAgICB2YXIgdG91Y2ggPSBlLnRvdWNoZXNbMF07XG4gICAgICByZXR1cm4gdG91Y2gucmFkaXVzWCA8PSAxICYmIHRvdWNoLnJhZGl1c1kgPD0gMVxuICAgIH1cbiAgICBmdW5jdGlvbiBmYXJBd2F5KHRvdWNoLCBvdGhlcikge1xuICAgICAgaWYgKG90aGVyLmxlZnQgPT0gbnVsbCkgeyByZXR1cm4gdHJ1ZSB9XG4gICAgICB2YXIgZHggPSBvdGhlci5sZWZ0IC0gdG91Y2gubGVmdCwgZHkgPSBvdGhlci50b3AgLSB0b3VjaC50b3A7XG4gICAgICByZXR1cm4gZHggKiBkeCArIGR5ICogZHkgPiAyMCAqIDIwXG4gICAgfVxuICAgIG9uKGQuc2Nyb2xsZXIsIFwidG91Y2hzdGFydFwiLCBmdW5jdGlvbiAoZSkge1xuICAgICAgaWYgKCFzaWduYWxET01FdmVudChjbSwgZSkgJiYgIWlzTW91c2VMaWtlVG91Y2hFdmVudChlKSAmJiAhY2xpY2tJbkd1dHRlcihjbSwgZSkpIHtcbiAgICAgICAgZC5pbnB1dC5lbnN1cmVQb2xsZWQoKTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRvdWNoRmluaXNoZWQpO1xuICAgICAgICB2YXIgbm93ID0gK25ldyBEYXRlO1xuICAgICAgICBkLmFjdGl2ZVRvdWNoID0ge3N0YXJ0OiBub3csIG1vdmVkOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2OiBub3cgLSBwcmV2VG91Y2guZW5kIDw9IDMwMCA/IHByZXZUb3VjaCA6IG51bGx9O1xuICAgICAgICBpZiAoZS50b3VjaGVzLmxlbmd0aCA9PSAxKSB7XG4gICAgICAgICAgZC5hY3RpdmVUb3VjaC5sZWZ0ID0gZS50b3VjaGVzWzBdLnBhZ2VYO1xuICAgICAgICAgIGQuYWN0aXZlVG91Y2gudG9wID0gZS50b3VjaGVzWzBdLnBhZ2VZO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgb24oZC5zY3JvbGxlciwgXCJ0b3VjaG1vdmVcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKGQuYWN0aXZlVG91Y2gpIHsgZC5hY3RpdmVUb3VjaC5tb3ZlZCA9IHRydWU7IH1cbiAgICB9KTtcbiAgICBvbihkLnNjcm9sbGVyLCBcInRvdWNoZW5kXCIsIGZ1bmN0aW9uIChlKSB7XG4gICAgICB2YXIgdG91Y2ggPSBkLmFjdGl2ZVRvdWNoO1xuICAgICAgaWYgKHRvdWNoICYmICFldmVudEluV2lkZ2V0KGQsIGUpICYmIHRvdWNoLmxlZnQgIT0gbnVsbCAmJlxuICAgICAgICAgICF0b3VjaC5tb3ZlZCAmJiBuZXcgRGF0ZSAtIHRvdWNoLnN0YXJ0IDwgMzAwKSB7XG4gICAgICAgIHZhciBwb3MgPSBjbS5jb29yZHNDaGFyKGQuYWN0aXZlVG91Y2gsIFwicGFnZVwiKSwgcmFuZ2U7XG4gICAgICAgIGlmICghdG91Y2gucHJldiB8fCBmYXJBd2F5KHRvdWNoLCB0b3VjaC5wcmV2KSkgLy8gU2luZ2xlIHRhcFxuICAgICAgICAgIHsgcmFuZ2UgPSBuZXcgUmFuZ2UocG9zLCBwb3MpOyB9XG4gICAgICAgIGVsc2UgaWYgKCF0b3VjaC5wcmV2LnByZXYgfHwgZmFyQXdheSh0b3VjaCwgdG91Y2gucHJldi5wcmV2KSkgLy8gRG91YmxlIHRhcFxuICAgICAgICAgIHsgcmFuZ2UgPSBjbS5maW5kV29yZEF0KHBvcyk7IH1cbiAgICAgICAgZWxzZSAvLyBUcmlwbGUgdGFwXG4gICAgICAgICAgeyByYW5nZSA9IG5ldyBSYW5nZShQb3MocG9zLmxpbmUsIDApLCBjbGlwUG9zKGNtLmRvYywgUG9zKHBvcy5saW5lICsgMSwgMCkpKTsgfVxuICAgICAgICBjbS5zZXRTZWxlY3Rpb24ocmFuZ2UuYW5jaG9yLCByYW5nZS5oZWFkKTtcbiAgICAgICAgY20uZm9jdXMoKTtcbiAgICAgICAgZV9wcmV2ZW50RGVmYXVsdChlKTtcbiAgICAgIH1cbiAgICAgIGZpbmlzaFRvdWNoKCk7XG4gICAgfSk7XG4gICAgb24oZC5zY3JvbGxlciwgXCJ0b3VjaGNhbmNlbFwiLCBmaW5pc2hUb3VjaCk7XG5cbiAgICAvLyBTeW5jIHNjcm9sbGluZyBiZXR3ZWVuIGZha2Ugc2Nyb2xsYmFycyBhbmQgcmVhbCBzY3JvbGxhYmxlXG4gICAgLy8gYXJlYSwgZW5zdXJlIHZpZXdwb3J0IGlzIHVwZGF0ZWQgd2hlbiBzY3JvbGxpbmcuXG4gICAgb24oZC5zY3JvbGxlciwgXCJzY3JvbGxcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKGQuc2Nyb2xsZXIuY2xpZW50SGVpZ2h0KSB7XG4gICAgICAgIHVwZGF0ZVNjcm9sbFRvcChjbSwgZC5zY3JvbGxlci5zY3JvbGxUb3ApO1xuICAgICAgICBzZXRTY3JvbGxMZWZ0KGNtLCBkLnNjcm9sbGVyLnNjcm9sbExlZnQsIHRydWUpO1xuICAgICAgICBzaWduYWwoY20sIFwic2Nyb2xsXCIsIGNtKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIExpc3RlbiB0byB3aGVlbCBldmVudHMgaW4gb3JkZXIgdG8gdHJ5IGFuZCB1cGRhdGUgdGhlIHZpZXdwb3J0IG9uIHRpbWUuXG4gICAgb24oZC5zY3JvbGxlciwgXCJtb3VzZXdoZWVsXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBvblNjcm9sbFdoZWVsKGNtLCBlKTsgfSk7XG4gICAgb24oZC5zY3JvbGxlciwgXCJET01Nb3VzZVNjcm9sbFwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gb25TY3JvbGxXaGVlbChjbSwgZSk7IH0pO1xuXG4gICAgLy8gUHJldmVudCB3cmFwcGVyIGZyb20gZXZlciBzY3JvbGxpbmdcbiAgICBvbihkLndyYXBwZXIsIFwic2Nyb2xsXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIGQud3JhcHBlci5zY3JvbGxUb3AgPSBkLndyYXBwZXIuc2Nyb2xsTGVmdCA9IDA7IH0pO1xuXG4gICAgZC5kcmFnRnVuY3Rpb25zID0ge1xuICAgICAgZW50ZXI6IGZ1bmN0aW9uIChlKSB7aWYgKCFzaWduYWxET01FdmVudChjbSwgZSkpIHsgZV9zdG9wKGUpOyB9fSxcbiAgICAgIG92ZXI6IGZ1bmN0aW9uIChlKSB7aWYgKCFzaWduYWxET01FdmVudChjbSwgZSkpIHsgb25EcmFnT3ZlcihjbSwgZSk7IGVfc3RvcChlKTsgfX0sXG4gICAgICBzdGFydDogZnVuY3Rpb24gKGUpIHsgcmV0dXJuIG9uRHJhZ1N0YXJ0KGNtLCBlKTsgfSxcbiAgICAgIGRyb3A6IG9wZXJhdGlvbihjbSwgb25Ecm9wKSxcbiAgICAgIGxlYXZlOiBmdW5jdGlvbiAoZSkge2lmICghc2lnbmFsRE9NRXZlbnQoY20sIGUpKSB7IGNsZWFyRHJhZ0N1cnNvcihjbSk7IH19XG4gICAgfTtcblxuICAgIHZhciBpbnAgPSBkLmlucHV0LmdldEZpZWxkKCk7XG4gICAgb24oaW5wLCBcImtleXVwXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBvbktleVVwLmNhbGwoY20sIGUpOyB9KTtcbiAgICBvbihpbnAsIFwia2V5ZG93blwiLCBvcGVyYXRpb24oY20sIG9uS2V5RG93bikpO1xuICAgIG9uKGlucCwgXCJrZXlwcmVzc1wiLCBvcGVyYXRpb24oY20sIG9uS2V5UHJlc3MpKTtcbiAgICBvbihpbnAsIFwiZm9jdXNcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIG9uRm9jdXMoY20sIGUpOyB9KTtcbiAgICBvbihpbnAsIFwiYmx1clwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gb25CbHVyKGNtLCBlKTsgfSk7XG4gIH1cblxuICB2YXIgaW5pdEhvb2tzID0gW107XG4gIENvZGVNaXJyb3IuZGVmaW5lSW5pdEhvb2sgPSBmdW5jdGlvbiAoZikgeyByZXR1cm4gaW5pdEhvb2tzLnB1c2goZik7IH07XG5cbiAgLy8gSW5kZW50IHRoZSBnaXZlbiBsaW5lLiBUaGUgaG93IHBhcmFtZXRlciBjYW4gYmUgXCJzbWFydFwiLFxuICAvLyBcImFkZFwiL251bGwsIFwic3VidHJhY3RcIiwgb3IgXCJwcmV2XCIuIFdoZW4gYWdncmVzc2l2ZSBpcyBmYWxzZVxuICAvLyAodHlwaWNhbGx5IHNldCB0byB0cnVlIGZvciBmb3JjZWQgc2luZ2xlLWxpbmUgaW5kZW50cyksIGVtcHR5XG4gIC8vIGxpbmVzIGFyZSBub3QgaW5kZW50ZWQsIGFuZCBwbGFjZXMgd2hlcmUgdGhlIG1vZGUgcmV0dXJucyBQYXNzXG4gIC8vIGFyZSBsZWZ0IGFsb25lLlxuICBmdW5jdGlvbiBpbmRlbnRMaW5lKGNtLCBuLCBob3csIGFnZ3Jlc3NpdmUpIHtcbiAgICB2YXIgZG9jID0gY20uZG9jLCBzdGF0ZTtcbiAgICBpZiAoaG93ID09IG51bGwpIHsgaG93ID0gXCJhZGRcIjsgfVxuICAgIGlmIChob3cgPT0gXCJzbWFydFwiKSB7XG4gICAgICAvLyBGYWxsIGJhY2sgdG8gXCJwcmV2XCIgd2hlbiB0aGUgbW9kZSBkb2Vzbid0IGhhdmUgYW4gaW5kZW50YXRpb25cbiAgICAgIC8vIG1ldGhvZC5cbiAgICAgIGlmICghZG9jLm1vZGUuaW5kZW50KSB7IGhvdyA9IFwicHJldlwiOyB9XG4gICAgICBlbHNlIHsgc3RhdGUgPSBnZXRDb250ZXh0QmVmb3JlKGNtLCBuKS5zdGF0ZTsgfVxuICAgIH1cblxuICAgIHZhciB0YWJTaXplID0gY20ub3B0aW9ucy50YWJTaXplO1xuICAgIHZhciBsaW5lID0gZ2V0TGluZShkb2MsIG4pLCBjdXJTcGFjZSA9IGNvdW50Q29sdW1uKGxpbmUudGV4dCwgbnVsbCwgdGFiU2l6ZSk7XG4gICAgaWYgKGxpbmUuc3RhdGVBZnRlcikgeyBsaW5lLnN0YXRlQWZ0ZXIgPSBudWxsOyB9XG4gICAgdmFyIGN1clNwYWNlU3RyaW5nID0gbGluZS50ZXh0Lm1hdGNoKC9eXFxzKi8pWzBdLCBpbmRlbnRhdGlvbjtcbiAgICBpZiAoIWFnZ3Jlc3NpdmUgJiYgIS9cXFMvLnRlc3QobGluZS50ZXh0KSkge1xuICAgICAgaW5kZW50YXRpb24gPSAwO1xuICAgICAgaG93ID0gXCJub3RcIjtcbiAgICB9IGVsc2UgaWYgKGhvdyA9PSBcInNtYXJ0XCIpIHtcbiAgICAgIGluZGVudGF0aW9uID0gZG9jLm1vZGUuaW5kZW50KHN0YXRlLCBsaW5lLnRleHQuc2xpY2UoY3VyU3BhY2VTdHJpbmcubGVuZ3RoKSwgbGluZS50ZXh0KTtcbiAgICAgIGlmIChpbmRlbnRhdGlvbiA9PSBQYXNzIHx8IGluZGVudGF0aW9uID4gMTUwKSB7XG4gICAgICAgIGlmICghYWdncmVzc2l2ZSkgeyByZXR1cm4gfVxuICAgICAgICBob3cgPSBcInByZXZcIjtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGhvdyA9PSBcInByZXZcIikge1xuICAgICAgaWYgKG4gPiBkb2MuZmlyc3QpIHsgaW5kZW50YXRpb24gPSBjb3VudENvbHVtbihnZXRMaW5lKGRvYywgbi0xKS50ZXh0LCBudWxsLCB0YWJTaXplKTsgfVxuICAgICAgZWxzZSB7IGluZGVudGF0aW9uID0gMDsgfVxuICAgIH0gZWxzZSBpZiAoaG93ID09IFwiYWRkXCIpIHtcbiAgICAgIGluZGVudGF0aW9uID0gY3VyU3BhY2UgKyBjbS5vcHRpb25zLmluZGVudFVuaXQ7XG4gICAgfSBlbHNlIGlmIChob3cgPT0gXCJzdWJ0cmFjdFwiKSB7XG4gICAgICBpbmRlbnRhdGlvbiA9IGN1clNwYWNlIC0gY20ub3B0aW9ucy5pbmRlbnRVbml0O1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGhvdyA9PSBcIm51bWJlclwiKSB7XG4gICAgICBpbmRlbnRhdGlvbiA9IGN1clNwYWNlICsgaG93O1xuICAgIH1cbiAgICBpbmRlbnRhdGlvbiA9IE1hdGgubWF4KDAsIGluZGVudGF0aW9uKTtcblxuICAgIHZhciBpbmRlbnRTdHJpbmcgPSBcIlwiLCBwb3MgPSAwO1xuICAgIGlmIChjbS5vcHRpb25zLmluZGVudFdpdGhUYWJzKVxuICAgICAgeyBmb3IgKHZhciBpID0gTWF0aC5mbG9vcihpbmRlbnRhdGlvbiAvIHRhYlNpemUpOyBpOyAtLWkpIHtwb3MgKz0gdGFiU2l6ZTsgaW5kZW50U3RyaW5nICs9IFwiXFx0XCI7fSB9XG4gICAgaWYgKHBvcyA8IGluZGVudGF0aW9uKSB7IGluZGVudFN0cmluZyArPSBzcGFjZVN0cihpbmRlbnRhdGlvbiAtIHBvcyk7IH1cblxuICAgIGlmIChpbmRlbnRTdHJpbmcgIT0gY3VyU3BhY2VTdHJpbmcpIHtcbiAgICAgIHJlcGxhY2VSYW5nZShkb2MsIGluZGVudFN0cmluZywgUG9zKG4sIDApLCBQb3MobiwgY3VyU3BhY2VTdHJpbmcubGVuZ3RoKSwgXCIraW5wdXRcIik7XG4gICAgICBsaW5lLnN0YXRlQWZ0ZXIgPSBudWxsO1xuICAgICAgcmV0dXJuIHRydWVcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRW5zdXJlIHRoYXQsIGlmIHRoZSBjdXJzb3Igd2FzIGluIHRoZSB3aGl0ZXNwYWNlIGF0IHRoZSBzdGFydFxuICAgICAgLy8gb2YgdGhlIGxpbmUsIGl0IGlzIG1vdmVkIHRvIHRoZSBlbmQgb2YgdGhhdCBzcGFjZS5cbiAgICAgIGZvciAodmFyIGkkMSA9IDA7IGkkMSA8IGRvYy5zZWwucmFuZ2VzLmxlbmd0aDsgaSQxKyspIHtcbiAgICAgICAgdmFyIHJhbmdlID0gZG9jLnNlbC5yYW5nZXNbaSQxXTtcbiAgICAgICAgaWYgKHJhbmdlLmhlYWQubGluZSA9PSBuICYmIHJhbmdlLmhlYWQuY2ggPCBjdXJTcGFjZVN0cmluZy5sZW5ndGgpIHtcbiAgICAgICAgICB2YXIgcG9zJDEgPSBQb3MobiwgY3VyU3BhY2VTdHJpbmcubGVuZ3RoKTtcbiAgICAgICAgICByZXBsYWNlT25lU2VsZWN0aW9uKGRvYywgaSQxLCBuZXcgUmFuZ2UocG9zJDEsIHBvcyQxKSk7XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIFRoaXMgd2lsbCBiZSBzZXQgdG8gYSB7bGluZVdpc2U6IGJvb2wsIHRleHQ6IFtzdHJpbmddfSBvYmplY3QsIHNvXG4gIC8vIHRoYXQsIHdoZW4gcGFzdGluZywgd2Uga25vdyB3aGF0IGtpbmQgb2Ygc2VsZWN0aW9ucyB0aGUgY29waWVkXG4gIC8vIHRleHQgd2FzIG1hZGUgb3V0IG9mLlxuICB2YXIgbGFzdENvcGllZCA9IG51bGw7XG5cbiAgZnVuY3Rpb24gc2V0TGFzdENvcGllZChuZXdMYXN0Q29waWVkKSB7XG4gICAgbGFzdENvcGllZCA9IG5ld0xhc3RDb3BpZWQ7XG4gIH1cblxuICBmdW5jdGlvbiBhcHBseVRleHRJbnB1dChjbSwgaW5zZXJ0ZWQsIGRlbGV0ZWQsIHNlbCwgb3JpZ2luKSB7XG4gICAgdmFyIGRvYyA9IGNtLmRvYztcbiAgICBjbS5kaXNwbGF5LnNoaWZ0ID0gZmFsc2U7XG4gICAgaWYgKCFzZWwpIHsgc2VsID0gZG9jLnNlbDsgfVxuXG4gICAgdmFyIHJlY2VudCA9ICtuZXcgRGF0ZSAtIDIwMDtcbiAgICB2YXIgcGFzdGUgPSBvcmlnaW4gPT0gXCJwYXN0ZVwiIHx8IGNtLnN0YXRlLnBhc3RlSW5jb21pbmcgPiByZWNlbnQ7XG4gICAgdmFyIHRleHRMaW5lcyA9IHNwbGl0TGluZXNBdXRvKGluc2VydGVkKSwgbXVsdGlQYXN0ZSA9IG51bGw7XG4gICAgLy8gV2hlbiBwYXN0aW5nIE4gbGluZXMgaW50byBOIHNlbGVjdGlvbnMsIGluc2VydCBvbmUgbGluZSBwZXIgc2VsZWN0aW9uXG4gICAgaWYgKHBhc3RlICYmIHNlbC5yYW5nZXMubGVuZ3RoID4gMSkge1xuICAgICAgaWYgKGxhc3RDb3BpZWQgJiYgbGFzdENvcGllZC50ZXh0LmpvaW4oXCJcXG5cIikgPT0gaW5zZXJ0ZWQpIHtcbiAgICAgICAgaWYgKHNlbC5yYW5nZXMubGVuZ3RoICUgbGFzdENvcGllZC50ZXh0Lmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgbXVsdGlQYXN0ZSA9IFtdO1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGFzdENvcGllZC50ZXh0Lmxlbmd0aDsgaSsrKVxuICAgICAgICAgICAgeyBtdWx0aVBhc3RlLnB1c2goZG9jLnNwbGl0TGluZXMobGFzdENvcGllZC50ZXh0W2ldKSk7IH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0ZXh0TGluZXMubGVuZ3RoID09IHNlbC5yYW5nZXMubGVuZ3RoICYmIGNtLm9wdGlvbnMucGFzdGVMaW5lc1BlclNlbGVjdGlvbikge1xuICAgICAgICBtdWx0aVBhc3RlID0gbWFwKHRleHRMaW5lcywgZnVuY3Rpb24gKGwpIHsgcmV0dXJuIFtsXTsgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHVwZGF0ZUlucHV0ID0gY20uY3VyT3AudXBkYXRlSW5wdXQ7XG4gICAgLy8gTm9ybWFsIGJlaGF2aW9yIGlzIHRvIGluc2VydCB0aGUgbmV3IHRleHQgaW50byBldmVyeSBzZWxlY3Rpb25cbiAgICBmb3IgKHZhciBpJDEgPSBzZWwucmFuZ2VzLmxlbmd0aCAtIDE7IGkkMSA+PSAwOyBpJDEtLSkge1xuICAgICAgdmFyIHJhbmdlID0gc2VsLnJhbmdlc1tpJDFdO1xuICAgICAgdmFyIGZyb20gPSByYW5nZS5mcm9tKCksIHRvID0gcmFuZ2UudG8oKTtcbiAgICAgIGlmIChyYW5nZS5lbXB0eSgpKSB7XG4gICAgICAgIGlmIChkZWxldGVkICYmIGRlbGV0ZWQgPiAwKSAvLyBIYW5kbGUgZGVsZXRpb25cbiAgICAgICAgICB7IGZyb20gPSBQb3MoZnJvbS5saW5lLCBmcm9tLmNoIC0gZGVsZXRlZCk7IH1cbiAgICAgICAgZWxzZSBpZiAoY20uc3RhdGUub3ZlcndyaXRlICYmICFwYXN0ZSkgLy8gSGFuZGxlIG92ZXJ3cml0ZVxuICAgICAgICAgIHsgdG8gPSBQb3ModG8ubGluZSwgTWF0aC5taW4oZ2V0TGluZShkb2MsIHRvLmxpbmUpLnRleHQubGVuZ3RoLCB0by5jaCArIGxzdCh0ZXh0TGluZXMpLmxlbmd0aCkpOyB9XG4gICAgICAgIGVsc2UgaWYgKHBhc3RlICYmIGxhc3RDb3BpZWQgJiYgbGFzdENvcGllZC5saW5lV2lzZSAmJiBsYXN0Q29waWVkLnRleHQuam9pbihcIlxcblwiKSA9PSB0ZXh0TGluZXMuam9pbihcIlxcblwiKSlcbiAgICAgICAgICB7IGZyb20gPSB0byA9IFBvcyhmcm9tLmxpbmUsIDApOyB9XG4gICAgICB9XG4gICAgICB2YXIgY2hhbmdlRXZlbnQgPSB7ZnJvbTogZnJvbSwgdG86IHRvLCB0ZXh0OiBtdWx0aVBhc3RlID8gbXVsdGlQYXN0ZVtpJDEgJSBtdWx0aVBhc3RlLmxlbmd0aF0gOiB0ZXh0TGluZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgb3JpZ2luOiBvcmlnaW4gfHwgKHBhc3RlID8gXCJwYXN0ZVwiIDogY20uc3RhdGUuY3V0SW5jb21pbmcgPiByZWNlbnQgPyBcImN1dFwiIDogXCIraW5wdXRcIil9O1xuICAgICAgbWFrZUNoYW5nZShjbS5kb2MsIGNoYW5nZUV2ZW50KTtcbiAgICAgIHNpZ25hbExhdGVyKGNtLCBcImlucHV0UmVhZFwiLCBjbSwgY2hhbmdlRXZlbnQpO1xuICAgIH1cbiAgICBpZiAoaW5zZXJ0ZWQgJiYgIXBhc3RlKVxuICAgICAgeyB0cmlnZ2VyRWxlY3RyaWMoY20sIGluc2VydGVkKTsgfVxuXG4gICAgZW5zdXJlQ3Vyc29yVmlzaWJsZShjbSk7XG4gICAgaWYgKGNtLmN1ck9wLnVwZGF0ZUlucHV0IDwgMikgeyBjbS5jdXJPcC51cGRhdGVJbnB1dCA9IHVwZGF0ZUlucHV0OyB9XG4gICAgY20uY3VyT3AudHlwaW5nID0gdHJ1ZTtcbiAgICBjbS5zdGF0ZS5wYXN0ZUluY29taW5nID0gY20uc3RhdGUuY3V0SW5jb21pbmcgPSAtMTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGhhbmRsZVBhc3RlKGUsIGNtKSB7XG4gICAgdmFyIHBhc3RlZCA9IGUuY2xpcGJvYXJkRGF0YSAmJiBlLmNsaXBib2FyZERhdGEuZ2V0RGF0YShcIlRleHRcIik7XG4gICAgaWYgKHBhc3RlZCkge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgaWYgKCFjbS5pc1JlYWRPbmx5KCkgJiYgIWNtLm9wdGlvbnMuZGlzYWJsZUlucHV0ICYmIGNtLmhhc0ZvY3VzKCkpXG4gICAgICAgIHsgcnVuSW5PcChjbSwgZnVuY3Rpb24gKCkgeyByZXR1cm4gYXBwbHlUZXh0SW5wdXQoY20sIHBhc3RlZCwgMCwgbnVsbCwgXCJwYXN0ZVwiKTsgfSk7IH1cbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gdHJpZ2dlckVsZWN0cmljKGNtLCBpbnNlcnRlZCkge1xuICAgIC8vIFdoZW4gYW4gJ2VsZWN0cmljJyBjaGFyYWN0ZXIgaXMgaW5zZXJ0ZWQsIGltbWVkaWF0ZWx5IHRyaWdnZXIgYSByZWluZGVudFxuICAgIGlmICghY20ub3B0aW9ucy5lbGVjdHJpY0NoYXJzIHx8ICFjbS5vcHRpb25zLnNtYXJ0SW5kZW50KSB7IHJldHVybiB9XG4gICAgdmFyIHNlbCA9IGNtLmRvYy5zZWw7XG5cbiAgICBmb3IgKHZhciBpID0gc2VsLnJhbmdlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgdmFyIHJhbmdlID0gc2VsLnJhbmdlc1tpXTtcbiAgICAgIGlmIChyYW5nZS5oZWFkLmNoID4gMTAwIHx8IChpICYmIHNlbC5yYW5nZXNbaSAtIDFdLmhlYWQubGluZSA9PSByYW5nZS5oZWFkLmxpbmUpKSB7IGNvbnRpbnVlIH1cbiAgICAgIHZhciBtb2RlID0gY20uZ2V0TW9kZUF0KHJhbmdlLmhlYWQpO1xuICAgICAgdmFyIGluZGVudGVkID0gZmFsc2U7XG4gICAgICBpZiAobW9kZS5lbGVjdHJpY0NoYXJzKSB7XG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbW9kZS5lbGVjdHJpY0NoYXJzLmxlbmd0aDsgaisrKVxuICAgICAgICAgIHsgaWYgKGluc2VydGVkLmluZGV4T2YobW9kZS5lbGVjdHJpY0NoYXJzLmNoYXJBdChqKSkgPiAtMSkge1xuICAgICAgICAgICAgaW5kZW50ZWQgPSBpbmRlbnRMaW5lKGNtLCByYW5nZS5oZWFkLmxpbmUsIFwic21hcnRcIik7XG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIH0gfVxuICAgICAgfSBlbHNlIGlmIChtb2RlLmVsZWN0cmljSW5wdXQpIHtcbiAgICAgICAgaWYgKG1vZGUuZWxlY3RyaWNJbnB1dC50ZXN0KGdldExpbmUoY20uZG9jLCByYW5nZS5oZWFkLmxpbmUpLnRleHQuc2xpY2UoMCwgcmFuZ2UuaGVhZC5jaCkpKVxuICAgICAgICAgIHsgaW5kZW50ZWQgPSBpbmRlbnRMaW5lKGNtLCByYW5nZS5oZWFkLmxpbmUsIFwic21hcnRcIik7IH1cbiAgICAgIH1cbiAgICAgIGlmIChpbmRlbnRlZCkgeyBzaWduYWxMYXRlcihjbSwgXCJlbGVjdHJpY0lucHV0XCIsIGNtLCByYW5nZS5oZWFkLmxpbmUpOyB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gY29weWFibGVSYW5nZXMoY20pIHtcbiAgICB2YXIgdGV4dCA9IFtdLCByYW5nZXMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNtLmRvYy5zZWwucmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgbGluZSA9IGNtLmRvYy5zZWwucmFuZ2VzW2ldLmhlYWQubGluZTtcbiAgICAgIHZhciBsaW5lUmFuZ2UgPSB7YW5jaG9yOiBQb3MobGluZSwgMCksIGhlYWQ6IFBvcyhsaW5lICsgMSwgMCl9O1xuICAgICAgcmFuZ2VzLnB1c2gobGluZVJhbmdlKTtcbiAgICAgIHRleHQucHVzaChjbS5nZXRSYW5nZShsaW5lUmFuZ2UuYW5jaG9yLCBsaW5lUmFuZ2UuaGVhZCkpO1xuICAgIH1cbiAgICByZXR1cm4ge3RleHQ6IHRleHQsIHJhbmdlczogcmFuZ2VzfVxuICB9XG5cbiAgZnVuY3Rpb24gZGlzYWJsZUJyb3dzZXJNYWdpYyhmaWVsZCwgc3BlbGxjaGVjaywgYXV0b2NvcnJlY3QsIGF1dG9jYXBpdGFsaXplKSB7XG4gICAgZmllbGQuc2V0QXR0cmlidXRlKFwiYXV0b2NvcnJlY3RcIiwgYXV0b2NvcnJlY3QgPyBcIlwiIDogXCJvZmZcIik7XG4gICAgZmllbGQuc2V0QXR0cmlidXRlKFwiYXV0b2NhcGl0YWxpemVcIiwgYXV0b2NhcGl0YWxpemUgPyBcIlwiIDogXCJvZmZcIik7XG4gICAgZmllbGQuc2V0QXR0cmlidXRlKFwic3BlbGxjaGVja1wiLCAhIXNwZWxsY2hlY2spO1xuICB9XG5cbiAgZnVuY3Rpb24gaGlkZGVuVGV4dGFyZWEoKSB7XG4gICAgdmFyIHRlID0gZWx0KFwidGV4dGFyZWFcIiwgbnVsbCwgbnVsbCwgXCJwb3NpdGlvbjogYWJzb2x1dGU7IGJvdHRvbTogLTFlbTsgcGFkZGluZzogMDsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxZW07IG1pbi1oZWlnaHQ6IDFlbTsgb3V0bGluZTogbm9uZVwiKTtcbiAgICB2YXIgZGl2ID0gZWx0KFwiZGl2XCIsIFt0ZV0sIG51bGwsIFwib3ZlcmZsb3c6IGhpZGRlbjsgcG9zaXRpb246IHJlbGF0aXZlOyB3aWR0aDogM3B4OyBoZWlnaHQ6IDBweDtcIik7XG4gICAgLy8gVGhlIHRleHRhcmVhIGlzIGtlcHQgcG9zaXRpb25lZCBuZWFyIHRoZSBjdXJzb3IgdG8gcHJldmVudCB0aGVcbiAgICAvLyBmYWN0IHRoYXQgaXQnbGwgYmUgc2Nyb2xsZWQgaW50byB2aWV3IG9uIGlucHV0IGZyb20gc2Nyb2xsaW5nXG4gICAgLy8gb3VyIGZha2UgY3Vyc29yIG91dCBvZiB2aWV3LiBPbiB3ZWJraXQsIHdoZW4gd3JhcD1vZmYsIHBhc3RlIGlzXG4gICAgLy8gdmVyeSBzbG93LiBTbyBtYWtlIHRoZSBhcmVhIHdpZGUgaW5zdGVhZC5cbiAgICBpZiAod2Via2l0KSB7IHRlLnN0eWxlLndpZHRoID0gXCIxMDAwcHhcIjsgfVxuICAgIGVsc2UgeyB0ZS5zZXRBdHRyaWJ1dGUoXCJ3cmFwXCIsIFwib2ZmXCIpOyB9XG4gICAgLy8gSWYgYm9yZGVyOiAwOyAtLSBpT1MgZmFpbHMgdG8gb3BlbiBrZXlib2FyZCAoaXNzdWUgIzEyODcpXG4gICAgaWYgKGlvcykgeyB0ZS5zdHlsZS5ib3JkZXIgPSBcIjFweCBzb2xpZCBibGFja1wiOyB9XG4gICAgZGlzYWJsZUJyb3dzZXJNYWdpYyh0ZSk7XG4gICAgcmV0dXJuIGRpdlxuICB9XG5cbiAgLy8gVGhlIHB1YmxpY2x5IHZpc2libGUgQVBJLiBOb3RlIHRoYXQgbWV0aG9kT3AoZikgbWVhbnNcbiAgLy8gJ3dyYXAgZiBpbiBhbiBvcGVyYXRpb24sIHBlcmZvcm1lZCBvbiBpdHMgYHRoaXNgIHBhcmFtZXRlcicuXG5cbiAgLy8gVGhpcyBpcyBub3QgdGhlIGNvbXBsZXRlIHNldCBvZiBlZGl0b3IgbWV0aG9kcy4gTW9zdCBvZiB0aGVcbiAgLy8gbWV0aG9kcyBkZWZpbmVkIG9uIHRoZSBEb2MgdHlwZSBhcmUgYWxzbyBpbmplY3RlZCBpbnRvXG4gIC8vIENvZGVNaXJyb3IucHJvdG90eXBlLCBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgYW5kXG4gIC8vIGNvbnZlbmllbmNlLlxuXG4gIGZ1bmN0aW9uIGFkZEVkaXRvck1ldGhvZHMoQ29kZU1pcnJvcikge1xuICAgIHZhciBvcHRpb25IYW5kbGVycyA9IENvZGVNaXJyb3Iub3B0aW9uSGFuZGxlcnM7XG5cbiAgICB2YXIgaGVscGVycyA9IENvZGVNaXJyb3IuaGVscGVycyA9IHt9O1xuXG4gICAgQ29kZU1pcnJvci5wcm90b3R5cGUgPSB7XG4gICAgICBjb25zdHJ1Y3RvcjogQ29kZU1pcnJvcixcbiAgICAgIGZvY3VzOiBmdW5jdGlvbigpe3dpbmRvdy5mb2N1cygpOyB0aGlzLmRpc3BsYXkuaW5wdXQuZm9jdXMoKTt9LFxuXG4gICAgICBzZXRPcHRpb246IGZ1bmN0aW9uKG9wdGlvbiwgdmFsdWUpIHtcbiAgICAgICAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMsIG9sZCA9IG9wdGlvbnNbb3B0aW9uXTtcbiAgICAgICAgaWYgKG9wdGlvbnNbb3B0aW9uXSA9PSB2YWx1ZSAmJiBvcHRpb24gIT0gXCJtb2RlXCIpIHsgcmV0dXJuIH1cbiAgICAgICAgb3B0aW9uc1tvcHRpb25dID0gdmFsdWU7XG4gICAgICAgIGlmIChvcHRpb25IYW5kbGVycy5oYXNPd25Qcm9wZXJ0eShvcHRpb24pKVxuICAgICAgICAgIHsgb3BlcmF0aW9uKHRoaXMsIG9wdGlvbkhhbmRsZXJzW29wdGlvbl0pKHRoaXMsIHZhbHVlLCBvbGQpOyB9XG4gICAgICAgIHNpZ25hbCh0aGlzLCBcIm9wdGlvbkNoYW5nZVwiLCB0aGlzLCBvcHRpb24pO1xuICAgICAgfSxcblxuICAgICAgZ2V0T3B0aW9uOiBmdW5jdGlvbihvcHRpb24pIHtyZXR1cm4gdGhpcy5vcHRpb25zW29wdGlvbl19LFxuICAgICAgZ2V0RG9jOiBmdW5jdGlvbigpIHtyZXR1cm4gdGhpcy5kb2N9LFxuXG4gICAgICBhZGRLZXlNYXA6IGZ1bmN0aW9uKG1hcCwgYm90dG9tKSB7XG4gICAgICAgIHRoaXMuc3RhdGUua2V5TWFwc1tib3R0b20gPyBcInB1c2hcIiA6IFwidW5zaGlmdFwiXShnZXRLZXlNYXAobWFwKSk7XG4gICAgICB9LFxuICAgICAgcmVtb3ZlS2V5TWFwOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdmFyIG1hcHMgPSB0aGlzLnN0YXRlLmtleU1hcHM7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWFwcy5sZW5ndGg7ICsraSlcbiAgICAgICAgICB7IGlmIChtYXBzW2ldID09IG1hcCB8fCBtYXBzW2ldLm5hbWUgPT0gbWFwKSB7XG4gICAgICAgICAgICBtYXBzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgICAgfSB9XG4gICAgICB9LFxuXG4gICAgICBhZGRPdmVybGF5OiBtZXRob2RPcChmdW5jdGlvbihzcGVjLCBvcHRpb25zKSB7XG4gICAgICAgIHZhciBtb2RlID0gc3BlYy50b2tlbiA/IHNwZWMgOiBDb2RlTWlycm9yLmdldE1vZGUodGhpcy5vcHRpb25zLCBzcGVjKTtcbiAgICAgICAgaWYgKG1vZGUuc3RhcnRTdGF0ZSkgeyB0aHJvdyBuZXcgRXJyb3IoXCJPdmVybGF5cyBtYXkgbm90IGJlIHN0YXRlZnVsLlwiKSB9XG4gICAgICAgIGluc2VydFNvcnRlZCh0aGlzLnN0YXRlLm92ZXJsYXlzLFxuICAgICAgICAgICAgICAgICAgICAge21vZGU6IG1vZGUsIG1vZGVTcGVjOiBzcGVjLCBvcGFxdWU6IG9wdGlvbnMgJiYgb3B0aW9ucy5vcGFxdWUsXG4gICAgICAgICAgICAgICAgICAgICAgcHJpb3JpdHk6IChvcHRpb25zICYmIG9wdGlvbnMucHJpb3JpdHkpIHx8IDB9LFxuICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKG92ZXJsYXkpIHsgcmV0dXJuIG92ZXJsYXkucHJpb3JpdHk7IH0pO1xuICAgICAgICB0aGlzLnN0YXRlLm1vZGVHZW4rKztcbiAgICAgICAgcmVnQ2hhbmdlKHRoaXMpO1xuICAgICAgfSksXG4gICAgICByZW1vdmVPdmVybGF5OiBtZXRob2RPcChmdW5jdGlvbihzcGVjKSB7XG4gICAgICAgIHZhciBvdmVybGF5cyA9IHRoaXMuc3RhdGUub3ZlcmxheXM7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3ZlcmxheXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICB2YXIgY3VyID0gb3ZlcmxheXNbaV0ubW9kZVNwZWM7XG4gICAgICAgICAgaWYgKGN1ciA9PSBzcGVjIHx8IHR5cGVvZiBzcGVjID09IFwic3RyaW5nXCIgJiYgY3VyLm5hbWUgPT0gc3BlYykge1xuICAgICAgICAgICAgb3ZlcmxheXMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgdGhpcy5zdGF0ZS5tb2RlR2VuKys7XG4gICAgICAgICAgICByZWdDaGFuZ2UodGhpcyk7XG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pLFxuXG4gICAgICBpbmRlbnRMaW5lOiBtZXRob2RPcChmdW5jdGlvbihuLCBkaXIsIGFnZ3Jlc3NpdmUpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBkaXIgIT0gXCJzdHJpbmdcIiAmJiB0eXBlb2YgZGlyICE9IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICBpZiAoZGlyID09IG51bGwpIHsgZGlyID0gdGhpcy5vcHRpb25zLnNtYXJ0SW5kZW50ID8gXCJzbWFydFwiIDogXCJwcmV2XCI7IH1cbiAgICAgICAgICBlbHNlIHsgZGlyID0gZGlyID8gXCJhZGRcIiA6IFwic3VidHJhY3RcIjsgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChpc0xpbmUodGhpcy5kb2MsIG4pKSB7IGluZGVudExpbmUodGhpcywgbiwgZGlyLCBhZ2dyZXNzaXZlKTsgfVxuICAgICAgfSksXG4gICAgICBpbmRlbnRTZWxlY3Rpb246IG1ldGhvZE9wKGZ1bmN0aW9uKGhvdykge1xuICAgICAgICB2YXIgcmFuZ2VzID0gdGhpcy5kb2Muc2VsLnJhbmdlcywgZW5kID0gLTE7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIHJhbmdlID0gcmFuZ2VzW2ldO1xuICAgICAgICAgIGlmICghcmFuZ2UuZW1wdHkoKSkge1xuICAgICAgICAgICAgdmFyIGZyb20gPSByYW5nZS5mcm9tKCksIHRvID0gcmFuZ2UudG8oKTtcbiAgICAgICAgICAgIHZhciBzdGFydCA9IE1hdGgubWF4KGVuZCwgZnJvbS5saW5lKTtcbiAgICAgICAgICAgIGVuZCA9IE1hdGgubWluKHRoaXMubGFzdExpbmUoKSwgdG8ubGluZSAtICh0by5jaCA/IDAgOiAxKSkgKyAxO1xuICAgICAgICAgICAgZm9yICh2YXIgaiA9IHN0YXJ0OyBqIDwgZW5kOyArK2opXG4gICAgICAgICAgICAgIHsgaW5kZW50TGluZSh0aGlzLCBqLCBob3cpOyB9XG4gICAgICAgICAgICB2YXIgbmV3UmFuZ2VzID0gdGhpcy5kb2Muc2VsLnJhbmdlcztcbiAgICAgICAgICAgIGlmIChmcm9tLmNoID09IDAgJiYgcmFuZ2VzLmxlbmd0aCA9PSBuZXdSYW5nZXMubGVuZ3RoICYmIG5ld1Jhbmdlc1tpXS5mcm9tKCkuY2ggPiAwKVxuICAgICAgICAgICAgICB7IHJlcGxhY2VPbmVTZWxlY3Rpb24odGhpcy5kb2MsIGksIG5ldyBSYW5nZShmcm9tLCBuZXdSYW5nZXNbaV0udG8oKSksIHNlbF9kb250U2Nyb2xsKTsgfVxuICAgICAgICAgIH0gZWxzZSBpZiAocmFuZ2UuaGVhZC5saW5lID4gZW5kKSB7XG4gICAgICAgICAgICBpbmRlbnRMaW5lKHRoaXMsIHJhbmdlLmhlYWQubGluZSwgaG93LCB0cnVlKTtcbiAgICAgICAgICAgIGVuZCA9IHJhbmdlLmhlYWQubGluZTtcbiAgICAgICAgICAgIGlmIChpID09IHRoaXMuZG9jLnNlbC5wcmltSW5kZXgpIHsgZW5zdXJlQ3Vyc29yVmlzaWJsZSh0aGlzKTsgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSksXG5cbiAgICAgIC8vIEZldGNoIHRoZSBwYXJzZXIgdG9rZW4gZm9yIGEgZ2l2ZW4gY2hhcmFjdGVyLiBVc2VmdWwgZm9yIGhhY2tzXG4gICAgICAvLyB0aGF0IHdhbnQgdG8gaW5zcGVjdCB0aGUgbW9kZSBzdGF0ZSAoc2F5LCBmb3IgY29tcGxldGlvbikuXG4gICAgICBnZXRUb2tlbkF0OiBmdW5jdGlvbihwb3MsIHByZWNpc2UpIHtcbiAgICAgICAgcmV0dXJuIHRha2VUb2tlbih0aGlzLCBwb3MsIHByZWNpc2UpXG4gICAgICB9LFxuXG4gICAgICBnZXRMaW5lVG9rZW5zOiBmdW5jdGlvbihsaW5lLCBwcmVjaXNlKSB7XG4gICAgICAgIHJldHVybiB0YWtlVG9rZW4odGhpcywgUG9zKGxpbmUpLCBwcmVjaXNlLCB0cnVlKVxuICAgICAgfSxcblxuICAgICAgZ2V0VG9rZW5UeXBlQXQ6IGZ1bmN0aW9uKHBvcykge1xuICAgICAgICBwb3MgPSBjbGlwUG9zKHRoaXMuZG9jLCBwb3MpO1xuICAgICAgICB2YXIgc3R5bGVzID0gZ2V0TGluZVN0eWxlcyh0aGlzLCBnZXRMaW5lKHRoaXMuZG9jLCBwb3MubGluZSkpO1xuICAgICAgICB2YXIgYmVmb3JlID0gMCwgYWZ0ZXIgPSAoc3R5bGVzLmxlbmd0aCAtIDEpIC8gMiwgY2ggPSBwb3MuY2g7XG4gICAgICAgIHZhciB0eXBlO1xuICAgICAgICBpZiAoY2ggPT0gMCkgeyB0eXBlID0gc3R5bGVzWzJdOyB9XG4gICAgICAgIGVsc2UgeyBmb3IgKDs7KSB7XG4gICAgICAgICAgdmFyIG1pZCA9IChiZWZvcmUgKyBhZnRlcikgPj4gMTtcbiAgICAgICAgICBpZiAoKG1pZCA/IHN0eWxlc1ttaWQgKiAyIC0gMV0gOiAwKSA+PSBjaCkgeyBhZnRlciA9IG1pZDsgfVxuICAgICAgICAgIGVsc2UgaWYgKHN0eWxlc1ttaWQgKiAyICsgMV0gPCBjaCkgeyBiZWZvcmUgPSBtaWQgKyAxOyB9XG4gICAgICAgICAgZWxzZSB7IHR5cGUgPSBzdHlsZXNbbWlkICogMiArIDJdOyBicmVhayB9XG4gICAgICAgIH0gfVxuICAgICAgICB2YXIgY3V0ID0gdHlwZSA/IHR5cGUuaW5kZXhPZihcIm92ZXJsYXkgXCIpIDogLTE7XG4gICAgICAgIHJldHVybiBjdXQgPCAwID8gdHlwZSA6IGN1dCA9PSAwID8gbnVsbCA6IHR5cGUuc2xpY2UoMCwgY3V0IC0gMSlcbiAgICAgIH0sXG5cbiAgICAgIGdldE1vZGVBdDogZnVuY3Rpb24ocG9zKSB7XG4gICAgICAgIHZhciBtb2RlID0gdGhpcy5kb2MubW9kZTtcbiAgICAgICAgaWYgKCFtb2RlLmlubmVyTW9kZSkgeyByZXR1cm4gbW9kZSB9XG4gICAgICAgIHJldHVybiBDb2RlTWlycm9yLmlubmVyTW9kZShtb2RlLCB0aGlzLmdldFRva2VuQXQocG9zKS5zdGF0ZSkubW9kZVxuICAgICAgfSxcblxuICAgICAgZ2V0SGVscGVyOiBmdW5jdGlvbihwb3MsIHR5cGUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0SGVscGVycyhwb3MsIHR5cGUpWzBdXG4gICAgICB9LFxuXG4gICAgICBnZXRIZWxwZXJzOiBmdW5jdGlvbihwb3MsIHR5cGUpIHtcbiAgICAgICAgdmFyIGZvdW5kID0gW107XG4gICAgICAgIGlmICghaGVscGVycy5oYXNPd25Qcm9wZXJ0eSh0eXBlKSkgeyByZXR1cm4gZm91bmQgfVxuICAgICAgICB2YXIgaGVscCA9IGhlbHBlcnNbdHlwZV0sIG1vZGUgPSB0aGlzLmdldE1vZGVBdChwb3MpO1xuICAgICAgICBpZiAodHlwZW9mIG1vZGVbdHlwZV0gPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgIGlmIChoZWxwW21vZGVbdHlwZV1dKSB7IGZvdW5kLnB1c2goaGVscFttb2RlW3R5cGVdXSk7IH1cbiAgICAgICAgfSBlbHNlIGlmIChtb2RlW3R5cGVdKSB7XG4gICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb2RlW3R5cGVdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgdmFsID0gaGVscFttb2RlW3R5cGVdW2ldXTtcbiAgICAgICAgICAgIGlmICh2YWwpIHsgZm91bmQucHVzaCh2YWwpOyB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKG1vZGUuaGVscGVyVHlwZSAmJiBoZWxwW21vZGUuaGVscGVyVHlwZV0pIHtcbiAgICAgICAgICBmb3VuZC5wdXNoKGhlbHBbbW9kZS5oZWxwZXJUeXBlXSk7XG4gICAgICAgIH0gZWxzZSBpZiAoaGVscFttb2RlLm5hbWVdKSB7XG4gICAgICAgICAgZm91bmQucHVzaChoZWxwW21vZGUubmFtZV0pO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGkkMSA9IDA7IGkkMSA8IGhlbHAuX2dsb2JhbC5sZW5ndGg7IGkkMSsrKSB7XG4gICAgICAgICAgdmFyIGN1ciA9IGhlbHAuX2dsb2JhbFtpJDFdO1xuICAgICAgICAgIGlmIChjdXIucHJlZChtb2RlLCB0aGlzKSAmJiBpbmRleE9mKGZvdW5kLCBjdXIudmFsKSA9PSAtMSlcbiAgICAgICAgICAgIHsgZm91bmQucHVzaChjdXIudmFsKTsgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmb3VuZFxuICAgICAgfSxcblxuICAgICAgZ2V0U3RhdGVBZnRlcjogZnVuY3Rpb24obGluZSwgcHJlY2lzZSkge1xuICAgICAgICB2YXIgZG9jID0gdGhpcy5kb2M7XG4gICAgICAgIGxpbmUgPSBjbGlwTGluZShkb2MsIGxpbmUgPT0gbnVsbCA/IGRvYy5maXJzdCArIGRvYy5zaXplIC0gMTogbGluZSk7XG4gICAgICAgIHJldHVybiBnZXRDb250ZXh0QmVmb3JlKHRoaXMsIGxpbmUgKyAxLCBwcmVjaXNlKS5zdGF0ZVxuICAgICAgfSxcblxuICAgICAgY3Vyc29yQ29vcmRzOiBmdW5jdGlvbihzdGFydCwgbW9kZSkge1xuICAgICAgICB2YXIgcG9zLCByYW5nZSA9IHRoaXMuZG9jLnNlbC5wcmltYXJ5KCk7XG4gICAgICAgIGlmIChzdGFydCA9PSBudWxsKSB7IHBvcyA9IHJhbmdlLmhlYWQ7IH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIHN0YXJ0ID09IFwib2JqZWN0XCIpIHsgcG9zID0gY2xpcFBvcyh0aGlzLmRvYywgc3RhcnQpOyB9XG4gICAgICAgIGVsc2UgeyBwb3MgPSBzdGFydCA/IHJhbmdlLmZyb20oKSA6IHJhbmdlLnRvKCk7IH1cbiAgICAgICAgcmV0dXJuIGN1cnNvckNvb3Jkcyh0aGlzLCBwb3MsIG1vZGUgfHwgXCJwYWdlXCIpXG4gICAgICB9LFxuXG4gICAgICBjaGFyQ29vcmRzOiBmdW5jdGlvbihwb3MsIG1vZGUpIHtcbiAgICAgICAgcmV0dXJuIGNoYXJDb29yZHModGhpcywgY2xpcFBvcyh0aGlzLmRvYywgcG9zKSwgbW9kZSB8fCBcInBhZ2VcIilcbiAgICAgIH0sXG5cbiAgICAgIGNvb3Jkc0NoYXI6IGZ1bmN0aW9uKGNvb3JkcywgbW9kZSkge1xuICAgICAgICBjb29yZHMgPSBmcm9tQ29vcmRTeXN0ZW0odGhpcywgY29vcmRzLCBtb2RlIHx8IFwicGFnZVwiKTtcbiAgICAgICAgcmV0dXJuIGNvb3Jkc0NoYXIodGhpcywgY29vcmRzLmxlZnQsIGNvb3Jkcy50b3ApXG4gICAgICB9LFxuXG4gICAgICBsaW5lQXRIZWlnaHQ6IGZ1bmN0aW9uKGhlaWdodCwgbW9kZSkge1xuICAgICAgICBoZWlnaHQgPSBmcm9tQ29vcmRTeXN0ZW0odGhpcywge3RvcDogaGVpZ2h0LCBsZWZ0OiAwfSwgbW9kZSB8fCBcInBhZ2VcIikudG9wO1xuICAgICAgICByZXR1cm4gbGluZUF0SGVpZ2h0KHRoaXMuZG9jLCBoZWlnaHQgKyB0aGlzLmRpc3BsYXkudmlld09mZnNldClcbiAgICAgIH0sXG4gICAgICBoZWlnaHRBdExpbmU6IGZ1bmN0aW9uKGxpbmUsIG1vZGUsIGluY2x1ZGVXaWRnZXRzKSB7XG4gICAgICAgIHZhciBlbmQgPSBmYWxzZSwgbGluZU9iajtcbiAgICAgICAgaWYgKHR5cGVvZiBsaW5lID09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICB2YXIgbGFzdCA9IHRoaXMuZG9jLmZpcnN0ICsgdGhpcy5kb2Muc2l6ZSAtIDE7XG4gICAgICAgICAgaWYgKGxpbmUgPCB0aGlzLmRvYy5maXJzdCkgeyBsaW5lID0gdGhpcy5kb2MuZmlyc3Q7IH1cbiAgICAgICAgICBlbHNlIGlmIChsaW5lID4gbGFzdCkgeyBsaW5lID0gbGFzdDsgZW5kID0gdHJ1ZTsgfVxuICAgICAgICAgIGxpbmVPYmogPSBnZXRMaW5lKHRoaXMuZG9jLCBsaW5lKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsaW5lT2JqID0gbGluZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaW50b0Nvb3JkU3lzdGVtKHRoaXMsIGxpbmVPYmosIHt0b3A6IDAsIGxlZnQ6IDB9LCBtb2RlIHx8IFwicGFnZVwiLCBpbmNsdWRlV2lkZ2V0cyB8fCBlbmQpLnRvcCArXG4gICAgICAgICAgKGVuZCA/IHRoaXMuZG9jLmhlaWdodCAtIGhlaWdodEF0TGluZShsaW5lT2JqKSA6IDApXG4gICAgICB9LFxuXG4gICAgICBkZWZhdWx0VGV4dEhlaWdodDogZnVuY3Rpb24oKSB7IHJldHVybiB0ZXh0SGVpZ2h0KHRoaXMuZGlzcGxheSkgfSxcbiAgICAgIGRlZmF1bHRDaGFyV2lkdGg6IGZ1bmN0aW9uKCkgeyByZXR1cm4gY2hhcldpZHRoKHRoaXMuZGlzcGxheSkgfSxcblxuICAgICAgZ2V0Vmlld3BvcnQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4ge2Zyb206IHRoaXMuZGlzcGxheS52aWV3RnJvbSwgdG86IHRoaXMuZGlzcGxheS52aWV3VG99fSxcblxuICAgICAgYWRkV2lkZ2V0OiBmdW5jdGlvbihwb3MsIG5vZGUsIHNjcm9sbCwgdmVydCwgaG9yaXopIHtcbiAgICAgICAgdmFyIGRpc3BsYXkgPSB0aGlzLmRpc3BsYXk7XG4gICAgICAgIHBvcyA9IGN1cnNvckNvb3Jkcyh0aGlzLCBjbGlwUG9zKHRoaXMuZG9jLCBwb3MpKTtcbiAgICAgICAgdmFyIHRvcCA9IHBvcy5ib3R0b20sIGxlZnQgPSBwb3MubGVmdDtcbiAgICAgICAgbm9kZS5zdHlsZS5wb3NpdGlvbiA9IFwiYWJzb2x1dGVcIjtcbiAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoXCJjbS1pZ25vcmUtZXZlbnRzXCIsIFwidHJ1ZVwiKTtcbiAgICAgICAgdGhpcy5kaXNwbGF5LmlucHV0LnNldFVuZWRpdGFibGUobm9kZSk7XG4gICAgICAgIGRpc3BsYXkuc2l6ZXIuYXBwZW5kQ2hpbGQobm9kZSk7XG4gICAgICAgIGlmICh2ZXJ0ID09IFwib3ZlclwiKSB7XG4gICAgICAgICAgdG9wID0gcG9zLnRvcDtcbiAgICAgICAgfSBlbHNlIGlmICh2ZXJ0ID09IFwiYWJvdmVcIiB8fCB2ZXJ0ID09IFwibmVhclwiKSB7XG4gICAgICAgICAgdmFyIHZzcGFjZSA9IE1hdGgubWF4KGRpc3BsYXkud3JhcHBlci5jbGllbnRIZWlnaHQsIHRoaXMuZG9jLmhlaWdodCksXG4gICAgICAgICAgaHNwYWNlID0gTWF0aC5tYXgoZGlzcGxheS5zaXplci5jbGllbnRXaWR0aCwgZGlzcGxheS5saW5lU3BhY2UuY2xpZW50V2lkdGgpO1xuICAgICAgICAgIC8vIERlZmF1bHQgdG8gcG9zaXRpb25pbmcgYWJvdmUgKGlmIHNwZWNpZmllZCBhbmQgcG9zc2libGUpOyBvdGhlcndpc2UgZGVmYXVsdCB0byBwb3NpdGlvbmluZyBiZWxvd1xuICAgICAgICAgIGlmICgodmVydCA9PSAnYWJvdmUnIHx8IHBvcy5ib3R0b20gKyBub2RlLm9mZnNldEhlaWdodCA+IHZzcGFjZSkgJiYgcG9zLnRvcCA+IG5vZGUub2Zmc2V0SGVpZ2h0KVxuICAgICAgICAgICAgeyB0b3AgPSBwb3MudG9wIC0gbm9kZS5vZmZzZXRIZWlnaHQ7IH1cbiAgICAgICAgICBlbHNlIGlmIChwb3MuYm90dG9tICsgbm9kZS5vZmZzZXRIZWlnaHQgPD0gdnNwYWNlKVxuICAgICAgICAgICAgeyB0b3AgPSBwb3MuYm90dG9tOyB9XG4gICAgICAgICAgaWYgKGxlZnQgKyBub2RlLm9mZnNldFdpZHRoID4gaHNwYWNlKVxuICAgICAgICAgICAgeyBsZWZ0ID0gaHNwYWNlIC0gbm9kZS5vZmZzZXRXaWR0aDsgfVxuICAgICAgICB9XG4gICAgICAgIG5vZGUuc3R5bGUudG9wID0gdG9wICsgXCJweFwiO1xuICAgICAgICBub2RlLnN0eWxlLmxlZnQgPSBub2RlLnN0eWxlLnJpZ2h0ID0gXCJcIjtcbiAgICAgICAgaWYgKGhvcml6ID09IFwicmlnaHRcIikge1xuICAgICAgICAgIGxlZnQgPSBkaXNwbGF5LnNpemVyLmNsaWVudFdpZHRoIC0gbm9kZS5vZmZzZXRXaWR0aDtcbiAgICAgICAgICBub2RlLnN0eWxlLnJpZ2h0ID0gXCIwcHhcIjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoaG9yaXogPT0gXCJsZWZ0XCIpIHsgbGVmdCA9IDA7IH1cbiAgICAgICAgICBlbHNlIGlmIChob3JpeiA9PSBcIm1pZGRsZVwiKSB7IGxlZnQgPSAoZGlzcGxheS5zaXplci5jbGllbnRXaWR0aCAtIG5vZGUub2Zmc2V0V2lkdGgpIC8gMjsgfVxuICAgICAgICAgIG5vZGUuc3R5bGUubGVmdCA9IGxlZnQgKyBcInB4XCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNjcm9sbClcbiAgICAgICAgICB7IHNjcm9sbEludG9WaWV3KHRoaXMsIHtsZWZ0OiBsZWZ0LCB0b3A6IHRvcCwgcmlnaHQ6IGxlZnQgKyBub2RlLm9mZnNldFdpZHRoLCBib3R0b206IHRvcCArIG5vZGUub2Zmc2V0SGVpZ2h0fSk7IH1cbiAgICAgIH0sXG5cbiAgICAgIHRyaWdnZXJPbktleURvd246IG1ldGhvZE9wKG9uS2V5RG93biksXG4gICAgICB0cmlnZ2VyT25LZXlQcmVzczogbWV0aG9kT3Aob25LZXlQcmVzcyksXG4gICAgICB0cmlnZ2VyT25LZXlVcDogb25LZXlVcCxcbiAgICAgIHRyaWdnZXJPbk1vdXNlRG93bjogbWV0aG9kT3Aob25Nb3VzZURvd24pLFxuXG4gICAgICBleGVjQ29tbWFuZDogZnVuY3Rpb24oY21kKSB7XG4gICAgICAgIGlmIChjb21tYW5kcy5oYXNPd25Qcm9wZXJ0eShjbWQpKVxuICAgICAgICAgIHsgcmV0dXJuIGNvbW1hbmRzW2NtZF0uY2FsbChudWxsLCB0aGlzKSB9XG4gICAgICB9LFxuXG4gICAgICB0cmlnZ2VyRWxlY3RyaWM6IG1ldGhvZE9wKGZ1bmN0aW9uKHRleHQpIHsgdHJpZ2dlckVsZWN0cmljKHRoaXMsIHRleHQpOyB9KSxcblxuICAgICAgZmluZFBvc0g6IGZ1bmN0aW9uKGZyb20sIGFtb3VudCwgdW5pdCwgdmlzdWFsbHkpIHtcbiAgICAgICAgdmFyIGRpciA9IDE7XG4gICAgICAgIGlmIChhbW91bnQgPCAwKSB7IGRpciA9IC0xOyBhbW91bnQgPSAtYW1vdW50OyB9XG4gICAgICAgIHZhciBjdXIgPSBjbGlwUG9zKHRoaXMuZG9jLCBmcm9tKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhbW91bnQ7ICsraSkge1xuICAgICAgICAgIGN1ciA9IGZpbmRQb3NIKHRoaXMuZG9jLCBjdXIsIGRpciwgdW5pdCwgdmlzdWFsbHkpO1xuICAgICAgICAgIGlmIChjdXIuaGl0U2lkZSkgeyBicmVhayB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGN1clxuICAgICAgfSxcblxuICAgICAgbW92ZUg6IG1ldGhvZE9wKGZ1bmN0aW9uKGRpciwgdW5pdCkge1xuICAgICAgICB2YXIgdGhpcyQxID0gdGhpcztcblxuICAgICAgICB0aGlzLmV4dGVuZFNlbGVjdGlvbnNCeShmdW5jdGlvbiAocmFuZ2UpIHtcbiAgICAgICAgICBpZiAodGhpcyQxLmRpc3BsYXkuc2hpZnQgfHwgdGhpcyQxLmRvYy5leHRlbmQgfHwgcmFuZ2UuZW1wdHkoKSlcbiAgICAgICAgICAgIHsgcmV0dXJuIGZpbmRQb3NIKHRoaXMkMS5kb2MsIHJhbmdlLmhlYWQsIGRpciwgdW5pdCwgdGhpcyQxLm9wdGlvbnMucnRsTW92ZVZpc3VhbGx5KSB9XG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgeyByZXR1cm4gZGlyIDwgMCA/IHJhbmdlLmZyb20oKSA6IHJhbmdlLnRvKCkgfVxuICAgICAgICB9LCBzZWxfbW92ZSk7XG4gICAgICB9KSxcblxuICAgICAgZGVsZXRlSDogbWV0aG9kT3AoZnVuY3Rpb24oZGlyLCB1bml0KSB7XG4gICAgICAgIHZhciBzZWwgPSB0aGlzLmRvYy5zZWwsIGRvYyA9IHRoaXMuZG9jO1xuICAgICAgICBpZiAoc2VsLnNvbWV0aGluZ1NlbGVjdGVkKCkpXG4gICAgICAgICAgeyBkb2MucmVwbGFjZVNlbGVjdGlvbihcIlwiLCBudWxsLCBcIitkZWxldGVcIik7IH1cbiAgICAgICAgZWxzZVxuICAgICAgICAgIHsgZGVsZXRlTmVhclNlbGVjdGlvbih0aGlzLCBmdW5jdGlvbiAocmFuZ2UpIHtcbiAgICAgICAgICAgIHZhciBvdGhlciA9IGZpbmRQb3NIKGRvYywgcmFuZ2UuaGVhZCwgZGlyLCB1bml0LCBmYWxzZSk7XG4gICAgICAgICAgICByZXR1cm4gZGlyIDwgMCA/IHtmcm9tOiBvdGhlciwgdG86IHJhbmdlLmhlYWR9IDoge2Zyb206IHJhbmdlLmhlYWQsIHRvOiBvdGhlcn1cbiAgICAgICAgICB9KTsgfVxuICAgICAgfSksXG5cbiAgICAgIGZpbmRQb3NWOiBmdW5jdGlvbihmcm9tLCBhbW91bnQsIHVuaXQsIGdvYWxDb2x1bW4pIHtcbiAgICAgICAgdmFyIGRpciA9IDEsIHggPSBnb2FsQ29sdW1uO1xuICAgICAgICBpZiAoYW1vdW50IDwgMCkgeyBkaXIgPSAtMTsgYW1vdW50ID0gLWFtb3VudDsgfVxuICAgICAgICB2YXIgY3VyID0gY2xpcFBvcyh0aGlzLmRvYywgZnJvbSk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYW1vdW50OyArK2kpIHtcbiAgICAgICAgICB2YXIgY29vcmRzID0gY3Vyc29yQ29vcmRzKHRoaXMsIGN1ciwgXCJkaXZcIik7XG4gICAgICAgICAgaWYgKHggPT0gbnVsbCkgeyB4ID0gY29vcmRzLmxlZnQ7IH1cbiAgICAgICAgICBlbHNlIHsgY29vcmRzLmxlZnQgPSB4OyB9XG4gICAgICAgICAgY3VyID0gZmluZFBvc1YodGhpcywgY29vcmRzLCBkaXIsIHVuaXQpO1xuICAgICAgICAgIGlmIChjdXIuaGl0U2lkZSkgeyBicmVhayB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGN1clxuICAgICAgfSxcblxuICAgICAgbW92ZVY6IG1ldGhvZE9wKGZ1bmN0aW9uKGRpciwgdW5pdCkge1xuICAgICAgICB2YXIgdGhpcyQxID0gdGhpcztcblxuICAgICAgICB2YXIgZG9jID0gdGhpcy5kb2MsIGdvYWxzID0gW107XG4gICAgICAgIHZhciBjb2xsYXBzZSA9ICF0aGlzLmRpc3BsYXkuc2hpZnQgJiYgIWRvYy5leHRlbmQgJiYgZG9jLnNlbC5zb21ldGhpbmdTZWxlY3RlZCgpO1xuICAgICAgICBkb2MuZXh0ZW5kU2VsZWN0aW9uc0J5KGZ1bmN0aW9uIChyYW5nZSkge1xuICAgICAgICAgIGlmIChjb2xsYXBzZSlcbiAgICAgICAgICAgIHsgcmV0dXJuIGRpciA8IDAgPyByYW5nZS5mcm9tKCkgOiByYW5nZS50bygpIH1cbiAgICAgICAgICB2YXIgaGVhZFBvcyA9IGN1cnNvckNvb3Jkcyh0aGlzJDEsIHJhbmdlLmhlYWQsIFwiZGl2XCIpO1xuICAgICAgICAgIGlmIChyYW5nZS5nb2FsQ29sdW1uICE9IG51bGwpIHsgaGVhZFBvcy5sZWZ0ID0gcmFuZ2UuZ29hbENvbHVtbjsgfVxuICAgICAgICAgIGdvYWxzLnB1c2goaGVhZFBvcy5sZWZ0KTtcbiAgICAgICAgICB2YXIgcG9zID0gZmluZFBvc1YodGhpcyQxLCBoZWFkUG9zLCBkaXIsIHVuaXQpO1xuICAgICAgICAgIGlmICh1bml0ID09IFwicGFnZVwiICYmIHJhbmdlID09IGRvYy5zZWwucHJpbWFyeSgpKVxuICAgICAgICAgICAgeyBhZGRUb1Njcm9sbFRvcCh0aGlzJDEsIGNoYXJDb29yZHModGhpcyQxLCBwb3MsIFwiZGl2XCIpLnRvcCAtIGhlYWRQb3MudG9wKTsgfVxuICAgICAgICAgIHJldHVybiBwb3NcbiAgICAgICAgfSwgc2VsX21vdmUpO1xuICAgICAgICBpZiAoZ29hbHMubGVuZ3RoKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgZG9jLnNlbC5yYW5nZXMubGVuZ3RoOyBpKyspXG4gICAgICAgICAgeyBkb2Muc2VsLnJhbmdlc1tpXS5nb2FsQ29sdW1uID0gZ29hbHNbaV07IH0gfVxuICAgICAgfSksXG5cbiAgICAgIC8vIEZpbmQgdGhlIHdvcmQgYXQgdGhlIGdpdmVuIHBvc2l0aW9uIChhcyByZXR1cm5lZCBieSBjb29yZHNDaGFyKS5cbiAgICAgIGZpbmRXb3JkQXQ6IGZ1bmN0aW9uKHBvcykge1xuICAgICAgICB2YXIgZG9jID0gdGhpcy5kb2MsIGxpbmUgPSBnZXRMaW5lKGRvYywgcG9zLmxpbmUpLnRleHQ7XG4gICAgICAgIHZhciBzdGFydCA9IHBvcy5jaCwgZW5kID0gcG9zLmNoO1xuICAgICAgICBpZiAobGluZSkge1xuICAgICAgICAgIHZhciBoZWxwZXIgPSB0aGlzLmdldEhlbHBlcihwb3MsIFwid29yZENoYXJzXCIpO1xuICAgICAgICAgIGlmICgocG9zLnN0aWNreSA9PSBcImJlZm9yZVwiIHx8IGVuZCA9PSBsaW5lLmxlbmd0aCkgJiYgc3RhcnQpIHsgLS1zdGFydDsgfSBlbHNlIHsgKytlbmQ7IH1cbiAgICAgICAgICB2YXIgc3RhcnRDaGFyID0gbGluZS5jaGFyQXQoc3RhcnQpO1xuICAgICAgICAgIHZhciBjaGVjayA9IGlzV29yZENoYXIoc3RhcnRDaGFyLCBoZWxwZXIpXG4gICAgICAgICAgICA/IGZ1bmN0aW9uIChjaCkgeyByZXR1cm4gaXNXb3JkQ2hhcihjaCwgaGVscGVyKTsgfVxuICAgICAgICAgICAgOiAvXFxzLy50ZXN0KHN0YXJ0Q2hhcikgPyBmdW5jdGlvbiAoY2gpIHsgcmV0dXJuIC9cXHMvLnRlc3QoY2gpOyB9XG4gICAgICAgICAgICA6IGZ1bmN0aW9uIChjaCkgeyByZXR1cm4gKCEvXFxzLy50ZXN0KGNoKSAmJiAhaXNXb3JkQ2hhcihjaCkpOyB9O1xuICAgICAgICAgIHdoaWxlIChzdGFydCA+IDAgJiYgY2hlY2sobGluZS5jaGFyQXQoc3RhcnQgLSAxKSkpIHsgLS1zdGFydDsgfVxuICAgICAgICAgIHdoaWxlIChlbmQgPCBsaW5lLmxlbmd0aCAmJiBjaGVjayhsaW5lLmNoYXJBdChlbmQpKSkgeyArK2VuZDsgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgUmFuZ2UoUG9zKHBvcy5saW5lLCBzdGFydCksIFBvcyhwb3MubGluZSwgZW5kKSlcbiAgICAgIH0sXG5cbiAgICAgIHRvZ2dsZU92ZXJ3cml0ZTogZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgaWYgKHZhbHVlICE9IG51bGwgJiYgdmFsdWUgPT0gdGhpcy5zdGF0ZS5vdmVyd3JpdGUpIHsgcmV0dXJuIH1cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUub3ZlcndyaXRlID0gIXRoaXMuc3RhdGUub3ZlcndyaXRlKVxuICAgICAgICAgIHsgYWRkQ2xhc3ModGhpcy5kaXNwbGF5LmN1cnNvckRpdiwgXCJDb2RlTWlycm9yLW92ZXJ3cml0ZVwiKTsgfVxuICAgICAgICBlbHNlXG4gICAgICAgICAgeyBybUNsYXNzKHRoaXMuZGlzcGxheS5jdXJzb3JEaXYsIFwiQ29kZU1pcnJvci1vdmVyd3JpdGVcIik7IH1cblxuICAgICAgICBzaWduYWwodGhpcywgXCJvdmVyd3JpdGVUb2dnbGVcIiwgdGhpcywgdGhpcy5zdGF0ZS5vdmVyd3JpdGUpO1xuICAgICAgfSxcbiAgICAgIGhhc0ZvY3VzOiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMuZGlzcGxheS5pbnB1dC5nZXRGaWVsZCgpID09IGFjdGl2ZUVsdCgpIH0sXG4gICAgICBpc1JlYWRPbmx5OiBmdW5jdGlvbigpIHsgcmV0dXJuICEhKHRoaXMub3B0aW9ucy5yZWFkT25seSB8fCB0aGlzLmRvYy5jYW50RWRpdCkgfSxcblxuICAgICAgc2Nyb2xsVG86IG1ldGhvZE9wKGZ1bmN0aW9uICh4LCB5KSB7IHNjcm9sbFRvQ29vcmRzKHRoaXMsIHgsIHkpOyB9KSxcbiAgICAgIGdldFNjcm9sbEluZm86IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgc2Nyb2xsZXIgPSB0aGlzLmRpc3BsYXkuc2Nyb2xsZXI7XG4gICAgICAgIHJldHVybiB7bGVmdDogc2Nyb2xsZXIuc2Nyb2xsTGVmdCwgdG9wOiBzY3JvbGxlci5zY3JvbGxUb3AsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBzY3JvbGxlci5zY3JvbGxIZWlnaHQgLSBzY3JvbGxHYXAodGhpcykgLSB0aGlzLmRpc3BsYXkuYmFySGVpZ2h0LFxuICAgICAgICAgICAgICAgIHdpZHRoOiBzY3JvbGxlci5zY3JvbGxXaWR0aCAtIHNjcm9sbEdhcCh0aGlzKSAtIHRoaXMuZGlzcGxheS5iYXJXaWR0aCxcbiAgICAgICAgICAgICAgICBjbGllbnRIZWlnaHQ6IGRpc3BsYXlIZWlnaHQodGhpcyksIGNsaWVudFdpZHRoOiBkaXNwbGF5V2lkdGgodGhpcyl9XG4gICAgICB9LFxuXG4gICAgICBzY3JvbGxJbnRvVmlldzogbWV0aG9kT3AoZnVuY3Rpb24ocmFuZ2UsIG1hcmdpbikge1xuICAgICAgICBpZiAocmFuZ2UgPT0gbnVsbCkge1xuICAgICAgICAgIHJhbmdlID0ge2Zyb206IHRoaXMuZG9jLnNlbC5wcmltYXJ5KCkuaGVhZCwgdG86IG51bGx9O1xuICAgICAgICAgIGlmIChtYXJnaW4gPT0gbnVsbCkgeyBtYXJnaW4gPSB0aGlzLm9wdGlvbnMuY3Vyc29yU2Nyb2xsTWFyZ2luOyB9XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHJhbmdlID09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICByYW5nZSA9IHtmcm9tOiBQb3MocmFuZ2UsIDApLCB0bzogbnVsbH07XG4gICAgICAgIH0gZWxzZSBpZiAocmFuZ2UuZnJvbSA9PSBudWxsKSB7XG4gICAgICAgICAgcmFuZ2UgPSB7ZnJvbTogcmFuZ2UsIHRvOiBudWxsfTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXJhbmdlLnRvKSB7IHJhbmdlLnRvID0gcmFuZ2UuZnJvbTsgfVxuICAgICAgICByYW5nZS5tYXJnaW4gPSBtYXJnaW4gfHwgMDtcblxuICAgICAgICBpZiAocmFuZ2UuZnJvbS5saW5lICE9IG51bGwpIHtcbiAgICAgICAgICBzY3JvbGxUb1JhbmdlKHRoaXMsIHJhbmdlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzY3JvbGxUb0Nvb3Jkc1JhbmdlKHRoaXMsIHJhbmdlLmZyb20sIHJhbmdlLnRvLCByYW5nZS5tYXJnaW4pO1xuICAgICAgICB9XG4gICAgICB9KSxcblxuICAgICAgc2V0U2l6ZTogbWV0aG9kT3AoZnVuY3Rpb24od2lkdGgsIGhlaWdodCkge1xuICAgICAgICB2YXIgdGhpcyQxID0gdGhpcztcblxuICAgICAgICB2YXIgaW50ZXJwcmV0ID0gZnVuY3Rpb24gKHZhbCkgeyByZXR1cm4gdHlwZW9mIHZhbCA9PSBcIm51bWJlclwiIHx8IC9eXFxkKyQvLnRlc3QoU3RyaW5nKHZhbCkpID8gdmFsICsgXCJweFwiIDogdmFsOyB9O1xuICAgICAgICBpZiAod2lkdGggIT0gbnVsbCkgeyB0aGlzLmRpc3BsYXkud3JhcHBlci5zdHlsZS53aWR0aCA9IGludGVycHJldCh3aWR0aCk7IH1cbiAgICAgICAgaWYgKGhlaWdodCAhPSBudWxsKSB7IHRoaXMuZGlzcGxheS53cmFwcGVyLnN0eWxlLmhlaWdodCA9IGludGVycHJldChoZWlnaHQpOyB9XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMubGluZVdyYXBwaW5nKSB7IGNsZWFyTGluZU1lYXN1cmVtZW50Q2FjaGUodGhpcyk7IH1cbiAgICAgICAgdmFyIGxpbmVObyA9IHRoaXMuZGlzcGxheS52aWV3RnJvbTtcbiAgICAgICAgdGhpcy5kb2MuaXRlcihsaW5lTm8sIHRoaXMuZGlzcGxheS52aWV3VG8sIGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgICAgaWYgKGxpbmUud2lkZ2V0cykgeyBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmUud2lkZ2V0cy5sZW5ndGg7IGkrKylcbiAgICAgICAgICAgIHsgaWYgKGxpbmUud2lkZ2V0c1tpXS5ub0hTY3JvbGwpIHsgcmVnTGluZUNoYW5nZSh0aGlzJDEsIGxpbmVObywgXCJ3aWRnZXRcIik7IGJyZWFrIH0gfSB9XG4gICAgICAgICAgKytsaW5lTm87XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmN1ck9wLmZvcmNlVXBkYXRlID0gdHJ1ZTtcbiAgICAgICAgc2lnbmFsKHRoaXMsIFwicmVmcmVzaFwiLCB0aGlzKTtcbiAgICAgIH0pLFxuXG4gICAgICBvcGVyYXRpb246IGZ1bmN0aW9uKGYpe3JldHVybiBydW5Jbk9wKHRoaXMsIGYpfSxcbiAgICAgIHN0YXJ0T3BlcmF0aW9uOiBmdW5jdGlvbigpe3JldHVybiBzdGFydE9wZXJhdGlvbih0aGlzKX0sXG4gICAgICBlbmRPcGVyYXRpb246IGZ1bmN0aW9uKCl7cmV0dXJuIGVuZE9wZXJhdGlvbih0aGlzKX0sXG5cbiAgICAgIHJlZnJlc2g6IG1ldGhvZE9wKGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgb2xkSGVpZ2h0ID0gdGhpcy5kaXNwbGF5LmNhY2hlZFRleHRIZWlnaHQ7XG4gICAgICAgIHJlZ0NoYW5nZSh0aGlzKTtcbiAgICAgICAgdGhpcy5jdXJPcC5mb3JjZVVwZGF0ZSA9IHRydWU7XG4gICAgICAgIGNsZWFyQ2FjaGVzKHRoaXMpO1xuICAgICAgICBzY3JvbGxUb0Nvb3Jkcyh0aGlzLCB0aGlzLmRvYy5zY3JvbGxMZWZ0LCB0aGlzLmRvYy5zY3JvbGxUb3ApO1xuICAgICAgICB1cGRhdGVHdXR0ZXJTcGFjZSh0aGlzLmRpc3BsYXkpO1xuICAgICAgICBpZiAob2xkSGVpZ2h0ID09IG51bGwgfHwgTWF0aC5hYnMob2xkSGVpZ2h0IC0gdGV4dEhlaWdodCh0aGlzLmRpc3BsYXkpKSA+IC41IHx8IHRoaXMub3B0aW9ucy5saW5lV3JhcHBpbmcpXG4gICAgICAgICAgeyBlc3RpbWF0ZUxpbmVIZWlnaHRzKHRoaXMpOyB9XG4gICAgICAgIHNpZ25hbCh0aGlzLCBcInJlZnJlc2hcIiwgdGhpcyk7XG4gICAgICB9KSxcblxuICAgICAgc3dhcERvYzogbWV0aG9kT3AoZnVuY3Rpb24oZG9jKSB7XG4gICAgICAgIHZhciBvbGQgPSB0aGlzLmRvYztcbiAgICAgICAgb2xkLmNtID0gbnVsbDtcbiAgICAgICAgLy8gQ2FuY2VsIHRoZSBjdXJyZW50IHRleHQgc2VsZWN0aW9uIGlmIGFueSAoIzU4MjEpXG4gICAgICAgIGlmICh0aGlzLnN0YXRlLnNlbGVjdGluZ1RleHQpIHsgdGhpcy5zdGF0ZS5zZWxlY3RpbmdUZXh0KCk7IH1cbiAgICAgICAgYXR0YWNoRG9jKHRoaXMsIGRvYyk7XG4gICAgICAgIGNsZWFyQ2FjaGVzKHRoaXMpO1xuICAgICAgICB0aGlzLmRpc3BsYXkuaW5wdXQucmVzZXQoKTtcbiAgICAgICAgc2Nyb2xsVG9Db29yZHModGhpcywgZG9jLnNjcm9sbExlZnQsIGRvYy5zY3JvbGxUb3ApO1xuICAgICAgICB0aGlzLmN1ck9wLmZvcmNlU2Nyb2xsID0gdHJ1ZTtcbiAgICAgICAgc2lnbmFsTGF0ZXIodGhpcywgXCJzd2FwRG9jXCIsIHRoaXMsIG9sZCk7XG4gICAgICAgIHJldHVybiBvbGRcbiAgICAgIH0pLFxuXG4gICAgICBwaHJhc2U6IGZ1bmN0aW9uKHBocmFzZVRleHQpIHtcbiAgICAgICAgdmFyIHBocmFzZXMgPSB0aGlzLm9wdGlvbnMucGhyYXNlcztcbiAgICAgICAgcmV0dXJuIHBocmFzZXMgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHBocmFzZXMsIHBocmFzZVRleHQpID8gcGhyYXNlc1twaHJhc2VUZXh0XSA6IHBocmFzZVRleHRcbiAgICAgIH0sXG5cbiAgICAgIGdldElucHV0RmllbGQ6IGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZGlzcGxheS5pbnB1dC5nZXRGaWVsZCgpfSxcbiAgICAgIGdldFdyYXBwZXJFbGVtZW50OiBmdW5jdGlvbigpe3JldHVybiB0aGlzLmRpc3BsYXkud3JhcHBlcn0sXG4gICAgICBnZXRTY3JvbGxlckVsZW1lbnQ6IGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZGlzcGxheS5zY3JvbGxlcn0sXG4gICAgICBnZXRHdXR0ZXJFbGVtZW50OiBmdW5jdGlvbigpe3JldHVybiB0aGlzLmRpc3BsYXkuZ3V0dGVyc31cbiAgICB9O1xuICAgIGV2ZW50TWl4aW4oQ29kZU1pcnJvcik7XG5cbiAgICBDb2RlTWlycm9yLnJlZ2lzdGVySGVscGVyID0gZnVuY3Rpb24odHlwZSwgbmFtZSwgdmFsdWUpIHtcbiAgICAgIGlmICghaGVscGVycy5oYXNPd25Qcm9wZXJ0eSh0eXBlKSkgeyBoZWxwZXJzW3R5cGVdID0gQ29kZU1pcnJvclt0eXBlXSA9IHtfZ2xvYmFsOiBbXX07IH1cbiAgICAgIGhlbHBlcnNbdHlwZV1bbmFtZV0gPSB2YWx1ZTtcbiAgICB9O1xuICAgIENvZGVNaXJyb3IucmVnaXN0ZXJHbG9iYWxIZWxwZXIgPSBmdW5jdGlvbih0eXBlLCBuYW1lLCBwcmVkaWNhdGUsIHZhbHVlKSB7XG4gICAgICBDb2RlTWlycm9yLnJlZ2lzdGVySGVscGVyKHR5cGUsIG5hbWUsIHZhbHVlKTtcbiAgICAgIGhlbHBlcnNbdHlwZV0uX2dsb2JhbC5wdXNoKHtwcmVkOiBwcmVkaWNhdGUsIHZhbDogdmFsdWV9KTtcbiAgICB9O1xuICB9XG5cbiAgLy8gVXNlZCBmb3IgaG9yaXpvbnRhbCByZWxhdGl2ZSBtb3Rpb24uIERpciBpcyAtMSBvciAxIChsZWZ0IG9yXG4gIC8vIHJpZ2h0KSwgdW5pdCBjYW4gYmUgXCJjb2RlcG9pbnRcIiwgXCJjaGFyXCIsIFwiY29sdW1uXCIgKGxpa2UgY2hhciwgYnV0XG4gIC8vIGRvZXNuJ3QgY3Jvc3MgbGluZSBib3VuZGFyaWVzKSwgXCJ3b3JkXCIgKGFjcm9zcyBuZXh0IHdvcmQpLCBvclxuICAvLyBcImdyb3VwXCIgKHRvIHRoZSBzdGFydCBvZiBuZXh0IGdyb3VwIG9mIHdvcmQgb3JcbiAgLy8gbm9uLXdvcmQtbm9uLXdoaXRlc3BhY2UgY2hhcnMpLiBUaGUgdmlzdWFsbHkgcGFyYW0gY29udHJvbHNcbiAgLy8gd2hldGhlciwgaW4gcmlnaHQtdG8tbGVmdCB0ZXh0LCBkaXJlY3Rpb24gMSBtZWFucyB0byBtb3ZlIHRvd2FyZHNcbiAgLy8gdGhlIG5leHQgaW5kZXggaW4gdGhlIHN0cmluZywgb3IgdG93YXJkcyB0aGUgY2hhcmFjdGVyIHRvIHRoZSByaWdodFxuICAvLyBvZiB0aGUgY3VycmVudCBwb3NpdGlvbi4gVGhlIHJlc3VsdGluZyBwb3NpdGlvbiB3aWxsIGhhdmUgYVxuICAvLyBoaXRTaWRlPXRydWUgcHJvcGVydHkgaWYgaXQgcmVhY2hlZCB0aGUgZW5kIG9mIHRoZSBkb2N1bWVudC5cbiAgZnVuY3Rpb24gZmluZFBvc0goZG9jLCBwb3MsIGRpciwgdW5pdCwgdmlzdWFsbHkpIHtcbiAgICB2YXIgb2xkUG9zID0gcG9zO1xuICAgIHZhciBvcmlnRGlyID0gZGlyO1xuICAgIHZhciBsaW5lT2JqID0gZ2V0TGluZShkb2MsIHBvcy5saW5lKTtcbiAgICB2YXIgbGluZURpciA9IHZpc3VhbGx5ICYmIGRvYy5kaXJlY3Rpb24gPT0gXCJydGxcIiA/IC1kaXIgOiBkaXI7XG4gICAgZnVuY3Rpb24gZmluZE5leHRMaW5lKCkge1xuICAgICAgdmFyIGwgPSBwb3MubGluZSArIGxpbmVEaXI7XG4gICAgICBpZiAobCA8IGRvYy5maXJzdCB8fCBsID49IGRvYy5maXJzdCArIGRvYy5zaXplKSB7IHJldHVybiBmYWxzZSB9XG4gICAgICBwb3MgPSBuZXcgUG9zKGwsIHBvcy5jaCwgcG9zLnN0aWNreSk7XG4gICAgICByZXR1cm4gbGluZU9iaiA9IGdldExpbmUoZG9jLCBsKVxuICAgIH1cbiAgICBmdW5jdGlvbiBtb3ZlT25jZShib3VuZFRvTGluZSkge1xuICAgICAgdmFyIG5leHQ7XG4gICAgICBpZiAodW5pdCA9PSBcImNvZGVwb2ludFwiKSB7XG4gICAgICAgIHZhciBjaCA9IGxpbmVPYmoudGV4dC5jaGFyQ29kZUF0KHBvcy5jaCArIChkaXIgPiAwID8gMCA6IC0xKSk7XG4gICAgICAgIGlmIChpc05hTihjaCkpIHtcbiAgICAgICAgICBuZXh0ID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YXIgYXN0cmFsID0gZGlyID4gMCA/IGNoID49IDB4RDgwMCAmJiBjaCA8IDB4REMwMCA6IGNoID49IDB4REMwMCAmJiBjaCA8IDB4REZGRjtcbiAgICAgICAgICBuZXh0ID0gbmV3IFBvcyhwb3MubGluZSwgTWF0aC5tYXgoMCwgTWF0aC5taW4obGluZU9iai50ZXh0Lmxlbmd0aCwgcG9zLmNoICsgZGlyICogKGFzdHJhbCA/IDIgOiAxKSkpLCAtZGlyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh2aXN1YWxseSkge1xuICAgICAgICBuZXh0ID0gbW92ZVZpc3VhbGx5KGRvYy5jbSwgbGluZU9iaiwgcG9zLCBkaXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmV4dCA9IG1vdmVMb2dpY2FsbHkobGluZU9iaiwgcG9zLCBkaXIpO1xuICAgICAgfVxuICAgICAgaWYgKG5leHQgPT0gbnVsbCkge1xuICAgICAgICBpZiAoIWJvdW5kVG9MaW5lICYmIGZpbmROZXh0TGluZSgpKVxuICAgICAgICAgIHsgcG9zID0gZW5kT2ZMaW5lKHZpc3VhbGx5LCBkb2MuY20sIGxpbmVPYmosIHBvcy5saW5lLCBsaW5lRGlyKTsgfVxuICAgICAgICBlbHNlXG4gICAgICAgICAgeyByZXR1cm4gZmFsc2UgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcG9zID0gbmV4dDtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuXG4gICAgaWYgKHVuaXQgPT0gXCJjaGFyXCIgfHwgdW5pdCA9PSBcImNvZGVwb2ludFwiKSB7XG4gICAgICBtb3ZlT25jZSgpO1xuICAgIH0gZWxzZSBpZiAodW5pdCA9PSBcImNvbHVtblwiKSB7XG4gICAgICBtb3ZlT25jZSh0cnVlKTtcbiAgICB9IGVsc2UgaWYgKHVuaXQgPT0gXCJ3b3JkXCIgfHwgdW5pdCA9PSBcImdyb3VwXCIpIHtcbiAgICAgIHZhciBzYXdUeXBlID0gbnVsbCwgZ3JvdXAgPSB1bml0ID09IFwiZ3JvdXBcIjtcbiAgICAgIHZhciBoZWxwZXIgPSBkb2MuY20gJiYgZG9jLmNtLmdldEhlbHBlcihwb3MsIFwid29yZENoYXJzXCIpO1xuICAgICAgZm9yICh2YXIgZmlyc3QgPSB0cnVlOzsgZmlyc3QgPSBmYWxzZSkge1xuICAgICAgICBpZiAoZGlyIDwgMCAmJiAhbW92ZU9uY2UoIWZpcnN0KSkgeyBicmVhayB9XG4gICAgICAgIHZhciBjdXIgPSBsaW5lT2JqLnRleHQuY2hhckF0KHBvcy5jaCkgfHwgXCJcXG5cIjtcbiAgICAgICAgdmFyIHR5cGUgPSBpc1dvcmRDaGFyKGN1ciwgaGVscGVyKSA/IFwid1wiXG4gICAgICAgICAgOiBncm91cCAmJiBjdXIgPT0gXCJcXG5cIiA/IFwiblwiXG4gICAgICAgICAgOiAhZ3JvdXAgfHwgL1xccy8udGVzdChjdXIpID8gbnVsbFxuICAgICAgICAgIDogXCJwXCI7XG4gICAgICAgIGlmIChncm91cCAmJiAhZmlyc3QgJiYgIXR5cGUpIHsgdHlwZSA9IFwic1wiOyB9XG4gICAgICAgIGlmIChzYXdUeXBlICYmIHNhd1R5cGUgIT0gdHlwZSkge1xuICAgICAgICAgIGlmIChkaXIgPCAwKSB7ZGlyID0gMTsgbW92ZU9uY2UoKTsgcG9zLnN0aWNreSA9IFwiYWZ0ZXJcIjt9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlKSB7IHNhd1R5cGUgPSB0eXBlOyB9XG4gICAgICAgIGlmIChkaXIgPiAwICYmICFtb3ZlT25jZSghZmlyc3QpKSB7IGJyZWFrIH1cbiAgICAgIH1cbiAgICB9XG4gICAgdmFyIHJlc3VsdCA9IHNraXBBdG9taWMoZG9jLCBwb3MsIG9sZFBvcywgb3JpZ0RpciwgdHJ1ZSk7XG4gICAgaWYgKGVxdWFsQ3Vyc29yUG9zKG9sZFBvcywgcmVzdWx0KSkgeyByZXN1bHQuaGl0U2lkZSA9IHRydWU7IH1cbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cblxuICAvLyBGb3IgcmVsYXRpdmUgdmVydGljYWwgbW92ZW1lbnQuIERpciBtYXkgYmUgLTEgb3IgMS4gVW5pdCBjYW4gYmVcbiAgLy8gXCJwYWdlXCIgb3IgXCJsaW5lXCIuIFRoZSByZXN1bHRpbmcgcG9zaXRpb24gd2lsbCBoYXZlIGEgaGl0U2lkZT10cnVlXG4gIC8vIHByb3BlcnR5IGlmIGl0IHJlYWNoZWQgdGhlIGVuZCBvZiB0aGUgZG9jdW1lbnQuXG4gIGZ1bmN0aW9uIGZpbmRQb3NWKGNtLCBwb3MsIGRpciwgdW5pdCkge1xuICAgIHZhciBkb2MgPSBjbS5kb2MsIHggPSBwb3MubGVmdCwgeTtcbiAgICBpZiAodW5pdCA9PSBcInBhZ2VcIikge1xuICAgICAgdmFyIHBhZ2VTaXplID0gTWF0aC5taW4oY20uZGlzcGxheS53cmFwcGVyLmNsaWVudEhlaWdodCwgd2luZG93LmlubmVySGVpZ2h0IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQpO1xuICAgICAgdmFyIG1vdmVBbW91bnQgPSBNYXRoLm1heChwYWdlU2l6ZSAtIC41ICogdGV4dEhlaWdodChjbS5kaXNwbGF5KSwgMyk7XG4gICAgICB5ID0gKGRpciA+IDAgPyBwb3MuYm90dG9tIDogcG9zLnRvcCkgKyBkaXIgKiBtb3ZlQW1vdW50O1xuXG4gICAgfSBlbHNlIGlmICh1bml0ID09IFwibGluZVwiKSB7XG4gICAgICB5ID0gZGlyID4gMCA/IHBvcy5ib3R0b20gKyAzIDogcG9zLnRvcCAtIDM7XG4gICAgfVxuICAgIHZhciB0YXJnZXQ7XG4gICAgZm9yICg7Oykge1xuICAgICAgdGFyZ2V0ID0gY29vcmRzQ2hhcihjbSwgeCwgeSk7XG4gICAgICBpZiAoIXRhcmdldC5vdXRzaWRlKSB7IGJyZWFrIH1cbiAgICAgIGlmIChkaXIgPCAwID8geSA8PSAwIDogeSA+PSBkb2MuaGVpZ2h0KSB7IHRhcmdldC5oaXRTaWRlID0gdHJ1ZTsgYnJlYWsgfVxuICAgICAgeSArPSBkaXIgKiA1O1xuICAgIH1cbiAgICByZXR1cm4gdGFyZ2V0XG4gIH1cblxuICAvLyBDT05URU5URURJVEFCTEUgSU5QVVQgU1RZTEVcblxuICB2YXIgQ29udGVudEVkaXRhYmxlSW5wdXQgPSBmdW5jdGlvbihjbSkge1xuICAgIHRoaXMuY20gPSBjbTtcbiAgICB0aGlzLmxhc3RBbmNob3JOb2RlID0gdGhpcy5sYXN0QW5jaG9yT2Zmc2V0ID0gdGhpcy5sYXN0Rm9jdXNOb2RlID0gdGhpcy5sYXN0Rm9jdXNPZmZzZXQgPSBudWxsO1xuICAgIHRoaXMucG9sbGluZyA9IG5ldyBEZWxheWVkKCk7XG4gICAgdGhpcy5jb21wb3NpbmcgPSBudWxsO1xuICAgIHRoaXMuZ3JhY2VQZXJpb2QgPSBmYWxzZTtcbiAgICB0aGlzLnJlYWRET01UaW1lb3V0ID0gbnVsbDtcbiAgfTtcblxuICBDb250ZW50RWRpdGFibGVJbnB1dC5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uIChkaXNwbGF5KSB7XG4gICAgICB2YXIgdGhpcyQxID0gdGhpcztcblxuICAgIHZhciBpbnB1dCA9IHRoaXMsIGNtID0gaW5wdXQuY207XG4gICAgdmFyIGRpdiA9IGlucHV0LmRpdiA9IGRpc3BsYXkubGluZURpdjtcbiAgICBkaXYuY29udGVudEVkaXRhYmxlID0gdHJ1ZTtcbiAgICBkaXNhYmxlQnJvd3Nlck1hZ2ljKGRpdiwgY20ub3B0aW9ucy5zcGVsbGNoZWNrLCBjbS5vcHRpb25zLmF1dG9jb3JyZWN0LCBjbS5vcHRpb25zLmF1dG9jYXBpdGFsaXplKTtcblxuICAgIGZ1bmN0aW9uIGJlbG9uZ3NUb0lucHV0KGUpIHtcbiAgICAgIGZvciAodmFyIHQgPSBlLnRhcmdldDsgdDsgdCA9IHQucGFyZW50Tm9kZSkge1xuICAgICAgICBpZiAodCA9PSBkaXYpIHsgcmV0dXJuIHRydWUgfVxuICAgICAgICBpZiAoL1xcYkNvZGVNaXJyb3ItKD86bGluZSk/d2lkZ2V0XFxiLy50ZXN0KHQuY2xhc3NOYW1lKSkgeyBicmVhayB9XG4gICAgICB9XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG5cbiAgICBvbihkaXYsIFwicGFzdGVcIiwgZnVuY3Rpb24gKGUpIHtcbiAgICAgIGlmICghYmVsb25nc1RvSW5wdXQoZSkgfHwgc2lnbmFsRE9NRXZlbnQoY20sIGUpIHx8IGhhbmRsZVBhc3RlKGUsIGNtKSkgeyByZXR1cm4gfVxuICAgICAgLy8gSUUgZG9lc24ndCBmaXJlIGlucHV0IGV2ZW50cywgc28gd2Ugc2NoZWR1bGUgYSByZWFkIGZvciB0aGUgcGFzdGVkIGNvbnRlbnQgaW4gdGhpcyB3YXlcbiAgICAgIGlmIChpZV92ZXJzaW9uIDw9IDExKSB7IHNldFRpbWVvdXQob3BlcmF0aW9uKGNtLCBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzJDEudXBkYXRlRnJvbURPTSgpOyB9KSwgMjApOyB9XG4gICAgfSk7XG5cbiAgICBvbihkaXYsIFwiY29tcG9zaXRpb25zdGFydFwiLCBmdW5jdGlvbiAoZSkge1xuICAgICAgdGhpcyQxLmNvbXBvc2luZyA9IHtkYXRhOiBlLmRhdGEsIGRvbmU6IGZhbHNlfTtcbiAgICB9KTtcbiAgICBvbihkaXYsIFwiY29tcG9zaXRpb251cGRhdGVcIiwgZnVuY3Rpb24gKGUpIHtcbiAgICAgIGlmICghdGhpcyQxLmNvbXBvc2luZykgeyB0aGlzJDEuY29tcG9zaW5nID0ge2RhdGE6IGUuZGF0YSwgZG9uZTogZmFsc2V9OyB9XG4gICAgfSk7XG4gICAgb24oZGl2LCBcImNvbXBvc2l0aW9uZW5kXCIsIGZ1bmN0aW9uIChlKSB7XG4gICAgICBpZiAodGhpcyQxLmNvbXBvc2luZykge1xuICAgICAgICBpZiAoZS5kYXRhICE9IHRoaXMkMS5jb21wb3NpbmcuZGF0YSkgeyB0aGlzJDEucmVhZEZyb21ET01Tb29uKCk7IH1cbiAgICAgICAgdGhpcyQxLmNvbXBvc2luZy5kb25lID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIG9uKGRpdiwgXCJ0b3VjaHN0YXJ0XCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIGlucHV0LmZvcmNlQ29tcG9zaXRpb25FbmQoKTsgfSk7XG5cbiAgICBvbihkaXYsIFwiaW5wdXRcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKCF0aGlzJDEuY29tcG9zaW5nKSB7IHRoaXMkMS5yZWFkRnJvbURPTVNvb24oKTsgfVxuICAgIH0pO1xuXG4gICAgZnVuY3Rpb24gb25Db3B5Q3V0KGUpIHtcbiAgICAgIGlmICghYmVsb25nc1RvSW5wdXQoZSkgfHwgc2lnbmFsRE9NRXZlbnQoY20sIGUpKSB7IHJldHVybiB9XG4gICAgICBpZiAoY20uc29tZXRoaW5nU2VsZWN0ZWQoKSkge1xuICAgICAgICBzZXRMYXN0Q29waWVkKHtsaW5lV2lzZTogZmFsc2UsIHRleHQ6IGNtLmdldFNlbGVjdGlvbnMoKX0pO1xuICAgICAgICBpZiAoZS50eXBlID09IFwiY3V0XCIpIHsgY20ucmVwbGFjZVNlbGVjdGlvbihcIlwiLCBudWxsLCBcImN1dFwiKTsgfVxuICAgICAgfSBlbHNlIGlmICghY20ub3B0aW9ucy5saW5lV2lzZUNvcHlDdXQpIHtcbiAgICAgICAgcmV0dXJuXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgcmFuZ2VzID0gY29weWFibGVSYW5nZXMoY20pO1xuICAgICAgICBzZXRMYXN0Q29waWVkKHtsaW5lV2lzZTogdHJ1ZSwgdGV4dDogcmFuZ2VzLnRleHR9KTtcbiAgICAgICAgaWYgKGUudHlwZSA9PSBcImN1dFwiKSB7XG4gICAgICAgICAgY20ub3BlcmF0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGNtLnNldFNlbGVjdGlvbnMocmFuZ2VzLnJhbmdlcywgMCwgc2VsX2RvbnRTY3JvbGwpO1xuICAgICAgICAgICAgY20ucmVwbGFjZVNlbGVjdGlvbihcIlwiLCBudWxsLCBcImN1dFwiKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGUuY2xpcGJvYXJkRGF0YSkge1xuICAgICAgICBlLmNsaXBib2FyZERhdGEuY2xlYXJEYXRhKCk7XG4gICAgICAgIHZhciBjb250ZW50ID0gbGFzdENvcGllZC50ZXh0LmpvaW4oXCJcXG5cIik7XG4gICAgICAgIC8vIGlPUyBleHBvc2VzIHRoZSBjbGlwYm9hcmQgQVBJLCBidXQgc2VlbXMgdG8gZGlzY2FyZCBjb250ZW50IGluc2VydGVkIGludG8gaXRcbiAgICAgICAgZS5jbGlwYm9hcmREYXRhLnNldERhdGEoXCJUZXh0XCIsIGNvbnRlbnQpO1xuICAgICAgICBpZiAoZS5jbGlwYm9hcmREYXRhLmdldERhdGEoXCJUZXh0XCIpID09IGNvbnRlbnQpIHtcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIE9sZC1mYXNoaW9uZWQgYnJpZWZseS1mb2N1cy1hLXRleHRhcmVhIGhhY2tcbiAgICAgIHZhciBrbHVkZ2UgPSBoaWRkZW5UZXh0YXJlYSgpLCB0ZSA9IGtsdWRnZS5maXJzdENoaWxkO1xuICAgICAgY20uZGlzcGxheS5saW5lU3BhY2UuaW5zZXJ0QmVmb3JlKGtsdWRnZSwgY20uZGlzcGxheS5saW5lU3BhY2UuZmlyc3RDaGlsZCk7XG4gICAgICB0ZS52YWx1ZSA9IGxhc3RDb3BpZWQudGV4dC5qb2luKFwiXFxuXCIpO1xuICAgICAgdmFyIGhhZEZvY3VzID0gYWN0aXZlRWx0KCk7XG4gICAgICBzZWxlY3RJbnB1dCh0ZSk7XG4gICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY20uZGlzcGxheS5saW5lU3BhY2UucmVtb3ZlQ2hpbGQoa2x1ZGdlKTtcbiAgICAgICAgaGFkRm9jdXMuZm9jdXMoKTtcbiAgICAgICAgaWYgKGhhZEZvY3VzID09IGRpdikgeyBpbnB1dC5zaG93UHJpbWFyeVNlbGVjdGlvbigpOyB9XG4gICAgICB9LCA1MCk7XG4gICAgfVxuICAgIG9uKGRpdiwgXCJjb3B5XCIsIG9uQ29weUN1dCk7XG4gICAgb24oZGl2LCBcImN1dFwiLCBvbkNvcHlDdXQpO1xuICB9O1xuXG4gIENvbnRlbnRFZGl0YWJsZUlucHV0LnByb3RvdHlwZS5zY3JlZW5SZWFkZXJMYWJlbENoYW5nZWQgPSBmdW5jdGlvbiAobGFiZWwpIHtcbiAgICAvLyBMYWJlbCBmb3Igc2NyZWVucmVhZGVycywgYWNjZXNzaWJpbGl0eVxuICAgIGlmKGxhYmVsKSB7XG4gICAgICB0aGlzLmRpdi5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCBsYWJlbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGl2LnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1sYWJlbCcpO1xuICAgIH1cbiAgfTtcblxuICBDb250ZW50RWRpdGFibGVJbnB1dC5wcm90b3R5cGUucHJlcGFyZVNlbGVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcmVzdWx0ID0gcHJlcGFyZVNlbGVjdGlvbih0aGlzLmNtLCBmYWxzZSk7XG4gICAgcmVzdWx0LmZvY3VzID0gYWN0aXZlRWx0KCkgPT0gdGhpcy5kaXY7XG4gICAgcmV0dXJuIHJlc3VsdFxuICB9O1xuXG4gIENvbnRlbnRFZGl0YWJsZUlucHV0LnByb3RvdHlwZS5zaG93U2VsZWN0aW9uID0gZnVuY3Rpb24gKGluZm8sIHRha2VGb2N1cykge1xuICAgIGlmICghaW5mbyB8fCAhdGhpcy5jbS5kaXNwbGF5LnZpZXcubGVuZ3RoKSB7IHJldHVybiB9XG4gICAgaWYgKGluZm8uZm9jdXMgfHwgdGFrZUZvY3VzKSB7IHRoaXMuc2hvd1ByaW1hcnlTZWxlY3Rpb24oKTsgfVxuICAgIHRoaXMuc2hvd011bHRpcGxlU2VsZWN0aW9ucyhpbmZvKTtcbiAgfTtcblxuICBDb250ZW50RWRpdGFibGVJbnB1dC5wcm90b3R5cGUuZ2V0U2VsZWN0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmNtLmRpc3BsYXkud3JhcHBlci5vd25lckRvY3VtZW50LmdldFNlbGVjdGlvbigpXG4gIH07XG5cbiAgQ29udGVudEVkaXRhYmxlSW5wdXQucHJvdG90eXBlLnNob3dQcmltYXJ5U2VsZWN0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzZWwgPSB0aGlzLmdldFNlbGVjdGlvbigpLCBjbSA9IHRoaXMuY20sIHByaW0gPSBjbS5kb2Muc2VsLnByaW1hcnkoKTtcbiAgICB2YXIgZnJvbSA9IHByaW0uZnJvbSgpLCB0byA9IHByaW0udG8oKTtcblxuICAgIGlmIChjbS5kaXNwbGF5LnZpZXdUbyA9PSBjbS5kaXNwbGF5LnZpZXdGcm9tIHx8IGZyb20ubGluZSA+PSBjbS5kaXNwbGF5LnZpZXdUbyB8fCB0by5saW5lIDwgY20uZGlzcGxheS52aWV3RnJvbSkge1xuICAgICAgc2VsLnJlbW92ZUFsbFJhbmdlcygpO1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgdmFyIGN1ckFuY2hvciA9IGRvbVRvUG9zKGNtLCBzZWwuYW5jaG9yTm9kZSwgc2VsLmFuY2hvck9mZnNldCk7XG4gICAgdmFyIGN1ckZvY3VzID0gZG9tVG9Qb3MoY20sIHNlbC5mb2N1c05vZGUsIHNlbC5mb2N1c09mZnNldCk7XG4gICAgaWYgKGN1ckFuY2hvciAmJiAhY3VyQW5jaG9yLmJhZCAmJiBjdXJGb2N1cyAmJiAhY3VyRm9jdXMuYmFkICYmXG4gICAgICAgIGNtcChtaW5Qb3MoY3VyQW5jaG9yLCBjdXJGb2N1cyksIGZyb20pID09IDAgJiZcbiAgICAgICAgY21wKG1heFBvcyhjdXJBbmNob3IsIGN1ckZvY3VzKSwgdG8pID09IDApXG4gICAgICB7IHJldHVybiB9XG5cbiAgICB2YXIgdmlldyA9IGNtLmRpc3BsYXkudmlldztcbiAgICB2YXIgc3RhcnQgPSAoZnJvbS5saW5lID49IGNtLmRpc3BsYXkudmlld0Zyb20gJiYgcG9zVG9ET00oY20sIGZyb20pKSB8fFxuICAgICAgICB7bm9kZTogdmlld1swXS5tZWFzdXJlLm1hcFsyXSwgb2Zmc2V0OiAwfTtcbiAgICB2YXIgZW5kID0gdG8ubGluZSA8IGNtLmRpc3BsYXkudmlld1RvICYmIHBvc1RvRE9NKGNtLCB0byk7XG4gICAgaWYgKCFlbmQpIHtcbiAgICAgIHZhciBtZWFzdXJlID0gdmlld1t2aWV3Lmxlbmd0aCAtIDFdLm1lYXN1cmU7XG4gICAgICB2YXIgbWFwID0gbWVhc3VyZS5tYXBzID8gbWVhc3VyZS5tYXBzW21lYXN1cmUubWFwcy5sZW5ndGggLSAxXSA6IG1lYXN1cmUubWFwO1xuICAgICAgZW5kID0ge25vZGU6IG1hcFttYXAubGVuZ3RoIC0gMV0sIG9mZnNldDogbWFwW21hcC5sZW5ndGggLSAyXSAtIG1hcFttYXAubGVuZ3RoIC0gM119O1xuICAgIH1cblxuICAgIGlmICghc3RhcnQgfHwgIWVuZCkge1xuICAgICAgc2VsLnJlbW92ZUFsbFJhbmdlcygpO1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgdmFyIG9sZCA9IHNlbC5yYW5nZUNvdW50ICYmIHNlbC5nZXRSYW5nZUF0KDApLCBybmc7XG4gICAgdHJ5IHsgcm5nID0gcmFuZ2Uoc3RhcnQubm9kZSwgc3RhcnQub2Zmc2V0LCBlbmQub2Zmc2V0LCBlbmQubm9kZSk7IH1cbiAgICBjYXRjaChlKSB7fSAvLyBPdXIgbW9kZWwgb2YgdGhlIERPTSBtaWdodCBiZSBvdXRkYXRlZCwgaW4gd2hpY2ggY2FzZSB0aGUgcmFuZ2Ugd2UgdHJ5IHRvIHNldCBjYW4gYmUgaW1wb3NzaWJsZVxuICAgIGlmIChybmcpIHtcbiAgICAgIGlmICghZ2Vja28gJiYgY20uc3RhdGUuZm9jdXNlZCkge1xuICAgICAgICBzZWwuY29sbGFwc2Uoc3RhcnQubm9kZSwgc3RhcnQub2Zmc2V0KTtcbiAgICAgICAgaWYgKCFybmcuY29sbGFwc2VkKSB7XG4gICAgICAgICAgc2VsLnJlbW92ZUFsbFJhbmdlcygpO1xuICAgICAgICAgIHNlbC5hZGRSYW5nZShybmcpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZWwucmVtb3ZlQWxsUmFuZ2VzKCk7XG4gICAgICAgIHNlbC5hZGRSYW5nZShybmcpO1xuICAgICAgfVxuICAgICAgaWYgKG9sZCAmJiBzZWwuYW5jaG9yTm9kZSA9PSBudWxsKSB7IHNlbC5hZGRSYW5nZShvbGQpOyB9XG4gICAgICBlbHNlIGlmIChnZWNrbykgeyB0aGlzLnN0YXJ0R3JhY2VQZXJpb2QoKTsgfVxuICAgIH1cbiAgICB0aGlzLnJlbWVtYmVyU2VsZWN0aW9uKCk7XG4gIH07XG5cbiAgQ29udGVudEVkaXRhYmxlSW5wdXQucHJvdG90eXBlLnN0YXJ0R3JhY2VQZXJpb2QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgdGhpcyQxID0gdGhpcztcblxuICAgIGNsZWFyVGltZW91dCh0aGlzLmdyYWNlUGVyaW9kKTtcbiAgICB0aGlzLmdyYWNlUGVyaW9kID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICB0aGlzJDEuZ3JhY2VQZXJpb2QgPSBmYWxzZTtcbiAgICAgIGlmICh0aGlzJDEuc2VsZWN0aW9uQ2hhbmdlZCgpKVxuICAgICAgICB7IHRoaXMkMS5jbS5vcGVyYXRpb24oZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcyQxLmNtLmN1ck9wLnNlbGVjdGlvbkNoYW5nZWQgPSB0cnVlOyB9KTsgfVxuICAgIH0sIDIwKTtcbiAgfTtcblxuICBDb250ZW50RWRpdGFibGVJbnB1dC5wcm90b3R5cGUuc2hvd011bHRpcGxlU2VsZWN0aW9ucyA9IGZ1bmN0aW9uIChpbmZvKSB7XG4gICAgcmVtb3ZlQ2hpbGRyZW5BbmRBZGQodGhpcy5jbS5kaXNwbGF5LmN1cnNvckRpdiwgaW5mby5jdXJzb3JzKTtcbiAgICByZW1vdmVDaGlsZHJlbkFuZEFkZCh0aGlzLmNtLmRpc3BsYXkuc2VsZWN0aW9uRGl2LCBpbmZvLnNlbGVjdGlvbik7XG4gIH07XG5cbiAgQ29udGVudEVkaXRhYmxlSW5wdXQucHJvdG90eXBlLnJlbWVtYmVyU2VsZWN0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzZWwgPSB0aGlzLmdldFNlbGVjdGlvbigpO1xuICAgIHRoaXMubGFzdEFuY2hvck5vZGUgPSBzZWwuYW5jaG9yTm9kZTsgdGhpcy5sYXN0QW5jaG9yT2Zmc2V0ID0gc2VsLmFuY2hvck9mZnNldDtcbiAgICB0aGlzLmxhc3RGb2N1c05vZGUgPSBzZWwuZm9jdXNOb2RlOyB0aGlzLmxhc3RGb2N1c09mZnNldCA9IHNlbC5mb2N1c09mZnNldDtcbiAgfTtcblxuICBDb250ZW50RWRpdGFibGVJbnB1dC5wcm90b3R5cGUuc2VsZWN0aW9uSW5FZGl0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHNlbCA9IHRoaXMuZ2V0U2VsZWN0aW9uKCk7XG4gICAgaWYgKCFzZWwucmFuZ2VDb3VudCkgeyByZXR1cm4gZmFsc2UgfVxuICAgIHZhciBub2RlID0gc2VsLmdldFJhbmdlQXQoMCkuY29tbW9uQW5jZXN0b3JDb250YWluZXI7XG4gICAgcmV0dXJuIGNvbnRhaW5zKHRoaXMuZGl2LCBub2RlKVxuICB9O1xuXG4gIENvbnRlbnRFZGl0YWJsZUlucHV0LnByb3RvdHlwZS5mb2N1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5jbS5vcHRpb25zLnJlYWRPbmx5ICE9IFwibm9jdXJzb3JcIikge1xuICAgICAgaWYgKCF0aGlzLnNlbGVjdGlvbkluRWRpdG9yKCkgfHwgYWN0aXZlRWx0KCkgIT0gdGhpcy5kaXYpXG4gICAgICAgIHsgdGhpcy5zaG93U2VsZWN0aW9uKHRoaXMucHJlcGFyZVNlbGVjdGlvbigpLCB0cnVlKTsgfVxuICAgICAgdGhpcy5kaXYuZm9jdXMoKTtcbiAgICB9XG4gIH07XG4gIENvbnRlbnRFZGl0YWJsZUlucHV0LnByb3RvdHlwZS5ibHVyID0gZnVuY3Rpb24gKCkgeyB0aGlzLmRpdi5ibHVyKCk7IH07XG4gIENvbnRlbnRFZGl0YWJsZUlucHV0LnByb3RvdHlwZS5nZXRGaWVsZCA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuZGl2IH07XG5cbiAgQ29udGVudEVkaXRhYmxlSW5wdXQucHJvdG90eXBlLnN1cHBvcnRzVG91Y2ggPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0cnVlIH07XG5cbiAgQ29udGVudEVkaXRhYmxlSW5wdXQucHJvdG90eXBlLnJlY2VpdmVkRm9jdXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgdGhpcyQxID0gdGhpcztcblxuICAgIHZhciBpbnB1dCA9IHRoaXM7XG4gICAgaWYgKHRoaXMuc2VsZWN0aW9uSW5FZGl0b3IoKSlcbiAgICAgIHsgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzJDEucG9sbFNlbGVjdGlvbigpOyB9LCAyMCk7IH1cbiAgICBlbHNlXG4gICAgICB7IHJ1bkluT3AodGhpcy5jbSwgZnVuY3Rpb24gKCkgeyByZXR1cm4gaW5wdXQuY20uY3VyT3Auc2VsZWN0aW9uQ2hhbmdlZCA9IHRydWU7IH0pOyB9XG5cbiAgICBmdW5jdGlvbiBwb2xsKCkge1xuICAgICAgaWYgKGlucHV0LmNtLnN0YXRlLmZvY3VzZWQpIHtcbiAgICAgICAgaW5wdXQucG9sbFNlbGVjdGlvbigpO1xuICAgICAgICBpbnB1dC5wb2xsaW5nLnNldChpbnB1dC5jbS5vcHRpb25zLnBvbGxJbnRlcnZhbCwgcG9sbCk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMucG9sbGluZy5zZXQodGhpcy5jbS5vcHRpb25zLnBvbGxJbnRlcnZhbCwgcG9sbCk7XG4gIH07XG5cbiAgQ29udGVudEVkaXRhYmxlSW5wdXQucHJvdG90eXBlLnNlbGVjdGlvbkNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHNlbCA9IHRoaXMuZ2V0U2VsZWN0aW9uKCk7XG4gICAgcmV0dXJuIHNlbC5hbmNob3JOb2RlICE9IHRoaXMubGFzdEFuY2hvck5vZGUgfHwgc2VsLmFuY2hvck9mZnNldCAhPSB0aGlzLmxhc3RBbmNob3JPZmZzZXQgfHxcbiAgICAgIHNlbC5mb2N1c05vZGUgIT0gdGhpcy5sYXN0Rm9jdXNOb2RlIHx8IHNlbC5mb2N1c09mZnNldCAhPSB0aGlzLmxhc3RGb2N1c09mZnNldFxuICB9O1xuXG4gIENvbnRlbnRFZGl0YWJsZUlucHV0LnByb3RvdHlwZS5wb2xsU2VsZWN0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnJlYWRET01UaW1lb3V0ICE9IG51bGwgfHwgdGhpcy5ncmFjZVBlcmlvZCB8fCAhdGhpcy5zZWxlY3Rpb25DaGFuZ2VkKCkpIHsgcmV0dXJuIH1cbiAgICB2YXIgc2VsID0gdGhpcy5nZXRTZWxlY3Rpb24oKSwgY20gPSB0aGlzLmNtO1xuICAgIC8vIE9uIEFuZHJvaWQgQ2hyb21lICh2ZXJzaW9uIDU2LCBhdCBsZWFzdCksIGJhY2tzcGFjaW5nIGludG8gYW5cbiAgICAvLyB1bmVkaXRhYmxlIGJsb2NrIGVsZW1lbnQgd2lsbCBwdXQgdGhlIGN1cnNvciBpbiB0aGF0IGVsZW1lbnQsXG4gICAgLy8gYW5kIHRoZW4sIGJlY2F1c2UgaXQncyBub3QgZWRpdGFibGUsIGhpZGUgdGhlIHZpcnR1YWwga2V5Ym9hcmQuXG4gICAgLy8gQmVjYXVzZSBBbmRyb2lkIGRvZXNuJ3QgYWxsb3cgdXMgdG8gYWN0dWFsbHkgZGV0ZWN0IGJhY2tzcGFjZVxuICAgIC8vIHByZXNzZXMgaW4gYSBzYW5lIHdheSwgdGhpcyBjb2RlIGNoZWNrcyBmb3Igd2hlbiB0aGF0IGhhcHBlbnNcbiAgICAvLyBhbmQgc2ltdWxhdGVzIGEgYmFja3NwYWNlIHByZXNzIGluIHRoaXMgY2FzZS5cbiAgICBpZiAoYW5kcm9pZCAmJiBjaHJvbWUgJiYgdGhpcy5jbS5kaXNwbGF5Lmd1dHRlclNwZWNzLmxlbmd0aCAmJiBpc0luR3V0dGVyKHNlbC5hbmNob3JOb2RlKSkge1xuICAgICAgdGhpcy5jbS50cmlnZ2VyT25LZXlEb3duKHt0eXBlOiBcImtleWRvd25cIiwga2V5Q29kZTogOCwgcHJldmVudERlZmF1bHQ6IE1hdGguYWJzfSk7XG4gICAgICB0aGlzLmJsdXIoKTtcbiAgICAgIHRoaXMuZm9jdXMoKTtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBpZiAodGhpcy5jb21wb3NpbmcpIHsgcmV0dXJuIH1cbiAgICB0aGlzLnJlbWVtYmVyU2VsZWN0aW9uKCk7XG4gICAgdmFyIGFuY2hvciA9IGRvbVRvUG9zKGNtLCBzZWwuYW5jaG9yTm9kZSwgc2VsLmFuY2hvck9mZnNldCk7XG4gICAgdmFyIGhlYWQgPSBkb21Ub1BvcyhjbSwgc2VsLmZvY3VzTm9kZSwgc2VsLmZvY3VzT2Zmc2V0KTtcbiAgICBpZiAoYW5jaG9yICYmIGhlYWQpIHsgcnVuSW5PcChjbSwgZnVuY3Rpb24gKCkge1xuICAgICAgc2V0U2VsZWN0aW9uKGNtLmRvYywgc2ltcGxlU2VsZWN0aW9uKGFuY2hvciwgaGVhZCksIHNlbF9kb250U2Nyb2xsKTtcbiAgICAgIGlmIChhbmNob3IuYmFkIHx8IGhlYWQuYmFkKSB7IGNtLmN1ck9wLnNlbGVjdGlvbkNoYW5nZWQgPSB0cnVlOyB9XG4gICAgfSk7IH1cbiAgfTtcblxuICBDb250ZW50RWRpdGFibGVJbnB1dC5wcm90b3R5cGUucG9sbENvbnRlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMucmVhZERPTVRpbWVvdXQgIT0gbnVsbCkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMucmVhZERPTVRpbWVvdXQpO1xuICAgICAgdGhpcy5yZWFkRE9NVGltZW91dCA9IG51bGw7XG4gICAgfVxuXG4gICAgdmFyIGNtID0gdGhpcy5jbSwgZGlzcGxheSA9IGNtLmRpc3BsYXksIHNlbCA9IGNtLmRvYy5zZWwucHJpbWFyeSgpO1xuICAgIHZhciBmcm9tID0gc2VsLmZyb20oKSwgdG8gPSBzZWwudG8oKTtcbiAgICBpZiAoZnJvbS5jaCA9PSAwICYmIGZyb20ubGluZSA+IGNtLmZpcnN0TGluZSgpKVxuICAgICAgeyBmcm9tID0gUG9zKGZyb20ubGluZSAtIDEsIGdldExpbmUoY20uZG9jLCBmcm9tLmxpbmUgLSAxKS5sZW5ndGgpOyB9XG4gICAgaWYgKHRvLmNoID09IGdldExpbmUoY20uZG9jLCB0by5saW5lKS50ZXh0Lmxlbmd0aCAmJiB0by5saW5lIDwgY20ubGFzdExpbmUoKSlcbiAgICAgIHsgdG8gPSBQb3ModG8ubGluZSArIDEsIDApOyB9XG4gICAgaWYgKGZyb20ubGluZSA8IGRpc3BsYXkudmlld0Zyb20gfHwgdG8ubGluZSA+IGRpc3BsYXkudmlld1RvIC0gMSkgeyByZXR1cm4gZmFsc2UgfVxuXG4gICAgdmFyIGZyb21JbmRleCwgZnJvbUxpbmUsIGZyb21Ob2RlO1xuICAgIGlmIChmcm9tLmxpbmUgPT0gZGlzcGxheS52aWV3RnJvbSB8fCAoZnJvbUluZGV4ID0gZmluZFZpZXdJbmRleChjbSwgZnJvbS5saW5lKSkgPT0gMCkge1xuICAgICAgZnJvbUxpbmUgPSBsaW5lTm8oZGlzcGxheS52aWV3WzBdLmxpbmUpO1xuICAgICAgZnJvbU5vZGUgPSBkaXNwbGF5LnZpZXdbMF0ubm9kZTtcbiAgICB9IGVsc2Uge1xuICAgICAgZnJvbUxpbmUgPSBsaW5lTm8oZGlzcGxheS52aWV3W2Zyb21JbmRleF0ubGluZSk7XG4gICAgICBmcm9tTm9kZSA9IGRpc3BsYXkudmlld1tmcm9tSW5kZXggLSAxXS5ub2RlLm5leHRTaWJsaW5nO1xuICAgIH1cbiAgICB2YXIgdG9JbmRleCA9IGZpbmRWaWV3SW5kZXgoY20sIHRvLmxpbmUpO1xuICAgIHZhciB0b0xpbmUsIHRvTm9kZTtcbiAgICBpZiAodG9JbmRleCA9PSBkaXNwbGF5LnZpZXcubGVuZ3RoIC0gMSkge1xuICAgICAgdG9MaW5lID0gZGlzcGxheS52aWV3VG8gLSAxO1xuICAgICAgdG9Ob2RlID0gZGlzcGxheS5saW5lRGl2Lmxhc3RDaGlsZDtcbiAgICB9IGVsc2Uge1xuICAgICAgdG9MaW5lID0gbGluZU5vKGRpc3BsYXkudmlld1t0b0luZGV4ICsgMV0ubGluZSkgLSAxO1xuICAgICAgdG9Ob2RlID0gZGlzcGxheS52aWV3W3RvSW5kZXggKyAxXS5ub2RlLnByZXZpb3VzU2libGluZztcbiAgICB9XG5cbiAgICBpZiAoIWZyb21Ob2RlKSB7IHJldHVybiBmYWxzZSB9XG4gICAgdmFyIG5ld1RleHQgPSBjbS5kb2Muc3BsaXRMaW5lcyhkb21UZXh0QmV0d2VlbihjbSwgZnJvbU5vZGUsIHRvTm9kZSwgZnJvbUxpbmUsIHRvTGluZSkpO1xuICAgIHZhciBvbGRUZXh0ID0gZ2V0QmV0d2VlbihjbS5kb2MsIFBvcyhmcm9tTGluZSwgMCksIFBvcyh0b0xpbmUsIGdldExpbmUoY20uZG9jLCB0b0xpbmUpLnRleHQubGVuZ3RoKSk7XG4gICAgd2hpbGUgKG5ld1RleHQubGVuZ3RoID4gMSAmJiBvbGRUZXh0Lmxlbmd0aCA+IDEpIHtcbiAgICAgIGlmIChsc3QobmV3VGV4dCkgPT0gbHN0KG9sZFRleHQpKSB7IG5ld1RleHQucG9wKCk7IG9sZFRleHQucG9wKCk7IHRvTGluZS0tOyB9XG4gICAgICBlbHNlIGlmIChuZXdUZXh0WzBdID09IG9sZFRleHRbMF0pIHsgbmV3VGV4dC5zaGlmdCgpOyBvbGRUZXh0LnNoaWZ0KCk7IGZyb21MaW5lKys7IH1cbiAgICAgIGVsc2UgeyBicmVhayB9XG4gICAgfVxuXG4gICAgdmFyIGN1dEZyb250ID0gMCwgY3V0RW5kID0gMDtcbiAgICB2YXIgbmV3VG9wID0gbmV3VGV4dFswXSwgb2xkVG9wID0gb2xkVGV4dFswXSwgbWF4Q3V0RnJvbnQgPSBNYXRoLm1pbihuZXdUb3AubGVuZ3RoLCBvbGRUb3AubGVuZ3RoKTtcbiAgICB3aGlsZSAoY3V0RnJvbnQgPCBtYXhDdXRGcm9udCAmJiBuZXdUb3AuY2hhckNvZGVBdChjdXRGcm9udCkgPT0gb2xkVG9wLmNoYXJDb2RlQXQoY3V0RnJvbnQpKVxuICAgICAgeyArK2N1dEZyb250OyB9XG4gICAgdmFyIG5ld0JvdCA9IGxzdChuZXdUZXh0KSwgb2xkQm90ID0gbHN0KG9sZFRleHQpO1xuICAgIHZhciBtYXhDdXRFbmQgPSBNYXRoLm1pbihuZXdCb3QubGVuZ3RoIC0gKG5ld1RleHQubGVuZ3RoID09IDEgPyBjdXRGcm9udCA6IDApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbGRCb3QubGVuZ3RoIC0gKG9sZFRleHQubGVuZ3RoID09IDEgPyBjdXRGcm9udCA6IDApKTtcbiAgICB3aGlsZSAoY3V0RW5kIDwgbWF4Q3V0RW5kICYmXG4gICAgICAgICAgIG5ld0JvdC5jaGFyQ29kZUF0KG5ld0JvdC5sZW5ndGggLSBjdXRFbmQgLSAxKSA9PSBvbGRCb3QuY2hhckNvZGVBdChvbGRCb3QubGVuZ3RoIC0gY3V0RW5kIC0gMSkpXG4gICAgICB7ICsrY3V0RW5kOyB9XG4gICAgLy8gVHJ5IHRvIG1vdmUgc3RhcnQgb2YgY2hhbmdlIHRvIHN0YXJ0IG9mIHNlbGVjdGlvbiBpZiBhbWJpZ3VvdXNcbiAgICBpZiAobmV3VGV4dC5sZW5ndGggPT0gMSAmJiBvbGRUZXh0Lmxlbmd0aCA9PSAxICYmIGZyb21MaW5lID09IGZyb20ubGluZSkge1xuICAgICAgd2hpbGUgKGN1dEZyb250ICYmIGN1dEZyb250ID4gZnJvbS5jaCAmJlxuICAgICAgICAgICAgIG5ld0JvdC5jaGFyQ29kZUF0KG5ld0JvdC5sZW5ndGggLSBjdXRFbmQgLSAxKSA9PSBvbGRCb3QuY2hhckNvZGVBdChvbGRCb3QubGVuZ3RoIC0gY3V0RW5kIC0gMSkpIHtcbiAgICAgICAgY3V0RnJvbnQtLTtcbiAgICAgICAgY3V0RW5kKys7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbmV3VGV4dFtuZXdUZXh0Lmxlbmd0aCAtIDFdID0gbmV3Qm90LnNsaWNlKDAsIG5ld0JvdC5sZW5ndGggLSBjdXRFbmQpLnJlcGxhY2UoL15cXHUyMDBiKy8sIFwiXCIpO1xuICAgIG5ld1RleHRbMF0gPSBuZXdUZXh0WzBdLnNsaWNlKGN1dEZyb250KS5yZXBsYWNlKC9cXHUyMDBiKyQvLCBcIlwiKTtcblxuICAgIHZhciBjaEZyb20gPSBQb3MoZnJvbUxpbmUsIGN1dEZyb250KTtcbiAgICB2YXIgY2hUbyA9IFBvcyh0b0xpbmUsIG9sZFRleHQubGVuZ3RoID8gbHN0KG9sZFRleHQpLmxlbmd0aCAtIGN1dEVuZCA6IDApO1xuICAgIGlmIChuZXdUZXh0Lmxlbmd0aCA+IDEgfHwgbmV3VGV4dFswXSB8fCBjbXAoY2hGcm9tLCBjaFRvKSkge1xuICAgICAgcmVwbGFjZVJhbmdlKGNtLmRvYywgbmV3VGV4dCwgY2hGcm9tLCBjaFRvLCBcIitpbnB1dFwiKTtcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICB9O1xuXG4gIENvbnRlbnRFZGl0YWJsZUlucHV0LnByb3RvdHlwZS5lbnN1cmVQb2xsZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5mb3JjZUNvbXBvc2l0aW9uRW5kKCk7XG4gIH07XG4gIENvbnRlbnRFZGl0YWJsZUlucHV0LnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmZvcmNlQ29tcG9zaXRpb25FbmQoKTtcbiAgfTtcbiAgQ29udGVudEVkaXRhYmxlSW5wdXQucHJvdG90eXBlLmZvcmNlQ29tcG9zaXRpb25FbmQgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCF0aGlzLmNvbXBvc2luZykgeyByZXR1cm4gfVxuICAgIGNsZWFyVGltZW91dCh0aGlzLnJlYWRET01UaW1lb3V0KTtcbiAgICB0aGlzLmNvbXBvc2luZyA9IG51bGw7XG4gICAgdGhpcy51cGRhdGVGcm9tRE9NKCk7XG4gICAgdGhpcy5kaXYuYmx1cigpO1xuICAgIHRoaXMuZGl2LmZvY3VzKCk7XG4gIH07XG4gIENvbnRlbnRFZGl0YWJsZUlucHV0LnByb3RvdHlwZS5yZWFkRnJvbURPTVNvb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgdGhpcyQxID0gdGhpcztcblxuICAgIGlmICh0aGlzLnJlYWRET01UaW1lb3V0ICE9IG51bGwpIHsgcmV0dXJuIH1cbiAgICB0aGlzLnJlYWRET01UaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICB0aGlzJDEucmVhZERPTVRpbWVvdXQgPSBudWxsO1xuICAgICAgaWYgKHRoaXMkMS5jb21wb3NpbmcpIHtcbiAgICAgICAgaWYgKHRoaXMkMS5jb21wb3NpbmcuZG9uZSkgeyB0aGlzJDEuY29tcG9zaW5nID0gbnVsbDsgfVxuICAgICAgICBlbHNlIHsgcmV0dXJuIH1cbiAgICAgIH1cbiAgICAgIHRoaXMkMS51cGRhdGVGcm9tRE9NKCk7XG4gICAgfSwgODApO1xuICB9O1xuXG4gIENvbnRlbnRFZGl0YWJsZUlucHV0LnByb3RvdHlwZS51cGRhdGVGcm9tRE9NID0gZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIHRoaXMkMSA9IHRoaXM7XG5cbiAgICBpZiAodGhpcy5jbS5pc1JlYWRPbmx5KCkgfHwgIXRoaXMucG9sbENvbnRlbnQoKSlcbiAgICAgIHsgcnVuSW5PcCh0aGlzLmNtLCBmdW5jdGlvbiAoKSB7IHJldHVybiByZWdDaGFuZ2UodGhpcyQxLmNtKTsgfSk7IH1cbiAgfTtcblxuICBDb250ZW50RWRpdGFibGVJbnB1dC5wcm90b3R5cGUuc2V0VW5lZGl0YWJsZSA9IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgbm9kZS5jb250ZW50RWRpdGFibGUgPSBcImZhbHNlXCI7XG4gIH07XG5cbiAgQ29udGVudEVkaXRhYmxlSW5wdXQucHJvdG90eXBlLm9uS2V5UHJlc3MgPSBmdW5jdGlvbiAoZSkge1xuICAgIGlmIChlLmNoYXJDb2RlID09IDAgfHwgdGhpcy5jb21wb3NpbmcpIHsgcmV0dXJuIH1cbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgaWYgKCF0aGlzLmNtLmlzUmVhZE9ubHkoKSlcbiAgICAgIHsgb3BlcmF0aW9uKHRoaXMuY20sIGFwcGx5VGV4dElucHV0KSh0aGlzLmNtLCBTdHJpbmcuZnJvbUNoYXJDb2RlKGUuY2hhckNvZGUgPT0gbnVsbCA/IGUua2V5Q29kZSA6IGUuY2hhckNvZGUpLCAwKTsgfVxuICB9O1xuXG4gIENvbnRlbnRFZGl0YWJsZUlucHV0LnByb3RvdHlwZS5yZWFkT25seUNoYW5nZWQgPSBmdW5jdGlvbiAodmFsKSB7XG4gICAgdGhpcy5kaXYuY29udGVudEVkaXRhYmxlID0gU3RyaW5nKHZhbCAhPSBcIm5vY3Vyc29yXCIpO1xuICB9O1xuXG4gIENvbnRlbnRFZGl0YWJsZUlucHV0LnByb3RvdHlwZS5vbkNvbnRleHRNZW51ID0gZnVuY3Rpb24gKCkge307XG4gIENvbnRlbnRFZGl0YWJsZUlucHV0LnByb3RvdHlwZS5yZXNldFBvc2l0aW9uID0gZnVuY3Rpb24gKCkge307XG5cbiAgQ29udGVudEVkaXRhYmxlSW5wdXQucHJvdG90eXBlLm5lZWRzQ29udGVudEF0dHJpYnV0ZSA9IHRydWU7XG5cbiAgZnVuY3Rpb24gcG9zVG9ET00oY20sIHBvcykge1xuICAgIHZhciB2aWV3ID0gZmluZFZpZXdGb3JMaW5lKGNtLCBwb3MubGluZSk7XG4gICAgaWYgKCF2aWV3IHx8IHZpZXcuaGlkZGVuKSB7IHJldHVybiBudWxsIH1cbiAgICB2YXIgbGluZSA9IGdldExpbmUoY20uZG9jLCBwb3MubGluZSk7XG4gICAgdmFyIGluZm8gPSBtYXBGcm9tTGluZVZpZXcodmlldywgbGluZSwgcG9zLmxpbmUpO1xuXG4gICAgdmFyIG9yZGVyID0gZ2V0T3JkZXIobGluZSwgY20uZG9jLmRpcmVjdGlvbiksIHNpZGUgPSBcImxlZnRcIjtcbiAgICBpZiAob3JkZXIpIHtcbiAgICAgIHZhciBwYXJ0UG9zID0gZ2V0QmlkaVBhcnRBdChvcmRlciwgcG9zLmNoKTtcbiAgICAgIHNpZGUgPSBwYXJ0UG9zICUgMiA/IFwicmlnaHRcIiA6IFwibGVmdFwiO1xuICAgIH1cbiAgICB2YXIgcmVzdWx0ID0gbm9kZUFuZE9mZnNldEluTGluZU1hcChpbmZvLm1hcCwgcG9zLmNoLCBzaWRlKTtcbiAgICByZXN1bHQub2Zmc2V0ID0gcmVzdWx0LmNvbGxhcHNlID09IFwicmlnaHRcIiA/IHJlc3VsdC5lbmQgOiByZXN1bHQuc3RhcnQ7XG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG5cbiAgZnVuY3Rpb24gaXNJbkd1dHRlcihub2RlKSB7XG4gICAgZm9yICh2YXIgc2NhbiA9IG5vZGU7IHNjYW47IHNjYW4gPSBzY2FuLnBhcmVudE5vZGUpXG4gICAgICB7IGlmICgvQ29kZU1pcnJvci1ndXR0ZXItd3JhcHBlci8udGVzdChzY2FuLmNsYXNzTmFtZSkpIHsgcmV0dXJuIHRydWUgfSB9XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICBmdW5jdGlvbiBiYWRQb3MocG9zLCBiYWQpIHsgaWYgKGJhZCkgeyBwb3MuYmFkID0gdHJ1ZTsgfSByZXR1cm4gcG9zIH1cblxuICBmdW5jdGlvbiBkb21UZXh0QmV0d2VlbihjbSwgZnJvbSwgdG8sIGZyb21MaW5lLCB0b0xpbmUpIHtcbiAgICB2YXIgdGV4dCA9IFwiXCIsIGNsb3NpbmcgPSBmYWxzZSwgbGluZVNlcCA9IGNtLmRvYy5saW5lU2VwYXJhdG9yKCksIGV4dHJhTGluZWJyZWFrID0gZmFsc2U7XG4gICAgZnVuY3Rpb24gcmVjb2duaXplTWFya2VyKGlkKSB7IHJldHVybiBmdW5jdGlvbiAobWFya2VyKSB7IHJldHVybiBtYXJrZXIuaWQgPT0gaWQ7IH0gfVxuICAgIGZ1bmN0aW9uIGNsb3NlKCkge1xuICAgICAgaWYgKGNsb3NpbmcpIHtcbiAgICAgICAgdGV4dCArPSBsaW5lU2VwO1xuICAgICAgICBpZiAoZXh0cmFMaW5lYnJlYWspIHsgdGV4dCArPSBsaW5lU2VwOyB9XG4gICAgICAgIGNsb3NpbmcgPSBleHRyYUxpbmVicmVhayA9IGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBhZGRUZXh0KHN0cikge1xuICAgICAgaWYgKHN0cikge1xuICAgICAgICBjbG9zZSgpO1xuICAgICAgICB0ZXh0ICs9IHN0cjtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gd2Fsayhub2RlKSB7XG4gICAgICBpZiAobm9kZS5ub2RlVHlwZSA9PSAxKSB7XG4gICAgICAgIHZhciBjbVRleHQgPSBub2RlLmdldEF0dHJpYnV0ZShcImNtLXRleHRcIik7XG4gICAgICAgIGlmIChjbVRleHQpIHtcbiAgICAgICAgICBhZGRUZXh0KGNtVGV4dCk7XG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1hcmtlcklEID0gbm9kZS5nZXRBdHRyaWJ1dGUoXCJjbS1tYXJrZXJcIiksIHJhbmdlO1xuICAgICAgICBpZiAobWFya2VySUQpIHtcbiAgICAgICAgICB2YXIgZm91bmQgPSBjbS5maW5kTWFya3MoUG9zKGZyb21MaW5lLCAwKSwgUG9zKHRvTGluZSArIDEsIDApLCByZWNvZ25pemVNYXJrZXIoK21hcmtlcklEKSk7XG4gICAgICAgICAgaWYgKGZvdW5kLmxlbmd0aCAmJiAocmFuZ2UgPSBmb3VuZFswXS5maW5kKDApKSlcbiAgICAgICAgICAgIHsgYWRkVGV4dChnZXRCZXR3ZWVuKGNtLmRvYywgcmFuZ2UuZnJvbSwgcmFuZ2UudG8pLmpvaW4obGluZVNlcCkpOyB9XG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5vZGUuZ2V0QXR0cmlidXRlKFwiY29udGVudGVkaXRhYmxlXCIpID09IFwiZmFsc2VcIikgeyByZXR1cm4gfVxuICAgICAgICB2YXIgaXNCbG9jayA9IC9eKHByZXxkaXZ8cHxsaXx0YWJsZXxicikkL2kudGVzdChub2RlLm5vZGVOYW1lKTtcbiAgICAgICAgaWYgKCEvXmJyJC9pLnRlc3Qobm9kZS5ub2RlTmFtZSkgJiYgbm9kZS50ZXh0Q29udGVudC5sZW5ndGggPT0gMCkgeyByZXR1cm4gfVxuXG4gICAgICAgIGlmIChpc0Jsb2NrKSB7IGNsb3NlKCk7IH1cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2RlLmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspXG4gICAgICAgICAgeyB3YWxrKG5vZGUuY2hpbGROb2Rlc1tpXSk7IH1cblxuICAgICAgICBpZiAoL14ocHJlfHApJC9pLnRlc3Qobm9kZS5ub2RlTmFtZSkpIHsgZXh0cmFMaW5lYnJlYWsgPSB0cnVlOyB9XG4gICAgICAgIGlmIChpc0Jsb2NrKSB7IGNsb3NpbmcgPSB0cnVlOyB9XG4gICAgICB9IGVsc2UgaWYgKG5vZGUubm9kZVR5cGUgPT0gMykge1xuICAgICAgICBhZGRUZXh0KG5vZGUubm9kZVZhbHVlLnJlcGxhY2UoL1xcdTIwMGIvZywgXCJcIikucmVwbGFjZSgvXFx1MDBhMC9nLCBcIiBcIikpO1xuICAgICAgfVxuICAgIH1cbiAgICBmb3IgKDs7KSB7XG4gICAgICB3YWxrKGZyb20pO1xuICAgICAgaWYgKGZyb20gPT0gdG8pIHsgYnJlYWsgfVxuICAgICAgZnJvbSA9IGZyb20ubmV4dFNpYmxpbmc7XG4gICAgICBleHRyYUxpbmVicmVhayA9IGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdGV4dFxuICB9XG5cbiAgZnVuY3Rpb24gZG9tVG9Qb3MoY20sIG5vZGUsIG9mZnNldCkge1xuICAgIHZhciBsaW5lTm9kZTtcbiAgICBpZiAobm9kZSA9PSBjbS5kaXNwbGF5LmxpbmVEaXYpIHtcbiAgICAgIGxpbmVOb2RlID0gY20uZGlzcGxheS5saW5lRGl2LmNoaWxkTm9kZXNbb2Zmc2V0XTtcbiAgICAgIGlmICghbGluZU5vZGUpIHsgcmV0dXJuIGJhZFBvcyhjbS5jbGlwUG9zKFBvcyhjbS5kaXNwbGF5LnZpZXdUbyAtIDEpKSwgdHJ1ZSkgfVxuICAgICAgbm9kZSA9IG51bGw7IG9mZnNldCA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAobGluZU5vZGUgPSBub2RlOzsgbGluZU5vZGUgPSBsaW5lTm9kZS5wYXJlbnROb2RlKSB7XG4gICAgICAgIGlmICghbGluZU5vZGUgfHwgbGluZU5vZGUgPT0gY20uZGlzcGxheS5saW5lRGl2KSB7IHJldHVybiBudWxsIH1cbiAgICAgICAgaWYgKGxpbmVOb2RlLnBhcmVudE5vZGUgJiYgbGluZU5vZGUucGFyZW50Tm9kZSA9PSBjbS5kaXNwbGF5LmxpbmVEaXYpIHsgYnJlYWsgfVxuICAgICAgfVxuICAgIH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNtLmRpc3BsYXkudmlldy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGxpbmVWaWV3ID0gY20uZGlzcGxheS52aWV3W2ldO1xuICAgICAgaWYgKGxpbmVWaWV3Lm5vZGUgPT0gbGluZU5vZGUpXG4gICAgICAgIHsgcmV0dXJuIGxvY2F0ZU5vZGVJbkxpbmVWaWV3KGxpbmVWaWV3LCBub2RlLCBvZmZzZXQpIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBsb2NhdGVOb2RlSW5MaW5lVmlldyhsaW5lVmlldywgbm9kZSwgb2Zmc2V0KSB7XG4gICAgdmFyIHdyYXBwZXIgPSBsaW5lVmlldy50ZXh0LmZpcnN0Q2hpbGQsIGJhZCA9IGZhbHNlO1xuICAgIGlmICghbm9kZSB8fCAhY29udGFpbnMod3JhcHBlciwgbm9kZSkpIHsgcmV0dXJuIGJhZFBvcyhQb3MobGluZU5vKGxpbmVWaWV3LmxpbmUpLCAwKSwgdHJ1ZSkgfVxuICAgIGlmIChub2RlID09IHdyYXBwZXIpIHtcbiAgICAgIGJhZCA9IHRydWU7XG4gICAgICBub2RlID0gd3JhcHBlci5jaGlsZE5vZGVzW29mZnNldF07XG4gICAgICBvZmZzZXQgPSAwO1xuICAgICAgaWYgKCFub2RlKSB7XG4gICAgICAgIHZhciBsaW5lID0gbGluZVZpZXcucmVzdCA/IGxzdChsaW5lVmlldy5yZXN0KSA6IGxpbmVWaWV3LmxpbmU7XG4gICAgICAgIHJldHVybiBiYWRQb3MoUG9zKGxpbmVObyhsaW5lKSwgbGluZS50ZXh0Lmxlbmd0aCksIGJhZClcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgdGV4dE5vZGUgPSBub2RlLm5vZGVUeXBlID09IDMgPyBub2RlIDogbnVsbCwgdG9wTm9kZSA9IG5vZGU7XG4gICAgaWYgKCF0ZXh0Tm9kZSAmJiBub2RlLmNoaWxkTm9kZXMubGVuZ3RoID09IDEgJiYgbm9kZS5maXJzdENoaWxkLm5vZGVUeXBlID09IDMpIHtcbiAgICAgIHRleHROb2RlID0gbm9kZS5maXJzdENoaWxkO1xuICAgICAgaWYgKG9mZnNldCkgeyBvZmZzZXQgPSB0ZXh0Tm9kZS5ub2RlVmFsdWUubGVuZ3RoOyB9XG4gICAgfVxuICAgIHdoaWxlICh0b3BOb2RlLnBhcmVudE5vZGUgIT0gd3JhcHBlcikgeyB0b3BOb2RlID0gdG9wTm9kZS5wYXJlbnROb2RlOyB9XG4gICAgdmFyIG1lYXN1cmUgPSBsaW5lVmlldy5tZWFzdXJlLCBtYXBzID0gbWVhc3VyZS5tYXBzO1xuXG4gICAgZnVuY3Rpb24gZmluZCh0ZXh0Tm9kZSwgdG9wTm9kZSwgb2Zmc2V0KSB7XG4gICAgICBmb3IgKHZhciBpID0gLTE7IGkgPCAobWFwcyA/IG1hcHMubGVuZ3RoIDogMCk7IGkrKykge1xuICAgICAgICB2YXIgbWFwID0gaSA8IDAgPyBtZWFzdXJlLm1hcCA6IG1hcHNbaV07XG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWFwLmxlbmd0aDsgaiArPSAzKSB7XG4gICAgICAgICAgdmFyIGN1ck5vZGUgPSBtYXBbaiArIDJdO1xuICAgICAgICAgIGlmIChjdXJOb2RlID09IHRleHROb2RlIHx8IGN1ck5vZGUgPT0gdG9wTm9kZSkge1xuICAgICAgICAgICAgdmFyIGxpbmUgPSBsaW5lTm8oaSA8IDAgPyBsaW5lVmlldy5saW5lIDogbGluZVZpZXcucmVzdFtpXSk7XG4gICAgICAgICAgICB2YXIgY2ggPSBtYXBbal0gKyBvZmZzZXQ7XG4gICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBjdXJOb2RlICE9IHRleHROb2RlKSB7IGNoID0gbWFwW2ogKyAob2Zmc2V0ID8gMSA6IDApXTsgfVxuICAgICAgICAgICAgcmV0dXJuIFBvcyhsaW5lLCBjaClcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgdmFyIGZvdW5kID0gZmluZCh0ZXh0Tm9kZSwgdG9wTm9kZSwgb2Zmc2V0KTtcbiAgICBpZiAoZm91bmQpIHsgcmV0dXJuIGJhZFBvcyhmb3VuZCwgYmFkKSB9XG5cbiAgICAvLyBGSVhNRSB0aGlzIGlzIGFsbCByZWFsbHkgc2hha3kuIG1pZ2h0IGhhbmRsZSB0aGUgZmV3IGNhc2VzIGl0IG5lZWRzIHRvIGhhbmRsZSwgYnV0IGxpa2VseSB0byBjYXVzZSBwcm9ibGVtc1xuICAgIGZvciAodmFyIGFmdGVyID0gdG9wTm9kZS5uZXh0U2libGluZywgZGlzdCA9IHRleHROb2RlID8gdGV4dE5vZGUubm9kZVZhbHVlLmxlbmd0aCAtIG9mZnNldCA6IDA7IGFmdGVyOyBhZnRlciA9IGFmdGVyLm5leHRTaWJsaW5nKSB7XG4gICAgICBmb3VuZCA9IGZpbmQoYWZ0ZXIsIGFmdGVyLmZpcnN0Q2hpbGQsIDApO1xuICAgICAgaWYgKGZvdW5kKVxuICAgICAgICB7IHJldHVybiBiYWRQb3MoUG9zKGZvdW5kLmxpbmUsIGZvdW5kLmNoIC0gZGlzdCksIGJhZCkgfVxuICAgICAgZWxzZVxuICAgICAgICB7IGRpc3QgKz0gYWZ0ZXIudGV4dENvbnRlbnQubGVuZ3RoOyB9XG4gICAgfVxuICAgIGZvciAodmFyIGJlZm9yZSA9IHRvcE5vZGUucHJldmlvdXNTaWJsaW5nLCBkaXN0JDEgPSBvZmZzZXQ7IGJlZm9yZTsgYmVmb3JlID0gYmVmb3JlLnByZXZpb3VzU2libGluZykge1xuICAgICAgZm91bmQgPSBmaW5kKGJlZm9yZSwgYmVmb3JlLmZpcnN0Q2hpbGQsIC0xKTtcbiAgICAgIGlmIChmb3VuZClcbiAgICAgICAgeyByZXR1cm4gYmFkUG9zKFBvcyhmb3VuZC5saW5lLCBmb3VuZC5jaCArIGRpc3QkMSksIGJhZCkgfVxuICAgICAgZWxzZVxuICAgICAgICB7IGRpc3QkMSArPSBiZWZvcmUudGV4dENvbnRlbnQubGVuZ3RoOyB9XG4gICAgfVxuICB9XG5cbiAgLy8gVEVYVEFSRUEgSU5QVVQgU1RZTEVcblxuICB2YXIgVGV4dGFyZWFJbnB1dCA9IGZ1bmN0aW9uKGNtKSB7XG4gICAgdGhpcy5jbSA9IGNtO1xuICAgIC8vIFNlZSBpbnB1dC5wb2xsIGFuZCBpbnB1dC5yZXNldFxuICAgIHRoaXMucHJldklucHV0ID0gXCJcIjtcblxuICAgIC8vIEZsYWcgdGhhdCBpbmRpY2F0ZXMgd2hldGhlciB3ZSBleHBlY3QgaW5wdXQgdG8gYXBwZWFyIHJlYWwgc29vblxuICAgIC8vIG5vdyAoYWZ0ZXIgc29tZSBldmVudCBsaWtlICdrZXlwcmVzcycgb3IgJ2lucHV0JykgYW5kIGFyZVxuICAgIC8vIHBvbGxpbmcgaW50ZW5zaXZlbHkuXG4gICAgdGhpcy5wb2xsaW5nRmFzdCA9IGZhbHNlO1xuICAgIC8vIFNlbGYtcmVzZXR0aW5nIHRpbWVvdXQgZm9yIHRoZSBwb2xsZXJcbiAgICB0aGlzLnBvbGxpbmcgPSBuZXcgRGVsYXllZCgpO1xuICAgIC8vIFVzZWQgdG8gd29yayBhcm91bmQgSUUgaXNzdWUgd2l0aCBzZWxlY3Rpb24gYmVpbmcgZm9yZ290dGVuIHdoZW4gZm9jdXMgbW92ZXMgYXdheSBmcm9tIHRleHRhcmVhXG4gICAgdGhpcy5oYXNTZWxlY3Rpb24gPSBmYWxzZTtcbiAgICB0aGlzLmNvbXBvc2luZyA9IG51bGw7XG4gIH07XG5cbiAgVGV4dGFyZWFJbnB1dC5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uIChkaXNwbGF5KSB7XG4gICAgICB2YXIgdGhpcyQxID0gdGhpcztcblxuICAgIHZhciBpbnB1dCA9IHRoaXMsIGNtID0gdGhpcy5jbTtcbiAgICB0aGlzLmNyZWF0ZUZpZWxkKGRpc3BsYXkpO1xuICAgIHZhciB0ZSA9IHRoaXMudGV4dGFyZWE7XG5cbiAgICBkaXNwbGF5LndyYXBwZXIuaW5zZXJ0QmVmb3JlKHRoaXMud3JhcHBlciwgZGlzcGxheS53cmFwcGVyLmZpcnN0Q2hpbGQpO1xuXG4gICAgLy8gTmVlZGVkIHRvIGhpZGUgYmlnIGJsdWUgYmxpbmtpbmcgY3Vyc29yIG9uIE1vYmlsZSBTYWZhcmkgKGRvZXNuJ3Qgc2VlbSB0byB3b3JrIGluIGlPUyA4IGFueW1vcmUpXG4gICAgaWYgKGlvcykgeyB0ZS5zdHlsZS53aWR0aCA9IFwiMHB4XCI7IH1cblxuICAgIG9uKHRlLCBcImlucHV0XCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmIChpZSAmJiBpZV92ZXJzaW9uID49IDkgJiYgdGhpcyQxLmhhc1NlbGVjdGlvbikgeyB0aGlzJDEuaGFzU2VsZWN0aW9uID0gbnVsbDsgfVxuICAgICAgaW5wdXQucG9sbCgpO1xuICAgIH0pO1xuXG4gICAgb24odGUsIFwicGFzdGVcIiwgZnVuY3Rpb24gKGUpIHtcbiAgICAgIGlmIChzaWduYWxET01FdmVudChjbSwgZSkgfHwgaGFuZGxlUGFzdGUoZSwgY20pKSB7IHJldHVybiB9XG5cbiAgICAgIGNtLnN0YXRlLnBhc3RlSW5jb21pbmcgPSArbmV3IERhdGU7XG4gICAgICBpbnB1dC5mYXN0UG9sbCgpO1xuICAgIH0pO1xuXG4gICAgZnVuY3Rpb24gcHJlcGFyZUNvcHlDdXQoZSkge1xuICAgICAgaWYgKHNpZ25hbERPTUV2ZW50KGNtLCBlKSkgeyByZXR1cm4gfVxuICAgICAgaWYgKGNtLnNvbWV0aGluZ1NlbGVjdGVkKCkpIHtcbiAgICAgICAgc2V0TGFzdENvcGllZCh7bGluZVdpc2U6IGZhbHNlLCB0ZXh0OiBjbS5nZXRTZWxlY3Rpb25zKCl9KTtcbiAgICAgIH0gZWxzZSBpZiAoIWNtLm9wdGlvbnMubGluZVdpc2VDb3B5Q3V0KSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHJhbmdlcyA9IGNvcHlhYmxlUmFuZ2VzKGNtKTtcbiAgICAgICAgc2V0TGFzdENvcGllZCh7bGluZVdpc2U6IHRydWUsIHRleHQ6IHJhbmdlcy50ZXh0fSk7XG4gICAgICAgIGlmIChlLnR5cGUgPT0gXCJjdXRcIikge1xuICAgICAgICAgIGNtLnNldFNlbGVjdGlvbnMocmFuZ2VzLnJhbmdlcywgbnVsbCwgc2VsX2RvbnRTY3JvbGwpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlucHV0LnByZXZJbnB1dCA9IFwiXCI7XG4gICAgICAgICAgdGUudmFsdWUgPSByYW5nZXMudGV4dC5qb2luKFwiXFxuXCIpO1xuICAgICAgICAgIHNlbGVjdElucHV0KHRlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGUudHlwZSA9PSBcImN1dFwiKSB7IGNtLnN0YXRlLmN1dEluY29taW5nID0gK25ldyBEYXRlOyB9XG4gICAgfVxuICAgIG9uKHRlLCBcImN1dFwiLCBwcmVwYXJlQ29weUN1dCk7XG4gICAgb24odGUsIFwiY29weVwiLCBwcmVwYXJlQ29weUN1dCk7XG5cbiAgICBvbihkaXNwbGF5LnNjcm9sbGVyLCBcInBhc3RlXCIsIGZ1bmN0aW9uIChlKSB7XG4gICAgICBpZiAoZXZlbnRJbldpZGdldChkaXNwbGF5LCBlKSB8fCBzaWduYWxET01FdmVudChjbSwgZSkpIHsgcmV0dXJuIH1cbiAgICAgIGlmICghdGUuZGlzcGF0Y2hFdmVudCkge1xuICAgICAgICBjbS5zdGF0ZS5wYXN0ZUluY29taW5nID0gK25ldyBEYXRlO1xuICAgICAgICBpbnB1dC5mb2N1cygpO1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgLy8gUGFzcyB0aGUgYHBhc3RlYCBldmVudCB0byB0aGUgdGV4dGFyZWEgc28gaXQncyBoYW5kbGVkIGJ5IGl0cyBldmVudCBsaXN0ZW5lci5cbiAgICAgIHZhciBldmVudCA9IG5ldyBFdmVudChcInBhc3RlXCIpO1xuICAgICAgZXZlbnQuY2xpcGJvYXJkRGF0YSA9IGUuY2xpcGJvYXJkRGF0YTtcbiAgICAgIHRlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgIH0pO1xuXG4gICAgLy8gUHJldmVudCBub3JtYWwgc2VsZWN0aW9uIGluIHRoZSBlZGl0b3IgKHdlIGhhbmRsZSBvdXIgb3duKVxuICAgIG9uKGRpc3BsYXkubGluZVNwYWNlLCBcInNlbGVjdHN0YXJ0XCIsIGZ1bmN0aW9uIChlKSB7XG4gICAgICBpZiAoIWV2ZW50SW5XaWRnZXQoZGlzcGxheSwgZSkpIHsgZV9wcmV2ZW50RGVmYXVsdChlKTsgfVxuICAgIH0pO1xuXG4gICAgb24odGUsIFwiY29tcG9zaXRpb25zdGFydFwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgc3RhcnQgPSBjbS5nZXRDdXJzb3IoXCJmcm9tXCIpO1xuICAgICAgaWYgKGlucHV0LmNvbXBvc2luZykgeyBpbnB1dC5jb21wb3NpbmcucmFuZ2UuY2xlYXIoKTsgfVxuICAgICAgaW5wdXQuY29tcG9zaW5nID0ge1xuICAgICAgICBzdGFydDogc3RhcnQsXG4gICAgICAgIHJhbmdlOiBjbS5tYXJrVGV4dChzdGFydCwgY20uZ2V0Q3Vyc29yKFwidG9cIiksIHtjbGFzc05hbWU6IFwiQ29kZU1pcnJvci1jb21wb3NpbmdcIn0pXG4gICAgICB9O1xuICAgIH0pO1xuICAgIG9uKHRlLCBcImNvbXBvc2l0aW9uZW5kXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmIChpbnB1dC5jb21wb3NpbmcpIHtcbiAgICAgICAgaW5wdXQucG9sbCgpO1xuICAgICAgICBpbnB1dC5jb21wb3NpbmcucmFuZ2UuY2xlYXIoKTtcbiAgICAgICAgaW5wdXQuY29tcG9zaW5nID0gbnVsbDtcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcblxuICBUZXh0YXJlYUlucHV0LnByb3RvdHlwZS5jcmVhdGVGaWVsZCA9IGZ1bmN0aW9uIChfZGlzcGxheSkge1xuICAgIC8vIFdyYXBzIGFuZCBoaWRlcyBpbnB1dCB0ZXh0YXJlYVxuICAgIHRoaXMud3JhcHBlciA9IGhpZGRlblRleHRhcmVhKCk7XG4gICAgLy8gVGhlIHNlbWloaWRkZW4gdGV4dGFyZWEgdGhhdCBpcyBmb2N1c2VkIHdoZW4gdGhlIGVkaXRvciBpc1xuICAgIC8vIGZvY3VzZWQsIGFuZCByZWNlaXZlcyBpbnB1dC5cbiAgICB0aGlzLnRleHRhcmVhID0gdGhpcy53cmFwcGVyLmZpcnN0Q2hpbGQ7XG4gIH07XG5cbiAgVGV4dGFyZWFJbnB1dC5wcm90b3R5cGUuc2NyZWVuUmVhZGVyTGFiZWxDaGFuZ2VkID0gZnVuY3Rpb24gKGxhYmVsKSB7XG4gICAgLy8gTGFiZWwgZm9yIHNjcmVlbnJlYWRlcnMsIGFjY2Vzc2liaWxpdHlcbiAgICBpZihsYWJlbCkge1xuICAgICAgdGhpcy50ZXh0YXJlYS5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCBsYWJlbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudGV4dGFyZWEucmVtb3ZlQXR0cmlidXRlKCdhcmlhLWxhYmVsJyk7XG4gICAgfVxuICB9O1xuXG4gIFRleHRhcmVhSW5wdXQucHJvdG90eXBlLnByZXBhcmVTZWxlY3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgLy8gUmVkcmF3IHRoZSBzZWxlY3Rpb24gYW5kL29yIGN1cnNvclxuICAgIHZhciBjbSA9IHRoaXMuY20sIGRpc3BsYXkgPSBjbS5kaXNwbGF5LCBkb2MgPSBjbS5kb2M7XG4gICAgdmFyIHJlc3VsdCA9IHByZXBhcmVTZWxlY3Rpb24oY20pO1xuXG4gICAgLy8gTW92ZSB0aGUgaGlkZGVuIHRleHRhcmVhIG5lYXIgdGhlIGN1cnNvciB0byBwcmV2ZW50IHNjcm9sbGluZyBhcnRpZmFjdHNcbiAgICBpZiAoY20ub3B0aW9ucy5tb3ZlSW5wdXRXaXRoQ3Vyc29yKSB7XG4gICAgICB2YXIgaGVhZFBvcyA9IGN1cnNvckNvb3JkcyhjbSwgZG9jLnNlbC5wcmltYXJ5KCkuaGVhZCwgXCJkaXZcIik7XG4gICAgICB2YXIgd3JhcE9mZiA9IGRpc3BsYXkud3JhcHBlci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSwgbGluZU9mZiA9IGRpc3BsYXkubGluZURpdi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIHJlc3VsdC50ZVRvcCA9IE1hdGgubWF4KDAsIE1hdGgubWluKGRpc3BsYXkud3JhcHBlci5jbGllbnRIZWlnaHQgLSAxMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRQb3MudG9wICsgbGluZU9mZi50b3AgLSB3cmFwT2ZmLnRvcCkpO1xuICAgICAgcmVzdWx0LnRlTGVmdCA9IE1hdGgubWF4KDAsIE1hdGgubWluKGRpc3BsYXkud3JhcHBlci5jbGllbnRXaWR0aCAtIDEwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRQb3MubGVmdCArIGxpbmVPZmYubGVmdCAtIHdyYXBPZmYubGVmdCkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHRcbiAgfTtcblxuICBUZXh0YXJlYUlucHV0LnByb3RvdHlwZS5zaG93U2VsZWN0aW9uID0gZnVuY3Rpb24gKGRyYXduKSB7XG4gICAgdmFyIGNtID0gdGhpcy5jbSwgZGlzcGxheSA9IGNtLmRpc3BsYXk7XG4gICAgcmVtb3ZlQ2hpbGRyZW5BbmRBZGQoZGlzcGxheS5jdXJzb3JEaXYsIGRyYXduLmN1cnNvcnMpO1xuICAgIHJlbW92ZUNoaWxkcmVuQW5kQWRkKGRpc3BsYXkuc2VsZWN0aW9uRGl2LCBkcmF3bi5zZWxlY3Rpb24pO1xuICAgIGlmIChkcmF3bi50ZVRvcCAhPSBudWxsKSB7XG4gICAgICB0aGlzLndyYXBwZXIuc3R5bGUudG9wID0gZHJhd24udGVUb3AgKyBcInB4XCI7XG4gICAgICB0aGlzLndyYXBwZXIuc3R5bGUubGVmdCA9IGRyYXduLnRlTGVmdCArIFwicHhcIjtcbiAgICB9XG4gIH07XG5cbiAgLy8gUmVzZXQgdGhlIGlucHV0IHRvIGNvcnJlc3BvbmQgdG8gdGhlIHNlbGVjdGlvbiAob3IgdG8gYmUgZW1wdHksXG4gIC8vIHdoZW4gbm90IHR5cGluZyBhbmQgbm90aGluZyBpcyBzZWxlY3RlZClcbiAgVGV4dGFyZWFJbnB1dC5wcm90b3R5cGUucmVzZXQgPSBmdW5jdGlvbiAodHlwaW5nKSB7XG4gICAgaWYgKHRoaXMuY29udGV4dE1lbnVQZW5kaW5nIHx8IHRoaXMuY29tcG9zaW5nKSB7IHJldHVybiB9XG4gICAgdmFyIGNtID0gdGhpcy5jbTtcbiAgICBpZiAoY20uc29tZXRoaW5nU2VsZWN0ZWQoKSkge1xuICAgICAgdGhpcy5wcmV2SW5wdXQgPSBcIlwiO1xuICAgICAgdmFyIGNvbnRlbnQgPSBjbS5nZXRTZWxlY3Rpb24oKTtcbiAgICAgIHRoaXMudGV4dGFyZWEudmFsdWUgPSBjb250ZW50O1xuICAgICAgaWYgKGNtLnN0YXRlLmZvY3VzZWQpIHsgc2VsZWN0SW5wdXQodGhpcy50ZXh0YXJlYSk7IH1cbiAgICAgIGlmIChpZSAmJiBpZV92ZXJzaW9uID49IDkpIHsgdGhpcy5oYXNTZWxlY3Rpb24gPSBjb250ZW50OyB9XG4gICAgfSBlbHNlIGlmICghdHlwaW5nKSB7XG4gICAgICB0aGlzLnByZXZJbnB1dCA9IHRoaXMudGV4dGFyZWEudmFsdWUgPSBcIlwiO1xuICAgICAgaWYgKGllICYmIGllX3ZlcnNpb24gPj0gOSkgeyB0aGlzLmhhc1NlbGVjdGlvbiA9IG51bGw7IH1cbiAgICB9XG4gIH07XG5cbiAgVGV4dGFyZWFJbnB1dC5wcm90b3R5cGUuZ2V0RmllbGQgPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLnRleHRhcmVhIH07XG5cbiAgVGV4dGFyZWFJbnB1dC5wcm90b3R5cGUuc3VwcG9ydHNUb3VjaCA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGZhbHNlIH07XG5cbiAgVGV4dGFyZWFJbnB1dC5wcm90b3R5cGUuZm9jdXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuY20ub3B0aW9ucy5yZWFkT25seSAhPSBcIm5vY3Vyc29yXCIgJiYgKCFtb2JpbGUgfHwgYWN0aXZlRWx0KCkgIT0gdGhpcy50ZXh0YXJlYSkpIHtcbiAgICAgIHRyeSB7IHRoaXMudGV4dGFyZWEuZm9jdXMoKTsgfVxuICAgICAgY2F0Y2ggKGUpIHt9IC8vIElFOCB3aWxsIHRocm93IGlmIHRoZSB0ZXh0YXJlYSBpcyBkaXNwbGF5OiBub25lIG9yIG5vdCBpbiBET01cbiAgICB9XG4gIH07XG5cbiAgVGV4dGFyZWFJbnB1dC5wcm90b3R5cGUuYmx1ciA9IGZ1bmN0aW9uICgpIHsgdGhpcy50ZXh0YXJlYS5ibHVyKCk7IH07XG5cbiAgVGV4dGFyZWFJbnB1dC5wcm90b3R5cGUucmVzZXRQb3NpdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLndyYXBwZXIuc3R5bGUudG9wID0gdGhpcy53cmFwcGVyLnN0eWxlLmxlZnQgPSAwO1xuICB9O1xuXG4gIFRleHRhcmVhSW5wdXQucHJvdG90eXBlLnJlY2VpdmVkRm9jdXMgPSBmdW5jdGlvbiAoKSB7IHRoaXMuc2xvd1BvbGwoKTsgfTtcblxuICAvLyBQb2xsIGZvciBpbnB1dCBjaGFuZ2VzLCB1c2luZyB0aGUgbm9ybWFsIHJhdGUgb2YgcG9sbGluZy4gVGhpc1xuICAvLyBydW5zIGFzIGxvbmcgYXMgdGhlIGVkaXRvciBpcyBmb2N1c2VkLlxuICBUZXh0YXJlYUlucHV0LnByb3RvdHlwZS5zbG93UG9sbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciB0aGlzJDEgPSB0aGlzO1xuXG4gICAgaWYgKHRoaXMucG9sbGluZ0Zhc3QpIHsgcmV0dXJuIH1cbiAgICB0aGlzLnBvbGxpbmcuc2V0KHRoaXMuY20ub3B0aW9ucy5wb2xsSW50ZXJ2YWwsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRoaXMkMS5wb2xsKCk7XG4gICAgICBpZiAodGhpcyQxLmNtLnN0YXRlLmZvY3VzZWQpIHsgdGhpcyQxLnNsb3dQb2xsKCk7IH1cbiAgICB9KTtcbiAgfTtcblxuICAvLyBXaGVuIGFuIGV2ZW50IGhhcyBqdXN0IGNvbWUgaW4gdGhhdCBpcyBsaWtlbHkgdG8gYWRkIG9yIGNoYW5nZVxuICAvLyBzb21ldGhpbmcgaW4gdGhlIGlucHV0IHRleHRhcmVhLCB3ZSBwb2xsIGZhc3RlciwgdG8gZW5zdXJlIHRoYXRcbiAgLy8gdGhlIGNoYW5nZSBhcHBlYXJzIG9uIHRoZSBzY3JlZW4gcXVpY2tseS5cbiAgVGV4dGFyZWFJbnB1dC5wcm90b3R5cGUuZmFzdFBvbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIG1pc3NlZCA9IGZhbHNlLCBpbnB1dCA9IHRoaXM7XG4gICAgaW5wdXQucG9sbGluZ0Zhc3QgPSB0cnVlO1xuICAgIGZ1bmN0aW9uIHAoKSB7XG4gICAgICB2YXIgY2hhbmdlZCA9IGlucHV0LnBvbGwoKTtcbiAgICAgIGlmICghY2hhbmdlZCAmJiAhbWlzc2VkKSB7bWlzc2VkID0gdHJ1ZTsgaW5wdXQucG9sbGluZy5zZXQoNjAsIHApO31cbiAgICAgIGVsc2Uge2lucHV0LnBvbGxpbmdGYXN0ID0gZmFsc2U7IGlucHV0LnNsb3dQb2xsKCk7fVxuICAgIH1cbiAgICBpbnB1dC5wb2xsaW5nLnNldCgyMCwgcCk7XG4gIH07XG5cbiAgLy8gUmVhZCBpbnB1dCBmcm9tIHRoZSB0ZXh0YXJlYSwgYW5kIHVwZGF0ZSB0aGUgZG9jdW1lbnQgdG8gbWF0Y2guXG4gIC8vIFdoZW4gc29tZXRoaW5nIGlzIHNlbGVjdGVkLCBpdCBpcyBwcmVzZW50IGluIHRoZSB0ZXh0YXJlYSwgYW5kXG4gIC8vIHNlbGVjdGVkICh1bmxlc3MgaXQgaXMgaHVnZSwgaW4gd2hpY2ggY2FzZSBhIHBsYWNlaG9sZGVyIGlzXG4gIC8vIHVzZWQpLiBXaGVuIG5vdGhpbmcgaXMgc2VsZWN0ZWQsIHRoZSBjdXJzb3Igc2l0cyBhZnRlciBwcmV2aW91c2x5XG4gIC8vIHNlZW4gdGV4dCAoY2FuIGJlIGVtcHR5KSwgd2hpY2ggaXMgc3RvcmVkIGluIHByZXZJbnB1dCAod2UgbXVzdFxuICAvLyBub3QgcmVzZXQgdGhlIHRleHRhcmVhIHdoZW4gdHlwaW5nLCBiZWNhdXNlIHRoYXQgYnJlYWtzIElNRSkuXG4gIFRleHRhcmVhSW5wdXQucHJvdG90eXBlLnBvbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgdGhpcyQxID0gdGhpcztcblxuICAgIHZhciBjbSA9IHRoaXMuY20sIGlucHV0ID0gdGhpcy50ZXh0YXJlYSwgcHJldklucHV0ID0gdGhpcy5wcmV2SW5wdXQ7XG4gICAgLy8gU2luY2UgdGhpcyBpcyBjYWxsZWQgYSAqbG90KiwgdHJ5IHRvIGJhaWwgb3V0IGFzIGNoZWFwbHkgYXNcbiAgICAvLyBwb3NzaWJsZSB3aGVuIGl0IGlzIGNsZWFyIHRoYXQgbm90aGluZyBoYXBwZW5lZC4gaGFzU2VsZWN0aW9uXG4gICAgLy8gd2lsbCBiZSB0aGUgY2FzZSB3aGVuIHRoZXJlIGlzIGEgbG90IG9mIHRleHQgaW4gdGhlIHRleHRhcmVhLFxuICAgIC8vIGluIHdoaWNoIGNhc2UgcmVhZGluZyBpdHMgdmFsdWUgd291bGQgYmUgZXhwZW5zaXZlLlxuICAgIGlmICh0aGlzLmNvbnRleHRNZW51UGVuZGluZyB8fCAhY20uc3RhdGUuZm9jdXNlZCB8fFxuICAgICAgICAoaGFzU2VsZWN0aW9uKGlucHV0KSAmJiAhcHJldklucHV0ICYmICF0aGlzLmNvbXBvc2luZykgfHxcbiAgICAgICAgY20uaXNSZWFkT25seSgpIHx8IGNtLm9wdGlvbnMuZGlzYWJsZUlucHV0IHx8IGNtLnN0YXRlLmtleVNlcSlcbiAgICAgIHsgcmV0dXJuIGZhbHNlIH1cblxuICAgIHZhciB0ZXh0ID0gaW5wdXQudmFsdWU7XG4gICAgLy8gSWYgbm90aGluZyBjaGFuZ2VkLCBiYWlsLlxuICAgIGlmICh0ZXh0ID09IHByZXZJbnB1dCAmJiAhY20uc29tZXRoaW5nU2VsZWN0ZWQoKSkgeyByZXR1cm4gZmFsc2UgfVxuICAgIC8vIFdvcmsgYXJvdW5kIG5vbnNlbnNpY2FsIHNlbGVjdGlvbiByZXNldHRpbmcgaW4gSUU5LzEwLCBhbmRcbiAgICAvLyBpbmV4cGxpY2FibGUgYXBwZWFyYW5jZSBvZiBwcml2YXRlIGFyZWEgdW5pY29kZSBjaGFyYWN0ZXJzIG9uXG4gICAgLy8gc29tZSBrZXkgY29tYm9zIGluIE1hYyAoIzI2ODkpLlxuICAgIGlmIChpZSAmJiBpZV92ZXJzaW9uID49IDkgJiYgdGhpcy5oYXNTZWxlY3Rpb24gPT09IHRleHQgfHxcbiAgICAgICAgbWFjICYmIC9bXFx1ZjcwMC1cXHVmN2ZmXS8udGVzdCh0ZXh0KSkge1xuICAgICAgY20uZGlzcGxheS5pbnB1dC5yZXNldCgpO1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuXG4gICAgaWYgKGNtLmRvYy5zZWwgPT0gY20uZGlzcGxheS5zZWxGb3JDb250ZXh0TWVudSkge1xuICAgICAgdmFyIGZpcnN0ID0gdGV4dC5jaGFyQ29kZUF0KDApO1xuICAgICAgaWYgKGZpcnN0ID09IDB4MjAwYiAmJiAhcHJldklucHV0KSB7IHByZXZJbnB1dCA9IFwiXFx1MjAwYlwiOyB9XG4gICAgICBpZiAoZmlyc3QgPT0gMHgyMWRhKSB7IHRoaXMucmVzZXQoKTsgcmV0dXJuIHRoaXMuY20uZXhlY0NvbW1hbmQoXCJ1bmRvXCIpIH1cbiAgICB9XG4gICAgLy8gRmluZCB0aGUgcGFydCBvZiB0aGUgaW5wdXQgdGhhdCBpcyBhY3R1YWxseSBuZXdcbiAgICB2YXIgc2FtZSA9IDAsIGwgPSBNYXRoLm1pbihwcmV2SW5wdXQubGVuZ3RoLCB0ZXh0Lmxlbmd0aCk7XG4gICAgd2hpbGUgKHNhbWUgPCBsICYmIHByZXZJbnB1dC5jaGFyQ29kZUF0KHNhbWUpID09IHRleHQuY2hhckNvZGVBdChzYW1lKSkgeyArK3NhbWU7IH1cblxuICAgIHJ1bkluT3AoY20sIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFwcGx5VGV4dElucHV0KGNtLCB0ZXh0LnNsaWNlKHNhbWUpLCBwcmV2SW5wdXQubGVuZ3RoIC0gc2FtZSxcbiAgICAgICAgICAgICAgICAgICAgIG51bGwsIHRoaXMkMS5jb21wb3NpbmcgPyBcIipjb21wb3NlXCIgOiBudWxsKTtcblxuICAgICAgLy8gRG9uJ3QgbGVhdmUgbG9uZyB0ZXh0IGluIHRoZSB0ZXh0YXJlYSwgc2luY2UgaXQgbWFrZXMgZnVydGhlciBwb2xsaW5nIHNsb3dcbiAgICAgIGlmICh0ZXh0Lmxlbmd0aCA+IDEwMDAgfHwgdGV4dC5pbmRleE9mKFwiXFxuXCIpID4gLTEpIHsgaW5wdXQudmFsdWUgPSB0aGlzJDEucHJldklucHV0ID0gXCJcIjsgfVxuICAgICAgZWxzZSB7IHRoaXMkMS5wcmV2SW5wdXQgPSB0ZXh0OyB9XG5cbiAgICAgIGlmICh0aGlzJDEuY29tcG9zaW5nKSB7XG4gICAgICAgIHRoaXMkMS5jb21wb3NpbmcucmFuZ2UuY2xlYXIoKTtcbiAgICAgICAgdGhpcyQxLmNvbXBvc2luZy5yYW5nZSA9IGNtLm1hcmtUZXh0KHRoaXMkMS5jb21wb3Npbmcuc3RhcnQsIGNtLmdldEN1cnNvcihcInRvXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtjbGFzc05hbWU6IFwiQ29kZU1pcnJvci1jb21wb3NpbmdcIn0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiB0cnVlXG4gIH07XG5cbiAgVGV4dGFyZWFJbnB1dC5wcm90b3R5cGUuZW5zdXJlUG9sbGVkID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnBvbGxpbmdGYXN0ICYmIHRoaXMucG9sbCgpKSB7IHRoaXMucG9sbGluZ0Zhc3QgPSBmYWxzZTsgfVxuICB9O1xuXG4gIFRleHRhcmVhSW5wdXQucHJvdG90eXBlLm9uS2V5UHJlc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKGllICYmIGllX3ZlcnNpb24gPj0gOSkgeyB0aGlzLmhhc1NlbGVjdGlvbiA9IG51bGw7IH1cbiAgICB0aGlzLmZhc3RQb2xsKCk7XG4gIH07XG5cbiAgVGV4dGFyZWFJbnB1dC5wcm90b3R5cGUub25Db250ZXh0TWVudSA9IGZ1bmN0aW9uIChlKSB7XG4gICAgdmFyIGlucHV0ID0gdGhpcywgY20gPSBpbnB1dC5jbSwgZGlzcGxheSA9IGNtLmRpc3BsYXksIHRlID0gaW5wdXQudGV4dGFyZWE7XG4gICAgaWYgKGlucHV0LmNvbnRleHRNZW51UGVuZGluZykgeyBpbnB1dC5jb250ZXh0TWVudVBlbmRpbmcoKTsgfVxuICAgIHZhciBwb3MgPSBwb3NGcm9tTW91c2UoY20sIGUpLCBzY3JvbGxQb3MgPSBkaXNwbGF5LnNjcm9sbGVyLnNjcm9sbFRvcDtcbiAgICBpZiAoIXBvcyB8fCBwcmVzdG8pIHsgcmV0dXJuIH0gLy8gT3BlcmEgaXMgZGlmZmljdWx0LlxuXG4gICAgLy8gUmVzZXQgdGhlIGN1cnJlbnQgdGV4dCBzZWxlY3Rpb24gb25seSBpZiB0aGUgY2xpY2sgaXMgZG9uZSBvdXRzaWRlIG9mIHRoZSBzZWxlY3Rpb25cbiAgICAvLyBhbmQgJ3Jlc2V0U2VsZWN0aW9uT25Db250ZXh0TWVudScgb3B0aW9uIGlzIHRydWUuXG4gICAgdmFyIHJlc2V0ID0gY20ub3B0aW9ucy5yZXNldFNlbGVjdGlvbk9uQ29udGV4dE1lbnU7XG4gICAgaWYgKHJlc2V0ICYmIGNtLmRvYy5zZWwuY29udGFpbnMocG9zKSA9PSAtMSlcbiAgICAgIHsgb3BlcmF0aW9uKGNtLCBzZXRTZWxlY3Rpb24pKGNtLmRvYywgc2ltcGxlU2VsZWN0aW9uKHBvcyksIHNlbF9kb250U2Nyb2xsKTsgfVxuXG4gICAgdmFyIG9sZENTUyA9IHRlLnN0eWxlLmNzc1RleHQsIG9sZFdyYXBwZXJDU1MgPSBpbnB1dC53cmFwcGVyLnN0eWxlLmNzc1RleHQ7XG4gICAgdmFyIHdyYXBwZXJCb3ggPSBpbnB1dC53cmFwcGVyLm9mZnNldFBhcmVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBpbnB1dC53cmFwcGVyLnN0eWxlLmNzc1RleHQgPSBcInBvc2l0aW9uOiBzdGF0aWNcIjtcbiAgICB0ZS5zdHlsZS5jc3NUZXh0ID0gXCJwb3NpdGlvbjogYWJzb2x1dGU7IHdpZHRoOiAzMHB4OyBoZWlnaHQ6IDMwcHg7XFxuICAgICAgdG9wOiBcIiArIChlLmNsaWVudFkgLSB3cmFwcGVyQm94LnRvcCAtIDUpICsgXCJweDsgbGVmdDogXCIgKyAoZS5jbGllbnRYIC0gd3JhcHBlckJveC5sZWZ0IC0gNSkgKyBcInB4O1xcbiAgICAgIHotaW5kZXg6IDEwMDA7IGJhY2tncm91bmQ6IFwiICsgKGllID8gXCJyZ2JhKDI1NSwgMjU1LCAyNTUsIC4wNSlcIiA6IFwidHJhbnNwYXJlbnRcIikgKyBcIjtcXG4gICAgICBvdXRsaW5lOiBub25lOyBib3JkZXItd2lkdGg6IDA7IG91dGxpbmU6IG5vbmU7IG92ZXJmbG93OiBoaWRkZW47IG9wYWNpdHk6IC4wNTsgZmlsdGVyOiBhbHBoYShvcGFjaXR5PTUpO1wiO1xuICAgIHZhciBvbGRTY3JvbGxZO1xuICAgIGlmICh3ZWJraXQpIHsgb2xkU2Nyb2xsWSA9IHdpbmRvdy5zY3JvbGxZOyB9IC8vIFdvcmsgYXJvdW5kIENocm9tZSBpc3N1ZSAoIzI3MTIpXG4gICAgZGlzcGxheS5pbnB1dC5mb2N1cygpO1xuICAgIGlmICh3ZWJraXQpIHsgd2luZG93LnNjcm9sbFRvKG51bGwsIG9sZFNjcm9sbFkpOyB9XG4gICAgZGlzcGxheS5pbnB1dC5yZXNldCgpO1xuICAgIC8vIEFkZHMgXCJTZWxlY3QgYWxsXCIgdG8gY29udGV4dCBtZW51IGluIEZGXG4gICAgaWYgKCFjbS5zb21ldGhpbmdTZWxlY3RlZCgpKSB7IHRlLnZhbHVlID0gaW5wdXQucHJldklucHV0ID0gXCIgXCI7IH1cbiAgICBpbnB1dC5jb250ZXh0TWVudVBlbmRpbmcgPSByZWhpZGU7XG4gICAgZGlzcGxheS5zZWxGb3JDb250ZXh0TWVudSA9IGNtLmRvYy5zZWw7XG4gICAgY2xlYXJUaW1lb3V0KGRpc3BsYXkuZGV0ZWN0aW5nU2VsZWN0QWxsKTtcblxuICAgIC8vIFNlbGVjdC1hbGwgd2lsbCBiZSBncmV5ZWQgb3V0IGlmIHRoZXJlJ3Mgbm90aGluZyB0byBzZWxlY3QsIHNvXG4gICAgLy8gdGhpcyBhZGRzIGEgemVyby13aWR0aCBzcGFjZSBzbyB0aGF0IHdlIGNhbiBsYXRlciBjaGVjayB3aGV0aGVyXG4gICAgLy8gaXQgZ290IHNlbGVjdGVkLlxuICAgIGZ1bmN0aW9uIHByZXBhcmVTZWxlY3RBbGxIYWNrKCkge1xuICAgICAgaWYgKHRlLnNlbGVjdGlvblN0YXJ0ICE9IG51bGwpIHtcbiAgICAgICAgdmFyIHNlbGVjdGVkID0gY20uc29tZXRoaW5nU2VsZWN0ZWQoKTtcbiAgICAgICAgdmFyIGV4dHZhbCA9IFwiXFx1MjAwYlwiICsgKHNlbGVjdGVkID8gdGUudmFsdWUgOiBcIlwiKTtcbiAgICAgICAgdGUudmFsdWUgPSBcIlxcdTIxZGFcIjsgLy8gVXNlZCB0byBjYXRjaCBjb250ZXh0LW1lbnUgdW5kb1xuICAgICAgICB0ZS52YWx1ZSA9IGV4dHZhbDtcbiAgICAgICAgaW5wdXQucHJldklucHV0ID0gc2VsZWN0ZWQgPyBcIlwiIDogXCJcXHUyMDBiXCI7XG4gICAgICAgIHRlLnNlbGVjdGlvblN0YXJ0ID0gMTsgdGUuc2VsZWN0aW9uRW5kID0gZXh0dmFsLmxlbmd0aDtcbiAgICAgICAgLy8gUmUtc2V0IHRoaXMsIGluIGNhc2Ugc29tZSBvdGhlciBoYW5kbGVyIHRvdWNoZWQgdGhlXG4gICAgICAgIC8vIHNlbGVjdGlvbiBpbiB0aGUgbWVhbnRpbWUuXG4gICAgICAgIGRpc3BsYXkuc2VsRm9yQ29udGV4dE1lbnUgPSBjbS5kb2Muc2VsO1xuICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiByZWhpZGUoKSB7XG4gICAgICBpZiAoaW5wdXQuY29udGV4dE1lbnVQZW5kaW5nICE9IHJlaGlkZSkgeyByZXR1cm4gfVxuICAgICAgaW5wdXQuY29udGV4dE1lbnVQZW5kaW5nID0gZmFsc2U7XG4gICAgICBpbnB1dC53cmFwcGVyLnN0eWxlLmNzc1RleHQgPSBvbGRXcmFwcGVyQ1NTO1xuICAgICAgdGUuc3R5bGUuY3NzVGV4dCA9IG9sZENTUztcbiAgICAgIGlmIChpZSAmJiBpZV92ZXJzaW9uIDwgOSkgeyBkaXNwbGF5LnNjcm9sbGJhcnMuc2V0U2Nyb2xsVG9wKGRpc3BsYXkuc2Nyb2xsZXIuc2Nyb2xsVG9wID0gc2Nyb2xsUG9zKTsgfVxuXG4gICAgICAvLyBUcnkgdG8gZGV0ZWN0IHRoZSB1c2VyIGNob29zaW5nIHNlbGVjdC1hbGxcbiAgICAgIGlmICh0ZS5zZWxlY3Rpb25TdGFydCAhPSBudWxsKSB7XG4gICAgICAgIGlmICghaWUgfHwgKGllICYmIGllX3ZlcnNpb24gPCA5KSkgeyBwcmVwYXJlU2VsZWN0QWxsSGFjaygpOyB9XG4gICAgICAgIHZhciBpID0gMCwgcG9sbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBpZiAoZGlzcGxheS5zZWxGb3JDb250ZXh0TWVudSA9PSBjbS5kb2Muc2VsICYmIHRlLnNlbGVjdGlvblN0YXJ0ID09IDAgJiZcbiAgICAgICAgICAgICAgdGUuc2VsZWN0aW9uRW5kID4gMCAmJiBpbnB1dC5wcmV2SW5wdXQgPT0gXCJcXHUyMDBiXCIpIHtcbiAgICAgICAgICAgIG9wZXJhdGlvbihjbSwgc2VsZWN0QWxsKShjbSk7XG4gICAgICAgICAgfSBlbHNlIGlmIChpKysgPCAxMCkge1xuICAgICAgICAgICAgZGlzcGxheS5kZXRlY3RpbmdTZWxlY3RBbGwgPSBzZXRUaW1lb3V0KHBvbGwsIDUwMCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRpc3BsYXkuc2VsRm9yQ29udGV4dE1lbnUgPSBudWxsO1xuICAgICAgICAgICAgZGlzcGxheS5pbnB1dC5yZXNldCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgZGlzcGxheS5kZXRlY3RpbmdTZWxlY3RBbGwgPSBzZXRUaW1lb3V0KHBvbGwsIDIwMCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGllICYmIGllX3ZlcnNpb24gPj0gOSkgeyBwcmVwYXJlU2VsZWN0QWxsSGFjaygpOyB9XG4gICAgaWYgKGNhcHR1cmVSaWdodENsaWNrKSB7XG4gICAgICBlX3N0b3AoZSk7XG4gICAgICB2YXIgbW91c2V1cCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgb2ZmKHdpbmRvdywgXCJtb3VzZXVwXCIsIG1vdXNldXApO1xuICAgICAgICBzZXRUaW1lb3V0KHJlaGlkZSwgMjApO1xuICAgICAgfTtcbiAgICAgIG9uKHdpbmRvdywgXCJtb3VzZXVwXCIsIG1vdXNldXApO1xuICAgIH0gZWxzZSB7XG4gICAgICBzZXRUaW1lb3V0KHJlaGlkZSwgNTApO1xuICAgIH1cbiAgfTtcblxuICBUZXh0YXJlYUlucHV0LnByb3RvdHlwZS5yZWFkT25seUNoYW5nZWQgPSBmdW5jdGlvbiAodmFsKSB7XG4gICAgaWYgKCF2YWwpIHsgdGhpcy5yZXNldCgpOyB9XG4gICAgdGhpcy50ZXh0YXJlYS5kaXNhYmxlZCA9IHZhbCA9PSBcIm5vY3Vyc29yXCI7XG4gICAgdGhpcy50ZXh0YXJlYS5yZWFkT25seSA9ICEhdmFsO1xuICB9O1xuXG4gIFRleHRhcmVhSW5wdXQucHJvdG90eXBlLnNldFVuZWRpdGFibGUgPSBmdW5jdGlvbiAoKSB7fTtcblxuICBUZXh0YXJlYUlucHV0LnByb3RvdHlwZS5uZWVkc0NvbnRlbnRBdHRyaWJ1dGUgPSBmYWxzZTtcblxuICBmdW5jdGlvbiBmcm9tVGV4dEFyZWEodGV4dGFyZWEsIG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyA/IGNvcHlPYmoob3B0aW9ucykgOiB7fTtcbiAgICBvcHRpb25zLnZhbHVlID0gdGV4dGFyZWEudmFsdWU7XG4gICAgaWYgKCFvcHRpb25zLnRhYmluZGV4ICYmIHRleHRhcmVhLnRhYkluZGV4KVxuICAgICAgeyBvcHRpb25zLnRhYmluZGV4ID0gdGV4dGFyZWEudGFiSW5kZXg7IH1cbiAgICBpZiAoIW9wdGlvbnMucGxhY2Vob2xkZXIgJiYgdGV4dGFyZWEucGxhY2Vob2xkZXIpXG4gICAgICB7IG9wdGlvbnMucGxhY2Vob2xkZXIgPSB0ZXh0YXJlYS5wbGFjZWhvbGRlcjsgfVxuICAgIC8vIFNldCBhdXRvZm9jdXMgdG8gdHJ1ZSBpZiB0aGlzIHRleHRhcmVhIGlzIGZvY3VzZWQsIG9yIGlmIGl0IGhhc1xuICAgIC8vIGF1dG9mb2N1cyBhbmQgbm8gb3RoZXIgZWxlbWVudCBpcyBmb2N1c2VkLlxuICAgIGlmIChvcHRpb25zLmF1dG9mb2N1cyA9PSBudWxsKSB7XG4gICAgICB2YXIgaGFzRm9jdXMgPSBhY3RpdmVFbHQoKTtcbiAgICAgIG9wdGlvbnMuYXV0b2ZvY3VzID0gaGFzRm9jdXMgPT0gdGV4dGFyZWEgfHxcbiAgICAgICAgdGV4dGFyZWEuZ2V0QXR0cmlidXRlKFwiYXV0b2ZvY3VzXCIpICE9IG51bGwgJiYgaGFzRm9jdXMgPT0gZG9jdW1lbnQuYm9keTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzYXZlKCkge3RleHRhcmVhLnZhbHVlID0gY20uZ2V0VmFsdWUoKTt9XG5cbiAgICB2YXIgcmVhbFN1Ym1pdDtcbiAgICBpZiAodGV4dGFyZWEuZm9ybSkge1xuICAgICAgb24odGV4dGFyZWEuZm9ybSwgXCJzdWJtaXRcIiwgc2F2ZSk7XG4gICAgICAvLyBEZXBsb3JhYmxlIGhhY2sgdG8gbWFrZSB0aGUgc3VibWl0IG1ldGhvZCBkbyB0aGUgcmlnaHQgdGhpbmcuXG4gICAgICBpZiAoIW9wdGlvbnMubGVhdmVTdWJtaXRNZXRob2RBbG9uZSkge1xuICAgICAgICB2YXIgZm9ybSA9IHRleHRhcmVhLmZvcm07XG4gICAgICAgIHJlYWxTdWJtaXQgPSBmb3JtLnN1Ym1pdDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB2YXIgd3JhcHBlZFN1Ym1pdCA9IGZvcm0uc3VibWl0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc2F2ZSgpO1xuICAgICAgICAgICAgZm9ybS5zdWJtaXQgPSByZWFsU3VibWl0O1xuICAgICAgICAgICAgZm9ybS5zdWJtaXQoKTtcbiAgICAgICAgICAgIGZvcm0uc3VibWl0ID0gd3JhcHBlZFN1Ym1pdDtcbiAgICAgICAgICB9O1xuICAgICAgICB9IGNhdGNoKGUpIHt9XG4gICAgICB9XG4gICAgfVxuXG4gICAgb3B0aW9ucy5maW5pc2hJbml0ID0gZnVuY3Rpb24gKGNtKSB7XG4gICAgICBjbS5zYXZlID0gc2F2ZTtcbiAgICAgIGNtLmdldFRleHRBcmVhID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGV4dGFyZWE7IH07XG4gICAgICBjbS50b1RleHRBcmVhID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjbS50b1RleHRBcmVhID0gaXNOYU47IC8vIFByZXZlbnQgdGhpcyBmcm9tIGJlaW5nIHJhbiB0d2ljZVxuICAgICAgICBzYXZlKCk7XG4gICAgICAgIHRleHRhcmVhLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoY20uZ2V0V3JhcHBlckVsZW1lbnQoKSk7XG4gICAgICAgIHRleHRhcmVhLnN0eWxlLmRpc3BsYXkgPSBcIlwiO1xuICAgICAgICBpZiAodGV4dGFyZWEuZm9ybSkge1xuICAgICAgICAgIG9mZih0ZXh0YXJlYS5mb3JtLCBcInN1Ym1pdFwiLCBzYXZlKTtcbiAgICAgICAgICBpZiAoIW9wdGlvbnMubGVhdmVTdWJtaXRNZXRob2RBbG9uZSAmJiB0eXBlb2YgdGV4dGFyZWEuZm9ybS5zdWJtaXQgPT0gXCJmdW5jdGlvblwiKVxuICAgICAgICAgICAgeyB0ZXh0YXJlYS5mb3JtLnN1Ym1pdCA9IHJlYWxTdWJtaXQ7IH1cbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9O1xuXG4gICAgdGV4dGFyZWEuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgIHZhciBjbSA9IENvZGVNaXJyb3IoZnVuY3Rpb24gKG5vZGUpIHsgcmV0dXJuIHRleHRhcmVhLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIHRleHRhcmVhLm5leHRTaWJsaW5nKTsgfSxcbiAgICAgIG9wdGlvbnMpO1xuICAgIHJldHVybiBjbVxuICB9XG5cbiAgZnVuY3Rpb24gYWRkTGVnYWN5UHJvcHMoQ29kZU1pcnJvcikge1xuICAgIENvZGVNaXJyb3Iub2ZmID0gb2ZmO1xuICAgIENvZGVNaXJyb3Iub24gPSBvbjtcbiAgICBDb2RlTWlycm9yLndoZWVsRXZlbnRQaXhlbHMgPSB3aGVlbEV2ZW50UGl4ZWxzO1xuICAgIENvZGVNaXJyb3IuRG9jID0gRG9jO1xuICAgIENvZGVNaXJyb3Iuc3BsaXRMaW5lcyA9IHNwbGl0TGluZXNBdXRvO1xuICAgIENvZGVNaXJyb3IuY291bnRDb2x1bW4gPSBjb3VudENvbHVtbjtcbiAgICBDb2RlTWlycm9yLmZpbmRDb2x1bW4gPSBmaW5kQ29sdW1uO1xuICAgIENvZGVNaXJyb3IuaXNXb3JkQ2hhciA9IGlzV29yZENoYXJCYXNpYztcbiAgICBDb2RlTWlycm9yLlBhc3MgPSBQYXNzO1xuICAgIENvZGVNaXJyb3Iuc2lnbmFsID0gc2lnbmFsO1xuICAgIENvZGVNaXJyb3IuTGluZSA9IExpbmU7XG4gICAgQ29kZU1pcnJvci5jaGFuZ2VFbmQgPSBjaGFuZ2VFbmQ7XG4gICAgQ29kZU1pcnJvci5zY3JvbGxiYXJNb2RlbCA9IHNjcm9sbGJhck1vZGVsO1xuICAgIENvZGVNaXJyb3IuUG9zID0gUG9zO1xuICAgIENvZGVNaXJyb3IuY21wUG9zID0gY21wO1xuICAgIENvZGVNaXJyb3IubW9kZXMgPSBtb2RlcztcbiAgICBDb2RlTWlycm9yLm1pbWVNb2RlcyA9IG1pbWVNb2RlcztcbiAgICBDb2RlTWlycm9yLnJlc29sdmVNb2RlID0gcmVzb2x2ZU1vZGU7XG4gICAgQ29kZU1pcnJvci5nZXRNb2RlID0gZ2V0TW9kZTtcbiAgICBDb2RlTWlycm9yLm1vZGVFeHRlbnNpb25zID0gbW9kZUV4dGVuc2lvbnM7XG4gICAgQ29kZU1pcnJvci5leHRlbmRNb2RlID0gZXh0ZW5kTW9kZTtcbiAgICBDb2RlTWlycm9yLmNvcHlTdGF0ZSA9IGNvcHlTdGF0ZTtcbiAgICBDb2RlTWlycm9yLnN0YXJ0U3RhdGUgPSBzdGFydFN0YXRlO1xuICAgIENvZGVNaXJyb3IuaW5uZXJNb2RlID0gaW5uZXJNb2RlO1xuICAgIENvZGVNaXJyb3IuY29tbWFuZHMgPSBjb21tYW5kcztcbiAgICBDb2RlTWlycm9yLmtleU1hcCA9IGtleU1hcDtcbiAgICBDb2RlTWlycm9yLmtleU5hbWUgPSBrZXlOYW1lO1xuICAgIENvZGVNaXJyb3IuaXNNb2RpZmllcktleSA9IGlzTW9kaWZpZXJLZXk7XG4gICAgQ29kZU1pcnJvci5sb29rdXBLZXkgPSBsb29rdXBLZXk7XG4gICAgQ29kZU1pcnJvci5ub3JtYWxpemVLZXlNYXAgPSBub3JtYWxpemVLZXlNYXA7XG4gICAgQ29kZU1pcnJvci5TdHJpbmdTdHJlYW0gPSBTdHJpbmdTdHJlYW07XG4gICAgQ29kZU1pcnJvci5TaGFyZWRUZXh0TWFya2VyID0gU2hhcmVkVGV4dE1hcmtlcjtcbiAgICBDb2RlTWlycm9yLlRleHRNYXJrZXIgPSBUZXh0TWFya2VyO1xuICAgIENvZGVNaXJyb3IuTGluZVdpZGdldCA9IExpbmVXaWRnZXQ7XG4gICAgQ29kZU1pcnJvci5lX3ByZXZlbnREZWZhdWx0ID0gZV9wcmV2ZW50RGVmYXVsdDtcbiAgICBDb2RlTWlycm9yLmVfc3RvcFByb3BhZ2F0aW9uID0gZV9zdG9wUHJvcGFnYXRpb247XG4gICAgQ29kZU1pcnJvci5lX3N0b3AgPSBlX3N0b3A7XG4gICAgQ29kZU1pcnJvci5hZGRDbGFzcyA9IGFkZENsYXNzO1xuICAgIENvZGVNaXJyb3IuY29udGFpbnMgPSBjb250YWlucztcbiAgICBDb2RlTWlycm9yLnJtQ2xhc3MgPSBybUNsYXNzO1xuICAgIENvZGVNaXJyb3Iua2V5TmFtZXMgPSBrZXlOYW1lcztcbiAgfVxuXG4gIC8vIEVESVRPUiBDT05TVFJVQ1RPUlxuXG4gIGRlZmluZU9wdGlvbnMoQ29kZU1pcnJvcik7XG5cbiAgYWRkRWRpdG9yTWV0aG9kcyhDb2RlTWlycm9yKTtcblxuICAvLyBTZXQgdXAgbWV0aG9kcyBvbiBDb2RlTWlycm9yJ3MgcHJvdG90eXBlIHRvIHJlZGlyZWN0IHRvIHRoZSBlZGl0b3IncyBkb2N1bWVudC5cbiAgdmFyIGRvbnREZWxlZ2F0ZSA9IFwiaXRlciBpbnNlcnQgcmVtb3ZlIGNvcHkgZ2V0RWRpdG9yIGNvbnN0cnVjdG9yXCIuc3BsaXQoXCIgXCIpO1xuICBmb3IgKHZhciBwcm9wIGluIERvYy5wcm90b3R5cGUpIHsgaWYgKERvYy5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkocHJvcCkgJiYgaW5kZXhPZihkb250RGVsZWdhdGUsIHByb3ApIDwgMClcbiAgICB7IENvZGVNaXJyb3IucHJvdG90eXBlW3Byb3BdID0gKGZ1bmN0aW9uKG1ldGhvZCkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge3JldHVybiBtZXRob2QuYXBwbHkodGhpcy5kb2MsIGFyZ3VtZW50cyl9XG4gICAgfSkoRG9jLnByb3RvdHlwZVtwcm9wXSk7IH0gfVxuXG4gIGV2ZW50TWl4aW4oRG9jKTtcbiAgQ29kZU1pcnJvci5pbnB1dFN0eWxlcyA9IHtcInRleHRhcmVhXCI6IFRleHRhcmVhSW5wdXQsIFwiY29udGVudGVkaXRhYmxlXCI6IENvbnRlbnRFZGl0YWJsZUlucHV0fTtcblxuICAvLyBFeHRyYSBhcmd1bWVudHMgYXJlIHN0b3JlZCBhcyB0aGUgbW9kZSdzIGRlcGVuZGVuY2llcywgd2hpY2ggaXNcbiAgLy8gdXNlZCBieSAobGVnYWN5KSBtZWNoYW5pc21zIGxpa2UgbG9hZG1vZGUuanMgdG8gYXV0b21hdGljYWxseVxuICAvLyBsb2FkIGEgbW9kZS4gKFByZWZlcnJlZCBtZWNoYW5pc20gaXMgdGhlIHJlcXVpcmUvZGVmaW5lIGNhbGxzLilcbiAgQ29kZU1pcnJvci5kZWZpbmVNb2RlID0gZnVuY3Rpb24obmFtZS8qLCBtb2RlLCDigKYqLykge1xuICAgIGlmICghQ29kZU1pcnJvci5kZWZhdWx0cy5tb2RlICYmIG5hbWUgIT0gXCJudWxsXCIpIHsgQ29kZU1pcnJvci5kZWZhdWx0cy5tb2RlID0gbmFtZTsgfVxuICAgIGRlZmluZU1vZGUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgfTtcblxuICBDb2RlTWlycm9yLmRlZmluZU1JTUUgPSBkZWZpbmVNSU1FO1xuXG4gIC8vIE1pbmltYWwgZGVmYXVsdCBtb2RlLlxuICBDb2RlTWlycm9yLmRlZmluZU1vZGUoXCJudWxsXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuICh7dG9rZW46IGZ1bmN0aW9uIChzdHJlYW0pIHsgcmV0dXJuIHN0cmVhbS5za2lwVG9FbmQoKTsgfX0pOyB9KTtcbiAgQ29kZU1pcnJvci5kZWZpbmVNSU1FKFwidGV4dC9wbGFpblwiLCBcIm51bGxcIik7XG5cbiAgLy8gRVhURU5TSU9OU1xuXG4gIENvZGVNaXJyb3IuZGVmaW5lRXh0ZW5zaW9uID0gZnVuY3Rpb24gKG5hbWUsIGZ1bmMpIHtcbiAgICBDb2RlTWlycm9yLnByb3RvdHlwZVtuYW1lXSA9IGZ1bmM7XG4gIH07XG4gIENvZGVNaXJyb3IuZGVmaW5lRG9jRXh0ZW5zaW9uID0gZnVuY3Rpb24gKG5hbWUsIGZ1bmMpIHtcbiAgICBEb2MucHJvdG90eXBlW25hbWVdID0gZnVuYztcbiAgfTtcblxuICBDb2RlTWlycm9yLmZyb21UZXh0QXJlYSA9IGZyb21UZXh0QXJlYTtcblxuICBhZGRMZWdhY3lQcm9wcyhDb2RlTWlycm9yKTtcblxuICBDb2RlTWlycm9yLnZlcnNpb24gPSBcIjUuNjUuNVwiO1xuXG4gIHJldHVybiBDb2RlTWlycm9yO1xuXG59KSkpO1xuIiwiLy8gQ29kZU1pcnJvciwgY29weXJpZ2h0IChjKSBieSBNYXJpam4gSGF2ZXJiZWtlIGFuZCBvdGhlcnNcbi8vIERpc3RyaWJ1dGVkIHVuZGVyIGFuIE1JVCBsaWNlbnNlOiBodHRwczovL2NvZGVtaXJyb3IubmV0L0xJQ0VOU0VcblxuKGZ1bmN0aW9uKG1vZCkge1xuICBpZiAodHlwZW9mIGV4cG9ydHMgPT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlID09IFwib2JqZWN0XCIpIC8vIENvbW1vbkpTXG4gICAgbW9kKHJlcXVpcmUoXCIuLi8uLi9saWIvY29kZW1pcnJvclwiKSk7XG4gIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIC8vIEFNRFxuICAgIGRlZmluZShbXCIuLi8uLi9saWIvY29kZW1pcnJvclwiXSwgbW9kKTtcbiAgZWxzZSAvLyBQbGFpbiBicm93c2VyIGVudlxuICAgIG1vZChDb2RlTWlycm9yKTtcbn0pKGZ1bmN0aW9uKENvZGVNaXJyb3IpIHtcblwidXNlIHN0cmljdFwiO1xuXG5mdW5jdGlvbiBDb250ZXh0KGluZGVudGVkLCBjb2x1bW4sIHR5cGUsIGluZm8sIGFsaWduLCBwcmV2KSB7XG4gIHRoaXMuaW5kZW50ZWQgPSBpbmRlbnRlZDtcbiAgdGhpcy5jb2x1bW4gPSBjb2x1bW47XG4gIHRoaXMudHlwZSA9IHR5cGU7XG4gIHRoaXMuaW5mbyA9IGluZm87XG4gIHRoaXMuYWxpZ24gPSBhbGlnbjtcbiAgdGhpcy5wcmV2ID0gcHJldjtcbn1cbmZ1bmN0aW9uIHB1c2hDb250ZXh0KHN0YXRlLCBjb2wsIHR5cGUsIGluZm8pIHtcbiAgdmFyIGluZGVudCA9IHN0YXRlLmluZGVudGVkO1xuICBpZiAoc3RhdGUuY29udGV4dCAmJiBzdGF0ZS5jb250ZXh0LnR5cGUgPT0gXCJzdGF0ZW1lbnRcIiAmJiB0eXBlICE9IFwic3RhdGVtZW50XCIpXG4gICAgaW5kZW50ID0gc3RhdGUuY29udGV4dC5pbmRlbnRlZDtcbiAgcmV0dXJuIHN0YXRlLmNvbnRleHQgPSBuZXcgQ29udGV4dChpbmRlbnQsIGNvbCwgdHlwZSwgaW5mbywgbnVsbCwgc3RhdGUuY29udGV4dCk7XG59XG5mdW5jdGlvbiBwb3BDb250ZXh0KHN0YXRlKSB7XG4gIHZhciB0ID0gc3RhdGUuY29udGV4dC50eXBlO1xuICBpZiAodCA9PSBcIilcIiB8fCB0ID09IFwiXVwiIHx8IHQgPT0gXCJ9XCIpXG4gICAgc3RhdGUuaW5kZW50ZWQgPSBzdGF0ZS5jb250ZXh0LmluZGVudGVkO1xuICByZXR1cm4gc3RhdGUuY29udGV4dCA9IHN0YXRlLmNvbnRleHQucHJldjtcbn1cblxuZnVuY3Rpb24gdHlwZUJlZm9yZShzdHJlYW0sIHN0YXRlLCBwb3MpIHtcbiAgaWYgKHN0YXRlLnByZXZUb2tlbiA9PSBcInZhcmlhYmxlXCIgfHwgc3RhdGUucHJldlRva2VuID09IFwidHlwZVwiKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKC9cXFMoPzpbXi0gXT58WypcXF1dKVxccyokfFxcKiQvLnRlc3Qoc3RyZWFtLnN0cmluZy5zbGljZSgwLCBwb3MpKSkgcmV0dXJuIHRydWU7XG4gIGlmIChzdGF0ZS50eXBlQXRFbmRPZkxpbmUgJiYgc3RyZWFtLmNvbHVtbigpID09IHN0cmVhbS5pbmRlbnRhdGlvbigpKSByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gaXNUb3BTY29wZShjb250ZXh0KSB7XG4gIGZvciAoOzspIHtcbiAgICBpZiAoIWNvbnRleHQgfHwgY29udGV4dC50eXBlID09IFwidG9wXCIpIHJldHVybiB0cnVlO1xuICAgIGlmIChjb250ZXh0LnR5cGUgPT0gXCJ9XCIgJiYgY29udGV4dC5wcmV2LmluZm8gIT0gXCJuYW1lc3BhY2VcIikgcmV0dXJuIGZhbHNlO1xuICAgIGNvbnRleHQgPSBjb250ZXh0LnByZXY7XG4gIH1cbn1cblxuQ29kZU1pcnJvci5kZWZpbmVNb2RlKFwiY2xpa2VcIiwgZnVuY3Rpb24oY29uZmlnLCBwYXJzZXJDb25maWcpIHtcbiAgdmFyIGluZGVudFVuaXQgPSBjb25maWcuaW5kZW50VW5pdCxcbiAgICAgIHN0YXRlbWVudEluZGVudFVuaXQgPSBwYXJzZXJDb25maWcuc3RhdGVtZW50SW5kZW50VW5pdCB8fCBpbmRlbnRVbml0LFxuICAgICAgZG9udEFsaWduQ2FsbHMgPSBwYXJzZXJDb25maWcuZG9udEFsaWduQ2FsbHMsXG4gICAgICBrZXl3b3JkcyA9IHBhcnNlckNvbmZpZy5rZXl3b3JkcyB8fCB7fSxcbiAgICAgIHR5cGVzID0gcGFyc2VyQ29uZmlnLnR5cGVzIHx8IHt9LFxuICAgICAgYnVpbHRpbiA9IHBhcnNlckNvbmZpZy5idWlsdGluIHx8IHt9LFxuICAgICAgYmxvY2tLZXl3b3JkcyA9IHBhcnNlckNvbmZpZy5ibG9ja0tleXdvcmRzIHx8IHt9LFxuICAgICAgZGVmS2V5d29yZHMgPSBwYXJzZXJDb25maWcuZGVmS2V5d29yZHMgfHwge30sXG4gICAgICBhdG9tcyA9IHBhcnNlckNvbmZpZy5hdG9tcyB8fCB7fSxcbiAgICAgIGhvb2tzID0gcGFyc2VyQ29uZmlnLmhvb2tzIHx8IHt9LFxuICAgICAgbXVsdGlMaW5lU3RyaW5ncyA9IHBhcnNlckNvbmZpZy5tdWx0aUxpbmVTdHJpbmdzLFxuICAgICAgaW5kZW50U3RhdGVtZW50cyA9IHBhcnNlckNvbmZpZy5pbmRlbnRTdGF0ZW1lbnRzICE9PSBmYWxzZSxcbiAgICAgIGluZGVudFN3aXRjaCA9IHBhcnNlckNvbmZpZy5pbmRlbnRTd2l0Y2ggIT09IGZhbHNlLFxuICAgICAgbmFtZXNwYWNlU2VwYXJhdG9yID0gcGFyc2VyQ29uZmlnLm5hbWVzcGFjZVNlcGFyYXRvcixcbiAgICAgIGlzUHVuY3R1YXRpb25DaGFyID0gcGFyc2VyQ29uZmlnLmlzUHVuY3R1YXRpb25DaGFyIHx8IC9bXFxbXFxde31cXChcXCksO1xcOlxcLl0vLFxuICAgICAgbnVtYmVyU3RhcnQgPSBwYXJzZXJDb25maWcubnVtYmVyU3RhcnQgfHwgL1tcXGRcXC5dLyxcbiAgICAgIG51bWJlciA9IHBhcnNlckNvbmZpZy5udW1iZXIgfHwgL14oPzoweFthLWZcXGRdK3wwYlswMV0rfCg/OlxcZCtcXC4/XFxkKnxcXC5cXGQrKSg/OmVbLStdP1xcZCspPykodXxsbD98bHxmKT8vaSxcbiAgICAgIGlzT3BlcmF0b3JDaGFyID0gcGFyc2VyQ29uZmlnLmlzT3BlcmF0b3JDaGFyIHx8IC9bK1xcLSomJT08PiE/fFxcL10vLFxuICAgICAgaXNJZGVudGlmaWVyQ2hhciA9IHBhcnNlckNvbmZpZy5pc0lkZW50aWZpZXJDaGFyIHx8IC9bXFx3XFwkX1xceGExLVxcdWZmZmZdLyxcbiAgICAgIC8vIEFuIG9wdGlvbmFsIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYSB7c3RyaW5nfSB0b2tlbiBhbmQgcmV0dXJucyB0cnVlIGlmIGl0XG4gICAgICAvLyBzaG91bGQgYmUgdHJlYXRlZCBhcyBhIGJ1aWx0aW4uXG4gICAgICBpc1Jlc2VydmVkSWRlbnRpZmllciA9IHBhcnNlckNvbmZpZy5pc1Jlc2VydmVkSWRlbnRpZmllciB8fCBmYWxzZTtcblxuICB2YXIgY3VyUHVuYywgaXNEZWZLZXl3b3JkO1xuXG4gIGZ1bmN0aW9uIHRva2VuQmFzZShzdHJlYW0sIHN0YXRlKSB7XG4gICAgdmFyIGNoID0gc3RyZWFtLm5leHQoKTtcbiAgICBpZiAoaG9va3NbY2hdKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gaG9va3NbY2hdKHN0cmVhbSwgc3RhdGUpO1xuICAgICAgaWYgKHJlc3VsdCAhPT0gZmFsc2UpIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICAgIGlmIChjaCA9PSAnXCInIHx8IGNoID09IFwiJ1wiKSB7XG4gICAgICBzdGF0ZS50b2tlbml6ZSA9IHRva2VuU3RyaW5nKGNoKTtcbiAgICAgIHJldHVybiBzdGF0ZS50b2tlbml6ZShzdHJlYW0sIHN0YXRlKTtcbiAgICB9XG4gICAgaWYgKG51bWJlclN0YXJ0LnRlc3QoY2gpKSB7XG4gICAgICBzdHJlYW0uYmFja1VwKDEpXG4gICAgICBpZiAoc3RyZWFtLm1hdGNoKG51bWJlcikpIHJldHVybiBcIm51bWJlclwiXG4gICAgICBzdHJlYW0ubmV4dCgpXG4gICAgfVxuICAgIGlmIChpc1B1bmN0dWF0aW9uQ2hhci50ZXN0KGNoKSkge1xuICAgICAgY3VyUHVuYyA9IGNoO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmIChjaCA9PSBcIi9cIikge1xuICAgICAgaWYgKHN0cmVhbS5lYXQoXCIqXCIpKSB7XG4gICAgICAgIHN0YXRlLnRva2VuaXplID0gdG9rZW5Db21tZW50O1xuICAgICAgICByZXR1cm4gdG9rZW5Db21tZW50KHN0cmVhbSwgc3RhdGUpO1xuICAgICAgfVxuICAgICAgaWYgKHN0cmVhbS5lYXQoXCIvXCIpKSB7XG4gICAgICAgIHN0cmVhbS5za2lwVG9FbmQoKTtcbiAgICAgICAgcmV0dXJuIFwiY29tbWVudFwiO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoaXNPcGVyYXRvckNoYXIudGVzdChjaCkpIHtcbiAgICAgIHdoaWxlICghc3RyZWFtLm1hdGNoKC9eXFwvW1xcLypdLywgZmFsc2UpICYmIHN0cmVhbS5lYXQoaXNPcGVyYXRvckNoYXIpKSB7fVxuICAgICAgcmV0dXJuIFwib3BlcmF0b3JcIjtcbiAgICB9XG4gICAgc3RyZWFtLmVhdFdoaWxlKGlzSWRlbnRpZmllckNoYXIpO1xuICAgIGlmIChuYW1lc3BhY2VTZXBhcmF0b3IpIHdoaWxlIChzdHJlYW0ubWF0Y2gobmFtZXNwYWNlU2VwYXJhdG9yKSlcbiAgICAgIHN0cmVhbS5lYXRXaGlsZShpc0lkZW50aWZpZXJDaGFyKTtcblxuICAgIHZhciBjdXIgPSBzdHJlYW0uY3VycmVudCgpO1xuICAgIGlmIChjb250YWlucyhrZXl3b3JkcywgY3VyKSkge1xuICAgICAgaWYgKGNvbnRhaW5zKGJsb2NrS2V5d29yZHMsIGN1cikpIGN1clB1bmMgPSBcIm5ld3N0YXRlbWVudFwiO1xuICAgICAgaWYgKGNvbnRhaW5zKGRlZktleXdvcmRzLCBjdXIpKSBpc0RlZktleXdvcmQgPSB0cnVlO1xuICAgICAgcmV0dXJuIFwia2V5d29yZFwiO1xuICAgIH1cbiAgICBpZiAoY29udGFpbnModHlwZXMsIGN1cikpIHJldHVybiBcInR5cGVcIjtcbiAgICBpZiAoY29udGFpbnMoYnVpbHRpbiwgY3VyKVxuICAgICAgICB8fCAoaXNSZXNlcnZlZElkZW50aWZpZXIgJiYgaXNSZXNlcnZlZElkZW50aWZpZXIoY3VyKSkpIHtcbiAgICAgIGlmIChjb250YWlucyhibG9ja0tleXdvcmRzLCBjdXIpKSBjdXJQdW5jID0gXCJuZXdzdGF0ZW1lbnRcIjtcbiAgICAgIHJldHVybiBcImJ1aWx0aW5cIjtcbiAgICB9XG4gICAgaWYgKGNvbnRhaW5zKGF0b21zLCBjdXIpKSByZXR1cm4gXCJhdG9tXCI7XG4gICAgcmV0dXJuIFwidmFyaWFibGVcIjtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRva2VuU3RyaW5nKHF1b3RlKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgIHZhciBlc2NhcGVkID0gZmFsc2UsIG5leHQsIGVuZCA9IGZhbHNlO1xuICAgICAgd2hpbGUgKChuZXh0ID0gc3RyZWFtLm5leHQoKSkgIT0gbnVsbCkge1xuICAgICAgICBpZiAobmV4dCA9PSBxdW90ZSAmJiAhZXNjYXBlZCkge2VuZCA9IHRydWU7IGJyZWFrO31cbiAgICAgICAgZXNjYXBlZCA9ICFlc2NhcGVkICYmIG5leHQgPT0gXCJcXFxcXCI7XG4gICAgICB9XG4gICAgICBpZiAoZW5kIHx8ICEoZXNjYXBlZCB8fCBtdWx0aUxpbmVTdHJpbmdzKSlcbiAgICAgICAgc3RhdGUudG9rZW5pemUgPSBudWxsO1xuICAgICAgcmV0dXJuIFwic3RyaW5nXCI7XG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRva2VuQ29tbWVudChzdHJlYW0sIHN0YXRlKSB7XG4gICAgdmFyIG1heWJlRW5kID0gZmFsc2UsIGNoO1xuICAgIHdoaWxlIChjaCA9IHN0cmVhbS5uZXh0KCkpIHtcbiAgICAgIGlmIChjaCA9PSBcIi9cIiAmJiBtYXliZUVuZCkge1xuICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IG51bGw7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgbWF5YmVFbmQgPSAoY2ggPT0gXCIqXCIpO1xuICAgIH1cbiAgICByZXR1cm4gXCJjb21tZW50XCI7XG4gIH1cblxuICBmdW5jdGlvbiBtYXliZUVPTChzdHJlYW0sIHN0YXRlKSB7XG4gICAgaWYgKHBhcnNlckNvbmZpZy50eXBlRmlyc3REZWZpbml0aW9ucyAmJiBzdHJlYW0uZW9sKCkgJiYgaXNUb3BTY29wZShzdGF0ZS5jb250ZXh0KSlcbiAgICAgIHN0YXRlLnR5cGVBdEVuZE9mTGluZSA9IHR5cGVCZWZvcmUoc3RyZWFtLCBzdGF0ZSwgc3RyZWFtLnBvcylcbiAgfVxuXG4gIC8vIEludGVyZmFjZVxuXG4gIHJldHVybiB7XG4gICAgc3RhcnRTdGF0ZTogZnVuY3Rpb24oYmFzZWNvbHVtbikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdG9rZW5pemU6IG51bGwsXG4gICAgICAgIGNvbnRleHQ6IG5ldyBDb250ZXh0KChiYXNlY29sdW1uIHx8IDApIC0gaW5kZW50VW5pdCwgMCwgXCJ0b3BcIiwgbnVsbCwgZmFsc2UpLFxuICAgICAgICBpbmRlbnRlZDogMCxcbiAgICAgICAgc3RhcnRPZkxpbmU6IHRydWUsXG4gICAgICAgIHByZXZUb2tlbjogbnVsbFxuICAgICAgfTtcbiAgICB9LFxuXG4gICAgdG9rZW46IGZ1bmN0aW9uKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgIHZhciBjdHggPSBzdGF0ZS5jb250ZXh0O1xuICAgICAgaWYgKHN0cmVhbS5zb2woKSkge1xuICAgICAgICBpZiAoY3R4LmFsaWduID09IG51bGwpIGN0eC5hbGlnbiA9IGZhbHNlO1xuICAgICAgICBzdGF0ZS5pbmRlbnRlZCA9IHN0cmVhbS5pbmRlbnRhdGlvbigpO1xuICAgICAgICBzdGF0ZS5zdGFydE9mTGluZSA9IHRydWU7XG4gICAgICB9XG4gICAgICBpZiAoc3RyZWFtLmVhdFNwYWNlKCkpIHsgbWF5YmVFT0woc3RyZWFtLCBzdGF0ZSk7IHJldHVybiBudWxsOyB9XG4gICAgICBjdXJQdW5jID0gaXNEZWZLZXl3b3JkID0gbnVsbDtcbiAgICAgIHZhciBzdHlsZSA9IChzdGF0ZS50b2tlbml6ZSB8fCB0b2tlbkJhc2UpKHN0cmVhbSwgc3RhdGUpO1xuICAgICAgaWYgKHN0eWxlID09IFwiY29tbWVudFwiIHx8IHN0eWxlID09IFwibWV0YVwiKSByZXR1cm4gc3R5bGU7XG4gICAgICBpZiAoY3R4LmFsaWduID09IG51bGwpIGN0eC5hbGlnbiA9IHRydWU7XG5cbiAgICAgIGlmIChjdXJQdW5jID09IFwiO1wiIHx8IGN1clB1bmMgPT0gXCI6XCIgfHwgKGN1clB1bmMgPT0gXCIsXCIgJiYgc3RyZWFtLm1hdGNoKC9eXFxzKig/OlxcL1xcLy4qKT8kLywgZmFsc2UpKSlcbiAgICAgICAgd2hpbGUgKHN0YXRlLmNvbnRleHQudHlwZSA9PSBcInN0YXRlbWVudFwiKSBwb3BDb250ZXh0KHN0YXRlKTtcbiAgICAgIGVsc2UgaWYgKGN1clB1bmMgPT0gXCJ7XCIpIHB1c2hDb250ZXh0KHN0YXRlLCBzdHJlYW0uY29sdW1uKCksIFwifVwiKTtcbiAgICAgIGVsc2UgaWYgKGN1clB1bmMgPT0gXCJbXCIpIHB1c2hDb250ZXh0KHN0YXRlLCBzdHJlYW0uY29sdW1uKCksIFwiXVwiKTtcbiAgICAgIGVsc2UgaWYgKGN1clB1bmMgPT0gXCIoXCIpIHB1c2hDb250ZXh0KHN0YXRlLCBzdHJlYW0uY29sdW1uKCksIFwiKVwiKTtcbiAgICAgIGVsc2UgaWYgKGN1clB1bmMgPT0gXCJ9XCIpIHtcbiAgICAgICAgd2hpbGUgKGN0eC50eXBlID09IFwic3RhdGVtZW50XCIpIGN0eCA9IHBvcENvbnRleHQoc3RhdGUpO1xuICAgICAgICBpZiAoY3R4LnR5cGUgPT0gXCJ9XCIpIGN0eCA9IHBvcENvbnRleHQoc3RhdGUpO1xuICAgICAgICB3aGlsZSAoY3R4LnR5cGUgPT0gXCJzdGF0ZW1lbnRcIikgY3R4ID0gcG9wQ29udGV4dChzdGF0ZSk7XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChjdXJQdW5jID09IGN0eC50eXBlKSBwb3BDb250ZXh0KHN0YXRlKTtcbiAgICAgIGVsc2UgaWYgKGluZGVudFN0YXRlbWVudHMgJiZcbiAgICAgICAgICAgICAgICgoKGN0eC50eXBlID09IFwifVwiIHx8IGN0eC50eXBlID09IFwidG9wXCIpICYmIGN1clB1bmMgIT0gXCI7XCIpIHx8XG4gICAgICAgICAgICAgICAgKGN0eC50eXBlID09IFwic3RhdGVtZW50XCIgJiYgY3VyUHVuYyA9PSBcIm5ld3N0YXRlbWVudFwiKSkpIHtcbiAgICAgICAgcHVzaENvbnRleHQoc3RhdGUsIHN0cmVhbS5jb2x1bW4oKSwgXCJzdGF0ZW1lbnRcIiwgc3RyZWFtLmN1cnJlbnQoKSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChzdHlsZSA9PSBcInZhcmlhYmxlXCIgJiZcbiAgICAgICAgICAoKHN0YXRlLnByZXZUb2tlbiA9PSBcImRlZlwiIHx8XG4gICAgICAgICAgICAocGFyc2VyQ29uZmlnLnR5cGVGaXJzdERlZmluaXRpb25zICYmIHR5cGVCZWZvcmUoc3RyZWFtLCBzdGF0ZSwgc3RyZWFtLnN0YXJ0KSAmJlxuICAgICAgICAgICAgIGlzVG9wU2NvcGUoc3RhdGUuY29udGV4dCkgJiYgc3RyZWFtLm1hdGNoKC9eXFxzKlxcKC8sIGZhbHNlKSkpKSlcbiAgICAgICAgc3R5bGUgPSBcImRlZlwiO1xuXG4gICAgICBpZiAoaG9va3MudG9rZW4pIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGhvb2tzLnRva2VuKHN0cmVhbSwgc3RhdGUsIHN0eWxlKTtcbiAgICAgICAgaWYgKHJlc3VsdCAhPT0gdW5kZWZpbmVkKSBzdHlsZSA9IHJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgaWYgKHN0eWxlID09IFwiZGVmXCIgJiYgcGFyc2VyQ29uZmlnLnN0eWxlRGVmcyA9PT0gZmFsc2UpIHN0eWxlID0gXCJ2YXJpYWJsZVwiO1xuXG4gICAgICBzdGF0ZS5zdGFydE9mTGluZSA9IGZhbHNlO1xuICAgICAgc3RhdGUucHJldlRva2VuID0gaXNEZWZLZXl3b3JkID8gXCJkZWZcIiA6IHN0eWxlIHx8IGN1clB1bmM7XG4gICAgICBtYXliZUVPTChzdHJlYW0sIHN0YXRlKTtcbiAgICAgIHJldHVybiBzdHlsZTtcbiAgICB9LFxuXG4gICAgaW5kZW50OiBmdW5jdGlvbihzdGF0ZSwgdGV4dEFmdGVyKSB7XG4gICAgICBpZiAoc3RhdGUudG9rZW5pemUgIT0gdG9rZW5CYXNlICYmIHN0YXRlLnRva2VuaXplICE9IG51bGwgfHwgc3RhdGUudHlwZUF0RW5kT2ZMaW5lKSByZXR1cm4gQ29kZU1pcnJvci5QYXNzO1xuICAgICAgdmFyIGN0eCA9IHN0YXRlLmNvbnRleHQsIGZpcnN0Q2hhciA9IHRleHRBZnRlciAmJiB0ZXh0QWZ0ZXIuY2hhckF0KDApO1xuICAgICAgdmFyIGNsb3NpbmcgPSBmaXJzdENoYXIgPT0gY3R4LnR5cGU7XG4gICAgICBpZiAoY3R4LnR5cGUgPT0gXCJzdGF0ZW1lbnRcIiAmJiBmaXJzdENoYXIgPT0gXCJ9XCIpIGN0eCA9IGN0eC5wcmV2O1xuICAgICAgaWYgKHBhcnNlckNvbmZpZy5kb250SW5kZW50U3RhdGVtZW50cylcbiAgICAgICAgd2hpbGUgKGN0eC50eXBlID09IFwic3RhdGVtZW50XCIgJiYgcGFyc2VyQ29uZmlnLmRvbnRJbmRlbnRTdGF0ZW1lbnRzLnRlc3QoY3R4LmluZm8pKVxuICAgICAgICAgIGN0eCA9IGN0eC5wcmV2XG4gICAgICBpZiAoaG9va3MuaW5kZW50KSB7XG4gICAgICAgIHZhciBob29rID0gaG9va3MuaW5kZW50KHN0YXRlLCBjdHgsIHRleHRBZnRlciwgaW5kZW50VW5pdCk7XG4gICAgICAgIGlmICh0eXBlb2YgaG9vayA9PSBcIm51bWJlclwiKSByZXR1cm4gaG9va1xuICAgICAgfVxuICAgICAgdmFyIHN3aXRjaEJsb2NrID0gY3R4LnByZXYgJiYgY3R4LnByZXYuaW5mbyA9PSBcInN3aXRjaFwiO1xuICAgICAgaWYgKHBhcnNlckNvbmZpZy5hbGxtYW5JbmRlbnRhdGlvbiAmJiAvW3soXS8udGVzdChmaXJzdENoYXIpKSB7XG4gICAgICAgIHdoaWxlIChjdHgudHlwZSAhPSBcInRvcFwiICYmIGN0eC50eXBlICE9IFwifVwiKSBjdHggPSBjdHgucHJldlxuICAgICAgICByZXR1cm4gY3R4LmluZGVudGVkXG4gICAgICB9XG4gICAgICBpZiAoY3R4LnR5cGUgPT0gXCJzdGF0ZW1lbnRcIilcbiAgICAgICAgcmV0dXJuIGN0eC5pbmRlbnRlZCArIChmaXJzdENoYXIgPT0gXCJ7XCIgPyAwIDogc3RhdGVtZW50SW5kZW50VW5pdCk7XG4gICAgICBpZiAoY3R4LmFsaWduICYmICghZG9udEFsaWduQ2FsbHMgfHwgY3R4LnR5cGUgIT0gXCIpXCIpKVxuICAgICAgICByZXR1cm4gY3R4LmNvbHVtbiArIChjbG9zaW5nID8gMCA6IDEpO1xuICAgICAgaWYgKGN0eC50eXBlID09IFwiKVwiICYmICFjbG9zaW5nKVxuICAgICAgICByZXR1cm4gY3R4LmluZGVudGVkICsgc3RhdGVtZW50SW5kZW50VW5pdDtcblxuICAgICAgcmV0dXJuIGN0eC5pbmRlbnRlZCArIChjbG9zaW5nID8gMCA6IGluZGVudFVuaXQpICtcbiAgICAgICAgKCFjbG9zaW5nICYmIHN3aXRjaEJsb2NrICYmICEvXig/OmNhc2V8ZGVmYXVsdClcXGIvLnRlc3QodGV4dEFmdGVyKSA/IGluZGVudFVuaXQgOiAwKTtcbiAgICB9LFxuXG4gICAgZWxlY3RyaWNJbnB1dDogaW5kZW50U3dpdGNoID8gL15cXHMqKD86Y2FzZSAuKj86fGRlZmF1bHQ6fFxce1xcfT98XFx9KSQvIDogL15cXHMqW3t9XSQvLFxuICAgIGJsb2NrQ29tbWVudFN0YXJ0OiBcIi8qXCIsXG4gICAgYmxvY2tDb21tZW50RW5kOiBcIiovXCIsXG4gICAgYmxvY2tDb21tZW50Q29udGludWU6IFwiICogXCIsXG4gICAgbGluZUNvbW1lbnQ6IFwiLy9cIixcbiAgICBmb2xkOiBcImJyYWNlXCJcbiAgfTtcbn0pO1xuXG4gIGZ1bmN0aW9uIHdvcmRzKHN0cikge1xuICAgIHZhciBvYmogPSB7fSwgd29yZHMgPSBzdHIuc3BsaXQoXCIgXCIpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgd29yZHMubGVuZ3RoOyArK2kpIG9ialt3b3Jkc1tpXV0gPSB0cnVlO1xuICAgIHJldHVybiBvYmo7XG4gIH1cbiAgZnVuY3Rpb24gY29udGFpbnMod29yZHMsIHdvcmQpIHtcbiAgICBpZiAodHlwZW9mIHdvcmRzID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIHJldHVybiB3b3Jkcyh3b3JkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHdvcmRzLnByb3BlcnR5SXNFbnVtZXJhYmxlKHdvcmQpO1xuICAgIH1cbiAgfVxuICB2YXIgY0tleXdvcmRzID0gXCJhdXRvIGlmIGJyZWFrIGNhc2UgcmVnaXN0ZXIgY29udGludWUgcmV0dXJuIGRlZmF1bHQgZG8gc2l6ZW9mIFwiICtcbiAgICBcInN0YXRpYyBlbHNlIHN0cnVjdCBzd2l0Y2ggZXh0ZXJuIHR5cGVkZWYgdW5pb24gZm9yIGdvdG8gd2hpbGUgZW51bSBjb25zdCBcIiArXG4gICAgXCJ2b2xhdGlsZSBpbmxpbmUgcmVzdHJpY3QgYXNtIGZvcnRyYW5cIjtcblxuICAvLyBLZXl3b3JkcyBmcm9tIGh0dHBzOi8vZW4uY3BwcmVmZXJlbmNlLmNvbS93L2NwcC9rZXl3b3JkIGluY2x1ZGVzIEMrKzIwLlxuICB2YXIgY3BwS2V5d29yZHMgPSBcImFsaWduYXMgYWxpZ25vZiBhbmQgYW5kX2VxIGF1ZGl0IGF4aW9tIGJpdGFuZCBiaXRvciBjYXRjaCBcIiArXG4gIFwiY2xhc3MgY29tcGwgY29uY2VwdCBjb25zdGV4cHIgY29uc3RfY2FzdCBkZWNsdHlwZSBkZWxldGUgZHluYW1pY19jYXN0IFwiICtcbiAgXCJleHBsaWNpdCBleHBvcnQgZmluYWwgZnJpZW5kIGltcG9ydCBtb2R1bGUgbXV0YWJsZSBuYW1lc3BhY2UgbmV3IG5vZXhjZXB0IFwiICtcbiAgXCJub3Qgbm90X2VxIG9wZXJhdG9yIG9yIG9yX2VxIG92ZXJyaWRlIHByaXZhdGUgcHJvdGVjdGVkIHB1YmxpYyBcIiArXG4gIFwicmVpbnRlcnByZXRfY2FzdCByZXF1aXJlcyBzdGF0aWNfYXNzZXJ0IHN0YXRpY19jYXN0IHRlbXBsYXRlIHRoaXMgXCIgK1xuICBcInRocmVhZF9sb2NhbCB0aHJvdyB0cnkgdHlwZWlkIHR5cGVuYW1lIHVzaW5nIHZpcnR1YWwgeG9yIHhvcl9lcVwiO1xuXG4gIHZhciBvYmpDS2V5d29yZHMgPSBcImJ5Y29weSBieXJlZiBpbiBpbm91dCBvbmV3YXkgb3V0IHNlbGYgc3VwZXIgYXRvbWljIG5vbmF0b21pYyByZXRhaW4gY29weSBcIiArXG4gIFwicmVhZHdyaXRlIHJlYWRvbmx5IHN0cm9uZyB3ZWFrIGFzc2lnbiB0eXBlb2YgbnVsbGFibGUgbm9ubnVsbCBudWxsX3Jlc2V0dGFibGUgX2NtZCBcIiArXG4gIFwiQGludGVyZmFjZSBAaW1wbGVtZW50YXRpb24gQGVuZCBAcHJvdG9jb2wgQGVuY29kZSBAcHJvcGVydHkgQHN5bnRoZXNpemUgQGR5bmFtaWMgQGNsYXNzIFwiICtcbiAgXCJAcHVibGljIEBwYWNrYWdlIEBwcml2YXRlIEBwcm90ZWN0ZWQgQHJlcXVpcmVkIEBvcHRpb25hbCBAdHJ5IEBjYXRjaCBAZmluYWxseSBAaW1wb3J0IFwiICtcbiAgXCJAc2VsZWN0b3IgQGVuY29kZSBAZGVmcyBAc3luY2hyb25pemVkIEBhdXRvcmVsZWFzZXBvb2wgQGNvbXBhdGliaWxpdHlfYWxpYXMgQGF2YWlsYWJsZVwiO1xuXG4gIHZhciBvYmpDQnVpbHRpbnMgPSBcIkZPVU5EQVRJT05fRVhQT1JUIEZPVU5EQVRJT05fRVhURVJOIE5TX0lOTElORSBOU19GT1JNQVRfRlVOQ1RJT04gXCIgK1xuICBcIiBOU19SRVRVUk5TX1JFVEFJTkVETlNfRVJST1JfRU5VTSBOU19SRVRVUk5TX05PVF9SRVRBSU5FRCBOU19SRVRVUk5TX0lOTkVSX1BPSU5URVIgXCIgK1xuICBcIk5TX0RFU0lHTkFURURfSU5JVElBTElaRVIgTlNfRU5VTSBOU19PUFRJT05TIE5TX1JFUVVJUkVTX05JTF9URVJNSU5BVElPTiBcIiArXG4gIFwiTlNfQVNTVU1FX05PTk5VTExfQkVHSU4gTlNfQVNTVU1FX05PTk5VTExfRU5EIE5TX1NXSUZUX05BTUUgTlNfUkVGSU5FRF9GT1JfU1dJRlRcIlxuXG4gIC8vIERvIG5vdCB1c2UgdGhpcy4gVXNlIHRoZSBjVHlwZXMgZnVuY3Rpb24gYmVsb3cuIFRoaXMgaXMgZ2xvYmFsIGp1c3QgdG8gYXZvaWRcbiAgLy8gZXhjZXNzaXZlIGNhbGxzIHdoZW4gY1R5cGVzIGlzIGJlaW5nIGNhbGxlZCBtdWx0aXBsZSB0aW1lcyBkdXJpbmcgYSBwYXJzZS5cbiAgdmFyIGJhc2ljQ1R5cGVzID0gd29yZHMoXCJpbnQgbG9uZyBjaGFyIHNob3J0IGRvdWJsZSBmbG9hdCB1bnNpZ25lZCBzaWduZWQgXCIgK1xuICAgIFwidm9pZCBib29sXCIpO1xuXG4gIC8vIERvIG5vdCB1c2UgdGhpcy4gVXNlIHRoZSBvYmpDVHlwZXMgZnVuY3Rpb24gYmVsb3cuIFRoaXMgaXMgZ2xvYmFsIGp1c3QgdG8gYXZvaWRcbiAgLy8gZXhjZXNzaXZlIGNhbGxzIHdoZW4gb2JqQ1R5cGVzIGlzIGJlaW5nIGNhbGxlZCBtdWx0aXBsZSB0aW1lcyBkdXJpbmcgYSBwYXJzZS5cbiAgdmFyIGJhc2ljT2JqQ1R5cGVzID0gd29yZHMoXCJTRUwgaW5zdGFuY2V0eXBlIGlkIENsYXNzIFByb3RvY29sIEJPT0xcIik7XG5cbiAgLy8gUmV0dXJucyB0cnVlIGlmIGlkZW50aWZpZXIgaXMgYSBcIkNcIiB0eXBlLlxuICAvLyBDIHR5cGUgaXMgZGVmaW5lZCBhcyB0aG9zZSB0aGF0IGFyZSByZXNlcnZlZCBieSB0aGUgY29tcGlsZXIgKGJhc2ljVHlwZXMpLFxuICAvLyBhbmQgdGhvc2UgdGhhdCBlbmQgaW4gX3QgKFJlc2VydmVkIGJ5IFBPU0lYIGZvciB0eXBlcylcbiAgLy8gaHR0cDovL3d3dy5nbnUub3JnL3NvZnR3YXJlL2xpYmMvbWFudWFsL2h0bWxfbm9kZS9SZXNlcnZlZC1OYW1lcy5odG1sXG4gIGZ1bmN0aW9uIGNUeXBlcyhpZGVudGlmaWVyKSB7XG4gICAgcmV0dXJuIGNvbnRhaW5zKGJhc2ljQ1R5cGVzLCBpZGVudGlmaWVyKSB8fCAvLitfdCQvLnRlc3QoaWRlbnRpZmllcik7XG4gIH1cblxuICAvLyBSZXR1cm5zIHRydWUgaWYgaWRlbnRpZmllciBpcyBhIFwiT2JqZWN0aXZlIENcIiB0eXBlLlxuICBmdW5jdGlvbiBvYmpDVHlwZXMoaWRlbnRpZmllcikge1xuICAgIHJldHVybiBjVHlwZXMoaWRlbnRpZmllcikgfHwgY29udGFpbnMoYmFzaWNPYmpDVHlwZXMsIGlkZW50aWZpZXIpO1xuICB9XG5cbiAgdmFyIGNCbG9ja0tleXdvcmRzID0gXCJjYXNlIGRvIGVsc2UgZm9yIGlmIHN3aXRjaCB3aGlsZSBzdHJ1Y3QgZW51bSB1bmlvblwiO1xuICB2YXIgY0RlZktleXdvcmRzID0gXCJzdHJ1Y3QgZW51bSB1bmlvblwiO1xuXG4gIGZ1bmN0aW9uIGNwcEhvb2soc3RyZWFtLCBzdGF0ZSkge1xuICAgIGlmICghc3RhdGUuc3RhcnRPZkxpbmUpIHJldHVybiBmYWxzZVxuICAgIGZvciAodmFyIGNoLCBuZXh0ID0gbnVsbDsgY2ggPSBzdHJlYW0ucGVlaygpOykge1xuICAgICAgaWYgKGNoID09IFwiXFxcXFwiICYmIHN0cmVhbS5tYXRjaCgvXi4kLykpIHtcbiAgICAgICAgbmV4dCA9IGNwcEhvb2tcbiAgICAgICAgYnJlYWtcbiAgICAgIH0gZWxzZSBpZiAoY2ggPT0gXCIvXCIgJiYgc3RyZWFtLm1hdGNoKC9eXFwvW1xcL1xcKl0vLCBmYWxzZSkpIHtcbiAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICAgIHN0cmVhbS5uZXh0KClcbiAgICB9XG4gICAgc3RhdGUudG9rZW5pemUgPSBuZXh0XG4gICAgcmV0dXJuIFwibWV0YVwiXG4gIH1cblxuICBmdW5jdGlvbiBwb2ludGVySG9vayhfc3RyZWFtLCBzdGF0ZSkge1xuICAgIGlmIChzdGF0ZS5wcmV2VG9rZW4gPT0gXCJ0eXBlXCIpIHJldHVybiBcInR5cGVcIjtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLyBGb3IgQyBhbmQgQysrIChhbmQgT2JqQyk6IGlkZW50aWZpZXJzIHN0YXJ0aW5nIHdpdGggX19cbiAgLy8gb3IgXyBmb2xsb3dlZCBieSBhIGNhcGl0YWwgbGV0dGVyIGFyZSByZXNlcnZlZCBmb3IgdGhlIGNvbXBpbGVyLlxuICBmdW5jdGlvbiBjSXNSZXNlcnZlZElkZW50aWZpZXIodG9rZW4pIHtcbiAgICBpZiAoIXRva2VuIHx8IHRva2VuLmxlbmd0aCA8IDIpIHJldHVybiBmYWxzZTtcbiAgICBpZiAodG9rZW5bMF0gIT0gJ18nKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuICh0b2tlblsxXSA9PSAnXycpIHx8ICh0b2tlblsxXSAhPT0gdG9rZW5bMV0udG9Mb3dlckNhc2UoKSk7XG4gIH1cblxuICBmdW5jdGlvbiBjcHAxNExpdGVyYWwoc3RyZWFtKSB7XG4gICAgc3RyZWFtLmVhdFdoaWxlKC9bXFx3XFwuJ10vKTtcbiAgICByZXR1cm4gXCJudW1iZXJcIjtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNwcDExU3RyaW5nSG9vayhzdHJlYW0sIHN0YXRlKSB7XG4gICAgc3RyZWFtLmJhY2tVcCgxKTtcbiAgICAvLyBSYXcgc3RyaW5ncy5cbiAgICBpZiAoc3RyZWFtLm1hdGNoKC9eKD86Unx1OFJ8dVJ8VVJ8TFIpLykpIHtcbiAgICAgIHZhciBtYXRjaCA9IHN0cmVhbS5tYXRjaCgvXlwiKFteXFxzXFxcXCgpXXswLDE2fSlcXCgvKTtcbiAgICAgIGlmICghbWF0Y2gpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgc3RhdGUuY3BwMTFSYXdTdHJpbmdEZWxpbSA9IG1hdGNoWzFdO1xuICAgICAgc3RhdGUudG9rZW5pemUgPSB0b2tlblJhd1N0cmluZztcbiAgICAgIHJldHVybiB0b2tlblJhd1N0cmluZyhzdHJlYW0sIHN0YXRlKTtcbiAgICB9XG4gICAgLy8gVW5pY29kZSBzdHJpbmdzL2NoYXJzLlxuICAgIGlmIChzdHJlYW0ubWF0Y2goL14oPzp1OHx1fFV8TCkvKSkge1xuICAgICAgaWYgKHN0cmVhbS5tYXRjaCgvXltcIiddLywgLyogZWF0ICovIGZhbHNlKSkge1xuICAgICAgICByZXR1cm4gXCJzdHJpbmdcIjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgLy8gSWdub3JlIHRoaXMgaG9vay5cbiAgICBzdHJlYW0ubmV4dCgpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNwcExvb2tzTGlrZUNvbnN0cnVjdG9yKHdvcmQpIHtcbiAgICB2YXIgbGFzdFR3byA9IC8oXFx3Kyk6On4/KFxcdyspJC8uZXhlYyh3b3JkKTtcbiAgICByZXR1cm4gbGFzdFR3byAmJiBsYXN0VHdvWzFdID09IGxhc3RUd29bMl07XG4gIH1cblxuICAvLyBDIy1zdHlsZSBzdHJpbmdzIHdoZXJlIFwiXCIgZXNjYXBlcyBhIHF1b3RlLlxuICBmdW5jdGlvbiB0b2tlbkF0U3RyaW5nKHN0cmVhbSwgc3RhdGUpIHtcbiAgICB2YXIgbmV4dDtcbiAgICB3aGlsZSAoKG5leHQgPSBzdHJlYW0ubmV4dCgpKSAhPSBudWxsKSB7XG4gICAgICBpZiAobmV4dCA9PSAnXCInICYmICFzdHJlYW0uZWF0KCdcIicpKSB7XG4gICAgICAgIHN0YXRlLnRva2VuaXplID0gbnVsbDtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBcInN0cmluZ1wiO1xuICB9XG5cbiAgLy8gQysrMTEgcmF3IHN0cmluZyBsaXRlcmFsIGlzIDxwcmVmaXg+XCI8ZGVsaW0+KCBhbnl0aGluZyApPGRlbGltPlwiLCB3aGVyZVxuICAvLyA8ZGVsaW0+IGNhbiBiZSBhIHN0cmluZyB1cCB0byAxNiBjaGFyYWN0ZXJzIGxvbmcuXG4gIGZ1bmN0aW9uIHRva2VuUmF3U3RyaW5nKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAvLyBFc2NhcGUgY2hhcmFjdGVycyB0aGF0IGhhdmUgc3BlY2lhbCByZWdleCBtZWFuaW5ncy5cbiAgICB2YXIgZGVsaW0gPSBzdGF0ZS5jcHAxMVJhd1N0cmluZ0RlbGltLnJlcGxhY2UoL1teXFx3XFxzXS9nLCAnXFxcXCQmJyk7XG4gICAgdmFyIG1hdGNoID0gc3RyZWFtLm1hdGNoKG5ldyBSZWdFeHAoXCIuKj9cXFxcKVwiICsgZGVsaW0gKyAnXCInKSk7XG4gICAgaWYgKG1hdGNoKVxuICAgICAgc3RhdGUudG9rZW5pemUgPSBudWxsO1xuICAgIGVsc2VcbiAgICAgIHN0cmVhbS5za2lwVG9FbmQoKTtcbiAgICByZXR1cm4gXCJzdHJpbmdcIjtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlZihtaW1lcywgbW9kZSkge1xuICAgIGlmICh0eXBlb2YgbWltZXMgPT0gXCJzdHJpbmdcIikgbWltZXMgPSBbbWltZXNdO1xuICAgIHZhciB3b3JkcyA9IFtdO1xuICAgIGZ1bmN0aW9uIGFkZChvYmopIHtcbiAgICAgIGlmIChvYmopIGZvciAodmFyIHByb3AgaW4gb2JqKSBpZiAob2JqLmhhc093blByb3BlcnR5KHByb3ApKVxuICAgICAgICB3b3Jkcy5wdXNoKHByb3ApO1xuICAgIH1cbiAgICBhZGQobW9kZS5rZXl3b3Jkcyk7XG4gICAgYWRkKG1vZGUudHlwZXMpO1xuICAgIGFkZChtb2RlLmJ1aWx0aW4pO1xuICAgIGFkZChtb2RlLmF0b21zKTtcbiAgICBpZiAod29yZHMubGVuZ3RoKSB7XG4gICAgICBtb2RlLmhlbHBlclR5cGUgPSBtaW1lc1swXTtcbiAgICAgIENvZGVNaXJyb3IucmVnaXN0ZXJIZWxwZXIoXCJoaW50V29yZHNcIiwgbWltZXNbMF0sIHdvcmRzKTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1pbWVzLmxlbmd0aDsgKytpKVxuICAgICAgQ29kZU1pcnJvci5kZWZpbmVNSU1FKG1pbWVzW2ldLCBtb2RlKTtcbiAgfVxuXG4gIGRlZihbXCJ0ZXh0L3gtY3NyY1wiLCBcInRleHQveC1jXCIsIFwidGV4dC94LWNoZHJcIl0sIHtcbiAgICBuYW1lOiBcImNsaWtlXCIsXG4gICAga2V5d29yZHM6IHdvcmRzKGNLZXl3b3JkcyksXG4gICAgdHlwZXM6IGNUeXBlcyxcbiAgICBibG9ja0tleXdvcmRzOiB3b3JkcyhjQmxvY2tLZXl3b3JkcyksXG4gICAgZGVmS2V5d29yZHM6IHdvcmRzKGNEZWZLZXl3b3JkcyksXG4gICAgdHlwZUZpcnN0RGVmaW5pdGlvbnM6IHRydWUsXG4gICAgYXRvbXM6IHdvcmRzKFwiTlVMTCB0cnVlIGZhbHNlXCIpLFxuICAgIGlzUmVzZXJ2ZWRJZGVudGlmaWVyOiBjSXNSZXNlcnZlZElkZW50aWZpZXIsXG4gICAgaG9va3M6IHtcbiAgICAgIFwiI1wiOiBjcHBIb29rLFxuICAgICAgXCIqXCI6IHBvaW50ZXJIb29rLFxuICAgIH0sXG4gICAgbW9kZVByb3BzOiB7Zm9sZDogW1wiYnJhY2VcIiwgXCJpbmNsdWRlXCJdfVxuICB9KTtcblxuICBkZWYoW1widGV4dC94LWMrK3NyY1wiLCBcInRleHQveC1jKytoZHJcIl0sIHtcbiAgICBuYW1lOiBcImNsaWtlXCIsXG4gICAga2V5d29yZHM6IHdvcmRzKGNLZXl3b3JkcyArIFwiIFwiICsgY3BwS2V5d29yZHMpLFxuICAgIHR5cGVzOiBjVHlwZXMsXG4gICAgYmxvY2tLZXl3b3Jkczogd29yZHMoY0Jsb2NrS2V5d29yZHMgKyBcIiBjbGFzcyB0cnkgY2F0Y2hcIiksXG4gICAgZGVmS2V5d29yZHM6IHdvcmRzKGNEZWZLZXl3b3JkcyArIFwiIGNsYXNzIG5hbWVzcGFjZVwiKSxcbiAgICB0eXBlRmlyc3REZWZpbml0aW9uczogdHJ1ZSxcbiAgICBhdG9tczogd29yZHMoXCJ0cnVlIGZhbHNlIE5VTEwgbnVsbHB0clwiKSxcbiAgICBkb250SW5kZW50U3RhdGVtZW50czogL150ZW1wbGF0ZSQvLFxuICAgIGlzSWRlbnRpZmllckNoYXI6IC9bXFx3XFwkX35cXHhhMS1cXHVmZmZmXS8sXG4gICAgaXNSZXNlcnZlZElkZW50aWZpZXI6IGNJc1Jlc2VydmVkSWRlbnRpZmllcixcbiAgICBob29rczoge1xuICAgICAgXCIjXCI6IGNwcEhvb2ssXG4gICAgICBcIipcIjogcG9pbnRlckhvb2ssXG4gICAgICBcInVcIjogY3BwMTFTdHJpbmdIb29rLFxuICAgICAgXCJVXCI6IGNwcDExU3RyaW5nSG9vayxcbiAgICAgIFwiTFwiOiBjcHAxMVN0cmluZ0hvb2ssXG4gICAgICBcIlJcIjogY3BwMTFTdHJpbmdIb29rLFxuICAgICAgXCIwXCI6IGNwcDE0TGl0ZXJhbCxcbiAgICAgIFwiMVwiOiBjcHAxNExpdGVyYWwsXG4gICAgICBcIjJcIjogY3BwMTRMaXRlcmFsLFxuICAgICAgXCIzXCI6IGNwcDE0TGl0ZXJhbCxcbiAgICAgIFwiNFwiOiBjcHAxNExpdGVyYWwsXG4gICAgICBcIjVcIjogY3BwMTRMaXRlcmFsLFxuICAgICAgXCI2XCI6IGNwcDE0TGl0ZXJhbCxcbiAgICAgIFwiN1wiOiBjcHAxNExpdGVyYWwsXG4gICAgICBcIjhcIjogY3BwMTRMaXRlcmFsLFxuICAgICAgXCI5XCI6IGNwcDE0TGl0ZXJhbCxcbiAgICAgIHRva2VuOiBmdW5jdGlvbihzdHJlYW0sIHN0YXRlLCBzdHlsZSkge1xuICAgICAgICBpZiAoc3R5bGUgPT0gXCJ2YXJpYWJsZVwiICYmIHN0cmVhbS5wZWVrKCkgPT0gXCIoXCIgJiZcbiAgICAgICAgICAgIChzdGF0ZS5wcmV2VG9rZW4gPT0gXCI7XCIgfHwgc3RhdGUucHJldlRva2VuID09IG51bGwgfHxcbiAgICAgICAgICAgICBzdGF0ZS5wcmV2VG9rZW4gPT0gXCJ9XCIpICYmXG4gICAgICAgICAgICBjcHBMb29rc0xpa2VDb25zdHJ1Y3RvcihzdHJlYW0uY3VycmVudCgpKSlcbiAgICAgICAgICByZXR1cm4gXCJkZWZcIjtcbiAgICAgIH1cbiAgICB9LFxuICAgIG5hbWVzcGFjZVNlcGFyYXRvcjogXCI6OlwiLFxuICAgIG1vZGVQcm9wczoge2ZvbGQ6IFtcImJyYWNlXCIsIFwiaW5jbHVkZVwiXX1cbiAgfSk7XG5cbiAgZGVmKFwidGV4dC94LWphdmFcIiwge1xuICAgIG5hbWU6IFwiY2xpa2VcIixcbiAgICBrZXl3b3Jkczogd29yZHMoXCJhYnN0cmFjdCBhc3NlcnQgYnJlYWsgY2FzZSBjYXRjaCBjbGFzcyBjb25zdCBjb250aW51ZSBkZWZhdWx0IFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJkbyBlbHNlIGVudW0gZXh0ZW5kcyBmaW5hbCBmaW5hbGx5IGZvciBnb3RvIGlmIGltcGxlbWVudHMgaW1wb3J0IFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJpbnN0YW5jZW9mIGludGVyZmFjZSBuYXRpdmUgbmV3IHBhY2thZ2UgcHJpdmF0ZSBwcm90ZWN0ZWQgcHVibGljIFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJyZXR1cm4gc3RhdGljIHN0cmljdGZwIHN1cGVyIHN3aXRjaCBzeW5jaHJvbml6ZWQgdGhpcyB0aHJvdyB0aHJvd3MgdHJhbnNpZW50IFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJ0cnkgdm9sYXRpbGUgd2hpbGUgQGludGVyZmFjZVwiKSxcbiAgICB0eXBlczogd29yZHMoXCJ2YXIgYnl0ZSBzaG9ydCBpbnQgbG9uZyBmbG9hdCBkb3VibGUgYm9vbGVhbiBjaGFyIHZvaWQgQm9vbGVhbiBCeXRlIENoYXJhY3RlciBEb3VibGUgRmxvYXQgXCIgK1xuICAgICAgICAgICAgICAgICBcIkludGVnZXIgTG9uZyBOdW1iZXIgT2JqZWN0IFNob3J0IFN0cmluZyBTdHJpbmdCdWZmZXIgU3RyaW5nQnVpbGRlciBWb2lkXCIpLFxuICAgIGJsb2NrS2V5d29yZHM6IHdvcmRzKFwiY2F0Y2ggY2xhc3MgZG8gZWxzZSBmaW5hbGx5IGZvciBpZiBzd2l0Y2ggdHJ5IHdoaWxlXCIpLFxuICAgIGRlZktleXdvcmRzOiB3b3JkcyhcImNsYXNzIGludGVyZmFjZSBlbnVtIEBpbnRlcmZhY2VcIiksXG4gICAgdHlwZUZpcnN0RGVmaW5pdGlvbnM6IHRydWUsXG4gICAgYXRvbXM6IHdvcmRzKFwidHJ1ZSBmYWxzZSBudWxsXCIpLFxuICAgIG51bWJlcjogL14oPzoweFthLWZcXGRfXSt8MGJbMDFfXSt8KD86W1xcZF9dK1xcLj9cXGQqfFxcLlxcZCspKD86ZVstK10/W1xcZF9dKyk/KSh1fGxsP3xsfGYpPy9pLFxuICAgIGhvb2tzOiB7XG4gICAgICBcIkBcIjogZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgIC8vIERvbid0IG1hdGNoIHRoZSBAaW50ZXJmYWNlIGtleXdvcmQuXG4gICAgICAgIGlmIChzdHJlYW0ubWF0Y2goJ2ludGVyZmFjZScsIGZhbHNlKSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIHN0cmVhbS5lYXRXaGlsZSgvW1xcd1xcJF9dLyk7XG4gICAgICAgIHJldHVybiBcIm1ldGFcIjtcbiAgICAgIH0sXG4gICAgICAnXCInOiBmdW5jdGlvbihzdHJlYW0sIHN0YXRlKSB7XG4gICAgICAgIGlmICghc3RyZWFtLm1hdGNoKC9cIlwiJC8pKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIHN0YXRlLnRva2VuaXplID0gdG9rZW5UcmlwbGVTdHJpbmc7XG4gICAgICAgIHJldHVybiBzdGF0ZS50b2tlbml6ZShzdHJlYW0sIHN0YXRlKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIG1vZGVQcm9wczoge2ZvbGQ6IFtcImJyYWNlXCIsIFwiaW1wb3J0XCJdfVxuICB9KTtcblxuICBkZWYoXCJ0ZXh0L3gtY3NoYXJwXCIsIHtcbiAgICBuYW1lOiBcImNsaWtlXCIsXG4gICAga2V5d29yZHM6IHdvcmRzKFwiYWJzdHJhY3QgYXMgYXN5bmMgYXdhaXQgYmFzZSBicmVhayBjYXNlIGNhdGNoIGNoZWNrZWQgY2xhc3MgY29uc3QgY29udGludWVcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiIGRlZmF1bHQgZGVsZWdhdGUgZG8gZWxzZSBlbnVtIGV2ZW50IGV4cGxpY2l0IGV4dGVybiBmaW5hbGx5IGZpeGVkIGZvclwiICtcbiAgICAgICAgICAgICAgICAgICAgXCIgZm9yZWFjaCBnb3RvIGlmIGltcGxpY2l0IGluIGludGVyZmFjZSBpbnRlcm5hbCBpcyBsb2NrIG5hbWVzcGFjZSBuZXdcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiIG9wZXJhdG9yIG91dCBvdmVycmlkZSBwYXJhbXMgcHJpdmF0ZSBwcm90ZWN0ZWQgcHVibGljIHJlYWRvbmx5IHJlZiByZXR1cm4gc2VhbGVkXCIgK1xuICAgICAgICAgICAgICAgICAgICBcIiBzaXplb2Ygc3RhY2thbGxvYyBzdGF0aWMgc3RydWN0IHN3aXRjaCB0aGlzIHRocm93IHRyeSB0eXBlb2YgdW5jaGVja2VkXCIgK1xuICAgICAgICAgICAgICAgICAgICBcIiB1bnNhZmUgdXNpbmcgdmlydHVhbCB2b2lkIHZvbGF0aWxlIHdoaWxlIGFkZCBhbGlhcyBhc2NlbmRpbmcgZGVzY2VuZGluZyBkeW5hbWljIGZyb20gZ2V0XCIgK1xuICAgICAgICAgICAgICAgICAgICBcIiBnbG9iYWwgZ3JvdXAgaW50byBqb2luIGxldCBvcmRlcmJ5IHBhcnRpYWwgcmVtb3ZlIHNlbGVjdCBzZXQgdmFsdWUgdmFyIHlpZWxkXCIpLFxuICAgIHR5cGVzOiB3b3JkcyhcIkFjdGlvbiBCb29sZWFuIEJ5dGUgQ2hhciBEYXRlVGltZSBEYXRlVGltZU9mZnNldCBEZWNpbWFsIERvdWJsZSBGdW5jXCIgK1xuICAgICAgICAgICAgICAgICBcIiBHdWlkIEludDE2IEludDMyIEludDY0IE9iamVjdCBTQnl0ZSBTaW5nbGUgU3RyaW5nIFRhc2sgVGltZVNwYW4gVUludDE2IFVJbnQzMlwiICtcbiAgICAgICAgICAgICAgICAgXCIgVUludDY0IGJvb2wgYnl0ZSBjaGFyIGRlY2ltYWwgZG91YmxlIHNob3J0IGludCBsb25nIG9iamVjdFwiICArXG4gICAgICAgICAgICAgICAgIFwiIHNieXRlIGZsb2F0IHN0cmluZyB1c2hvcnQgdWludCB1bG9uZ1wiKSxcbiAgICBibG9ja0tleXdvcmRzOiB3b3JkcyhcImNhdGNoIGNsYXNzIGRvIGVsc2UgZmluYWxseSBmb3IgZm9yZWFjaCBpZiBzdHJ1Y3Qgc3dpdGNoIHRyeSB3aGlsZVwiKSxcbiAgICBkZWZLZXl3b3Jkczogd29yZHMoXCJjbGFzcyBpbnRlcmZhY2UgbmFtZXNwYWNlIHN0cnVjdCB2YXJcIiksXG4gICAgdHlwZUZpcnN0RGVmaW5pdGlvbnM6IHRydWUsXG4gICAgYXRvbXM6IHdvcmRzKFwidHJ1ZSBmYWxzZSBudWxsXCIpLFxuICAgIGhvb2tzOiB7XG4gICAgICBcIkBcIjogZnVuY3Rpb24oc3RyZWFtLCBzdGF0ZSkge1xuICAgICAgICBpZiAoc3RyZWFtLmVhdCgnXCInKSkge1xuICAgICAgICAgIHN0YXRlLnRva2VuaXplID0gdG9rZW5BdFN0cmluZztcbiAgICAgICAgICByZXR1cm4gdG9rZW5BdFN0cmluZyhzdHJlYW0sIHN0YXRlKTtcbiAgICAgICAgfVxuICAgICAgICBzdHJlYW0uZWF0V2hpbGUoL1tcXHdcXCRfXS8pO1xuICAgICAgICByZXR1cm4gXCJtZXRhXCI7XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICBmdW5jdGlvbiB0b2tlblRyaXBsZVN0cmluZyhzdHJlYW0sIHN0YXRlKSB7XG4gICAgdmFyIGVzY2FwZWQgPSBmYWxzZTtcbiAgICB3aGlsZSAoIXN0cmVhbS5lb2woKSkge1xuICAgICAgaWYgKCFlc2NhcGVkICYmIHN0cmVhbS5tYXRjaCgnXCJcIlwiJykpIHtcbiAgICAgICAgc3RhdGUudG9rZW5pemUgPSBudWxsO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGVzY2FwZWQgPSBzdHJlYW0ubmV4dCgpID09IFwiXFxcXFwiICYmICFlc2NhcGVkO1xuICAgIH1cbiAgICByZXR1cm4gXCJzdHJpbmdcIjtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRva2VuTmVzdGVkQ29tbWVudChkZXB0aCkge1xuICAgIHJldHVybiBmdW5jdGlvbiAoc3RyZWFtLCBzdGF0ZSkge1xuICAgICAgdmFyIGNoXG4gICAgICB3aGlsZSAoY2ggPSBzdHJlYW0ubmV4dCgpKSB7XG4gICAgICAgIGlmIChjaCA9PSBcIipcIiAmJiBzdHJlYW0uZWF0KFwiL1wiKSkge1xuICAgICAgICAgIGlmIChkZXB0aCA9PSAxKSB7XG4gICAgICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IG51bGxcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0YXRlLnRva2VuaXplID0gdG9rZW5OZXN0ZWRDb21tZW50KGRlcHRoIC0gMSlcbiAgICAgICAgICAgIHJldHVybiBzdGF0ZS50b2tlbml6ZShzdHJlYW0sIHN0YXRlKVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChjaCA9PSBcIi9cIiAmJiBzdHJlYW0uZWF0KFwiKlwiKSkge1xuICAgICAgICAgIHN0YXRlLnRva2VuaXplID0gdG9rZW5OZXN0ZWRDb21tZW50KGRlcHRoICsgMSlcbiAgICAgICAgICByZXR1cm4gc3RhdGUudG9rZW5pemUoc3RyZWFtLCBzdGF0ZSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIFwiY29tbWVudFwiXG4gICAgfVxuICB9XG5cbiAgZGVmKFwidGV4dC94LXNjYWxhXCIsIHtcbiAgICBuYW1lOiBcImNsaWtlXCIsXG4gICAga2V5d29yZHM6IHdvcmRzKFxuICAgICAgLyogc2NhbGEgKi9cbiAgICAgIFwiYWJzdHJhY3QgY2FzZSBjYXRjaCBjbGFzcyBkZWYgZG8gZWxzZSBleHRlbmRzIGZpbmFsIGZpbmFsbHkgZm9yIGZvclNvbWUgaWYgXCIgK1xuICAgICAgXCJpbXBsaWNpdCBpbXBvcnQgbGF6eSBtYXRjaCBuZXcgbnVsbCBvYmplY3Qgb3ZlcnJpZGUgcGFja2FnZSBwcml2YXRlIHByb3RlY3RlZCByZXR1cm4gXCIgK1xuICAgICAgXCJzZWFsZWQgc3VwZXIgdGhpcyB0aHJvdyB0cmFpdCB0cnkgdHlwZSB2YWwgdmFyIHdoaWxlIHdpdGggeWllbGQgXyBcIiArXG5cbiAgICAgIC8qIHBhY2thZ2Ugc2NhbGEgKi9cbiAgICAgIFwiYXNzZXJ0IGFzc3VtZSByZXF1aXJlIHByaW50IHByaW50bG4gcHJpbnRmIHJlYWRMaW5lIHJlYWRCb29sZWFuIHJlYWRCeXRlIHJlYWRTaG9ydCBcIiArXG4gICAgICBcInJlYWRDaGFyIHJlYWRJbnQgcmVhZExvbmcgcmVhZEZsb2F0IHJlYWREb3VibGVcIlxuICAgICksXG4gICAgdHlwZXM6IHdvcmRzKFxuICAgICAgXCJBbnlWYWwgQXBwIEFwcGxpY2F0aW9uIEFycmF5IEJ1ZmZlcmVkSXRlcmF0b3IgQmlnRGVjaW1hbCBCaWdJbnQgQ2hhciBDb25zb2xlIEVpdGhlciBcIiArXG4gICAgICBcIkVudW1lcmF0aW9uIEVxdWl2IEVycm9yIEV4Y2VwdGlvbiBGcmFjdGlvbmFsIEZ1bmN0aW9uIEluZGV4ZWRTZXEgSW50IEludGVncmFsIEl0ZXJhYmxlIFwiICtcbiAgICAgIFwiSXRlcmF0b3IgTGlzdCBNYXAgTnVtZXJpYyBOaWwgTm90TnVsbCBPcHRpb24gT3JkZXJlZCBPcmRlcmluZyBQYXJ0aWFsRnVuY3Rpb24gUGFydGlhbE9yZGVyaW5nIFwiICtcbiAgICAgIFwiUHJvZHVjdCBQcm94eSBSYW5nZSBSZXNwb25kZXIgU2VxIFNlcmlhbGl6YWJsZSBTZXQgU3BlY2lhbGl6YWJsZSBTdHJlYW0gU3RyaW5nQnVpbGRlciBcIiArXG4gICAgICBcIlN0cmluZ0NvbnRleHQgU3ltYm9sIFRocm93YWJsZSBUcmF2ZXJzYWJsZSBUcmF2ZXJzYWJsZU9uY2UgVHVwbGUgVW5pdCBWZWN0b3IgXCIgK1xuXG4gICAgICAvKiBwYWNrYWdlIGphdmEubGFuZyAqL1xuICAgICAgXCJCb29sZWFuIEJ5dGUgQ2hhcmFjdGVyIENoYXJTZXF1ZW5jZSBDbGFzcyBDbGFzc0xvYWRlciBDbG9uZWFibGUgQ29tcGFyYWJsZSBcIiArXG4gICAgICBcIkNvbXBpbGVyIERvdWJsZSBFeGNlcHRpb24gRmxvYXQgSW50ZWdlciBMb25nIE1hdGggTnVtYmVyIE9iamVjdCBQYWNrYWdlIFBhaXIgUHJvY2VzcyBcIiArXG4gICAgICBcIlJ1bnRpbWUgUnVubmFibGUgU2VjdXJpdHlNYW5hZ2VyIFNob3J0IFN0YWNrVHJhY2VFbGVtZW50IFN0cmljdE1hdGggU3RyaW5nIFwiICtcbiAgICAgIFwiU3RyaW5nQnVmZmVyIFN5c3RlbSBUaHJlYWQgVGhyZWFkR3JvdXAgVGhyZWFkTG9jYWwgVGhyb3dhYmxlIFRyaXBsZSBWb2lkXCJcbiAgICApLFxuICAgIG11bHRpTGluZVN0cmluZ3M6IHRydWUsXG4gICAgYmxvY2tLZXl3b3Jkczogd29yZHMoXCJjYXRjaCBjbGFzcyBlbnVtIGRvIGVsc2UgZmluYWxseSBmb3IgZm9yU29tZSBpZiBtYXRjaCBzd2l0Y2ggdHJ5IHdoaWxlXCIpLFxuICAgIGRlZktleXdvcmRzOiB3b3JkcyhcImNsYXNzIGVudW0gZGVmIG9iamVjdCBwYWNrYWdlIHRyYWl0IHR5cGUgdmFsIHZhclwiKSxcbiAgICBhdG9tczogd29yZHMoXCJ0cnVlIGZhbHNlIG51bGxcIiksXG4gICAgaW5kZW50U3RhdGVtZW50czogZmFsc2UsXG4gICAgaW5kZW50U3dpdGNoOiBmYWxzZSxcbiAgICBpc09wZXJhdG9yQ2hhcjogL1srXFwtKiYlPTw+IT98XFwvIzpAXS8sXG4gICAgaG9va3M6IHtcbiAgICAgIFwiQFwiOiBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgc3RyZWFtLmVhdFdoaWxlKC9bXFx3XFwkX10vKTtcbiAgICAgICAgcmV0dXJuIFwibWV0YVwiO1xuICAgICAgfSxcbiAgICAgICdcIic6IGZ1bmN0aW9uKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgICAgaWYgKCFzdHJlYW0ubWF0Y2goJ1wiXCInKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IHRva2VuVHJpcGxlU3RyaW5nO1xuICAgICAgICByZXR1cm4gc3RhdGUudG9rZW5pemUoc3RyZWFtLCBzdGF0ZSk7XG4gICAgICB9LFxuICAgICAgXCInXCI6IGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgICAgICBzdHJlYW0uZWF0V2hpbGUoL1tcXHdcXCRfXFx4YTEtXFx1ZmZmZl0vKTtcbiAgICAgICAgcmV0dXJuIFwiYXRvbVwiO1xuICAgICAgfSxcbiAgICAgIFwiPVwiOiBmdW5jdGlvbihzdHJlYW0sIHN0YXRlKSB7XG4gICAgICAgIHZhciBjeCA9IHN0YXRlLmNvbnRleHRcbiAgICAgICAgaWYgKGN4LnR5cGUgPT0gXCJ9XCIgJiYgY3guYWxpZ24gJiYgc3RyZWFtLmVhdChcIj5cIikpIHtcbiAgICAgICAgICBzdGF0ZS5jb250ZXh0ID0gbmV3IENvbnRleHQoY3guaW5kZW50ZWQsIGN4LmNvbHVtbiwgY3gudHlwZSwgY3guaW5mbywgbnVsbCwgY3gucHJldilcbiAgICAgICAgICByZXR1cm4gXCJvcGVyYXRvclwiXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICAgIH1cbiAgICAgIH0sXG5cbiAgICAgIFwiL1wiOiBmdW5jdGlvbihzdHJlYW0sIHN0YXRlKSB7XG4gICAgICAgIGlmICghc3RyZWFtLmVhdChcIipcIikpIHJldHVybiBmYWxzZVxuICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IHRva2VuTmVzdGVkQ29tbWVudCgxKVxuICAgICAgICByZXR1cm4gc3RhdGUudG9rZW5pemUoc3RyZWFtLCBzdGF0ZSlcbiAgICAgIH1cbiAgICB9LFxuICAgIG1vZGVQcm9wczoge2Nsb3NlQnJhY2tldHM6IHtwYWlyczogJygpW117fVwiXCInLCB0cmlwbGVzOiAnXCInfX1cbiAgfSk7XG5cbiAgZnVuY3Rpb24gdG9rZW5Lb3RsaW5TdHJpbmcodHJpcGxlU3RyaW5nKXtcbiAgICByZXR1cm4gZnVuY3Rpb24gKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgIHZhciBlc2NhcGVkID0gZmFsc2UsIG5leHQsIGVuZCA9IGZhbHNlO1xuICAgICAgd2hpbGUgKCFzdHJlYW0uZW9sKCkpIHtcbiAgICAgICAgaWYgKCF0cmlwbGVTdHJpbmcgJiYgIWVzY2FwZWQgJiYgc3RyZWFtLm1hdGNoKCdcIicpICkge2VuZCA9IHRydWU7IGJyZWFrO31cbiAgICAgICAgaWYgKHRyaXBsZVN0cmluZyAmJiBzdHJlYW0ubWF0Y2goJ1wiXCJcIicpKSB7ZW5kID0gdHJ1ZTsgYnJlYWs7fVxuICAgICAgICBuZXh0ID0gc3RyZWFtLm5leHQoKTtcbiAgICAgICAgaWYoIWVzY2FwZWQgJiYgbmV4dCA9PSBcIiRcIiAmJiBzdHJlYW0ubWF0Y2goJ3snKSlcbiAgICAgICAgICBzdHJlYW0uc2tpcFRvKFwifVwiKTtcbiAgICAgICAgZXNjYXBlZCA9ICFlc2NhcGVkICYmIG5leHQgPT0gXCJcXFxcXCIgJiYgIXRyaXBsZVN0cmluZztcbiAgICAgIH1cbiAgICAgIGlmIChlbmQgfHwgIXRyaXBsZVN0cmluZylcbiAgICAgICAgc3RhdGUudG9rZW5pemUgPSBudWxsO1xuICAgICAgcmV0dXJuIFwic3RyaW5nXCI7XG4gICAgfVxuICB9XG5cbiAgZGVmKFwidGV4dC94LWtvdGxpblwiLCB7XG4gICAgbmFtZTogXCJjbGlrZVwiLFxuICAgIGtleXdvcmRzOiB3b3JkcyhcbiAgICAgIC8qa2V5d29yZHMqL1xuICAgICAgXCJwYWNrYWdlIGFzIHR5cGVhbGlhcyBjbGFzcyBpbnRlcmZhY2UgdGhpcyBzdXBlciB2YWwgb3BlcmF0b3IgXCIgK1xuICAgICAgXCJ2YXIgZnVuIGZvciBpcyBpbiBUaGlzIHRocm93IHJldHVybiBhbm5vdGF0aW9uIFwiICtcbiAgICAgIFwiYnJlYWsgY29udGludWUgb2JqZWN0IGlmIGVsc2Ugd2hpbGUgZG8gdHJ5IHdoZW4gIWluICFpcyBhcz8gXCIgK1xuXG4gICAgICAvKnNvZnQga2V5d29yZHMqL1xuICAgICAgXCJmaWxlIGltcG9ydCB3aGVyZSBieSBnZXQgc2V0IGFic3RyYWN0IGVudW0gb3BlbiBpbm5lciBvdmVycmlkZSBwcml2YXRlIHB1YmxpYyBpbnRlcm5hbCBcIiArXG4gICAgICBcInByb3RlY3RlZCBjYXRjaCBmaW5hbGx5IG91dCBmaW5hbCB2YXJhcmcgcmVpZmllZCBkeW5hbWljIGNvbXBhbmlvbiBjb25zdHJ1Y3RvciBpbml0IFwiICtcbiAgICAgIFwic2VhbGVkIGZpZWxkIHByb3BlcnR5IHJlY2VpdmVyIHBhcmFtIHNwYXJhbSBsYXRlaW5pdCBkYXRhIGlubGluZSBub2lubGluZSB0YWlscmVjIFwiICtcbiAgICAgIFwiZXh0ZXJuYWwgYW5ub3RhdGlvbiBjcm9zc2lubGluZSBjb25zdCBvcGVyYXRvciBpbmZpeCBzdXNwZW5kIGFjdHVhbCBleHBlY3Qgc2V0cGFyYW0gdmFsdWVcIlxuICAgICksXG4gICAgdHlwZXM6IHdvcmRzKFxuICAgICAgLyogcGFja2FnZSBqYXZhLmxhbmcgKi9cbiAgICAgIFwiQm9vbGVhbiBCeXRlIENoYXJhY3RlciBDaGFyU2VxdWVuY2UgQ2xhc3MgQ2xhc3NMb2FkZXIgQ2xvbmVhYmxlIENvbXBhcmFibGUgXCIgK1xuICAgICAgXCJDb21waWxlciBEb3VibGUgRXhjZXB0aW9uIEZsb2F0IEludGVnZXIgTG9uZyBNYXRoIE51bWJlciBPYmplY3QgUGFja2FnZSBQYWlyIFByb2Nlc3MgXCIgK1xuICAgICAgXCJSdW50aW1lIFJ1bm5hYmxlIFNlY3VyaXR5TWFuYWdlciBTaG9ydCBTdGFja1RyYWNlRWxlbWVudCBTdHJpY3RNYXRoIFN0cmluZyBcIiArXG4gICAgICBcIlN0cmluZ0J1ZmZlciBTeXN0ZW0gVGhyZWFkIFRocmVhZEdyb3VwIFRocmVhZExvY2FsIFRocm93YWJsZSBUcmlwbGUgVm9pZCBBbm5vdGF0aW9uIEFueSBCb29sZWFuQXJyYXkgXCIgK1xuICAgICAgXCJCeXRlQXJyYXkgQ2hhciBDaGFyQXJyYXkgRGVwcmVjYXRpb25MZXZlbCBEb3VibGVBcnJheSBFbnVtIEZsb2F0QXJyYXkgRnVuY3Rpb24gSW50IEludEFycmF5IExhenkgXCIgK1xuICAgICAgXCJMYXp5VGhyZWFkU2FmZXR5TW9kZSBMb25nQXJyYXkgTm90aGluZyBTaG9ydEFycmF5IFVuaXRcIlxuICAgICksXG4gICAgaW50ZW5kU3dpdGNoOiBmYWxzZSxcbiAgICBpbmRlbnRTdGF0ZW1lbnRzOiBmYWxzZSxcbiAgICBtdWx0aUxpbmVTdHJpbmdzOiB0cnVlLFxuICAgIG51bWJlcjogL14oPzoweFthLWZcXGRfXSt8MGJbMDFfXSt8KD86W1xcZF9dKyhcXC5cXGQrKT98XFwuXFxkKykoPzplWy0rXT9bXFxkX10rKT8pKHV8bGw/fGx8Zik/L2ksXG4gICAgYmxvY2tLZXl3b3Jkczogd29yZHMoXCJjYXRjaCBjbGFzcyBkbyBlbHNlIGZpbmFsbHkgZm9yIGlmIHdoZXJlIHRyeSB3aGlsZSBlbnVtXCIpLFxuICAgIGRlZktleXdvcmRzOiB3b3JkcyhcImNsYXNzIHZhbCB2YXIgb2JqZWN0IGludGVyZmFjZSBmdW5cIiksXG4gICAgYXRvbXM6IHdvcmRzKFwidHJ1ZSBmYWxzZSBudWxsIHRoaXNcIiksXG4gICAgaG9va3M6IHtcbiAgICAgIFwiQFwiOiBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgc3RyZWFtLmVhdFdoaWxlKC9bXFx3XFwkX10vKTtcbiAgICAgICAgcmV0dXJuIFwibWV0YVwiO1xuICAgICAgfSxcbiAgICAgICcqJzogZnVuY3Rpb24oX3N0cmVhbSwgc3RhdGUpIHtcbiAgICAgICAgcmV0dXJuIHN0YXRlLnByZXZUb2tlbiA9PSAnLicgPyAndmFyaWFibGUnIDogJ29wZXJhdG9yJztcbiAgICAgIH0sXG4gICAgICAnXCInOiBmdW5jdGlvbihzdHJlYW0sIHN0YXRlKSB7XG4gICAgICAgIHN0YXRlLnRva2VuaXplID0gdG9rZW5Lb3RsaW5TdHJpbmcoc3RyZWFtLm1hdGNoKCdcIlwiJykpO1xuICAgICAgICByZXR1cm4gc3RhdGUudG9rZW5pemUoc3RyZWFtLCBzdGF0ZSk7XG4gICAgICB9LFxuICAgICAgXCIvXCI6IGZ1bmN0aW9uKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgICAgaWYgKCFzdHJlYW0uZWF0KFwiKlwiKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IHRva2VuTmVzdGVkQ29tbWVudCgxKTtcbiAgICAgICAgcmV0dXJuIHN0YXRlLnRva2VuaXplKHN0cmVhbSwgc3RhdGUpXG4gICAgICB9LFxuICAgICAgaW5kZW50OiBmdW5jdGlvbihzdGF0ZSwgY3R4LCB0ZXh0QWZ0ZXIsIGluZGVudFVuaXQpIHtcbiAgICAgICAgdmFyIGZpcnN0Q2hhciA9IHRleHRBZnRlciAmJiB0ZXh0QWZ0ZXIuY2hhckF0KDApO1xuICAgICAgICBpZiAoKHN0YXRlLnByZXZUb2tlbiA9PSBcIn1cIiB8fCBzdGF0ZS5wcmV2VG9rZW4gPT0gXCIpXCIpICYmIHRleHRBZnRlciA9PSBcIlwiKVxuICAgICAgICAgIHJldHVybiBzdGF0ZS5pbmRlbnRlZDtcbiAgICAgICAgaWYgKChzdGF0ZS5wcmV2VG9rZW4gPT0gXCJvcGVyYXRvclwiICYmIHRleHRBZnRlciAhPSBcIn1cIiAmJiBzdGF0ZS5jb250ZXh0LnR5cGUgIT0gXCJ9XCIpIHx8XG4gICAgICAgICAgc3RhdGUucHJldlRva2VuID09IFwidmFyaWFibGVcIiAmJiBmaXJzdENoYXIgPT0gXCIuXCIgfHxcbiAgICAgICAgICAoc3RhdGUucHJldlRva2VuID09IFwifVwiIHx8IHN0YXRlLnByZXZUb2tlbiA9PSBcIilcIikgJiYgZmlyc3RDaGFyID09IFwiLlwiKVxuICAgICAgICAgIHJldHVybiBpbmRlbnRVbml0ICogMiArIGN0eC5pbmRlbnRlZDtcbiAgICAgICAgaWYgKGN0eC5hbGlnbiAmJiBjdHgudHlwZSA9PSBcIn1cIilcbiAgICAgICAgICByZXR1cm4gY3R4LmluZGVudGVkICsgKHN0YXRlLmNvbnRleHQudHlwZSA9PSAodGV4dEFmdGVyIHx8IFwiXCIpLmNoYXJBdCgwKSA/IDAgOiBpbmRlbnRVbml0KTtcbiAgICAgIH1cbiAgICB9LFxuICAgIG1vZGVQcm9wczoge2Nsb3NlQnJhY2tldHM6IHt0cmlwbGVzOiAnXCInfX1cbiAgfSk7XG5cbiAgZGVmKFtcIngtc2hhZGVyL3gtdmVydGV4XCIsIFwieC1zaGFkZXIveC1mcmFnbWVudFwiXSwge1xuICAgIG5hbWU6IFwiY2xpa2VcIixcbiAgICBrZXl3b3Jkczogd29yZHMoXCJzYW1wbGVyMUQgc2FtcGxlcjJEIHNhbXBsZXIzRCBzYW1wbGVyQ3ViZSBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwic2FtcGxlcjFEU2hhZG93IHNhbXBsZXIyRFNoYWRvdyBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiY29uc3QgYXR0cmlidXRlIHVuaWZvcm0gdmFyeWluZyBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiYnJlYWsgY29udGludWUgZGlzY2FyZCByZXR1cm4gXCIgK1xuICAgICAgICAgICAgICAgICAgICBcImZvciB3aGlsZSBkbyBpZiBlbHNlIHN0cnVjdCBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiaW4gb3V0IGlub3V0XCIpLFxuICAgIHR5cGVzOiB3b3JkcyhcImZsb2F0IGludCBib29sIHZvaWQgXCIgK1xuICAgICAgICAgICAgICAgICBcInZlYzIgdmVjMyB2ZWM0IGl2ZWMyIGl2ZWMzIGl2ZWM0IGJ2ZWMyIGJ2ZWMzIGJ2ZWM0IFwiICtcbiAgICAgICAgICAgICAgICAgXCJtYXQyIG1hdDMgbWF0NFwiKSxcbiAgICBibG9ja0tleXdvcmRzOiB3b3JkcyhcImZvciB3aGlsZSBkbyBpZiBlbHNlIHN0cnVjdFwiKSxcbiAgICBidWlsdGluOiB3b3JkcyhcInJhZGlhbnMgZGVncmVlcyBzaW4gY29zIHRhbiBhc2luIGFjb3MgYXRhbiBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwicG93IGV4cCBsb2cgZXhwMiBzcXJ0IGludmVyc2VzcXJ0IFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJhYnMgc2lnbiBmbG9vciBjZWlsIGZyYWN0IG1vZCBtaW4gbWF4IGNsYW1wIG1peCBzdGVwIHNtb290aHN0ZXAgXCIgK1xuICAgICAgICAgICAgICAgICAgICBcImxlbmd0aCBkaXN0YW5jZSBkb3QgY3Jvc3Mgbm9ybWFsaXplIGZ0cmFuc2Zvcm0gZmFjZWZvcndhcmQgXCIgK1xuICAgICAgICAgICAgICAgICAgICBcInJlZmxlY3QgcmVmcmFjdCBtYXRyaXhDb21wTXVsdCBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwibGVzc1RoYW4gbGVzc1RoYW5FcXVhbCBncmVhdGVyVGhhbiBncmVhdGVyVGhhbkVxdWFsIFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJlcXVhbCBub3RFcXVhbCBhbnkgYWxsIG5vdCBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwidGV4dHVyZTFEIHRleHR1cmUxRFByb2ogdGV4dHVyZTFETG9kIHRleHR1cmUxRFByb2pMb2QgXCIgK1xuICAgICAgICAgICAgICAgICAgICBcInRleHR1cmUyRCB0ZXh0dXJlMkRQcm9qIHRleHR1cmUyRExvZCB0ZXh0dXJlMkRQcm9qTG9kIFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJ0ZXh0dXJlM0QgdGV4dHVyZTNEUHJvaiB0ZXh0dXJlM0RMb2QgdGV4dHVyZTNEUHJvakxvZCBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwidGV4dHVyZUN1YmUgdGV4dHVyZUN1YmVMb2QgXCIgK1xuICAgICAgICAgICAgICAgICAgICBcInNoYWRvdzFEIHNoYWRvdzJEIHNoYWRvdzFEUHJvaiBzaGFkb3cyRFByb2ogXCIgK1xuICAgICAgICAgICAgICAgICAgICBcInNoYWRvdzFETG9kIHNoYWRvdzJETG9kIHNoYWRvdzFEUHJvakxvZCBzaGFkb3cyRFByb2pMb2QgXCIgK1xuICAgICAgICAgICAgICAgICAgICBcImRGZHggZEZkeSBmd2lkdGggXCIgK1xuICAgICAgICAgICAgICAgICAgICBcIm5vaXNlMSBub2lzZTIgbm9pc2UzIG5vaXNlNFwiKSxcbiAgICBhdG9tczogd29yZHMoXCJ0cnVlIGZhbHNlIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX0ZyYWdDb2xvciBnbF9TZWNvbmRhcnlDb2xvciBnbF9Ob3JtYWwgZ2xfVmVydGV4IFwiICtcbiAgICAgICAgICAgICAgICBcImdsX011bHRpVGV4Q29vcmQwIGdsX011bHRpVGV4Q29vcmQxIGdsX011bHRpVGV4Q29vcmQyIGdsX011bHRpVGV4Q29vcmQzIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX011bHRpVGV4Q29vcmQ0IGdsX011bHRpVGV4Q29vcmQ1IGdsX011bHRpVGV4Q29vcmQ2IGdsX011bHRpVGV4Q29vcmQ3IFwiICtcbiAgICAgICAgICAgICAgICBcImdsX0ZvZ0Nvb3JkIGdsX1BvaW50Q29vcmQgXCIgK1xuICAgICAgICAgICAgICAgIFwiZ2xfUG9zaXRpb24gZ2xfUG9pbnRTaXplIGdsX0NsaXBWZXJ0ZXggXCIgK1xuICAgICAgICAgICAgICAgIFwiZ2xfRnJvbnRDb2xvciBnbF9CYWNrQ29sb3IgZ2xfRnJvbnRTZWNvbmRhcnlDb2xvciBnbF9CYWNrU2Vjb25kYXJ5Q29sb3IgXCIgK1xuICAgICAgICAgICAgICAgIFwiZ2xfVGV4Q29vcmQgZ2xfRm9nRnJhZ0Nvb3JkIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX0ZyYWdDb29yZCBnbF9Gcm9udEZhY2luZyBcIiArXG4gICAgICAgICAgICAgICAgXCJnbF9GcmFnRGF0YSBnbF9GcmFnRGVwdGggXCIgK1xuICAgICAgICAgICAgICAgIFwiZ2xfTW9kZWxWaWV3TWF0cml4IGdsX1Byb2plY3Rpb25NYXRyaXggZ2xfTW9kZWxWaWV3UHJvamVjdGlvbk1hdHJpeCBcIiArXG4gICAgICAgICAgICAgICAgXCJnbF9UZXh0dXJlTWF0cml4IGdsX05vcm1hbE1hdHJpeCBnbF9Nb2RlbFZpZXdNYXRyaXhJbnZlcnNlIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX1Byb2plY3Rpb25NYXRyaXhJbnZlcnNlIGdsX01vZGVsVmlld1Byb2plY3Rpb25NYXRyaXhJbnZlcnNlIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX1RleHR1cmVNYXRyaXhUcmFuc3Bvc2UgZ2xfTW9kZWxWaWV3TWF0cml4SW52ZXJzZVRyYW5zcG9zZSBcIiArXG4gICAgICAgICAgICAgICAgXCJnbF9Qcm9qZWN0aW9uTWF0cml4SW52ZXJzZVRyYW5zcG9zZSBcIiArXG4gICAgICAgICAgICAgICAgXCJnbF9Nb2RlbFZpZXdQcm9qZWN0aW9uTWF0cml4SW52ZXJzZVRyYW5zcG9zZSBcIiArXG4gICAgICAgICAgICAgICAgXCJnbF9UZXh0dXJlTWF0cml4SW52ZXJzZVRyYW5zcG9zZSBcIiArXG4gICAgICAgICAgICAgICAgXCJnbF9Ob3JtYWxTY2FsZSBnbF9EZXB0aFJhbmdlIGdsX0NsaXBQbGFuZSBcIiArXG4gICAgICAgICAgICAgICAgXCJnbF9Qb2ludCBnbF9Gcm9udE1hdGVyaWFsIGdsX0JhY2tNYXRlcmlhbCBnbF9MaWdodFNvdXJjZSBnbF9MaWdodE1vZGVsIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX0Zyb250TGlnaHRNb2RlbFByb2R1Y3QgZ2xfQmFja0xpZ2h0TW9kZWxQcm9kdWN0IFwiICtcbiAgICAgICAgICAgICAgICBcImdsX1RleHR1cmVDb2xvciBnbF9FeWVQbGFuZVMgZ2xfRXllUGxhbmVUIGdsX0V5ZVBsYW5lUiBnbF9FeWVQbGFuZVEgXCIgK1xuICAgICAgICAgICAgICAgIFwiZ2xfRm9nUGFyYW1ldGVycyBcIiArXG4gICAgICAgICAgICAgICAgXCJnbF9NYXhMaWdodHMgZ2xfTWF4Q2xpcFBsYW5lcyBnbF9NYXhUZXh0dXJlVW5pdHMgZ2xfTWF4VGV4dHVyZUNvb3JkcyBcIiArXG4gICAgICAgICAgICAgICAgXCJnbF9NYXhWZXJ0ZXhBdHRyaWJzIGdsX01heFZlcnRleFVuaWZvcm1Db21wb25lbnRzIGdsX01heFZhcnlpbmdGbG9hdHMgXCIgK1xuICAgICAgICAgICAgICAgIFwiZ2xfTWF4VmVydGV4VGV4dHVyZUltYWdlVW5pdHMgZ2xfTWF4VGV4dHVyZUltYWdlVW5pdHMgXCIgK1xuICAgICAgICAgICAgICAgIFwiZ2xfTWF4RnJhZ21lbnRVbmlmb3JtQ29tcG9uZW50cyBnbF9NYXhDb21iaW5lVGV4dHVyZUltYWdlVW5pdHMgXCIgK1xuICAgICAgICAgICAgICAgIFwiZ2xfTWF4RHJhd0J1ZmZlcnNcIiksXG4gICAgaW5kZW50U3dpdGNoOiBmYWxzZSxcbiAgICBob29rczoge1wiI1wiOiBjcHBIb29rfSxcbiAgICBtb2RlUHJvcHM6IHtmb2xkOiBbXCJicmFjZVwiLCBcImluY2x1ZGVcIl19XG4gIH0pO1xuXG4gIGRlZihcInRleHQveC1uZXNjXCIsIHtcbiAgICBuYW1lOiBcImNsaWtlXCIsXG4gICAga2V5d29yZHM6IHdvcmRzKGNLZXl3b3JkcyArIFwiIGFzIGF0b21pYyBhc3luYyBjYWxsIGNvbW1hbmQgY29tcG9uZW50IGNvbXBvbmVudHMgY29uZmlndXJhdGlvbiBldmVudCBnZW5lcmljIFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJpbXBsZW1lbnRhdGlvbiBpbmNsdWRlcyBpbnRlcmZhY2UgbW9kdWxlIG5ldyBub3JhY2Ugbnhfc3RydWN0IG54X3VuaW9uIHBvc3QgcHJvdmlkZXMgXCIgK1xuICAgICAgICAgICAgICAgICAgICBcInNpZ25hbCB0YXNrIHVzZXMgYWJzdHJhY3QgZXh0ZW5kc1wiKSxcbiAgICB0eXBlczogY1R5cGVzLFxuICAgIGJsb2NrS2V5d29yZHM6IHdvcmRzKGNCbG9ja0tleXdvcmRzKSxcbiAgICBhdG9tczogd29yZHMoXCJudWxsIHRydWUgZmFsc2VcIiksXG4gICAgaG9va3M6IHtcIiNcIjogY3BwSG9va30sXG4gICAgbW9kZVByb3BzOiB7Zm9sZDogW1wiYnJhY2VcIiwgXCJpbmNsdWRlXCJdfVxuICB9KTtcblxuICBkZWYoXCJ0ZXh0L3gtb2JqZWN0aXZlY1wiLCB7XG4gICAgbmFtZTogXCJjbGlrZVwiLFxuICAgIGtleXdvcmRzOiB3b3JkcyhjS2V5d29yZHMgKyBcIiBcIiArIG9iakNLZXl3b3JkcyksXG4gICAgdHlwZXM6IG9iakNUeXBlcyxcbiAgICBidWlsdGluOiB3b3JkcyhvYmpDQnVpbHRpbnMpLFxuICAgIGJsb2NrS2V5d29yZHM6IHdvcmRzKGNCbG9ja0tleXdvcmRzICsgXCIgQHN5bnRoZXNpemUgQHRyeSBAY2F0Y2ggQGZpbmFsbHkgQGF1dG9yZWxlYXNlcG9vbCBAc3luY2hyb25pemVkXCIpLFxuICAgIGRlZktleXdvcmRzOiB3b3JkcyhjRGVmS2V5d29yZHMgKyBcIiBAaW50ZXJmYWNlIEBpbXBsZW1lbnRhdGlvbiBAcHJvdG9jb2wgQGNsYXNzXCIpLFxuICAgIGRvbnRJbmRlbnRTdGF0ZW1lbnRzOiAvXkAuKiQvLFxuICAgIHR5cGVGaXJzdERlZmluaXRpb25zOiB0cnVlLFxuICAgIGF0b21zOiB3b3JkcyhcIllFUyBOTyBOVUxMIE5pbCBuaWwgdHJ1ZSBmYWxzZSBudWxscHRyXCIpLFxuICAgIGlzUmVzZXJ2ZWRJZGVudGlmaWVyOiBjSXNSZXNlcnZlZElkZW50aWZpZXIsXG4gICAgaG9va3M6IHtcbiAgICAgIFwiI1wiOiBjcHBIb29rLFxuICAgICAgXCIqXCI6IHBvaW50ZXJIb29rLFxuICAgIH0sXG4gICAgbW9kZVByb3BzOiB7Zm9sZDogW1wiYnJhY2VcIiwgXCJpbmNsdWRlXCJdfVxuICB9KTtcblxuICBkZWYoXCJ0ZXh0L3gtb2JqZWN0aXZlYysrXCIsIHtcbiAgICBuYW1lOiBcImNsaWtlXCIsXG4gICAga2V5d29yZHM6IHdvcmRzKGNLZXl3b3JkcyArIFwiIFwiICsgb2JqQ0tleXdvcmRzICsgXCIgXCIgKyBjcHBLZXl3b3JkcyksXG4gICAgdHlwZXM6IG9iakNUeXBlcyxcbiAgICBidWlsdGluOiB3b3JkcyhvYmpDQnVpbHRpbnMpLFxuICAgIGJsb2NrS2V5d29yZHM6IHdvcmRzKGNCbG9ja0tleXdvcmRzICsgXCIgQHN5bnRoZXNpemUgQHRyeSBAY2F0Y2ggQGZpbmFsbHkgQGF1dG9yZWxlYXNlcG9vbCBAc3luY2hyb25pemVkIGNsYXNzIHRyeSBjYXRjaFwiKSxcbiAgICBkZWZLZXl3b3Jkczogd29yZHMoY0RlZktleXdvcmRzICsgXCIgQGludGVyZmFjZSBAaW1wbGVtZW50YXRpb24gQHByb3RvY29sIEBjbGFzcyBjbGFzcyBuYW1lc3BhY2VcIiksXG4gICAgZG9udEluZGVudFN0YXRlbWVudHM6IC9eQC4qJHxedGVtcGxhdGUkLyxcbiAgICB0eXBlRmlyc3REZWZpbml0aW9uczogdHJ1ZSxcbiAgICBhdG9tczogd29yZHMoXCJZRVMgTk8gTlVMTCBOaWwgbmlsIHRydWUgZmFsc2UgbnVsbHB0clwiKSxcbiAgICBpc1Jlc2VydmVkSWRlbnRpZmllcjogY0lzUmVzZXJ2ZWRJZGVudGlmaWVyLFxuICAgIGhvb2tzOiB7XG4gICAgICBcIiNcIjogY3BwSG9vayxcbiAgICAgIFwiKlwiOiBwb2ludGVySG9vayxcbiAgICAgIFwidVwiOiBjcHAxMVN0cmluZ0hvb2ssXG4gICAgICBcIlVcIjogY3BwMTFTdHJpbmdIb29rLFxuICAgICAgXCJMXCI6IGNwcDExU3RyaW5nSG9vayxcbiAgICAgIFwiUlwiOiBjcHAxMVN0cmluZ0hvb2ssXG4gICAgICBcIjBcIjogY3BwMTRMaXRlcmFsLFxuICAgICAgXCIxXCI6IGNwcDE0TGl0ZXJhbCxcbiAgICAgIFwiMlwiOiBjcHAxNExpdGVyYWwsXG4gICAgICBcIjNcIjogY3BwMTRMaXRlcmFsLFxuICAgICAgXCI0XCI6IGNwcDE0TGl0ZXJhbCxcbiAgICAgIFwiNVwiOiBjcHAxNExpdGVyYWwsXG4gICAgICBcIjZcIjogY3BwMTRMaXRlcmFsLFxuICAgICAgXCI3XCI6IGNwcDE0TGl0ZXJhbCxcbiAgICAgIFwiOFwiOiBjcHAxNExpdGVyYWwsXG4gICAgICBcIjlcIjogY3BwMTRMaXRlcmFsLFxuICAgICAgdG9rZW46IGZ1bmN0aW9uKHN0cmVhbSwgc3RhdGUsIHN0eWxlKSB7XG4gICAgICAgIGlmIChzdHlsZSA9PSBcInZhcmlhYmxlXCIgJiYgc3RyZWFtLnBlZWsoKSA9PSBcIihcIiAmJlxuICAgICAgICAgICAgKHN0YXRlLnByZXZUb2tlbiA9PSBcIjtcIiB8fCBzdGF0ZS5wcmV2VG9rZW4gPT0gbnVsbCB8fFxuICAgICAgICAgICAgIHN0YXRlLnByZXZUb2tlbiA9PSBcIn1cIikgJiZcbiAgICAgICAgICAgIGNwcExvb2tzTGlrZUNvbnN0cnVjdG9yKHN0cmVhbS5jdXJyZW50KCkpKVxuICAgICAgICAgIHJldHVybiBcImRlZlwiO1xuICAgICAgfVxuICAgIH0sXG4gICAgbmFtZXNwYWNlU2VwYXJhdG9yOiBcIjo6XCIsXG4gICAgbW9kZVByb3BzOiB7Zm9sZDogW1wiYnJhY2VcIiwgXCJpbmNsdWRlXCJdfVxuICB9KTtcblxuICBkZWYoXCJ0ZXh0L3gtc3F1aXJyZWxcIiwge1xuICAgIG5hbWU6IFwiY2xpa2VcIixcbiAgICBrZXl3b3Jkczogd29yZHMoXCJiYXNlIGJyZWFrIGNsb25lIGNvbnRpbnVlIGNvbnN0IGRlZmF1bHQgZGVsZXRlIGVudW0gZXh0ZW5kcyBmdW5jdGlvbiBpbiBjbGFzc1wiICtcbiAgICAgICAgICAgICAgICAgICAgXCIgZm9yZWFjaCBsb2NhbCByZXN1bWUgcmV0dXJuIHRoaXMgdGhyb3cgdHlwZW9mIHlpZWxkIGNvbnN0cnVjdG9yIGluc3RhbmNlb2Ygc3RhdGljXCIpLFxuICAgIHR5cGVzOiBjVHlwZXMsXG4gICAgYmxvY2tLZXl3b3Jkczogd29yZHMoXCJjYXNlIGNhdGNoIGNsYXNzIGVsc2UgZm9yIGZvcmVhY2ggaWYgc3dpdGNoIHRyeSB3aGlsZVwiKSxcbiAgICBkZWZLZXl3b3Jkczogd29yZHMoXCJmdW5jdGlvbiBsb2NhbCBjbGFzc1wiKSxcbiAgICB0eXBlRmlyc3REZWZpbml0aW9uczogdHJ1ZSxcbiAgICBhdG9tczogd29yZHMoXCJ0cnVlIGZhbHNlIG51bGxcIiksXG4gICAgaG9va3M6IHtcIiNcIjogY3BwSG9va30sXG4gICAgbW9kZVByb3BzOiB7Zm9sZDogW1wiYnJhY2VcIiwgXCJpbmNsdWRlXCJdfVxuICB9KTtcblxuICAvLyBDZXlsb24gU3RyaW5ncyBuZWVkIHRvIGRlYWwgd2l0aCBpbnRlcnBvbGF0aW9uXG4gIHZhciBzdHJpbmdUb2tlbml6ZXIgPSBudWxsO1xuICBmdW5jdGlvbiB0b2tlbkNleWxvblN0cmluZyh0eXBlKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgIHZhciBlc2NhcGVkID0gZmFsc2UsIG5leHQsIGVuZCA9IGZhbHNlO1xuICAgICAgd2hpbGUgKCFzdHJlYW0uZW9sKCkpIHtcbiAgICAgICAgaWYgKCFlc2NhcGVkICYmIHN0cmVhbS5tYXRjaCgnXCInKSAmJlxuICAgICAgICAgICAgICAodHlwZSA9PSBcInNpbmdsZVwiIHx8IHN0cmVhbS5tYXRjaCgnXCJcIicpKSkge1xuICAgICAgICAgIGVuZCA9IHRydWU7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFlc2NhcGVkICYmIHN0cmVhbS5tYXRjaCgnYGAnKSkge1xuICAgICAgICAgIHN0cmluZ1Rva2VuaXplciA9IHRva2VuQ2V5bG9uU3RyaW5nKHR5cGUpO1xuICAgICAgICAgIGVuZCA9IHRydWU7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgbmV4dCA9IHN0cmVhbS5uZXh0KCk7XG4gICAgICAgIGVzY2FwZWQgPSB0eXBlID09IFwic2luZ2xlXCIgJiYgIWVzY2FwZWQgJiYgbmV4dCA9PSBcIlxcXFxcIjtcbiAgICAgIH1cbiAgICAgIGlmIChlbmQpXG4gICAgICAgICAgc3RhdGUudG9rZW5pemUgPSBudWxsO1xuICAgICAgcmV0dXJuIFwic3RyaW5nXCI7XG4gICAgfVxuICB9XG5cbiAgZGVmKFwidGV4dC94LWNleWxvblwiLCB7XG4gICAgbmFtZTogXCJjbGlrZVwiLFxuICAgIGtleXdvcmRzOiB3b3JkcyhcImFic3RyYWN0cyBhbGlhcyBhc3NlbWJseSBhc3NlcnQgYXNzaWduIGJyZWFrIGNhc2UgY2F0Y2ggY2xhc3MgY29udGludWUgZHluYW1pYyBlbHNlXCIgK1xuICAgICAgICAgICAgICAgICAgICBcIiBleGlzdHMgZXh0ZW5kcyBmaW5hbGx5IGZvciBmdW5jdGlvbiBnaXZlbiBpZiBpbXBvcnQgaW4gaW50ZXJmYWNlIGlzIGxldCBtb2R1bGUgbmV3XCIgK1xuICAgICAgICAgICAgICAgICAgICBcIiBub25lbXB0eSBvYmplY3Qgb2Ygb3V0IG91dGVyIHBhY2thZ2UgcmV0dXJuIHNhdGlzZmllcyBzdXBlciBzd2l0Y2ggdGhlbiB0aGlzIHRocm93XCIgK1xuICAgICAgICAgICAgICAgICAgICBcIiB0cnkgdmFsdWUgdm9pZCB3aGlsZVwiKSxcbiAgICB0eXBlczogZnVuY3Rpb24od29yZCkge1xuICAgICAgICAvLyBJbiBDZXlsb24gYWxsIGlkZW50aWZpZXJzIHRoYXQgc3RhcnQgd2l0aCBhbiB1cHBlcmNhc2UgYXJlIHR5cGVzXG4gICAgICAgIHZhciBmaXJzdCA9IHdvcmQuY2hhckF0KDApO1xuICAgICAgICByZXR1cm4gKGZpcnN0ID09PSBmaXJzdC50b1VwcGVyQ2FzZSgpICYmIGZpcnN0ICE9PSBmaXJzdC50b0xvd2VyQ2FzZSgpKTtcbiAgICB9LFxuICAgIGJsb2NrS2V5d29yZHM6IHdvcmRzKFwiY2FzZSBjYXRjaCBjbGFzcyBkeW5hbWljIGVsc2UgZmluYWxseSBmb3IgZnVuY3Rpb24gaWYgaW50ZXJmYWNlIG1vZHVsZSBuZXcgb2JqZWN0IHN3aXRjaCB0cnkgd2hpbGVcIiksXG4gICAgZGVmS2V5d29yZHM6IHdvcmRzKFwiY2xhc3MgZHluYW1pYyBmdW5jdGlvbiBpbnRlcmZhY2UgbW9kdWxlIG9iamVjdCBwYWNrYWdlIHZhbHVlXCIpLFxuICAgIGJ1aWx0aW46IHdvcmRzKFwiYWJzdHJhY3QgYWN0dWFsIGFsaWFzZWQgYW5ub3RhdGlvbiBieSBkZWZhdWx0IGRlcHJlY2F0ZWQgZG9jIGZpbmFsIGZvcm1hbCBsYXRlIGxpY2Vuc2VcIiArXG4gICAgICAgICAgICAgICAgICAgXCIgbmF0aXZlIG9wdGlvbmFsIHNlYWxlZCBzZWUgc2VyaWFsaXphYmxlIHNoYXJlZCBzdXBwcmVzc1dhcm5pbmdzIHRhZ2dlZCB0aHJvd3MgdmFyaWFibGVcIiksXG4gICAgaXNQdW5jdHVhdGlvbkNoYXI6IC9bXFxbXFxde31cXChcXCksO1xcOlxcLmBdLyxcbiAgICBpc09wZXJhdG9yQ2hhcjogL1srXFwtKiYlPTw+IT98Xn46XFwvXS8sXG4gICAgbnVtYmVyU3RhcnQ6IC9bXFxkIyRdLyxcbiAgICBudW1iZXI6IC9eKD86I1tcXGRhLWZBLUZfXSt8XFwkWzAxX10rfFtcXGRfXStba01HVFBtdW5wZl0/fFtcXGRfXStcXC5bXFxkX10rKD86W2VFXVstK10/XFxkK3xba01HVFBtdW5wZl18KXwpL2ksXG4gICAgbXVsdGlMaW5lU3RyaW5nczogdHJ1ZSxcbiAgICB0eXBlRmlyc3REZWZpbml0aW9uczogdHJ1ZSxcbiAgICBhdG9tczogd29yZHMoXCJ0cnVlIGZhbHNlIG51bGwgbGFyZ2VyIHNtYWxsZXIgZXF1YWwgZW1wdHkgZmluaXNoZWRcIiksXG4gICAgaW5kZW50U3dpdGNoOiBmYWxzZSxcbiAgICBzdHlsZURlZnM6IGZhbHNlLFxuICAgIGhvb2tzOiB7XG4gICAgICBcIkBcIjogZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgIHN0cmVhbS5lYXRXaGlsZSgvW1xcd1xcJF9dLyk7XG4gICAgICAgIHJldHVybiBcIm1ldGFcIjtcbiAgICAgIH0sXG4gICAgICAnXCInOiBmdW5jdGlvbihzdHJlYW0sIHN0YXRlKSB7XG4gICAgICAgICAgc3RhdGUudG9rZW5pemUgPSB0b2tlbkNleWxvblN0cmluZyhzdHJlYW0ubWF0Y2goJ1wiXCInKSA/IFwidHJpcGxlXCIgOiBcInNpbmdsZVwiKTtcbiAgICAgICAgICByZXR1cm4gc3RhdGUudG9rZW5pemUoc3RyZWFtLCBzdGF0ZSk7XG4gICAgICAgIH0sXG4gICAgICAnYCc6IGZ1bmN0aW9uKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgICAgICBpZiAoIXN0cmluZ1Rva2VuaXplciB8fCAhc3RyZWFtLm1hdGNoKCdgJykpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IHN0cmluZ1Rva2VuaXplcjtcbiAgICAgICAgICBzdHJpbmdUb2tlbml6ZXIgPSBudWxsO1xuICAgICAgICAgIHJldHVybiBzdGF0ZS50b2tlbml6ZShzdHJlYW0sIHN0YXRlKTtcbiAgICAgICAgfSxcbiAgICAgIFwiJ1wiOiBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgc3RyZWFtLmVhdFdoaWxlKC9bXFx3XFwkX1xceGExLVxcdWZmZmZdLyk7XG4gICAgICAgIHJldHVybiBcImF0b21cIjtcbiAgICAgIH0sXG4gICAgICB0b2tlbjogZnVuY3Rpb24oX3N0cmVhbSwgc3RhdGUsIHN0eWxlKSB7XG4gICAgICAgICAgaWYgKChzdHlsZSA9PSBcInZhcmlhYmxlXCIgfHwgc3R5bGUgPT0gXCJ0eXBlXCIpICYmXG4gICAgICAgICAgICAgIHN0YXRlLnByZXZUb2tlbiA9PSBcIi5cIikge1xuICAgICAgICAgICAgcmV0dXJuIFwidmFyaWFibGUtMlwiO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG4gICAgbW9kZVByb3BzOiB7XG4gICAgICAgIGZvbGQ6IFtcImJyYWNlXCIsIFwiaW1wb3J0XCJdLFxuICAgICAgICBjbG9zZUJyYWNrZXRzOiB7dHJpcGxlczogJ1wiJ31cbiAgICB9XG4gIH0pO1xuXG59KTtcbiIsIi8vIENvZGVNaXJyb3IsIGNvcHlyaWdodCAoYykgYnkgTWFyaWpuIEhhdmVyYmVrZSBhbmQgb3RoZXJzXG4vLyBEaXN0cmlidXRlZCB1bmRlciBhbiBNSVQgbGljZW5zZTogaHR0cHM6Ly9jb2RlbWlycm9yLm5ldC9MSUNFTlNFXG5cbihmdW5jdGlvbihtb2QpIHtcbiAgaWYgKHR5cGVvZiBleHBvcnRzID09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZSA9PSBcIm9iamVjdFwiKSAvLyBDb21tb25KU1xuICAgIG1vZChyZXF1aXJlKFwiLi4vLi4vbGliL2NvZGVtaXJyb3JcIikpO1xuICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSAvLyBBTURcbiAgICBkZWZpbmUoW1wiLi4vLi4vbGliL2NvZGVtaXJyb3JcIl0sIG1vZCk7XG4gIGVsc2UgLy8gUGxhaW4gYnJvd3NlciBlbnZcbiAgICBtb2QoQ29kZU1pcnJvcik7XG59KShmdW5jdGlvbihDb2RlTWlycm9yKSB7XG5cInVzZSBzdHJpY3RcIjtcblxuQ29kZU1pcnJvci5kZWZpbmVNb2RlKFwiY3NzXCIsIGZ1bmN0aW9uKGNvbmZpZywgcGFyc2VyQ29uZmlnKSB7XG4gIHZhciBpbmxpbmUgPSBwYXJzZXJDb25maWcuaW5saW5lXG4gIGlmICghcGFyc2VyQ29uZmlnLnByb3BlcnR5S2V5d29yZHMpIHBhcnNlckNvbmZpZyA9IENvZGVNaXJyb3IucmVzb2x2ZU1vZGUoXCJ0ZXh0L2Nzc1wiKTtcblxuICB2YXIgaW5kZW50VW5pdCA9IGNvbmZpZy5pbmRlbnRVbml0LFxuICAgICAgdG9rZW5Ib29rcyA9IHBhcnNlckNvbmZpZy50b2tlbkhvb2tzLFxuICAgICAgZG9jdW1lbnRUeXBlcyA9IHBhcnNlckNvbmZpZy5kb2N1bWVudFR5cGVzIHx8IHt9LFxuICAgICAgbWVkaWFUeXBlcyA9IHBhcnNlckNvbmZpZy5tZWRpYVR5cGVzIHx8IHt9LFxuICAgICAgbWVkaWFGZWF0dXJlcyA9IHBhcnNlckNvbmZpZy5tZWRpYUZlYXR1cmVzIHx8IHt9LFxuICAgICAgbWVkaWFWYWx1ZUtleXdvcmRzID0gcGFyc2VyQ29uZmlnLm1lZGlhVmFsdWVLZXl3b3JkcyB8fCB7fSxcbiAgICAgIHByb3BlcnR5S2V5d29yZHMgPSBwYXJzZXJDb25maWcucHJvcGVydHlLZXl3b3JkcyB8fCB7fSxcbiAgICAgIG5vblN0YW5kYXJkUHJvcGVydHlLZXl3b3JkcyA9IHBhcnNlckNvbmZpZy5ub25TdGFuZGFyZFByb3BlcnR5S2V5d29yZHMgfHwge30sXG4gICAgICBmb250UHJvcGVydGllcyA9IHBhcnNlckNvbmZpZy5mb250UHJvcGVydGllcyB8fCB7fSxcbiAgICAgIGNvdW50ZXJEZXNjcmlwdG9ycyA9IHBhcnNlckNvbmZpZy5jb3VudGVyRGVzY3JpcHRvcnMgfHwge30sXG4gICAgICBjb2xvcktleXdvcmRzID0gcGFyc2VyQ29uZmlnLmNvbG9yS2V5d29yZHMgfHwge30sXG4gICAgICB2YWx1ZUtleXdvcmRzID0gcGFyc2VyQ29uZmlnLnZhbHVlS2V5d29yZHMgfHwge30sXG4gICAgICBhbGxvd05lc3RlZCA9IHBhcnNlckNvbmZpZy5hbGxvd05lc3RlZCxcbiAgICAgIGxpbmVDb21tZW50ID0gcGFyc2VyQ29uZmlnLmxpbmVDb21tZW50LFxuICAgICAgc3VwcG9ydHNBdENvbXBvbmVudCA9IHBhcnNlckNvbmZpZy5zdXBwb3J0c0F0Q29tcG9uZW50ID09PSB0cnVlLFxuICAgICAgaGlnaGxpZ2h0Tm9uU3RhbmRhcmRQcm9wZXJ0eUtleXdvcmRzID0gY29uZmlnLmhpZ2hsaWdodE5vblN0YW5kYXJkUHJvcGVydHlLZXl3b3JkcyAhPT0gZmFsc2U7XG5cbiAgdmFyIHR5cGUsIG92ZXJyaWRlO1xuICBmdW5jdGlvbiByZXQoc3R5bGUsIHRwKSB7IHR5cGUgPSB0cDsgcmV0dXJuIHN0eWxlOyB9XG5cbiAgLy8gVG9rZW5pemVyc1xuXG4gIGZ1bmN0aW9uIHRva2VuQmFzZShzdHJlYW0sIHN0YXRlKSB7XG4gICAgdmFyIGNoID0gc3RyZWFtLm5leHQoKTtcbiAgICBpZiAodG9rZW5Ib29rc1tjaF0pIHtcbiAgICAgIHZhciByZXN1bHQgPSB0b2tlbkhvb2tzW2NoXShzdHJlYW0sIHN0YXRlKTtcbiAgICAgIGlmIChyZXN1bHQgIT09IGZhbHNlKSByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICBpZiAoY2ggPT0gXCJAXCIpIHtcbiAgICAgIHN0cmVhbS5lYXRXaGlsZSgvW1xcd1xcXFxcXC1dLyk7XG4gICAgICByZXR1cm4gcmV0KFwiZGVmXCIsIHN0cmVhbS5jdXJyZW50KCkpO1xuICAgIH0gZWxzZSBpZiAoY2ggPT0gXCI9XCIgfHwgKGNoID09IFwiflwiIHx8IGNoID09IFwifFwiKSAmJiBzdHJlYW0uZWF0KFwiPVwiKSkge1xuICAgICAgcmV0dXJuIHJldChudWxsLCBcImNvbXBhcmVcIik7XG4gICAgfSBlbHNlIGlmIChjaCA9PSBcIlxcXCJcIiB8fCBjaCA9PSBcIidcIikge1xuICAgICAgc3RhdGUudG9rZW5pemUgPSB0b2tlblN0cmluZyhjaCk7XG4gICAgICByZXR1cm4gc3RhdGUudG9rZW5pemUoc3RyZWFtLCBzdGF0ZSk7XG4gICAgfSBlbHNlIGlmIChjaCA9PSBcIiNcIikge1xuICAgICAgc3RyZWFtLmVhdFdoaWxlKC9bXFx3XFxcXFxcLV0vKTtcbiAgICAgIHJldHVybiByZXQoXCJhdG9tXCIsIFwiaGFzaFwiKTtcbiAgICB9IGVsc2UgaWYgKGNoID09IFwiIVwiKSB7XG4gICAgICBzdHJlYW0ubWF0Y2goL15cXHMqXFx3Ki8pO1xuICAgICAgcmV0dXJuIHJldChcImtleXdvcmRcIiwgXCJpbXBvcnRhbnRcIik7XG4gICAgfSBlbHNlIGlmICgvXFxkLy50ZXN0KGNoKSB8fCBjaCA9PSBcIi5cIiAmJiBzdHJlYW0uZWF0KC9cXGQvKSkge1xuICAgICAgc3RyZWFtLmVhdFdoaWxlKC9bXFx3LiVdLyk7XG4gICAgICByZXR1cm4gcmV0KFwibnVtYmVyXCIsIFwidW5pdFwiKTtcbiAgICB9IGVsc2UgaWYgKGNoID09PSBcIi1cIikge1xuICAgICAgaWYgKC9bXFxkLl0vLnRlc3Qoc3RyZWFtLnBlZWsoKSkpIHtcbiAgICAgICAgc3RyZWFtLmVhdFdoaWxlKC9bXFx3LiVdLyk7XG4gICAgICAgIHJldHVybiByZXQoXCJudW1iZXJcIiwgXCJ1bml0XCIpO1xuICAgICAgfSBlbHNlIGlmIChzdHJlYW0ubWF0Y2goL14tW1xcd1xcXFxcXC1dKi8pKSB7XG4gICAgICAgIHN0cmVhbS5lYXRXaGlsZSgvW1xcd1xcXFxcXC1dLyk7XG4gICAgICAgIGlmIChzdHJlYW0ubWF0Y2goL15cXHMqOi8sIGZhbHNlKSlcbiAgICAgICAgICByZXR1cm4gcmV0KFwidmFyaWFibGUtMlwiLCBcInZhcmlhYmxlLWRlZmluaXRpb25cIik7XG4gICAgICAgIHJldHVybiByZXQoXCJ2YXJpYWJsZS0yXCIsIFwidmFyaWFibGVcIik7XG4gICAgICB9IGVsc2UgaWYgKHN0cmVhbS5tYXRjaCgvXlxcdystLykpIHtcbiAgICAgICAgcmV0dXJuIHJldChcIm1ldGFcIiwgXCJtZXRhXCIpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoL1ssKz4qXFwvXS8udGVzdChjaCkpIHtcbiAgICAgIHJldHVybiByZXQobnVsbCwgXCJzZWxlY3Qtb3BcIik7XG4gICAgfSBlbHNlIGlmIChjaCA9PSBcIi5cIiAmJiBzdHJlYW0ubWF0Y2goL14tP1tfYS16XVtfYS16MC05LV0qL2kpKSB7XG4gICAgICByZXR1cm4gcmV0KFwicXVhbGlmaWVyXCIsIFwicXVhbGlmaWVyXCIpO1xuICAgIH0gZWxzZSBpZiAoL1s6O3t9XFxbXFxdXFwoXFwpXS8udGVzdChjaCkpIHtcbiAgICAgIHJldHVybiByZXQobnVsbCwgY2gpO1xuICAgIH0gZWxzZSBpZiAoc3RyZWFtLm1hdGNoKC9eW1xcdy0uXSsoPz1cXCgpLykpIHtcbiAgICAgIGlmICgvXih1cmwoLXByZWZpeCk/fGRvbWFpbnxyZWdleHApJC9pLnRlc3Qoc3RyZWFtLmN1cnJlbnQoKSkpIHtcbiAgICAgICAgc3RhdGUudG9rZW5pemUgPSB0b2tlblBhcmVudGhlc2l6ZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmV0KFwidmFyaWFibGUgY2FsbGVlXCIsIFwidmFyaWFibGVcIik7XG4gICAgfSBlbHNlIGlmICgvW1xcd1xcXFxcXC1dLy50ZXN0KGNoKSkge1xuICAgICAgc3RyZWFtLmVhdFdoaWxlKC9bXFx3XFxcXFxcLV0vKTtcbiAgICAgIHJldHVybiByZXQoXCJwcm9wZXJ0eVwiLCBcIndvcmRcIik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiByZXQobnVsbCwgbnVsbCk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gdG9rZW5TdHJpbmcocXVvdGUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oc3RyZWFtLCBzdGF0ZSkge1xuICAgICAgdmFyIGVzY2FwZWQgPSBmYWxzZSwgY2g7XG4gICAgICB3aGlsZSAoKGNoID0gc3RyZWFtLm5leHQoKSkgIT0gbnVsbCkge1xuICAgICAgICBpZiAoY2ggPT0gcXVvdGUgJiYgIWVzY2FwZWQpIHtcbiAgICAgICAgICBpZiAocXVvdGUgPT0gXCIpXCIpIHN0cmVhbS5iYWNrVXAoMSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgZXNjYXBlZCA9ICFlc2NhcGVkICYmIGNoID09IFwiXFxcXFwiO1xuICAgICAgfVxuICAgICAgaWYgKGNoID09IHF1b3RlIHx8ICFlc2NhcGVkICYmIHF1b3RlICE9IFwiKVwiKSBzdGF0ZS50b2tlbml6ZSA9IG51bGw7XG4gICAgICByZXR1cm4gcmV0KFwic3RyaW5nXCIsIFwic3RyaW5nXCIpO1xuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiB0b2tlblBhcmVudGhlc2l6ZWQoc3RyZWFtLCBzdGF0ZSkge1xuICAgIHN0cmVhbS5uZXh0KCk7IC8vIE11c3QgYmUgJygnXG4gICAgaWYgKCFzdHJlYW0ubWF0Y2goL15cXHMqW1xcXCJcXCcpXS8sIGZhbHNlKSlcbiAgICAgIHN0YXRlLnRva2VuaXplID0gdG9rZW5TdHJpbmcoXCIpXCIpO1xuICAgIGVsc2VcbiAgICAgIHN0YXRlLnRva2VuaXplID0gbnVsbDtcbiAgICByZXR1cm4gcmV0KG51bGwsIFwiKFwiKTtcbiAgfVxuXG4gIC8vIENvbnRleHQgbWFuYWdlbWVudFxuXG4gIGZ1bmN0aW9uIENvbnRleHQodHlwZSwgaW5kZW50LCBwcmV2KSB7XG4gICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB0aGlzLmluZGVudCA9IGluZGVudDtcbiAgICB0aGlzLnByZXYgPSBwcmV2O1xuICB9XG5cbiAgZnVuY3Rpb24gcHVzaENvbnRleHQoc3RhdGUsIHN0cmVhbSwgdHlwZSwgaW5kZW50KSB7XG4gICAgc3RhdGUuY29udGV4dCA9IG5ldyBDb250ZXh0KHR5cGUsIHN0cmVhbS5pbmRlbnRhdGlvbigpICsgKGluZGVudCA9PT0gZmFsc2UgPyAwIDogaW5kZW50VW5pdCksIHN0YXRlLmNvbnRleHQpO1xuICAgIHJldHVybiB0eXBlO1xuICB9XG5cbiAgZnVuY3Rpb24gcG9wQ29udGV4dChzdGF0ZSkge1xuICAgIGlmIChzdGF0ZS5jb250ZXh0LnByZXYpXG4gICAgICBzdGF0ZS5jb250ZXh0ID0gc3RhdGUuY29udGV4dC5wcmV2O1xuICAgIHJldHVybiBzdGF0ZS5jb250ZXh0LnR5cGU7XG4gIH1cblxuICBmdW5jdGlvbiBwYXNzKHR5cGUsIHN0cmVhbSwgc3RhdGUpIHtcbiAgICByZXR1cm4gc3RhdGVzW3N0YXRlLmNvbnRleHQudHlwZV0odHlwZSwgc3RyZWFtLCBzdGF0ZSk7XG4gIH1cbiAgZnVuY3Rpb24gcG9wQW5kUGFzcyh0eXBlLCBzdHJlYW0sIHN0YXRlLCBuKSB7XG4gICAgZm9yICh2YXIgaSA9IG4gfHwgMTsgaSA+IDA7IGktLSlcbiAgICAgIHN0YXRlLmNvbnRleHQgPSBzdGF0ZS5jb250ZXh0LnByZXY7XG4gICAgcmV0dXJuIHBhc3ModHlwZSwgc3RyZWFtLCBzdGF0ZSk7XG4gIH1cblxuICAvLyBQYXJzZXJcblxuICBmdW5jdGlvbiB3b3JkQXNWYWx1ZShzdHJlYW0pIHtcbiAgICB2YXIgd29yZCA9IHN0cmVhbS5jdXJyZW50KCkudG9Mb3dlckNhc2UoKTtcbiAgICBpZiAodmFsdWVLZXl3b3Jkcy5oYXNPd25Qcm9wZXJ0eSh3b3JkKSlcbiAgICAgIG92ZXJyaWRlID0gXCJhdG9tXCI7XG4gICAgZWxzZSBpZiAoY29sb3JLZXl3b3Jkcy5oYXNPd25Qcm9wZXJ0eSh3b3JkKSlcbiAgICAgIG92ZXJyaWRlID0gXCJrZXl3b3JkXCI7XG4gICAgZWxzZVxuICAgICAgb3ZlcnJpZGUgPSBcInZhcmlhYmxlXCI7XG4gIH1cblxuICB2YXIgc3RhdGVzID0ge307XG5cbiAgc3RhdGVzLnRvcCA9IGZ1bmN0aW9uKHR5cGUsIHN0cmVhbSwgc3RhdGUpIHtcbiAgICBpZiAodHlwZSA9PSBcIntcIikge1xuICAgICAgcmV0dXJuIHB1c2hDb250ZXh0KHN0YXRlLCBzdHJlYW0sIFwiYmxvY2tcIik7XG4gICAgfSBlbHNlIGlmICh0eXBlID09IFwifVwiICYmIHN0YXRlLmNvbnRleHQucHJldikge1xuICAgICAgcmV0dXJuIHBvcENvbnRleHQoc3RhdGUpO1xuICAgIH0gZWxzZSBpZiAoc3VwcG9ydHNBdENvbXBvbmVudCAmJiAvQGNvbXBvbmVudC9pLnRlc3QodHlwZSkpIHtcbiAgICAgIHJldHVybiBwdXNoQ29udGV4dChzdGF0ZSwgc3RyZWFtLCBcImF0Q29tcG9uZW50QmxvY2tcIik7XG4gICAgfSBlbHNlIGlmICgvXkAoLW1vei0pP2RvY3VtZW50JC9pLnRlc3QodHlwZSkpIHtcbiAgICAgIHJldHVybiBwdXNoQ29udGV4dChzdGF0ZSwgc3RyZWFtLCBcImRvY3VtZW50VHlwZXNcIik7XG4gICAgfSBlbHNlIGlmICgvXkAobWVkaWF8c3VwcG9ydHN8KC1tb3otKT9kb2N1bWVudHxpbXBvcnQpJC9pLnRlc3QodHlwZSkpIHtcbiAgICAgIHJldHVybiBwdXNoQ29udGV4dChzdGF0ZSwgc3RyZWFtLCBcImF0QmxvY2tcIik7XG4gICAgfSBlbHNlIGlmICgvXkAoZm9udC1mYWNlfGNvdW50ZXItc3R5bGUpL2kudGVzdCh0eXBlKSkge1xuICAgICAgc3RhdGUuc3RhdGVBcmcgPSB0eXBlO1xuICAgICAgcmV0dXJuIFwicmVzdHJpY3RlZF9hdEJsb2NrX2JlZm9yZVwiO1xuICAgIH0gZWxzZSBpZiAoL15AKC0obW96fG1zfG98d2Via2l0KS0pP2tleWZyYW1lcyQvaS50ZXN0KHR5cGUpKSB7XG4gICAgICByZXR1cm4gXCJrZXlmcmFtZXNcIjtcbiAgICB9IGVsc2UgaWYgKHR5cGUgJiYgdHlwZS5jaGFyQXQoMCkgPT0gXCJAXCIpIHtcbiAgICAgIHJldHVybiBwdXNoQ29udGV4dChzdGF0ZSwgc3RyZWFtLCBcImF0XCIpO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PSBcImhhc2hcIikge1xuICAgICAgb3ZlcnJpZGUgPSBcImJ1aWx0aW5cIjtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT0gXCJ3b3JkXCIpIHtcbiAgICAgIG92ZXJyaWRlID0gXCJ0YWdcIjtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT0gXCJ2YXJpYWJsZS1kZWZpbml0aW9uXCIpIHtcbiAgICAgIHJldHVybiBcIm1heWJlcHJvcFwiO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PSBcImludGVycG9sYXRpb25cIikge1xuICAgICAgcmV0dXJuIHB1c2hDb250ZXh0KHN0YXRlLCBzdHJlYW0sIFwiaW50ZXJwb2xhdGlvblwiKTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT0gXCI6XCIpIHtcbiAgICAgIHJldHVybiBcInBzZXVkb1wiO1xuICAgIH0gZWxzZSBpZiAoYWxsb3dOZXN0ZWQgJiYgdHlwZSA9PSBcIihcIikge1xuICAgICAgcmV0dXJuIHB1c2hDb250ZXh0KHN0YXRlLCBzdHJlYW0sIFwicGFyZW5zXCIpO1xuICAgIH1cbiAgICByZXR1cm4gc3RhdGUuY29udGV4dC50eXBlO1xuICB9O1xuXG4gIHN0YXRlcy5ibG9jayA9IGZ1bmN0aW9uKHR5cGUsIHN0cmVhbSwgc3RhdGUpIHtcbiAgICBpZiAodHlwZSA9PSBcIndvcmRcIikge1xuICAgICAgdmFyIHdvcmQgPSBzdHJlYW0uY3VycmVudCgpLnRvTG93ZXJDYXNlKCk7XG4gICAgICBpZiAocHJvcGVydHlLZXl3b3Jkcy5oYXNPd25Qcm9wZXJ0eSh3b3JkKSkge1xuICAgICAgICBvdmVycmlkZSA9IFwicHJvcGVydHlcIjtcbiAgICAgICAgcmV0dXJuIFwibWF5YmVwcm9wXCI7XG4gICAgICB9IGVsc2UgaWYgKG5vblN0YW5kYXJkUHJvcGVydHlLZXl3b3Jkcy5oYXNPd25Qcm9wZXJ0eSh3b3JkKSkge1xuICAgICAgICBvdmVycmlkZSA9IGhpZ2hsaWdodE5vblN0YW5kYXJkUHJvcGVydHlLZXl3b3JkcyA/IFwic3RyaW5nLTJcIiA6IFwicHJvcGVydHlcIjtcbiAgICAgICAgcmV0dXJuIFwibWF5YmVwcm9wXCI7XG4gICAgICB9IGVsc2UgaWYgKGFsbG93TmVzdGVkKSB7XG4gICAgICAgIG92ZXJyaWRlID0gc3RyZWFtLm1hdGNoKC9eXFxzKjooPzpcXHN8JCkvLCBmYWxzZSkgPyBcInByb3BlcnR5XCIgOiBcInRhZ1wiO1xuICAgICAgICByZXR1cm4gXCJibG9ja1wiO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3ZlcnJpZGUgKz0gXCIgZXJyb3JcIjtcbiAgICAgICAgcmV0dXJuIFwibWF5YmVwcm9wXCI7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0eXBlID09IFwibWV0YVwiKSB7XG4gICAgICByZXR1cm4gXCJibG9ja1wiO1xuICAgIH0gZWxzZSBpZiAoIWFsbG93TmVzdGVkICYmICh0eXBlID09IFwiaGFzaFwiIHx8IHR5cGUgPT0gXCJxdWFsaWZpZXJcIikpIHtcbiAgICAgIG92ZXJyaWRlID0gXCJlcnJvclwiO1xuICAgICAgcmV0dXJuIFwiYmxvY2tcIjtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHN0YXRlcy50b3AodHlwZSwgc3RyZWFtLCBzdGF0ZSk7XG4gICAgfVxuICB9O1xuXG4gIHN0YXRlcy5tYXliZXByb3AgPSBmdW5jdGlvbih0eXBlLCBzdHJlYW0sIHN0YXRlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCI6XCIpIHJldHVybiBwdXNoQ29udGV4dChzdGF0ZSwgc3RyZWFtLCBcInByb3BcIik7XG4gICAgcmV0dXJuIHBhc3ModHlwZSwgc3RyZWFtLCBzdGF0ZSk7XG4gIH07XG5cbiAgc3RhdGVzLnByb3AgPSBmdW5jdGlvbih0eXBlLCBzdHJlYW0sIHN0YXRlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCI7XCIpIHJldHVybiBwb3BDb250ZXh0KHN0YXRlKTtcbiAgICBpZiAodHlwZSA9PSBcIntcIiAmJiBhbGxvd05lc3RlZCkgcmV0dXJuIHB1c2hDb250ZXh0KHN0YXRlLCBzdHJlYW0sIFwicHJvcEJsb2NrXCIpO1xuICAgIGlmICh0eXBlID09IFwifVwiIHx8IHR5cGUgPT0gXCJ7XCIpIHJldHVybiBwb3BBbmRQYXNzKHR5cGUsIHN0cmVhbSwgc3RhdGUpO1xuICAgIGlmICh0eXBlID09IFwiKFwiKSByZXR1cm4gcHVzaENvbnRleHQoc3RhdGUsIHN0cmVhbSwgXCJwYXJlbnNcIik7XG5cbiAgICBpZiAodHlwZSA9PSBcImhhc2hcIiAmJiAhL14jKFswLTlhLWZBLWZdezMsNH18WzAtOWEtZkEtZl17Nn18WzAtOWEtZkEtZl17OH0pJC8udGVzdChzdHJlYW0uY3VycmVudCgpKSkge1xuICAgICAgb3ZlcnJpZGUgKz0gXCIgZXJyb3JcIjtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT0gXCJ3b3JkXCIpIHtcbiAgICAgIHdvcmRBc1ZhbHVlKHN0cmVhbSk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09IFwiaW50ZXJwb2xhdGlvblwiKSB7XG4gICAgICByZXR1cm4gcHVzaENvbnRleHQoc3RhdGUsIHN0cmVhbSwgXCJpbnRlcnBvbGF0aW9uXCIpO1xuICAgIH1cbiAgICByZXR1cm4gXCJwcm9wXCI7XG4gIH07XG5cbiAgc3RhdGVzLnByb3BCbG9jayA9IGZ1bmN0aW9uKHR5cGUsIF9zdHJlYW0sIHN0YXRlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCJ9XCIpIHJldHVybiBwb3BDb250ZXh0KHN0YXRlKTtcbiAgICBpZiAodHlwZSA9PSBcIndvcmRcIikgeyBvdmVycmlkZSA9IFwicHJvcGVydHlcIjsgcmV0dXJuIFwibWF5YmVwcm9wXCI7IH1cbiAgICByZXR1cm4gc3RhdGUuY29udGV4dC50eXBlO1xuICB9O1xuXG4gIHN0YXRlcy5wYXJlbnMgPSBmdW5jdGlvbih0eXBlLCBzdHJlYW0sIHN0YXRlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCJ7XCIgfHwgdHlwZSA9PSBcIn1cIikgcmV0dXJuIHBvcEFuZFBhc3ModHlwZSwgc3RyZWFtLCBzdGF0ZSk7XG4gICAgaWYgKHR5cGUgPT0gXCIpXCIpIHJldHVybiBwb3BDb250ZXh0KHN0YXRlKTtcbiAgICBpZiAodHlwZSA9PSBcIihcIikgcmV0dXJuIHB1c2hDb250ZXh0KHN0YXRlLCBzdHJlYW0sIFwicGFyZW5zXCIpO1xuICAgIGlmICh0eXBlID09IFwiaW50ZXJwb2xhdGlvblwiKSByZXR1cm4gcHVzaENvbnRleHQoc3RhdGUsIHN0cmVhbSwgXCJpbnRlcnBvbGF0aW9uXCIpO1xuICAgIGlmICh0eXBlID09IFwid29yZFwiKSB3b3JkQXNWYWx1ZShzdHJlYW0pO1xuICAgIHJldHVybiBcInBhcmVuc1wiO1xuICB9O1xuXG4gIHN0YXRlcy5wc2V1ZG8gPSBmdW5jdGlvbih0eXBlLCBzdHJlYW0sIHN0YXRlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCJtZXRhXCIpIHJldHVybiBcInBzZXVkb1wiO1xuXG4gICAgaWYgKHR5cGUgPT0gXCJ3b3JkXCIpIHtcbiAgICAgIG92ZXJyaWRlID0gXCJ2YXJpYWJsZS0zXCI7XG4gICAgICByZXR1cm4gc3RhdGUuY29udGV4dC50eXBlO1xuICAgIH1cbiAgICByZXR1cm4gcGFzcyh0eXBlLCBzdHJlYW0sIHN0YXRlKTtcbiAgfTtcblxuICBzdGF0ZXMuZG9jdW1lbnRUeXBlcyA9IGZ1bmN0aW9uKHR5cGUsIHN0cmVhbSwgc3RhdGUpIHtcbiAgICBpZiAodHlwZSA9PSBcIndvcmRcIiAmJiBkb2N1bWVudFR5cGVzLmhhc093blByb3BlcnR5KHN0cmVhbS5jdXJyZW50KCkpKSB7XG4gICAgICBvdmVycmlkZSA9IFwidGFnXCI7XG4gICAgICByZXR1cm4gc3RhdGUuY29udGV4dC50eXBlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gc3RhdGVzLmF0QmxvY2sodHlwZSwgc3RyZWFtLCBzdGF0ZSk7XG4gICAgfVxuICB9O1xuXG4gIHN0YXRlcy5hdEJsb2NrID0gZnVuY3Rpb24odHlwZSwgc3RyZWFtLCBzdGF0ZSkge1xuICAgIGlmICh0eXBlID09IFwiKFwiKSByZXR1cm4gcHVzaENvbnRleHQoc3RhdGUsIHN0cmVhbSwgXCJhdEJsb2NrX3BhcmVuc1wiKTtcbiAgICBpZiAodHlwZSA9PSBcIn1cIiB8fCB0eXBlID09IFwiO1wiKSByZXR1cm4gcG9wQW5kUGFzcyh0eXBlLCBzdHJlYW0sIHN0YXRlKTtcbiAgICBpZiAodHlwZSA9PSBcIntcIikgcmV0dXJuIHBvcENvbnRleHQoc3RhdGUpICYmIHB1c2hDb250ZXh0KHN0YXRlLCBzdHJlYW0sIGFsbG93TmVzdGVkID8gXCJibG9ja1wiIDogXCJ0b3BcIik7XG5cbiAgICBpZiAodHlwZSA9PSBcImludGVycG9sYXRpb25cIikgcmV0dXJuIHB1c2hDb250ZXh0KHN0YXRlLCBzdHJlYW0sIFwiaW50ZXJwb2xhdGlvblwiKTtcblxuICAgIGlmICh0eXBlID09IFwid29yZFwiKSB7XG4gICAgICB2YXIgd29yZCA9IHN0cmVhbS5jdXJyZW50KCkudG9Mb3dlckNhc2UoKTtcbiAgICAgIGlmICh3b3JkID09IFwib25seVwiIHx8IHdvcmQgPT0gXCJub3RcIiB8fCB3b3JkID09IFwiYW5kXCIgfHwgd29yZCA9PSBcIm9yXCIpXG4gICAgICAgIG92ZXJyaWRlID0gXCJrZXl3b3JkXCI7XG4gICAgICBlbHNlIGlmIChtZWRpYVR5cGVzLmhhc093blByb3BlcnR5KHdvcmQpKVxuICAgICAgICBvdmVycmlkZSA9IFwiYXR0cmlidXRlXCI7XG4gICAgICBlbHNlIGlmIChtZWRpYUZlYXR1cmVzLmhhc093blByb3BlcnR5KHdvcmQpKVxuICAgICAgICBvdmVycmlkZSA9IFwicHJvcGVydHlcIjtcbiAgICAgIGVsc2UgaWYgKG1lZGlhVmFsdWVLZXl3b3Jkcy5oYXNPd25Qcm9wZXJ0eSh3b3JkKSlcbiAgICAgICAgb3ZlcnJpZGUgPSBcImtleXdvcmRcIjtcbiAgICAgIGVsc2UgaWYgKHByb3BlcnR5S2V5d29yZHMuaGFzT3duUHJvcGVydHkod29yZCkpXG4gICAgICAgIG92ZXJyaWRlID0gXCJwcm9wZXJ0eVwiO1xuICAgICAgZWxzZSBpZiAobm9uU3RhbmRhcmRQcm9wZXJ0eUtleXdvcmRzLmhhc093blByb3BlcnR5KHdvcmQpKVxuICAgICAgICBvdmVycmlkZSA9IGhpZ2hsaWdodE5vblN0YW5kYXJkUHJvcGVydHlLZXl3b3JkcyA/IFwic3RyaW5nLTJcIiA6IFwicHJvcGVydHlcIjtcbiAgICAgIGVsc2UgaWYgKHZhbHVlS2V5d29yZHMuaGFzT3duUHJvcGVydHkod29yZCkpXG4gICAgICAgIG92ZXJyaWRlID0gXCJhdG9tXCI7XG4gICAgICBlbHNlIGlmIChjb2xvcktleXdvcmRzLmhhc093blByb3BlcnR5KHdvcmQpKVxuICAgICAgICBvdmVycmlkZSA9IFwia2V5d29yZFwiO1xuICAgICAgZWxzZVxuICAgICAgICBvdmVycmlkZSA9IFwiZXJyb3JcIjtcbiAgICB9XG4gICAgcmV0dXJuIHN0YXRlLmNvbnRleHQudHlwZTtcbiAgfTtcblxuICBzdGF0ZXMuYXRDb21wb25lbnRCbG9jayA9IGZ1bmN0aW9uKHR5cGUsIHN0cmVhbSwgc3RhdGUpIHtcbiAgICBpZiAodHlwZSA9PSBcIn1cIilcbiAgICAgIHJldHVybiBwb3BBbmRQYXNzKHR5cGUsIHN0cmVhbSwgc3RhdGUpO1xuICAgIGlmICh0eXBlID09IFwie1wiKVxuICAgICAgcmV0dXJuIHBvcENvbnRleHQoc3RhdGUpICYmIHB1c2hDb250ZXh0KHN0YXRlLCBzdHJlYW0sIGFsbG93TmVzdGVkID8gXCJibG9ja1wiIDogXCJ0b3BcIiwgZmFsc2UpO1xuICAgIGlmICh0eXBlID09IFwid29yZFwiKVxuICAgICAgb3ZlcnJpZGUgPSBcImVycm9yXCI7XG4gICAgcmV0dXJuIHN0YXRlLmNvbnRleHQudHlwZTtcbiAgfTtcblxuICBzdGF0ZXMuYXRCbG9ja19wYXJlbnMgPSBmdW5jdGlvbih0eXBlLCBzdHJlYW0sIHN0YXRlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCIpXCIpIHJldHVybiBwb3BDb250ZXh0KHN0YXRlKTtcbiAgICBpZiAodHlwZSA9PSBcIntcIiB8fCB0eXBlID09IFwifVwiKSByZXR1cm4gcG9wQW5kUGFzcyh0eXBlLCBzdHJlYW0sIHN0YXRlLCAyKTtcbiAgICByZXR1cm4gc3RhdGVzLmF0QmxvY2sodHlwZSwgc3RyZWFtLCBzdGF0ZSk7XG4gIH07XG5cbiAgc3RhdGVzLnJlc3RyaWN0ZWRfYXRCbG9ja19iZWZvcmUgPSBmdW5jdGlvbih0eXBlLCBzdHJlYW0sIHN0YXRlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCJ7XCIpXG4gICAgICByZXR1cm4gcHVzaENvbnRleHQoc3RhdGUsIHN0cmVhbSwgXCJyZXN0cmljdGVkX2F0QmxvY2tcIik7XG4gICAgaWYgKHR5cGUgPT0gXCJ3b3JkXCIgJiYgc3RhdGUuc3RhdGVBcmcgPT0gXCJAY291bnRlci1zdHlsZVwiKSB7XG4gICAgICBvdmVycmlkZSA9IFwidmFyaWFibGVcIjtcbiAgICAgIHJldHVybiBcInJlc3RyaWN0ZWRfYXRCbG9ja19iZWZvcmVcIjtcbiAgICB9XG4gICAgcmV0dXJuIHBhc3ModHlwZSwgc3RyZWFtLCBzdGF0ZSk7XG4gIH07XG5cbiAgc3RhdGVzLnJlc3RyaWN0ZWRfYXRCbG9jayA9IGZ1bmN0aW9uKHR5cGUsIHN0cmVhbSwgc3RhdGUpIHtcbiAgICBpZiAodHlwZSA9PSBcIn1cIikge1xuICAgICAgc3RhdGUuc3RhdGVBcmcgPSBudWxsO1xuICAgICAgcmV0dXJuIHBvcENvbnRleHQoc3RhdGUpO1xuICAgIH1cbiAgICBpZiAodHlwZSA9PSBcIndvcmRcIikge1xuICAgICAgaWYgKChzdGF0ZS5zdGF0ZUFyZyA9PSBcIkBmb250LWZhY2VcIiAmJiAhZm9udFByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkoc3RyZWFtLmN1cnJlbnQoKS50b0xvd2VyQ2FzZSgpKSkgfHxcbiAgICAgICAgICAoc3RhdGUuc3RhdGVBcmcgPT0gXCJAY291bnRlci1zdHlsZVwiICYmICFjb3VudGVyRGVzY3JpcHRvcnMuaGFzT3duUHJvcGVydHkoc3RyZWFtLmN1cnJlbnQoKS50b0xvd2VyQ2FzZSgpKSkpXG4gICAgICAgIG92ZXJyaWRlID0gXCJlcnJvclwiO1xuICAgICAgZWxzZVxuICAgICAgICBvdmVycmlkZSA9IFwicHJvcGVydHlcIjtcbiAgICAgIHJldHVybiBcIm1heWJlcHJvcFwiO1xuICAgIH1cbiAgICByZXR1cm4gXCJyZXN0cmljdGVkX2F0QmxvY2tcIjtcbiAgfTtcblxuICBzdGF0ZXMua2V5ZnJhbWVzID0gZnVuY3Rpb24odHlwZSwgc3RyZWFtLCBzdGF0ZSkge1xuICAgIGlmICh0eXBlID09IFwid29yZFwiKSB7IG92ZXJyaWRlID0gXCJ2YXJpYWJsZVwiOyByZXR1cm4gXCJrZXlmcmFtZXNcIjsgfVxuICAgIGlmICh0eXBlID09IFwie1wiKSByZXR1cm4gcHVzaENvbnRleHQoc3RhdGUsIHN0cmVhbSwgXCJ0b3BcIik7XG4gICAgcmV0dXJuIHBhc3ModHlwZSwgc3RyZWFtLCBzdGF0ZSk7XG4gIH07XG5cbiAgc3RhdGVzLmF0ID0gZnVuY3Rpb24odHlwZSwgc3RyZWFtLCBzdGF0ZSkge1xuICAgIGlmICh0eXBlID09IFwiO1wiKSByZXR1cm4gcG9wQ29udGV4dChzdGF0ZSk7XG4gICAgaWYgKHR5cGUgPT0gXCJ7XCIgfHwgdHlwZSA9PSBcIn1cIikgcmV0dXJuIHBvcEFuZFBhc3ModHlwZSwgc3RyZWFtLCBzdGF0ZSk7XG4gICAgaWYgKHR5cGUgPT0gXCJ3b3JkXCIpIG92ZXJyaWRlID0gXCJ0YWdcIjtcbiAgICBlbHNlIGlmICh0eXBlID09IFwiaGFzaFwiKSBvdmVycmlkZSA9IFwiYnVpbHRpblwiO1xuICAgIHJldHVybiBcImF0XCI7XG4gIH07XG5cbiAgc3RhdGVzLmludGVycG9sYXRpb24gPSBmdW5jdGlvbih0eXBlLCBzdHJlYW0sIHN0YXRlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCJ9XCIpIHJldHVybiBwb3BDb250ZXh0KHN0YXRlKTtcbiAgICBpZiAodHlwZSA9PSBcIntcIiB8fCB0eXBlID09IFwiO1wiKSByZXR1cm4gcG9wQW5kUGFzcyh0eXBlLCBzdHJlYW0sIHN0YXRlKTtcbiAgICBpZiAodHlwZSA9PSBcIndvcmRcIikgb3ZlcnJpZGUgPSBcInZhcmlhYmxlXCI7XG4gICAgZWxzZSBpZiAodHlwZSAhPSBcInZhcmlhYmxlXCIgJiYgdHlwZSAhPSBcIihcIiAmJiB0eXBlICE9IFwiKVwiKSBvdmVycmlkZSA9IFwiZXJyb3JcIjtcbiAgICByZXR1cm4gXCJpbnRlcnBvbGF0aW9uXCI7XG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBzdGFydFN0YXRlOiBmdW5jdGlvbihiYXNlKSB7XG4gICAgICByZXR1cm4ge3Rva2VuaXplOiBudWxsLFxuICAgICAgICAgICAgICBzdGF0ZTogaW5saW5lID8gXCJibG9ja1wiIDogXCJ0b3BcIixcbiAgICAgICAgICAgICAgc3RhdGVBcmc6IG51bGwsXG4gICAgICAgICAgICAgIGNvbnRleHQ6IG5ldyBDb250ZXh0KGlubGluZSA/IFwiYmxvY2tcIiA6IFwidG9wXCIsIGJhc2UgfHwgMCwgbnVsbCl9O1xuICAgIH0sXG5cbiAgICB0b2tlbjogZnVuY3Rpb24oc3RyZWFtLCBzdGF0ZSkge1xuICAgICAgaWYgKCFzdGF0ZS50b2tlbml6ZSAmJiBzdHJlYW0uZWF0U3BhY2UoKSkgcmV0dXJuIG51bGw7XG4gICAgICB2YXIgc3R5bGUgPSAoc3RhdGUudG9rZW5pemUgfHwgdG9rZW5CYXNlKShzdHJlYW0sIHN0YXRlKTtcbiAgICAgIGlmIChzdHlsZSAmJiB0eXBlb2Ygc3R5bGUgPT0gXCJvYmplY3RcIikge1xuICAgICAgICB0eXBlID0gc3R5bGVbMV07XG4gICAgICAgIHN0eWxlID0gc3R5bGVbMF07XG4gICAgICB9XG4gICAgICBvdmVycmlkZSA9IHN0eWxlO1xuICAgICAgaWYgKHR5cGUgIT0gXCJjb21tZW50XCIpXG4gICAgICAgIHN0YXRlLnN0YXRlID0gc3RhdGVzW3N0YXRlLnN0YXRlXSh0eXBlLCBzdHJlYW0sIHN0YXRlKTtcbiAgICAgIHJldHVybiBvdmVycmlkZTtcbiAgICB9LFxuXG4gICAgaW5kZW50OiBmdW5jdGlvbihzdGF0ZSwgdGV4dEFmdGVyKSB7XG4gICAgICB2YXIgY3ggPSBzdGF0ZS5jb250ZXh0LCBjaCA9IHRleHRBZnRlciAmJiB0ZXh0QWZ0ZXIuY2hhckF0KDApO1xuICAgICAgdmFyIGluZGVudCA9IGN4LmluZGVudDtcbiAgICAgIGlmIChjeC50eXBlID09IFwicHJvcFwiICYmIChjaCA9PSBcIn1cIiB8fCBjaCA9PSBcIilcIikpIGN4ID0gY3gucHJldjtcbiAgICAgIGlmIChjeC5wcmV2KSB7XG4gICAgICAgIGlmIChjaCA9PSBcIn1cIiAmJiAoY3gudHlwZSA9PSBcImJsb2NrXCIgfHwgY3gudHlwZSA9PSBcInRvcFwiIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGN4LnR5cGUgPT0gXCJpbnRlcnBvbGF0aW9uXCIgfHwgY3gudHlwZSA9PSBcInJlc3RyaWN0ZWRfYXRCbG9ja1wiKSkge1xuICAgICAgICAgIC8vIFJlc3VtZSBpbmRlbnRhdGlvbiBmcm9tIHBhcmVudCBjb250ZXh0LlxuICAgICAgICAgIGN4ID0gY3gucHJldjtcbiAgICAgICAgICBpbmRlbnQgPSBjeC5pbmRlbnQ7XG4gICAgICAgIH0gZWxzZSBpZiAoY2ggPT0gXCIpXCIgJiYgKGN4LnR5cGUgPT0gXCJwYXJlbnNcIiB8fCBjeC50eXBlID09IFwiYXRCbG9ja19wYXJlbnNcIikgfHxcbiAgICAgICAgICAgIGNoID09IFwie1wiICYmIChjeC50eXBlID09IFwiYXRcIiB8fCBjeC50eXBlID09IFwiYXRCbG9ja1wiKSkge1xuICAgICAgICAgIC8vIERlZGVudCByZWxhdGl2ZSB0byBjdXJyZW50IGNvbnRleHQuXG4gICAgICAgICAgaW5kZW50ID0gTWF0aC5tYXgoMCwgY3guaW5kZW50IC0gaW5kZW50VW5pdCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBpbmRlbnQ7XG4gICAgfSxcblxuICAgIGVsZWN0cmljQ2hhcnM6IFwifVwiLFxuICAgIGJsb2NrQ29tbWVudFN0YXJ0OiBcIi8qXCIsXG4gICAgYmxvY2tDb21tZW50RW5kOiBcIiovXCIsXG4gICAgYmxvY2tDb21tZW50Q29udGludWU6IFwiICogXCIsXG4gICAgbGluZUNvbW1lbnQ6IGxpbmVDb21tZW50LFxuICAgIGZvbGQ6IFwiYnJhY2VcIlxuICB9O1xufSk7XG5cbiAgZnVuY3Rpb24ga2V5U2V0KGFycmF5KSB7XG4gICAgdmFyIGtleXMgPSB7fTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgKytpKSB7XG4gICAgICBrZXlzW2FycmF5W2ldLnRvTG93ZXJDYXNlKCldID0gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGtleXM7XG4gIH1cblxuICB2YXIgZG9jdW1lbnRUeXBlc18gPSBbXG4gICAgXCJkb21haW5cIiwgXCJyZWdleHBcIiwgXCJ1cmxcIiwgXCJ1cmwtcHJlZml4XCJcbiAgXSwgZG9jdW1lbnRUeXBlcyA9IGtleVNldChkb2N1bWVudFR5cGVzXyk7XG5cbiAgdmFyIG1lZGlhVHlwZXNfID0gW1xuICAgIFwiYWxsXCIsIFwiYXVyYWxcIiwgXCJicmFpbGxlXCIsIFwiaGFuZGhlbGRcIiwgXCJwcmludFwiLCBcInByb2plY3Rpb25cIiwgXCJzY3JlZW5cIixcbiAgICBcInR0eVwiLCBcInR2XCIsIFwiZW1ib3NzZWRcIlxuICBdLCBtZWRpYVR5cGVzID0ga2V5U2V0KG1lZGlhVHlwZXNfKTtcblxuICB2YXIgbWVkaWFGZWF0dXJlc18gPSBbXG4gICAgXCJ3aWR0aFwiLCBcIm1pbi13aWR0aFwiLCBcIm1heC13aWR0aFwiLCBcImhlaWdodFwiLCBcIm1pbi1oZWlnaHRcIiwgXCJtYXgtaGVpZ2h0XCIsXG4gICAgXCJkZXZpY2Utd2lkdGhcIiwgXCJtaW4tZGV2aWNlLXdpZHRoXCIsIFwibWF4LWRldmljZS13aWR0aFwiLCBcImRldmljZS1oZWlnaHRcIixcbiAgICBcIm1pbi1kZXZpY2UtaGVpZ2h0XCIsIFwibWF4LWRldmljZS1oZWlnaHRcIiwgXCJhc3BlY3QtcmF0aW9cIixcbiAgICBcIm1pbi1hc3BlY3QtcmF0aW9cIiwgXCJtYXgtYXNwZWN0LXJhdGlvXCIsIFwiZGV2aWNlLWFzcGVjdC1yYXRpb1wiLFxuICAgIFwibWluLWRldmljZS1hc3BlY3QtcmF0aW9cIiwgXCJtYXgtZGV2aWNlLWFzcGVjdC1yYXRpb1wiLCBcImNvbG9yXCIsIFwibWluLWNvbG9yXCIsXG4gICAgXCJtYXgtY29sb3JcIiwgXCJjb2xvci1pbmRleFwiLCBcIm1pbi1jb2xvci1pbmRleFwiLCBcIm1heC1jb2xvci1pbmRleFwiLFxuICAgIFwibW9ub2Nocm9tZVwiLCBcIm1pbi1tb25vY2hyb21lXCIsIFwibWF4LW1vbm9jaHJvbWVcIiwgXCJyZXNvbHV0aW9uXCIsXG4gICAgXCJtaW4tcmVzb2x1dGlvblwiLCBcIm1heC1yZXNvbHV0aW9uXCIsIFwic2NhblwiLCBcImdyaWRcIiwgXCJvcmllbnRhdGlvblwiLFxuICAgIFwiZGV2aWNlLXBpeGVsLXJhdGlvXCIsIFwibWluLWRldmljZS1waXhlbC1yYXRpb1wiLCBcIm1heC1kZXZpY2UtcGl4ZWwtcmF0aW9cIixcbiAgICBcInBvaW50ZXJcIiwgXCJhbnktcG9pbnRlclwiLCBcImhvdmVyXCIsIFwiYW55LWhvdmVyXCIsIFwicHJlZmVycy1jb2xvci1zY2hlbWVcIixcbiAgICBcImR5bmFtaWMtcmFuZ2VcIiwgXCJ2aWRlby1keW5hbWljLXJhbmdlXCJcbiAgXSwgbWVkaWFGZWF0dXJlcyA9IGtleVNldChtZWRpYUZlYXR1cmVzXyk7XG5cbiAgdmFyIG1lZGlhVmFsdWVLZXl3b3Jkc18gPSBbXG4gICAgXCJsYW5kc2NhcGVcIiwgXCJwb3J0cmFpdFwiLCBcIm5vbmVcIiwgXCJjb2Fyc2VcIiwgXCJmaW5lXCIsIFwib24tZGVtYW5kXCIsIFwiaG92ZXJcIixcbiAgICBcImludGVybGFjZVwiLCBcInByb2dyZXNzaXZlXCIsXG4gICAgXCJkYXJrXCIsIFwibGlnaHRcIixcbiAgICBcInN0YW5kYXJkXCIsIFwiaGlnaFwiXG4gIF0sIG1lZGlhVmFsdWVLZXl3b3JkcyA9IGtleVNldChtZWRpYVZhbHVlS2V5d29yZHNfKTtcblxuICB2YXIgcHJvcGVydHlLZXl3b3Jkc18gPSBbXG4gICAgXCJhbGlnbi1jb250ZW50XCIsIFwiYWxpZ24taXRlbXNcIiwgXCJhbGlnbi1zZWxmXCIsIFwiYWxpZ25tZW50LWFkanVzdFwiLFxuICAgIFwiYWxpZ25tZW50LWJhc2VsaW5lXCIsIFwiYWxsXCIsIFwiYW5jaG9yLXBvaW50XCIsIFwiYW5pbWF0aW9uXCIsIFwiYW5pbWF0aW9uLWRlbGF5XCIsXG4gICAgXCJhbmltYXRpb24tZGlyZWN0aW9uXCIsIFwiYW5pbWF0aW9uLWR1cmF0aW9uXCIsIFwiYW5pbWF0aW9uLWZpbGwtbW9kZVwiLFxuICAgIFwiYW5pbWF0aW9uLWl0ZXJhdGlvbi1jb3VudFwiLCBcImFuaW1hdGlvbi1uYW1lXCIsIFwiYW5pbWF0aW9uLXBsYXktc3RhdGVcIixcbiAgICBcImFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb25cIiwgXCJhcHBlYXJhbmNlXCIsIFwiYXppbXV0aFwiLCBcImJhY2tkcm9wLWZpbHRlclwiLFxuICAgIFwiYmFja2ZhY2UtdmlzaWJpbGl0eVwiLCBcImJhY2tncm91bmRcIiwgXCJiYWNrZ3JvdW5kLWF0dGFjaG1lbnRcIixcbiAgICBcImJhY2tncm91bmQtYmxlbmQtbW9kZVwiLCBcImJhY2tncm91bmQtY2xpcFwiLCBcImJhY2tncm91bmQtY29sb3JcIixcbiAgICBcImJhY2tncm91bmQtaW1hZ2VcIiwgXCJiYWNrZ3JvdW5kLW9yaWdpblwiLCBcImJhY2tncm91bmQtcG9zaXRpb25cIixcbiAgICBcImJhY2tncm91bmQtcG9zaXRpb24teFwiLCBcImJhY2tncm91bmQtcG9zaXRpb24teVwiLCBcImJhY2tncm91bmQtcmVwZWF0XCIsXG4gICAgXCJiYWNrZ3JvdW5kLXNpemVcIiwgXCJiYXNlbGluZS1zaGlmdFwiLCBcImJpbmRpbmdcIiwgXCJibGVlZFwiLCBcImJsb2NrLXNpemVcIixcbiAgICBcImJvb2ttYXJrLWxhYmVsXCIsIFwiYm9va21hcmstbGV2ZWxcIiwgXCJib29rbWFyay1zdGF0ZVwiLCBcImJvb2ttYXJrLXRhcmdldFwiLFxuICAgIFwiYm9yZGVyXCIsIFwiYm9yZGVyLWJvdHRvbVwiLCBcImJvcmRlci1ib3R0b20tY29sb3JcIiwgXCJib3JkZXItYm90dG9tLWxlZnQtcmFkaXVzXCIsXG4gICAgXCJib3JkZXItYm90dG9tLXJpZ2h0LXJhZGl1c1wiLCBcImJvcmRlci1ib3R0b20tc3R5bGVcIiwgXCJib3JkZXItYm90dG9tLXdpZHRoXCIsXG4gICAgXCJib3JkZXItY29sbGFwc2VcIiwgXCJib3JkZXItY29sb3JcIiwgXCJib3JkZXItaW1hZ2VcIiwgXCJib3JkZXItaW1hZ2Utb3V0c2V0XCIsXG4gICAgXCJib3JkZXItaW1hZ2UtcmVwZWF0XCIsIFwiYm9yZGVyLWltYWdlLXNsaWNlXCIsIFwiYm9yZGVyLWltYWdlLXNvdXJjZVwiLFxuICAgIFwiYm9yZGVyLWltYWdlLXdpZHRoXCIsIFwiYm9yZGVyLWxlZnRcIiwgXCJib3JkZXItbGVmdC1jb2xvclwiLCBcImJvcmRlci1sZWZ0LXN0eWxlXCIsXG4gICAgXCJib3JkZXItbGVmdC13aWR0aFwiLCBcImJvcmRlci1yYWRpdXNcIiwgXCJib3JkZXItcmlnaHRcIiwgXCJib3JkZXItcmlnaHQtY29sb3JcIixcbiAgICBcImJvcmRlci1yaWdodC1zdHlsZVwiLCBcImJvcmRlci1yaWdodC13aWR0aFwiLCBcImJvcmRlci1zcGFjaW5nXCIsIFwiYm9yZGVyLXN0eWxlXCIsXG4gICAgXCJib3JkZXItdG9wXCIsIFwiYm9yZGVyLXRvcC1jb2xvclwiLCBcImJvcmRlci10b3AtbGVmdC1yYWRpdXNcIixcbiAgICBcImJvcmRlci10b3AtcmlnaHQtcmFkaXVzXCIsIFwiYm9yZGVyLXRvcC1zdHlsZVwiLCBcImJvcmRlci10b3Atd2lkdGhcIixcbiAgICBcImJvcmRlci13aWR0aFwiLCBcImJvdHRvbVwiLCBcImJveC1kZWNvcmF0aW9uLWJyZWFrXCIsIFwiYm94LXNoYWRvd1wiLCBcImJveC1zaXppbmdcIixcbiAgICBcImJyZWFrLWFmdGVyXCIsIFwiYnJlYWstYmVmb3JlXCIsIFwiYnJlYWstaW5zaWRlXCIsIFwiY2FwdGlvbi1zaWRlXCIsIFwiY2FyZXQtY29sb3JcIixcbiAgICBcImNsZWFyXCIsIFwiY2xpcFwiLCBcImNvbG9yXCIsIFwiY29sb3ItcHJvZmlsZVwiLCBcImNvbHVtbi1jb3VudFwiLCBcImNvbHVtbi1maWxsXCIsXG4gICAgXCJjb2x1bW4tZ2FwXCIsIFwiY29sdW1uLXJ1bGVcIiwgXCJjb2x1bW4tcnVsZS1jb2xvclwiLCBcImNvbHVtbi1ydWxlLXN0eWxlXCIsXG4gICAgXCJjb2x1bW4tcnVsZS13aWR0aFwiLCBcImNvbHVtbi1zcGFuXCIsIFwiY29sdW1uLXdpZHRoXCIsIFwiY29sdW1uc1wiLCBcImNvbnRhaW5cIixcbiAgICBcImNvbnRlbnRcIiwgXCJjb3VudGVyLWluY3JlbWVudFwiLCBcImNvdW50ZXItcmVzZXRcIiwgXCJjcm9wXCIsIFwiY3VlXCIsIFwiY3VlLWFmdGVyXCIsXG4gICAgXCJjdWUtYmVmb3JlXCIsIFwiY3Vyc29yXCIsIFwiZGlyZWN0aW9uXCIsIFwiZGlzcGxheVwiLCBcImRvbWluYW50LWJhc2VsaW5lXCIsXG4gICAgXCJkcm9wLWluaXRpYWwtYWZ0ZXItYWRqdXN0XCIsIFwiZHJvcC1pbml0aWFsLWFmdGVyLWFsaWduXCIsXG4gICAgXCJkcm9wLWluaXRpYWwtYmVmb3JlLWFkanVzdFwiLCBcImRyb3AtaW5pdGlhbC1iZWZvcmUtYWxpZ25cIiwgXCJkcm9wLWluaXRpYWwtc2l6ZVwiLFxuICAgIFwiZHJvcC1pbml0aWFsLXZhbHVlXCIsIFwiZWxldmF0aW9uXCIsIFwiZW1wdHktY2VsbHNcIiwgXCJmaXRcIiwgXCJmaXQtY29udGVudFwiLCBcImZpdC1wb3NpdGlvblwiLFxuICAgIFwiZmxleFwiLCBcImZsZXgtYmFzaXNcIiwgXCJmbGV4LWRpcmVjdGlvblwiLCBcImZsZXgtZmxvd1wiLCBcImZsZXgtZ3Jvd1wiLFxuICAgIFwiZmxleC1zaHJpbmtcIiwgXCJmbGV4LXdyYXBcIiwgXCJmbG9hdFwiLCBcImZsb2F0LW9mZnNldFwiLCBcImZsb3ctZnJvbVwiLCBcImZsb3ctaW50b1wiLFxuICAgIFwiZm9udFwiLCBcImZvbnQtZmFtaWx5XCIsIFwiZm9udC1mZWF0dXJlLXNldHRpbmdzXCIsIFwiZm9udC1rZXJuaW5nXCIsXG4gICAgXCJmb250LWxhbmd1YWdlLW92ZXJyaWRlXCIsIFwiZm9udC1vcHRpY2FsLXNpemluZ1wiLCBcImZvbnQtc2l6ZVwiLFxuICAgIFwiZm9udC1zaXplLWFkanVzdFwiLCBcImZvbnQtc3RyZXRjaFwiLCBcImZvbnQtc3R5bGVcIiwgXCJmb250LXN5bnRoZXNpc1wiLFxuICAgIFwiZm9udC12YXJpYW50XCIsIFwiZm9udC12YXJpYW50LWFsdGVybmF0ZXNcIiwgXCJmb250LXZhcmlhbnQtY2Fwc1wiLFxuICAgIFwiZm9udC12YXJpYW50LWVhc3QtYXNpYW5cIiwgXCJmb250LXZhcmlhbnQtbGlnYXR1cmVzXCIsIFwiZm9udC12YXJpYW50LW51bWVyaWNcIixcbiAgICBcImZvbnQtdmFyaWFudC1wb3NpdGlvblwiLCBcImZvbnQtdmFyaWF0aW9uLXNldHRpbmdzXCIsIFwiZm9udC13ZWlnaHRcIiwgXCJnYXBcIixcbiAgICBcImdyaWRcIiwgXCJncmlkLWFyZWFcIiwgXCJncmlkLWF1dG8tY29sdW1uc1wiLCBcImdyaWQtYXV0by1mbG93XCIsIFwiZ3JpZC1hdXRvLXJvd3NcIixcbiAgICBcImdyaWQtY29sdW1uXCIsIFwiZ3JpZC1jb2x1bW4tZW5kXCIsIFwiZ3JpZC1jb2x1bW4tZ2FwXCIsIFwiZ3JpZC1jb2x1bW4tc3RhcnRcIixcbiAgICBcImdyaWQtZ2FwXCIsIFwiZ3JpZC1yb3dcIiwgXCJncmlkLXJvdy1lbmRcIiwgXCJncmlkLXJvdy1nYXBcIiwgXCJncmlkLXJvdy1zdGFydFwiLFxuICAgIFwiZ3JpZC10ZW1wbGF0ZVwiLCBcImdyaWQtdGVtcGxhdGUtYXJlYXNcIiwgXCJncmlkLXRlbXBsYXRlLWNvbHVtbnNcIixcbiAgICBcImdyaWQtdGVtcGxhdGUtcm93c1wiLCBcImhhbmdpbmctcHVuY3R1YXRpb25cIiwgXCJoZWlnaHRcIiwgXCJoeXBoZW5zXCIsIFwiaWNvblwiLFxuICAgIFwiaW1hZ2Utb3JpZW50YXRpb25cIiwgXCJpbWFnZS1yZW5kZXJpbmdcIiwgXCJpbWFnZS1yZXNvbHV0aW9uXCIsIFwiaW5saW5lLWJveC1hbGlnblwiLFxuICAgIFwiaW5zZXRcIiwgXCJpbnNldC1ibG9ja1wiLCBcImluc2V0LWJsb2NrLWVuZFwiLCBcImluc2V0LWJsb2NrLXN0YXJ0XCIsIFwiaW5zZXQtaW5saW5lXCIsXG4gICAgXCJpbnNldC1pbmxpbmUtZW5kXCIsIFwiaW5zZXQtaW5saW5lLXN0YXJ0XCIsIFwiaXNvbGF0aW9uXCIsIFwianVzdGlmeS1jb250ZW50XCIsXG4gICAgXCJqdXN0aWZ5LWl0ZW1zXCIsIFwianVzdGlmeS1zZWxmXCIsIFwibGVmdFwiLCBcImxldHRlci1zcGFjaW5nXCIsIFwibGluZS1icmVha1wiLFxuICAgIFwibGluZS1oZWlnaHRcIiwgXCJsaW5lLWhlaWdodC1zdGVwXCIsIFwibGluZS1zdGFja2luZ1wiLCBcImxpbmUtc3RhY2tpbmctcnVieVwiLFxuICAgIFwibGluZS1zdGFja2luZy1zaGlmdFwiLCBcImxpbmUtc3RhY2tpbmctc3RyYXRlZ3lcIiwgXCJsaXN0LXN0eWxlXCIsXG4gICAgXCJsaXN0LXN0eWxlLWltYWdlXCIsIFwibGlzdC1zdHlsZS1wb3NpdGlvblwiLCBcImxpc3Qtc3R5bGUtdHlwZVwiLCBcIm1hcmdpblwiLFxuICAgIFwibWFyZ2luLWJvdHRvbVwiLCBcIm1hcmdpbi1sZWZ0XCIsIFwibWFyZ2luLXJpZ2h0XCIsIFwibWFyZ2luLXRvcFwiLCBcIm1hcmtzXCIsXG4gICAgXCJtYXJxdWVlLWRpcmVjdGlvblwiLCBcIm1hcnF1ZWUtbG9vcFwiLCBcIm1hcnF1ZWUtcGxheS1jb3VudFwiLCBcIm1hcnF1ZWUtc3BlZWRcIixcbiAgICBcIm1hcnF1ZWUtc3R5bGVcIiwgXCJtYXNrLWNsaXBcIiwgXCJtYXNrLWNvbXBvc2l0ZVwiLCBcIm1hc2staW1hZ2VcIiwgXCJtYXNrLW1vZGVcIixcbiAgICBcIm1hc2stb3JpZ2luXCIsIFwibWFzay1wb3NpdGlvblwiLCBcIm1hc2stcmVwZWF0XCIsIFwibWFzay1zaXplXCIsXCJtYXNrLXR5cGVcIixcbiAgICBcIm1heC1ibG9jay1zaXplXCIsIFwibWF4LWhlaWdodFwiLCBcIm1heC1pbmxpbmUtc2l6ZVwiLFxuICAgIFwibWF4LXdpZHRoXCIsIFwibWluLWJsb2NrLXNpemVcIiwgXCJtaW4taGVpZ2h0XCIsIFwibWluLWlubGluZS1zaXplXCIsIFwibWluLXdpZHRoXCIsXG4gICAgXCJtaXgtYmxlbmQtbW9kZVwiLCBcIm1vdmUtdG9cIiwgXCJuYXYtZG93blwiLCBcIm5hdi1pbmRleFwiLCBcIm5hdi1sZWZ0XCIsIFwibmF2LXJpZ2h0XCIsXG4gICAgXCJuYXYtdXBcIiwgXCJvYmplY3QtZml0XCIsIFwib2JqZWN0LXBvc2l0aW9uXCIsIFwib2Zmc2V0XCIsIFwib2Zmc2V0LWFuY2hvclwiLFxuICAgIFwib2Zmc2V0LWRpc3RhbmNlXCIsIFwib2Zmc2V0LXBhdGhcIiwgXCJvZmZzZXQtcG9zaXRpb25cIiwgXCJvZmZzZXQtcm90YXRlXCIsXG4gICAgXCJvcGFjaXR5XCIsIFwib3JkZXJcIiwgXCJvcnBoYW5zXCIsIFwib3V0bGluZVwiLCBcIm91dGxpbmUtY29sb3JcIiwgXCJvdXRsaW5lLW9mZnNldFwiLFxuICAgIFwib3V0bGluZS1zdHlsZVwiLCBcIm91dGxpbmUtd2lkdGhcIiwgXCJvdmVyZmxvd1wiLCBcIm92ZXJmbG93LXN0eWxlXCIsXG4gICAgXCJvdmVyZmxvdy13cmFwXCIsIFwib3ZlcmZsb3cteFwiLCBcIm92ZXJmbG93LXlcIiwgXCJwYWRkaW5nXCIsIFwicGFkZGluZy1ib3R0b21cIixcbiAgICBcInBhZGRpbmctbGVmdFwiLCBcInBhZGRpbmctcmlnaHRcIiwgXCJwYWRkaW5nLXRvcFwiLCBcInBhZ2VcIiwgXCJwYWdlLWJyZWFrLWFmdGVyXCIsXG4gICAgXCJwYWdlLWJyZWFrLWJlZm9yZVwiLCBcInBhZ2UtYnJlYWstaW5zaWRlXCIsIFwicGFnZS1wb2xpY3lcIiwgXCJwYXVzZVwiLFxuICAgIFwicGF1c2UtYWZ0ZXJcIiwgXCJwYXVzZS1iZWZvcmVcIiwgXCJwZXJzcGVjdGl2ZVwiLCBcInBlcnNwZWN0aXZlLW9yaWdpblwiLCBcInBpdGNoXCIsXG4gICAgXCJwaXRjaC1yYW5nZVwiLCBcInBsYWNlLWNvbnRlbnRcIiwgXCJwbGFjZS1pdGVtc1wiLCBcInBsYWNlLXNlbGZcIiwgXCJwbGF5LWR1cmluZ1wiLFxuICAgIFwicG9zaXRpb25cIiwgXCJwcmVzZW50YXRpb24tbGV2ZWxcIiwgXCJwdW5jdHVhdGlvbi10cmltXCIsIFwicXVvdGVzXCIsXG4gICAgXCJyZWdpb24tYnJlYWstYWZ0ZXJcIiwgXCJyZWdpb24tYnJlYWstYmVmb3JlXCIsIFwicmVnaW9uLWJyZWFrLWluc2lkZVwiLFxuICAgIFwicmVnaW9uLWZyYWdtZW50XCIsIFwicmVuZGVyaW5nLWludGVudFwiLCBcInJlc2l6ZVwiLCBcInJlc3RcIiwgXCJyZXN0LWFmdGVyXCIsXG4gICAgXCJyZXN0LWJlZm9yZVwiLCBcInJpY2huZXNzXCIsIFwicmlnaHRcIiwgXCJyb3RhdGVcIiwgXCJyb3RhdGlvblwiLCBcInJvdGF0aW9uLXBvaW50XCIsXG4gICAgXCJyb3ctZ2FwXCIsIFwicnVieS1hbGlnblwiLCBcInJ1Ynktb3ZlcmhhbmdcIiwgXCJydWJ5LXBvc2l0aW9uXCIsIFwicnVieS1zcGFuXCIsXG4gICAgXCJzY2FsZVwiLCBcInNjcm9sbC1iZWhhdmlvclwiLCBcInNjcm9sbC1tYXJnaW5cIiwgXCJzY3JvbGwtbWFyZ2luLWJsb2NrXCIsXG4gICAgXCJzY3JvbGwtbWFyZ2luLWJsb2NrLWVuZFwiLCBcInNjcm9sbC1tYXJnaW4tYmxvY2stc3RhcnRcIiwgXCJzY3JvbGwtbWFyZ2luLWJvdHRvbVwiLFxuICAgIFwic2Nyb2xsLW1hcmdpbi1pbmxpbmVcIiwgXCJzY3JvbGwtbWFyZ2luLWlubGluZS1lbmRcIixcbiAgICBcInNjcm9sbC1tYXJnaW4taW5saW5lLXN0YXJ0XCIsIFwic2Nyb2xsLW1hcmdpbi1sZWZ0XCIsIFwic2Nyb2xsLW1hcmdpbi1yaWdodFwiLFxuICAgIFwic2Nyb2xsLW1hcmdpbi10b3BcIiwgXCJzY3JvbGwtcGFkZGluZ1wiLCBcInNjcm9sbC1wYWRkaW5nLWJsb2NrXCIsXG4gICAgXCJzY3JvbGwtcGFkZGluZy1ibG9jay1lbmRcIiwgXCJzY3JvbGwtcGFkZGluZy1ibG9jay1zdGFydFwiLFxuICAgIFwic2Nyb2xsLXBhZGRpbmctYm90dG9tXCIsIFwic2Nyb2xsLXBhZGRpbmctaW5saW5lXCIsIFwic2Nyb2xsLXBhZGRpbmctaW5saW5lLWVuZFwiLFxuICAgIFwic2Nyb2xsLXBhZGRpbmctaW5saW5lLXN0YXJ0XCIsIFwic2Nyb2xsLXBhZGRpbmctbGVmdFwiLCBcInNjcm9sbC1wYWRkaW5nLXJpZ2h0XCIsXG4gICAgXCJzY3JvbGwtcGFkZGluZy10b3BcIiwgXCJzY3JvbGwtc25hcC1hbGlnblwiLCBcInNjcm9sbC1zbmFwLXR5cGVcIixcbiAgICBcInNoYXBlLWltYWdlLXRocmVzaG9sZFwiLCBcInNoYXBlLWluc2lkZVwiLCBcInNoYXBlLW1hcmdpblwiLCBcInNoYXBlLW91dHNpZGVcIixcbiAgICBcInNpemVcIiwgXCJzcGVha1wiLCBcInNwZWFrLWFzXCIsIFwic3BlYWstaGVhZGVyXCIsIFwic3BlYWstbnVtZXJhbFwiLFxuICAgIFwic3BlYWstcHVuY3R1YXRpb25cIiwgXCJzcGVlY2gtcmF0ZVwiLCBcInN0cmVzc1wiLCBcInN0cmluZy1zZXRcIiwgXCJ0YWItc2l6ZVwiLFxuICAgIFwidGFibGUtbGF5b3V0XCIsIFwidGFyZ2V0XCIsIFwidGFyZ2V0LW5hbWVcIiwgXCJ0YXJnZXQtbmV3XCIsIFwidGFyZ2V0LXBvc2l0aW9uXCIsXG4gICAgXCJ0ZXh0LWFsaWduXCIsIFwidGV4dC1hbGlnbi1sYXN0XCIsIFwidGV4dC1jb21iaW5lLXVwcmlnaHRcIiwgXCJ0ZXh0LWRlY29yYXRpb25cIixcbiAgICBcInRleHQtZGVjb3JhdGlvbi1jb2xvclwiLCBcInRleHQtZGVjb3JhdGlvbi1saW5lXCIsIFwidGV4dC1kZWNvcmF0aW9uLXNraXBcIixcbiAgICBcInRleHQtZGVjb3JhdGlvbi1za2lwLWlua1wiLCBcInRleHQtZGVjb3JhdGlvbi1zdHlsZVwiLCBcInRleHQtZW1waGFzaXNcIixcbiAgICBcInRleHQtZW1waGFzaXMtY29sb3JcIiwgXCJ0ZXh0LWVtcGhhc2lzLXBvc2l0aW9uXCIsIFwidGV4dC1lbXBoYXNpcy1zdHlsZVwiLFxuICAgIFwidGV4dC1oZWlnaHRcIiwgXCJ0ZXh0LWluZGVudFwiLCBcInRleHQtanVzdGlmeVwiLCBcInRleHQtb3JpZW50YXRpb25cIixcbiAgICBcInRleHQtb3V0bGluZVwiLCBcInRleHQtb3ZlcmZsb3dcIiwgXCJ0ZXh0LXJlbmRlcmluZ1wiLCBcInRleHQtc2hhZG93XCIsXG4gICAgXCJ0ZXh0LXNpemUtYWRqdXN0XCIsIFwidGV4dC1zcGFjZS1jb2xsYXBzZVwiLCBcInRleHQtdHJhbnNmb3JtXCIsXG4gICAgXCJ0ZXh0LXVuZGVybGluZS1wb3NpdGlvblwiLCBcInRleHQtd3JhcFwiLCBcInRvcFwiLCBcInRvdWNoLWFjdGlvblwiLCBcInRyYW5zZm9ybVwiLCBcInRyYW5zZm9ybS1vcmlnaW5cIixcbiAgICBcInRyYW5zZm9ybS1zdHlsZVwiLCBcInRyYW5zaXRpb25cIiwgXCJ0cmFuc2l0aW9uLWRlbGF5XCIsIFwidHJhbnNpdGlvbi1kdXJhdGlvblwiLFxuICAgIFwidHJhbnNpdGlvbi1wcm9wZXJ0eVwiLCBcInRyYW5zaXRpb24tdGltaW5nLWZ1bmN0aW9uXCIsIFwidHJhbnNsYXRlXCIsXG4gICAgXCJ1bmljb2RlLWJpZGlcIiwgXCJ1c2VyLXNlbGVjdFwiLCBcInZlcnRpY2FsLWFsaWduXCIsIFwidmlzaWJpbGl0eVwiLCBcInZvaWNlLWJhbGFuY2VcIixcbiAgICBcInZvaWNlLWR1cmF0aW9uXCIsIFwidm9pY2UtZmFtaWx5XCIsIFwidm9pY2UtcGl0Y2hcIiwgXCJ2b2ljZS1yYW5nZVwiLCBcInZvaWNlLXJhdGVcIixcbiAgICBcInZvaWNlLXN0cmVzc1wiLCBcInZvaWNlLXZvbHVtZVwiLCBcInZvbHVtZVwiLCBcIndoaXRlLXNwYWNlXCIsIFwid2lkb3dzXCIsIFwid2lkdGhcIixcbiAgICBcIndpbGwtY2hhbmdlXCIsIFwid29yZC1icmVha1wiLCBcIndvcmQtc3BhY2luZ1wiLCBcIndvcmQtd3JhcFwiLCBcIndyaXRpbmctbW9kZVwiLCBcInotaW5kZXhcIixcbiAgICAvLyBTVkctc3BlY2lmaWNcbiAgICBcImNsaXAtcGF0aFwiLCBcImNsaXAtcnVsZVwiLCBcIm1hc2tcIiwgXCJlbmFibGUtYmFja2dyb3VuZFwiLCBcImZpbHRlclwiLCBcImZsb29kLWNvbG9yXCIsXG4gICAgXCJmbG9vZC1vcGFjaXR5XCIsIFwibGlnaHRpbmctY29sb3JcIiwgXCJzdG9wLWNvbG9yXCIsIFwic3RvcC1vcGFjaXR5XCIsIFwicG9pbnRlci1ldmVudHNcIixcbiAgICBcImNvbG9yLWludGVycG9sYXRpb25cIiwgXCJjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnNcIixcbiAgICBcImNvbG9yLXJlbmRlcmluZ1wiLCBcImZpbGxcIiwgXCJmaWxsLW9wYWNpdHlcIiwgXCJmaWxsLXJ1bGVcIiwgXCJpbWFnZS1yZW5kZXJpbmdcIixcbiAgICBcIm1hcmtlclwiLCBcIm1hcmtlci1lbmRcIiwgXCJtYXJrZXItbWlkXCIsIFwibWFya2VyLXN0YXJ0XCIsIFwicGFpbnQtb3JkZXJcIiwgXCJzaGFwZS1yZW5kZXJpbmdcIiwgXCJzdHJva2VcIixcbiAgICBcInN0cm9rZS1kYXNoYXJyYXlcIiwgXCJzdHJva2UtZGFzaG9mZnNldFwiLCBcInN0cm9rZS1saW5lY2FwXCIsIFwic3Ryb2tlLWxpbmVqb2luXCIsXG4gICAgXCJzdHJva2UtbWl0ZXJsaW1pdFwiLCBcInN0cm9rZS1vcGFjaXR5XCIsIFwic3Ryb2tlLXdpZHRoXCIsIFwidGV4dC1yZW5kZXJpbmdcIixcbiAgICBcImJhc2VsaW5lLXNoaWZ0XCIsIFwiZG9taW5hbnQtYmFzZWxpbmVcIiwgXCJnbHlwaC1vcmllbnRhdGlvbi1ob3Jpem9udGFsXCIsXG4gICAgXCJnbHlwaC1vcmllbnRhdGlvbi12ZXJ0aWNhbFwiLCBcInRleHQtYW5jaG9yXCIsIFwid3JpdGluZy1tb2RlXCIsXG4gIF0sIHByb3BlcnR5S2V5d29yZHMgPSBrZXlTZXQocHJvcGVydHlLZXl3b3Jkc18pO1xuXG4gIHZhciBub25TdGFuZGFyZFByb3BlcnR5S2V5d29yZHNfID0gW1xuICAgIFwiYWNjZW50LWNvbG9yXCIsIFwiYXNwZWN0LXJhdGlvXCIsIFwiYm9yZGVyLWJsb2NrXCIsIFwiYm9yZGVyLWJsb2NrLWNvbG9yXCIsIFwiYm9yZGVyLWJsb2NrLWVuZFwiLFxuICAgIFwiYm9yZGVyLWJsb2NrLWVuZC1jb2xvclwiLCBcImJvcmRlci1ibG9jay1lbmQtc3R5bGVcIiwgXCJib3JkZXItYmxvY2stZW5kLXdpZHRoXCIsXG4gICAgXCJib3JkZXItYmxvY2stc3RhcnRcIiwgXCJib3JkZXItYmxvY2stc3RhcnQtY29sb3JcIiwgXCJib3JkZXItYmxvY2stc3RhcnQtc3R5bGVcIixcbiAgICBcImJvcmRlci1ibG9jay1zdGFydC13aWR0aFwiLCBcImJvcmRlci1ibG9jay1zdHlsZVwiLCBcImJvcmRlci1ibG9jay13aWR0aFwiLFxuICAgIFwiYm9yZGVyLWlubGluZVwiLCBcImJvcmRlci1pbmxpbmUtY29sb3JcIiwgXCJib3JkZXItaW5saW5lLWVuZFwiLFxuICAgIFwiYm9yZGVyLWlubGluZS1lbmQtY29sb3JcIiwgXCJib3JkZXItaW5saW5lLWVuZC1zdHlsZVwiLFxuICAgIFwiYm9yZGVyLWlubGluZS1lbmQtd2lkdGhcIiwgXCJib3JkZXItaW5saW5lLXN0YXJ0XCIsIFwiYm9yZGVyLWlubGluZS1zdGFydC1jb2xvclwiLFxuICAgIFwiYm9yZGVyLWlubGluZS1zdGFydC1zdHlsZVwiLCBcImJvcmRlci1pbmxpbmUtc3RhcnQtd2lkdGhcIixcbiAgICBcImJvcmRlci1pbmxpbmUtc3R5bGVcIiwgXCJib3JkZXItaW5saW5lLXdpZHRoXCIsIFwiY29udGVudC12aXNpYmlsaXR5XCIsIFwibWFyZ2luLWJsb2NrXCIsXG4gICAgXCJtYXJnaW4tYmxvY2stZW5kXCIsIFwibWFyZ2luLWJsb2NrLXN0YXJ0XCIsIFwibWFyZ2luLWlubGluZVwiLCBcIm1hcmdpbi1pbmxpbmUtZW5kXCIsXG4gICAgXCJtYXJnaW4taW5saW5lLXN0YXJ0XCIsIFwib3ZlcmZsb3ctYW5jaG9yXCIsIFwib3ZlcnNjcm9sbC1iZWhhdmlvclwiLCBcInBhZGRpbmctYmxvY2tcIiwgXCJwYWRkaW5nLWJsb2NrLWVuZFwiLFxuICAgIFwicGFkZGluZy1ibG9jay1zdGFydFwiLCBcInBhZGRpbmctaW5saW5lXCIsIFwicGFkZGluZy1pbmxpbmUtZW5kXCIsXG4gICAgXCJwYWRkaW5nLWlubGluZS1zdGFydFwiLCBcInNjcm9sbC1zbmFwLXN0b3BcIiwgXCJzY3JvbGxiYXItM2QtbGlnaHQtY29sb3JcIixcbiAgICBcInNjcm9sbGJhci1hcnJvdy1jb2xvclwiLCBcInNjcm9sbGJhci1iYXNlLWNvbG9yXCIsIFwic2Nyb2xsYmFyLWRhcmstc2hhZG93LWNvbG9yXCIsXG4gICAgXCJzY3JvbGxiYXItZmFjZS1jb2xvclwiLCBcInNjcm9sbGJhci1oaWdobGlnaHQtY29sb3JcIiwgXCJzY3JvbGxiYXItc2hhZG93LWNvbG9yXCIsXG4gICAgXCJzY3JvbGxiYXItdHJhY2stY29sb3JcIiwgXCJzZWFyY2hmaWVsZC1jYW5jZWwtYnV0dG9uXCIsIFwic2VhcmNoZmllbGQtZGVjb3JhdGlvblwiLFxuICAgIFwic2VhcmNoZmllbGQtcmVzdWx0cy1idXR0b25cIiwgXCJzZWFyY2hmaWVsZC1yZXN1bHRzLWRlY29yYXRpb25cIiwgXCJzaGFwZS1pbnNpZGVcIiwgXCJ6b29tXCJcbiAgXSwgbm9uU3RhbmRhcmRQcm9wZXJ0eUtleXdvcmRzID0ga2V5U2V0KG5vblN0YW5kYXJkUHJvcGVydHlLZXl3b3Jkc18pO1xuXG4gIHZhciBmb250UHJvcGVydGllc18gPSBbXG4gICAgXCJmb250LWRpc3BsYXlcIiwgXCJmb250LWZhbWlseVwiLCBcInNyY1wiLCBcInVuaWNvZGUtcmFuZ2VcIiwgXCJmb250LXZhcmlhbnRcIixcbiAgICAgXCJmb250LWZlYXR1cmUtc2V0dGluZ3NcIiwgXCJmb250LXN0cmV0Y2hcIiwgXCJmb250LXdlaWdodFwiLCBcImZvbnQtc3R5bGVcIlxuICBdLCBmb250UHJvcGVydGllcyA9IGtleVNldChmb250UHJvcGVydGllc18pO1xuXG4gIHZhciBjb3VudGVyRGVzY3JpcHRvcnNfID0gW1xuICAgIFwiYWRkaXRpdmUtc3ltYm9sc1wiLCBcImZhbGxiYWNrXCIsIFwibmVnYXRpdmVcIiwgXCJwYWRcIiwgXCJwcmVmaXhcIiwgXCJyYW5nZVwiLFxuICAgIFwic3BlYWstYXNcIiwgXCJzdWZmaXhcIiwgXCJzeW1ib2xzXCIsIFwic3lzdGVtXCJcbiAgXSwgY291bnRlckRlc2NyaXB0b3JzID0ga2V5U2V0KGNvdW50ZXJEZXNjcmlwdG9yc18pO1xuXG4gIHZhciBjb2xvcktleXdvcmRzXyA9IFtcbiAgICBcImFsaWNlYmx1ZVwiLCBcImFudGlxdWV3aGl0ZVwiLCBcImFxdWFcIiwgXCJhcXVhbWFyaW5lXCIsIFwiYXp1cmVcIiwgXCJiZWlnZVwiLFxuICAgIFwiYmlzcXVlXCIsIFwiYmxhY2tcIiwgXCJibGFuY2hlZGFsbW9uZFwiLCBcImJsdWVcIiwgXCJibHVldmlvbGV0XCIsIFwiYnJvd25cIixcbiAgICBcImJ1cmx5d29vZFwiLCBcImNhZGV0Ymx1ZVwiLCBcImNoYXJ0cmV1c2VcIiwgXCJjaG9jb2xhdGVcIiwgXCJjb3JhbFwiLCBcImNvcm5mbG93ZXJibHVlXCIsXG4gICAgXCJjb3Juc2lsa1wiLCBcImNyaW1zb25cIiwgXCJjeWFuXCIsIFwiZGFya2JsdWVcIiwgXCJkYXJrY3lhblwiLCBcImRhcmtnb2xkZW5yb2RcIixcbiAgICBcImRhcmtncmF5XCIsIFwiZGFya2dyZWVuXCIsIFwiZGFya2dyZXlcIiwgXCJkYXJra2hha2lcIiwgXCJkYXJrbWFnZW50YVwiLCBcImRhcmtvbGl2ZWdyZWVuXCIsXG4gICAgXCJkYXJrb3JhbmdlXCIsIFwiZGFya29yY2hpZFwiLCBcImRhcmtyZWRcIiwgXCJkYXJrc2FsbW9uXCIsIFwiZGFya3NlYWdyZWVuXCIsXG4gICAgXCJkYXJrc2xhdGVibHVlXCIsIFwiZGFya3NsYXRlZ3JheVwiLCBcImRhcmtzbGF0ZWdyZXlcIiwgXCJkYXJrdHVycXVvaXNlXCIsIFwiZGFya3Zpb2xldFwiLFxuICAgIFwiZGVlcHBpbmtcIiwgXCJkZWVwc2t5Ymx1ZVwiLCBcImRpbWdyYXlcIiwgXCJkaW1ncmV5XCIsIFwiZG9kZ2VyYmx1ZVwiLCBcImZpcmVicmlja1wiLFxuICAgIFwiZmxvcmFsd2hpdGVcIiwgXCJmb3Jlc3RncmVlblwiLCBcImZ1Y2hzaWFcIiwgXCJnYWluc2Jvcm9cIiwgXCJnaG9zdHdoaXRlXCIsXG4gICAgXCJnb2xkXCIsIFwiZ29sZGVucm9kXCIsIFwiZ3JheVwiLCBcImdyZXlcIiwgXCJncmVlblwiLCBcImdyZWVueWVsbG93XCIsIFwiaG9uZXlkZXdcIixcbiAgICBcImhvdHBpbmtcIiwgXCJpbmRpYW5yZWRcIiwgXCJpbmRpZ29cIiwgXCJpdm9yeVwiLCBcImtoYWtpXCIsIFwibGF2ZW5kZXJcIixcbiAgICBcImxhdmVuZGVyYmx1c2hcIiwgXCJsYXduZ3JlZW5cIiwgXCJsZW1vbmNoaWZmb25cIiwgXCJsaWdodGJsdWVcIiwgXCJsaWdodGNvcmFsXCIsXG4gICAgXCJsaWdodGN5YW5cIiwgXCJsaWdodGdvbGRlbnJvZHllbGxvd1wiLCBcImxpZ2h0Z3JheVwiLCBcImxpZ2h0Z3JlZW5cIiwgXCJsaWdodGdyZXlcIiwgXCJsaWdodHBpbmtcIixcbiAgICBcImxpZ2h0c2FsbW9uXCIsIFwibGlnaHRzZWFncmVlblwiLCBcImxpZ2h0c2t5Ymx1ZVwiLCBcImxpZ2h0c2xhdGVncmF5XCIsIFwibGlnaHRzbGF0ZWdyZXlcIixcbiAgICBcImxpZ2h0c3RlZWxibHVlXCIsIFwibGlnaHR5ZWxsb3dcIiwgXCJsaW1lXCIsIFwibGltZWdyZWVuXCIsIFwibGluZW5cIiwgXCJtYWdlbnRhXCIsXG4gICAgXCJtYXJvb25cIiwgXCJtZWRpdW1hcXVhbWFyaW5lXCIsIFwibWVkaXVtYmx1ZVwiLCBcIm1lZGl1bW9yY2hpZFwiLCBcIm1lZGl1bXB1cnBsZVwiLFxuICAgIFwibWVkaXVtc2VhZ3JlZW5cIiwgXCJtZWRpdW1zbGF0ZWJsdWVcIiwgXCJtZWRpdW1zcHJpbmdncmVlblwiLCBcIm1lZGl1bXR1cnF1b2lzZVwiLFxuICAgIFwibWVkaXVtdmlvbGV0cmVkXCIsIFwibWlkbmlnaHRibHVlXCIsIFwibWludGNyZWFtXCIsIFwibWlzdHlyb3NlXCIsIFwibW9jY2FzaW5cIixcbiAgICBcIm5hdmFqb3doaXRlXCIsIFwibmF2eVwiLCBcIm9sZGxhY2VcIiwgXCJvbGl2ZVwiLCBcIm9saXZlZHJhYlwiLCBcIm9yYW5nZVwiLCBcIm9yYW5nZXJlZFwiLFxuICAgIFwib3JjaGlkXCIsIFwicGFsZWdvbGRlbnJvZFwiLCBcInBhbGVncmVlblwiLCBcInBhbGV0dXJxdW9pc2VcIiwgXCJwYWxldmlvbGV0cmVkXCIsXG4gICAgXCJwYXBheWF3aGlwXCIsIFwicGVhY2hwdWZmXCIsIFwicGVydVwiLCBcInBpbmtcIiwgXCJwbHVtXCIsIFwicG93ZGVyYmx1ZVwiLFxuICAgIFwicHVycGxlXCIsIFwicmViZWNjYXB1cnBsZVwiLCBcInJlZFwiLCBcInJvc3licm93blwiLCBcInJveWFsYmx1ZVwiLCBcInNhZGRsZWJyb3duXCIsXG4gICAgXCJzYWxtb25cIiwgXCJzYW5keWJyb3duXCIsIFwic2VhZ3JlZW5cIiwgXCJzZWFzaGVsbFwiLCBcInNpZW5uYVwiLCBcInNpbHZlclwiLCBcInNreWJsdWVcIixcbiAgICBcInNsYXRlYmx1ZVwiLCBcInNsYXRlZ3JheVwiLCBcInNsYXRlZ3JleVwiLCBcInNub3dcIiwgXCJzcHJpbmdncmVlblwiLCBcInN0ZWVsYmx1ZVwiLCBcInRhblwiLFxuICAgIFwidGVhbFwiLCBcInRoaXN0bGVcIiwgXCJ0b21hdG9cIiwgXCJ0dXJxdW9pc2VcIiwgXCJ2aW9sZXRcIiwgXCJ3aGVhdFwiLCBcIndoaXRlXCIsXG4gICAgXCJ3aGl0ZXNtb2tlXCIsIFwieWVsbG93XCIsIFwieWVsbG93Z3JlZW5cIlxuICBdLCBjb2xvcktleXdvcmRzID0ga2V5U2V0KGNvbG9yS2V5d29yZHNfKTtcblxuICB2YXIgdmFsdWVLZXl3b3Jkc18gPSBbXG4gICAgXCJhYm92ZVwiLCBcImFic29sdXRlXCIsIFwiYWN0aXZlYm9yZGVyXCIsIFwiYWRkaXRpdmVcIiwgXCJhY3RpdmVjYXB0aW9uXCIsIFwiYWZhclwiLFxuICAgIFwiYWZ0ZXItd2hpdGUtc3BhY2VcIiwgXCJhaGVhZFwiLCBcImFsaWFzXCIsIFwiYWxsXCIsIFwiYWxsLXNjcm9sbFwiLCBcImFscGhhYmV0aWNcIiwgXCJhbHRlcm5hdGVcIixcbiAgICBcImFsd2F5c1wiLCBcImFtaGFyaWNcIiwgXCJhbWhhcmljLWFiZWdlZGVcIiwgXCJhbnRpYWxpYXNlZFwiLCBcImFwcHdvcmtzcGFjZVwiLFxuICAgIFwiYXJhYmljLWluZGljXCIsIFwiYXJtZW5pYW5cIiwgXCJhc3Rlcmlza3NcIiwgXCJhdHRyXCIsIFwiYXV0b1wiLCBcImF1dG8tZmxvd1wiLCBcImF2b2lkXCIsIFwiYXZvaWQtY29sdW1uXCIsIFwiYXZvaWQtcGFnZVwiLFxuICAgIFwiYXZvaWQtcmVnaW9uXCIsIFwiYXhpcy1wYW5cIiwgXCJiYWNrZ3JvdW5kXCIsIFwiYmFja3dhcmRzXCIsIFwiYmFzZWxpbmVcIiwgXCJiZWxvd1wiLCBcImJpZGktb3ZlcnJpZGVcIiwgXCJiaW5hcnlcIixcbiAgICBcImJlbmdhbGlcIiwgXCJibGlua1wiLCBcImJsb2NrXCIsIFwiYmxvY2stYXhpc1wiLCBcImJsdXJcIiwgXCJib2xkXCIsIFwiYm9sZGVyXCIsIFwiYm9yZGVyXCIsIFwiYm9yZGVyLWJveFwiLFxuICAgIFwiYm90aFwiLCBcImJvdHRvbVwiLCBcImJyZWFrXCIsIFwiYnJlYWstYWxsXCIsIFwiYnJlYWstd29yZFwiLCBcImJyaWdodG5lc3NcIiwgXCJidWxsZXRzXCIsIFwiYnV0dG9uXCIsXG4gICAgXCJidXR0b25mYWNlXCIsIFwiYnV0dG9uaGlnaGxpZ2h0XCIsIFwiYnV0dG9uc2hhZG93XCIsIFwiYnV0dG9udGV4dFwiLCBcImNhbGNcIiwgXCJjYW1ib2RpYW5cIixcbiAgICBcImNhcGl0YWxpemVcIiwgXCJjYXBzLWxvY2staW5kaWNhdG9yXCIsIFwiY2FwdGlvblwiLCBcImNhcHRpb250ZXh0XCIsIFwiY2FyZXRcIixcbiAgICBcImNlbGxcIiwgXCJjZW50ZXJcIiwgXCJjaGVja2JveFwiLCBcImNpcmNsZVwiLCBcImNqay1kZWNpbWFsXCIsIFwiY2prLWVhcnRobHktYnJhbmNoXCIsXG4gICAgXCJjamstaGVhdmVubHktc3RlbVwiLCBcImNqay1pZGVvZ3JhcGhpY1wiLCBcImNsZWFyXCIsIFwiY2xpcFwiLCBcImNsb3NlLXF1b3RlXCIsXG4gICAgXCJjb2wtcmVzaXplXCIsIFwiY29sbGFwc2VcIiwgXCJjb2xvclwiLCBcImNvbG9yLWJ1cm5cIiwgXCJjb2xvci1kb2RnZVwiLCBcImNvbHVtblwiLCBcImNvbHVtbi1yZXZlcnNlXCIsXG4gICAgXCJjb21wYWN0XCIsIFwiY29uZGVuc2VkXCIsIFwiY29uaWMtZ3JhZGllbnRcIiwgXCJjb250YWluXCIsIFwiY29udGVudFwiLCBcImNvbnRlbnRzXCIsXG4gICAgXCJjb250ZW50LWJveFwiLCBcImNvbnRleHQtbWVudVwiLCBcImNvbnRpbnVvdXNcIiwgXCJjb250cmFzdFwiLCBcImNvcHlcIiwgXCJjb3VudGVyXCIsIFwiY291bnRlcnNcIiwgXCJjb3ZlclwiLCBcImNyb3BcIixcbiAgICBcImNyb3NzXCIsIFwiY3Jvc3NoYWlyXCIsIFwiY3ViaWMtYmV6aWVyXCIsIFwiY3VycmVudGNvbG9yXCIsIFwiY3Vyc2l2ZVwiLCBcImN5Y2xpY1wiLCBcImRhcmtlblwiLCBcImRhc2hlZFwiLCBcImRlY2ltYWxcIixcbiAgICBcImRlY2ltYWwtbGVhZGluZy16ZXJvXCIsIFwiZGVmYXVsdFwiLCBcImRlZmF1bHQtYnV0dG9uXCIsIFwiZGVuc2VcIiwgXCJkZXN0aW5hdGlvbi1hdG9wXCIsXG4gICAgXCJkZXN0aW5hdGlvbi1pblwiLCBcImRlc3RpbmF0aW9uLW91dFwiLCBcImRlc3RpbmF0aW9uLW92ZXJcIiwgXCJkZXZhbmFnYXJpXCIsIFwiZGlmZmVyZW5jZVwiLFxuICAgIFwiZGlzY1wiLCBcImRpc2NhcmRcIiwgXCJkaXNjbG9zdXJlLWNsb3NlZFwiLCBcImRpc2Nsb3N1cmUtb3BlblwiLCBcImRvY3VtZW50XCIsXG4gICAgXCJkb3QtZGFzaFwiLCBcImRvdC1kb3QtZGFzaFwiLFxuICAgIFwiZG90dGVkXCIsIFwiZG91YmxlXCIsIFwiZG93blwiLCBcImRyb3Atc2hhZG93XCIsIFwiZS1yZXNpemVcIiwgXCJlYXNlXCIsIFwiZWFzZS1pblwiLCBcImVhc2UtaW4tb3V0XCIsIFwiZWFzZS1vdXRcIixcbiAgICBcImVsZW1lbnRcIiwgXCJlbGxpcHNlXCIsIFwiZWxsaXBzaXNcIiwgXCJlbWJlZFwiLCBcImVuZFwiLCBcImV0aGlvcGljXCIsIFwiZXRoaW9waWMtYWJlZ2VkZVwiLFxuICAgIFwiZXRoaW9waWMtYWJlZ2VkZS1hbS1ldFwiLCBcImV0aGlvcGljLWFiZWdlZGUtZ2V6XCIsIFwiZXRoaW9waWMtYWJlZ2VkZS10aS1lclwiLFxuICAgIFwiZXRoaW9waWMtYWJlZ2VkZS10aS1ldFwiLCBcImV0aGlvcGljLWhhbGVoYW1lLWFhLWVyXCIsXG4gICAgXCJldGhpb3BpYy1oYWxlaGFtZS1hYS1ldFwiLCBcImV0aGlvcGljLWhhbGVoYW1lLWFtLWV0XCIsXG4gICAgXCJldGhpb3BpYy1oYWxlaGFtZS1nZXpcIiwgXCJldGhpb3BpYy1oYWxlaGFtZS1vbS1ldFwiLFxuICAgIFwiZXRoaW9waWMtaGFsZWhhbWUtc2lkLWV0XCIsIFwiZXRoaW9waWMtaGFsZWhhbWUtc28tZXRcIixcbiAgICBcImV0aGlvcGljLWhhbGVoYW1lLXRpLWVyXCIsIFwiZXRoaW9waWMtaGFsZWhhbWUtdGktZXRcIiwgXCJldGhpb3BpYy1oYWxlaGFtZS10aWdcIixcbiAgICBcImV0aGlvcGljLW51bWVyaWNcIiwgXCJldy1yZXNpemVcIiwgXCJleGNsdXNpb25cIiwgXCJleHBhbmRlZFwiLCBcImV4dGVuZHNcIiwgXCJleHRyYS1jb25kZW5zZWRcIixcbiAgICBcImV4dHJhLWV4cGFuZGVkXCIsIFwiZmFudGFzeVwiLCBcImZhc3RcIiwgXCJmaWxsXCIsIFwiZmlsbC1ib3hcIiwgXCJmaXhlZFwiLCBcImZsYXRcIiwgXCJmbGV4XCIsIFwiZmxleC1lbmRcIiwgXCJmbGV4LXN0YXJ0XCIsIFwiZm9vdG5vdGVzXCIsXG4gICAgXCJmb3J3YXJkc1wiLCBcImZyb21cIiwgXCJnZW9tZXRyaWNQcmVjaXNpb25cIiwgXCJnZW9yZ2lhblwiLCBcImdyYXlzY2FsZVwiLCBcImdyYXl0ZXh0XCIsIFwiZ3JpZFwiLCBcImdyb292ZVwiLFxuICAgIFwiZ3VqYXJhdGlcIiwgXCJndXJtdWtoaVwiLCBcImhhbmRcIiwgXCJoYW5ndWxcIiwgXCJoYW5ndWwtY29uc29uYW50XCIsIFwiaGFyZC1saWdodFwiLCBcImhlYnJld1wiLFxuICAgIFwiaGVscFwiLCBcImhpZGRlblwiLCBcImhpZGVcIiwgXCJoaWdoZXJcIiwgXCJoaWdobGlnaHRcIiwgXCJoaWdobGlnaHR0ZXh0XCIsXG4gICAgXCJoaXJhZ2FuYVwiLCBcImhpcmFnYW5hLWlyb2hhXCIsIFwiaG9yaXpvbnRhbFwiLCBcImhzbFwiLCBcImhzbGFcIiwgXCJodWVcIiwgXCJodWUtcm90YXRlXCIsIFwiaWNvblwiLCBcImlnbm9yZVwiLFxuICAgIFwiaW5hY3RpdmVib3JkZXJcIiwgXCJpbmFjdGl2ZWNhcHRpb25cIiwgXCJpbmFjdGl2ZWNhcHRpb250ZXh0XCIsIFwiaW5maW5pdGVcIixcbiAgICBcImluZm9iYWNrZ3JvdW5kXCIsIFwiaW5mb3RleHRcIiwgXCJpbmhlcml0XCIsIFwiaW5pdGlhbFwiLCBcImlubGluZVwiLCBcImlubGluZS1heGlzXCIsXG4gICAgXCJpbmxpbmUtYmxvY2tcIiwgXCJpbmxpbmUtZmxleFwiLCBcImlubGluZS1ncmlkXCIsIFwiaW5saW5lLXRhYmxlXCIsIFwiaW5zZXRcIiwgXCJpbnNpZGVcIiwgXCJpbnRyaW5zaWNcIiwgXCJpbnZlcnRcIixcbiAgICBcIml0YWxpY1wiLCBcImphcGFuZXNlLWZvcm1hbFwiLCBcImphcGFuZXNlLWluZm9ybWFsXCIsIFwianVzdGlmeVwiLCBcImthbm5hZGFcIixcbiAgICBcImthdGFrYW5hXCIsIFwia2F0YWthbmEtaXJvaGFcIiwgXCJrZWVwLWFsbFwiLCBcImtobWVyXCIsXG4gICAgXCJrb3JlYW4taGFuZ3VsLWZvcm1hbFwiLCBcImtvcmVhbi1oYW5qYS1mb3JtYWxcIiwgXCJrb3JlYW4taGFuamEtaW5mb3JtYWxcIixcbiAgICBcImxhbmRzY2FwZVwiLCBcImxhb1wiLCBcImxhcmdlXCIsIFwibGFyZ2VyXCIsIFwibGVmdFwiLCBcImxldmVsXCIsIFwibGlnaHRlclwiLCBcImxpZ2h0ZW5cIixcbiAgICBcImxpbmUtdGhyb3VnaFwiLCBcImxpbmVhclwiLCBcImxpbmVhci1ncmFkaWVudFwiLCBcImxpbmVzXCIsIFwibGlzdC1pdGVtXCIsIFwibGlzdGJveFwiLCBcImxpc3RpdGVtXCIsXG4gICAgXCJsb2NhbFwiLCBcImxvZ2ljYWxcIiwgXCJsb3VkXCIsIFwibG93ZXJcIiwgXCJsb3dlci1hbHBoYVwiLCBcImxvd2VyLWFybWVuaWFuXCIsXG4gICAgXCJsb3dlci1ncmVla1wiLCBcImxvd2VyLWhleGFkZWNpbWFsXCIsIFwibG93ZXItbGF0aW5cIiwgXCJsb3dlci1ub3J3ZWdpYW5cIixcbiAgICBcImxvd2VyLXJvbWFuXCIsIFwibG93ZXJjYXNlXCIsIFwibHRyXCIsIFwibHVtaW5vc2l0eVwiLCBcIm1hbGF5YWxhbVwiLCBcIm1hbmlwdWxhdGlvblwiLCBcIm1hdGNoXCIsIFwibWF0cml4XCIsIFwibWF0cml4M2RcIixcbiAgICBcIm1lZGlhLXBsYXktYnV0dG9uXCIsIFwibWVkaWEtc2xpZGVyXCIsIFwibWVkaWEtc2xpZGVydGh1bWJcIixcbiAgICBcIm1lZGlhLXZvbHVtZS1zbGlkZXJcIiwgXCJtZWRpYS12b2x1bWUtc2xpZGVydGh1bWJcIiwgXCJtZWRpdW1cIixcbiAgICBcIm1lbnVcIiwgXCJtZW51bGlzdFwiLCBcIm1lbnVsaXN0LWJ1dHRvblwiLFxuICAgIFwibWVudXRleHRcIiwgXCJtZXNzYWdlLWJveFwiLCBcIm1pZGRsZVwiLCBcIm1pbi1pbnRyaW5zaWNcIixcbiAgICBcIm1peFwiLCBcIm1vbmdvbGlhblwiLCBcIm1vbm9zcGFjZVwiLCBcIm1vdmVcIiwgXCJtdWx0aXBsZVwiLCBcIm11bHRpcGxlX21hc2tfaW1hZ2VzXCIsIFwibXVsdGlwbHlcIiwgXCJteWFubWFyXCIsIFwibi1yZXNpemVcIixcbiAgICBcIm5hcnJvd2VyXCIsIFwibmUtcmVzaXplXCIsIFwibmVzdy1yZXNpemVcIiwgXCJuby1jbG9zZS1xdW90ZVwiLCBcIm5vLWRyb3BcIixcbiAgICBcIm5vLW9wZW4tcXVvdGVcIiwgXCJuby1yZXBlYXRcIiwgXCJub25lXCIsIFwibm9ybWFsXCIsIFwibm90LWFsbG93ZWRcIiwgXCJub3dyYXBcIixcbiAgICBcIm5zLXJlc2l6ZVwiLCBcIm51bWJlcnNcIiwgXCJudW1lcmljXCIsIFwibnctcmVzaXplXCIsIFwibndzZS1yZXNpemVcIiwgXCJvYmxpcXVlXCIsIFwib2N0YWxcIiwgXCJvcGFjaXR5XCIsIFwib3Blbi1xdW90ZVwiLFxuICAgIFwib3B0aW1pemVMZWdpYmlsaXR5XCIsIFwib3B0aW1pemVTcGVlZFwiLCBcIm9yaXlhXCIsIFwib3JvbW9cIiwgXCJvdXRzZXRcIixcbiAgICBcIm91dHNpZGVcIiwgXCJvdXRzaWRlLXNoYXBlXCIsIFwib3ZlcmxheVwiLCBcIm92ZXJsaW5lXCIsIFwicGFkZGluZ1wiLCBcInBhZGRpbmctYm94XCIsXG4gICAgXCJwYWludGVkXCIsIFwicGFnZVwiLCBcInBhdXNlZFwiLCBcInBlcnNpYW5cIiwgXCJwZXJzcGVjdGl2ZVwiLCBcInBpbmNoLXpvb21cIiwgXCJwbHVzLWRhcmtlclwiLCBcInBsdXMtbGlnaHRlclwiLFxuICAgIFwicG9pbnRlclwiLCBcInBvbHlnb25cIiwgXCJwb3J0cmFpdFwiLCBcInByZVwiLCBcInByZS1saW5lXCIsIFwicHJlLXdyYXBcIiwgXCJwcmVzZXJ2ZS0zZFwiLFxuICAgIFwicHJvZ3Jlc3NcIiwgXCJwdXNoLWJ1dHRvblwiLCBcInJhZGlhbC1ncmFkaWVudFwiLCBcInJhZGlvXCIsIFwicmVhZC1vbmx5XCIsXG4gICAgXCJyZWFkLXdyaXRlXCIsIFwicmVhZC13cml0ZS1wbGFpbnRleHQtb25seVwiLCBcInJlY3RhbmdsZVwiLCBcInJlZ2lvblwiLFxuICAgIFwicmVsYXRpdmVcIiwgXCJyZXBlYXRcIiwgXCJyZXBlYXRpbmctbGluZWFyLWdyYWRpZW50XCIsIFwicmVwZWF0aW5nLXJhZGlhbC1ncmFkaWVudFwiLFxuICAgIFwicmVwZWF0aW5nLWNvbmljLWdyYWRpZW50XCIsIFwicmVwZWF0LXhcIiwgXCJyZXBlYXQteVwiLCBcInJlc2V0XCIsIFwicmV2ZXJzZVwiLFxuICAgIFwicmdiXCIsIFwicmdiYVwiLCBcInJpZGdlXCIsIFwicmlnaHRcIiwgXCJyb3RhdGVcIiwgXCJyb3RhdGUzZFwiLCBcInJvdGF0ZVhcIiwgXCJyb3RhdGVZXCIsXG4gICAgXCJyb3RhdGVaXCIsIFwicm91bmRcIiwgXCJyb3dcIiwgXCJyb3ctcmVzaXplXCIsIFwicm93LXJldmVyc2VcIiwgXCJydGxcIiwgXCJydW4taW5cIiwgXCJydW5uaW5nXCIsXG4gICAgXCJzLXJlc2l6ZVwiLCBcInNhbnMtc2VyaWZcIiwgXCJzYXR1cmF0ZVwiLCBcInNhdHVyYXRpb25cIiwgXCJzY2FsZVwiLCBcInNjYWxlM2RcIiwgXCJzY2FsZVhcIiwgXCJzY2FsZVlcIiwgXCJzY2FsZVpcIiwgXCJzY3JlZW5cIixcbiAgICBcInNjcm9sbFwiLCBcInNjcm9sbGJhclwiLCBcInNjcm9sbC1wb3NpdGlvblwiLCBcInNlLXJlc2l6ZVwiLCBcInNlYXJjaGZpZWxkXCIsXG4gICAgXCJzZWFyY2hmaWVsZC1jYW5jZWwtYnV0dG9uXCIsIFwic2VhcmNoZmllbGQtZGVjb3JhdGlvblwiLFxuICAgIFwic2VhcmNoZmllbGQtcmVzdWx0cy1idXR0b25cIiwgXCJzZWFyY2hmaWVsZC1yZXN1bHRzLWRlY29yYXRpb25cIiwgXCJzZWxmLXN0YXJ0XCIsIFwic2VsZi1lbmRcIixcbiAgICBcInNlbWktY29uZGVuc2VkXCIsIFwic2VtaS1leHBhbmRlZFwiLCBcInNlcGFyYXRlXCIsIFwic2VwaWFcIiwgXCJzZXJpZlwiLCBcInNob3dcIiwgXCJzaWRhbWFcIixcbiAgICBcInNpbXAtY2hpbmVzZS1mb3JtYWxcIiwgXCJzaW1wLWNoaW5lc2UtaW5mb3JtYWxcIiwgXCJzaW5nbGVcIixcbiAgICBcInNrZXdcIiwgXCJza2V3WFwiLCBcInNrZXdZXCIsIFwic2tpcC13aGl0ZS1zcGFjZVwiLCBcInNsaWRlXCIsIFwic2xpZGVyLWhvcml6b250YWxcIixcbiAgICBcInNsaWRlci12ZXJ0aWNhbFwiLCBcInNsaWRlcnRodW1iLWhvcml6b250YWxcIiwgXCJzbGlkZXJ0aHVtYi12ZXJ0aWNhbFwiLCBcInNsb3dcIixcbiAgICBcInNtYWxsXCIsIFwic21hbGwtY2Fwc1wiLCBcInNtYWxsLWNhcHRpb25cIiwgXCJzbWFsbGVyXCIsIFwic29mdC1saWdodFwiLCBcInNvbGlkXCIsIFwic29tYWxpXCIsXG4gICAgXCJzb3VyY2UtYXRvcFwiLCBcInNvdXJjZS1pblwiLCBcInNvdXJjZS1vdXRcIiwgXCJzb3VyY2Utb3ZlclwiLCBcInNwYWNlXCIsIFwic3BhY2UtYXJvdW5kXCIsIFwic3BhY2UtYmV0d2VlblwiLCBcInNwYWNlLWV2ZW5seVwiLCBcInNwZWxsLW91dFwiLCBcInNxdWFyZVwiLFxuICAgIFwic3F1YXJlLWJ1dHRvblwiLCBcInN0YXJ0XCIsIFwic3RhdGljXCIsIFwic3RhdHVzLWJhclwiLCBcInN0cmV0Y2hcIiwgXCJzdHJva2VcIiwgXCJzdHJva2UtYm94XCIsIFwic3ViXCIsXG4gICAgXCJzdWJwaXhlbC1hbnRpYWxpYXNlZFwiLCBcInN2Z19tYXNrc1wiLCBcInN1cGVyXCIsIFwic3ctcmVzaXplXCIsIFwic3ltYm9saWNcIiwgXCJzeW1ib2xzXCIsIFwic3lzdGVtLXVpXCIsIFwidGFibGVcIixcbiAgICBcInRhYmxlLWNhcHRpb25cIiwgXCJ0YWJsZS1jZWxsXCIsIFwidGFibGUtY29sdW1uXCIsIFwidGFibGUtY29sdW1uLWdyb3VwXCIsXG4gICAgXCJ0YWJsZS1mb290ZXItZ3JvdXBcIiwgXCJ0YWJsZS1oZWFkZXItZ3JvdXBcIiwgXCJ0YWJsZS1yb3dcIiwgXCJ0YWJsZS1yb3ctZ3JvdXBcIixcbiAgICBcInRhbWlsXCIsXG4gICAgXCJ0ZWx1Z3VcIiwgXCJ0ZXh0XCIsIFwidGV4dC1ib3R0b21cIiwgXCJ0ZXh0LXRvcFwiLCBcInRleHRhcmVhXCIsIFwidGV4dGZpZWxkXCIsIFwidGhhaVwiLFxuICAgIFwidGhpY2tcIiwgXCJ0aGluXCIsIFwidGhyZWVkZGFya3NoYWRvd1wiLCBcInRocmVlZGZhY2VcIiwgXCJ0aHJlZWRoaWdobGlnaHRcIixcbiAgICBcInRocmVlZGxpZ2h0c2hhZG93XCIsIFwidGhyZWVkc2hhZG93XCIsIFwidGliZXRhblwiLCBcInRpZ3JlXCIsIFwidGlncmlueWEtZXJcIixcbiAgICBcInRpZ3JpbnlhLWVyLWFiZWdlZGVcIiwgXCJ0aWdyaW55YS1ldFwiLCBcInRpZ3JpbnlhLWV0LWFiZWdlZGVcIiwgXCJ0b1wiLCBcInRvcFwiLFxuICAgIFwidHJhZC1jaGluZXNlLWZvcm1hbFwiLCBcInRyYWQtY2hpbmVzZS1pbmZvcm1hbFwiLCBcInRyYW5zZm9ybVwiLFxuICAgIFwidHJhbnNsYXRlXCIsIFwidHJhbnNsYXRlM2RcIiwgXCJ0cmFuc2xhdGVYXCIsIFwidHJhbnNsYXRlWVwiLCBcInRyYW5zbGF0ZVpcIixcbiAgICBcInRyYW5zcGFyZW50XCIsIFwidWx0cmEtY29uZGVuc2VkXCIsIFwidWx0cmEtZXhwYW5kZWRcIiwgXCJ1bmRlcmxpbmVcIiwgXCJ1bmlkaXJlY3Rpb25hbC1wYW5cIiwgXCJ1bnNldFwiLCBcInVwXCIsXG4gICAgXCJ1cHBlci1hbHBoYVwiLCBcInVwcGVyLWFybWVuaWFuXCIsIFwidXBwZXItZ3JlZWtcIiwgXCJ1cHBlci1oZXhhZGVjaW1hbFwiLFxuICAgIFwidXBwZXItbGF0aW5cIiwgXCJ1cHBlci1ub3J3ZWdpYW5cIiwgXCJ1cHBlci1yb21hblwiLCBcInVwcGVyY2FzZVwiLCBcInVyZHVcIiwgXCJ1cmxcIixcbiAgICBcInZhclwiLCBcInZlcnRpY2FsXCIsIFwidmVydGljYWwtdGV4dFwiLCBcInZpZXctYm94XCIsIFwidmlzaWJsZVwiLCBcInZpc2libGVGaWxsXCIsIFwidmlzaWJsZVBhaW50ZWRcIixcbiAgICBcInZpc2libGVTdHJva2VcIiwgXCJ2aXN1YWxcIiwgXCJ3LXJlc2l6ZVwiLCBcIndhaXRcIiwgXCJ3YXZlXCIsIFwid2lkZXJcIixcbiAgICBcIndpbmRvd1wiLCBcIndpbmRvd2ZyYW1lXCIsIFwid2luZG93dGV4dFwiLCBcIndvcmRzXCIsIFwid3JhcFwiLCBcIndyYXAtcmV2ZXJzZVwiLCBcIngtbGFyZ2VcIiwgXCJ4LXNtYWxsXCIsIFwieG9yXCIsXG4gICAgXCJ4eC1sYXJnZVwiLCBcInh4LXNtYWxsXCJcbiAgXSwgdmFsdWVLZXl3b3JkcyA9IGtleVNldCh2YWx1ZUtleXdvcmRzXyk7XG5cbiAgdmFyIGFsbFdvcmRzID0gZG9jdW1lbnRUeXBlc18uY29uY2F0KG1lZGlhVHlwZXNfKS5jb25jYXQobWVkaWFGZWF0dXJlc18pLmNvbmNhdChtZWRpYVZhbHVlS2V5d29yZHNfKVxuICAgIC5jb25jYXQocHJvcGVydHlLZXl3b3Jkc18pLmNvbmNhdChub25TdGFuZGFyZFByb3BlcnR5S2V5d29yZHNfKS5jb25jYXQoY29sb3JLZXl3b3Jkc18pXG4gICAgLmNvbmNhdCh2YWx1ZUtleXdvcmRzXyk7XG4gIENvZGVNaXJyb3IucmVnaXN0ZXJIZWxwZXIoXCJoaW50V29yZHNcIiwgXCJjc3NcIiwgYWxsV29yZHMpO1xuXG4gIGZ1bmN0aW9uIHRva2VuQ0NvbW1lbnQoc3RyZWFtLCBzdGF0ZSkge1xuICAgIHZhciBtYXliZUVuZCA9IGZhbHNlLCBjaDtcbiAgICB3aGlsZSAoKGNoID0gc3RyZWFtLm5leHQoKSkgIT0gbnVsbCkge1xuICAgICAgaWYgKG1heWJlRW5kICYmIGNoID09IFwiL1wiKSB7XG4gICAgICAgIHN0YXRlLnRva2VuaXplID0gbnVsbDtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBtYXliZUVuZCA9IChjaCA9PSBcIipcIik7XG4gICAgfVxuICAgIHJldHVybiBbXCJjb21tZW50XCIsIFwiY29tbWVudFwiXTtcbiAgfVxuXG4gIENvZGVNaXJyb3IuZGVmaW5lTUlNRShcInRleHQvY3NzXCIsIHtcbiAgICBkb2N1bWVudFR5cGVzOiBkb2N1bWVudFR5cGVzLFxuICAgIG1lZGlhVHlwZXM6IG1lZGlhVHlwZXMsXG4gICAgbWVkaWFGZWF0dXJlczogbWVkaWFGZWF0dXJlcyxcbiAgICBtZWRpYVZhbHVlS2V5d29yZHM6IG1lZGlhVmFsdWVLZXl3b3JkcyxcbiAgICBwcm9wZXJ0eUtleXdvcmRzOiBwcm9wZXJ0eUtleXdvcmRzLFxuICAgIG5vblN0YW5kYXJkUHJvcGVydHlLZXl3b3Jkczogbm9uU3RhbmRhcmRQcm9wZXJ0eUtleXdvcmRzLFxuICAgIGZvbnRQcm9wZXJ0aWVzOiBmb250UHJvcGVydGllcyxcbiAgICBjb3VudGVyRGVzY3JpcHRvcnM6IGNvdW50ZXJEZXNjcmlwdG9ycyxcbiAgICBjb2xvcktleXdvcmRzOiBjb2xvcktleXdvcmRzLFxuICAgIHZhbHVlS2V5d29yZHM6IHZhbHVlS2V5d29yZHMsXG4gICAgdG9rZW5Ib29rczoge1xuICAgICAgXCIvXCI6IGZ1bmN0aW9uKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgICAgaWYgKCFzdHJlYW0uZWF0KFwiKlwiKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IHRva2VuQ0NvbW1lbnQ7XG4gICAgICAgIHJldHVybiB0b2tlbkNDb21tZW50KHN0cmVhbSwgc3RhdGUpO1xuICAgICAgfVxuICAgIH0sXG4gICAgbmFtZTogXCJjc3NcIlxuICB9KTtcblxuICBDb2RlTWlycm9yLmRlZmluZU1JTUUoXCJ0ZXh0L3gtc2Nzc1wiLCB7XG4gICAgbWVkaWFUeXBlczogbWVkaWFUeXBlcyxcbiAgICBtZWRpYUZlYXR1cmVzOiBtZWRpYUZlYXR1cmVzLFxuICAgIG1lZGlhVmFsdWVLZXl3b3JkczogbWVkaWFWYWx1ZUtleXdvcmRzLFxuICAgIHByb3BlcnR5S2V5d29yZHM6IHByb3BlcnR5S2V5d29yZHMsXG4gICAgbm9uU3RhbmRhcmRQcm9wZXJ0eUtleXdvcmRzOiBub25TdGFuZGFyZFByb3BlcnR5S2V5d29yZHMsXG4gICAgY29sb3JLZXl3b3JkczogY29sb3JLZXl3b3JkcyxcbiAgICB2YWx1ZUtleXdvcmRzOiB2YWx1ZUtleXdvcmRzLFxuICAgIGZvbnRQcm9wZXJ0aWVzOiBmb250UHJvcGVydGllcyxcbiAgICBhbGxvd05lc3RlZDogdHJ1ZSxcbiAgICBsaW5lQ29tbWVudDogXCIvL1wiLFxuICAgIHRva2VuSG9va3M6IHtcbiAgICAgIFwiL1wiOiBmdW5jdGlvbihzdHJlYW0sIHN0YXRlKSB7XG4gICAgICAgIGlmIChzdHJlYW0uZWF0KFwiL1wiKSkge1xuICAgICAgICAgIHN0cmVhbS5za2lwVG9FbmQoKTtcbiAgICAgICAgICByZXR1cm4gW1wiY29tbWVudFwiLCBcImNvbW1lbnRcIl07XG4gICAgICAgIH0gZWxzZSBpZiAoc3RyZWFtLmVhdChcIipcIikpIHtcbiAgICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IHRva2VuQ0NvbW1lbnQ7XG4gICAgICAgICAgcmV0dXJuIHRva2VuQ0NvbW1lbnQoc3RyZWFtLCBzdGF0ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIFtcIm9wZXJhdG9yXCIsIFwib3BlcmF0b3JcIl07XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBcIjpcIjogZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgIGlmIChzdHJlYW0ubWF0Y2goL15cXHMqXFx7LywgZmFsc2UpKVxuICAgICAgICAgIHJldHVybiBbbnVsbCwgbnVsbF1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSxcbiAgICAgIFwiJFwiOiBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgc3RyZWFtLm1hdGNoKC9eW1xcdy1dKy8pO1xuICAgICAgICBpZiAoc3RyZWFtLm1hdGNoKC9eXFxzKjovLCBmYWxzZSkpXG4gICAgICAgICAgcmV0dXJuIFtcInZhcmlhYmxlLTJcIiwgXCJ2YXJpYWJsZS1kZWZpbml0aW9uXCJdO1xuICAgICAgICByZXR1cm4gW1widmFyaWFibGUtMlwiLCBcInZhcmlhYmxlXCJdO1xuICAgICAgfSxcbiAgICAgIFwiI1wiOiBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgaWYgKCFzdHJlYW0uZWF0KFwie1wiKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICByZXR1cm4gW251bGwsIFwiaW50ZXJwb2xhdGlvblwiXTtcbiAgICAgIH1cbiAgICB9LFxuICAgIG5hbWU6IFwiY3NzXCIsXG4gICAgaGVscGVyVHlwZTogXCJzY3NzXCJcbiAgfSk7XG5cbiAgQ29kZU1pcnJvci5kZWZpbmVNSU1FKFwidGV4dC94LWxlc3NcIiwge1xuICAgIG1lZGlhVHlwZXM6IG1lZGlhVHlwZXMsXG4gICAgbWVkaWFGZWF0dXJlczogbWVkaWFGZWF0dXJlcyxcbiAgICBtZWRpYVZhbHVlS2V5d29yZHM6IG1lZGlhVmFsdWVLZXl3b3JkcyxcbiAgICBwcm9wZXJ0eUtleXdvcmRzOiBwcm9wZXJ0eUtleXdvcmRzLFxuICAgIG5vblN0YW5kYXJkUHJvcGVydHlLZXl3b3Jkczogbm9uU3RhbmRhcmRQcm9wZXJ0eUtleXdvcmRzLFxuICAgIGNvbG9yS2V5d29yZHM6IGNvbG9yS2V5d29yZHMsXG4gICAgdmFsdWVLZXl3b3JkczogdmFsdWVLZXl3b3JkcyxcbiAgICBmb250UHJvcGVydGllczogZm9udFByb3BlcnRpZXMsXG4gICAgYWxsb3dOZXN0ZWQ6IHRydWUsXG4gICAgbGluZUNvbW1lbnQ6IFwiLy9cIixcbiAgICB0b2tlbkhvb2tzOiB7XG4gICAgICBcIi9cIjogZnVuY3Rpb24oc3RyZWFtLCBzdGF0ZSkge1xuICAgICAgICBpZiAoc3RyZWFtLmVhdChcIi9cIikpIHtcbiAgICAgICAgICBzdHJlYW0uc2tpcFRvRW5kKCk7XG4gICAgICAgICAgcmV0dXJuIFtcImNvbW1lbnRcIiwgXCJjb21tZW50XCJdO1xuICAgICAgICB9IGVsc2UgaWYgKHN0cmVhbS5lYXQoXCIqXCIpKSB7XG4gICAgICAgICAgc3RhdGUudG9rZW5pemUgPSB0b2tlbkNDb21tZW50O1xuICAgICAgICAgIHJldHVybiB0b2tlbkNDb21tZW50KHN0cmVhbSwgc3RhdGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBbXCJvcGVyYXRvclwiLCBcIm9wZXJhdG9yXCJdO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgXCJAXCI6IGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgICAgICBpZiAoc3RyZWFtLmVhdChcIntcIikpIHJldHVybiBbbnVsbCwgXCJpbnRlcnBvbGF0aW9uXCJdO1xuICAgICAgICBpZiAoc3RyZWFtLm1hdGNoKC9eKGNoYXJzZXR8ZG9jdW1lbnR8Zm9udC1mYWNlfGltcG9ydHwoLShtb3p8bXN8b3x3ZWJraXQpLSk/a2V5ZnJhbWVzfG1lZGlhfG5hbWVzcGFjZXxwYWdlfHN1cHBvcnRzKVxcYi9pLCBmYWxzZSkpIHJldHVybiBmYWxzZTtcbiAgICAgICAgc3RyZWFtLmVhdFdoaWxlKC9bXFx3XFxcXFxcLV0vKTtcbiAgICAgICAgaWYgKHN0cmVhbS5tYXRjaCgvXlxccyo6LywgZmFsc2UpKVxuICAgICAgICAgIHJldHVybiBbXCJ2YXJpYWJsZS0yXCIsIFwidmFyaWFibGUtZGVmaW5pdGlvblwiXTtcbiAgICAgICAgcmV0dXJuIFtcInZhcmlhYmxlLTJcIiwgXCJ2YXJpYWJsZVwiXTtcbiAgICAgIH0sXG4gICAgICBcIiZcIjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBbXCJhdG9tXCIsIFwiYXRvbVwiXTtcbiAgICAgIH1cbiAgICB9LFxuICAgIG5hbWU6IFwiY3NzXCIsXG4gICAgaGVscGVyVHlwZTogXCJsZXNzXCJcbiAgfSk7XG5cbiAgQ29kZU1pcnJvci5kZWZpbmVNSU1FKFwidGV4dC94LWdzc1wiLCB7XG4gICAgZG9jdW1lbnRUeXBlczogZG9jdW1lbnRUeXBlcyxcbiAgICBtZWRpYVR5cGVzOiBtZWRpYVR5cGVzLFxuICAgIG1lZGlhRmVhdHVyZXM6IG1lZGlhRmVhdHVyZXMsXG4gICAgcHJvcGVydHlLZXl3b3JkczogcHJvcGVydHlLZXl3b3JkcyxcbiAgICBub25TdGFuZGFyZFByb3BlcnR5S2V5d29yZHM6IG5vblN0YW5kYXJkUHJvcGVydHlLZXl3b3JkcyxcbiAgICBmb250UHJvcGVydGllczogZm9udFByb3BlcnRpZXMsXG4gICAgY291bnRlckRlc2NyaXB0b3JzOiBjb3VudGVyRGVzY3JpcHRvcnMsXG4gICAgY29sb3JLZXl3b3JkczogY29sb3JLZXl3b3JkcyxcbiAgICB2YWx1ZUtleXdvcmRzOiB2YWx1ZUtleXdvcmRzLFxuICAgIHN1cHBvcnRzQXRDb21wb25lbnQ6IHRydWUsXG4gICAgdG9rZW5Ib29rczoge1xuICAgICAgXCIvXCI6IGZ1bmN0aW9uKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgICAgaWYgKCFzdHJlYW0uZWF0KFwiKlwiKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IHRva2VuQ0NvbW1lbnQ7XG4gICAgICAgIHJldHVybiB0b2tlbkNDb21tZW50KHN0cmVhbSwgc3RhdGUpO1xuICAgICAgfVxuICAgIH0sXG4gICAgbmFtZTogXCJjc3NcIixcbiAgICBoZWxwZXJUeXBlOiBcImdzc1wiXG4gIH0pO1xuXG59KTtcbiIsIi8vIENvZGVNaXJyb3IsIGNvcHlyaWdodCAoYykgYnkgTWFyaWpuIEhhdmVyYmVrZSBhbmQgb3RoZXJzXG4vLyBEaXN0cmlidXRlZCB1bmRlciBhbiBNSVQgbGljZW5zZTogaHR0cHM6Ly9jb2RlbWlycm9yLm5ldC9MSUNFTlNFXG5cbihmdW5jdGlvbihtb2QpIHtcbiAgaWYgKHR5cGVvZiBleHBvcnRzID09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZSA9PSBcIm9iamVjdFwiKSAvLyBDb21tb25KU1xuICAgIG1vZChyZXF1aXJlKFwiLi4vLi4vbGliL2NvZGVtaXJyb3JcIiksIHJlcXVpcmUoXCIuLi94bWwveG1sXCIpLCByZXF1aXJlKFwiLi4vamF2YXNjcmlwdC9qYXZhc2NyaXB0XCIpLCByZXF1aXJlKFwiLi4vY3NzL2Nzc1wiKSk7XG4gIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIC8vIEFNRFxuICAgIGRlZmluZShbXCIuLi8uLi9saWIvY29kZW1pcnJvclwiLCBcIi4uL3htbC94bWxcIiwgXCIuLi9qYXZhc2NyaXB0L2phdmFzY3JpcHRcIiwgXCIuLi9jc3MvY3NzXCJdLCBtb2QpO1xuICBlbHNlIC8vIFBsYWluIGJyb3dzZXIgZW52XG4gICAgbW9kKENvZGVNaXJyb3IpO1xufSkoZnVuY3Rpb24oQ29kZU1pcnJvcikge1xuICBcInVzZSBzdHJpY3RcIjtcblxuICB2YXIgZGVmYXVsdFRhZ3MgPSB7XG4gICAgc2NyaXB0OiBbXG4gICAgICBbXCJsYW5nXCIsIC8oamF2YXNjcmlwdHxiYWJlbCkvaSwgXCJqYXZhc2NyaXB0XCJdLFxuICAgICAgW1widHlwZVwiLCAvXig/OnRleHR8YXBwbGljYXRpb24pXFwvKD86eC0pPyg/OmphdmF8ZWNtYSlzY3JpcHQkfF5tb2R1bGUkfF4kL2ksIFwiamF2YXNjcmlwdFwiXSxcbiAgICAgIFtcInR5cGVcIiwgLy4vLCBcInRleHQvcGxhaW5cIl0sXG4gICAgICBbbnVsbCwgbnVsbCwgXCJqYXZhc2NyaXB0XCJdXG4gICAgXSxcbiAgICBzdHlsZTogIFtcbiAgICAgIFtcImxhbmdcIiwgL15jc3MkL2ksIFwiY3NzXCJdLFxuICAgICAgW1widHlwZVwiLCAvXih0ZXh0XFwvKT8oeC0pPyhzdHlsZXNoZWV0fGNzcykkL2ksIFwiY3NzXCJdLFxuICAgICAgW1widHlwZVwiLCAvLi8sIFwidGV4dC9wbGFpblwiXSxcbiAgICAgIFtudWxsLCBudWxsLCBcImNzc1wiXVxuICAgIF1cbiAgfTtcblxuICBmdW5jdGlvbiBtYXliZUJhY2t1cChzdHJlYW0sIHBhdCwgc3R5bGUpIHtcbiAgICB2YXIgY3VyID0gc3RyZWFtLmN1cnJlbnQoKSwgY2xvc2UgPSBjdXIuc2VhcmNoKHBhdCk7XG4gICAgaWYgKGNsb3NlID4gLTEpIHtcbiAgICAgIHN0cmVhbS5iYWNrVXAoY3VyLmxlbmd0aCAtIGNsb3NlKTtcbiAgICB9IGVsc2UgaWYgKGN1ci5tYXRjaCgvPFxcLz8kLykpIHtcbiAgICAgIHN0cmVhbS5iYWNrVXAoY3VyLmxlbmd0aCk7XG4gICAgICBpZiAoIXN0cmVhbS5tYXRjaChwYXQsIGZhbHNlKSkgc3RyZWFtLm1hdGNoKGN1cik7XG4gICAgfVxuICAgIHJldHVybiBzdHlsZTtcbiAgfVxuXG4gIHZhciBhdHRyUmVnZXhwQ2FjaGUgPSB7fTtcbiAgZnVuY3Rpb24gZ2V0QXR0clJlZ2V4cChhdHRyKSB7XG4gICAgdmFyIHJlZ2V4cCA9IGF0dHJSZWdleHBDYWNoZVthdHRyXTtcbiAgICBpZiAocmVnZXhwKSByZXR1cm4gcmVnZXhwO1xuICAgIHJldHVybiBhdHRyUmVnZXhwQ2FjaGVbYXR0cl0gPSBuZXcgUmVnRXhwKFwiXFxcXHMrXCIgKyBhdHRyICsgXCJcXFxccyo9XFxcXHMqKCd8XFxcIik/KFteJ1xcXCJdKykoJ3xcXFwiKT9cXFxccypcIik7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRBdHRyVmFsdWUodGV4dCwgYXR0cikge1xuICAgIHZhciBtYXRjaCA9IHRleHQubWF0Y2goZ2V0QXR0clJlZ2V4cChhdHRyKSlcbiAgICByZXR1cm4gbWF0Y2ggPyAvXlxccyooLio/KVxccyokLy5leGVjKG1hdGNoWzJdKVsxXSA6IFwiXCJcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldFRhZ1JlZ2V4cCh0YWdOYW1lLCBhbmNob3JlZCkge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKChhbmNob3JlZCA/IFwiXlwiIDogXCJcIikgKyBcIjxcXC9cXFxccypcIiArIHRhZ05hbWUgKyBcIlxcXFxzKj5cIiwgXCJpXCIpO1xuICB9XG5cbiAgZnVuY3Rpb24gYWRkVGFncyhmcm9tLCB0bykge1xuICAgIGZvciAodmFyIHRhZyBpbiBmcm9tKSB7XG4gICAgICB2YXIgZGVzdCA9IHRvW3RhZ10gfHwgKHRvW3RhZ10gPSBbXSk7XG4gICAgICB2YXIgc291cmNlID0gZnJvbVt0YWddO1xuICAgICAgZm9yICh2YXIgaSA9IHNvdXJjZS5sZW5ndGggLSAxOyBpID49IDA7IGktLSlcbiAgICAgICAgZGVzdC51bnNoaWZ0KHNvdXJjZVtpXSlcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBmaW5kTWF0Y2hpbmdNb2RlKHRhZ0luZm8sIHRhZ1RleHQpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRhZ0luZm8ubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBzcGVjID0gdGFnSW5mb1tpXTtcbiAgICAgIGlmICghc3BlY1swXSB8fCBzcGVjWzFdLnRlc3QoZ2V0QXR0clZhbHVlKHRhZ1RleHQsIHNwZWNbMF0pKSkgcmV0dXJuIHNwZWNbMl07XG4gICAgfVxuICB9XG5cbiAgQ29kZU1pcnJvci5kZWZpbmVNb2RlKFwiaHRtbG1peGVkXCIsIGZ1bmN0aW9uIChjb25maWcsIHBhcnNlckNvbmZpZykge1xuICAgIHZhciBodG1sTW9kZSA9IENvZGVNaXJyb3IuZ2V0TW9kZShjb25maWcsIHtcbiAgICAgIG5hbWU6IFwieG1sXCIsXG4gICAgICBodG1sTW9kZTogdHJ1ZSxcbiAgICAgIG11bHRpbGluZVRhZ0luZGVudEZhY3RvcjogcGFyc2VyQ29uZmlnLm11bHRpbGluZVRhZ0luZGVudEZhY3RvcixcbiAgICAgIG11bHRpbGluZVRhZ0luZGVudFBhc3RUYWc6IHBhcnNlckNvbmZpZy5tdWx0aWxpbmVUYWdJbmRlbnRQYXN0VGFnLFxuICAgICAgYWxsb3dNaXNzaW5nVGFnTmFtZTogcGFyc2VyQ29uZmlnLmFsbG93TWlzc2luZ1RhZ05hbWUsXG4gICAgfSk7XG5cbiAgICB2YXIgdGFncyA9IHt9O1xuICAgIHZhciBjb25maWdUYWdzID0gcGFyc2VyQ29uZmlnICYmIHBhcnNlckNvbmZpZy50YWdzLCBjb25maWdTY3JpcHQgPSBwYXJzZXJDb25maWcgJiYgcGFyc2VyQ29uZmlnLnNjcmlwdFR5cGVzO1xuICAgIGFkZFRhZ3MoZGVmYXVsdFRhZ3MsIHRhZ3MpO1xuICAgIGlmIChjb25maWdUYWdzKSBhZGRUYWdzKGNvbmZpZ1RhZ3MsIHRhZ3MpO1xuICAgIGlmIChjb25maWdTY3JpcHQpIGZvciAodmFyIGkgPSBjb25maWdTY3JpcHQubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pXG4gICAgICB0YWdzLnNjcmlwdC51bnNoaWZ0KFtcInR5cGVcIiwgY29uZmlnU2NyaXB0W2ldLm1hdGNoZXMsIGNvbmZpZ1NjcmlwdFtpXS5tb2RlXSlcblxuICAgIGZ1bmN0aW9uIGh0bWwoc3RyZWFtLCBzdGF0ZSkge1xuICAgICAgdmFyIHN0eWxlID0gaHRtbE1vZGUudG9rZW4oc3RyZWFtLCBzdGF0ZS5odG1sU3RhdGUpLCB0YWcgPSAvXFxidGFnXFxiLy50ZXN0KHN0eWxlKSwgdGFnTmFtZVxuICAgICAgaWYgKHRhZyAmJiAhL1s8Plxcc1xcL10vLnRlc3Qoc3RyZWFtLmN1cnJlbnQoKSkgJiZcbiAgICAgICAgICAodGFnTmFtZSA9IHN0YXRlLmh0bWxTdGF0ZS50YWdOYW1lICYmIHN0YXRlLmh0bWxTdGF0ZS50YWdOYW1lLnRvTG93ZXJDYXNlKCkpICYmXG4gICAgICAgICAgdGFncy5oYXNPd25Qcm9wZXJ0eSh0YWdOYW1lKSkge1xuICAgICAgICBzdGF0ZS5pblRhZyA9IHRhZ05hbWUgKyBcIiBcIlxuICAgICAgfSBlbHNlIGlmIChzdGF0ZS5pblRhZyAmJiB0YWcgJiYgLz4kLy50ZXN0KHN0cmVhbS5jdXJyZW50KCkpKSB7XG4gICAgICAgIHZhciBpblRhZyA9IC9eKFtcXFNdKykgKC4qKS8uZXhlYyhzdGF0ZS5pblRhZylcbiAgICAgICAgc3RhdGUuaW5UYWcgPSBudWxsXG4gICAgICAgIHZhciBtb2RlU3BlYyA9IHN0cmVhbS5jdXJyZW50KCkgPT0gXCI+XCIgJiYgZmluZE1hdGNoaW5nTW9kZSh0YWdzW2luVGFnWzFdXSwgaW5UYWdbMl0pXG4gICAgICAgIHZhciBtb2RlID0gQ29kZU1pcnJvci5nZXRNb2RlKGNvbmZpZywgbW9kZVNwZWMpXG4gICAgICAgIHZhciBlbmRUYWdBID0gZ2V0VGFnUmVnZXhwKGluVGFnWzFdLCB0cnVlKSwgZW5kVGFnID0gZ2V0VGFnUmVnZXhwKGluVGFnWzFdLCBmYWxzZSk7XG4gICAgICAgIHN0YXRlLnRva2VuID0gZnVuY3Rpb24gKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgICAgICBpZiAoc3RyZWFtLm1hdGNoKGVuZFRhZ0EsIGZhbHNlKSkge1xuICAgICAgICAgICAgc3RhdGUudG9rZW4gPSBodG1sO1xuICAgICAgICAgICAgc3RhdGUubG9jYWxTdGF0ZSA9IHN0YXRlLmxvY2FsTW9kZSA9IG51bGw7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG1heWJlQmFja3VwKHN0cmVhbSwgZW5kVGFnLCBzdGF0ZS5sb2NhbE1vZGUudG9rZW4oc3RyZWFtLCBzdGF0ZS5sb2NhbFN0YXRlKSk7XG4gICAgICAgIH07XG4gICAgICAgIHN0YXRlLmxvY2FsTW9kZSA9IG1vZGU7XG4gICAgICAgIHN0YXRlLmxvY2FsU3RhdGUgPSBDb2RlTWlycm9yLnN0YXJ0U3RhdGUobW9kZSwgaHRtbE1vZGUuaW5kZW50KHN0YXRlLmh0bWxTdGF0ZSwgXCJcIiwgXCJcIikpO1xuICAgICAgfSBlbHNlIGlmIChzdGF0ZS5pblRhZykge1xuICAgICAgICBzdGF0ZS5pblRhZyArPSBzdHJlYW0uY3VycmVudCgpXG4gICAgICAgIGlmIChzdHJlYW0uZW9sKCkpIHN0YXRlLmluVGFnICs9IFwiIFwiXG4gICAgICB9XG4gICAgICByZXR1cm4gc3R5bGU7XG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICBzdGFydFN0YXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzdGF0ZSA9IENvZGVNaXJyb3Iuc3RhcnRTdGF0ZShodG1sTW9kZSk7XG4gICAgICAgIHJldHVybiB7dG9rZW46IGh0bWwsIGluVGFnOiBudWxsLCBsb2NhbE1vZGU6IG51bGwsIGxvY2FsU3RhdGU6IG51bGwsIGh0bWxTdGF0ZTogc3RhdGV9O1xuICAgICAgfSxcblxuICAgICAgY29weVN0YXRlOiBmdW5jdGlvbiAoc3RhdGUpIHtcbiAgICAgICAgdmFyIGxvY2FsO1xuICAgICAgICBpZiAoc3RhdGUubG9jYWxTdGF0ZSkge1xuICAgICAgICAgIGxvY2FsID0gQ29kZU1pcnJvci5jb3B5U3RhdGUoc3RhdGUubG9jYWxNb2RlLCBzdGF0ZS5sb2NhbFN0YXRlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge3Rva2VuOiBzdGF0ZS50b2tlbiwgaW5UYWc6IHN0YXRlLmluVGFnLFxuICAgICAgICAgICAgICAgIGxvY2FsTW9kZTogc3RhdGUubG9jYWxNb2RlLCBsb2NhbFN0YXRlOiBsb2NhbCxcbiAgICAgICAgICAgICAgICBodG1sU3RhdGU6IENvZGVNaXJyb3IuY29weVN0YXRlKGh0bWxNb2RlLCBzdGF0ZS5odG1sU3RhdGUpfTtcbiAgICAgIH0sXG5cbiAgICAgIHRva2VuOiBmdW5jdGlvbiAoc3RyZWFtLCBzdGF0ZSkge1xuICAgICAgICByZXR1cm4gc3RhdGUudG9rZW4oc3RyZWFtLCBzdGF0ZSk7XG4gICAgICB9LFxuXG4gICAgICBpbmRlbnQ6IGZ1bmN0aW9uIChzdGF0ZSwgdGV4dEFmdGVyLCBsaW5lKSB7XG4gICAgICAgIGlmICghc3RhdGUubG9jYWxNb2RlIHx8IC9eXFxzKjxcXC8vLnRlc3QodGV4dEFmdGVyKSlcbiAgICAgICAgICByZXR1cm4gaHRtbE1vZGUuaW5kZW50KHN0YXRlLmh0bWxTdGF0ZSwgdGV4dEFmdGVyLCBsaW5lKTtcbiAgICAgICAgZWxzZSBpZiAoc3RhdGUubG9jYWxNb2RlLmluZGVudClcbiAgICAgICAgICByZXR1cm4gc3RhdGUubG9jYWxNb2RlLmluZGVudChzdGF0ZS5sb2NhbFN0YXRlLCB0ZXh0QWZ0ZXIsIGxpbmUpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgcmV0dXJuIENvZGVNaXJyb3IuUGFzcztcbiAgICAgIH0sXG5cbiAgICAgIGlubmVyTW9kZTogZnVuY3Rpb24gKHN0YXRlKSB7XG4gICAgICAgIHJldHVybiB7c3RhdGU6IHN0YXRlLmxvY2FsU3RhdGUgfHwgc3RhdGUuaHRtbFN0YXRlLCBtb2RlOiBzdGF0ZS5sb2NhbE1vZGUgfHwgaHRtbE1vZGV9O1xuICAgICAgfVxuICAgIH07XG4gIH0sIFwieG1sXCIsIFwiamF2YXNjcmlwdFwiLCBcImNzc1wiKTtcblxuICBDb2RlTWlycm9yLmRlZmluZU1JTUUoXCJ0ZXh0L2h0bWxcIiwgXCJodG1sbWl4ZWRcIik7XG59KTtcbiIsIi8vIENvZGVNaXJyb3IsIGNvcHlyaWdodCAoYykgYnkgTWFyaWpuIEhhdmVyYmVrZSBhbmQgb3RoZXJzXG4vLyBEaXN0cmlidXRlZCB1bmRlciBhbiBNSVQgbGljZW5zZTogaHR0cHM6Ly9jb2RlbWlycm9yLm5ldC9MSUNFTlNFXG5cbihmdW5jdGlvbihtb2QpIHtcbiAgaWYgKHR5cGVvZiBleHBvcnRzID09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZSA9PSBcIm9iamVjdFwiKSAvLyBDb21tb25KU1xuICAgIG1vZChyZXF1aXJlKFwiLi4vLi4vbGliL2NvZGVtaXJyb3JcIikpO1xuICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSAvLyBBTURcbiAgICBkZWZpbmUoW1wiLi4vLi4vbGliL2NvZGVtaXJyb3JcIl0sIG1vZCk7XG4gIGVsc2UgLy8gUGxhaW4gYnJvd3NlciBlbnZcbiAgICBtb2QoQ29kZU1pcnJvcik7XG59KShmdW5jdGlvbihDb2RlTWlycm9yKSB7XG5cInVzZSBzdHJpY3RcIjtcblxuQ29kZU1pcnJvci5kZWZpbmVNb2RlKFwiamF2YXNjcmlwdFwiLCBmdW5jdGlvbihjb25maWcsIHBhcnNlckNvbmZpZykge1xuICB2YXIgaW5kZW50VW5pdCA9IGNvbmZpZy5pbmRlbnRVbml0O1xuICB2YXIgc3RhdGVtZW50SW5kZW50ID0gcGFyc2VyQ29uZmlnLnN0YXRlbWVudEluZGVudDtcbiAgdmFyIGpzb25sZE1vZGUgPSBwYXJzZXJDb25maWcuanNvbmxkO1xuICB2YXIganNvbk1vZGUgPSBwYXJzZXJDb25maWcuanNvbiB8fCBqc29ubGRNb2RlO1xuICB2YXIgdHJhY2tTY29wZSA9IHBhcnNlckNvbmZpZy50cmFja1Njb3BlICE9PSBmYWxzZVxuICB2YXIgaXNUUyA9IHBhcnNlckNvbmZpZy50eXBlc2NyaXB0O1xuICB2YXIgd29yZFJFID0gcGFyc2VyQ29uZmlnLndvcmRDaGFyYWN0ZXJzIHx8IC9bXFx3JFxceGExLVxcdWZmZmZdLztcblxuICAvLyBUb2tlbml6ZXJcblxuICB2YXIga2V5d29yZHMgPSBmdW5jdGlvbigpe1xuICAgIGZ1bmN0aW9uIGt3KHR5cGUpIHtyZXR1cm4ge3R5cGU6IHR5cGUsIHN0eWxlOiBcImtleXdvcmRcIn07fVxuICAgIHZhciBBID0ga3coXCJrZXl3b3JkIGFcIiksIEIgPSBrdyhcImtleXdvcmQgYlwiKSwgQyA9IGt3KFwia2V5d29yZCBjXCIpLCBEID0ga3coXCJrZXl3b3JkIGRcIik7XG4gICAgdmFyIG9wZXJhdG9yID0ga3coXCJvcGVyYXRvclwiKSwgYXRvbSA9IHt0eXBlOiBcImF0b21cIiwgc3R5bGU6IFwiYXRvbVwifTtcblxuICAgIHJldHVybiB7XG4gICAgICBcImlmXCI6IGt3KFwiaWZcIiksIFwid2hpbGVcIjogQSwgXCJ3aXRoXCI6IEEsIFwiZWxzZVwiOiBCLCBcImRvXCI6IEIsIFwidHJ5XCI6IEIsIFwiZmluYWxseVwiOiBCLFxuICAgICAgXCJyZXR1cm5cIjogRCwgXCJicmVha1wiOiBELCBcImNvbnRpbnVlXCI6IEQsIFwibmV3XCI6IGt3KFwibmV3XCIpLCBcImRlbGV0ZVwiOiBDLCBcInZvaWRcIjogQywgXCJ0aHJvd1wiOiBDLFxuICAgICAgXCJkZWJ1Z2dlclwiOiBrdyhcImRlYnVnZ2VyXCIpLCBcInZhclwiOiBrdyhcInZhclwiKSwgXCJjb25zdFwiOiBrdyhcInZhclwiKSwgXCJsZXRcIjoga3coXCJ2YXJcIiksXG4gICAgICBcImZ1bmN0aW9uXCI6IGt3KFwiZnVuY3Rpb25cIiksIFwiY2F0Y2hcIjoga3coXCJjYXRjaFwiKSxcbiAgICAgIFwiZm9yXCI6IGt3KFwiZm9yXCIpLCBcInN3aXRjaFwiOiBrdyhcInN3aXRjaFwiKSwgXCJjYXNlXCI6IGt3KFwiY2FzZVwiKSwgXCJkZWZhdWx0XCI6IGt3KFwiZGVmYXVsdFwiKSxcbiAgICAgIFwiaW5cIjogb3BlcmF0b3IsIFwidHlwZW9mXCI6IG9wZXJhdG9yLCBcImluc3RhbmNlb2ZcIjogb3BlcmF0b3IsXG4gICAgICBcInRydWVcIjogYXRvbSwgXCJmYWxzZVwiOiBhdG9tLCBcIm51bGxcIjogYXRvbSwgXCJ1bmRlZmluZWRcIjogYXRvbSwgXCJOYU5cIjogYXRvbSwgXCJJbmZpbml0eVwiOiBhdG9tLFxuICAgICAgXCJ0aGlzXCI6IGt3KFwidGhpc1wiKSwgXCJjbGFzc1wiOiBrdyhcImNsYXNzXCIpLCBcInN1cGVyXCI6IGt3KFwiYXRvbVwiKSxcbiAgICAgIFwieWllbGRcIjogQywgXCJleHBvcnRcIjoga3coXCJleHBvcnRcIiksIFwiaW1wb3J0XCI6IGt3KFwiaW1wb3J0XCIpLCBcImV4dGVuZHNcIjogQyxcbiAgICAgIFwiYXdhaXRcIjogQ1xuICAgIH07XG4gIH0oKTtcblxuICB2YXIgaXNPcGVyYXRvckNoYXIgPSAvWytcXC0qJiU9PD4hP3x+XkBdLztcbiAgdmFyIGlzSnNvbmxkS2V5d29yZCA9IC9eQChjb250ZXh0fGlkfHZhbHVlfGxhbmd1YWdlfHR5cGV8Y29udGFpbmVyfGxpc3R8c2V0fHJldmVyc2V8aW5kZXh8YmFzZXx2b2NhYnxncmFwaClcIi87XG5cbiAgZnVuY3Rpb24gcmVhZFJlZ2V4cChzdHJlYW0pIHtcbiAgICB2YXIgZXNjYXBlZCA9IGZhbHNlLCBuZXh0LCBpblNldCA9IGZhbHNlO1xuICAgIHdoaWxlICgobmV4dCA9IHN0cmVhbS5uZXh0KCkpICE9IG51bGwpIHtcbiAgICAgIGlmICghZXNjYXBlZCkge1xuICAgICAgICBpZiAobmV4dCA9PSBcIi9cIiAmJiAhaW5TZXQpIHJldHVybjtcbiAgICAgICAgaWYgKG5leHQgPT0gXCJbXCIpIGluU2V0ID0gdHJ1ZTtcbiAgICAgICAgZWxzZSBpZiAoaW5TZXQgJiYgbmV4dCA9PSBcIl1cIikgaW5TZXQgPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGVzY2FwZWQgPSAhZXNjYXBlZCAmJiBuZXh0ID09IFwiXFxcXFwiO1xuICAgIH1cbiAgfVxuXG4gIC8vIFVzZWQgYXMgc2NyYXRjaCB2YXJpYWJsZXMgdG8gY29tbXVuaWNhdGUgbXVsdGlwbGUgdmFsdWVzIHdpdGhvdXRcbiAgLy8gY29uc2luZyB1cCB0b25zIG9mIG9iamVjdHMuXG4gIHZhciB0eXBlLCBjb250ZW50O1xuICBmdW5jdGlvbiByZXQodHAsIHN0eWxlLCBjb250KSB7XG4gICAgdHlwZSA9IHRwOyBjb250ZW50ID0gY29udDtcbiAgICByZXR1cm4gc3R5bGU7XG4gIH1cbiAgZnVuY3Rpb24gdG9rZW5CYXNlKHN0cmVhbSwgc3RhdGUpIHtcbiAgICB2YXIgY2ggPSBzdHJlYW0ubmV4dCgpO1xuICAgIGlmIChjaCA9PSAnXCInIHx8IGNoID09IFwiJ1wiKSB7XG4gICAgICBzdGF0ZS50b2tlbml6ZSA9IHRva2VuU3RyaW5nKGNoKTtcbiAgICAgIHJldHVybiBzdGF0ZS50b2tlbml6ZShzdHJlYW0sIHN0YXRlKTtcbiAgICB9IGVsc2UgaWYgKGNoID09IFwiLlwiICYmIHN0cmVhbS5tYXRjaCgvXlxcZFtcXGRfXSooPzpbZUVdWytcXC1dP1tcXGRfXSspPy8pKSB7XG4gICAgICByZXR1cm4gcmV0KFwibnVtYmVyXCIsIFwibnVtYmVyXCIpO1xuICAgIH0gZWxzZSBpZiAoY2ggPT0gXCIuXCIgJiYgc3RyZWFtLm1hdGNoKFwiLi5cIikpIHtcbiAgICAgIHJldHVybiByZXQoXCJzcHJlYWRcIiwgXCJtZXRhXCIpO1xuICAgIH0gZWxzZSBpZiAoL1tcXFtcXF17fVxcKFxcKSw7XFw6XFwuXS8udGVzdChjaCkpIHtcbiAgICAgIHJldHVybiByZXQoY2gpO1xuICAgIH0gZWxzZSBpZiAoY2ggPT0gXCI9XCIgJiYgc3RyZWFtLmVhdChcIj5cIikpIHtcbiAgICAgIHJldHVybiByZXQoXCI9PlwiLCBcIm9wZXJhdG9yXCIpO1xuICAgIH0gZWxzZSBpZiAoY2ggPT0gXCIwXCIgJiYgc3RyZWFtLm1hdGNoKC9eKD86eFtcXGRBLUZhLWZfXSt8b1swLTdfXSt8YlswMV9dKyluPy8pKSB7XG4gICAgICByZXR1cm4gcmV0KFwibnVtYmVyXCIsIFwibnVtYmVyXCIpO1xuICAgIH0gZWxzZSBpZiAoL1xcZC8udGVzdChjaCkpIHtcbiAgICAgIHN0cmVhbS5tYXRjaCgvXltcXGRfXSooPzpufCg/OlxcLltcXGRfXSopPyg/OltlRV1bK1xcLV0/W1xcZF9dKyk/KT8vKTtcbiAgICAgIHJldHVybiByZXQoXCJudW1iZXJcIiwgXCJudW1iZXJcIik7XG4gICAgfSBlbHNlIGlmIChjaCA9PSBcIi9cIikge1xuICAgICAgaWYgKHN0cmVhbS5lYXQoXCIqXCIpKSB7XG4gICAgICAgIHN0YXRlLnRva2VuaXplID0gdG9rZW5Db21tZW50O1xuICAgICAgICByZXR1cm4gdG9rZW5Db21tZW50KHN0cmVhbSwgc3RhdGUpO1xuICAgICAgfSBlbHNlIGlmIChzdHJlYW0uZWF0KFwiL1wiKSkge1xuICAgICAgICBzdHJlYW0uc2tpcFRvRW5kKCk7XG4gICAgICAgIHJldHVybiByZXQoXCJjb21tZW50XCIsIFwiY29tbWVudFwiKTtcbiAgICAgIH0gZWxzZSBpZiAoZXhwcmVzc2lvbkFsbG93ZWQoc3RyZWFtLCBzdGF0ZSwgMSkpIHtcbiAgICAgICAgcmVhZFJlZ2V4cChzdHJlYW0pO1xuICAgICAgICBzdHJlYW0ubWF0Y2goL15cXGIoKFtnaW15dXNdKSg/IVtnaW15dXNdKlxcMikpK1xcYi8pO1xuICAgICAgICByZXR1cm4gcmV0KFwicmVnZXhwXCIsIFwic3RyaW5nLTJcIik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdHJlYW0uZWF0KFwiPVwiKTtcbiAgICAgICAgcmV0dXJuIHJldChcIm9wZXJhdG9yXCIsIFwib3BlcmF0b3JcIiwgc3RyZWFtLmN1cnJlbnQoKSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChjaCA9PSBcImBcIikge1xuICAgICAgc3RhdGUudG9rZW5pemUgPSB0b2tlblF1YXNpO1xuICAgICAgcmV0dXJuIHRva2VuUXVhc2koc3RyZWFtLCBzdGF0ZSk7XG4gICAgfSBlbHNlIGlmIChjaCA9PSBcIiNcIiAmJiBzdHJlYW0ucGVlaygpID09IFwiIVwiKSB7XG4gICAgICBzdHJlYW0uc2tpcFRvRW5kKCk7XG4gICAgICByZXR1cm4gcmV0KFwibWV0YVwiLCBcIm1ldGFcIik7XG4gICAgfSBlbHNlIGlmIChjaCA9PSBcIiNcIiAmJiBzdHJlYW0uZWF0V2hpbGUod29yZFJFKSkge1xuICAgICAgcmV0dXJuIHJldChcInZhcmlhYmxlXCIsIFwicHJvcGVydHlcIilcbiAgICB9IGVsc2UgaWYgKGNoID09IFwiPFwiICYmIHN0cmVhbS5tYXRjaChcIiEtLVwiKSB8fFxuICAgICAgICAgICAgICAgKGNoID09IFwiLVwiICYmIHN0cmVhbS5tYXRjaChcIi0+XCIpICYmICEvXFxTLy50ZXN0KHN0cmVhbS5zdHJpbmcuc2xpY2UoMCwgc3RyZWFtLnN0YXJ0KSkpKSB7XG4gICAgICBzdHJlYW0uc2tpcFRvRW5kKClcbiAgICAgIHJldHVybiByZXQoXCJjb21tZW50XCIsIFwiY29tbWVudFwiKVxuICAgIH0gZWxzZSBpZiAoaXNPcGVyYXRvckNoYXIudGVzdChjaCkpIHtcbiAgICAgIGlmIChjaCAhPSBcIj5cIiB8fCAhc3RhdGUubGV4aWNhbCB8fCBzdGF0ZS5sZXhpY2FsLnR5cGUgIT0gXCI+XCIpIHtcbiAgICAgICAgaWYgKHN0cmVhbS5lYXQoXCI9XCIpKSB7XG4gICAgICAgICAgaWYgKGNoID09IFwiIVwiIHx8IGNoID09IFwiPVwiKSBzdHJlYW0uZWF0KFwiPVwiKVxuICAgICAgICB9IGVsc2UgaWYgKC9bPD4qK1xcLXwmP10vLnRlc3QoY2gpKSB7XG4gICAgICAgICAgc3RyZWFtLmVhdChjaClcbiAgICAgICAgICBpZiAoY2ggPT0gXCI+XCIpIHN0cmVhbS5lYXQoY2gpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChjaCA9PSBcIj9cIiAmJiBzdHJlYW0uZWF0KFwiLlwiKSkgcmV0dXJuIHJldChcIi5cIilcbiAgICAgIHJldHVybiByZXQoXCJvcGVyYXRvclwiLCBcIm9wZXJhdG9yXCIsIHN0cmVhbS5jdXJyZW50KCkpO1xuICAgIH0gZWxzZSBpZiAod29yZFJFLnRlc3QoY2gpKSB7XG4gICAgICBzdHJlYW0uZWF0V2hpbGUod29yZFJFKTtcbiAgICAgIHZhciB3b3JkID0gc3RyZWFtLmN1cnJlbnQoKVxuICAgICAgaWYgKHN0YXRlLmxhc3RUeXBlICE9IFwiLlwiKSB7XG4gICAgICAgIGlmIChrZXl3b3Jkcy5wcm9wZXJ0eUlzRW51bWVyYWJsZSh3b3JkKSkge1xuICAgICAgICAgIHZhciBrdyA9IGtleXdvcmRzW3dvcmRdXG4gICAgICAgICAgcmV0dXJuIHJldChrdy50eXBlLCBrdy5zdHlsZSwgd29yZClcbiAgICAgICAgfVxuICAgICAgICBpZiAod29yZCA9PSBcImFzeW5jXCIgJiYgc3RyZWFtLm1hdGNoKC9eKFxcc3xcXC9cXCooW14qXXxcXCooPyFcXC8pKSo/XFwqXFwvKSpbXFxbXFwoXFx3XS8sIGZhbHNlKSlcbiAgICAgICAgICByZXR1cm4gcmV0KFwiYXN5bmNcIiwgXCJrZXl3b3JkXCIsIHdvcmQpXG4gICAgICB9XG4gICAgICByZXR1cm4gcmV0KFwidmFyaWFibGVcIiwgXCJ2YXJpYWJsZVwiLCB3b3JkKVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHRva2VuU3RyaW5nKHF1b3RlKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgIHZhciBlc2NhcGVkID0gZmFsc2UsIG5leHQ7XG4gICAgICBpZiAoanNvbmxkTW9kZSAmJiBzdHJlYW0ucGVlaygpID09IFwiQFwiICYmIHN0cmVhbS5tYXRjaChpc0pzb25sZEtleXdvcmQpKXtcbiAgICAgICAgc3RhdGUudG9rZW5pemUgPSB0b2tlbkJhc2U7XG4gICAgICAgIHJldHVybiByZXQoXCJqc29ubGQta2V5d29yZFwiLCBcIm1ldGFcIik7XG4gICAgICB9XG4gICAgICB3aGlsZSAoKG5leHQgPSBzdHJlYW0ubmV4dCgpKSAhPSBudWxsKSB7XG4gICAgICAgIGlmIChuZXh0ID09IHF1b3RlICYmICFlc2NhcGVkKSBicmVhaztcbiAgICAgICAgZXNjYXBlZCA9ICFlc2NhcGVkICYmIG5leHQgPT0gXCJcXFxcXCI7XG4gICAgICB9XG4gICAgICBpZiAoIWVzY2FwZWQpIHN0YXRlLnRva2VuaXplID0gdG9rZW5CYXNlO1xuICAgICAgcmV0dXJuIHJldChcInN0cmluZ1wiLCBcInN0cmluZ1wiKTtcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gdG9rZW5Db21tZW50KHN0cmVhbSwgc3RhdGUpIHtcbiAgICB2YXIgbWF5YmVFbmQgPSBmYWxzZSwgY2g7XG4gICAgd2hpbGUgKGNoID0gc3RyZWFtLm5leHQoKSkge1xuICAgICAgaWYgKGNoID09IFwiL1wiICYmIG1heWJlRW5kKSB7XG4gICAgICAgIHN0YXRlLnRva2VuaXplID0gdG9rZW5CYXNlO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIG1heWJlRW5kID0gKGNoID09IFwiKlwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHJldChcImNvbW1lbnRcIiwgXCJjb21tZW50XCIpO1xuICB9XG5cbiAgZnVuY3Rpb24gdG9rZW5RdWFzaShzdHJlYW0sIHN0YXRlKSB7XG4gICAgdmFyIGVzY2FwZWQgPSBmYWxzZSwgbmV4dDtcbiAgICB3aGlsZSAoKG5leHQgPSBzdHJlYW0ubmV4dCgpKSAhPSBudWxsKSB7XG4gICAgICBpZiAoIWVzY2FwZWQgJiYgKG5leHQgPT0gXCJgXCIgfHwgbmV4dCA9PSBcIiRcIiAmJiBzdHJlYW0uZWF0KFwie1wiKSkpIHtcbiAgICAgICAgc3RhdGUudG9rZW5pemUgPSB0b2tlbkJhc2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgZXNjYXBlZCA9ICFlc2NhcGVkICYmIG5leHQgPT0gXCJcXFxcXCI7XG4gICAgfVxuICAgIHJldHVybiByZXQoXCJxdWFzaVwiLCBcInN0cmluZy0yXCIsIHN0cmVhbS5jdXJyZW50KCkpO1xuICB9XG5cbiAgdmFyIGJyYWNrZXRzID0gXCIoW3t9XSlcIjtcbiAgLy8gVGhpcyBpcyBhIGNydWRlIGxvb2thaGVhZCB0cmljayB0byB0cnkgYW5kIG5vdGljZSB0aGF0IHdlJ3JlXG4gIC8vIHBhcnNpbmcgdGhlIGFyZ3VtZW50IHBhdHRlcm5zIGZvciBhIGZhdC1hcnJvdyBmdW5jdGlvbiBiZWZvcmUgd2VcbiAgLy8gYWN0dWFsbHkgaGl0IHRoZSBhcnJvdyB0b2tlbi4gSXQgb25seSB3b3JrcyBpZiB0aGUgYXJyb3cgaXMgb25cbiAgLy8gdGhlIHNhbWUgbGluZSBhcyB0aGUgYXJndW1lbnRzIGFuZCB0aGVyZSdzIG5vIHN0cmFuZ2Ugbm9pc2VcbiAgLy8gKGNvbW1lbnRzKSBpbiBiZXR3ZWVuLiBGYWxsYmFjayBpcyB0byBvbmx5IG5vdGljZSB3aGVuIHdlIGhpdCB0aGVcbiAgLy8gYXJyb3csIGFuZCBub3QgZGVjbGFyZSB0aGUgYXJndW1lbnRzIGFzIGxvY2FscyBmb3IgdGhlIGFycm93XG4gIC8vIGJvZHkuXG4gIGZ1bmN0aW9uIGZpbmRGYXRBcnJvdyhzdHJlYW0sIHN0YXRlKSB7XG4gICAgaWYgKHN0YXRlLmZhdEFycm93QXQpIHN0YXRlLmZhdEFycm93QXQgPSBudWxsO1xuICAgIHZhciBhcnJvdyA9IHN0cmVhbS5zdHJpbmcuaW5kZXhPZihcIj0+XCIsIHN0cmVhbS5zdGFydCk7XG4gICAgaWYgKGFycm93IDwgMCkgcmV0dXJuO1xuXG4gICAgaWYgKGlzVFMpIHsgLy8gVHJ5IHRvIHNraXAgVHlwZVNjcmlwdCByZXR1cm4gdHlwZSBkZWNsYXJhdGlvbnMgYWZ0ZXIgdGhlIGFyZ3VtZW50c1xuICAgICAgdmFyIG0gPSAvOlxccyooPzpcXHcrKD86PFtePl0qPnxcXFtcXF0pP3xcXHtbXn1dKlxcfSlcXHMqJC8uZXhlYyhzdHJlYW0uc3RyaW5nLnNsaWNlKHN0cmVhbS5zdGFydCwgYXJyb3cpKVxuICAgICAgaWYgKG0pIGFycm93ID0gbS5pbmRleFxuICAgIH1cblxuICAgIHZhciBkZXB0aCA9IDAsIHNhd1NvbWV0aGluZyA9IGZhbHNlO1xuICAgIGZvciAodmFyIHBvcyA9IGFycm93IC0gMTsgcG9zID49IDA7IC0tcG9zKSB7XG4gICAgICB2YXIgY2ggPSBzdHJlYW0uc3RyaW5nLmNoYXJBdChwb3MpO1xuICAgICAgdmFyIGJyYWNrZXQgPSBicmFja2V0cy5pbmRleE9mKGNoKTtcbiAgICAgIGlmIChicmFja2V0ID49IDAgJiYgYnJhY2tldCA8IDMpIHtcbiAgICAgICAgaWYgKCFkZXB0aCkgeyArK3BvczsgYnJlYWs7IH1cbiAgICAgICAgaWYgKC0tZGVwdGggPT0gMCkgeyBpZiAoY2ggPT0gXCIoXCIpIHNhd1NvbWV0aGluZyA9IHRydWU7IGJyZWFrOyB9XG4gICAgICB9IGVsc2UgaWYgKGJyYWNrZXQgPj0gMyAmJiBicmFja2V0IDwgNikge1xuICAgICAgICArK2RlcHRoO1xuICAgICAgfSBlbHNlIGlmICh3b3JkUkUudGVzdChjaCkpIHtcbiAgICAgICAgc2F3U29tZXRoaW5nID0gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoL1tcIidcXC9gXS8udGVzdChjaCkpIHtcbiAgICAgICAgZm9yICg7OyAtLXBvcykge1xuICAgICAgICAgIGlmIChwb3MgPT0gMCkgcmV0dXJuXG4gICAgICAgICAgdmFyIG5leHQgPSBzdHJlYW0uc3RyaW5nLmNoYXJBdChwb3MgLSAxKVxuICAgICAgICAgIGlmIChuZXh0ID09IGNoICYmIHN0cmVhbS5zdHJpbmcuY2hhckF0KHBvcyAtIDIpICE9IFwiXFxcXFwiKSB7IHBvcy0tOyBicmVhayB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoc2F3U29tZXRoaW5nICYmICFkZXB0aCkge1xuICAgICAgICArK3BvcztcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChzYXdTb21ldGhpbmcgJiYgIWRlcHRoKSBzdGF0ZS5mYXRBcnJvd0F0ID0gcG9zO1xuICB9XG5cbiAgLy8gUGFyc2VyXG5cbiAgdmFyIGF0b21pY1R5cGVzID0ge1wiYXRvbVwiOiB0cnVlLCBcIm51bWJlclwiOiB0cnVlLCBcInZhcmlhYmxlXCI6IHRydWUsIFwic3RyaW5nXCI6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICBcInJlZ2V4cFwiOiB0cnVlLCBcInRoaXNcIjogdHJ1ZSwgXCJpbXBvcnRcIjogdHJ1ZSwgXCJqc29ubGQta2V5d29yZFwiOiB0cnVlfTtcblxuICBmdW5jdGlvbiBKU0xleGljYWwoaW5kZW50ZWQsIGNvbHVtbiwgdHlwZSwgYWxpZ24sIHByZXYsIGluZm8pIHtcbiAgICB0aGlzLmluZGVudGVkID0gaW5kZW50ZWQ7XG4gICAgdGhpcy5jb2x1bW4gPSBjb2x1bW47XG4gICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB0aGlzLnByZXYgPSBwcmV2O1xuICAgIHRoaXMuaW5mbyA9IGluZm87XG4gICAgaWYgKGFsaWduICE9IG51bGwpIHRoaXMuYWxpZ24gPSBhbGlnbjtcbiAgfVxuXG4gIGZ1bmN0aW9uIGluU2NvcGUoc3RhdGUsIHZhcm5hbWUpIHtcbiAgICBpZiAoIXRyYWNrU2NvcGUpIHJldHVybiBmYWxzZVxuICAgIGZvciAodmFyIHYgPSBzdGF0ZS5sb2NhbFZhcnM7IHY7IHYgPSB2Lm5leHQpXG4gICAgICBpZiAodi5uYW1lID09IHZhcm5hbWUpIHJldHVybiB0cnVlO1xuICAgIGZvciAodmFyIGN4ID0gc3RhdGUuY29udGV4dDsgY3g7IGN4ID0gY3gucHJldikge1xuICAgICAgZm9yICh2YXIgdiA9IGN4LnZhcnM7IHY7IHYgPSB2Lm5leHQpXG4gICAgICAgIGlmICh2Lm5hbWUgPT0gdmFybmFtZSkgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VKUyhzdGF0ZSwgc3R5bGUsIHR5cGUsIGNvbnRlbnQsIHN0cmVhbSkge1xuICAgIHZhciBjYyA9IHN0YXRlLmNjO1xuICAgIC8vIENvbW11bmljYXRlIG91ciBjb250ZXh0IHRvIHRoZSBjb21iaW5hdG9ycy5cbiAgICAvLyAoTGVzcyB3YXN0ZWZ1bCB0aGFuIGNvbnNpbmcgdXAgYSBodW5kcmVkIGNsb3N1cmVzIG9uIGV2ZXJ5IGNhbGwuKVxuICAgIGN4LnN0YXRlID0gc3RhdGU7IGN4LnN0cmVhbSA9IHN0cmVhbTsgY3gubWFya2VkID0gbnVsbCwgY3guY2MgPSBjYzsgY3guc3R5bGUgPSBzdHlsZTtcblxuICAgIGlmICghc3RhdGUubGV4aWNhbC5oYXNPd25Qcm9wZXJ0eShcImFsaWduXCIpKVxuICAgICAgc3RhdGUubGV4aWNhbC5hbGlnbiA9IHRydWU7XG5cbiAgICB3aGlsZSh0cnVlKSB7XG4gICAgICB2YXIgY29tYmluYXRvciA9IGNjLmxlbmd0aCA/IGNjLnBvcCgpIDoganNvbk1vZGUgPyBleHByZXNzaW9uIDogc3RhdGVtZW50O1xuICAgICAgaWYgKGNvbWJpbmF0b3IodHlwZSwgY29udGVudCkpIHtcbiAgICAgICAgd2hpbGUoY2MubGVuZ3RoICYmIGNjW2NjLmxlbmd0aCAtIDFdLmxleClcbiAgICAgICAgICBjYy5wb3AoKSgpO1xuICAgICAgICBpZiAoY3gubWFya2VkKSByZXR1cm4gY3gubWFya2VkO1xuICAgICAgICBpZiAodHlwZSA9PSBcInZhcmlhYmxlXCIgJiYgaW5TY29wZShzdGF0ZSwgY29udGVudCkpIHJldHVybiBcInZhcmlhYmxlLTJcIjtcbiAgICAgICAgcmV0dXJuIHN0eWxlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIENvbWJpbmF0b3IgdXRpbHNcblxuICB2YXIgY3ggPSB7c3RhdGU6IG51bGwsIGNvbHVtbjogbnVsbCwgbWFya2VkOiBudWxsLCBjYzogbnVsbH07XG4gIGZ1bmN0aW9uIHBhc3MoKSB7XG4gICAgZm9yICh2YXIgaSA9IGFyZ3VtZW50cy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgY3guY2MucHVzaChhcmd1bWVudHNbaV0pO1xuICB9XG4gIGZ1bmN0aW9uIGNvbnQoKSB7XG4gICAgcGFzcy5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIGZ1bmN0aW9uIGluTGlzdChuYW1lLCBsaXN0KSB7XG4gICAgZm9yICh2YXIgdiA9IGxpc3Q7IHY7IHYgPSB2Lm5leHQpIGlmICh2Lm5hbWUgPT0gbmFtZSkgcmV0dXJuIHRydWVcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgZnVuY3Rpb24gcmVnaXN0ZXIodmFybmFtZSkge1xuICAgIHZhciBzdGF0ZSA9IGN4LnN0YXRlO1xuICAgIGN4Lm1hcmtlZCA9IFwiZGVmXCI7XG4gICAgaWYgKCF0cmFja1Njb3BlKSByZXR1cm5cbiAgICBpZiAoc3RhdGUuY29udGV4dCkge1xuICAgICAgaWYgKHN0YXRlLmxleGljYWwuaW5mbyA9PSBcInZhclwiICYmIHN0YXRlLmNvbnRleHQgJiYgc3RhdGUuY29udGV4dC5ibG9jaykge1xuICAgICAgICAvLyBGSVhNRSBmdW5jdGlvbiBkZWNscyBhcmUgYWxzbyBub3QgYmxvY2sgc2NvcGVkXG4gICAgICAgIHZhciBuZXdDb250ZXh0ID0gcmVnaXN0ZXJWYXJTY29wZWQodmFybmFtZSwgc3RhdGUuY29udGV4dClcbiAgICAgICAgaWYgKG5ld0NvbnRleHQgIT0gbnVsbCkge1xuICAgICAgICAgIHN0YXRlLmNvbnRleHQgPSBuZXdDb250ZXh0XG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoIWluTGlzdCh2YXJuYW1lLCBzdGF0ZS5sb2NhbFZhcnMpKSB7XG4gICAgICAgIHN0YXRlLmxvY2FsVmFycyA9IG5ldyBWYXIodmFybmFtZSwgc3RhdGUubG9jYWxWYXJzKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRmFsbCB0aHJvdWdoIG1lYW5zIHRoaXMgaXMgZ2xvYmFsXG4gICAgaWYgKHBhcnNlckNvbmZpZy5nbG9iYWxWYXJzICYmICFpbkxpc3QodmFybmFtZSwgc3RhdGUuZ2xvYmFsVmFycykpXG4gICAgICBzdGF0ZS5nbG9iYWxWYXJzID0gbmV3IFZhcih2YXJuYW1lLCBzdGF0ZS5nbG9iYWxWYXJzKVxuICB9XG4gIGZ1bmN0aW9uIHJlZ2lzdGVyVmFyU2NvcGVkKHZhcm5hbWUsIGNvbnRleHQpIHtcbiAgICBpZiAoIWNvbnRleHQpIHtcbiAgICAgIHJldHVybiBudWxsXG4gICAgfSBlbHNlIGlmIChjb250ZXh0LmJsb2NrKSB7XG4gICAgICB2YXIgaW5uZXIgPSByZWdpc3RlclZhclNjb3BlZCh2YXJuYW1lLCBjb250ZXh0LnByZXYpXG4gICAgICBpZiAoIWlubmVyKSByZXR1cm4gbnVsbFxuICAgICAgaWYgKGlubmVyID09IGNvbnRleHQucHJldikgcmV0dXJuIGNvbnRleHRcbiAgICAgIHJldHVybiBuZXcgQ29udGV4dChpbm5lciwgY29udGV4dC52YXJzLCB0cnVlKVxuICAgIH0gZWxzZSBpZiAoaW5MaXN0KHZhcm5hbWUsIGNvbnRleHQudmFycykpIHtcbiAgICAgIHJldHVybiBjb250ZXh0XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBuZXcgQ29udGV4dChjb250ZXh0LnByZXYsIG5ldyBWYXIodmFybmFtZSwgY29udGV4dC52YXJzKSwgZmFsc2UpXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaXNNb2RpZmllcihuYW1lKSB7XG4gICAgcmV0dXJuIG5hbWUgPT0gXCJwdWJsaWNcIiB8fCBuYW1lID09IFwicHJpdmF0ZVwiIHx8IG5hbWUgPT0gXCJwcm90ZWN0ZWRcIiB8fCBuYW1lID09IFwiYWJzdHJhY3RcIiB8fCBuYW1lID09IFwicmVhZG9ubHlcIlxuICB9XG5cbiAgLy8gQ29tYmluYXRvcnNcblxuICBmdW5jdGlvbiBDb250ZXh0KHByZXYsIHZhcnMsIGJsb2NrKSB7IHRoaXMucHJldiA9IHByZXY7IHRoaXMudmFycyA9IHZhcnM7IHRoaXMuYmxvY2sgPSBibG9jayB9XG4gIGZ1bmN0aW9uIFZhcihuYW1lLCBuZXh0KSB7IHRoaXMubmFtZSA9IG5hbWU7IHRoaXMubmV4dCA9IG5leHQgfVxuXG4gIHZhciBkZWZhdWx0VmFycyA9IG5ldyBWYXIoXCJ0aGlzXCIsIG5ldyBWYXIoXCJhcmd1bWVudHNcIiwgbnVsbCkpXG4gIGZ1bmN0aW9uIHB1c2hjb250ZXh0KCkge1xuICAgIGN4LnN0YXRlLmNvbnRleHQgPSBuZXcgQ29udGV4dChjeC5zdGF0ZS5jb250ZXh0LCBjeC5zdGF0ZS5sb2NhbFZhcnMsIGZhbHNlKVxuICAgIGN4LnN0YXRlLmxvY2FsVmFycyA9IGRlZmF1bHRWYXJzXG4gIH1cbiAgZnVuY3Rpb24gcHVzaGJsb2NrY29udGV4dCgpIHtcbiAgICBjeC5zdGF0ZS5jb250ZXh0ID0gbmV3IENvbnRleHQoY3guc3RhdGUuY29udGV4dCwgY3guc3RhdGUubG9jYWxWYXJzLCB0cnVlKVxuICAgIGN4LnN0YXRlLmxvY2FsVmFycyA9IG51bGxcbiAgfVxuICBwdXNoY29udGV4dC5sZXggPSBwdXNoYmxvY2tjb250ZXh0LmxleCA9IHRydWVcbiAgZnVuY3Rpb24gcG9wY29udGV4dCgpIHtcbiAgICBjeC5zdGF0ZS5sb2NhbFZhcnMgPSBjeC5zdGF0ZS5jb250ZXh0LnZhcnNcbiAgICBjeC5zdGF0ZS5jb250ZXh0ID0gY3guc3RhdGUuY29udGV4dC5wcmV2XG4gIH1cbiAgcG9wY29udGV4dC5sZXggPSB0cnVlXG4gIGZ1bmN0aW9uIHB1c2hsZXgodHlwZSwgaW5mbykge1xuICAgIHZhciByZXN1bHQgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBzdGF0ZSA9IGN4LnN0YXRlLCBpbmRlbnQgPSBzdGF0ZS5pbmRlbnRlZDtcbiAgICAgIGlmIChzdGF0ZS5sZXhpY2FsLnR5cGUgPT0gXCJzdGF0XCIpIGluZGVudCA9IHN0YXRlLmxleGljYWwuaW5kZW50ZWQ7XG4gICAgICBlbHNlIGZvciAodmFyIG91dGVyID0gc3RhdGUubGV4aWNhbDsgb3V0ZXIgJiYgb3V0ZXIudHlwZSA9PSBcIilcIiAmJiBvdXRlci5hbGlnbjsgb3V0ZXIgPSBvdXRlci5wcmV2KVxuICAgICAgICBpbmRlbnQgPSBvdXRlci5pbmRlbnRlZDtcbiAgICAgIHN0YXRlLmxleGljYWwgPSBuZXcgSlNMZXhpY2FsKGluZGVudCwgY3guc3RyZWFtLmNvbHVtbigpLCB0eXBlLCBudWxsLCBzdGF0ZS5sZXhpY2FsLCBpbmZvKTtcbiAgICB9O1xuICAgIHJlc3VsdC5sZXggPSB0cnVlO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgZnVuY3Rpb24gcG9wbGV4KCkge1xuICAgIHZhciBzdGF0ZSA9IGN4LnN0YXRlO1xuICAgIGlmIChzdGF0ZS5sZXhpY2FsLnByZXYpIHtcbiAgICAgIGlmIChzdGF0ZS5sZXhpY2FsLnR5cGUgPT0gXCIpXCIpXG4gICAgICAgIHN0YXRlLmluZGVudGVkID0gc3RhdGUubGV4aWNhbC5pbmRlbnRlZDtcbiAgICAgIHN0YXRlLmxleGljYWwgPSBzdGF0ZS5sZXhpY2FsLnByZXY7XG4gICAgfVxuICB9XG4gIHBvcGxleC5sZXggPSB0cnVlO1xuXG4gIGZ1bmN0aW9uIGV4cGVjdCh3YW50ZWQpIHtcbiAgICBmdW5jdGlvbiBleHAodHlwZSkge1xuICAgICAgaWYgKHR5cGUgPT0gd2FudGVkKSByZXR1cm4gY29udCgpO1xuICAgICAgZWxzZSBpZiAod2FudGVkID09IFwiO1wiIHx8IHR5cGUgPT0gXCJ9XCIgfHwgdHlwZSA9PSBcIilcIiB8fCB0eXBlID09IFwiXVwiKSByZXR1cm4gcGFzcygpO1xuICAgICAgZWxzZSByZXR1cm4gY29udChleHApO1xuICAgIH07XG4gICAgcmV0dXJuIGV4cDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHN0YXRlbWVudCh0eXBlLCB2YWx1ZSkge1xuICAgIGlmICh0eXBlID09IFwidmFyXCIpIHJldHVybiBjb250KHB1c2hsZXgoXCJ2YXJkZWZcIiwgdmFsdWUpLCB2YXJkZWYsIGV4cGVjdChcIjtcIiksIHBvcGxleCk7XG4gICAgaWYgKHR5cGUgPT0gXCJrZXl3b3JkIGFcIikgcmV0dXJuIGNvbnQocHVzaGxleChcImZvcm1cIiksIHBhcmVuRXhwciwgc3RhdGVtZW50LCBwb3BsZXgpO1xuICAgIGlmICh0eXBlID09IFwia2V5d29yZCBiXCIpIHJldHVybiBjb250KHB1c2hsZXgoXCJmb3JtXCIpLCBzdGF0ZW1lbnQsIHBvcGxleCk7XG4gICAgaWYgKHR5cGUgPT0gXCJrZXl3b3JkIGRcIikgcmV0dXJuIGN4LnN0cmVhbS5tYXRjaCgvXlxccyokLywgZmFsc2UpID8gY29udCgpIDogY29udChwdXNobGV4KFwic3RhdFwiKSwgbWF5YmVleHByZXNzaW9uLCBleHBlY3QoXCI7XCIpLCBwb3BsZXgpO1xuICAgIGlmICh0eXBlID09IFwiZGVidWdnZXJcIikgcmV0dXJuIGNvbnQoZXhwZWN0KFwiO1wiKSk7XG4gICAgaWYgKHR5cGUgPT0gXCJ7XCIpIHJldHVybiBjb250KHB1c2hsZXgoXCJ9XCIpLCBwdXNoYmxvY2tjb250ZXh0LCBibG9jaywgcG9wbGV4LCBwb3Bjb250ZXh0KTtcbiAgICBpZiAodHlwZSA9PSBcIjtcIikgcmV0dXJuIGNvbnQoKTtcbiAgICBpZiAodHlwZSA9PSBcImlmXCIpIHtcbiAgICAgIGlmIChjeC5zdGF0ZS5sZXhpY2FsLmluZm8gPT0gXCJlbHNlXCIgJiYgY3guc3RhdGUuY2NbY3guc3RhdGUuY2MubGVuZ3RoIC0gMV0gPT0gcG9wbGV4KVxuICAgICAgICBjeC5zdGF0ZS5jYy5wb3AoKSgpO1xuICAgICAgcmV0dXJuIGNvbnQocHVzaGxleChcImZvcm1cIiksIHBhcmVuRXhwciwgc3RhdGVtZW50LCBwb3BsZXgsIG1heWJlZWxzZSk7XG4gICAgfVxuICAgIGlmICh0eXBlID09IFwiZnVuY3Rpb25cIikgcmV0dXJuIGNvbnQoZnVuY3Rpb25kZWYpO1xuICAgIGlmICh0eXBlID09IFwiZm9yXCIpIHJldHVybiBjb250KHB1c2hsZXgoXCJmb3JtXCIpLCBwdXNoYmxvY2tjb250ZXh0LCBmb3JzcGVjLCBzdGF0ZW1lbnQsIHBvcGNvbnRleHQsIHBvcGxleCk7XG4gICAgaWYgKHR5cGUgPT0gXCJjbGFzc1wiIHx8IChpc1RTICYmIHZhbHVlID09IFwiaW50ZXJmYWNlXCIpKSB7XG4gICAgICBjeC5tYXJrZWQgPSBcImtleXdvcmRcIlxuICAgICAgcmV0dXJuIGNvbnQocHVzaGxleChcImZvcm1cIiwgdHlwZSA9PSBcImNsYXNzXCIgPyB0eXBlIDogdmFsdWUpLCBjbGFzc05hbWUsIHBvcGxleClcbiAgICB9XG4gICAgaWYgKHR5cGUgPT0gXCJ2YXJpYWJsZVwiKSB7XG4gICAgICBpZiAoaXNUUyAmJiB2YWx1ZSA9PSBcImRlY2xhcmVcIikge1xuICAgICAgICBjeC5tYXJrZWQgPSBcImtleXdvcmRcIlxuICAgICAgICByZXR1cm4gY29udChzdGF0ZW1lbnQpXG4gICAgICB9IGVsc2UgaWYgKGlzVFMgJiYgKHZhbHVlID09IFwibW9kdWxlXCIgfHwgdmFsdWUgPT0gXCJlbnVtXCIgfHwgdmFsdWUgPT0gXCJ0eXBlXCIpICYmIGN4LnN0cmVhbS5tYXRjaCgvXlxccypcXHcvLCBmYWxzZSkpIHtcbiAgICAgICAgY3gubWFya2VkID0gXCJrZXl3b3JkXCJcbiAgICAgICAgaWYgKHZhbHVlID09IFwiZW51bVwiKSByZXR1cm4gY29udChlbnVtZGVmKTtcbiAgICAgICAgZWxzZSBpZiAodmFsdWUgPT0gXCJ0eXBlXCIpIHJldHVybiBjb250KHR5cGVuYW1lLCBleHBlY3QoXCJvcGVyYXRvclwiKSwgdHlwZWV4cHIsIGV4cGVjdChcIjtcIikpO1xuICAgICAgICBlbHNlIHJldHVybiBjb250KHB1c2hsZXgoXCJmb3JtXCIpLCBwYXR0ZXJuLCBleHBlY3QoXCJ7XCIpLCBwdXNobGV4KFwifVwiKSwgYmxvY2ssIHBvcGxleCwgcG9wbGV4KVxuICAgICAgfSBlbHNlIGlmIChpc1RTICYmIHZhbHVlID09IFwibmFtZXNwYWNlXCIpIHtcbiAgICAgICAgY3gubWFya2VkID0gXCJrZXl3b3JkXCJcbiAgICAgICAgcmV0dXJuIGNvbnQocHVzaGxleChcImZvcm1cIiksIGV4cHJlc3Npb24sIHN0YXRlbWVudCwgcG9wbGV4KVxuICAgICAgfSBlbHNlIGlmIChpc1RTICYmIHZhbHVlID09IFwiYWJzdHJhY3RcIikge1xuICAgICAgICBjeC5tYXJrZWQgPSBcImtleXdvcmRcIlxuICAgICAgICByZXR1cm4gY29udChzdGF0ZW1lbnQpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gY29udChwdXNobGV4KFwic3RhdFwiKSwgbWF5YmVsYWJlbCk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICh0eXBlID09IFwic3dpdGNoXCIpIHJldHVybiBjb250KHB1c2hsZXgoXCJmb3JtXCIpLCBwYXJlbkV4cHIsIGV4cGVjdChcIntcIiksIHB1c2hsZXgoXCJ9XCIsIFwic3dpdGNoXCIpLCBwdXNoYmxvY2tjb250ZXh0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBibG9jaywgcG9wbGV4LCBwb3BsZXgsIHBvcGNvbnRleHQpO1xuICAgIGlmICh0eXBlID09IFwiY2FzZVwiKSByZXR1cm4gY29udChleHByZXNzaW9uLCBleHBlY3QoXCI6XCIpKTtcbiAgICBpZiAodHlwZSA9PSBcImRlZmF1bHRcIikgcmV0dXJuIGNvbnQoZXhwZWN0KFwiOlwiKSk7XG4gICAgaWYgKHR5cGUgPT0gXCJjYXRjaFwiKSByZXR1cm4gY29udChwdXNobGV4KFwiZm9ybVwiKSwgcHVzaGNvbnRleHQsIG1heWJlQ2F0Y2hCaW5kaW5nLCBzdGF0ZW1lbnQsIHBvcGxleCwgcG9wY29udGV4dCk7XG4gICAgaWYgKHR5cGUgPT0gXCJleHBvcnRcIikgcmV0dXJuIGNvbnQocHVzaGxleChcInN0YXRcIiksIGFmdGVyRXhwb3J0LCBwb3BsZXgpO1xuICAgIGlmICh0eXBlID09IFwiaW1wb3J0XCIpIHJldHVybiBjb250KHB1c2hsZXgoXCJzdGF0XCIpLCBhZnRlckltcG9ydCwgcG9wbGV4KTtcbiAgICBpZiAodHlwZSA9PSBcImFzeW5jXCIpIHJldHVybiBjb250KHN0YXRlbWVudClcbiAgICBpZiAodmFsdWUgPT0gXCJAXCIpIHJldHVybiBjb250KGV4cHJlc3Npb24sIHN0YXRlbWVudClcbiAgICByZXR1cm4gcGFzcyhwdXNobGV4KFwic3RhdFwiKSwgZXhwcmVzc2lvbiwgZXhwZWN0KFwiO1wiKSwgcG9wbGV4KTtcbiAgfVxuICBmdW5jdGlvbiBtYXliZUNhdGNoQmluZGluZyh0eXBlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCIoXCIpIHJldHVybiBjb250KGZ1bmFyZywgZXhwZWN0KFwiKVwiKSlcbiAgfVxuICBmdW5jdGlvbiBleHByZXNzaW9uKHR5cGUsIHZhbHVlKSB7XG4gICAgcmV0dXJuIGV4cHJlc3Npb25Jbm5lcih0eXBlLCB2YWx1ZSwgZmFsc2UpO1xuICB9XG4gIGZ1bmN0aW9uIGV4cHJlc3Npb25Ob0NvbW1hKHR5cGUsIHZhbHVlKSB7XG4gICAgcmV0dXJuIGV4cHJlc3Npb25Jbm5lcih0eXBlLCB2YWx1ZSwgdHJ1ZSk7XG4gIH1cbiAgZnVuY3Rpb24gcGFyZW5FeHByKHR5cGUpIHtcbiAgICBpZiAodHlwZSAhPSBcIihcIikgcmV0dXJuIHBhc3MoKVxuICAgIHJldHVybiBjb250KHB1c2hsZXgoXCIpXCIpLCBtYXliZWV4cHJlc3Npb24sIGV4cGVjdChcIilcIiksIHBvcGxleClcbiAgfVxuICBmdW5jdGlvbiBleHByZXNzaW9uSW5uZXIodHlwZSwgdmFsdWUsIG5vQ29tbWEpIHtcbiAgICBpZiAoY3guc3RhdGUuZmF0QXJyb3dBdCA9PSBjeC5zdHJlYW0uc3RhcnQpIHtcbiAgICAgIHZhciBib2R5ID0gbm9Db21tYSA/IGFycm93Qm9keU5vQ29tbWEgOiBhcnJvd0JvZHk7XG4gICAgICBpZiAodHlwZSA9PSBcIihcIikgcmV0dXJuIGNvbnQocHVzaGNvbnRleHQsIHB1c2hsZXgoXCIpXCIpLCBjb21tYXNlcChmdW5hcmcsIFwiKVwiKSwgcG9wbGV4LCBleHBlY3QoXCI9PlwiKSwgYm9keSwgcG9wY29udGV4dCk7XG4gICAgICBlbHNlIGlmICh0eXBlID09IFwidmFyaWFibGVcIikgcmV0dXJuIHBhc3MocHVzaGNvbnRleHQsIHBhdHRlcm4sIGV4cGVjdChcIj0+XCIpLCBib2R5LCBwb3Bjb250ZXh0KTtcbiAgICB9XG5cbiAgICB2YXIgbWF5YmVvcCA9IG5vQ29tbWEgPyBtYXliZW9wZXJhdG9yTm9Db21tYSA6IG1heWJlb3BlcmF0b3JDb21tYTtcbiAgICBpZiAoYXRvbWljVHlwZXMuaGFzT3duUHJvcGVydHkodHlwZSkpIHJldHVybiBjb250KG1heWJlb3ApO1xuICAgIGlmICh0eXBlID09IFwiZnVuY3Rpb25cIikgcmV0dXJuIGNvbnQoZnVuY3Rpb25kZWYsIG1heWJlb3ApO1xuICAgIGlmICh0eXBlID09IFwiY2xhc3NcIiB8fCAoaXNUUyAmJiB2YWx1ZSA9PSBcImludGVyZmFjZVwiKSkgeyBjeC5tYXJrZWQgPSBcImtleXdvcmRcIjsgcmV0dXJuIGNvbnQocHVzaGxleChcImZvcm1cIiksIGNsYXNzRXhwcmVzc2lvbiwgcG9wbGV4KTsgfVxuICAgIGlmICh0eXBlID09IFwia2V5d29yZCBjXCIgfHwgdHlwZSA9PSBcImFzeW5jXCIpIHJldHVybiBjb250KG5vQ29tbWEgPyBleHByZXNzaW9uTm9Db21tYSA6IGV4cHJlc3Npb24pO1xuICAgIGlmICh0eXBlID09IFwiKFwiKSByZXR1cm4gY29udChwdXNobGV4KFwiKVwiKSwgbWF5YmVleHByZXNzaW9uLCBleHBlY3QoXCIpXCIpLCBwb3BsZXgsIG1heWJlb3ApO1xuICAgIGlmICh0eXBlID09IFwib3BlcmF0b3JcIiB8fCB0eXBlID09IFwic3ByZWFkXCIpIHJldHVybiBjb250KG5vQ29tbWEgPyBleHByZXNzaW9uTm9Db21tYSA6IGV4cHJlc3Npb24pO1xuICAgIGlmICh0eXBlID09IFwiW1wiKSByZXR1cm4gY29udChwdXNobGV4KFwiXVwiKSwgYXJyYXlMaXRlcmFsLCBwb3BsZXgsIG1heWJlb3ApO1xuICAgIGlmICh0eXBlID09IFwie1wiKSByZXR1cm4gY29udENvbW1hc2VwKG9ianByb3AsIFwifVwiLCBudWxsLCBtYXliZW9wKTtcbiAgICBpZiAodHlwZSA9PSBcInF1YXNpXCIpIHJldHVybiBwYXNzKHF1YXNpLCBtYXliZW9wKTtcbiAgICBpZiAodHlwZSA9PSBcIm5ld1wiKSByZXR1cm4gY29udChtYXliZVRhcmdldChub0NvbW1hKSk7XG4gICAgcmV0dXJuIGNvbnQoKTtcbiAgfVxuICBmdW5jdGlvbiBtYXliZWV4cHJlc3Npb24odHlwZSkge1xuICAgIGlmICh0eXBlLm1hdGNoKC9bO1xcfVxcKVxcXSxdLykpIHJldHVybiBwYXNzKCk7XG4gICAgcmV0dXJuIHBhc3MoZXhwcmVzc2lvbik7XG4gIH1cblxuICBmdW5jdGlvbiBtYXliZW9wZXJhdG9yQ29tbWEodHlwZSwgdmFsdWUpIHtcbiAgICBpZiAodHlwZSA9PSBcIixcIikgcmV0dXJuIGNvbnQobWF5YmVleHByZXNzaW9uKTtcbiAgICByZXR1cm4gbWF5YmVvcGVyYXRvck5vQ29tbWEodHlwZSwgdmFsdWUsIGZhbHNlKTtcbiAgfVxuICBmdW5jdGlvbiBtYXliZW9wZXJhdG9yTm9Db21tYSh0eXBlLCB2YWx1ZSwgbm9Db21tYSkge1xuICAgIHZhciBtZSA9IG5vQ29tbWEgPT0gZmFsc2UgPyBtYXliZW9wZXJhdG9yQ29tbWEgOiBtYXliZW9wZXJhdG9yTm9Db21tYTtcbiAgICB2YXIgZXhwciA9IG5vQ29tbWEgPT0gZmFsc2UgPyBleHByZXNzaW9uIDogZXhwcmVzc2lvbk5vQ29tbWE7XG4gICAgaWYgKHR5cGUgPT0gXCI9PlwiKSByZXR1cm4gY29udChwdXNoY29udGV4dCwgbm9Db21tYSA/IGFycm93Qm9keU5vQ29tbWEgOiBhcnJvd0JvZHksIHBvcGNvbnRleHQpO1xuICAgIGlmICh0eXBlID09IFwib3BlcmF0b3JcIikge1xuICAgICAgaWYgKC9cXCtcXCt8LS0vLnRlc3QodmFsdWUpIHx8IGlzVFMgJiYgdmFsdWUgPT0gXCIhXCIpIHJldHVybiBjb250KG1lKTtcbiAgICAgIGlmIChpc1RTICYmIHZhbHVlID09IFwiPFwiICYmIGN4LnN0cmVhbS5tYXRjaCgvXihbXjw+XXw8W148Pl0qPikqPlxccypcXCgvLCBmYWxzZSkpXG4gICAgICAgIHJldHVybiBjb250KHB1c2hsZXgoXCI+XCIpLCBjb21tYXNlcCh0eXBlZXhwciwgXCI+XCIpLCBwb3BsZXgsIG1lKTtcbiAgICAgIGlmICh2YWx1ZSA9PSBcIj9cIikgcmV0dXJuIGNvbnQoZXhwcmVzc2lvbiwgZXhwZWN0KFwiOlwiKSwgZXhwcik7XG4gICAgICByZXR1cm4gY29udChleHByKTtcbiAgICB9XG4gICAgaWYgKHR5cGUgPT0gXCJxdWFzaVwiKSB7IHJldHVybiBwYXNzKHF1YXNpLCBtZSk7IH1cbiAgICBpZiAodHlwZSA9PSBcIjtcIikgcmV0dXJuO1xuICAgIGlmICh0eXBlID09IFwiKFwiKSByZXR1cm4gY29udENvbW1hc2VwKGV4cHJlc3Npb25Ob0NvbW1hLCBcIilcIiwgXCJjYWxsXCIsIG1lKTtcbiAgICBpZiAodHlwZSA9PSBcIi5cIikgcmV0dXJuIGNvbnQocHJvcGVydHksIG1lKTtcbiAgICBpZiAodHlwZSA9PSBcIltcIikgcmV0dXJuIGNvbnQocHVzaGxleChcIl1cIiksIG1heWJlZXhwcmVzc2lvbiwgZXhwZWN0KFwiXVwiKSwgcG9wbGV4LCBtZSk7XG4gICAgaWYgKGlzVFMgJiYgdmFsdWUgPT0gXCJhc1wiKSB7IGN4Lm1hcmtlZCA9IFwia2V5d29yZFwiOyByZXR1cm4gY29udCh0eXBlZXhwciwgbWUpIH1cbiAgICBpZiAodHlwZSA9PSBcInJlZ2V4cFwiKSB7XG4gICAgICBjeC5zdGF0ZS5sYXN0VHlwZSA9IGN4Lm1hcmtlZCA9IFwib3BlcmF0b3JcIlxuICAgICAgY3guc3RyZWFtLmJhY2tVcChjeC5zdHJlYW0ucG9zIC0gY3guc3RyZWFtLnN0YXJ0IC0gMSlcbiAgICAgIHJldHVybiBjb250KGV4cHIpXG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIHF1YXNpKHR5cGUsIHZhbHVlKSB7XG4gICAgaWYgKHR5cGUgIT0gXCJxdWFzaVwiKSByZXR1cm4gcGFzcygpO1xuICAgIGlmICh2YWx1ZS5zbGljZSh2YWx1ZS5sZW5ndGggLSAyKSAhPSBcIiR7XCIpIHJldHVybiBjb250KHF1YXNpKTtcbiAgICByZXR1cm4gY29udChtYXliZWV4cHJlc3Npb24sIGNvbnRpbnVlUXVhc2kpO1xuICB9XG4gIGZ1bmN0aW9uIGNvbnRpbnVlUXVhc2kodHlwZSkge1xuICAgIGlmICh0eXBlID09IFwifVwiKSB7XG4gICAgICBjeC5tYXJrZWQgPSBcInN0cmluZy0yXCI7XG4gICAgICBjeC5zdGF0ZS50b2tlbml6ZSA9IHRva2VuUXVhc2k7XG4gICAgICByZXR1cm4gY29udChxdWFzaSk7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGFycm93Qm9keSh0eXBlKSB7XG4gICAgZmluZEZhdEFycm93KGN4LnN0cmVhbSwgY3guc3RhdGUpO1xuICAgIHJldHVybiBwYXNzKHR5cGUgPT0gXCJ7XCIgPyBzdGF0ZW1lbnQgOiBleHByZXNzaW9uKTtcbiAgfVxuICBmdW5jdGlvbiBhcnJvd0JvZHlOb0NvbW1hKHR5cGUpIHtcbiAgICBmaW5kRmF0QXJyb3coY3guc3RyZWFtLCBjeC5zdGF0ZSk7XG4gICAgcmV0dXJuIHBhc3ModHlwZSA9PSBcIntcIiA/IHN0YXRlbWVudCA6IGV4cHJlc3Npb25Ob0NvbW1hKTtcbiAgfVxuICBmdW5jdGlvbiBtYXliZVRhcmdldChub0NvbW1hKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHR5cGUpIHtcbiAgICAgIGlmICh0eXBlID09IFwiLlwiKSByZXR1cm4gY29udChub0NvbW1hID8gdGFyZ2V0Tm9Db21tYSA6IHRhcmdldCk7XG4gICAgICBlbHNlIGlmICh0eXBlID09IFwidmFyaWFibGVcIiAmJiBpc1RTKSByZXR1cm4gY29udChtYXliZVR5cGVBcmdzLCBub0NvbW1hID8gbWF5YmVvcGVyYXRvck5vQ29tbWEgOiBtYXliZW9wZXJhdG9yQ29tbWEpXG4gICAgICBlbHNlIHJldHVybiBwYXNzKG5vQ29tbWEgPyBleHByZXNzaW9uTm9Db21tYSA6IGV4cHJlc3Npb24pO1xuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gdGFyZ2V0KF8sIHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09IFwidGFyZ2V0XCIpIHsgY3gubWFya2VkID0gXCJrZXl3b3JkXCI7IHJldHVybiBjb250KG1heWJlb3BlcmF0b3JDb21tYSk7IH1cbiAgfVxuICBmdW5jdGlvbiB0YXJnZXROb0NvbW1hKF8sIHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09IFwidGFyZ2V0XCIpIHsgY3gubWFya2VkID0gXCJrZXl3b3JkXCI7IHJldHVybiBjb250KG1heWJlb3BlcmF0b3JOb0NvbW1hKTsgfVxuICB9XG4gIGZ1bmN0aW9uIG1heWJlbGFiZWwodHlwZSkge1xuICAgIGlmICh0eXBlID09IFwiOlwiKSByZXR1cm4gY29udChwb3BsZXgsIHN0YXRlbWVudCk7XG4gICAgcmV0dXJuIHBhc3MobWF5YmVvcGVyYXRvckNvbW1hLCBleHBlY3QoXCI7XCIpLCBwb3BsZXgpO1xuICB9XG4gIGZ1bmN0aW9uIHByb3BlcnR5KHR5cGUpIHtcbiAgICBpZiAodHlwZSA9PSBcInZhcmlhYmxlXCIpIHtjeC5tYXJrZWQgPSBcInByb3BlcnR5XCI7IHJldHVybiBjb250KCk7fVxuICB9XG4gIGZ1bmN0aW9uIG9ianByb3AodHlwZSwgdmFsdWUpIHtcbiAgICBpZiAodHlwZSA9PSBcImFzeW5jXCIpIHtcbiAgICAgIGN4Lm1hcmtlZCA9IFwicHJvcGVydHlcIjtcbiAgICAgIHJldHVybiBjb250KG9ianByb3ApO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PSBcInZhcmlhYmxlXCIgfHwgY3guc3R5bGUgPT0gXCJrZXl3b3JkXCIpIHtcbiAgICAgIGN4Lm1hcmtlZCA9IFwicHJvcGVydHlcIjtcbiAgICAgIGlmICh2YWx1ZSA9PSBcImdldFwiIHx8IHZhbHVlID09IFwic2V0XCIpIHJldHVybiBjb250KGdldHRlclNldHRlcik7XG4gICAgICB2YXIgbSAvLyBXb3JrIGFyb3VuZCBmYXQtYXJyb3ctZGV0ZWN0aW9uIGNvbXBsaWNhdGlvbiBmb3IgZGV0ZWN0aW5nIHR5cGVzY3JpcHQgdHlwZWQgYXJyb3cgcGFyYW1zXG4gICAgICBpZiAoaXNUUyAmJiBjeC5zdGF0ZS5mYXRBcnJvd0F0ID09IGN4LnN0cmVhbS5zdGFydCAmJiAobSA9IGN4LnN0cmVhbS5tYXRjaCgvXlxccyo6XFxzKi8sIGZhbHNlKSkpXG4gICAgICAgIGN4LnN0YXRlLmZhdEFycm93QXQgPSBjeC5zdHJlYW0ucG9zICsgbVswXS5sZW5ndGhcbiAgICAgIHJldHVybiBjb250KGFmdGVycHJvcCk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09IFwibnVtYmVyXCIgfHwgdHlwZSA9PSBcInN0cmluZ1wiKSB7XG4gICAgICBjeC5tYXJrZWQgPSBqc29ubGRNb2RlID8gXCJwcm9wZXJ0eVwiIDogKGN4LnN0eWxlICsgXCIgcHJvcGVydHlcIik7XG4gICAgICByZXR1cm4gY29udChhZnRlcnByb3ApO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PSBcImpzb25sZC1rZXl3b3JkXCIpIHtcbiAgICAgIHJldHVybiBjb250KGFmdGVycHJvcCk7XG4gICAgfSBlbHNlIGlmIChpc1RTICYmIGlzTW9kaWZpZXIodmFsdWUpKSB7XG4gICAgICBjeC5tYXJrZWQgPSBcImtleXdvcmRcIlxuICAgICAgcmV0dXJuIGNvbnQob2JqcHJvcClcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT0gXCJbXCIpIHtcbiAgICAgIHJldHVybiBjb250KGV4cHJlc3Npb24sIG1heWJldHlwZSwgZXhwZWN0KFwiXVwiKSwgYWZ0ZXJwcm9wKTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT0gXCJzcHJlYWRcIikge1xuICAgICAgcmV0dXJuIGNvbnQoZXhwcmVzc2lvbk5vQ29tbWEsIGFmdGVycHJvcCk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZSA9PSBcIipcIikge1xuICAgICAgY3gubWFya2VkID0gXCJrZXl3b3JkXCI7XG4gICAgICByZXR1cm4gY29udChvYmpwcm9wKTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT0gXCI6XCIpIHtcbiAgICAgIHJldHVybiBwYXNzKGFmdGVycHJvcClcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZ2V0dGVyU2V0dGVyKHR5cGUpIHtcbiAgICBpZiAodHlwZSAhPSBcInZhcmlhYmxlXCIpIHJldHVybiBwYXNzKGFmdGVycHJvcCk7XG4gICAgY3gubWFya2VkID0gXCJwcm9wZXJ0eVwiO1xuICAgIHJldHVybiBjb250KGZ1bmN0aW9uZGVmKTtcbiAgfVxuICBmdW5jdGlvbiBhZnRlcnByb3AodHlwZSkge1xuICAgIGlmICh0eXBlID09IFwiOlwiKSByZXR1cm4gY29udChleHByZXNzaW9uTm9Db21tYSk7XG4gICAgaWYgKHR5cGUgPT0gXCIoXCIpIHJldHVybiBwYXNzKGZ1bmN0aW9uZGVmKTtcbiAgfVxuICBmdW5jdGlvbiBjb21tYXNlcCh3aGF0LCBlbmQsIHNlcCkge1xuICAgIGZ1bmN0aW9uIHByb2NlZWQodHlwZSwgdmFsdWUpIHtcbiAgICAgIGlmIChzZXAgPyBzZXAuaW5kZXhPZih0eXBlKSA+IC0xIDogdHlwZSA9PSBcIixcIikge1xuICAgICAgICB2YXIgbGV4ID0gY3guc3RhdGUubGV4aWNhbDtcbiAgICAgICAgaWYgKGxleC5pbmZvID09IFwiY2FsbFwiKSBsZXgucG9zID0gKGxleC5wb3MgfHwgMCkgKyAxO1xuICAgICAgICByZXR1cm4gY29udChmdW5jdGlvbih0eXBlLCB2YWx1ZSkge1xuICAgICAgICAgIGlmICh0eXBlID09IGVuZCB8fCB2YWx1ZSA9PSBlbmQpIHJldHVybiBwYXNzKClcbiAgICAgICAgICByZXR1cm4gcGFzcyh3aGF0KVxuICAgICAgICB9LCBwcm9jZWVkKTtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlID09IGVuZCB8fCB2YWx1ZSA9PSBlbmQpIHJldHVybiBjb250KCk7XG4gICAgICBpZiAoc2VwICYmIHNlcC5pbmRleE9mKFwiO1wiKSA+IC0xKSByZXR1cm4gcGFzcyh3aGF0KVxuICAgICAgcmV0dXJuIGNvbnQoZXhwZWN0KGVuZCkpO1xuICAgIH1cbiAgICByZXR1cm4gZnVuY3Rpb24odHlwZSwgdmFsdWUpIHtcbiAgICAgIGlmICh0eXBlID09IGVuZCB8fCB2YWx1ZSA9PSBlbmQpIHJldHVybiBjb250KCk7XG4gICAgICByZXR1cm4gcGFzcyh3aGF0LCBwcm9jZWVkKTtcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGNvbnRDb21tYXNlcCh3aGF0LCBlbmQsIGluZm8pIHtcbiAgICBmb3IgKHZhciBpID0gMzsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKylcbiAgICAgIGN4LmNjLnB1c2goYXJndW1lbnRzW2ldKTtcbiAgICByZXR1cm4gY29udChwdXNobGV4KGVuZCwgaW5mbyksIGNvbW1hc2VwKHdoYXQsIGVuZCksIHBvcGxleCk7XG4gIH1cbiAgZnVuY3Rpb24gYmxvY2sodHlwZSkge1xuICAgIGlmICh0eXBlID09IFwifVwiKSByZXR1cm4gY29udCgpO1xuICAgIHJldHVybiBwYXNzKHN0YXRlbWVudCwgYmxvY2spO1xuICB9XG4gIGZ1bmN0aW9uIG1heWJldHlwZSh0eXBlLCB2YWx1ZSkge1xuICAgIGlmIChpc1RTKSB7XG4gICAgICBpZiAodHlwZSA9PSBcIjpcIikgcmV0dXJuIGNvbnQodHlwZWV4cHIpO1xuICAgICAgaWYgKHZhbHVlID09IFwiP1wiKSByZXR1cm4gY29udChtYXliZXR5cGUpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBtYXliZXR5cGVPckluKHR5cGUsIHZhbHVlKSB7XG4gICAgaWYgKGlzVFMgJiYgKHR5cGUgPT0gXCI6XCIgfHwgdmFsdWUgPT0gXCJpblwiKSkgcmV0dXJuIGNvbnQodHlwZWV4cHIpXG4gIH1cbiAgZnVuY3Rpb24gbWF5YmVyZXR0eXBlKHR5cGUpIHtcbiAgICBpZiAoaXNUUyAmJiB0eXBlID09IFwiOlwiKSB7XG4gICAgICBpZiAoY3guc3RyZWFtLm1hdGNoKC9eXFxzKlxcdytcXHMraXNcXGIvLCBmYWxzZSkpIHJldHVybiBjb250KGV4cHJlc3Npb24sIGlzS1csIHR5cGVleHByKVxuICAgICAgZWxzZSByZXR1cm4gY29udCh0eXBlZXhwcilcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gaXNLVyhfLCB2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PSBcImlzXCIpIHtcbiAgICAgIGN4Lm1hcmtlZCA9IFwia2V5d29yZFwiXG4gICAgICByZXR1cm4gY29udCgpXG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIHR5cGVleHByKHR5cGUsIHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09IFwia2V5b2ZcIiB8fCB2YWx1ZSA9PSBcInR5cGVvZlwiIHx8IHZhbHVlID09IFwiaW5mZXJcIiB8fCB2YWx1ZSA9PSBcInJlYWRvbmx5XCIpIHtcbiAgICAgIGN4Lm1hcmtlZCA9IFwia2V5d29yZFwiXG4gICAgICByZXR1cm4gY29udCh2YWx1ZSA9PSBcInR5cGVvZlwiID8gZXhwcmVzc2lvbk5vQ29tbWEgOiB0eXBlZXhwcilcbiAgICB9XG4gICAgaWYgKHR5cGUgPT0gXCJ2YXJpYWJsZVwiIHx8IHZhbHVlID09IFwidm9pZFwiKSB7XG4gICAgICBjeC5tYXJrZWQgPSBcInR5cGVcIlxuICAgICAgcmV0dXJuIGNvbnQoYWZ0ZXJUeXBlKVxuICAgIH1cbiAgICBpZiAodmFsdWUgPT0gXCJ8XCIgfHwgdmFsdWUgPT0gXCImXCIpIHJldHVybiBjb250KHR5cGVleHByKVxuICAgIGlmICh0eXBlID09IFwic3RyaW5nXCIgfHwgdHlwZSA9PSBcIm51bWJlclwiIHx8IHR5cGUgPT0gXCJhdG9tXCIpIHJldHVybiBjb250KGFmdGVyVHlwZSk7XG4gICAgaWYgKHR5cGUgPT0gXCJbXCIpIHJldHVybiBjb250KHB1c2hsZXgoXCJdXCIpLCBjb21tYXNlcCh0eXBlZXhwciwgXCJdXCIsIFwiLFwiKSwgcG9wbGV4LCBhZnRlclR5cGUpXG4gICAgaWYgKHR5cGUgPT0gXCJ7XCIpIHJldHVybiBjb250KHB1c2hsZXgoXCJ9XCIpLCB0eXBlcHJvcHMsIHBvcGxleCwgYWZ0ZXJUeXBlKVxuICAgIGlmICh0eXBlID09IFwiKFwiKSByZXR1cm4gY29udChjb21tYXNlcCh0eXBlYXJnLCBcIilcIiksIG1heWJlUmV0dXJuVHlwZSwgYWZ0ZXJUeXBlKVxuICAgIGlmICh0eXBlID09IFwiPFwiKSByZXR1cm4gY29udChjb21tYXNlcCh0eXBlZXhwciwgXCI+XCIpLCB0eXBlZXhwcilcbiAgICBpZiAodHlwZSA9PSBcInF1YXNpXCIpIHsgcmV0dXJuIHBhc3MocXVhc2lUeXBlLCBhZnRlclR5cGUpOyB9XG4gIH1cbiAgZnVuY3Rpb24gbWF5YmVSZXR1cm5UeXBlKHR5cGUpIHtcbiAgICBpZiAodHlwZSA9PSBcIj0+XCIpIHJldHVybiBjb250KHR5cGVleHByKVxuICB9XG4gIGZ1bmN0aW9uIHR5cGVwcm9wcyh0eXBlKSB7XG4gICAgaWYgKHR5cGUubWF0Y2goL1tcXH1cXClcXF1dLykpIHJldHVybiBjb250KClcbiAgICBpZiAodHlwZSA9PSBcIixcIiB8fCB0eXBlID09IFwiO1wiKSByZXR1cm4gY29udCh0eXBlcHJvcHMpXG4gICAgcmV0dXJuIHBhc3ModHlwZXByb3AsIHR5cGVwcm9wcylcbiAgfVxuICBmdW5jdGlvbiB0eXBlcHJvcCh0eXBlLCB2YWx1ZSkge1xuICAgIGlmICh0eXBlID09IFwidmFyaWFibGVcIiB8fCBjeC5zdHlsZSA9PSBcImtleXdvcmRcIikge1xuICAgICAgY3gubWFya2VkID0gXCJwcm9wZXJ0eVwiXG4gICAgICByZXR1cm4gY29udCh0eXBlcHJvcClcbiAgICB9IGVsc2UgaWYgKHZhbHVlID09IFwiP1wiIHx8IHR5cGUgPT0gXCJudW1iZXJcIiB8fCB0eXBlID09IFwic3RyaW5nXCIpIHtcbiAgICAgIHJldHVybiBjb250KHR5cGVwcm9wKVxuICAgIH0gZWxzZSBpZiAodHlwZSA9PSBcIjpcIikge1xuICAgICAgcmV0dXJuIGNvbnQodHlwZWV4cHIpXG4gICAgfSBlbHNlIGlmICh0eXBlID09IFwiW1wiKSB7XG4gICAgICByZXR1cm4gY29udChleHBlY3QoXCJ2YXJpYWJsZVwiKSwgbWF5YmV0eXBlT3JJbiwgZXhwZWN0KFwiXVwiKSwgdHlwZXByb3ApXG4gICAgfSBlbHNlIGlmICh0eXBlID09IFwiKFwiKSB7XG4gICAgICByZXR1cm4gcGFzcyhmdW5jdGlvbmRlY2wsIHR5cGVwcm9wKVxuICAgIH0gZWxzZSBpZiAoIXR5cGUubWF0Y2goL1s7XFx9XFwpXFxdLF0vKSkge1xuICAgICAgcmV0dXJuIGNvbnQoKVxuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBxdWFzaVR5cGUodHlwZSwgdmFsdWUpIHtcbiAgICBpZiAodHlwZSAhPSBcInF1YXNpXCIpIHJldHVybiBwYXNzKCk7XG4gICAgaWYgKHZhbHVlLnNsaWNlKHZhbHVlLmxlbmd0aCAtIDIpICE9IFwiJHtcIikgcmV0dXJuIGNvbnQocXVhc2lUeXBlKTtcbiAgICByZXR1cm4gY29udCh0eXBlZXhwciwgY29udGludWVRdWFzaVR5cGUpO1xuICB9XG4gIGZ1bmN0aW9uIGNvbnRpbnVlUXVhc2lUeXBlKHR5cGUpIHtcbiAgICBpZiAodHlwZSA9PSBcIn1cIikge1xuICAgICAgY3gubWFya2VkID0gXCJzdHJpbmctMlwiO1xuICAgICAgY3guc3RhdGUudG9rZW5pemUgPSB0b2tlblF1YXNpO1xuICAgICAgcmV0dXJuIGNvbnQocXVhc2lUeXBlKTtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gdHlwZWFyZyh0eXBlLCB2YWx1ZSkge1xuICAgIGlmICh0eXBlID09IFwidmFyaWFibGVcIiAmJiBjeC5zdHJlYW0ubWF0Y2goL15cXHMqWz86XS8sIGZhbHNlKSB8fCB2YWx1ZSA9PSBcIj9cIikgcmV0dXJuIGNvbnQodHlwZWFyZylcbiAgICBpZiAodHlwZSA9PSBcIjpcIikgcmV0dXJuIGNvbnQodHlwZWV4cHIpXG4gICAgaWYgKHR5cGUgPT0gXCJzcHJlYWRcIikgcmV0dXJuIGNvbnQodHlwZWFyZylcbiAgICByZXR1cm4gcGFzcyh0eXBlZXhwcilcbiAgfVxuICBmdW5jdGlvbiBhZnRlclR5cGUodHlwZSwgdmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPT0gXCI8XCIpIHJldHVybiBjb250KHB1c2hsZXgoXCI+XCIpLCBjb21tYXNlcCh0eXBlZXhwciwgXCI+XCIpLCBwb3BsZXgsIGFmdGVyVHlwZSlcbiAgICBpZiAodmFsdWUgPT0gXCJ8XCIgfHwgdHlwZSA9PSBcIi5cIiB8fCB2YWx1ZSA9PSBcIiZcIikgcmV0dXJuIGNvbnQodHlwZWV4cHIpXG4gICAgaWYgKHR5cGUgPT0gXCJbXCIpIHJldHVybiBjb250KHR5cGVleHByLCBleHBlY3QoXCJdXCIpLCBhZnRlclR5cGUpXG4gICAgaWYgKHZhbHVlID09IFwiZXh0ZW5kc1wiIHx8IHZhbHVlID09IFwiaW1wbGVtZW50c1wiKSB7IGN4Lm1hcmtlZCA9IFwia2V5d29yZFwiOyByZXR1cm4gY29udCh0eXBlZXhwcikgfVxuICAgIGlmICh2YWx1ZSA9PSBcIj9cIikgcmV0dXJuIGNvbnQodHlwZWV4cHIsIGV4cGVjdChcIjpcIiksIHR5cGVleHByKVxuICB9XG4gIGZ1bmN0aW9uIG1heWJlVHlwZUFyZ3MoXywgdmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPT0gXCI8XCIpIHJldHVybiBjb250KHB1c2hsZXgoXCI+XCIpLCBjb21tYXNlcCh0eXBlZXhwciwgXCI+XCIpLCBwb3BsZXgsIGFmdGVyVHlwZSlcbiAgfVxuICBmdW5jdGlvbiB0eXBlcGFyYW0oKSB7XG4gICAgcmV0dXJuIHBhc3ModHlwZWV4cHIsIG1heWJlVHlwZURlZmF1bHQpXG4gIH1cbiAgZnVuY3Rpb24gbWF5YmVUeXBlRGVmYXVsdChfLCB2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PSBcIj1cIikgcmV0dXJuIGNvbnQodHlwZWV4cHIpXG4gIH1cbiAgZnVuY3Rpb24gdmFyZGVmKF8sIHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09IFwiZW51bVwiKSB7Y3gubWFya2VkID0gXCJrZXl3b3JkXCI7IHJldHVybiBjb250KGVudW1kZWYpfVxuICAgIHJldHVybiBwYXNzKHBhdHRlcm4sIG1heWJldHlwZSwgbWF5YmVBc3NpZ24sIHZhcmRlZkNvbnQpO1xuICB9XG4gIGZ1bmN0aW9uIHBhdHRlcm4odHlwZSwgdmFsdWUpIHtcbiAgICBpZiAoaXNUUyAmJiBpc01vZGlmaWVyKHZhbHVlKSkgeyBjeC5tYXJrZWQgPSBcImtleXdvcmRcIjsgcmV0dXJuIGNvbnQocGF0dGVybikgfVxuICAgIGlmICh0eXBlID09IFwidmFyaWFibGVcIikgeyByZWdpc3Rlcih2YWx1ZSk7IHJldHVybiBjb250KCk7IH1cbiAgICBpZiAodHlwZSA9PSBcInNwcmVhZFwiKSByZXR1cm4gY29udChwYXR0ZXJuKTtcbiAgICBpZiAodHlwZSA9PSBcIltcIikgcmV0dXJuIGNvbnRDb21tYXNlcChlbHRwYXR0ZXJuLCBcIl1cIik7XG4gICAgaWYgKHR5cGUgPT0gXCJ7XCIpIHJldHVybiBjb250Q29tbWFzZXAocHJvcHBhdHRlcm4sIFwifVwiKTtcbiAgfVxuICBmdW5jdGlvbiBwcm9wcGF0dGVybih0eXBlLCB2YWx1ZSkge1xuICAgIGlmICh0eXBlID09IFwidmFyaWFibGVcIiAmJiAhY3guc3RyZWFtLm1hdGNoKC9eXFxzKjovLCBmYWxzZSkpIHtcbiAgICAgIHJlZ2lzdGVyKHZhbHVlKTtcbiAgICAgIHJldHVybiBjb250KG1heWJlQXNzaWduKTtcbiAgICB9XG4gICAgaWYgKHR5cGUgPT0gXCJ2YXJpYWJsZVwiKSBjeC5tYXJrZWQgPSBcInByb3BlcnR5XCI7XG4gICAgaWYgKHR5cGUgPT0gXCJzcHJlYWRcIikgcmV0dXJuIGNvbnQocGF0dGVybik7XG4gICAgaWYgKHR5cGUgPT0gXCJ9XCIpIHJldHVybiBwYXNzKCk7XG4gICAgaWYgKHR5cGUgPT0gXCJbXCIpIHJldHVybiBjb250KGV4cHJlc3Npb24sIGV4cGVjdCgnXScpLCBleHBlY3QoJzonKSwgcHJvcHBhdHRlcm4pO1xuICAgIHJldHVybiBjb250KGV4cGVjdChcIjpcIiksIHBhdHRlcm4sIG1heWJlQXNzaWduKTtcbiAgfVxuICBmdW5jdGlvbiBlbHRwYXR0ZXJuKCkge1xuICAgIHJldHVybiBwYXNzKHBhdHRlcm4sIG1heWJlQXNzaWduKVxuICB9XG4gIGZ1bmN0aW9uIG1heWJlQXNzaWduKF90eXBlLCB2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PSBcIj1cIikgcmV0dXJuIGNvbnQoZXhwcmVzc2lvbk5vQ29tbWEpO1xuICB9XG4gIGZ1bmN0aW9uIHZhcmRlZkNvbnQodHlwZSkge1xuICAgIGlmICh0eXBlID09IFwiLFwiKSByZXR1cm4gY29udCh2YXJkZWYpO1xuICB9XG4gIGZ1bmN0aW9uIG1heWJlZWxzZSh0eXBlLCB2YWx1ZSkge1xuICAgIGlmICh0eXBlID09IFwia2V5d29yZCBiXCIgJiYgdmFsdWUgPT0gXCJlbHNlXCIpIHJldHVybiBjb250KHB1c2hsZXgoXCJmb3JtXCIsIFwiZWxzZVwiKSwgc3RhdGVtZW50LCBwb3BsZXgpO1xuICB9XG4gIGZ1bmN0aW9uIGZvcnNwZWModHlwZSwgdmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPT0gXCJhd2FpdFwiKSByZXR1cm4gY29udChmb3JzcGVjKTtcbiAgICBpZiAodHlwZSA9PSBcIihcIikgcmV0dXJuIGNvbnQocHVzaGxleChcIilcIiksIGZvcnNwZWMxLCBwb3BsZXgpO1xuICB9XG4gIGZ1bmN0aW9uIGZvcnNwZWMxKHR5cGUpIHtcbiAgICBpZiAodHlwZSA9PSBcInZhclwiKSByZXR1cm4gY29udCh2YXJkZWYsIGZvcnNwZWMyKTtcbiAgICBpZiAodHlwZSA9PSBcInZhcmlhYmxlXCIpIHJldHVybiBjb250KGZvcnNwZWMyKTtcbiAgICByZXR1cm4gcGFzcyhmb3JzcGVjMilcbiAgfVxuICBmdW5jdGlvbiBmb3JzcGVjMih0eXBlLCB2YWx1ZSkge1xuICAgIGlmICh0eXBlID09IFwiKVwiKSByZXR1cm4gY29udCgpXG4gICAgaWYgKHR5cGUgPT0gXCI7XCIpIHJldHVybiBjb250KGZvcnNwZWMyKVxuICAgIGlmICh2YWx1ZSA9PSBcImluXCIgfHwgdmFsdWUgPT0gXCJvZlwiKSB7IGN4Lm1hcmtlZCA9IFwia2V5d29yZFwiOyByZXR1cm4gY29udChleHByZXNzaW9uLCBmb3JzcGVjMikgfVxuICAgIHJldHVybiBwYXNzKGV4cHJlc3Npb24sIGZvcnNwZWMyKVxuICB9XG4gIGZ1bmN0aW9uIGZ1bmN0aW9uZGVmKHR5cGUsIHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09IFwiKlwiKSB7Y3gubWFya2VkID0gXCJrZXl3b3JkXCI7IHJldHVybiBjb250KGZ1bmN0aW9uZGVmKTt9XG4gICAgaWYgKHR5cGUgPT0gXCJ2YXJpYWJsZVwiKSB7cmVnaXN0ZXIodmFsdWUpOyByZXR1cm4gY29udChmdW5jdGlvbmRlZik7fVxuICAgIGlmICh0eXBlID09IFwiKFwiKSByZXR1cm4gY29udChwdXNoY29udGV4dCwgcHVzaGxleChcIilcIiksIGNvbW1hc2VwKGZ1bmFyZywgXCIpXCIpLCBwb3BsZXgsIG1heWJlcmV0dHlwZSwgc3RhdGVtZW50LCBwb3Bjb250ZXh0KTtcbiAgICBpZiAoaXNUUyAmJiB2YWx1ZSA9PSBcIjxcIikgcmV0dXJuIGNvbnQocHVzaGxleChcIj5cIiksIGNvbW1hc2VwKHR5cGVwYXJhbSwgXCI+XCIpLCBwb3BsZXgsIGZ1bmN0aW9uZGVmKVxuICB9XG4gIGZ1bmN0aW9uIGZ1bmN0aW9uZGVjbCh0eXBlLCB2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PSBcIipcIikge2N4Lm1hcmtlZCA9IFwia2V5d29yZFwiOyByZXR1cm4gY29udChmdW5jdGlvbmRlY2wpO31cbiAgICBpZiAodHlwZSA9PSBcInZhcmlhYmxlXCIpIHtyZWdpc3Rlcih2YWx1ZSk7IHJldHVybiBjb250KGZ1bmN0aW9uZGVjbCk7fVxuICAgIGlmICh0eXBlID09IFwiKFwiKSByZXR1cm4gY29udChwdXNoY29udGV4dCwgcHVzaGxleChcIilcIiksIGNvbW1hc2VwKGZ1bmFyZywgXCIpXCIpLCBwb3BsZXgsIG1heWJlcmV0dHlwZSwgcG9wY29udGV4dCk7XG4gICAgaWYgKGlzVFMgJiYgdmFsdWUgPT0gXCI8XCIpIHJldHVybiBjb250KHB1c2hsZXgoXCI+XCIpLCBjb21tYXNlcCh0eXBlcGFyYW0sIFwiPlwiKSwgcG9wbGV4LCBmdW5jdGlvbmRlY2wpXG4gIH1cbiAgZnVuY3Rpb24gdHlwZW5hbWUodHlwZSwgdmFsdWUpIHtcbiAgICBpZiAodHlwZSA9PSBcImtleXdvcmRcIiB8fCB0eXBlID09IFwidmFyaWFibGVcIikge1xuICAgICAgY3gubWFya2VkID0gXCJ0eXBlXCJcbiAgICAgIHJldHVybiBjb250KHR5cGVuYW1lKVxuICAgIH0gZWxzZSBpZiAodmFsdWUgPT0gXCI8XCIpIHtcbiAgICAgIHJldHVybiBjb250KHB1c2hsZXgoXCI+XCIpLCBjb21tYXNlcCh0eXBlcGFyYW0sIFwiPlwiKSwgcG9wbGV4KVxuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBmdW5hcmcodHlwZSwgdmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPT0gXCJAXCIpIGNvbnQoZXhwcmVzc2lvbiwgZnVuYXJnKVxuICAgIGlmICh0eXBlID09IFwic3ByZWFkXCIpIHJldHVybiBjb250KGZ1bmFyZyk7XG4gICAgaWYgKGlzVFMgJiYgaXNNb2RpZmllcih2YWx1ZSkpIHsgY3gubWFya2VkID0gXCJrZXl3b3JkXCI7IHJldHVybiBjb250KGZ1bmFyZyk7IH1cbiAgICBpZiAoaXNUUyAmJiB0eXBlID09IFwidGhpc1wiKSByZXR1cm4gY29udChtYXliZXR5cGUsIG1heWJlQXNzaWduKVxuICAgIHJldHVybiBwYXNzKHBhdHRlcm4sIG1heWJldHlwZSwgbWF5YmVBc3NpZ24pO1xuICB9XG4gIGZ1bmN0aW9uIGNsYXNzRXhwcmVzc2lvbih0eXBlLCB2YWx1ZSkge1xuICAgIC8vIENsYXNzIGV4cHJlc3Npb25zIG1heSBoYXZlIGFuIG9wdGlvbmFsIG5hbWUuXG4gICAgaWYgKHR5cGUgPT0gXCJ2YXJpYWJsZVwiKSByZXR1cm4gY2xhc3NOYW1lKHR5cGUsIHZhbHVlKTtcbiAgICByZXR1cm4gY2xhc3NOYW1lQWZ0ZXIodHlwZSwgdmFsdWUpO1xuICB9XG4gIGZ1bmN0aW9uIGNsYXNzTmFtZSh0eXBlLCB2YWx1ZSkge1xuICAgIGlmICh0eXBlID09IFwidmFyaWFibGVcIikge3JlZ2lzdGVyKHZhbHVlKTsgcmV0dXJuIGNvbnQoY2xhc3NOYW1lQWZ0ZXIpO31cbiAgfVxuICBmdW5jdGlvbiBjbGFzc05hbWVBZnRlcih0eXBlLCB2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PSBcIjxcIikgcmV0dXJuIGNvbnQocHVzaGxleChcIj5cIiksIGNvbW1hc2VwKHR5cGVwYXJhbSwgXCI+XCIpLCBwb3BsZXgsIGNsYXNzTmFtZUFmdGVyKVxuICAgIGlmICh2YWx1ZSA9PSBcImV4dGVuZHNcIiB8fCB2YWx1ZSA9PSBcImltcGxlbWVudHNcIiB8fCAoaXNUUyAmJiB0eXBlID09IFwiLFwiKSkge1xuICAgICAgaWYgKHZhbHVlID09IFwiaW1wbGVtZW50c1wiKSBjeC5tYXJrZWQgPSBcImtleXdvcmRcIjtcbiAgICAgIHJldHVybiBjb250KGlzVFMgPyB0eXBlZXhwciA6IGV4cHJlc3Npb24sIGNsYXNzTmFtZUFmdGVyKTtcbiAgICB9XG4gICAgaWYgKHR5cGUgPT0gXCJ7XCIpIHJldHVybiBjb250KHB1c2hsZXgoXCJ9XCIpLCBjbGFzc0JvZHksIHBvcGxleCk7XG4gIH1cbiAgZnVuY3Rpb24gY2xhc3NCb2R5KHR5cGUsIHZhbHVlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCJhc3luY1wiIHx8XG4gICAgICAgICh0eXBlID09IFwidmFyaWFibGVcIiAmJlxuICAgICAgICAgKHZhbHVlID09IFwic3RhdGljXCIgfHwgdmFsdWUgPT0gXCJnZXRcIiB8fCB2YWx1ZSA9PSBcInNldFwiIHx8IChpc1RTICYmIGlzTW9kaWZpZXIodmFsdWUpKSkgJiZcbiAgICAgICAgIGN4LnN0cmVhbS5tYXRjaCgvXlxccytbXFx3JFxceGExLVxcdWZmZmZdLywgZmFsc2UpKSkge1xuICAgICAgY3gubWFya2VkID0gXCJrZXl3b3JkXCI7XG4gICAgICByZXR1cm4gY29udChjbGFzc0JvZHkpO1xuICAgIH1cbiAgICBpZiAodHlwZSA9PSBcInZhcmlhYmxlXCIgfHwgY3guc3R5bGUgPT0gXCJrZXl3b3JkXCIpIHtcbiAgICAgIGN4Lm1hcmtlZCA9IFwicHJvcGVydHlcIjtcbiAgICAgIHJldHVybiBjb250KGNsYXNzZmllbGQsIGNsYXNzQm9keSk7XG4gICAgfVxuICAgIGlmICh0eXBlID09IFwibnVtYmVyXCIgfHwgdHlwZSA9PSBcInN0cmluZ1wiKSByZXR1cm4gY29udChjbGFzc2ZpZWxkLCBjbGFzc0JvZHkpO1xuICAgIGlmICh0eXBlID09IFwiW1wiKVxuICAgICAgcmV0dXJuIGNvbnQoZXhwcmVzc2lvbiwgbWF5YmV0eXBlLCBleHBlY3QoXCJdXCIpLCBjbGFzc2ZpZWxkLCBjbGFzc0JvZHkpXG4gICAgaWYgKHZhbHVlID09IFwiKlwiKSB7XG4gICAgICBjeC5tYXJrZWQgPSBcImtleXdvcmRcIjtcbiAgICAgIHJldHVybiBjb250KGNsYXNzQm9keSk7XG4gICAgfVxuICAgIGlmIChpc1RTICYmIHR5cGUgPT0gXCIoXCIpIHJldHVybiBwYXNzKGZ1bmN0aW9uZGVjbCwgY2xhc3NCb2R5KVxuICAgIGlmICh0eXBlID09IFwiO1wiIHx8IHR5cGUgPT0gXCIsXCIpIHJldHVybiBjb250KGNsYXNzQm9keSk7XG4gICAgaWYgKHR5cGUgPT0gXCJ9XCIpIHJldHVybiBjb250KCk7XG4gICAgaWYgKHZhbHVlID09IFwiQFwiKSByZXR1cm4gY29udChleHByZXNzaW9uLCBjbGFzc0JvZHkpXG4gIH1cbiAgZnVuY3Rpb24gY2xhc3NmaWVsZCh0eXBlLCB2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PSBcIiFcIikgcmV0dXJuIGNvbnQoY2xhc3NmaWVsZClcbiAgICBpZiAodmFsdWUgPT0gXCI/XCIpIHJldHVybiBjb250KGNsYXNzZmllbGQpXG4gICAgaWYgKHR5cGUgPT0gXCI6XCIpIHJldHVybiBjb250KHR5cGVleHByLCBtYXliZUFzc2lnbilcbiAgICBpZiAodmFsdWUgPT0gXCI9XCIpIHJldHVybiBjb250KGV4cHJlc3Npb25Ob0NvbW1hKVxuICAgIHZhciBjb250ZXh0ID0gY3guc3RhdGUubGV4aWNhbC5wcmV2LCBpc0ludGVyZmFjZSA9IGNvbnRleHQgJiYgY29udGV4dC5pbmZvID09IFwiaW50ZXJmYWNlXCJcbiAgICByZXR1cm4gcGFzcyhpc0ludGVyZmFjZSA/IGZ1bmN0aW9uZGVjbCA6IGZ1bmN0aW9uZGVmKVxuICB9XG4gIGZ1bmN0aW9uIGFmdGVyRXhwb3J0KHR5cGUsIHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09IFwiKlwiKSB7IGN4Lm1hcmtlZCA9IFwia2V5d29yZFwiOyByZXR1cm4gY29udChtYXliZUZyb20sIGV4cGVjdChcIjtcIikpOyB9XG4gICAgaWYgKHZhbHVlID09IFwiZGVmYXVsdFwiKSB7IGN4Lm1hcmtlZCA9IFwia2V5d29yZFwiOyByZXR1cm4gY29udChleHByZXNzaW9uLCBleHBlY3QoXCI7XCIpKTsgfVxuICAgIGlmICh0eXBlID09IFwie1wiKSByZXR1cm4gY29udChjb21tYXNlcChleHBvcnRGaWVsZCwgXCJ9XCIpLCBtYXliZUZyb20sIGV4cGVjdChcIjtcIikpO1xuICAgIHJldHVybiBwYXNzKHN0YXRlbWVudCk7XG4gIH1cbiAgZnVuY3Rpb24gZXhwb3J0RmllbGQodHlwZSwgdmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPT0gXCJhc1wiKSB7IGN4Lm1hcmtlZCA9IFwia2V5d29yZFwiOyByZXR1cm4gY29udChleHBlY3QoXCJ2YXJpYWJsZVwiKSk7IH1cbiAgICBpZiAodHlwZSA9PSBcInZhcmlhYmxlXCIpIHJldHVybiBwYXNzKGV4cHJlc3Npb25Ob0NvbW1hLCBleHBvcnRGaWVsZCk7XG4gIH1cbiAgZnVuY3Rpb24gYWZ0ZXJJbXBvcnQodHlwZSkge1xuICAgIGlmICh0eXBlID09IFwic3RyaW5nXCIpIHJldHVybiBjb250KCk7XG4gICAgaWYgKHR5cGUgPT0gXCIoXCIpIHJldHVybiBwYXNzKGV4cHJlc3Npb24pO1xuICAgIGlmICh0eXBlID09IFwiLlwiKSByZXR1cm4gcGFzcyhtYXliZW9wZXJhdG9yQ29tbWEpO1xuICAgIHJldHVybiBwYXNzKGltcG9ydFNwZWMsIG1heWJlTW9yZUltcG9ydHMsIG1heWJlRnJvbSk7XG4gIH1cbiAgZnVuY3Rpb24gaW1wb3J0U3BlYyh0eXBlLCB2YWx1ZSkge1xuICAgIGlmICh0eXBlID09IFwie1wiKSByZXR1cm4gY29udENvbW1hc2VwKGltcG9ydFNwZWMsIFwifVwiKTtcbiAgICBpZiAodHlwZSA9PSBcInZhcmlhYmxlXCIpIHJlZ2lzdGVyKHZhbHVlKTtcbiAgICBpZiAodmFsdWUgPT0gXCIqXCIpIGN4Lm1hcmtlZCA9IFwia2V5d29yZFwiO1xuICAgIHJldHVybiBjb250KG1heWJlQXMpO1xuICB9XG4gIGZ1bmN0aW9uIG1heWJlTW9yZUltcG9ydHModHlwZSkge1xuICAgIGlmICh0eXBlID09IFwiLFwiKSByZXR1cm4gY29udChpbXBvcnRTcGVjLCBtYXliZU1vcmVJbXBvcnRzKVxuICB9XG4gIGZ1bmN0aW9uIG1heWJlQXMoX3R5cGUsIHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09IFwiYXNcIikgeyBjeC5tYXJrZWQgPSBcImtleXdvcmRcIjsgcmV0dXJuIGNvbnQoaW1wb3J0U3BlYyk7IH1cbiAgfVxuICBmdW5jdGlvbiBtYXliZUZyb20oX3R5cGUsIHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09IFwiZnJvbVwiKSB7IGN4Lm1hcmtlZCA9IFwia2V5d29yZFwiOyByZXR1cm4gY29udChleHByZXNzaW9uKTsgfVxuICB9XG4gIGZ1bmN0aW9uIGFycmF5TGl0ZXJhbCh0eXBlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCJdXCIpIHJldHVybiBjb250KCk7XG4gICAgcmV0dXJuIHBhc3MoY29tbWFzZXAoZXhwcmVzc2lvbk5vQ29tbWEsIFwiXVwiKSk7XG4gIH1cbiAgZnVuY3Rpb24gZW51bWRlZigpIHtcbiAgICByZXR1cm4gcGFzcyhwdXNobGV4KFwiZm9ybVwiKSwgcGF0dGVybiwgZXhwZWN0KFwie1wiKSwgcHVzaGxleChcIn1cIiksIGNvbW1hc2VwKGVudW1tZW1iZXIsIFwifVwiKSwgcG9wbGV4LCBwb3BsZXgpXG4gIH1cbiAgZnVuY3Rpb24gZW51bW1lbWJlcigpIHtcbiAgICByZXR1cm4gcGFzcyhwYXR0ZXJuLCBtYXliZUFzc2lnbik7XG4gIH1cblxuICBmdW5jdGlvbiBpc0NvbnRpbnVlZFN0YXRlbWVudChzdGF0ZSwgdGV4dEFmdGVyKSB7XG4gICAgcmV0dXJuIHN0YXRlLmxhc3RUeXBlID09IFwib3BlcmF0b3JcIiB8fCBzdGF0ZS5sYXN0VHlwZSA9PSBcIixcIiB8fFxuICAgICAgaXNPcGVyYXRvckNoYXIudGVzdCh0ZXh0QWZ0ZXIuY2hhckF0KDApKSB8fFxuICAgICAgL1ssLl0vLnRlc3QodGV4dEFmdGVyLmNoYXJBdCgwKSk7XG4gIH1cblxuICBmdW5jdGlvbiBleHByZXNzaW9uQWxsb3dlZChzdHJlYW0sIHN0YXRlLCBiYWNrVXApIHtcbiAgICByZXR1cm4gc3RhdGUudG9rZW5pemUgPT0gdG9rZW5CYXNlICYmXG4gICAgICAvXig/Om9wZXJhdG9yfHNvZnxrZXl3b3JkIFtiY2RdfGNhc2V8bmV3fGV4cG9ydHxkZWZhdWx0fHNwcmVhZHxbXFxbe31cXCgsOzpdfD0+KSQvLnRlc3Qoc3RhdGUubGFzdFR5cGUpIHx8XG4gICAgICAoc3RhdGUubGFzdFR5cGUgPT0gXCJxdWFzaVwiICYmIC9cXHtcXHMqJC8udGVzdChzdHJlYW0uc3RyaW5nLnNsaWNlKDAsIHN0cmVhbS5wb3MgLSAoYmFja1VwIHx8IDApKSkpXG4gIH1cblxuICAvLyBJbnRlcmZhY2VcblxuICByZXR1cm4ge1xuICAgIHN0YXJ0U3RhdGU6IGZ1bmN0aW9uKGJhc2Vjb2x1bW4pIHtcbiAgICAgIHZhciBzdGF0ZSA9IHtcbiAgICAgICAgdG9rZW5pemU6IHRva2VuQmFzZSxcbiAgICAgICAgbGFzdFR5cGU6IFwic29mXCIsXG4gICAgICAgIGNjOiBbXSxcbiAgICAgICAgbGV4aWNhbDogbmV3IEpTTGV4aWNhbCgoYmFzZWNvbHVtbiB8fCAwKSAtIGluZGVudFVuaXQsIDAsIFwiYmxvY2tcIiwgZmFsc2UpLFxuICAgICAgICBsb2NhbFZhcnM6IHBhcnNlckNvbmZpZy5sb2NhbFZhcnMsXG4gICAgICAgIGNvbnRleHQ6IHBhcnNlckNvbmZpZy5sb2NhbFZhcnMgJiYgbmV3IENvbnRleHQobnVsbCwgbnVsbCwgZmFsc2UpLFxuICAgICAgICBpbmRlbnRlZDogYmFzZWNvbHVtbiB8fCAwXG4gICAgICB9O1xuICAgICAgaWYgKHBhcnNlckNvbmZpZy5nbG9iYWxWYXJzICYmIHR5cGVvZiBwYXJzZXJDb25maWcuZ2xvYmFsVmFycyA9PSBcIm9iamVjdFwiKVxuICAgICAgICBzdGF0ZS5nbG9iYWxWYXJzID0gcGFyc2VyQ29uZmlnLmdsb2JhbFZhcnM7XG4gICAgICByZXR1cm4gc3RhdGU7XG4gICAgfSxcblxuICAgIHRva2VuOiBmdW5jdGlvbihzdHJlYW0sIHN0YXRlKSB7XG4gICAgICBpZiAoc3RyZWFtLnNvbCgpKSB7XG4gICAgICAgIGlmICghc3RhdGUubGV4aWNhbC5oYXNPd25Qcm9wZXJ0eShcImFsaWduXCIpKVxuICAgICAgICAgIHN0YXRlLmxleGljYWwuYWxpZ24gPSBmYWxzZTtcbiAgICAgICAgc3RhdGUuaW5kZW50ZWQgPSBzdHJlYW0uaW5kZW50YXRpb24oKTtcbiAgICAgICAgZmluZEZhdEFycm93KHN0cmVhbSwgc3RhdGUpO1xuICAgICAgfVxuICAgICAgaWYgKHN0YXRlLnRva2VuaXplICE9IHRva2VuQ29tbWVudCAmJiBzdHJlYW0uZWF0U3BhY2UoKSkgcmV0dXJuIG51bGw7XG4gICAgICB2YXIgc3R5bGUgPSBzdGF0ZS50b2tlbml6ZShzdHJlYW0sIHN0YXRlKTtcbiAgICAgIGlmICh0eXBlID09IFwiY29tbWVudFwiKSByZXR1cm4gc3R5bGU7XG4gICAgICBzdGF0ZS5sYXN0VHlwZSA9IHR5cGUgPT0gXCJvcGVyYXRvclwiICYmIChjb250ZW50ID09IFwiKytcIiB8fCBjb250ZW50ID09IFwiLS1cIikgPyBcImluY2RlY1wiIDogdHlwZTtcbiAgICAgIHJldHVybiBwYXJzZUpTKHN0YXRlLCBzdHlsZSwgdHlwZSwgY29udGVudCwgc3RyZWFtKTtcbiAgICB9LFxuXG4gICAgaW5kZW50OiBmdW5jdGlvbihzdGF0ZSwgdGV4dEFmdGVyKSB7XG4gICAgICBpZiAoc3RhdGUudG9rZW5pemUgPT0gdG9rZW5Db21tZW50IHx8IHN0YXRlLnRva2VuaXplID09IHRva2VuUXVhc2kpIHJldHVybiBDb2RlTWlycm9yLlBhc3M7XG4gICAgICBpZiAoc3RhdGUudG9rZW5pemUgIT0gdG9rZW5CYXNlKSByZXR1cm4gMDtcbiAgICAgIHZhciBmaXJzdENoYXIgPSB0ZXh0QWZ0ZXIgJiYgdGV4dEFmdGVyLmNoYXJBdCgwKSwgbGV4aWNhbCA9IHN0YXRlLmxleGljYWwsIHRvcFxuICAgICAgLy8gS2x1ZGdlIHRvIHByZXZlbnQgJ21heWJlbHNlJyBmcm9tIGJsb2NraW5nIGxleGljYWwgc2NvcGUgcG9wc1xuICAgICAgaWYgKCEvXlxccyplbHNlXFxiLy50ZXN0KHRleHRBZnRlcikpIGZvciAodmFyIGkgPSBzdGF0ZS5jYy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkge1xuICAgICAgICB2YXIgYyA9IHN0YXRlLmNjW2ldO1xuICAgICAgICBpZiAoYyA9PSBwb3BsZXgpIGxleGljYWwgPSBsZXhpY2FsLnByZXY7XG4gICAgICAgIGVsc2UgaWYgKGMgIT0gbWF5YmVlbHNlICYmIGMgIT0gcG9wY29udGV4dCkgYnJlYWs7XG4gICAgICB9XG4gICAgICB3aGlsZSAoKGxleGljYWwudHlwZSA9PSBcInN0YXRcIiB8fCBsZXhpY2FsLnR5cGUgPT0gXCJmb3JtXCIpICYmXG4gICAgICAgICAgICAgKGZpcnN0Q2hhciA9PSBcIn1cIiB8fCAoKHRvcCA9IHN0YXRlLmNjW3N0YXRlLmNjLmxlbmd0aCAtIDFdKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodG9wID09IG1heWJlb3BlcmF0b3JDb21tYSB8fCB0b3AgPT0gbWF5YmVvcGVyYXRvck5vQ29tbWEpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICEvXlssXFwuPStcXC0qOj9bXFwoXS8udGVzdCh0ZXh0QWZ0ZXIpKSkpXG4gICAgICAgIGxleGljYWwgPSBsZXhpY2FsLnByZXY7XG4gICAgICBpZiAoc3RhdGVtZW50SW5kZW50ICYmIGxleGljYWwudHlwZSA9PSBcIilcIiAmJiBsZXhpY2FsLnByZXYudHlwZSA9PSBcInN0YXRcIilcbiAgICAgICAgbGV4aWNhbCA9IGxleGljYWwucHJldjtcbiAgICAgIHZhciB0eXBlID0gbGV4aWNhbC50eXBlLCBjbG9zaW5nID0gZmlyc3RDaGFyID09IHR5cGU7XG5cbiAgICAgIGlmICh0eXBlID09IFwidmFyZGVmXCIpIHJldHVybiBsZXhpY2FsLmluZGVudGVkICsgKHN0YXRlLmxhc3RUeXBlID09IFwib3BlcmF0b3JcIiB8fCBzdGF0ZS5sYXN0VHlwZSA9PSBcIixcIiA/IGxleGljYWwuaW5mby5sZW5ndGggKyAxIDogMCk7XG4gICAgICBlbHNlIGlmICh0eXBlID09IFwiZm9ybVwiICYmIGZpcnN0Q2hhciA9PSBcIntcIikgcmV0dXJuIGxleGljYWwuaW5kZW50ZWQ7XG4gICAgICBlbHNlIGlmICh0eXBlID09IFwiZm9ybVwiKSByZXR1cm4gbGV4aWNhbC5pbmRlbnRlZCArIGluZGVudFVuaXQ7XG4gICAgICBlbHNlIGlmICh0eXBlID09IFwic3RhdFwiKVxuICAgICAgICByZXR1cm4gbGV4aWNhbC5pbmRlbnRlZCArIChpc0NvbnRpbnVlZFN0YXRlbWVudChzdGF0ZSwgdGV4dEFmdGVyKSA/IHN0YXRlbWVudEluZGVudCB8fCBpbmRlbnRVbml0IDogMCk7XG4gICAgICBlbHNlIGlmIChsZXhpY2FsLmluZm8gPT0gXCJzd2l0Y2hcIiAmJiAhY2xvc2luZyAmJiBwYXJzZXJDb25maWcuZG91YmxlSW5kZW50U3dpdGNoICE9IGZhbHNlKVxuICAgICAgICByZXR1cm4gbGV4aWNhbC5pbmRlbnRlZCArICgvXig/OmNhc2V8ZGVmYXVsdClcXGIvLnRlc3QodGV4dEFmdGVyKSA/IGluZGVudFVuaXQgOiAyICogaW5kZW50VW5pdCk7XG4gICAgICBlbHNlIGlmIChsZXhpY2FsLmFsaWduKSByZXR1cm4gbGV4aWNhbC5jb2x1bW4gKyAoY2xvc2luZyA/IDAgOiAxKTtcbiAgICAgIGVsc2UgcmV0dXJuIGxleGljYWwuaW5kZW50ZWQgKyAoY2xvc2luZyA/IDAgOiBpbmRlbnRVbml0KTtcbiAgICB9LFxuXG4gICAgZWxlY3RyaWNJbnB1dDogL15cXHMqKD86Y2FzZSAuKj86fGRlZmF1bHQ6fFxce3xcXH0pJC8sXG4gICAgYmxvY2tDb21tZW50U3RhcnQ6IGpzb25Nb2RlID8gbnVsbCA6IFwiLypcIixcbiAgICBibG9ja0NvbW1lbnRFbmQ6IGpzb25Nb2RlID8gbnVsbCA6IFwiKi9cIixcbiAgICBibG9ja0NvbW1lbnRDb250aW51ZToganNvbk1vZGUgPyBudWxsIDogXCIgKiBcIixcbiAgICBsaW5lQ29tbWVudDoganNvbk1vZGUgPyBudWxsIDogXCIvL1wiLFxuICAgIGZvbGQ6IFwiYnJhY2VcIixcbiAgICBjbG9zZUJyYWNrZXRzOiBcIigpW117fScnXFxcIlxcXCJgYFwiLFxuXG4gICAgaGVscGVyVHlwZToganNvbk1vZGUgPyBcImpzb25cIiA6IFwiamF2YXNjcmlwdFwiLFxuICAgIGpzb25sZE1vZGU6IGpzb25sZE1vZGUsXG4gICAganNvbk1vZGU6IGpzb25Nb2RlLFxuXG4gICAgZXhwcmVzc2lvbkFsbG93ZWQ6IGV4cHJlc3Npb25BbGxvd2VkLFxuXG4gICAgc2tpcEV4cHJlc3Npb246IGZ1bmN0aW9uKHN0YXRlKSB7XG4gICAgICBwYXJzZUpTKHN0YXRlLCBcImF0b21cIiwgXCJhdG9tXCIsIFwidHJ1ZVwiLCBuZXcgQ29kZU1pcnJvci5TdHJpbmdTdHJlYW0oXCJcIiwgMiwgbnVsbCkpXG4gICAgfVxuICB9O1xufSk7XG5cbkNvZGVNaXJyb3IucmVnaXN0ZXJIZWxwZXIoXCJ3b3JkQ2hhcnNcIiwgXCJqYXZhc2NyaXB0XCIsIC9bXFx3JF0vKTtcblxuQ29kZU1pcnJvci5kZWZpbmVNSU1FKFwidGV4dC9qYXZhc2NyaXB0XCIsIFwiamF2YXNjcmlwdFwiKTtcbkNvZGVNaXJyb3IuZGVmaW5lTUlNRShcInRleHQvZWNtYXNjcmlwdFwiLCBcImphdmFzY3JpcHRcIik7XG5Db2RlTWlycm9yLmRlZmluZU1JTUUoXCJhcHBsaWNhdGlvbi9qYXZhc2NyaXB0XCIsIFwiamF2YXNjcmlwdFwiKTtcbkNvZGVNaXJyb3IuZGVmaW5lTUlNRShcImFwcGxpY2F0aW9uL3gtamF2YXNjcmlwdFwiLCBcImphdmFzY3JpcHRcIik7XG5Db2RlTWlycm9yLmRlZmluZU1JTUUoXCJhcHBsaWNhdGlvbi9lY21hc2NyaXB0XCIsIFwiamF2YXNjcmlwdFwiKTtcbkNvZGVNaXJyb3IuZGVmaW5lTUlNRShcImFwcGxpY2F0aW9uL2pzb25cIiwgeyBuYW1lOiBcImphdmFzY3JpcHRcIiwganNvbjogdHJ1ZSB9KTtcbkNvZGVNaXJyb3IuZGVmaW5lTUlNRShcImFwcGxpY2F0aW9uL3gtanNvblwiLCB7IG5hbWU6IFwiamF2YXNjcmlwdFwiLCBqc29uOiB0cnVlIH0pO1xuQ29kZU1pcnJvci5kZWZpbmVNSU1FKFwiYXBwbGljYXRpb24vbWFuaWZlc3QranNvblwiLCB7IG5hbWU6IFwiamF2YXNjcmlwdFwiLCBqc29uOiB0cnVlIH0pXG5Db2RlTWlycm9yLmRlZmluZU1JTUUoXCJhcHBsaWNhdGlvbi9sZCtqc29uXCIsIHsgbmFtZTogXCJqYXZhc2NyaXB0XCIsIGpzb25sZDogdHJ1ZSB9KTtcbkNvZGVNaXJyb3IuZGVmaW5lTUlNRShcInRleHQvdHlwZXNjcmlwdFwiLCB7IG5hbWU6IFwiamF2YXNjcmlwdFwiLCB0eXBlc2NyaXB0OiB0cnVlIH0pO1xuQ29kZU1pcnJvci5kZWZpbmVNSU1FKFwiYXBwbGljYXRpb24vdHlwZXNjcmlwdFwiLCB7IG5hbWU6IFwiamF2YXNjcmlwdFwiLCB0eXBlc2NyaXB0OiB0cnVlIH0pO1xuXG59KTtcbiIsIi8vIENvZGVNaXJyb3IsIGNvcHlyaWdodCAoYykgYnkgTWFyaWpuIEhhdmVyYmVrZSBhbmQgb3RoZXJzXG4vLyBEaXN0cmlidXRlZCB1bmRlciBhbiBNSVQgbGljZW5zZTogaHR0cHM6Ly9jb2RlbWlycm9yLm5ldC9MSUNFTlNFXG5cbihmdW5jdGlvbihtb2QpIHtcbiAgaWYgKHR5cGVvZiBleHBvcnRzID09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZSA9PSBcIm9iamVjdFwiKSAvLyBDb21tb25KU1xuICAgIG1vZChyZXF1aXJlKFwiLi4vLi4vbGliL2NvZGVtaXJyb3JcIiksIHJlcXVpcmUoXCIuLi9odG1sbWl4ZWQvaHRtbG1peGVkXCIpLCByZXF1aXJlKFwiLi4vY2xpa2UvY2xpa2VcIikpO1xuICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSAvLyBBTURcbiAgICBkZWZpbmUoW1wiLi4vLi4vbGliL2NvZGVtaXJyb3JcIiwgXCIuLi9odG1sbWl4ZWQvaHRtbG1peGVkXCIsIFwiLi4vY2xpa2UvY2xpa2VcIl0sIG1vZCk7XG4gIGVsc2UgLy8gUGxhaW4gYnJvd3NlciBlbnZcbiAgICBtb2QoQ29kZU1pcnJvcik7XG59KShmdW5jdGlvbihDb2RlTWlycm9yKSB7XG4gIFwidXNlIHN0cmljdFwiO1xuXG4gIGZ1bmN0aW9uIGtleXdvcmRzKHN0cikge1xuICAgIHZhciBvYmogPSB7fSwgd29yZHMgPSBzdHIuc3BsaXQoXCIgXCIpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgd29yZHMubGVuZ3RoOyArK2kpIG9ialt3b3Jkc1tpXV0gPSB0cnVlO1xuICAgIHJldHVybiBvYmo7XG4gIH1cblxuICAvLyBIZWxwZXIgZm9yIHBocFN0cmluZ1xuICBmdW5jdGlvbiBtYXRjaFNlcXVlbmNlKGxpc3QsIGVuZCwgZXNjYXBlcykge1xuICAgIGlmIChsaXN0Lmxlbmd0aCA9PSAwKSByZXR1cm4gcGhwU3RyaW5nKGVuZCk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChzdHJlYW0sIHN0YXRlKSB7XG4gICAgICB2YXIgcGF0dGVybnMgPSBsaXN0WzBdO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXR0ZXJucy5sZW5ndGg7IGkrKykgaWYgKHN0cmVhbS5tYXRjaChwYXR0ZXJuc1tpXVswXSkpIHtcbiAgICAgICAgc3RhdGUudG9rZW5pemUgPSBtYXRjaFNlcXVlbmNlKGxpc3Quc2xpY2UoMSksIGVuZCk7XG4gICAgICAgIHJldHVybiBwYXR0ZXJuc1tpXVsxXTtcbiAgICAgIH1cbiAgICAgIHN0YXRlLnRva2VuaXplID0gcGhwU3RyaW5nKGVuZCwgZXNjYXBlcyk7XG4gICAgICByZXR1cm4gXCJzdHJpbmdcIjtcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIHBocFN0cmluZyhjbG9zaW5nLCBlc2NhcGVzKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHN0cmVhbSwgc3RhdGUpIHsgcmV0dXJuIHBocFN0cmluZ18oc3RyZWFtLCBzdGF0ZSwgY2xvc2luZywgZXNjYXBlcyk7IH07XG4gIH1cbiAgZnVuY3Rpb24gcGhwU3RyaW5nXyhzdHJlYW0sIHN0YXRlLCBjbG9zaW5nLCBlc2NhcGVzKSB7XG4gICAgLy8gXCJDb21wbGV4XCIgc3ludGF4XG4gICAgaWYgKGVzY2FwZXMgIT09IGZhbHNlICYmIHN0cmVhbS5tYXRjaChcIiR7XCIsIGZhbHNlKSB8fCBzdHJlYW0ubWF0Y2goXCJ7JFwiLCBmYWxzZSkpIHtcbiAgICAgIHN0YXRlLnRva2VuaXplID0gbnVsbDtcbiAgICAgIHJldHVybiBcInN0cmluZ1wiO1xuICAgIH1cblxuICAgIC8vIFNpbXBsZSBzeW50YXhcbiAgICBpZiAoZXNjYXBlcyAhPT0gZmFsc2UgJiYgc3RyZWFtLm1hdGNoKC9eXFwkW2EtekEtWl9dW2EtekEtWjAtOV9dKi8pKSB7XG4gICAgICAvLyBBZnRlciB0aGUgdmFyaWFibGUgbmFtZSB0aGVyZSBtYXkgYXBwZWFyIGFycmF5IG9yIG9iamVjdCBvcGVyYXRvci5cbiAgICAgIGlmIChzdHJlYW0ubWF0Y2goXCJbXCIsIGZhbHNlKSkge1xuICAgICAgICAvLyBNYXRjaCBhcnJheSBvcGVyYXRvclxuICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IG1hdGNoU2VxdWVuY2UoW1xuICAgICAgICAgIFtbXCJbXCIsIG51bGxdXSxcbiAgICAgICAgICBbWy9cXGRbXFx3XFwuXSovLCBcIm51bWJlclwiXSxcbiAgICAgICAgICAgWy9cXCRbYS16QS1aX11bYS16QS1aMC05X10qLywgXCJ2YXJpYWJsZS0yXCJdLFxuICAgICAgICAgICBbL1tcXHdcXCRdKy8sIFwidmFyaWFibGVcIl1dLFxuICAgICAgICAgIFtbXCJdXCIsIG51bGxdXVxuICAgICAgICBdLCBjbG9zaW5nLCBlc2NhcGVzKTtcbiAgICAgIH1cbiAgICAgIGlmIChzdHJlYW0ubWF0Y2goL14tPlxcdy8sIGZhbHNlKSkge1xuICAgICAgICAvLyBNYXRjaCBvYmplY3Qgb3BlcmF0b3JcbiAgICAgICAgc3RhdGUudG9rZW5pemUgPSBtYXRjaFNlcXVlbmNlKFtcbiAgICAgICAgICBbW1wiLT5cIiwgbnVsbF1dLFxuICAgICAgICAgIFtbL1tcXHddKy8sIFwidmFyaWFibGVcIl1dXG4gICAgICAgIF0sIGNsb3NpbmcsIGVzY2FwZXMpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFwidmFyaWFibGUtMlwiO1xuICAgIH1cblxuICAgIHZhciBlc2NhcGVkID0gZmFsc2U7XG4gICAgLy8gTm9ybWFsIHN0cmluZ1xuICAgIHdoaWxlICghc3RyZWFtLmVvbCgpICYmXG4gICAgICAgICAgIChlc2NhcGVkIHx8IGVzY2FwZXMgPT09IGZhbHNlIHx8XG4gICAgICAgICAgICAoIXN0cmVhbS5tYXRjaChcInskXCIsIGZhbHNlKSAmJlxuICAgICAgICAgICAgICFzdHJlYW0ubWF0Y2goL14oXFwkW2EtekEtWl9dW2EtekEtWjAtOV9dKnxcXCRcXHspLywgZmFsc2UpKSkpIHtcbiAgICAgIGlmICghZXNjYXBlZCAmJiBzdHJlYW0ubWF0Y2goY2xvc2luZykpIHtcbiAgICAgICAgc3RhdGUudG9rZW5pemUgPSBudWxsO1xuICAgICAgICBzdGF0ZS50b2tTdGFjay5wb3AoKTsgc3RhdGUudG9rU3RhY2sucG9wKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgZXNjYXBlZCA9IHN0cmVhbS5uZXh0KCkgPT0gXCJcXFxcXCIgJiYgIWVzY2FwZWQ7XG4gICAgfVxuICAgIHJldHVybiBcInN0cmluZ1wiO1xuICB9XG5cbiAgdmFyIHBocEtleXdvcmRzID0gXCJhYnN0cmFjdCBhbmQgYXJyYXkgYXMgYnJlYWsgY2FzZSBjYXRjaCBjbGFzcyBjbG9uZSBjb25zdCBjb250aW51ZSBkZWNsYXJlIGRlZmF1bHQgXCIgK1xuICAgIFwiZG8gZWxzZSBlbHNlaWYgZW5kZGVjbGFyZSBlbmRmb3IgZW5kZm9yZWFjaCBlbmRpZiBlbmRzd2l0Y2ggZW5kd2hpbGUgZW51bSBleHRlbmRzIGZpbmFsIFwiICtcbiAgICBcImZvciBmb3JlYWNoIGZ1bmN0aW9uIGdsb2JhbCBnb3RvIGlmIGltcGxlbWVudHMgaW50ZXJmYWNlIGluc3RhbmNlb2YgbmFtZXNwYWNlIFwiICtcbiAgICBcIm5ldyBvciBwcml2YXRlIHByb3RlY3RlZCBwdWJsaWMgc3RhdGljIHN3aXRjaCB0aHJvdyB0cmFpdCB0cnkgdXNlIHZhciB3aGlsZSB4b3IgXCIgK1xuICAgIFwiZGllIGVjaG8gZW1wdHkgZXhpdCBldmFsIGluY2x1ZGUgaW5jbHVkZV9vbmNlIGlzc2V0IGxpc3QgcmVxdWlyZSByZXF1aXJlX29uY2UgcmV0dXJuIFwiICtcbiAgICBcInByaW50IHVuc2V0IF9faGFsdF9jb21waWxlciBzZWxmIHN0YXRpYyBwYXJlbnQgeWllbGQgaW5zdGVhZG9mIGZpbmFsbHkgcmVhZG9ubHkgbWF0Y2hcIjtcbiAgdmFyIHBocEF0b21zID0gXCJ0cnVlIGZhbHNlIG51bGwgVFJVRSBGQUxTRSBOVUxMIF9fQ0xBU1NfXyBfX0RJUl9fIF9fRklMRV9fIF9fTElORV9fIF9fTUVUSE9EX18gX19GVU5DVElPTl9fIF9fTkFNRVNQQUNFX18gX19UUkFJVF9fXCI7XG4gIHZhciBwaHBCdWlsdGluID0gXCJmdW5jX251bV9hcmdzIGZ1bmNfZ2V0X2FyZyBmdW5jX2dldF9hcmdzIHN0cmxlbiBzdHJjbXAgc3RybmNtcCBzdHJjYXNlY21wIHN0cm5jYXNlY21wIGVhY2ggZXJyb3JfcmVwb3J0aW5nIGRlZmluZSBkZWZpbmVkIHRyaWdnZXJfZXJyb3IgdXNlcl9lcnJvciBzZXRfZXJyb3JfaGFuZGxlciByZXN0b3JlX2Vycm9yX2hhbmRsZXIgZ2V0X2RlY2xhcmVkX2NsYXNzZXMgZ2V0X2xvYWRlZF9leHRlbnNpb25zIGV4dGVuc2lvbl9sb2FkZWQgZ2V0X2V4dGVuc2lvbl9mdW5jcyBkZWJ1Z19iYWNrdHJhY2UgY29uc3RhbnQgYmluMmhleCBoZXgyYmluIHNsZWVwIHVzbGVlcCB0aW1lIG1rdGltZSBnbW1rdGltZSBzdHJmdGltZSBnbXN0cmZ0aW1lIHN0cnRvdGltZSBkYXRlIGdtZGF0ZSBnZXRkYXRlIGxvY2FsdGltZSBjaGVja2RhdGUgZmx1c2ggd29yZHdyYXAgaHRtbHNwZWNpYWxjaGFycyBodG1sZW50aXRpZXMgaHRtbF9lbnRpdHlfZGVjb2RlIG1kNSBtZDVfZmlsZSBjcmMzMiBnZXRpbWFnZXNpemUgaW1hZ2VfdHlwZV90b19taW1lX3R5cGUgcGhwaW5mbyBwaHB2ZXJzaW9uIHBocGNyZWRpdHMgc3RybmF0Y21wIHN0cm5hdGNhc2VjbXAgc3Vic3RyX2NvdW50IHN0cnNwbiBzdHJjc3BuIHN0cnRvayBzdHJ0b3VwcGVyIHN0cnRvbG93ZXIgc3RycG9zIHN0cnJwb3Mgc3RycmV2IGhlYnJldiBoZWJyZXZjIG5sMmJyIGJhc2VuYW1lIGRpcm5hbWUgcGF0aGluZm8gc3RyaXBzbGFzaGVzIHN0cmlwY3NsYXNoZXMgc3Ryc3RyIHN0cmlzdHIgc3RycmNociBzdHJfc2h1ZmZsZSBzdHJfd29yZF9jb3VudCBzdHJjb2xsIHN1YnN0ciBzdWJzdHJfcmVwbGFjZSBxdW90ZW1ldGEgdWNmaXJzdCB1Y3dvcmRzIHN0cnRyIGFkZHNsYXNoZXMgYWRkY3NsYXNoZXMgcnRyaW0gc3RyX3JlcGxhY2Ugc3RyX3JlcGVhdCBjb3VudF9jaGFycyBjaHVua19zcGxpdCB0cmltIGx0cmltIHN0cmlwX3RhZ3Mgc2ltaWxhcl90ZXh0IGV4cGxvZGUgaW1wbG9kZSBzZXRsb2NhbGUgbG9jYWxlY29udiBwYXJzZV9zdHIgc3RyX3BhZCBjaG9wIHN0cmNociBzcHJpbnRmIHByaW50ZiB2cHJpbnRmIHZzcHJpbnRmIHNzY2FuZiBmc2NhbmYgcGFyc2VfdXJsIHVybGVuY29kZSB1cmxkZWNvZGUgcmF3dXJsZW5jb2RlIHJhd3VybGRlY29kZSByZWFkbGluayBsaW5raW5mbyBsaW5rIHVubGluayBleGVjIHN5c3RlbSBlc2NhcGVzaGVsbGNtZCBlc2NhcGVzaGVsbGFyZyBwYXNzdGhydSBzaGVsbF9leGVjIHByb2Nfb3BlbiBwcm9jX2Nsb3NlIHJhbmQgc3JhbmQgZ2V0cmFuZG1heCBtdF9yYW5kIG10X3NyYW5kIG10X2dldHJhbmRtYXggYmFzZTY0X2RlY29kZSBiYXNlNjRfZW5jb2RlIGFicyBjZWlsIGZsb29yIHJvdW5kIGlzX2Zpbml0ZSBpc19uYW4gaXNfaW5maW5pdGUgYmluZGVjIGhleGRlYyBvY3RkZWMgZGVjYmluIGRlY29jdCBkZWNoZXggYmFzZV9jb252ZXJ0IG51bWJlcl9mb3JtYXQgZm1vZCBpcDJsb25nIGxvbmcyaXAgZ2V0ZW52IHB1dGVudiBnZXRvcHQgbWljcm90aW1lIGdldHRpbWVvZmRheSBnZXRydXNhZ2UgdW5pcWlkIHF1b3RlZF9wcmludGFibGVfZGVjb2RlIHNldF90aW1lX2xpbWl0IGdldF9jZmdfdmFyIG1hZ2ljX3F1b3Rlc19ydW50aW1lIHNldF9tYWdpY19xdW90ZXNfcnVudGltZSBnZXRfbWFnaWNfcXVvdGVzX2dwYyBnZXRfbWFnaWNfcXVvdGVzX3J1bnRpbWUgaW1wb3J0X3JlcXVlc3RfdmFyaWFibGVzIGVycm9yX2xvZyBzZXJpYWxpemUgdW5zZXJpYWxpemUgbWVtb3J5X2dldF91c2FnZSBtZW1vcnlfZ2V0X3BlYWtfdXNhZ2UgdmFyX2R1bXAgdmFyX2V4cG9ydCBkZWJ1Z196dmFsX2R1bXAgcHJpbnRfciBoaWdobGlnaHRfZmlsZSBzaG93X3NvdXJjZSBoaWdobGlnaHRfc3RyaW5nIGluaV9nZXQgaW5pX2dldF9hbGwgaW5pX3NldCBpbmlfYWx0ZXIgaW5pX3Jlc3RvcmUgZ2V0X2luY2x1ZGVfcGF0aCBzZXRfaW5jbHVkZV9wYXRoIHJlc3RvcmVfaW5jbHVkZV9wYXRoIHNldGNvb2tpZSBoZWFkZXIgaGVhZGVyc19zZW50IGNvbm5lY3Rpb25fYWJvcnRlZCBjb25uZWN0aW9uX3N0YXR1cyBpZ25vcmVfdXNlcl9hYm9ydCBwYXJzZV9pbmlfZmlsZSBpc191cGxvYWRlZF9maWxlIG1vdmVfdXBsb2FkZWRfZmlsZSBpbnR2YWwgZmxvYXR2YWwgZG91YmxldmFsIHN0cnZhbCBnZXR0eXBlIHNldHR5cGUgaXNfbnVsbCBpc19yZXNvdXJjZSBpc19ib29sIGlzX2xvbmcgaXNfZmxvYXQgaXNfaW50IGlzX2ludGVnZXIgaXNfZG91YmxlIGlzX3JlYWwgaXNfbnVtZXJpYyBpc19zdHJpbmcgaXNfYXJyYXkgaXNfb2JqZWN0IGlzX3NjYWxhciBlcmVnIGVyZWdfcmVwbGFjZSBlcmVnaSBlcmVnaV9yZXBsYWNlIHNwbGl0IHNwbGl0aSBqb2luIHNxbF9yZWdjYXNlIGRsIHBjbG9zZSBwb3BlbiByZWFkZmlsZSByZXdpbmQgcm1kaXIgdW1hc2sgZmNsb3NlIGZlb2YgZmdldGMgZmdldHMgZmdldHNzIGZyZWFkIGZvcGVuIGZwYXNzdGhydSBmdHJ1bmNhdGUgZnN0YXQgZnNlZWsgZnRlbGwgZmZsdXNoIGZ3cml0ZSBmcHV0cyBta2RpciByZW5hbWUgY29weSB0ZW1wbmFtIHRtcGZpbGUgZmlsZSBmaWxlX2dldF9jb250ZW50cyBmaWxlX3B1dF9jb250ZW50cyBzdHJlYW1fc2VsZWN0IHN0cmVhbV9jb250ZXh0X2NyZWF0ZSBzdHJlYW1fY29udGV4dF9zZXRfcGFyYW1zIHN0cmVhbV9jb250ZXh0X3NldF9vcHRpb24gc3RyZWFtX2NvbnRleHRfZ2V0X29wdGlvbnMgc3RyZWFtX2ZpbHRlcl9wcmVwZW5kIHN0cmVhbV9maWx0ZXJfYXBwZW5kIGZnZXRjc3YgZmxvY2sgZ2V0X21ldGFfdGFncyBzdHJlYW1fc2V0X3dyaXRlX2J1ZmZlciBzZXRfZmlsZV9idWZmZXIgc2V0X3NvY2tldF9ibG9ja2luZyBzdHJlYW1fc2V0X2Jsb2NraW5nIHNvY2tldF9zZXRfYmxvY2tpbmcgc3RyZWFtX2dldF9tZXRhX2RhdGEgc3RyZWFtX3JlZ2lzdGVyX3dyYXBwZXIgc3RyZWFtX3dyYXBwZXJfcmVnaXN0ZXIgc3RyZWFtX3NldF90aW1lb3V0IHNvY2tldF9zZXRfdGltZW91dCBzb2NrZXRfZ2V0X3N0YXR1cyByZWFscGF0aCBmbm1hdGNoIGZzb2Nrb3BlbiBwZnNvY2tvcGVuIHBhY2sgdW5wYWNrIGdldF9icm93c2VyIGNyeXB0IG9wZW5kaXIgY2xvc2VkaXIgY2hkaXIgZ2V0Y3dkIHJld2luZGRpciByZWFkZGlyIGRpciBnbG9iIGZpbGVhdGltZSBmaWxlY3RpbWUgZmlsZWdyb3VwIGZpbGVpbm9kZSBmaWxlbXRpbWUgZmlsZW93bmVyIGZpbGVwZXJtcyBmaWxlc2l6ZSBmaWxldHlwZSBmaWxlX2V4aXN0cyBpc193cml0YWJsZSBpc193cml0ZWFibGUgaXNfcmVhZGFibGUgaXNfZXhlY3V0YWJsZSBpc19maWxlIGlzX2RpciBpc19saW5rIHN0YXQgbHN0YXQgY2hvd24gdG91Y2ggY2xlYXJzdGF0Y2FjaGUgbWFpbCBvYl9zdGFydCBvYl9mbHVzaCBvYl9jbGVhbiBvYl9lbmRfZmx1c2ggb2JfZW5kX2NsZWFuIG9iX2dldF9mbHVzaCBvYl9nZXRfY2xlYW4gb2JfZ2V0X2xlbmd0aCBvYl9nZXRfbGV2ZWwgb2JfZ2V0X3N0YXR1cyBvYl9nZXRfY29udGVudHMgb2JfaW1wbGljaXRfZmx1c2ggb2JfbGlzdF9oYW5kbGVycyBrc29ydCBrcnNvcnQgbmF0c29ydCBuYXRjYXNlc29ydCBhc29ydCBhcnNvcnQgc29ydCByc29ydCB1c29ydCB1YXNvcnQgdWtzb3J0IHNodWZmbGUgYXJyYXlfd2FsayBjb3VudCBlbmQgcHJldiBuZXh0IHJlc2V0IGN1cnJlbnQga2V5IG1pbiBtYXggaW5fYXJyYXkgYXJyYXlfc2VhcmNoIGV4dHJhY3QgY29tcGFjdCBhcnJheV9maWxsIHJhbmdlIGFycmF5X211bHRpc29ydCBhcnJheV9wdXNoIGFycmF5X3BvcCBhcnJheV9zaGlmdCBhcnJheV91bnNoaWZ0IGFycmF5X3NwbGljZSBhcnJheV9zbGljZSBhcnJheV9tZXJnZSBhcnJheV9tZXJnZV9yZWN1cnNpdmUgYXJyYXlfa2V5cyBhcnJheV92YWx1ZXMgYXJyYXlfY291bnRfdmFsdWVzIGFycmF5X3JldmVyc2UgYXJyYXlfcmVkdWNlIGFycmF5X3BhZCBhcnJheV9mbGlwIGFycmF5X2NoYW5nZV9rZXlfY2FzZSBhcnJheV9yYW5kIGFycmF5X3VuaXF1ZSBhcnJheV9pbnRlcnNlY3QgYXJyYXlfaW50ZXJzZWN0X2Fzc29jIGFycmF5X2RpZmYgYXJyYXlfZGlmZl9hc3NvYyBhcnJheV9zdW0gYXJyYXlfZmlsdGVyIGFycmF5X21hcCBhcnJheV9jaHVuayBhcnJheV9rZXlfZXhpc3RzIGFycmF5X2ludGVyc2VjdF9rZXkgYXJyYXlfY29tYmluZSBhcnJheV9jb2x1bW4gcG9zIHNpemVvZiBrZXlfZXhpc3RzIGFzc2VydCBhc3NlcnRfb3B0aW9ucyB2ZXJzaW9uX2NvbXBhcmUgZnRvayBzdHJfcm90MTMgYWdncmVnYXRlIHNlc3Npb25fbmFtZSBzZXNzaW9uX21vZHVsZV9uYW1lIHNlc3Npb25fc2F2ZV9wYXRoIHNlc3Npb25faWQgc2Vzc2lvbl9yZWdlbmVyYXRlX2lkIHNlc3Npb25fZGVjb2RlIHNlc3Npb25fcmVnaXN0ZXIgc2Vzc2lvbl91bnJlZ2lzdGVyIHNlc3Npb25faXNfcmVnaXN0ZXJlZCBzZXNzaW9uX2VuY29kZSBzZXNzaW9uX3N0YXJ0IHNlc3Npb25fZGVzdHJveSBzZXNzaW9uX3Vuc2V0IHNlc3Npb25fc2V0X3NhdmVfaGFuZGxlciBzZXNzaW9uX2NhY2hlX2xpbWl0ZXIgc2Vzc2lvbl9jYWNoZV9leHBpcmUgc2Vzc2lvbl9zZXRfY29va2llX3BhcmFtcyBzZXNzaW9uX2dldF9jb29raWVfcGFyYW1zIHNlc3Npb25fd3JpdGVfY2xvc2UgcHJlZ19tYXRjaCBwcmVnX21hdGNoX2FsbCBwcmVnX3JlcGxhY2UgcHJlZ19yZXBsYWNlX2NhbGxiYWNrIHByZWdfc3BsaXQgcHJlZ19xdW90ZSBwcmVnX2dyZXAgb3ZlcmxvYWQgY3R5cGVfYWxudW0gY3R5cGVfYWxwaGEgY3R5cGVfY250cmwgY3R5cGVfZGlnaXQgY3R5cGVfbG93ZXIgY3R5cGVfZ3JhcGggY3R5cGVfcHJpbnQgY3R5cGVfcHVuY3QgY3R5cGVfc3BhY2UgY3R5cGVfdXBwZXIgY3R5cGVfeGRpZ2l0IHZpcnR1YWwgYXBhY2hlX3JlcXVlc3RfaGVhZGVycyBhcGFjaGVfbm90ZSBhcGFjaGVfbG9va3VwX3VyaSBhcGFjaGVfY2hpbGRfdGVybWluYXRlIGFwYWNoZV9zZXRlbnYgYXBhY2hlX3Jlc3BvbnNlX2hlYWRlcnMgYXBhY2hlX2dldF92ZXJzaW9uIGdldGFsbGhlYWRlcnMgbXlzcWxfY29ubmVjdCBteXNxbF9wY29ubmVjdCBteXNxbF9jbG9zZSBteXNxbF9zZWxlY3RfZGIgbXlzcWxfY3JlYXRlX2RiIG15c3FsX2Ryb3BfZGIgbXlzcWxfcXVlcnkgbXlzcWxfdW5idWZmZXJlZF9xdWVyeSBteXNxbF9kYl9xdWVyeSBteXNxbF9saXN0X2RicyBteXNxbF9saXN0X3RhYmxlcyBteXNxbF9saXN0X2ZpZWxkcyBteXNxbF9saXN0X3Byb2Nlc3NlcyBteXNxbF9lcnJvciBteXNxbF9lcnJubyBteXNxbF9hZmZlY3RlZF9yb3dzIG15c3FsX2luc2VydF9pZCBteXNxbF9yZXN1bHQgbXlzcWxfbnVtX3Jvd3MgbXlzcWxfbnVtX2ZpZWxkcyBteXNxbF9mZXRjaF9yb3cgbXlzcWxfZmV0Y2hfYXJyYXkgbXlzcWxfZmV0Y2hfYXNzb2MgbXlzcWxfZmV0Y2hfb2JqZWN0IG15c3FsX2RhdGFfc2VlayBteXNxbF9mZXRjaF9sZW5ndGhzIG15c3FsX2ZldGNoX2ZpZWxkIG15c3FsX2ZpZWxkX3NlZWsgbXlzcWxfZnJlZV9yZXN1bHQgbXlzcWxfZmllbGRfbmFtZSBteXNxbF9maWVsZF90YWJsZSBteXNxbF9maWVsZF9sZW4gbXlzcWxfZmllbGRfdHlwZSBteXNxbF9maWVsZF9mbGFncyBteXNxbF9lc2NhcGVfc3RyaW5nIG15c3FsX3JlYWxfZXNjYXBlX3N0cmluZyBteXNxbF9zdGF0IG15c3FsX3RocmVhZF9pZCBteXNxbF9jbGllbnRfZW5jb2RpbmcgbXlzcWxfZ2V0X2NsaWVudF9pbmZvIG15c3FsX2dldF9ob3N0X2luZm8gbXlzcWxfZ2V0X3Byb3RvX2luZm8gbXlzcWxfZ2V0X3NlcnZlcl9pbmZvIG15c3FsX2luZm8gbXlzcWwgbXlzcWxfZmllbGRuYW1lIG15c3FsX2ZpZWxkdGFibGUgbXlzcWxfZmllbGRsZW4gbXlzcWxfZmllbGR0eXBlIG15c3FsX2ZpZWxkZmxhZ3MgbXlzcWxfc2VsZWN0ZGIgbXlzcWxfY3JlYXRlZGIgbXlzcWxfZHJvcGRiIG15c3FsX2ZyZWVyZXN1bHQgbXlzcWxfbnVtZmllbGRzIG15c3FsX251bXJvd3MgbXlzcWxfbGlzdGRicyBteXNxbF9saXN0dGFibGVzIG15c3FsX2xpc3RmaWVsZHMgbXlzcWxfZGJfbmFtZSBteXNxbF9kYm5hbWUgbXlzcWxfdGFibGVuYW1lIG15c3FsX3RhYmxlX25hbWUgcGdfY29ubmVjdCBwZ19wY29ubmVjdCBwZ19jbG9zZSBwZ19jb25uZWN0aW9uX3N0YXR1cyBwZ19jb25uZWN0aW9uX2J1c3kgcGdfY29ubmVjdGlvbl9yZXNldCBwZ19ob3N0IHBnX2RibmFtZSBwZ19wb3J0IHBnX3R0eSBwZ19vcHRpb25zIHBnX3BpbmcgcGdfcXVlcnkgcGdfc2VuZF9xdWVyeSBwZ19jYW5jZWxfcXVlcnkgcGdfZmV0Y2hfcmVzdWx0IHBnX2ZldGNoX3JvdyBwZ19mZXRjaF9hc3NvYyBwZ19mZXRjaF9hcnJheSBwZ19mZXRjaF9vYmplY3QgcGdfZmV0Y2hfYWxsIHBnX2FmZmVjdGVkX3Jvd3MgcGdfZ2V0X3Jlc3VsdCBwZ19yZXN1bHRfc2VlayBwZ19yZXN1bHRfc3RhdHVzIHBnX2ZyZWVfcmVzdWx0IHBnX2xhc3Rfb2lkIHBnX251bV9yb3dzIHBnX251bV9maWVsZHMgcGdfZmllbGRfbmFtZSBwZ19maWVsZF9udW0gcGdfZmllbGRfc2l6ZSBwZ19maWVsZF90eXBlIHBnX2ZpZWxkX3BydGxlbiBwZ19maWVsZF9pc19udWxsIHBnX2dldF9ub3RpZnkgcGdfZ2V0X3BpZCBwZ19yZXN1bHRfZXJyb3IgcGdfbGFzdF9lcnJvciBwZ19sYXN0X25vdGljZSBwZ19wdXRfbGluZSBwZ19lbmRfY29weSBwZ19jb3B5X3RvIHBnX2NvcHlfZnJvbSBwZ190cmFjZSBwZ191bnRyYWNlIHBnX2xvX2NyZWF0ZSBwZ19sb191bmxpbmsgcGdfbG9fb3BlbiBwZ19sb19jbG9zZSBwZ19sb19yZWFkIHBnX2xvX3dyaXRlIHBnX2xvX3JlYWRfYWxsIHBnX2xvX2ltcG9ydCBwZ19sb19leHBvcnQgcGdfbG9fc2VlayBwZ19sb190ZWxsIHBnX2VzY2FwZV9zdHJpbmcgcGdfZXNjYXBlX2J5dGVhIHBnX3VuZXNjYXBlX2J5dGVhIHBnX2NsaWVudF9lbmNvZGluZyBwZ19zZXRfY2xpZW50X2VuY29kaW5nIHBnX21ldGFfZGF0YSBwZ19jb252ZXJ0IHBnX2luc2VydCBwZ191cGRhdGUgcGdfZGVsZXRlIHBnX3NlbGVjdCBwZ19leGVjIHBnX2dldGxhc3RvaWQgcGdfY21kdHVwbGVzIHBnX2Vycm9ybWVzc2FnZSBwZ19udW1yb3dzIHBnX251bWZpZWxkcyBwZ19maWVsZG5hbWUgcGdfZmllbGRzaXplIHBnX2ZpZWxkdHlwZSBwZ19maWVsZG51bSBwZ19maWVsZHBydGxlbiBwZ19maWVsZGlzbnVsbCBwZ19mcmVlcmVzdWx0IHBnX3Jlc3VsdCBwZ19sb3JlYWRhbGwgcGdfbG9jcmVhdGUgcGdfbG91bmxpbmsgcGdfbG9vcGVuIHBnX2xvY2xvc2UgcGdfbG9yZWFkIHBnX2xvd3JpdGUgcGdfbG9pbXBvcnQgcGdfbG9leHBvcnQgaHR0cF9yZXNwb25zZV9jb2RlIGdldF9kZWNsYXJlZF90cmFpdHMgZ2V0aW1hZ2VzaXplZnJvbXN0cmluZyBzb2NrZXRfaW1wb3J0X3N0cmVhbSBzdHJlYW1fc2V0X2NodW5rX3NpemUgdHJhaXRfZXhpc3RzIGhlYWRlcl9yZWdpc3Rlcl9jYWxsYmFjayBjbGFzc191c2VzIHNlc3Npb25fc3RhdHVzIHNlc3Npb25fcmVnaXN0ZXJfc2h1dGRvd24gZWNobyBwcmludCBnbG9iYWwgc3RhdGljIGV4aXQgYXJyYXkgZW1wdHkgZXZhbCBpc3NldCB1bnNldCBkaWUgaW5jbHVkZSByZXF1aXJlIGluY2x1ZGVfb25jZSByZXF1aXJlX29uY2UganNvbl9kZWNvZGUganNvbl9lbmNvZGUganNvbl9sYXN0X2Vycm9yIGpzb25fbGFzdF9lcnJvcl9tc2cgY3VybF9jbG9zZSBjdXJsX2NvcHlfaGFuZGxlIGN1cmxfZXJybm8gY3VybF9lcnJvciBjdXJsX2VzY2FwZSBjdXJsX2V4ZWMgY3VybF9maWxlX2NyZWF0ZSBjdXJsX2dldGluZm8gY3VybF9pbml0IGN1cmxfbXVsdGlfYWRkX2hhbmRsZSBjdXJsX211bHRpX2Nsb3NlIGN1cmxfbXVsdGlfZXhlYyBjdXJsX211bHRpX2dldGNvbnRlbnQgY3VybF9tdWx0aV9pbmZvX3JlYWQgY3VybF9tdWx0aV9pbml0IGN1cmxfbXVsdGlfcmVtb3ZlX2hhbmRsZSBjdXJsX211bHRpX3NlbGVjdCBjdXJsX211bHRpX3NldG9wdCBjdXJsX211bHRpX3N0cmVycm9yIGN1cmxfcGF1c2UgY3VybF9yZXNldCBjdXJsX3NldG9wdF9hcnJheSBjdXJsX3NldG9wdCBjdXJsX3NoYXJlX2Nsb3NlIGN1cmxfc2hhcmVfaW5pdCBjdXJsX3NoYXJlX3NldG9wdCBjdXJsX3N0cmVycm9yIGN1cmxfdW5lc2NhcGUgY3VybF92ZXJzaW9uIG15c3FsaV9hZmZlY3RlZF9yb3dzIG15c3FsaV9hdXRvY29tbWl0IG15c3FsaV9jaGFuZ2VfdXNlciBteXNxbGlfY2hhcmFjdGVyX3NldF9uYW1lIG15c3FsaV9jbG9zZSBteXNxbGlfY29tbWl0IG15c3FsaV9jb25uZWN0X2Vycm5vIG15c3FsaV9jb25uZWN0X2Vycm9yIG15c3FsaV9jb25uZWN0IG15c3FsaV9kYXRhX3NlZWsgbXlzcWxpX2RlYnVnIG15c3FsaV9kdW1wX2RlYnVnX2luZm8gbXlzcWxpX2Vycm5vIG15c3FsaV9lcnJvcl9saXN0IG15c3FsaV9lcnJvciBteXNxbGlfZmV0Y2hfYWxsIG15c3FsaV9mZXRjaF9hcnJheSBteXNxbGlfZmV0Y2hfYXNzb2MgbXlzcWxpX2ZldGNoX2ZpZWxkX2RpcmVjdCBteXNxbGlfZmV0Y2hfZmllbGQgbXlzcWxpX2ZldGNoX2ZpZWxkcyBteXNxbGlfZmV0Y2hfbGVuZ3RocyBteXNxbGlfZmV0Y2hfb2JqZWN0IG15c3FsaV9mZXRjaF9yb3cgbXlzcWxpX2ZpZWxkX2NvdW50IG15c3FsaV9maWVsZF9zZWVrIG15c3FsaV9maWVsZF90ZWxsIG15c3FsaV9mcmVlX3Jlc3VsdCBteXNxbGlfZ2V0X2NoYXJzZXQgbXlzcWxpX2dldF9jbGllbnRfaW5mbyBteXNxbGlfZ2V0X2NsaWVudF9zdGF0cyBteXNxbGlfZ2V0X2NsaWVudF92ZXJzaW9uIG15c3FsaV9nZXRfY29ubmVjdGlvbl9zdGF0cyBteXNxbGlfZ2V0X2hvc3RfaW5mbyBteXNxbGlfZ2V0X3Byb3RvX2luZm8gbXlzcWxpX2dldF9zZXJ2ZXJfaW5mbyBteXNxbGlfZ2V0X3NlcnZlcl92ZXJzaW9uIG15c3FsaV9pbmZvIG15c3FsaV9pbml0IG15c3FsaV9pbnNlcnRfaWQgbXlzcWxpX2tpbGwgbXlzcWxpX21vcmVfcmVzdWx0cyBteXNxbGlfbXVsdGlfcXVlcnkgbXlzcWxpX25leHRfcmVzdWx0IG15c3FsaV9udW1fZmllbGRzIG15c3FsaV9udW1fcm93cyBteXNxbGlfb3B0aW9ucyBteXNxbGlfcGluZyBteXNxbGlfcHJlcGFyZSBteXNxbGlfcXVlcnkgbXlzcWxpX3JlYWxfY29ubmVjdCBteXNxbGlfcmVhbF9lc2NhcGVfc3RyaW5nIG15c3FsaV9yZWFsX3F1ZXJ5IG15c3FsaV9yZWFwX2FzeW5jX3F1ZXJ5IG15c3FsaV9yZWZyZXNoIG15c3FsaV9yb2xsYmFjayBteXNxbGlfc2VsZWN0X2RiIG15c3FsaV9zZXRfY2hhcnNldCBteXNxbGlfc2V0X2xvY2FsX2luZmlsZV9kZWZhdWx0IG15c3FsaV9zZXRfbG9jYWxfaW5maWxlX2hhbmRsZXIgbXlzcWxpX3NxbHN0YXRlIG15c3FsaV9zc2xfc2V0IG15c3FsaV9zdGF0IG15c3FsaV9zdG10X2luaXQgbXlzcWxpX3N0b3JlX3Jlc3VsdCBteXNxbGlfdGhyZWFkX2lkIG15c3FsaV90aHJlYWRfc2FmZSBteXNxbGlfdXNlX3Jlc3VsdCBteXNxbGlfd2FybmluZ19jb3VudFwiO1xuICBDb2RlTWlycm9yLnJlZ2lzdGVySGVscGVyKFwiaGludFdvcmRzXCIsIFwicGhwXCIsIFtwaHBLZXl3b3JkcywgcGhwQXRvbXMsIHBocEJ1aWx0aW5dLmpvaW4oXCIgXCIpLnNwbGl0KFwiIFwiKSk7XG4gIENvZGVNaXJyb3IucmVnaXN0ZXJIZWxwZXIoXCJ3b3JkQ2hhcnNcIiwgXCJwaHBcIiwgL1tcXHckXS8pO1xuXG4gIHZhciBwaHBDb25maWcgPSB7XG4gICAgbmFtZTogXCJjbGlrZVwiLFxuICAgIGhlbHBlclR5cGU6IFwicGhwXCIsXG4gICAga2V5d29yZHM6IGtleXdvcmRzKHBocEtleXdvcmRzKSxcbiAgICBibG9ja0tleXdvcmRzOiBrZXl3b3JkcyhcImNhdGNoIGRvIGVsc2UgZWxzZWlmIGZvciBmb3JlYWNoIGlmIHN3aXRjaCB0cnkgd2hpbGUgZmluYWxseVwiKSxcbiAgICBkZWZLZXl3b3Jkczoga2V5d29yZHMoXCJjbGFzcyBlbnVtIGZ1bmN0aW9uIGludGVyZmFjZSBuYW1lc3BhY2UgdHJhaXRcIiksXG4gICAgYXRvbXM6IGtleXdvcmRzKHBocEF0b21zKSxcbiAgICBidWlsdGluOiBrZXl3b3JkcyhwaHBCdWlsdGluKSxcbiAgICBtdWx0aUxpbmVTdHJpbmdzOiB0cnVlLFxuICAgIGhvb2tzOiB7XG4gICAgICBcIiRcIjogZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgIHN0cmVhbS5lYXRXaGlsZSgvW1xcd1xcJF9dLyk7XG4gICAgICAgIHJldHVybiBcInZhcmlhYmxlLTJcIjtcbiAgICAgIH0sXG4gICAgICBcIjxcIjogZnVuY3Rpb24oc3RyZWFtLCBzdGF0ZSkge1xuICAgICAgICB2YXIgYmVmb3JlO1xuICAgICAgICBpZiAoYmVmb3JlID0gc3RyZWFtLm1hdGNoKC9ePDxcXHMqLykpIHtcbiAgICAgICAgICB2YXIgcXVvdGVkID0gc3RyZWFtLmVhdCgvWydcIl0vKTtcbiAgICAgICAgICBzdHJlYW0uZWF0V2hpbGUoL1tcXHdcXC5dLyk7XG4gICAgICAgICAgdmFyIGRlbGltID0gc3RyZWFtLmN1cnJlbnQoKS5zbGljZShiZWZvcmVbMF0ubGVuZ3RoICsgKHF1b3RlZCA/IDIgOiAxKSk7XG4gICAgICAgICAgaWYgKHF1b3RlZCkgc3RyZWFtLmVhdChxdW90ZWQpO1xuICAgICAgICAgIGlmIChkZWxpbSkge1xuICAgICAgICAgICAgKHN0YXRlLnRva1N0YWNrIHx8IChzdGF0ZS50b2tTdGFjayA9IFtdKSkucHVzaChkZWxpbSwgMCk7XG4gICAgICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IHBocFN0cmluZyhkZWxpbSwgcXVvdGVkICE9IFwiJ1wiKTtcbiAgICAgICAgICAgIHJldHVybiBcInN0cmluZ1wiO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9LFxuICAgICAgXCIjXCI6IGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgICAgICB3aGlsZSAoIXN0cmVhbS5lb2woKSAmJiAhc3RyZWFtLm1hdGNoKFwiPz5cIiwgZmFsc2UpKSBzdHJlYW0ubmV4dCgpO1xuICAgICAgICByZXR1cm4gXCJjb21tZW50XCI7XG4gICAgICB9LFxuICAgICAgXCIvXCI6IGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgICAgICBpZiAoc3RyZWFtLmVhdChcIi9cIikpIHtcbiAgICAgICAgICB3aGlsZSAoIXN0cmVhbS5lb2woKSAmJiAhc3RyZWFtLm1hdGNoKFwiPz5cIiwgZmFsc2UpKSBzdHJlYW0ubmV4dCgpO1xuICAgICAgICAgIHJldHVybiBcImNvbW1lbnRcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9LFxuICAgICAgJ1wiJzogZnVuY3Rpb24oX3N0cmVhbSwgc3RhdGUpIHtcbiAgICAgICAgKHN0YXRlLnRva1N0YWNrIHx8IChzdGF0ZS50b2tTdGFjayA9IFtdKSkucHVzaCgnXCInLCAwKTtcbiAgICAgICAgc3RhdGUudG9rZW5pemUgPSBwaHBTdHJpbmcoJ1wiJyk7XG4gICAgICAgIHJldHVybiBcInN0cmluZ1wiO1xuICAgICAgfSxcbiAgICAgIFwie1wiOiBmdW5jdGlvbihfc3RyZWFtLCBzdGF0ZSkge1xuICAgICAgICBpZiAoc3RhdGUudG9rU3RhY2sgJiYgc3RhdGUudG9rU3RhY2subGVuZ3RoKVxuICAgICAgICAgIHN0YXRlLnRva1N0YWNrW3N0YXRlLnRva1N0YWNrLmxlbmd0aCAtIDFdKys7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH0sXG4gICAgICBcIn1cIjogZnVuY3Rpb24oX3N0cmVhbSwgc3RhdGUpIHtcbiAgICAgICAgaWYgKHN0YXRlLnRva1N0YWNrICYmIHN0YXRlLnRva1N0YWNrLmxlbmd0aCA+IDAgJiZcbiAgICAgICAgICAgICEtLXN0YXRlLnRva1N0YWNrW3N0YXRlLnRva1N0YWNrLmxlbmd0aCAtIDFdKSB7XG4gICAgICAgICAgc3RhdGUudG9rZW5pemUgPSBwaHBTdHJpbmcoc3RhdGUudG9rU3RhY2tbc3RhdGUudG9rU3RhY2subGVuZ3RoIC0gMl0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgQ29kZU1pcnJvci5kZWZpbmVNb2RlKFwicGhwXCIsIGZ1bmN0aW9uKGNvbmZpZywgcGFyc2VyQ29uZmlnKSB7XG4gICAgdmFyIGh0bWxNb2RlID0gQ29kZU1pcnJvci5nZXRNb2RlKGNvbmZpZywgKHBhcnNlckNvbmZpZyAmJiBwYXJzZXJDb25maWcuaHRtbE1vZGUpIHx8IFwidGV4dC9odG1sXCIpO1xuICAgIHZhciBwaHBNb2RlID0gQ29kZU1pcnJvci5nZXRNb2RlKGNvbmZpZywgcGhwQ29uZmlnKTtcblxuICAgIGZ1bmN0aW9uIGRpc3BhdGNoKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgIHZhciBpc1BIUCA9IHN0YXRlLmN1ck1vZGUgPT0gcGhwTW9kZTtcbiAgICAgIGlmIChzdHJlYW0uc29sKCkgJiYgc3RhdGUucGVuZGluZyAmJiBzdGF0ZS5wZW5kaW5nICE9ICdcIicgJiYgc3RhdGUucGVuZGluZyAhPSBcIidcIikgc3RhdGUucGVuZGluZyA9IG51bGw7XG4gICAgICBpZiAoIWlzUEhQKSB7XG4gICAgICAgIGlmIChzdHJlYW0ubWF0Y2goL148XFw/XFx3Ki8pKSB7XG4gICAgICAgICAgc3RhdGUuY3VyTW9kZSA9IHBocE1vZGU7XG4gICAgICAgICAgaWYgKCFzdGF0ZS5waHApIHN0YXRlLnBocCA9IENvZGVNaXJyb3Iuc3RhcnRTdGF0ZShwaHBNb2RlLCBodG1sTW9kZS5pbmRlbnQoc3RhdGUuaHRtbCwgXCJcIiwgXCJcIikpXG4gICAgICAgICAgc3RhdGUuY3VyU3RhdGUgPSBzdGF0ZS5waHA7XG4gICAgICAgICAgcmV0dXJuIFwibWV0YVwiO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdGF0ZS5wZW5kaW5nID09ICdcIicgfHwgc3RhdGUucGVuZGluZyA9PSBcIidcIikge1xuICAgICAgICAgIHdoaWxlICghc3RyZWFtLmVvbCgpICYmIHN0cmVhbS5uZXh0KCkgIT0gc3RhdGUucGVuZGluZykge31cbiAgICAgICAgICB2YXIgc3R5bGUgPSBcInN0cmluZ1wiO1xuICAgICAgICB9IGVsc2UgaWYgKHN0YXRlLnBlbmRpbmcgJiYgc3RyZWFtLnBvcyA8IHN0YXRlLnBlbmRpbmcuZW5kKSB7XG4gICAgICAgICAgc3RyZWFtLnBvcyA9IHN0YXRlLnBlbmRpbmcuZW5kO1xuICAgICAgICAgIHZhciBzdHlsZSA9IHN0YXRlLnBlbmRpbmcuc3R5bGU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHN0eWxlID0gaHRtbE1vZGUudG9rZW4oc3RyZWFtLCBzdGF0ZS5jdXJTdGF0ZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0YXRlLnBlbmRpbmcpIHN0YXRlLnBlbmRpbmcgPSBudWxsO1xuICAgICAgICB2YXIgY3VyID0gc3RyZWFtLmN1cnJlbnQoKSwgb3BlblBIUCA9IGN1ci5zZWFyY2goLzxcXD8vKSwgbTtcbiAgICAgICAgaWYgKG9wZW5QSFAgIT0gLTEpIHtcbiAgICAgICAgICBpZiAoc3R5bGUgPT0gXCJzdHJpbmdcIiAmJiAobSA9IGN1ci5tYXRjaCgvW1xcJ1xcXCJdJC8pKSAmJiAhL1xcPz4vLnRlc3QoY3VyKSkgc3RhdGUucGVuZGluZyA9IG1bMF07XG4gICAgICAgICAgZWxzZSBzdGF0ZS5wZW5kaW5nID0ge2VuZDogc3RyZWFtLnBvcywgc3R5bGU6IHN0eWxlfTtcbiAgICAgICAgICBzdHJlYW0uYmFja1VwKGN1ci5sZW5ndGggLSBvcGVuUEhQKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3R5bGU7XG4gICAgICB9IGVsc2UgaWYgKGlzUEhQICYmIHN0YXRlLnBocC50b2tlbml6ZSA9PSBudWxsICYmIHN0cmVhbS5tYXRjaChcIj8+XCIpKSB7XG4gICAgICAgIHN0YXRlLmN1ck1vZGUgPSBodG1sTW9kZTtcbiAgICAgICAgc3RhdGUuY3VyU3RhdGUgPSBzdGF0ZS5odG1sO1xuICAgICAgICBpZiAoIXN0YXRlLnBocC5jb250ZXh0LnByZXYpIHN0YXRlLnBocCA9IG51bGw7XG4gICAgICAgIHJldHVybiBcIm1ldGFcIjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBwaHBNb2RlLnRva2VuKHN0cmVhbSwgc3RhdGUuY3VyU3RhdGUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBzdGFydFN0YXRlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGh0bWwgPSBDb2RlTWlycm9yLnN0YXJ0U3RhdGUoaHRtbE1vZGUpXG4gICAgICAgIHZhciBwaHAgPSBwYXJzZXJDb25maWcuc3RhcnRPcGVuID8gQ29kZU1pcnJvci5zdGFydFN0YXRlKHBocE1vZGUpIDogbnVsbFxuICAgICAgICByZXR1cm4ge2h0bWw6IGh0bWwsXG4gICAgICAgICAgICAgICAgcGhwOiBwaHAsXG4gICAgICAgICAgICAgICAgY3VyTW9kZTogcGFyc2VyQ29uZmlnLnN0YXJ0T3BlbiA/IHBocE1vZGUgOiBodG1sTW9kZSxcbiAgICAgICAgICAgICAgICBjdXJTdGF0ZTogcGFyc2VyQ29uZmlnLnN0YXJ0T3BlbiA/IHBocCA6IGh0bWwsXG4gICAgICAgICAgICAgICAgcGVuZGluZzogbnVsbH07XG4gICAgICB9LFxuXG4gICAgICBjb3B5U3RhdGU6IGZ1bmN0aW9uKHN0YXRlKSB7XG4gICAgICAgIHZhciBodG1sID0gc3RhdGUuaHRtbCwgaHRtbE5ldyA9IENvZGVNaXJyb3IuY29weVN0YXRlKGh0bWxNb2RlLCBodG1sKSxcbiAgICAgICAgICAgIHBocCA9IHN0YXRlLnBocCwgcGhwTmV3ID0gcGhwICYmIENvZGVNaXJyb3IuY29weVN0YXRlKHBocE1vZGUsIHBocCksIGN1cjtcbiAgICAgICAgaWYgKHN0YXRlLmN1ck1vZGUgPT0gaHRtbE1vZGUpIGN1ciA9IGh0bWxOZXc7XG4gICAgICAgIGVsc2UgY3VyID0gcGhwTmV3O1xuICAgICAgICByZXR1cm4ge2h0bWw6IGh0bWxOZXcsIHBocDogcGhwTmV3LCBjdXJNb2RlOiBzdGF0ZS5jdXJNb2RlLCBjdXJTdGF0ZTogY3VyLFxuICAgICAgICAgICAgICAgIHBlbmRpbmc6IHN0YXRlLnBlbmRpbmd9O1xuICAgICAgfSxcblxuICAgICAgdG9rZW46IGRpc3BhdGNoLFxuXG4gICAgICBpbmRlbnQ6IGZ1bmN0aW9uKHN0YXRlLCB0ZXh0QWZ0ZXIsIGxpbmUpIHtcbiAgICAgICAgaWYgKChzdGF0ZS5jdXJNb2RlICE9IHBocE1vZGUgJiYgL15cXHMqPFxcLy8udGVzdCh0ZXh0QWZ0ZXIpKSB8fFxuICAgICAgICAgICAgKHN0YXRlLmN1ck1vZGUgPT0gcGhwTW9kZSAmJiAvXlxcPz4vLnRlc3QodGV4dEFmdGVyKSkpXG4gICAgICAgICAgcmV0dXJuIGh0bWxNb2RlLmluZGVudChzdGF0ZS5odG1sLCB0ZXh0QWZ0ZXIsIGxpbmUpO1xuICAgICAgICByZXR1cm4gc3RhdGUuY3VyTW9kZS5pbmRlbnQoc3RhdGUuY3VyU3RhdGUsIHRleHRBZnRlciwgbGluZSk7XG4gICAgICB9LFxuXG4gICAgICBibG9ja0NvbW1lbnRTdGFydDogXCIvKlwiLFxuICAgICAgYmxvY2tDb21tZW50RW5kOiBcIiovXCIsXG4gICAgICBsaW5lQ29tbWVudDogXCIvL1wiLFxuXG4gICAgICBpbm5lck1vZGU6IGZ1bmN0aW9uKHN0YXRlKSB7IHJldHVybiB7c3RhdGU6IHN0YXRlLmN1clN0YXRlLCBtb2RlOiBzdGF0ZS5jdXJNb2RlfTsgfVxuICAgIH07XG4gIH0sIFwiaHRtbG1peGVkXCIsIFwiY2xpa2VcIik7XG5cbiAgQ29kZU1pcnJvci5kZWZpbmVNSU1FKFwiYXBwbGljYXRpb24veC1odHRwZC1waHBcIiwgXCJwaHBcIik7XG4gIENvZGVNaXJyb3IuZGVmaW5lTUlNRShcImFwcGxpY2F0aW9uL3gtaHR0cGQtcGhwLW9wZW5cIiwge25hbWU6IFwicGhwXCIsIHN0YXJ0T3BlbjogdHJ1ZX0pO1xuICBDb2RlTWlycm9yLmRlZmluZU1JTUUoXCJ0ZXh0L3gtcGhwXCIsIHBocENvbmZpZyk7XG59KTtcbiIsIi8vIENvZGVNaXJyb3IsIGNvcHlyaWdodCAoYykgYnkgTWFyaWpuIEhhdmVyYmVrZSBhbmQgb3RoZXJzXG4vLyBEaXN0cmlidXRlZCB1bmRlciBhbiBNSVQgbGljZW5zZTogaHR0cHM6Ly9jb2RlbWlycm9yLm5ldC9MSUNFTlNFXG5cbihmdW5jdGlvbihtb2QpIHtcbiAgaWYgKHR5cGVvZiBleHBvcnRzID09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZSA9PSBcIm9iamVjdFwiKSAvLyBDb21tb25KU1xuICAgIG1vZChyZXF1aXJlKFwiLi4vLi4vbGliL2NvZGVtaXJyb3JcIiksICByZXF1aXJlKFwiLi4vLi4vYWRkb24vbW9kZS9tdWx0aXBsZXhcIikpO1xuICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSAvLyBBTURcbiAgICBkZWZpbmUoW1wiLi4vLi4vbGliL2NvZGVtaXJyb3JcIiwgXCIuLi8uLi9hZGRvbi9tb2RlL211bHRpcGxleFwiXSwgbW9kKTtcbiAgZWxzZSAvLyBQbGFpbiBicm93c2VyIGVudlxuICAgIG1vZChDb2RlTWlycm9yKTtcbn0pKGZ1bmN0aW9uKENvZGVNaXJyb3IpIHtcbiAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgQ29kZU1pcnJvci5kZWZpbmVNb2RlKFwidHdpZzppbm5lclwiLCBmdW5jdGlvbigpIHtcbiAgICB2YXIga2V5d29yZHMgPSBbXCJhbmRcIiwgXCJhc1wiLCBcImF1dG9lc2NhcGVcIiwgXCJlbmRhdXRvZXNjYXBlXCIsIFwiYmxvY2tcIiwgXCJkb1wiLCBcImVuZGJsb2NrXCIsIFwiZWxzZVwiLCBcImVsc2VpZlwiLCBcImV4dGVuZHNcIiwgXCJmb3JcIiwgXCJlbmRmb3JcIiwgXCJlbWJlZFwiLCBcImVuZGVtYmVkXCIsIFwiZmlsdGVyXCIsIFwiZW5kZmlsdGVyXCIsIFwiZmx1c2hcIiwgXCJmcm9tXCIsIFwiaWZcIiwgXCJlbmRpZlwiLCBcImluXCIsIFwiaXNcIiwgXCJpbmNsdWRlXCIsIFwiaW1wb3J0XCIsIFwibm90XCIsIFwib3JcIiwgXCJzZXRcIiwgXCJzcGFjZWxlc3NcIiwgXCJlbmRzcGFjZWxlc3NcIiwgXCJ3aXRoXCIsIFwiZW5kd2l0aFwiLCBcInRyYW5zXCIsIFwiZW5kdHJhbnNcIiwgXCJibG9ja3RyYW5zXCIsIFwiZW5kYmxvY2t0cmFuc1wiLCBcIm1hY3JvXCIsIFwiZW5kbWFjcm9cIiwgXCJ1c2VcIiwgXCJ2ZXJiYXRpbVwiLCBcImVuZHZlcmJhdGltXCJdLFxuICAgICAgICBvcGVyYXRvciA9IC9eWytcXC0qJiU9PD4hP3x+Xl0vLFxuICAgICAgICBzaWduID0gL15bOlxcW1xcKFxce10vLFxuICAgICAgICBhdG9tID0gW1widHJ1ZVwiLCBcImZhbHNlXCIsIFwibnVsbFwiLCBcImVtcHR5XCIsIFwiZGVmaW5lZFwiLCBcImRpdmlzaWJsZWJ5XCIsIFwiZGl2aXNpYmxlIGJ5XCIsIFwiZXZlblwiLCBcIm9kZFwiLCBcIml0ZXJhYmxlXCIsIFwic2FtZWFzXCIsIFwic2FtZSBhc1wiXSxcbiAgICAgICAgbnVtYmVyID0gL14oXFxkWytcXC1cXCpcXC9dKT9cXGQrKFxcLlxcZCspPy87XG5cbiAgICBrZXl3b3JkcyA9IG5ldyBSZWdFeHAoXCIoKFwiICsga2V5d29yZHMuam9pbihcIil8KFwiKSArIFwiKSlcXFxcYlwiKTtcbiAgICBhdG9tID0gbmV3IFJlZ0V4cChcIigoXCIgKyBhdG9tLmpvaW4oXCIpfChcIikgKyBcIikpXFxcXGJcIik7XG5cbiAgICBmdW5jdGlvbiB0b2tlbkJhc2UgKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgIHZhciBjaCA9IHN0cmVhbS5wZWVrKCk7XG5cbiAgICAgIC8vQ29tbWVudFxuICAgICAgaWYgKHN0YXRlLmluY29tbWVudCkge1xuICAgICAgICBpZiAoIXN0cmVhbS5za2lwVG8oXCIjfVwiKSkge1xuICAgICAgICAgIHN0cmVhbS5za2lwVG9FbmQoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzdHJlYW0uZWF0V2hpbGUoL1xcI3x9Lyk7XG4gICAgICAgICAgc3RhdGUuaW5jb21tZW50ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFwiY29tbWVudFwiO1xuICAgICAgLy9UYWdcbiAgICAgIH0gZWxzZSBpZiAoc3RhdGUuaW50YWcpIHtcbiAgICAgICAgLy9BZnRlciBvcGVyYXRvclxuICAgICAgICBpZiAoc3RhdGUub3BlcmF0b3IpIHtcbiAgICAgICAgICBzdGF0ZS5vcGVyYXRvciA9IGZhbHNlO1xuICAgICAgICAgIGlmIChzdHJlYW0ubWF0Y2goYXRvbSkpIHtcbiAgICAgICAgICAgIHJldHVybiBcImF0b21cIjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHN0cmVhbS5tYXRjaChudW1iZXIpKSB7XG4gICAgICAgICAgICByZXR1cm4gXCJudW1iZXJcIjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy9BZnRlciBzaWduXG4gICAgICAgIGlmIChzdGF0ZS5zaWduKSB7XG4gICAgICAgICAgc3RhdGUuc2lnbiA9IGZhbHNlO1xuICAgICAgICAgIGlmIChzdHJlYW0ubWF0Y2goYXRvbSkpIHtcbiAgICAgICAgICAgIHJldHVybiBcImF0b21cIjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHN0cmVhbS5tYXRjaChudW1iZXIpKSB7XG4gICAgICAgICAgICByZXR1cm4gXCJudW1iZXJcIjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3RhdGUuaW5zdHJpbmcpIHtcbiAgICAgICAgICBpZiAoY2ggPT0gc3RhdGUuaW5zdHJpbmcpIHtcbiAgICAgICAgICAgIHN0YXRlLmluc3RyaW5nID0gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICAgIHN0cmVhbS5uZXh0KCk7XG4gICAgICAgICAgcmV0dXJuIFwic3RyaW5nXCI7XG4gICAgICAgIH0gZWxzZSBpZiAoY2ggPT0gXCInXCIgfHwgY2ggPT0gJ1wiJykge1xuICAgICAgICAgIHN0YXRlLmluc3RyaW5nID0gY2g7XG4gICAgICAgICAgc3RyZWFtLm5leHQoKTtcbiAgICAgICAgICByZXR1cm4gXCJzdHJpbmdcIjtcbiAgICAgICAgfSBlbHNlIGlmIChzdHJlYW0ubWF0Y2goc3RhdGUuaW50YWcgKyBcIn1cIikgfHwgc3RyZWFtLmVhdChcIi1cIikgJiYgc3RyZWFtLm1hdGNoKHN0YXRlLmludGFnICsgXCJ9XCIpKSB7XG4gICAgICAgICAgc3RhdGUuaW50YWcgPSBmYWxzZTtcbiAgICAgICAgICByZXR1cm4gXCJ0YWdcIjtcbiAgICAgICAgfSBlbHNlIGlmIChzdHJlYW0ubWF0Y2gob3BlcmF0b3IpKSB7XG4gICAgICAgICAgc3RhdGUub3BlcmF0b3IgPSB0cnVlO1xuICAgICAgICAgIHJldHVybiBcIm9wZXJhdG9yXCI7XG4gICAgICAgIH0gZWxzZSBpZiAoc3RyZWFtLm1hdGNoKHNpZ24pKSB7XG4gICAgICAgICAgc3RhdGUuc2lnbiA9IHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKHN0cmVhbS5lYXQoXCIgXCIpIHx8IHN0cmVhbS5zb2woKSkge1xuICAgICAgICAgICAgaWYgKHN0cmVhbS5tYXRjaChrZXl3b3JkcykpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIFwia2V5d29yZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0cmVhbS5tYXRjaChhdG9tKSkge1xuICAgICAgICAgICAgICByZXR1cm4gXCJhdG9tXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RyZWFtLm1hdGNoKG51bWJlcikpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIFwibnVtYmVyXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RyZWFtLnNvbCgpKSB7XG4gICAgICAgICAgICAgIHN0cmVhbS5uZXh0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0cmVhbS5uZXh0KCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFwidmFyaWFibGVcIjtcbiAgICAgIH0gZWxzZSBpZiAoc3RyZWFtLmVhdChcIntcIikpIHtcbiAgICAgICAgaWYgKHN0cmVhbS5lYXQoXCIjXCIpKSB7XG4gICAgICAgICAgc3RhdGUuaW5jb21tZW50ID0gdHJ1ZTtcbiAgICAgICAgICBpZiAoIXN0cmVhbS5za2lwVG8oXCIjfVwiKSkge1xuICAgICAgICAgICAgc3RyZWFtLnNraXBUb0VuZCgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdHJlYW0uZWF0V2hpbGUoL1xcI3x9Lyk7XG4gICAgICAgICAgICBzdGF0ZS5pbmNvbW1lbnQgPSBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIFwiY29tbWVudFwiO1xuICAgICAgICAvL09wZW4gdGFnXG4gICAgICAgIH0gZWxzZSBpZiAoY2ggPSBzdHJlYW0uZWF0KC9cXHt8JS8pKSB7XG4gICAgICAgICAgLy9DYWNoZSBjbG9zZSB0YWdcbiAgICAgICAgICBzdGF0ZS5pbnRhZyA9IGNoO1xuICAgICAgICAgIGlmIChjaCA9PSBcIntcIikge1xuICAgICAgICAgICAgc3RhdGUuaW50YWcgPSBcIn1cIjtcbiAgICAgICAgICB9XG4gICAgICAgICAgc3RyZWFtLmVhdChcIi1cIik7XG4gICAgICAgICAgcmV0dXJuIFwidGFnXCI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHN0cmVhbS5uZXh0KCk7XG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICBzdGFydFN0YXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7fTtcbiAgICAgIH0sXG4gICAgICB0b2tlbjogZnVuY3Rpb24gKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgICAgcmV0dXJuIHRva2VuQmFzZShzdHJlYW0sIHN0YXRlKTtcbiAgICAgIH1cbiAgICB9O1xuICB9KTtcblxuICBDb2RlTWlycm9yLmRlZmluZU1vZGUoXCJ0d2lnXCIsIGZ1bmN0aW9uKGNvbmZpZywgcGFyc2VyQ29uZmlnKSB7XG4gICAgdmFyIHR3aWdJbm5lciA9IENvZGVNaXJyb3IuZ2V0TW9kZShjb25maWcsIFwidHdpZzppbm5lclwiKTtcbiAgICBpZiAoIXBhcnNlckNvbmZpZyB8fCAhcGFyc2VyQ29uZmlnLmJhc2UpIHJldHVybiB0d2lnSW5uZXI7XG4gICAgcmV0dXJuIENvZGVNaXJyb3IubXVsdGlwbGV4aW5nTW9kZShcbiAgICAgIENvZGVNaXJyb3IuZ2V0TW9kZShjb25maWcsIHBhcnNlckNvbmZpZy5iYXNlKSwge1xuICAgICAgICBvcGVuOiAvXFx7W3sjJV0vLCBjbG9zZTogL1t9IyVdXFx9LywgbW9kZTogdHdpZ0lubmVyLCBwYXJzZURlbGltaXRlcnM6IHRydWVcbiAgICAgIH1cbiAgICApO1xuICB9KTtcbiAgQ29kZU1pcnJvci5kZWZpbmVNSU1FKFwidGV4dC94LXR3aWdcIiwgXCJ0d2lnXCIpO1xufSk7XG4iLCIvLyBDb2RlTWlycm9yLCBjb3B5cmlnaHQgKGMpIGJ5IE1hcmlqbiBIYXZlcmJla2UgYW5kIG90aGVyc1xuLy8gRGlzdHJpYnV0ZWQgdW5kZXIgYW4gTUlUIGxpY2Vuc2U6IGh0dHBzOi8vY29kZW1pcnJvci5uZXQvTElDRU5TRVxuXG4oZnVuY3Rpb24obW9kKSB7XG4gIGlmICh0eXBlb2YgZXhwb3J0cyA9PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUgPT0gXCJvYmplY3RcIikgLy8gQ29tbW9uSlNcbiAgICBtb2QocmVxdWlyZShcIi4uLy4uL2xpYi9jb2RlbWlycm9yXCIpKTtcbiAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkgLy8gQU1EXG4gICAgZGVmaW5lKFtcIi4uLy4uL2xpYi9jb2RlbWlycm9yXCJdLCBtb2QpO1xuICBlbHNlIC8vIFBsYWluIGJyb3dzZXIgZW52XG4gICAgbW9kKENvZGVNaXJyb3IpO1xufSkoZnVuY3Rpb24oQ29kZU1pcnJvcikge1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBodG1sQ29uZmlnID0ge1xuICBhdXRvU2VsZkNsb3NlcnM6IHsnYXJlYSc6IHRydWUsICdiYXNlJzogdHJ1ZSwgJ2JyJzogdHJ1ZSwgJ2NvbCc6IHRydWUsICdjb21tYW5kJzogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgJ2VtYmVkJzogdHJ1ZSwgJ2ZyYW1lJzogdHJ1ZSwgJ2hyJzogdHJ1ZSwgJ2ltZyc6IHRydWUsICdpbnB1dCc6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICdrZXlnZW4nOiB0cnVlLCAnbGluayc6IHRydWUsICdtZXRhJzogdHJ1ZSwgJ3BhcmFtJzogdHJ1ZSwgJ3NvdXJjZSc6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICd0cmFjayc6IHRydWUsICd3YnInOiB0cnVlLCAnbWVudWl0ZW0nOiB0cnVlfSxcbiAgaW1wbGljaXRseUNsb3NlZDogeydkZCc6IHRydWUsICdsaSc6IHRydWUsICdvcHRncm91cCc6IHRydWUsICdvcHRpb24nOiB0cnVlLCAncCc6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAncnAnOiB0cnVlLCAncnQnOiB0cnVlLCAndGJvZHknOiB0cnVlLCAndGQnOiB0cnVlLCAndGZvb3QnOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgJ3RoJzogdHJ1ZSwgJ3RyJzogdHJ1ZX0sXG4gIGNvbnRleHRHcmFiYmVyczoge1xuICAgICdkZCc6IHsnZGQnOiB0cnVlLCAnZHQnOiB0cnVlfSxcbiAgICAnZHQnOiB7J2RkJzogdHJ1ZSwgJ2R0JzogdHJ1ZX0sXG4gICAgJ2xpJzogeydsaSc6IHRydWV9LFxuICAgICdvcHRpb24nOiB7J29wdGlvbic6IHRydWUsICdvcHRncm91cCc6IHRydWV9LFxuICAgICdvcHRncm91cCc6IHsnb3B0Z3JvdXAnOiB0cnVlfSxcbiAgICAncCc6IHsnYWRkcmVzcyc6IHRydWUsICdhcnRpY2xlJzogdHJ1ZSwgJ2FzaWRlJzogdHJ1ZSwgJ2Jsb2NrcXVvdGUnOiB0cnVlLCAnZGlyJzogdHJ1ZSxcbiAgICAgICAgICAnZGl2JzogdHJ1ZSwgJ2RsJzogdHJ1ZSwgJ2ZpZWxkc2V0JzogdHJ1ZSwgJ2Zvb3Rlcic6IHRydWUsICdmb3JtJzogdHJ1ZSxcbiAgICAgICAgICAnaDEnOiB0cnVlLCAnaDInOiB0cnVlLCAnaDMnOiB0cnVlLCAnaDQnOiB0cnVlLCAnaDUnOiB0cnVlLCAnaDYnOiB0cnVlLFxuICAgICAgICAgICdoZWFkZXInOiB0cnVlLCAnaGdyb3VwJzogdHJ1ZSwgJ2hyJzogdHJ1ZSwgJ21lbnUnOiB0cnVlLCAnbmF2JzogdHJ1ZSwgJ29sJzogdHJ1ZSxcbiAgICAgICAgICAncCc6IHRydWUsICdwcmUnOiB0cnVlLCAnc2VjdGlvbic6IHRydWUsICd0YWJsZSc6IHRydWUsICd1bCc6IHRydWV9LFxuICAgICdycCc6IHsncnAnOiB0cnVlLCAncnQnOiB0cnVlfSxcbiAgICAncnQnOiB7J3JwJzogdHJ1ZSwgJ3J0JzogdHJ1ZX0sXG4gICAgJ3Rib2R5Jzogeyd0Ym9keSc6IHRydWUsICd0Zm9vdCc6IHRydWV9LFxuICAgICd0ZCc6IHsndGQnOiB0cnVlLCAndGgnOiB0cnVlfSxcbiAgICAndGZvb3QnOiB7J3Rib2R5JzogdHJ1ZX0sXG4gICAgJ3RoJzogeyd0ZCc6IHRydWUsICd0aCc6IHRydWV9LFxuICAgICd0aGVhZCc6IHsndGJvZHknOiB0cnVlLCAndGZvb3QnOiB0cnVlfSxcbiAgICAndHInOiB7J3RyJzogdHJ1ZX1cbiAgfSxcbiAgZG9Ob3RJbmRlbnQ6IHtcInByZVwiOiB0cnVlfSxcbiAgYWxsb3dVbnF1b3RlZDogdHJ1ZSxcbiAgYWxsb3dNaXNzaW5nOiB0cnVlLFxuICBjYXNlRm9sZDogdHJ1ZVxufVxuXG52YXIgeG1sQ29uZmlnID0ge1xuICBhdXRvU2VsZkNsb3NlcnM6IHt9LFxuICBpbXBsaWNpdGx5Q2xvc2VkOiB7fSxcbiAgY29udGV4dEdyYWJiZXJzOiB7fSxcbiAgZG9Ob3RJbmRlbnQ6IHt9LFxuICBhbGxvd1VucXVvdGVkOiBmYWxzZSxcbiAgYWxsb3dNaXNzaW5nOiBmYWxzZSxcbiAgYWxsb3dNaXNzaW5nVGFnTmFtZTogZmFsc2UsXG4gIGNhc2VGb2xkOiBmYWxzZVxufVxuXG5Db2RlTWlycm9yLmRlZmluZU1vZGUoXCJ4bWxcIiwgZnVuY3Rpb24oZWRpdG9yQ29uZiwgY29uZmlnXykge1xuICB2YXIgaW5kZW50VW5pdCA9IGVkaXRvckNvbmYuaW5kZW50VW5pdFxuICB2YXIgY29uZmlnID0ge31cbiAgdmFyIGRlZmF1bHRzID0gY29uZmlnXy5odG1sTW9kZSA/IGh0bWxDb25maWcgOiB4bWxDb25maWdcbiAgZm9yICh2YXIgcHJvcCBpbiBkZWZhdWx0cykgY29uZmlnW3Byb3BdID0gZGVmYXVsdHNbcHJvcF1cbiAgZm9yICh2YXIgcHJvcCBpbiBjb25maWdfKSBjb25maWdbcHJvcF0gPSBjb25maWdfW3Byb3BdXG5cbiAgLy8gUmV0dXJuIHZhcmlhYmxlcyBmb3IgdG9rZW5pemVyc1xuICB2YXIgdHlwZSwgc2V0U3R5bGU7XG5cbiAgZnVuY3Rpb24gaW5UZXh0KHN0cmVhbSwgc3RhdGUpIHtcbiAgICBmdW5jdGlvbiBjaGFpbihwYXJzZXIpIHtcbiAgICAgIHN0YXRlLnRva2VuaXplID0gcGFyc2VyO1xuICAgICAgcmV0dXJuIHBhcnNlcihzdHJlYW0sIHN0YXRlKTtcbiAgICB9XG5cbiAgICB2YXIgY2ggPSBzdHJlYW0ubmV4dCgpO1xuICAgIGlmIChjaCA9PSBcIjxcIikge1xuICAgICAgaWYgKHN0cmVhbS5lYXQoXCIhXCIpKSB7XG4gICAgICAgIGlmIChzdHJlYW0uZWF0KFwiW1wiKSkge1xuICAgICAgICAgIGlmIChzdHJlYW0ubWF0Y2goXCJDREFUQVtcIikpIHJldHVybiBjaGFpbihpbkJsb2NrKFwiYXRvbVwiLCBcIl1dPlwiKSk7XG4gICAgICAgICAgZWxzZSByZXR1cm4gbnVsbDtcbiAgICAgICAgfSBlbHNlIGlmIChzdHJlYW0ubWF0Y2goXCItLVwiKSkge1xuICAgICAgICAgIHJldHVybiBjaGFpbihpbkJsb2NrKFwiY29tbWVudFwiLCBcIi0tPlwiKSk7XG4gICAgICAgIH0gZWxzZSBpZiAoc3RyZWFtLm1hdGNoKFwiRE9DVFlQRVwiLCB0cnVlLCB0cnVlKSkge1xuICAgICAgICAgIHN0cmVhbS5lYXRXaGlsZSgvW1xcd1xcLl9cXC1dLyk7XG4gICAgICAgICAgcmV0dXJuIGNoYWluKGRvY3R5cGUoMSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHN0cmVhbS5lYXQoXCI/XCIpKSB7XG4gICAgICAgIHN0cmVhbS5lYXRXaGlsZSgvW1xcd1xcLl9cXC1dLyk7XG4gICAgICAgIHN0YXRlLnRva2VuaXplID0gaW5CbG9jayhcIm1ldGFcIiwgXCI/PlwiKTtcbiAgICAgICAgcmV0dXJuIFwibWV0YVwiO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHlwZSA9IHN0cmVhbS5lYXQoXCIvXCIpID8gXCJjbG9zZVRhZ1wiIDogXCJvcGVuVGFnXCI7XG4gICAgICAgIHN0YXRlLnRva2VuaXplID0gaW5UYWc7XG4gICAgICAgIHJldHVybiBcInRhZyBicmFja2V0XCI7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChjaCA9PSBcIiZcIikge1xuICAgICAgdmFyIG9rO1xuICAgICAgaWYgKHN0cmVhbS5lYXQoXCIjXCIpKSB7XG4gICAgICAgIGlmIChzdHJlYW0uZWF0KFwieFwiKSkge1xuICAgICAgICAgIG9rID0gc3RyZWFtLmVhdFdoaWxlKC9bYS1mQS1GXFxkXS8pICYmIHN0cmVhbS5lYXQoXCI7XCIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG9rID0gc3RyZWFtLmVhdFdoaWxlKC9bXFxkXS8pICYmIHN0cmVhbS5lYXQoXCI7XCIpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvayA9IHN0cmVhbS5lYXRXaGlsZSgvW1xcd1xcLlxcLTpdLykgJiYgc3RyZWFtLmVhdChcIjtcIik7XG4gICAgICB9XG4gICAgICByZXR1cm4gb2sgPyBcImF0b21cIiA6IFwiZXJyb3JcIjtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RyZWFtLmVhdFdoaWxlKC9bXiY8XS8pO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG4gIGluVGV4dC5pc0luVGV4dCA9IHRydWU7XG5cbiAgZnVuY3Rpb24gaW5UYWcoc3RyZWFtLCBzdGF0ZSkge1xuICAgIHZhciBjaCA9IHN0cmVhbS5uZXh0KCk7XG4gICAgaWYgKGNoID09IFwiPlwiIHx8IChjaCA9PSBcIi9cIiAmJiBzdHJlYW0uZWF0KFwiPlwiKSkpIHtcbiAgICAgIHN0YXRlLnRva2VuaXplID0gaW5UZXh0O1xuICAgICAgdHlwZSA9IGNoID09IFwiPlwiID8gXCJlbmRUYWdcIiA6IFwic2VsZmNsb3NlVGFnXCI7XG4gICAgICByZXR1cm4gXCJ0YWcgYnJhY2tldFwiO1xuICAgIH0gZWxzZSBpZiAoY2ggPT0gXCI9XCIpIHtcbiAgICAgIHR5cGUgPSBcImVxdWFsc1wiO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSBlbHNlIGlmIChjaCA9PSBcIjxcIikge1xuICAgICAgc3RhdGUudG9rZW5pemUgPSBpblRleHQ7XG4gICAgICBzdGF0ZS5zdGF0ZSA9IGJhc2VTdGF0ZTtcbiAgICAgIHN0YXRlLnRhZ05hbWUgPSBzdGF0ZS50YWdTdGFydCA9IG51bGw7XG4gICAgICB2YXIgbmV4dCA9IHN0YXRlLnRva2VuaXplKHN0cmVhbSwgc3RhdGUpO1xuICAgICAgcmV0dXJuIG5leHQgPyBuZXh0ICsgXCIgdGFnIGVycm9yXCIgOiBcInRhZyBlcnJvclwiO1xuICAgIH0gZWxzZSBpZiAoL1tcXCdcXFwiXS8udGVzdChjaCkpIHtcbiAgICAgIHN0YXRlLnRva2VuaXplID0gaW5BdHRyaWJ1dGUoY2gpO1xuICAgICAgc3RhdGUuc3RyaW5nU3RhcnRDb2wgPSBzdHJlYW0uY29sdW1uKCk7XG4gICAgICByZXR1cm4gc3RhdGUudG9rZW5pemUoc3RyZWFtLCBzdGF0ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0cmVhbS5tYXRjaCgvXlteXFxzXFx1MDBhMD08PlxcXCJcXCddKlteXFxzXFx1MDBhMD08PlxcXCJcXCdcXC9dLyk7XG4gICAgICByZXR1cm4gXCJ3b3JkXCI7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5BdHRyaWJ1dGUocXVvdGUpIHtcbiAgICB2YXIgY2xvc3VyZSA9IGZ1bmN0aW9uKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgIHdoaWxlICghc3RyZWFtLmVvbCgpKSB7XG4gICAgICAgIGlmIChzdHJlYW0ubmV4dCgpID09IHF1b3RlKSB7XG4gICAgICAgICAgc3RhdGUudG9rZW5pemUgPSBpblRhZztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIFwic3RyaW5nXCI7XG4gICAgfTtcbiAgICBjbG9zdXJlLmlzSW5BdHRyaWJ1dGUgPSB0cnVlO1xuICAgIHJldHVybiBjbG9zdXJlO1xuICB9XG5cbiAgZnVuY3Rpb24gaW5CbG9jayhzdHlsZSwgdGVybWluYXRvcikge1xuICAgIHJldHVybiBmdW5jdGlvbihzdHJlYW0sIHN0YXRlKSB7XG4gICAgICB3aGlsZSAoIXN0cmVhbS5lb2woKSkge1xuICAgICAgICBpZiAoc3RyZWFtLm1hdGNoKHRlcm1pbmF0b3IpKSB7XG4gICAgICAgICAgc3RhdGUudG9rZW5pemUgPSBpblRleHQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgc3RyZWFtLm5leHQoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzdHlsZTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBkb2N0eXBlKGRlcHRoKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgIHZhciBjaDtcbiAgICAgIHdoaWxlICgoY2ggPSBzdHJlYW0ubmV4dCgpKSAhPSBudWxsKSB7XG4gICAgICAgIGlmIChjaCA9PSBcIjxcIikge1xuICAgICAgICAgIHN0YXRlLnRva2VuaXplID0gZG9jdHlwZShkZXB0aCArIDEpO1xuICAgICAgICAgIHJldHVybiBzdGF0ZS50b2tlbml6ZShzdHJlYW0sIHN0YXRlKTtcbiAgICAgICAgfSBlbHNlIGlmIChjaCA9PSBcIj5cIikge1xuICAgICAgICAgIGlmIChkZXB0aCA9PSAxKSB7XG4gICAgICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IGluVGV4dDtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IGRvY3R5cGUoZGVwdGggLSAxKTtcbiAgICAgICAgICAgIHJldHVybiBzdGF0ZS50b2tlbml6ZShzdHJlYW0sIHN0YXRlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBcIm1ldGFcIjtcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gbG93ZXIodGFnTmFtZSkge1xuICAgIHJldHVybiB0YWdOYW1lICYmIHRhZ05hbWUudG9Mb3dlckNhc2UoKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIENvbnRleHQoc3RhdGUsIHRhZ05hbWUsIHN0YXJ0T2ZMaW5lKSB7XG4gICAgdGhpcy5wcmV2ID0gc3RhdGUuY29udGV4dDtcbiAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lIHx8IFwiXCI7XG4gICAgdGhpcy5pbmRlbnQgPSBzdGF0ZS5pbmRlbnRlZDtcbiAgICB0aGlzLnN0YXJ0T2ZMaW5lID0gc3RhcnRPZkxpbmU7XG4gICAgaWYgKGNvbmZpZy5kb05vdEluZGVudC5oYXNPd25Qcm9wZXJ0eSh0YWdOYW1lKSB8fCAoc3RhdGUuY29udGV4dCAmJiBzdGF0ZS5jb250ZXh0Lm5vSW5kZW50KSlcbiAgICAgIHRoaXMubm9JbmRlbnQgPSB0cnVlO1xuICB9XG4gIGZ1bmN0aW9uIHBvcENvbnRleHQoc3RhdGUpIHtcbiAgICBpZiAoc3RhdGUuY29udGV4dCkgc3RhdGUuY29udGV4dCA9IHN0YXRlLmNvbnRleHQucHJldjtcbiAgfVxuICBmdW5jdGlvbiBtYXliZVBvcENvbnRleHQoc3RhdGUsIG5leHRUYWdOYW1lKSB7XG4gICAgdmFyIHBhcmVudFRhZ05hbWU7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGlmICghc3RhdGUuY29udGV4dCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBwYXJlbnRUYWdOYW1lID0gc3RhdGUuY29udGV4dC50YWdOYW1lO1xuICAgICAgaWYgKCFjb25maWcuY29udGV4dEdyYWJiZXJzLmhhc093blByb3BlcnR5KGxvd2VyKHBhcmVudFRhZ05hbWUpKSB8fFxuICAgICAgICAgICFjb25maWcuY29udGV4dEdyYWJiZXJzW2xvd2VyKHBhcmVudFRhZ05hbWUpXS5oYXNPd25Qcm9wZXJ0eShsb3dlcihuZXh0VGFnTmFtZSkpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHBvcENvbnRleHQoc3RhdGUpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGJhc2VTdGF0ZSh0eXBlLCBzdHJlYW0sIHN0YXRlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCJvcGVuVGFnXCIpIHtcbiAgICAgIHN0YXRlLnRhZ1N0YXJ0ID0gc3RyZWFtLmNvbHVtbigpO1xuICAgICAgcmV0dXJuIHRhZ05hbWVTdGF0ZTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT0gXCJjbG9zZVRhZ1wiKSB7XG4gICAgICByZXR1cm4gY2xvc2VUYWdOYW1lU3RhdGU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBiYXNlU3RhdGU7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIHRhZ05hbWVTdGF0ZSh0eXBlLCBzdHJlYW0sIHN0YXRlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCJ3b3JkXCIpIHtcbiAgICAgIHN0YXRlLnRhZ05hbWUgPSBzdHJlYW0uY3VycmVudCgpO1xuICAgICAgc2V0U3R5bGUgPSBcInRhZ1wiO1xuICAgICAgcmV0dXJuIGF0dHJTdGF0ZTtcbiAgICB9IGVsc2UgaWYgKGNvbmZpZy5hbGxvd01pc3NpbmdUYWdOYW1lICYmIHR5cGUgPT0gXCJlbmRUYWdcIikge1xuICAgICAgc2V0U3R5bGUgPSBcInRhZyBicmFja2V0XCI7XG4gICAgICByZXR1cm4gYXR0clN0YXRlKHR5cGUsIHN0cmVhbSwgc3RhdGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzZXRTdHlsZSA9IFwiZXJyb3JcIjtcbiAgICAgIHJldHVybiB0YWdOYW1lU3RhdGU7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGNsb3NlVGFnTmFtZVN0YXRlKHR5cGUsIHN0cmVhbSwgc3RhdGUpIHtcbiAgICBpZiAodHlwZSA9PSBcIndvcmRcIikge1xuICAgICAgdmFyIHRhZ05hbWUgPSBzdHJlYW0uY3VycmVudCgpO1xuICAgICAgaWYgKHN0YXRlLmNvbnRleHQgJiYgc3RhdGUuY29udGV4dC50YWdOYW1lICE9IHRhZ05hbWUgJiZcbiAgICAgICAgICBjb25maWcuaW1wbGljaXRseUNsb3NlZC5oYXNPd25Qcm9wZXJ0eShsb3dlcihzdGF0ZS5jb250ZXh0LnRhZ05hbWUpKSlcbiAgICAgICAgcG9wQ29udGV4dChzdGF0ZSk7XG4gICAgICBpZiAoKHN0YXRlLmNvbnRleHQgJiYgc3RhdGUuY29udGV4dC50YWdOYW1lID09IHRhZ05hbWUpIHx8IGNvbmZpZy5tYXRjaENsb3NpbmcgPT09IGZhbHNlKSB7XG4gICAgICAgIHNldFN0eWxlID0gXCJ0YWdcIjtcbiAgICAgICAgcmV0dXJuIGNsb3NlU3RhdGU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZXRTdHlsZSA9IFwidGFnIGVycm9yXCI7XG4gICAgICAgIHJldHVybiBjbG9zZVN0YXRlRXJyO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoY29uZmlnLmFsbG93TWlzc2luZ1RhZ05hbWUgJiYgdHlwZSA9PSBcImVuZFRhZ1wiKSB7XG4gICAgICBzZXRTdHlsZSA9IFwidGFnIGJyYWNrZXRcIjtcbiAgICAgIHJldHVybiBjbG9zZVN0YXRlKHR5cGUsIHN0cmVhbSwgc3RhdGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzZXRTdHlsZSA9IFwiZXJyb3JcIjtcbiAgICAgIHJldHVybiBjbG9zZVN0YXRlRXJyO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGNsb3NlU3RhdGUodHlwZSwgX3N0cmVhbSwgc3RhdGUpIHtcbiAgICBpZiAodHlwZSAhPSBcImVuZFRhZ1wiKSB7XG4gICAgICBzZXRTdHlsZSA9IFwiZXJyb3JcIjtcbiAgICAgIHJldHVybiBjbG9zZVN0YXRlO1xuICAgIH1cbiAgICBwb3BDb250ZXh0KHN0YXRlKTtcbiAgICByZXR1cm4gYmFzZVN0YXRlO1xuICB9XG4gIGZ1bmN0aW9uIGNsb3NlU3RhdGVFcnIodHlwZSwgc3RyZWFtLCBzdGF0ZSkge1xuICAgIHNldFN0eWxlID0gXCJlcnJvclwiO1xuICAgIHJldHVybiBjbG9zZVN0YXRlKHR5cGUsIHN0cmVhbSwgc3RhdGUpO1xuICB9XG5cbiAgZnVuY3Rpb24gYXR0clN0YXRlKHR5cGUsIF9zdHJlYW0sIHN0YXRlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCJ3b3JkXCIpIHtcbiAgICAgIHNldFN0eWxlID0gXCJhdHRyaWJ1dGVcIjtcbiAgICAgIHJldHVybiBhdHRyRXFTdGF0ZTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT0gXCJlbmRUYWdcIiB8fCB0eXBlID09IFwic2VsZmNsb3NlVGFnXCIpIHtcbiAgICAgIHZhciB0YWdOYW1lID0gc3RhdGUudGFnTmFtZSwgdGFnU3RhcnQgPSBzdGF0ZS50YWdTdGFydDtcbiAgICAgIHN0YXRlLnRhZ05hbWUgPSBzdGF0ZS50YWdTdGFydCA9IG51bGw7XG4gICAgICBpZiAodHlwZSA9PSBcInNlbGZjbG9zZVRhZ1wiIHx8XG4gICAgICAgICAgY29uZmlnLmF1dG9TZWxmQ2xvc2Vycy5oYXNPd25Qcm9wZXJ0eShsb3dlcih0YWdOYW1lKSkpIHtcbiAgICAgICAgbWF5YmVQb3BDb250ZXh0KHN0YXRlLCB0YWdOYW1lKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1heWJlUG9wQ29udGV4dChzdGF0ZSwgdGFnTmFtZSk7XG4gICAgICAgIHN0YXRlLmNvbnRleHQgPSBuZXcgQ29udGV4dChzdGF0ZSwgdGFnTmFtZSwgdGFnU3RhcnQgPT0gc3RhdGUuaW5kZW50ZWQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VTdGF0ZTtcbiAgICB9XG4gICAgc2V0U3R5bGUgPSBcImVycm9yXCI7XG4gICAgcmV0dXJuIGF0dHJTdGF0ZTtcbiAgfVxuICBmdW5jdGlvbiBhdHRyRXFTdGF0ZSh0eXBlLCBzdHJlYW0sIHN0YXRlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCJlcXVhbHNcIikgcmV0dXJuIGF0dHJWYWx1ZVN0YXRlO1xuICAgIGlmICghY29uZmlnLmFsbG93TWlzc2luZykgc2V0U3R5bGUgPSBcImVycm9yXCI7XG4gICAgcmV0dXJuIGF0dHJTdGF0ZSh0eXBlLCBzdHJlYW0sIHN0YXRlKTtcbiAgfVxuICBmdW5jdGlvbiBhdHRyVmFsdWVTdGF0ZSh0eXBlLCBzdHJlYW0sIHN0YXRlKSB7XG4gICAgaWYgKHR5cGUgPT0gXCJzdHJpbmdcIikgcmV0dXJuIGF0dHJDb250aW51ZWRTdGF0ZTtcbiAgICBpZiAodHlwZSA9PSBcIndvcmRcIiAmJiBjb25maWcuYWxsb3dVbnF1b3RlZCkge3NldFN0eWxlID0gXCJzdHJpbmdcIjsgcmV0dXJuIGF0dHJTdGF0ZTt9XG4gICAgc2V0U3R5bGUgPSBcImVycm9yXCI7XG4gICAgcmV0dXJuIGF0dHJTdGF0ZSh0eXBlLCBzdHJlYW0sIHN0YXRlKTtcbiAgfVxuICBmdW5jdGlvbiBhdHRyQ29udGludWVkU3RhdGUodHlwZSwgc3RyZWFtLCBzdGF0ZSkge1xuICAgIGlmICh0eXBlID09IFwic3RyaW5nXCIpIHJldHVybiBhdHRyQ29udGludWVkU3RhdGU7XG4gICAgcmV0dXJuIGF0dHJTdGF0ZSh0eXBlLCBzdHJlYW0sIHN0YXRlKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgc3RhcnRTdGF0ZTogZnVuY3Rpb24oYmFzZUluZGVudCkge1xuICAgICAgdmFyIHN0YXRlID0ge3Rva2VuaXplOiBpblRleHQsXG4gICAgICAgICAgICAgICAgICAgc3RhdGU6IGJhc2VTdGF0ZSxcbiAgICAgICAgICAgICAgICAgICBpbmRlbnRlZDogYmFzZUluZGVudCB8fCAwLFxuICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IG51bGwsIHRhZ1N0YXJ0OiBudWxsLFxuICAgICAgICAgICAgICAgICAgIGNvbnRleHQ6IG51bGx9XG4gICAgICBpZiAoYmFzZUluZGVudCAhPSBudWxsKSBzdGF0ZS5iYXNlSW5kZW50ID0gYmFzZUluZGVudFxuICAgICAgcmV0dXJuIHN0YXRlXG4gICAgfSxcblxuICAgIHRva2VuOiBmdW5jdGlvbihzdHJlYW0sIHN0YXRlKSB7XG4gICAgICBpZiAoIXN0YXRlLnRhZ05hbWUgJiYgc3RyZWFtLnNvbCgpKVxuICAgICAgICBzdGF0ZS5pbmRlbnRlZCA9IHN0cmVhbS5pbmRlbnRhdGlvbigpO1xuXG4gICAgICBpZiAoc3RyZWFtLmVhdFNwYWNlKCkpIHJldHVybiBudWxsO1xuICAgICAgdHlwZSA9IG51bGw7XG4gICAgICB2YXIgc3R5bGUgPSBzdGF0ZS50b2tlbml6ZShzdHJlYW0sIHN0YXRlKTtcbiAgICAgIGlmICgoc3R5bGUgfHwgdHlwZSkgJiYgc3R5bGUgIT0gXCJjb21tZW50XCIpIHtcbiAgICAgICAgc2V0U3R5bGUgPSBudWxsO1xuICAgICAgICBzdGF0ZS5zdGF0ZSA9IHN0YXRlLnN0YXRlKHR5cGUgfHwgc3R5bGUsIHN0cmVhbSwgc3RhdGUpO1xuICAgICAgICBpZiAoc2V0U3R5bGUpXG4gICAgICAgICAgc3R5bGUgPSBzZXRTdHlsZSA9PSBcImVycm9yXCIgPyBzdHlsZSArIFwiIGVycm9yXCIgOiBzZXRTdHlsZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzdHlsZTtcbiAgICB9LFxuXG4gICAgaW5kZW50OiBmdW5jdGlvbihzdGF0ZSwgdGV4dEFmdGVyLCBmdWxsTGluZSkge1xuICAgICAgdmFyIGNvbnRleHQgPSBzdGF0ZS5jb250ZXh0O1xuICAgICAgLy8gSW5kZW50IG11bHRpLWxpbmUgc3RyaW5ncyAoZS5nLiBjc3MpLlxuICAgICAgaWYgKHN0YXRlLnRva2VuaXplLmlzSW5BdHRyaWJ1dGUpIHtcbiAgICAgICAgaWYgKHN0YXRlLnRhZ1N0YXJ0ID09IHN0YXRlLmluZGVudGVkKVxuICAgICAgICAgIHJldHVybiBzdGF0ZS5zdHJpbmdTdGFydENvbCArIDE7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICByZXR1cm4gc3RhdGUuaW5kZW50ZWQgKyBpbmRlbnRVbml0O1xuICAgICAgfVxuICAgICAgaWYgKGNvbnRleHQgJiYgY29udGV4dC5ub0luZGVudCkgcmV0dXJuIENvZGVNaXJyb3IuUGFzcztcbiAgICAgIGlmIChzdGF0ZS50b2tlbml6ZSAhPSBpblRhZyAmJiBzdGF0ZS50b2tlbml6ZSAhPSBpblRleHQpXG4gICAgICAgIHJldHVybiBmdWxsTGluZSA/IGZ1bGxMaW5lLm1hdGNoKC9eKFxccyopLylbMF0ubGVuZ3RoIDogMDtcbiAgICAgIC8vIEluZGVudCB0aGUgc3RhcnRzIG9mIGF0dHJpYnV0ZSBuYW1lcy5cbiAgICAgIGlmIChzdGF0ZS50YWdOYW1lKSB7XG4gICAgICAgIGlmIChjb25maWcubXVsdGlsaW5lVGFnSW5kZW50UGFzdFRhZyAhPT0gZmFsc2UpXG4gICAgICAgICAgcmV0dXJuIHN0YXRlLnRhZ1N0YXJ0ICsgc3RhdGUudGFnTmFtZS5sZW5ndGggKyAyO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgcmV0dXJuIHN0YXRlLnRhZ1N0YXJ0ICsgaW5kZW50VW5pdCAqIChjb25maWcubXVsdGlsaW5lVGFnSW5kZW50RmFjdG9yIHx8IDEpO1xuICAgICAgfVxuICAgICAgaWYgKGNvbmZpZy5hbGlnbkNEQVRBICYmIC88IVxcW0NEQVRBXFxbLy50ZXN0KHRleHRBZnRlcikpIHJldHVybiAwO1xuICAgICAgdmFyIHRhZ0FmdGVyID0gdGV4dEFmdGVyICYmIC9ePChcXC8pPyhbXFx3XzpcXC4tXSopLy5leGVjKHRleHRBZnRlcik7XG4gICAgICBpZiAodGFnQWZ0ZXIgJiYgdGFnQWZ0ZXJbMV0pIHsgLy8gQ2xvc2luZyB0YWcgc3BvdHRlZFxuICAgICAgICB3aGlsZSAoY29udGV4dCkge1xuICAgICAgICAgIGlmIChjb250ZXh0LnRhZ05hbWUgPT0gdGFnQWZ0ZXJbMl0pIHtcbiAgICAgICAgICAgIGNvbnRleHQgPSBjb250ZXh0LnByZXY7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9IGVsc2UgaWYgKGNvbmZpZy5pbXBsaWNpdGx5Q2xvc2VkLmhhc093blByb3BlcnR5KGxvd2VyKGNvbnRleHQudGFnTmFtZSkpKSB7XG4gICAgICAgICAgICBjb250ZXh0ID0gY29udGV4dC5wcmV2O1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodGFnQWZ0ZXIpIHsgLy8gT3BlbmluZyB0YWcgc3BvdHRlZFxuICAgICAgICB3aGlsZSAoY29udGV4dCkge1xuICAgICAgICAgIHZhciBncmFiYmVycyA9IGNvbmZpZy5jb250ZXh0R3JhYmJlcnNbbG93ZXIoY29udGV4dC50YWdOYW1lKV07XG4gICAgICAgICAgaWYgKGdyYWJiZXJzICYmIGdyYWJiZXJzLmhhc093blByb3BlcnR5KGxvd2VyKHRhZ0FmdGVyWzJdKSkpXG4gICAgICAgICAgICBjb250ZXh0ID0gY29udGV4dC5wcmV2O1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB3aGlsZSAoY29udGV4dCAmJiBjb250ZXh0LnByZXYgJiYgIWNvbnRleHQuc3RhcnRPZkxpbmUpXG4gICAgICAgIGNvbnRleHQgPSBjb250ZXh0LnByZXY7XG4gICAgICBpZiAoY29udGV4dCkgcmV0dXJuIGNvbnRleHQuaW5kZW50ICsgaW5kZW50VW5pdDtcbiAgICAgIGVsc2UgcmV0dXJuIHN0YXRlLmJhc2VJbmRlbnQgfHwgMDtcbiAgICB9LFxuXG4gICAgZWxlY3RyaWNJbnB1dDogLzxcXC9bXFxzXFx3Ol0rPiQvLFxuICAgIGJsb2NrQ29tbWVudFN0YXJ0OiBcIjwhLS1cIixcbiAgICBibG9ja0NvbW1lbnRFbmQ6IFwiLS0+XCIsXG5cbiAgICBjb25maWd1cmF0aW9uOiBjb25maWcuaHRtbE1vZGUgPyBcImh0bWxcIiA6IFwieG1sXCIsXG4gICAgaGVscGVyVHlwZTogY29uZmlnLmh0bWxNb2RlID8gXCJodG1sXCIgOiBcInhtbFwiLFxuXG4gICAgc2tpcEF0dHJpYnV0ZTogZnVuY3Rpb24oc3RhdGUpIHtcbiAgICAgIGlmIChzdGF0ZS5zdGF0ZSA9PSBhdHRyVmFsdWVTdGF0ZSlcbiAgICAgICAgc3RhdGUuc3RhdGUgPSBhdHRyU3RhdGVcbiAgICB9LFxuXG4gICAgeG1sQ3VycmVudFRhZzogZnVuY3Rpb24oc3RhdGUpIHtcbiAgICAgIHJldHVybiBzdGF0ZS50YWdOYW1lID8ge25hbWU6IHN0YXRlLnRhZ05hbWUsIGNsb3NlOiBzdGF0ZS50eXBlID09IFwiY2xvc2VUYWdcIn0gOiBudWxsXG4gICAgfSxcblxuICAgIHhtbEN1cnJlbnRDb250ZXh0OiBmdW5jdGlvbihzdGF0ZSkge1xuICAgICAgdmFyIGNvbnRleHQgPSBbXVxuICAgICAgZm9yICh2YXIgY3ggPSBzdGF0ZS5jb250ZXh0OyBjeDsgY3ggPSBjeC5wcmV2KVxuICAgICAgICBjb250ZXh0LnB1c2goY3gudGFnTmFtZSlcbiAgICAgIHJldHVybiBjb250ZXh0LnJldmVyc2UoKVxuICAgIH1cbiAgfTtcbn0pO1xuXG5Db2RlTWlycm9yLmRlZmluZU1JTUUoXCJ0ZXh0L3htbFwiLCBcInhtbFwiKTtcbkNvZGVNaXJyb3IuZGVmaW5lTUlNRShcImFwcGxpY2F0aW9uL3htbFwiLCBcInhtbFwiKTtcbmlmICghQ29kZU1pcnJvci5taW1lTW9kZXMuaGFzT3duUHJvcGVydHkoXCJ0ZXh0L2h0bWxcIikpXG4gIENvZGVNaXJyb3IuZGVmaW5lTUlNRShcInRleHQvaHRtbFwiLCB7bmFtZTogXCJ4bWxcIiwgaHRtbE1vZGU6IHRydWV9KTtcblxufSk7XG4iLCIvLyBJbXBvcnRzXG5pbXBvcnQgX19fQ1NTX0xPQURFUl9BUElfU09VUkNFTUFQX0lNUE9SVF9fXyBmcm9tIFwiLi4vLi4vY3NzLWxvYWRlci9kaXN0L3J1bnRpbWUvY3NzV2l0aE1hcHBpbmdUb1N0cmluZy5qc1wiO1xuaW1wb3J0IF9fX0NTU19MT0FERVJfQVBJX0lNUE9SVF9fXyBmcm9tIFwiLi4vLi4vY3NzLWxvYWRlci9kaXN0L3J1bnRpbWUvYXBpLmpzXCI7XG52YXIgX19fQ1NTX0xPQURFUl9FWFBPUlRfX18gPSBfX19DU1NfTE9BREVSX0FQSV9JTVBPUlRfX18oX19fQ1NTX0xPQURFUl9BUElfU09VUkNFTUFQX0lNUE9SVF9fXyk7XG4vLyBNb2R1bGVcbl9fX0NTU19MT0FERVJfRVhQT1JUX19fLnB1c2goW21vZHVsZS5pZCwgXCIuQ29kZU1pcnJvcntjb2xvcjojMDAwO2RpcmVjdGlvbjpsdHI7Zm9udC1mYW1pbHk6bW9ub3NwYWNlO2hlaWdodDozMDBweH0uQ29kZU1pcnJvci1saW5lc3twYWRkaW5nOjRweCAwfS5Db2RlTWlycm9yIHByZS5Db2RlTWlycm9yLWxpbmUsLkNvZGVNaXJyb3IgcHJlLkNvZGVNaXJyb3ItbGluZS1saWtle3BhZGRpbmc6MCA0cHh9LkNvZGVNaXJyb3ItZ3V0dGVyLWZpbGxlciwuQ29kZU1pcnJvci1zY3JvbGxiYXItZmlsbGVye2JhY2tncm91bmQtY29sb3I6I2ZmZn0uQ29kZU1pcnJvci1ndXR0ZXJze2JhY2tncm91bmQtY29sb3I6I2Y3ZjdmNztib3JkZXItcmlnaHQ6MXB4IHNvbGlkICNkZGQ7d2hpdGUtc3BhY2U6bm93cmFwfS5Db2RlTWlycm9yLWxpbmVudW1iZXJ7Y29sb3I6Izk5OTttaW4td2lkdGg6MjBweDtwYWRkaW5nOjAgM3B4IDAgNXB4O3RleHQtYWxpZ246cmlnaHQ7d2hpdGUtc3BhY2U6bm93cmFwfS5Db2RlTWlycm9yLWd1dHRlcm1hcmtlcntjb2xvcjojMDAwfS5Db2RlTWlycm9yLWd1dHRlcm1hcmtlci1zdWJ0bGV7Y29sb3I6Izk5OX0uQ29kZU1pcnJvci1jdXJzb3J7Ym9yZGVyLWxlZnQ6MXB4IHNvbGlkICMwMDA7Ym9yZGVyLXJpZ2h0Om5vbmU7d2lkdGg6MH0uQ29kZU1pcnJvciBkaXYuQ29kZU1pcnJvci1zZWNvbmRhcnljdXJzb3J7Ym9yZGVyLWxlZnQ6MXB4IHNvbGlkIHNpbHZlcn0uY20tZmF0LWN1cnNvciAuQ29kZU1pcnJvci1jdXJzb3J7YmFja2dyb3VuZDojN2U3O2JvcmRlcjowIWltcG9ydGFudDt3aWR0aDphdXRvfS5jbS1mYXQtY3Vyc29yIGRpdi5Db2RlTWlycm9yLWN1cnNvcnN7ei1pbmRleDoxfS5jbS1mYXQtY3Vyc29yIC5Db2RlTWlycm9yLWxpbmU6OnNlbGVjdGlvbiwuY20tZmF0LWN1cnNvciAuQ29kZU1pcnJvci1saW5lPnNwYW46OnNlbGVjdGlvbiwuY20tZmF0LWN1cnNvciAuQ29kZU1pcnJvci1saW5lPnNwYW4+c3Bhbjo6c2VsZWN0aW9ue2JhY2tncm91bmQ6dHJhbnNwYXJlbnR9LmNtLWZhdC1jdXJzb3IgLkNvZGVNaXJyb3ItbGluZTo6LW1vei1zZWxlY3Rpb24sLmNtLWZhdC1jdXJzb3IgLkNvZGVNaXJyb3ItbGluZT5zcGFuOjotbW96LXNlbGVjdGlvbiwuY20tZmF0LWN1cnNvciAuQ29kZU1pcnJvci1saW5lPnNwYW4+c3Bhbjo6LW1vei1zZWxlY3Rpb257YmFja2dyb3VuZDp0cmFuc3BhcmVudH0uY20tZmF0LWN1cnNvcntjYXJldC1jb2xvcjp0cmFuc3BhcmVudH1ALXdlYmtpdC1rZXlmcmFtZXMgYmxpbmt7NTAle2JhY2tncm91bmQtY29sb3I6dHJhbnNwYXJlbnR9fUBrZXlmcmFtZXMgYmxpbmt7NTAle2JhY2tncm91bmQtY29sb3I6dHJhbnNwYXJlbnR9fS5jbS10YWJ7ZGlzcGxheTppbmxpbmUtYmxvY2s7dGV4dC1kZWNvcmF0aW9uOmluaGVyaXR9LkNvZGVNaXJyb3ItcnVsZXJze2JvdHRvbTowO2xlZnQ6MDtvdmVyZmxvdzpoaWRkZW47cG9zaXRpb246YWJzb2x1dGU7cmlnaHQ6MDt0b3A6LTUwcHh9LkNvZGVNaXJyb3ItcnVsZXJ7Ym9yZGVyLWxlZnQ6MXB4IHNvbGlkICNjY2M7Ym90dG9tOjA7cG9zaXRpb246YWJzb2x1dGU7dG9wOjB9LmNtLXMtZGVmYXVsdCAuY20taGVhZGVye2NvbG9yOmJsdWV9LmNtLXMtZGVmYXVsdCAuY20tcXVvdGV7Y29sb3I6IzA5MH0uY20tbmVnYXRpdmV7Y29sb3I6I2Q0NH0uY20tcG9zaXRpdmV7Y29sb3I6IzI5Mn0uY20taGVhZGVyLC5jbS1zdHJvbmd7Zm9udC13ZWlnaHQ6NzAwfS5jbS1lbXtmb250LXN0eWxlOml0YWxpY30uY20tbGlua3t0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lfS5jbS1zdHJpa2V0aHJvdWdoe3RleHQtZGVjb3JhdGlvbjpsaW5lLXRocm91Z2h9LmNtLXMtZGVmYXVsdCAuY20ta2V5d29yZHtjb2xvcjojNzA4fS5jbS1zLWRlZmF1bHQgLmNtLWF0b217Y29sb3I6IzIxOX0uY20tcy1kZWZhdWx0IC5jbS1udW1iZXJ7Y29sb3I6IzE2NH0uY20tcy1kZWZhdWx0IC5jbS1kZWZ7Y29sb3I6IzAwZn0uY20tcy1kZWZhdWx0IC5jbS12YXJpYWJsZS0ye2NvbG9yOiMwNWF9LmNtLXMtZGVmYXVsdCAuY20tdHlwZSwuY20tcy1kZWZhdWx0IC5jbS12YXJpYWJsZS0ze2NvbG9yOiMwODV9LmNtLXMtZGVmYXVsdCAuY20tY29tbWVudHtjb2xvcjojYTUwfS5jbS1zLWRlZmF1bHQgLmNtLXN0cmluZ3tjb2xvcjojYTExfS5jbS1zLWRlZmF1bHQgLmNtLXN0cmluZy0ye2NvbG9yOiNmNTB9LmNtLXMtZGVmYXVsdCAuY20tbWV0YSwuY20tcy1kZWZhdWx0IC5jbS1xdWFsaWZpZXJ7Y29sb3I6IzU1NX0uY20tcy1kZWZhdWx0IC5jbS1idWlsdGlue2NvbG9yOiMzMGF9LmNtLXMtZGVmYXVsdCAuY20tYnJhY2tldHtjb2xvcjojOTk3fS5jbS1zLWRlZmF1bHQgLmNtLXRhZ3tjb2xvcjojMTcwfS5jbS1zLWRlZmF1bHQgLmNtLWF0dHJpYnV0ZXtjb2xvcjojMDBjfS5jbS1zLWRlZmF1bHQgLmNtLWhye2NvbG9yOiM5OTl9LmNtLXMtZGVmYXVsdCAuY20tbGlua3tjb2xvcjojMDBjfS5jbS1pbnZhbGlkY2hhciwuY20tcy1kZWZhdWx0IC5jbS1lcnJvcntjb2xvcjpyZWR9LkNvZGVNaXJyb3ItY29tcG9zaW5ne2JvcmRlci1ib3R0b206MnB4IHNvbGlkfWRpdi5Db2RlTWlycm9yIHNwYW4uQ29kZU1pcnJvci1tYXRjaGluZ2JyYWNrZXR7Y29sb3I6IzBiMH1kaXYuQ29kZU1pcnJvciBzcGFuLkNvZGVNaXJyb3Itbm9ubWF0Y2hpbmdicmFja2V0e2NvbG9yOiNhMjJ9LkNvZGVNaXJyb3ItbWF0Y2hpbmd0YWd7YmFja2dyb3VuZDpyZ2JhKDI1NSwxNTAsMCwuMyl9LkNvZGVNaXJyb3ItYWN0aXZlbGluZS1iYWNrZ3JvdW5ke2JhY2tncm91bmQ6I2U4ZjJmZn0uQ29kZU1pcnJvcntiYWNrZ3JvdW5kOiNmZmY7b3ZlcmZsb3c6aGlkZGVuO3Bvc2l0aW9uOnJlbGF0aXZlfS5Db2RlTWlycm9yLXNjcm9sbHtoZWlnaHQ6MTAwJTttYXJnaW4tYm90dG9tOi01MHB4O21hcmdpbi1yaWdodDotNTBweDtvdXRsaW5lOm5vbmU7b3ZlcmZsb3c6c2Nyb2xsIWltcG9ydGFudDtwYWRkaW5nLWJvdHRvbTo1MHB4O3Bvc2l0aW9uOnJlbGF0aXZlO3otaW5kZXg6MH0uQ29kZU1pcnJvci1zaXplcntib3JkZXItcmlnaHQ6NTBweCBzb2xpZCB0cmFuc3BhcmVudDtwb3NpdGlvbjpyZWxhdGl2ZX0uQ29kZU1pcnJvci1ndXR0ZXItZmlsbGVyLC5Db2RlTWlycm9yLWhzY3JvbGxiYXIsLkNvZGVNaXJyb3Itc2Nyb2xsYmFyLWZpbGxlciwuQ29kZU1pcnJvci12c2Nyb2xsYmFye2Rpc3BsYXk6bm9uZTtvdXRsaW5lOm5vbmU7cG9zaXRpb246YWJzb2x1dGU7ei1pbmRleDo2fS5Db2RlTWlycm9yLXZzY3JvbGxiYXJ7b3ZlcmZsb3cteDpoaWRkZW47b3ZlcmZsb3cteTpzY3JvbGw7cmlnaHQ6MDt0b3A6MH0uQ29kZU1pcnJvci1oc2Nyb2xsYmFye2JvdHRvbTowO2xlZnQ6MDtvdmVyZmxvdy14OnNjcm9sbDtvdmVyZmxvdy15OmhpZGRlbn0uQ29kZU1pcnJvci1zY3JvbGxiYXItZmlsbGVye2JvdHRvbTowO3JpZ2h0OjB9LkNvZGVNaXJyb3ItZ3V0dGVyLWZpbGxlcntib3R0b206MDtsZWZ0OjB9LkNvZGVNaXJyb3ItZ3V0dGVyc3tsZWZ0OjA7bWluLWhlaWdodDoxMDAlO3Bvc2l0aW9uOmFic29sdXRlO3RvcDowO3otaW5kZXg6M30uQ29kZU1pcnJvci1ndXR0ZXJ7ZGlzcGxheTppbmxpbmUtYmxvY2s7aGVpZ2h0OjEwMCU7bWFyZ2luLWJvdHRvbTotNTBweDt2ZXJ0aWNhbC1hbGlnbjp0b3A7d2hpdGUtc3BhY2U6bm9ybWFsfS5Db2RlTWlycm9yLWd1dHRlci13cmFwcGVye2JhY2tncm91bmQ6bm9uZSFpbXBvcnRhbnQ7Ym9yZGVyOm5vbmUhaW1wb3J0YW50O3Bvc2l0aW9uOmFic29sdXRlO3otaW5kZXg6NH0uQ29kZU1pcnJvci1ndXR0ZXItYmFja2dyb3VuZHtib3R0b206MDtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDt6LWluZGV4OjR9LkNvZGVNaXJyb3ItZ3V0dGVyLWVsdHtjdXJzb3I6ZGVmYXVsdDtwb3NpdGlvbjphYnNvbHV0ZTt6LWluZGV4OjR9LkNvZGVNaXJyb3ItZ3V0dGVyLXdyYXBwZXIgOjpzZWxlY3Rpb257YmFja2dyb3VuZC1jb2xvcjp0cmFuc3BhcmVudH0uQ29kZU1pcnJvci1ndXR0ZXItd3JhcHBlciA6Oi1tb3otc2VsZWN0aW9ue2JhY2tncm91bmQtY29sb3I6dHJhbnNwYXJlbnR9LkNvZGVNaXJyb3ItbGluZXN7Y3Vyc29yOnRleHQ7bWluLWhlaWdodDoxcHh9LkNvZGVNaXJyb3IgcHJlLkNvZGVNaXJyb3ItbGluZSwuQ29kZU1pcnJvciBwcmUuQ29kZU1pcnJvci1saW5lLWxpa2V7d29yZC13cmFwOm5vcm1hbDstd2Via2l0LXRhcC1oaWdobGlnaHQtY29sb3I6dHJhbnNwYXJlbnQ7YmFja2dyb3VuZDp0cmFuc3BhcmVudDtib3JkZXItcmFkaXVzOjA7Ym9yZGVyLXdpZHRoOjA7Y29sb3I6aW5oZXJpdDtmb250LWZhbWlseTppbmhlcml0O2ZvbnQtc2l6ZTppbmhlcml0O2ZvbnQtdmFyaWFudC1saWdhdHVyZXM6Y29udGV4dHVhbDtsaW5lLWhlaWdodDppbmhlcml0O21hcmdpbjowO292ZXJmbG93OnZpc2libGU7cG9zaXRpb246cmVsYXRpdmU7d2hpdGUtc3BhY2U6cHJlO3otaW5kZXg6Mn0uQ29kZU1pcnJvci13cmFwIHByZS5Db2RlTWlycm9yLWxpbmUsLkNvZGVNaXJyb3Itd3JhcCBwcmUuQ29kZU1pcnJvci1saW5lLWxpa2V7d29yZC13cmFwOmJyZWFrLXdvcmQ7d2hpdGUtc3BhY2U6cHJlLXdyYXA7d29yZC1icmVhazpub3JtYWx9LkNvZGVNaXJyb3ItbGluZWJhY2tncm91bmR7Ym90dG9tOjA7bGVmdDowO3Bvc2l0aW9uOmFic29sdXRlO3JpZ2h0OjA7dG9wOjA7ei1pbmRleDowfS5Db2RlTWlycm9yLWxpbmV3aWRnZXR7cGFkZGluZzouMXB4O3Bvc2l0aW9uOnJlbGF0aXZlO3otaW5kZXg6Mn0uQ29kZU1pcnJvci1ydGwgcHJle2RpcmVjdGlvbjpydGx9LkNvZGVNaXJyb3ItY29kZXtvdXRsaW5lOm5vbmV9LkNvZGVNaXJyb3ItZ3V0dGVyLC5Db2RlTWlycm9yLWd1dHRlcnMsLkNvZGVNaXJyb3ItbGluZW51bWJlciwuQ29kZU1pcnJvci1zY3JvbGwsLkNvZGVNaXJyb3Itc2l6ZXJ7Ym94LXNpemluZzpjb250ZW50LWJveH0uQ29kZU1pcnJvci1tZWFzdXJle2hlaWdodDowO292ZXJmbG93OmhpZGRlbjtwb3NpdGlvbjphYnNvbHV0ZTt2aXNpYmlsaXR5OmhpZGRlbjt3aWR0aDoxMDAlfS5Db2RlTWlycm9yLWN1cnNvcntwb2ludGVyLWV2ZW50czpub25lO3Bvc2l0aW9uOmFic29sdXRlfS5Db2RlTWlycm9yLW1lYXN1cmUgcHJle3Bvc2l0aW9uOnN0YXRpY31kaXYuQ29kZU1pcnJvci1jdXJzb3Jze3Bvc2l0aW9uOnJlbGF0aXZlO3Zpc2liaWxpdHk6aGlkZGVuO3otaW5kZXg6M30uQ29kZU1pcnJvci1mb2N1c2VkIGRpdi5Db2RlTWlycm9yLWN1cnNvcnMsZGl2LkNvZGVNaXJyb3ItZHJhZ2N1cnNvcnN7dmlzaWJpbGl0eTp2aXNpYmxlfS5Db2RlTWlycm9yLXNlbGVjdGVke2JhY2tncm91bmQ6I2Q5ZDlkOX0uQ29kZU1pcnJvci1mb2N1c2VkIC5Db2RlTWlycm9yLXNlbGVjdGVke2JhY2tncm91bmQ6I2Q3ZDRmMH0uQ29kZU1pcnJvci1jcm9zc2hhaXJ7Y3Vyc29yOmNyb3NzaGFpcn0uQ29kZU1pcnJvci1saW5lOjpzZWxlY3Rpb24sLkNvZGVNaXJyb3ItbGluZT5zcGFuOjpzZWxlY3Rpb24sLkNvZGVNaXJyb3ItbGluZT5zcGFuPnNwYW46OnNlbGVjdGlvbntiYWNrZ3JvdW5kOiNkN2Q0ZjB9LkNvZGVNaXJyb3ItbGluZTo6LW1vei1zZWxlY3Rpb24sLkNvZGVNaXJyb3ItbGluZT5zcGFuOjotbW96LXNlbGVjdGlvbiwuQ29kZU1pcnJvci1saW5lPnNwYW4+c3Bhbjo6LW1vei1zZWxlY3Rpb257YmFja2dyb3VuZDojZDdkNGYwfS5jbS1zZWFyY2hpbmd7YmFja2dyb3VuZC1jb2xvcjojZmZhO2JhY2tncm91bmQtY29sb3I6cmdiYSgyNTUsMjU1LDAsLjQpfS5jbS1mb3JjZS1ib3JkZXJ7cGFkZGluZy1yaWdodDouMXB4fUBtZWRpYSBwcmludHsuQ29kZU1pcnJvciBkaXYuQ29kZU1pcnJvci1jdXJzb3Jze3Zpc2liaWxpdHk6aGlkZGVufX0uY20tdGFiLXdyYXAtaGFjazphZnRlcntjb250ZW50OlxcXCJcXFwifXNwYW4uQ29kZU1pcnJvci1zZWxlY3RlZHRleHR7YmFja2dyb3VuZDpub25lfVwiLCBcIlwiLHtcInZlcnNpb25cIjozLFwic291cmNlc1wiOltcIndlYnBhY2s6Ly8uL25vZGVfbW9kdWxlcy9jb2RlbWlycm9yL2xpYi9jb2RlbWlycm9yLmNzc1wiXSxcIm5hbWVzXCI6W10sXCJtYXBwaW5nc1wiOlwiQUFFQSxZQUlFLFVBQVksQ0FDWixhQUFjLENBSGQscUJBQXNCLENBQ3RCLFlBR0YsQ0FJQSxrQkFDRSxhQUNGLENBQ0EscUVBRUUsYUFDRixDQUVBLHVEQUNFLHFCQUNGLENBSUEsb0JBRUUsd0JBQXlCLENBRHpCLDJCQUE0QixDQUU1QixrQkFDRixDQUVBLHVCQUlFLFVBQVcsQ0FGWCxjQUFlLENBRGYsbUJBQW9CLENBRXBCLGdCQUFpQixDQUVqQixrQkFDRixDQUVBLHlCQUEyQixVQUFjLENBQ3pDLGdDQUFrQyxVQUFhLENBSS9DLG1CQUNFLDBCQUE0QixDQUM1QixpQkFBa0IsQ0FDbEIsT0FDRixDQUVBLDJDQUNFLDRCQUNGLENBQ0Esa0NBR0UsZUFBZ0IsQ0FEaEIsa0JBQW9CLENBRHBCLFVBR0YsQ0FDQSxzQ0FDRSxTQUNGLENBQ0EsZ0pBRTJELHNCQUF5QixDQUNwRiwrSkFFZ0Usc0JBQXlCLENBQ3pGLGVBQWlCLHVCQUEwQixDQU0zQyx5QkFFRSxJQUFNLDRCQUErQixD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QixhQUFnQixDQUV0QyxpQkFDRSxZQUNGLENBR0EsbUdBTUUsc0JBQ0YsQ0FFQSxvQkFHRSxRQUFTLENBQ1QsZUFBZ0IsQ0FIaEIsaUJBQWtCLENBSWxCLGlCQUFrQixDQUhsQixVQUlGLENBRUEsbUJBRUUsbUJBQW9CLENBRHBCLGlCQUVGLENBQ0Esd0JBQTBCLGVBQWtCLENBRTVDLHVCQUVFLGlCQUFrQixDQURsQixpQkFBa0IsQ0FFbEIsU0FDRixDQUtBLHNFQUNFLGtCQUNGLENBRUEscUJBQXVCLGtCQUFxQixDQUM1Qyx5Q0FBMkMsa0JBQXFCLENBQ2hFLHNCQUF3QixnQkFBbUIsQ0FDM0MsbUdBQTZHLGtCQUFxQixDQUNsSSxrSEFBNEgsa0JBQXFCLENBRWpKLGNBQ0UscUJBQXNCLENBQ3RCLG1DQUNGLENBR0EsaUJBQW1CLGtCQUFxQixDQUV4QyxhQUVFLG1DQUNFLGlCQUNGLENBQ0YsQ0FHQSx3QkFBMEIsVUFBYSxDQUd2Qyw2QkFBK0IsZUFBa0JcIixcInNvdXJjZXNDb250ZW50XCI6W1wiLyogQkFTSUNTICovXFxuXFxuLkNvZGVNaXJyb3Ige1xcbiAgLyogU2V0IGhlaWdodCwgd2lkdGgsIGJvcmRlcnMsIGFuZCBnbG9iYWwgZm9udCBwcm9wZXJ0aWVzIGhlcmUgKi9cXG4gIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7XFxuICBoZWlnaHQ6IDMwMHB4O1xcbiAgY29sb3I6IGJsYWNrO1xcbiAgZGlyZWN0aW9uOiBsdHI7XFxufVxcblxcbi8qIFBBRERJTkcgKi9cXG5cXG4uQ29kZU1pcnJvci1saW5lcyB7XFxuICBwYWRkaW5nOiA0cHggMDsgLyogVmVydGljYWwgcGFkZGluZyBhcm91bmQgY29udGVudCAqL1xcbn1cXG4uQ29kZU1pcnJvciBwcmUuQ29kZU1pcnJvci1saW5lLFxcbi5Db2RlTWlycm9yIHByZS5Db2RlTWlycm9yLWxpbmUtbGlrZSB7XFxuICBwYWRkaW5nOiAwIDRweDsgLyogSG9yaXpvbnRhbCBwYWRkaW5nIG9mIGNvbnRlbnQgKi9cXG59XFxuXFxuLkNvZGVNaXJyb3Itc2Nyb2xsYmFyLWZpbGxlciwgLkNvZGVNaXJyb3ItZ3V0dGVyLWZpbGxlciB7XFxuICBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsgLyogVGhlIGxpdHRsZSBzcXVhcmUgYmV0d2VlbiBIIGFuZCBWIHNjcm9sbGJhcnMgKi9cXG59XFxuXFxuLyogR1VUVEVSICovXFxuXFxuLkNvZGVNaXJyb3ItZ3V0dGVycyB7XFxuICBib3JkZXItcmlnaHQ6IDFweCBzb2xpZCAjZGRkO1xcbiAgYmFja2dyb3VuZC1jb2xvcjogI2Y3ZjdmNztcXG4gIHdoaXRlLXNwYWNlOiBub3dyYXA7XFxufVxcbi5Db2RlTWlycm9yLWxpbmVudW1iZXJzIHt9XFxuLkNvZGVNaXJyb3ItbGluZW51bWJlciB7XFxuICBwYWRkaW5nOiAwIDNweCAwIDVweDtcXG4gIG1pbi13aWR0aDogMjBweDtcXG4gIHRleHQtYWxpZ246IHJpZ2h0O1xcbiAgY29sb3I6ICM5OTk7XFxuICB3aGl0ZS1zcGFjZTogbm93cmFwO1xcbn1cXG5cXG4uQ29kZU1pcnJvci1ndXR0ZXJtYXJrZXIgeyBjb2xvcjogYmxhY2s7IH1cXG4uQ29kZU1pcnJvci1ndXR0ZXJtYXJrZXItc3VidGxlIHsgY29sb3I6ICM5OTk7IH1cXG5cXG4vKiBDVVJTT1IgKi9cXG5cXG4uQ29kZU1pcnJvci1jdXJzb3Ige1xcbiAgYm9yZGVyLWxlZnQ6IDFweCBzb2xpZCBibGFjaztcXG4gIGJvcmRlci1yaWdodDogbm9uZTtcXG4gIHdpZHRoOiAwO1xcbn1cXG4vKiBTaG93biB3aGVuIG1vdmluZyBpbiBiaS1kaXJlY3Rpb25hbCB0ZXh0ICovXFxuLkNvZGVNaXJyb3IgZGl2LkNvZGVNaXJyb3Itc2Vjb25kYXJ5Y3Vyc29yIHtcXG4gIGJvcmRlci1sZWZ0OiAxcHggc29saWQgc2lsdmVyO1xcbn1cXG4uY20tZmF0LWN1cnNvciAuQ29kZU1pcnJvci1jdXJzb3Ige1xcbiAgd2lkdGg6IGF1dG87XFxuICBib3JkZXI6IDAgIWltcG9ydGFudDtcXG4gIGJhY2tncm91bmQ6ICM3ZTc7XFxufVxcbi5jbS1mYXQtY3Vyc29yIGRpdi5Db2RlTWlycm9yLWN1cnNvcnMge1xcbiAgei1pbmRleDogMTtcXG59XFxuLmNtLWZhdC1jdXJzb3IgLkNvZGVNaXJyb3ItbGluZTo6c2VsZWN0aW9uLFxcbi5jbS1mYXQtY3Vyc29yIC5Db2RlTWlycm9yLWxpbmUgPiBzcGFuOjpzZWxlY3Rpb24sIFxcbi5jbS1mYXQtY3Vyc29yIC5Db2RlTWlycm9yLWxpbmUgPiBzcGFuID4gc3Bhbjo6c2VsZWN0aW9uIHsgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7IH1cXG4uY20tZmF0LWN1cnNvciAuQ29kZU1pcnJvci1saW5lOjotbW96LXNlbGVjdGlvbixcXG4uY20tZmF0LWN1cnNvciAuQ29kZU1pcnJvci1saW5lID4gc3Bhbjo6LW1vei1zZWxlY3Rpb24sXFxuLmNtLWZhdC1jdXJzb3IgLkNvZGVNaXJyb3ItbGluZSA+IHNwYW4gPiBzcGFuOjotbW96LXNlbGVjdGlvbiB7IGJhY2tncm91bmQ6IHRyYW5zcGFyZW50OyB9XFxuLmNtLWZhdC1jdXJzb3IgeyBjYXJldC1jb2xvcjogdHJhbnNwYXJlbnQ7IH1cXG5ALW1vei1rZXlmcmFtZXMgYmxpbmsge1xcbiAgMCUge31cXG4gIDUwJSB7IGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50OyB9XFxuICAxMDAlIHt9XFxufVxcbkAtd2Via2l0LWtleWZyYW1lcyBibGluayB7XFxuICAwJSB7fVxcbiAgNTAlIHsgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7IH1cXG4gIDEwMCUge31cXG59XFxuQGtleWZyYW1lcyBibGluayB7XFxuICAwJSB7fVxcbiAgNTAlIHsgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7IH1cXG4gIDEwMCUge31cXG59XFxuXFxuLyogQ2FuIHN0eWxlIGN1cnNvciBkaWZmZXJlbnQgaW4gb3ZlcndyaXRlIChub24taW5zZXJ0KSBtb2RlICovXFxuLkNvZGVNaXJyb3Itb3ZlcndyaXRlIC5Db2RlTWlycm9yLWN1cnNvciB7fVxcblxcbi5jbS10YWIgeyBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHRleHQtZGVjb3JhdGlvbjogaW5oZXJpdDsgfVxcblxcbi5Db2RlTWlycm9yLXJ1bGVycyB7XFxuICBwb3NpdGlvbjogYWJzb2x1dGU7XFxuICBsZWZ0OiAwOyByaWdodDogMDsgdG9wOiAtNTBweDsgYm90dG9tOiAwO1xcbiAgb3ZlcmZsb3c6IGhpZGRlbjtcXG59XFxuLkNvZGVNaXJyb3ItcnVsZXIge1xcbiAgYm9yZGVyLWxlZnQ6IDFweCBzb2xpZCAjY2NjO1xcbiAgdG9wOiAwOyBib3R0b206IDA7XFxuICBwb3NpdGlvbjogYWJzb2x1dGU7XFxufVxcblxcbi8qIERFRkFVTFQgVEhFTUUgKi9cXG5cXG4uY20tcy1kZWZhdWx0IC5jbS1oZWFkZXIge2NvbG9yOiBibHVlO31cXG4uY20tcy1kZWZhdWx0IC5jbS1xdW90ZSB7Y29sb3I6ICMwOTA7fVxcbi5jbS1uZWdhdGl2ZSB7Y29sb3I6ICNkNDQ7fVxcbi5jbS1wb3NpdGl2ZSB7Y29sb3I6ICMyOTI7fVxcbi5jbS1oZWFkZXIsIC5jbS1zdHJvbmcge2ZvbnQtd2VpZ2h0OiBib2xkO31cXG4uY20tZW0ge2ZvbnQtc3R5bGU6IGl0YWxpYzt9XFxuLmNtLWxpbmsge3RleHQtZGVjb3JhdGlvbjogdW5kZXJsaW5lO31cXG4uY20tc3RyaWtldGhyb3VnaCB7dGV4dC1kZWNvcmF0aW9uOiBsaW5lLXRocm91Z2g7fVxcblxcbi5jbS1zLWRlZmF1bHQgLmNtLWtleXdvcmQge2NvbG9yOiAjNzA4O31cXG4uY20tcy1kZWZhdWx0IC5jbS1hdG9tIHtjb2xvcjogIzIxOTt9XFxuLmNtLXMtZGVmYXVsdCAuY20tbnVtYmVyIHtjb2xvcjogIzE2NDt9XFxuLmNtLXMtZGVmYXVsdCAuY20tZGVmIHtjb2xvcjogIzAwZjt9XFxuLmNtLXMtZGVmYXVsdCAuY20tdmFyaWFibGUsXFxuLmNtLXMtZGVmYXVsdCAuY20tcHVuY3R1YXRpb24sXFxuLmNtLXMtZGVmYXVsdCAuY20tcHJvcGVydHksXFxuLmNtLXMtZGVmYXVsdCAuY20tb3BlcmF0b3Ige31cXG4uY20tcy1kZWZhdWx0IC5jbS12YXJpYWJsZS0yIHtjb2xvcjogIzA1YTt9XFxuLmNtLXMtZGVmYXVsdCAuY20tdmFyaWFibGUtMywgLmNtLXMtZGVmYXVsdCAuY20tdHlwZSB7Y29sb3I6ICMwODU7fVxcbi5jbS1zLWRlZmF1bHQgLmNtLWNvbW1lbnQge2NvbG9yOiAjYTUwO31cXG4uY20tcy1kZWZhdWx0IC5jbS1zdHJpbmcge2NvbG9yOiAjYTExO31cXG4uY20tcy1kZWZhdWx0IC5jbS1zdHJpbmctMiB7Y29sb3I6ICNmNTA7fVxcbi5jbS1zLWRlZmF1bHQgLmNtLW1ldGEge2NvbG9yOiAjNTU1O31cXG4uY20tcy1kZWZhdWx0IC5jbS1xdWFsaWZpZXIge2NvbG9yOiAjNTU1O31cXG4uY20tcy1kZWZhdWx0IC5jbS1idWlsdGluIHtjb2xvcjogIzMwYTt9XFxuLmNtLXMtZGVmYXVsdCAuY20tYnJhY2tldCB7Y29sb3I6ICM5OTc7fVxcbi5jbS1zLWRlZmF1bHQgLmNtLXRhZyB7Y29sb3I6ICMxNzA7fVxcbi5jbS1zLWRlZmF1bHQgLmNtLWF0dHJpYnV0ZSB7Y29sb3I6ICMwMGM7fVxcbi5jbS1zLWRlZmF1bHQgLmNtLWhyIHtjb2xvcjogIzk5OTt9XFxuLmNtLXMtZGVmYXVsdCAuY20tbGluayB7Y29sb3I6ICMwMGM7fVxcblxcbi5jbS1zLWRlZmF1bHQgLmNtLWVycm9yIHtjb2xvcjogI2YwMDt9XFxuLmNtLWludmFsaWRjaGFyIHtjb2xvcjogI2YwMDt9XFxuXFxuLkNvZGVNaXJyb3ItY29tcG9zaW5nIHsgYm9yZGVyLWJvdHRvbTogMnB4IHNvbGlkOyB9XFxuXFxuLyogRGVmYXVsdCBzdHlsZXMgZm9yIGNvbW1vbiBhZGRvbnMgKi9cXG5cXG5kaXYuQ29kZU1pcnJvciBzcGFuLkNvZGVNaXJyb3ItbWF0Y2hpbmdicmFja2V0IHtjb2xvcjogIzBiMDt9XFxuZGl2LkNvZGVNaXJyb3Igc3Bhbi5Db2RlTWlycm9yLW5vbm1hdGNoaW5nYnJhY2tldCB7Y29sb3I6ICNhMjI7fVxcbi5Db2RlTWlycm9yLW1hdGNoaW5ndGFnIHsgYmFja2dyb3VuZDogcmdiYSgyNTUsIDE1MCwgMCwgLjMpOyB9XFxuLkNvZGVNaXJyb3ItYWN0aXZlbGluZS1iYWNrZ3JvdW5kIHtiYWNrZ3JvdW5kOiAjZThmMmZmO31cXG5cXG4vKiBTVE9QICovXFxuXFxuLyogVGhlIHJlc3Qgb2YgdGhpcyBmaWxlIGNvbnRhaW5zIHN0eWxlcyByZWxhdGVkIHRvIHRoZSBtZWNoYW5pY3Mgb2ZcXG4gICB0aGUgZWRpdG9yLiBZb3UgcHJvYmFibHkgc2hvdWxkbid0IHRvdWNoIHRoZW0uICovXFxuXFxuLkNvZGVNaXJyb3Ige1xcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xcbiAgb3ZlcmZsb3c6IGhpZGRlbjtcXG4gIGJhY2tncm91bmQ6IHdoaXRlO1xcbn1cXG5cXG4uQ29kZU1pcnJvci1zY3JvbGwge1xcbiAgb3ZlcmZsb3c6IHNjcm9sbCAhaW1wb3J0YW50OyAvKiBUaGluZ3Mgd2lsbCBicmVhayBpZiB0aGlzIGlzIG92ZXJyaWRkZW4gKi9cXG4gIC8qIDUwcHggaXMgdGhlIG1hZ2ljIG1hcmdpbiB1c2VkIHRvIGhpZGUgdGhlIGVsZW1lbnQncyByZWFsIHNjcm9sbGJhcnMgKi9cXG4gIC8qIFNlZSBvdmVyZmxvdzogaGlkZGVuIGluIC5Db2RlTWlycm9yICovXFxuICBtYXJnaW4tYm90dG9tOiAtNTBweDsgbWFyZ2luLXJpZ2h0OiAtNTBweDtcXG4gIHBhZGRpbmctYm90dG9tOiA1MHB4O1xcbiAgaGVpZ2h0OiAxMDAlO1xcbiAgb3V0bGluZTogbm9uZTsgLyogUHJldmVudCBkcmFnZ2luZyBmcm9tIGhpZ2hsaWdodGluZyB0aGUgZWxlbWVudCAqL1xcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xcbiAgei1pbmRleDogMDtcXG59XFxuLkNvZGVNaXJyb3Itc2l6ZXIge1xcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xcbiAgYm9yZGVyLXJpZ2h0OiA1MHB4IHNvbGlkIHRyYW5zcGFyZW50O1xcbn1cXG5cXG4vKiBUaGUgZmFrZSwgdmlzaWJsZSBzY3JvbGxiYXJzLiBVc2VkIHRvIGZvcmNlIHJlZHJhdyBkdXJpbmcgc2Nyb2xsaW5nXFxuICAgYmVmb3JlIGFjdHVhbCBzY3JvbGxpbmcgaGFwcGVucywgdGh1cyBwcmV2ZW50aW5nIHNoYWtpbmcgYW5kXFxuICAgZmxpY2tlcmluZyBhcnRpZmFjdHMuICovXFxuLkNvZGVNaXJyb3ItdnNjcm9sbGJhciwgLkNvZGVNaXJyb3ItaHNjcm9sbGJhciwgLkNvZGVNaXJyb3Itc2Nyb2xsYmFyLWZpbGxlciwgLkNvZGVNaXJyb3ItZ3V0dGVyLWZpbGxlciB7XFxuICBwb3NpdGlvbjogYWJzb2x1dGU7XFxuICB6LWluZGV4OiA2O1xcbiAgZGlzcGxheTogbm9uZTtcXG4gIG91dGxpbmU6IG5vbmU7XFxufVxcbi5Db2RlTWlycm9yLXZzY3JvbGxiYXIge1xcbiAgcmlnaHQ6IDA7IHRvcDogMDtcXG4gIG92ZXJmbG93LXg6IGhpZGRlbjtcXG4gIG92ZXJmbG93LXk6IHNjcm9sbDtcXG59XFxuLkNvZGVNaXJyb3ItaHNjcm9sbGJhciB7XFxuICBib3R0b206IDA7IGxlZnQ6IDA7XFxuICBvdmVyZmxvdy15OiBoaWRkZW47XFxuICBvdmVyZmxvdy14OiBzY3JvbGw7XFxufVxcbi5Db2RlTWlycm9yLXNjcm9sbGJhci1maWxsZXIge1xcbiAgcmlnaHQ6IDA7IGJvdHRvbTogMDtcXG59XFxuLkNvZGVNaXJyb3ItZ3V0dGVyLWZpbGxlciB7XFxuICBsZWZ0OiAwOyBib3R0b206IDA7XFxufVxcblxcbi5Db2RlTWlycm9yLWd1dHRlcnMge1xcbiAgcG9zaXRpb246IGFic29sdXRlOyBsZWZ0OiAwOyB0b3A6IDA7XFxuICBtaW4taGVpZ2h0OiAxMDAlO1xcbiAgei1pbmRleDogMztcXG59XFxuLkNvZGVNaXJyb3ItZ3V0dGVyIHtcXG4gIHdoaXRlLXNwYWNlOiBub3JtYWw7XFxuICBoZWlnaHQ6IDEwMCU7XFxuICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XFxuICB2ZXJ0aWNhbC1hbGlnbjogdG9wO1xcbiAgbWFyZ2luLWJvdHRvbTogLTUwcHg7XFxufVxcbi5Db2RlTWlycm9yLWd1dHRlci13cmFwcGVyIHtcXG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcXG4gIHotaW5kZXg6IDQ7XFxuICBiYWNrZ3JvdW5kOiBub25lICFpbXBvcnRhbnQ7XFxuICBib3JkZXI6IG5vbmUgIWltcG9ydGFudDtcXG59XFxuLkNvZGVNaXJyb3ItZ3V0dGVyLWJhY2tncm91bmQge1xcbiAgcG9zaXRpb246IGFic29sdXRlO1xcbiAgdG9wOiAwOyBib3R0b206IDA7XFxuICB6LWluZGV4OiA0O1xcbn1cXG4uQ29kZU1pcnJvci1ndXR0ZXItZWx0IHtcXG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcXG4gIGN1cnNvcjogZGVmYXVsdDtcXG4gIHotaW5kZXg6IDQ7XFxufVxcbi5Db2RlTWlycm9yLWd1dHRlci13cmFwcGVyIDo6c2VsZWN0aW9uIHsgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgfVxcbi5Db2RlTWlycm9yLWd1dHRlci13cmFwcGVyIDo6LW1vei1zZWxlY3Rpb24geyBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudCB9XFxuXFxuLkNvZGVNaXJyb3ItbGluZXMge1xcbiAgY3Vyc29yOiB0ZXh0O1xcbiAgbWluLWhlaWdodDogMXB4OyAvKiBwcmV2ZW50cyBjb2xsYXBzaW5nIGJlZm9yZSBmaXJzdCBkcmF3ICovXFxufVxcbi5Db2RlTWlycm9yIHByZS5Db2RlTWlycm9yLWxpbmUsXFxuLkNvZGVNaXJyb3IgcHJlLkNvZGVNaXJyb3ItbGluZS1saWtlIHtcXG4gIC8qIFJlc2V0IHNvbWUgc3R5bGVzIHRoYXQgdGhlIHJlc3Qgb2YgdGhlIHBhZ2UgbWlnaHQgaGF2ZSBzZXQgKi9cXG4gIC1tb3otYm9yZGVyLXJhZGl1czogMDsgLXdlYmtpdC1ib3JkZXItcmFkaXVzOiAwOyBib3JkZXItcmFkaXVzOiAwO1xcbiAgYm9yZGVyLXdpZHRoOiAwO1xcbiAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XFxuICBmb250LWZhbWlseTogaW5oZXJpdDtcXG4gIGZvbnQtc2l6ZTogaW5oZXJpdDtcXG4gIG1hcmdpbjogMDtcXG4gIHdoaXRlLXNwYWNlOiBwcmU7XFxuICB3b3JkLXdyYXA6IG5vcm1hbDtcXG4gIGxpbmUtaGVpZ2h0OiBpbmhlcml0O1xcbiAgY29sb3I6IGluaGVyaXQ7XFxuICB6LWluZGV4OiAyO1xcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xcbiAgb3ZlcmZsb3c6IHZpc2libGU7XFxuICAtd2Via2l0LXRhcC1oaWdobGlnaHQtY29sb3I6IHRyYW5zcGFyZW50O1xcbiAgLXdlYmtpdC1mb250LXZhcmlhbnQtbGlnYXR1cmVzOiBjb250ZXh0dWFsO1xcbiAgZm9udC12YXJpYW50LWxpZ2F0dXJlczogY29udGV4dHVhbDtcXG59XFxuLkNvZGVNaXJyb3Itd3JhcCBwcmUuQ29kZU1pcnJvci1saW5lLFxcbi5Db2RlTWlycm9yLXdyYXAgcHJlLkNvZGVNaXJyb3ItbGluZS1saWtlIHtcXG4gIHdvcmQtd3JhcDogYnJlYWstd29yZDtcXG4gIHdoaXRlLXNwYWNlOiBwcmUtd3JhcDtcXG4gIHdvcmQtYnJlYWs6IG5vcm1hbDtcXG59XFxuXFxuLkNvZGVNaXJyb3ItbGluZWJhY2tncm91bmQge1xcbiAgcG9zaXRpb246IGFic29sdXRlO1xcbiAgbGVmdDogMDsgcmlnaHQ6IDA7IHRvcDogMDsgYm90dG9tOiAwO1xcbiAgei1pbmRleDogMDtcXG59XFxuXFxuLkNvZGVNaXJyb3ItbGluZXdpZGdldCB7XFxuICBwb3NpdGlvbjogcmVsYXRpdmU7XFxuICB6LWluZGV4OiAyO1xcbiAgcGFkZGluZzogMC4xcHg7IC8qIEZvcmNlIHdpZGdldCBtYXJnaW5zIHRvIHN0YXkgaW5zaWRlIG9mIHRoZSBjb250YWluZXIgKi9cXG59XFxuXFxuLkNvZGVNaXJyb3Itd2lkZ2V0IHt9XFxuXFxuLkNvZGVNaXJyb3ItcnRsIHByZSB7IGRpcmVjdGlvbjogcnRsOyB9XFxuXFxuLkNvZGVNaXJyb3ItY29kZSB7XFxuICBvdXRsaW5lOiBub25lO1xcbn1cXG5cXG4vKiBGb3JjZSBjb250ZW50LWJveCBzaXppbmcgZm9yIHRoZSBlbGVtZW50cyB3aGVyZSB3ZSBleHBlY3QgaXQgKi9cXG4uQ29kZU1pcnJvci1zY3JvbGwsXFxuLkNvZGVNaXJyb3Itc2l6ZXIsXFxuLkNvZGVNaXJyb3ItZ3V0dGVyLFxcbi5Db2RlTWlycm9yLWd1dHRlcnMsXFxuLkNvZGVNaXJyb3ItbGluZW51bWJlciB7XFxuICAtbW96LWJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xcbiAgYm94LXNpemluZzogY29udGVudC1ib3g7XFxufVxcblxcbi5Db2RlTWlycm9yLW1lYXN1cmUge1xcbiAgcG9zaXRpb246IGFic29sdXRlO1xcbiAgd2lkdGg6IDEwMCU7XFxuICBoZWlnaHQ6IDA7XFxuICBvdmVyZmxvdzogaGlkZGVuO1xcbiAgdmlzaWJpbGl0eTogaGlkZGVuO1xcbn1cXG5cXG4uQ29kZU1pcnJvci1jdXJzb3Ige1xcbiAgcG9zaXRpb246IGFic29sdXRlO1xcbiAgcG9pbnRlci1ldmVudHM6IG5vbmU7XFxufVxcbi5Db2RlTWlycm9yLW1lYXN1cmUgcHJlIHsgcG9zaXRpb246IHN0YXRpYzsgfVxcblxcbmRpdi5Db2RlTWlycm9yLWN1cnNvcnMge1xcbiAgdmlzaWJpbGl0eTogaGlkZGVuO1xcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xcbiAgei1pbmRleDogMztcXG59XFxuZGl2LkNvZGVNaXJyb3ItZHJhZ2N1cnNvcnMge1xcbiAgdmlzaWJpbGl0eTogdmlzaWJsZTtcXG59XFxuXFxuLkNvZGVNaXJyb3ItZm9jdXNlZCBkaXYuQ29kZU1pcnJvci1jdXJzb3JzIHtcXG4gIHZpc2liaWxpdHk6IHZpc2libGU7XFxufVxcblxcbi5Db2RlTWlycm9yLXNlbGVjdGVkIHsgYmFja2dyb3VuZDogI2Q5ZDlkOTsgfVxcbi5Db2RlTWlycm9yLWZvY3VzZWQgLkNvZGVNaXJyb3Itc2VsZWN0ZWQgeyBiYWNrZ3JvdW5kOiAjZDdkNGYwOyB9XFxuLkNvZGVNaXJyb3ItY3Jvc3NoYWlyIHsgY3Vyc29yOiBjcm9zc2hhaXI7IH1cXG4uQ29kZU1pcnJvci1saW5lOjpzZWxlY3Rpb24sIC5Db2RlTWlycm9yLWxpbmUgPiBzcGFuOjpzZWxlY3Rpb24sIC5Db2RlTWlycm9yLWxpbmUgPiBzcGFuID4gc3Bhbjo6c2VsZWN0aW9uIHsgYmFja2dyb3VuZDogI2Q3ZDRmMDsgfVxcbi5Db2RlTWlycm9yLWxpbmU6Oi1tb3otc2VsZWN0aW9uLCAuQ29kZU1pcnJvci1saW5lID4gc3Bhbjo6LW1vei1zZWxlY3Rpb24sIC5Db2RlTWlycm9yLWxpbmUgPiBzcGFuID4gc3Bhbjo6LW1vei1zZWxlY3Rpb24geyBiYWNrZ3JvdW5kOiAjZDdkNGYwOyB9XFxuXFxuLmNtLXNlYXJjaGluZyB7XFxuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZhO1xcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyNTUsIDI1NSwgMCwgLjQpO1xcbn1cXG5cXG4vKiBVc2VkIHRvIGZvcmNlIGEgYm9yZGVyIG1vZGVsIGZvciBhIG5vZGUgKi9cXG4uY20tZm9yY2UtYm9yZGVyIHsgcGFkZGluZy1yaWdodDogLjFweDsgfVxcblxcbkBtZWRpYSBwcmludCB7XFxuICAvKiBIaWRlIHRoZSBjdXJzb3Igd2hlbiBwcmludGluZyAqL1xcbiAgLkNvZGVNaXJyb3IgZGl2LkNvZGVNaXJyb3ItY3Vyc29ycyB7XFxuICAgIHZpc2liaWxpdHk6IGhpZGRlbjtcXG4gIH1cXG59XFxuXFxuLyogU2VlIGlzc3VlICMyOTAxICovXFxuLmNtLXRhYi13cmFwLWhhY2s6YWZ0ZXIgeyBjb250ZW50OiAnJzsgfVxcblxcbi8qIEhlbHAgdXNlcnMgdXNlIG1hcmtzZWxlY3Rpb24gdG8gc2FmZWx5IHN0eWxlIHRleHQgYmFja2dyb3VuZCAqL1xcbnNwYW4uQ29kZU1pcnJvci1zZWxlY3RlZHRleHQgeyBiYWNrZ3JvdW5kOiBub25lOyB9XFxuXCJdLFwic291cmNlUm9vdFwiOlwiXCJ9XSk7XG4vLyBFeHBvcnRzXG5leHBvcnQgZGVmYXVsdCBfX19DU1NfTE9BREVSX0VYUE9SVF9fXztcbiIsIi8vIEltcG9ydHNcbmltcG9ydCBfX19DU1NfTE9BREVSX0FQSV9TT1VSQ0VNQVBfSU1QT1JUX19fIGZyb20gXCIuLi8uLi9jc3MtbG9hZGVyL2Rpc3QvcnVudGltZS9jc3NXaXRoTWFwcGluZ1RvU3RyaW5nLmpzXCI7XG5pbXBvcnQgX19fQ1NTX0xPQURFUl9BUElfSU1QT1JUX19fIGZyb20gXCIuLi8uLi9jc3MtbG9hZGVyL2Rpc3QvcnVudGltZS9hcGkuanNcIjtcbnZhciBfX19DU1NfTE9BREVSX0VYUE9SVF9fXyA9IF9fX0NTU19MT0FERVJfQVBJX0lNUE9SVF9fXyhfX19DU1NfTE9BREVSX0FQSV9TT1VSQ0VNQVBfSU1QT1JUX19fKTtcbi8vIE1vZHVsZVxuX19fQ1NTX0xPQURFUl9FWFBPUlRfX18ucHVzaChbbW9kdWxlLmlkLCBcIi5jbS1zLXR3aWxpZ2h0LkNvZGVNaXJyb3J7YmFja2dyb3VuZDojMTQxNDE0O2NvbG9yOiNmN2Y3Zjd9LmNtLXMtdHdpbGlnaHQgZGl2LkNvZGVNaXJyb3Itc2VsZWN0ZWR7YmFja2dyb3VuZDojMzIzMjMyfS5jbS1zLXR3aWxpZ2h0IC5Db2RlTWlycm9yLWxpbmU6OnNlbGVjdGlvbiwuY20tcy10d2lsaWdodCAuQ29kZU1pcnJvci1saW5lPnNwYW46OnNlbGVjdGlvbiwuY20tcy10d2lsaWdodCAuQ29kZU1pcnJvci1saW5lPnNwYW4+c3Bhbjo6c2VsZWN0aW9ue2JhY2tncm91bmQ6cmdiYSg1MCw1MCw1MCwuOTkpfS5jbS1zLXR3aWxpZ2h0IC5Db2RlTWlycm9yLWxpbmU6Oi1tb3otc2VsZWN0aW9uLC5jbS1zLXR3aWxpZ2h0IC5Db2RlTWlycm9yLWxpbmU+c3Bhbjo6LW1vei1zZWxlY3Rpb24sLmNtLXMtdHdpbGlnaHQgLkNvZGVNaXJyb3ItbGluZT5zcGFuPnNwYW46Oi1tb3otc2VsZWN0aW9ue2JhY2tncm91bmQ6cmdiYSg1MCw1MCw1MCwuOTkpfS5jbS1zLXR3aWxpZ2h0IC5Db2RlTWlycm9yLWd1dHRlcnN7YmFja2dyb3VuZDojMjIyO2JvcmRlci1yaWdodDoxcHggc29saWQgI2FhYX0uY20tcy10d2lsaWdodCAuQ29kZU1pcnJvci1ndXR0ZXJtYXJrZXJ7Y29sb3I6I2ZmZn0uY20tcy10d2lsaWdodCAuQ29kZU1pcnJvci1ndXR0ZXJtYXJrZXItc3VidGxlLC5jbS1zLXR3aWxpZ2h0IC5Db2RlTWlycm9yLWxpbmVudW1iZXJ7Y29sb3I6I2FhYX0uY20tcy10d2lsaWdodCAuQ29kZU1pcnJvci1jdXJzb3J7Ym9yZGVyLWxlZnQ6MXB4IHNvbGlkICNmZmZ9LmNtLXMtdHdpbGlnaHQgLmNtLWtleXdvcmR7Y29sb3I6I2Y5ZWU5OH0uY20tcy10d2lsaWdodCAuY20tYXRvbXtjb2xvcjojZmMwfS5jbS1zLXR3aWxpZ2h0IC5jbS1udW1iZXJ7Y29sb3I6I2NhNzg0MX0uY20tcy10d2lsaWdodCAuY20tZGVme2NvbG9yOiM4ZGE2Y2V9LmNtLXMtdHdpbGlnaHQgc3Bhbi5jbS1kZWYsLmNtLXMtdHdpbGlnaHQgc3Bhbi5jbS10YWcsLmNtLXMtdHdpbGlnaHQgc3Bhbi5jbS10eXBlLC5jbS1zLXR3aWxpZ2h0IHNwYW4uY20tdmFyaWFibGUtMiwuY20tcy10d2lsaWdodCBzcGFuLmNtLXZhcmlhYmxlLTN7Y29sb3I6IzYwNzM5Mn0uY20tcy10d2lsaWdodCAuY20tb3BlcmF0b3J7Y29sb3I6I2NkYTg2OX0uY20tcy10d2lsaWdodCAuY20tY29tbWVudHtjb2xvcjojNzc3O2ZvbnQtc3R5bGU6aXRhbGljO2ZvbnQtd2VpZ2h0OjQwMH0uY20tcy10d2lsaWdodCAuY20tc3RyaW5ne2NvbG9yOiM4ZjlkNmE7Zm9udC1zdHlsZTppdGFsaWN9LmNtLXMtdHdpbGlnaHQgLmNtLXN0cmluZy0ye2NvbG9yOiNiZDZiMTh9LmNtLXMtdHdpbGlnaHQgLmNtLW1ldGF7YmFja2dyb3VuZC1jb2xvcjojMTQxNDE0O2NvbG9yOiNmN2Y3Zjd9LmNtLXMtdHdpbGlnaHQgLmNtLWJ1aWx0aW57Y29sb3I6I2NkYTg2OX0uY20tcy10d2lsaWdodCAuY20tdGFne2NvbG9yOiM5OTc2NDN9LmNtLXMtdHdpbGlnaHQgLmNtLWF0dHJpYnV0ZXtjb2xvcjojZDZiYjZkfS5jbS1zLXR3aWxpZ2h0IC5jbS1oZWFkZXJ7Y29sb3I6I2ZmNjQwMH0uY20tcy10d2lsaWdodCAuY20taHJ7Y29sb3I6I2FlYWVhZX0uY20tcy10d2lsaWdodCAuY20tbGlua3tjb2xvcjojYWQ5MzYxO2ZvbnQtc3R5bGU6aXRhbGljO3RleHQtZGVjb3JhdGlvbjpub25lfS5jbS1zLXR3aWxpZ2h0IC5jbS1lcnJvcntib3JkZXItYm90dG9tOjFweCBzb2xpZCByZWR9LmNtLXMtdHdpbGlnaHQgLkNvZGVNaXJyb3ItYWN0aXZlbGluZS1iYWNrZ3JvdW5ke2JhY2tncm91bmQ6IzI3MjgyZX0uY20tcy10d2lsaWdodCAuQ29kZU1pcnJvci1tYXRjaGluZ2JyYWNrZXR7Y29sb3I6I2ZmZiFpbXBvcnRhbnQ7b3V0bGluZToxcHggc29saWQgZ3JleX1cIiwgXCJcIix7XCJ2ZXJzaW9uXCI6MyxcInNvdXJjZXNcIjpbXCJ3ZWJwYWNrOi8vLi9ub2RlX21vZHVsZXMvY29kZW1pcnJvci90aGVtZS90d2lsaWdodC5jc3NcIl0sXCJuYW1lc1wiOltdLFwibWFwcGluZ3NcIjpcIkFBQUEsMEJBQTRCLGtCQUFtQixDQUFFLGFBQWdCLENBQ2pFLHVDQUF5QyxrQkFBcUIsQ0FDOUQsZ0pBQTBKLDZCQUFvQyxDQUM5TCwrSkFBeUssNkJBQW9DLENBRTdNLG1DQUFxQyxlQUFnQixDQUFFLDJCQUE4QixDQUNyRix3Q0FBMEMsVUFBYyxDQUV4RCxxRkFBd0MsVUFBYSxDQUNyRCxrQ0FBb0MsMEJBQThCLENBRWxFLDJCQUE2QixhQUFnQixDQUM3Qyx3QkFBMEIsVUFBYSxDQUN2QywwQkFBNEIsYUFBaUIsQ0FDN0MsdUJBQXlCLGFBQWdCLENBRXpDLHNKQUE2RixhQUFnQixDQUM3Ryw0QkFBOEIsYUFBZ0IsQ0FDOUMsMkJBQTZCLFVBQVUsQ0FBRSxpQkFBaUIsQ0FBRSxlQUFvQixDQUNoRiwwQkFBNEIsYUFBYSxDQUFFLGlCQUFtQixDQUM5RCw0QkFBOEIsYUFBZSxDQUM3Qyx3QkFBMEIsd0JBQXdCLENBQUUsYUFBZSxDQUNuRSwyQkFBNkIsYUFBZ0IsQ0FDN0MsdUJBQXlCLGFBQWdCLENBQ3pDLDZCQUErQixhQUFnQixDQUMvQywwQkFBNEIsYUFBZ0IsQ0FDNUMsc0JBQXdCLGFBQWdCLENBQ3hDLHdCQUEwQixhQUFhLENBQUUsaUJBQWlCLENBQUUsb0JBQXNCLENBQ2xGLHlCQUEyQiwyQkFBOEIsQ0FFekQsaURBQW1ELGtCQUFxQixDQUN4RSwyQ0FBcUUsb0JBQXNCLENBQTlDLHNCQUFnRFwiLFwic291cmNlc0NvbnRlbnRcIjpbXCIuY20tcy10d2lsaWdodC5Db2RlTWlycm9yIHsgYmFja2dyb3VuZDogIzE0MTQxNDsgY29sb3I6ICNmN2Y3Zjc7IH0gLyoqL1xcbi5jbS1zLXR3aWxpZ2h0IGRpdi5Db2RlTWlycm9yLXNlbGVjdGVkIHsgYmFja2dyb3VuZDogIzMyMzIzMjsgfSAvKiovXFxuLmNtLXMtdHdpbGlnaHQgLkNvZGVNaXJyb3ItbGluZTo6c2VsZWN0aW9uLCAuY20tcy10d2lsaWdodCAuQ29kZU1pcnJvci1saW5lID4gc3Bhbjo6c2VsZWN0aW9uLCAuY20tcy10d2lsaWdodCAuQ29kZU1pcnJvci1saW5lID4gc3BhbiA+IHNwYW46OnNlbGVjdGlvbiB7IGJhY2tncm91bmQ6IHJnYmEoNTAsIDUwLCA1MCwgMC45OSk7IH1cXG4uY20tcy10d2lsaWdodCAuQ29kZU1pcnJvci1saW5lOjotbW96LXNlbGVjdGlvbiwgLmNtLXMtdHdpbGlnaHQgLkNvZGVNaXJyb3ItbGluZSA+IHNwYW46Oi1tb3otc2VsZWN0aW9uLCAuY20tcy10d2lsaWdodCAuQ29kZU1pcnJvci1saW5lID4gc3BhbiA+IHNwYW46Oi1tb3otc2VsZWN0aW9uIHsgYmFja2dyb3VuZDogcmdiYSg1MCwgNTAsIDUwLCAwLjk5KTsgfVxcblxcbi5jbS1zLXR3aWxpZ2h0IC5Db2RlTWlycm9yLWd1dHRlcnMgeyBiYWNrZ3JvdW5kOiAjMjIyOyBib3JkZXItcmlnaHQ6IDFweCBzb2xpZCAjYWFhOyB9XFxuLmNtLXMtdHdpbGlnaHQgLkNvZGVNaXJyb3ItZ3V0dGVybWFya2VyIHsgY29sb3I6IHdoaXRlOyB9XFxuLmNtLXMtdHdpbGlnaHQgLkNvZGVNaXJyb3ItZ3V0dGVybWFya2VyLXN1YnRsZSB7IGNvbG9yOiAjYWFhOyB9XFxuLmNtLXMtdHdpbGlnaHQgLkNvZGVNaXJyb3ItbGluZW51bWJlciB7IGNvbG9yOiAjYWFhOyB9XFxuLmNtLXMtdHdpbGlnaHQgLkNvZGVNaXJyb3ItY3Vyc29yIHsgYm9yZGVyLWxlZnQ6IDFweCBzb2xpZCB3aGl0ZTsgfVxcblxcbi5jbS1zLXR3aWxpZ2h0IC5jbS1rZXl3b3JkIHsgY29sb3I6ICNmOWVlOTg7IH0gLyoqL1xcbi5jbS1zLXR3aWxpZ2h0IC5jbS1hdG9tIHsgY29sb3I6ICNGQzA7IH1cXG4uY20tcy10d2lsaWdodCAuY20tbnVtYmVyIHsgY29sb3I6ICAjY2E3ODQxOyB9IC8qKi9cXG4uY20tcy10d2lsaWdodCAuY20tZGVmIHsgY29sb3I6ICM4REE2Q0U7IH1cXG4uY20tcy10d2lsaWdodCBzcGFuLmNtLXZhcmlhYmxlLTIsIC5jbS1zLXR3aWxpZ2h0IHNwYW4uY20tdGFnIHsgY29sb3I6ICM2MDczOTI7IH0gLyoqL1xcbi5jbS1zLXR3aWxpZ2h0IHNwYW4uY20tdmFyaWFibGUtMywgLmNtLXMtdHdpbGlnaHQgc3Bhbi5jbS1kZWYsIC5jbS1zLXR3aWxpZ2h0IHNwYW4uY20tdHlwZSB7IGNvbG9yOiAjNjA3MzkyOyB9IC8qKi9cXG4uY20tcy10d2lsaWdodCAuY20tb3BlcmF0b3IgeyBjb2xvcjogI2NkYTg2OTsgfSAvKiovXFxuLmNtLXMtdHdpbGlnaHQgLmNtLWNvbW1lbnQgeyBjb2xvcjojNzc3OyBmb250LXN0eWxlOml0YWxpYzsgZm9udC13ZWlnaHQ6bm9ybWFsOyB9IC8qKi9cXG4uY20tcy10d2lsaWdodCAuY20tc3RyaW5nIHsgY29sb3I6IzhmOWQ2YTsgZm9udC1zdHlsZTppdGFsaWM7IH0gLyoqL1xcbi5jbS1zLXR3aWxpZ2h0IC5jbS1zdHJpbmctMiB7IGNvbG9yOiNiZDZiMTg7IH0gLyo/Ki9cXG4uY20tcy10d2lsaWdodCAuY20tbWV0YSB7IGJhY2tncm91bmQtY29sb3I6IzE0MTQxNDsgY29sb3I6I2Y3ZjdmNzsgfSAvKj8qL1xcbi5jbS1zLXR3aWxpZ2h0IC5jbS1idWlsdGluIHsgY29sb3I6ICNjZGE4Njk7IH0gLyo/Ki9cXG4uY20tcy10d2lsaWdodCAuY20tdGFnIHsgY29sb3I6ICM5OTc2NDM7IH0gLyoqL1xcbi5jbS1zLXR3aWxpZ2h0IC5jbS1hdHRyaWJ1dGUgeyBjb2xvcjogI2Q2YmI2ZDsgfSAvKj8qL1xcbi5jbS1zLXR3aWxpZ2h0IC5jbS1oZWFkZXIgeyBjb2xvcjogI0ZGNjQwMDsgfVxcbi5jbS1zLXR3aWxpZ2h0IC5jbS1ociB7IGNvbG9yOiAjQUVBRUFFOyB9XFxuLmNtLXMtdHdpbGlnaHQgLmNtLWxpbmsgeyBjb2xvcjojYWQ5MzYxOyBmb250LXN0eWxlOml0YWxpYzsgdGV4dC1kZWNvcmF0aW9uOm5vbmU7IH0gLyoqL1xcbi5jbS1zLXR3aWxpZ2h0IC5jbS1lcnJvciB7IGJvcmRlci1ib3R0b206IDFweCBzb2xpZCByZWQ7IH1cXG5cXG4uY20tcy10d2lsaWdodCAuQ29kZU1pcnJvci1hY3RpdmVsaW5lLWJhY2tncm91bmQgeyBiYWNrZ3JvdW5kOiAjMjcyODJFOyB9XFxuLmNtLXMtdHdpbGlnaHQgLkNvZGVNaXJyb3ItbWF0Y2hpbmdicmFja2V0IHsgb3V0bGluZToxcHggc29saWQgZ3JleTsgY29sb3I6d2hpdGUgIWltcG9ydGFudDsgfVxcblwiXSxcInNvdXJjZVJvb3RcIjpcIlwifV0pO1xuLy8gRXhwb3J0c1xuZXhwb3J0IGRlZmF1bHQgX19fQ1NTX0xPQURFUl9FWFBPUlRfX187XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuLypcbiAgTUlUIExpY2Vuc2UgaHR0cDovL3d3dy5vcGVuc291cmNlLm9yZy9saWNlbnNlcy9taXQtbGljZW5zZS5waHBcbiAgQXV0aG9yIFRvYmlhcyBLb3BwZXJzIEBzb2tyYVxuKi9cbi8vIGNzcyBiYXNlIGNvZGUsIGluamVjdGVkIGJ5IHRoZSBjc3MtbG9hZGVyXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZnVuYy1uYW1lc1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoY3NzV2l0aE1hcHBpbmdUb1N0cmluZykge1xuICB2YXIgbGlzdCA9IFtdOyAvLyByZXR1cm4gdGhlIGxpc3Qgb2YgbW9kdWxlcyBhcyBjc3Mgc3RyaW5nXG5cbiAgbGlzdC50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLm1hcChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgdmFyIGNvbnRlbnQgPSBjc3NXaXRoTWFwcGluZ1RvU3RyaW5nKGl0ZW0pO1xuXG4gICAgICBpZiAoaXRlbVsyXSkge1xuICAgICAgICByZXR1cm4gXCJAbWVkaWEgXCIuY29uY2F0KGl0ZW1bMl0sIFwiIHtcIikuY29uY2F0KGNvbnRlbnQsIFwifVwiKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNvbnRlbnQ7XG4gICAgfSkuam9pbihcIlwiKTtcbiAgfTsgLy8gaW1wb3J0IGEgbGlzdCBvZiBtb2R1bGVzIGludG8gdGhlIGxpc3RcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGZ1bmMtbmFtZXNcblxuXG4gIGxpc3QuaSA9IGZ1bmN0aW9uIChtb2R1bGVzLCBtZWRpYVF1ZXJ5LCBkZWR1cGUpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZXMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1wYXJhbS1yZWFzc2lnblxuICAgICAgbW9kdWxlcyA9IFtbbnVsbCwgbW9kdWxlcywgXCJcIl1dO1xuICAgIH1cblxuICAgIHZhciBhbHJlYWR5SW1wb3J0ZWRNb2R1bGVzID0ge307XG5cbiAgICBpZiAoZGVkdXBlKSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHByZWZlci1kZXN0cnVjdHVyaW5nXG4gICAgICAgIHZhciBpZCA9IHRoaXNbaV1bMF07XG5cbiAgICAgICAgaWYgKGlkICE9IG51bGwpIHtcbiAgICAgICAgICBhbHJlYWR5SW1wb3J0ZWRNb2R1bGVzW2lkXSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgbW9kdWxlcy5sZW5ndGg7IF9pKyspIHtcbiAgICAgIHZhciBpdGVtID0gW10uY29uY2F0KG1vZHVsZXNbX2ldKTtcblxuICAgICAgaWYgKGRlZHVwZSAmJiBhbHJlYWR5SW1wb3J0ZWRNb2R1bGVzW2l0ZW1bMF1dKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb250aW51ZVxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lZGlhUXVlcnkpIHtcbiAgICAgICAgaWYgKCFpdGVtWzJdKSB7XG4gICAgICAgICAgaXRlbVsyXSA9IG1lZGlhUXVlcnk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaXRlbVsyXSA9IFwiXCIuY29uY2F0KG1lZGlhUXVlcnksIFwiIGFuZCBcIikuY29uY2F0KGl0ZW1bMl0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGxpc3QucHVzaChpdGVtKTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIGxpc3Q7XG59OyIsIlwidXNlIHN0cmljdFwiO1xuXG5mdW5jdGlvbiBfc2xpY2VkVG9BcnJheShhcnIsIGkpIHsgcmV0dXJuIF9hcnJheVdpdGhIb2xlcyhhcnIpIHx8IF9pdGVyYWJsZVRvQXJyYXlMaW1pdChhcnIsIGkpIHx8IF91bnN1cHBvcnRlZEl0ZXJhYmxlVG9BcnJheShhcnIsIGkpIHx8IF9ub25JdGVyYWJsZVJlc3QoKTsgfVxuXG5mdW5jdGlvbiBfbm9uSXRlcmFibGVSZXN0KCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiSW52YWxpZCBhdHRlbXB0IHRvIGRlc3RydWN0dXJlIG5vbi1pdGVyYWJsZSBpbnN0YW5jZS5cXG5JbiBvcmRlciB0byBiZSBpdGVyYWJsZSwgbm9uLWFycmF5IG9iamVjdHMgbXVzdCBoYXZlIGEgW1N5bWJvbC5pdGVyYXRvcl0oKSBtZXRob2QuXCIpOyB9XG5cbmZ1bmN0aW9uIF91bnN1cHBvcnRlZEl0ZXJhYmxlVG9BcnJheShvLCBtaW5MZW4pIHsgaWYgKCFvKSByZXR1cm47IGlmICh0eXBlb2YgbyA9PT0gXCJzdHJpbmdcIikgcmV0dXJuIF9hcnJheUxpa2VUb0FycmF5KG8sIG1pbkxlbik7IHZhciBuID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG8pLnNsaWNlKDgsIC0xKTsgaWYgKG4gPT09IFwiT2JqZWN0XCIgJiYgby5jb25zdHJ1Y3RvcikgbiA9IG8uY29uc3RydWN0b3IubmFtZTsgaWYgKG4gPT09IFwiTWFwXCIgfHwgbiA9PT0gXCJTZXRcIikgcmV0dXJuIEFycmF5LmZyb20obyk7IGlmIChuID09PSBcIkFyZ3VtZW50c1wiIHx8IC9eKD86VWl8SSludCg/Ojh8MTZ8MzIpKD86Q2xhbXBlZCk/QXJyYXkkLy50ZXN0KG4pKSByZXR1cm4gX2FycmF5TGlrZVRvQXJyYXkobywgbWluTGVuKTsgfVxuXG5mdW5jdGlvbiBfYXJyYXlMaWtlVG9BcnJheShhcnIsIGxlbikgeyBpZiAobGVuID09IG51bGwgfHwgbGVuID4gYXJyLmxlbmd0aCkgbGVuID0gYXJyLmxlbmd0aDsgZm9yICh2YXIgaSA9IDAsIGFycjIgPSBuZXcgQXJyYXkobGVuKTsgaSA8IGxlbjsgaSsrKSB7IGFycjJbaV0gPSBhcnJbaV07IH0gcmV0dXJuIGFycjI7IH1cblxuZnVuY3Rpb24gX2l0ZXJhYmxlVG9BcnJheUxpbWl0KGFyciwgaSkgeyB2YXIgX2kgPSBhcnIgJiYgKHR5cGVvZiBTeW1ib2wgIT09IFwidW5kZWZpbmVkXCIgJiYgYXJyW1N5bWJvbC5pdGVyYXRvcl0gfHwgYXJyW1wiQEBpdGVyYXRvclwiXSk7IGlmIChfaSA9PSBudWxsKSByZXR1cm47IHZhciBfYXJyID0gW107IHZhciBfbiA9IHRydWU7IHZhciBfZCA9IGZhbHNlOyB2YXIgX3MsIF9lOyB0cnkgeyBmb3IgKF9pID0gX2kuY2FsbChhcnIpOyAhKF9uID0gKF9zID0gX2kubmV4dCgpKS5kb25lKTsgX24gPSB0cnVlKSB7IF9hcnIucHVzaChfcy52YWx1ZSk7IGlmIChpICYmIF9hcnIubGVuZ3RoID09PSBpKSBicmVhazsgfSB9IGNhdGNoIChlcnIpIHsgX2QgPSB0cnVlOyBfZSA9IGVycjsgfSBmaW5hbGx5IHsgdHJ5IHsgaWYgKCFfbiAmJiBfaVtcInJldHVyblwiXSAhPSBudWxsKSBfaVtcInJldHVyblwiXSgpOyB9IGZpbmFsbHkgeyBpZiAoX2QpIHRocm93IF9lOyB9IH0gcmV0dXJuIF9hcnI7IH1cblxuZnVuY3Rpb24gX2FycmF5V2l0aEhvbGVzKGFycikgeyBpZiAoQXJyYXkuaXNBcnJheShhcnIpKSByZXR1cm4gYXJyOyB9XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY3NzV2l0aE1hcHBpbmdUb1N0cmluZyhpdGVtKSB7XG4gIHZhciBfaXRlbSA9IF9zbGljZWRUb0FycmF5KGl0ZW0sIDQpLFxuICAgICAgY29udGVudCA9IF9pdGVtWzFdLFxuICAgICAgY3NzTWFwcGluZyA9IF9pdGVtWzNdO1xuXG4gIGlmICghY3NzTWFwcGluZykge1xuICAgIHJldHVybiBjb250ZW50O1xuICB9XG5cbiAgaWYgKHR5cGVvZiBidG9hID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW5kZWZcbiAgICB2YXIgYmFzZTY0ID0gYnRvYSh1bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQoSlNPTi5zdHJpbmdpZnkoY3NzTWFwcGluZykpKSk7XG4gICAgdmFyIGRhdGEgPSBcInNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2NoYXJzZXQ9dXRmLTg7YmFzZTY0LFwiLmNvbmNhdChiYXNlNjQpO1xuICAgIHZhciBzb3VyY2VNYXBwaW5nID0gXCIvKiMgXCIuY29uY2F0KGRhdGEsIFwiICovXCIpO1xuICAgIHZhciBzb3VyY2VVUkxzID0gY3NzTWFwcGluZy5zb3VyY2VzLm1hcChmdW5jdGlvbiAoc291cmNlKSB7XG4gICAgICByZXR1cm4gXCIvKiMgc291cmNlVVJMPVwiLmNvbmNhdChjc3NNYXBwaW5nLnNvdXJjZVJvb3QgfHwgXCJcIikuY29uY2F0KHNvdXJjZSwgXCIgKi9cIik7XG4gICAgfSk7XG4gICAgcmV0dXJuIFtjb250ZW50XS5jb25jYXQoc291cmNlVVJMcykuY29uY2F0KFtzb3VyY2VNYXBwaW5nXSkuam9pbihcIlxcblwiKTtcbiAgfVxuXG4gIHJldHVybiBbY29udGVudF0uam9pbihcIlxcblwiKTtcbn07IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBpc09sZElFID0gZnVuY3Rpb24gaXNPbGRJRSgpIHtcbiAgdmFyIG1lbW87XG4gIHJldHVybiBmdW5jdGlvbiBtZW1vcml6ZSgpIHtcbiAgICBpZiAodHlwZW9mIG1lbW8gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAvLyBUZXN0IGZvciBJRSA8PSA5IGFzIHByb3Bvc2VkIGJ5IEJyb3dzZXJoYWNrc1xuICAgICAgLy8gQHNlZSBodHRwOi8vYnJvd3NlcmhhY2tzLmNvbS8jaGFjay1lNzFkODY5MmY2NTMzNDE3M2ZlZTcxNWMyMjJjYjgwNVxuICAgICAgLy8gVGVzdHMgZm9yIGV4aXN0ZW5jZSBvZiBzdGFuZGFyZCBnbG9iYWxzIGlzIHRvIGFsbG93IHN0eWxlLWxvYWRlclxuICAgICAgLy8gdG8gb3BlcmF0ZSBjb3JyZWN0bHkgaW50byBub24tc3RhbmRhcmQgZW52aXJvbm1lbnRzXG4gICAgICAvLyBAc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS93ZWJwYWNrLWNvbnRyaWIvc3R5bGUtbG9hZGVyL2lzc3Vlcy8xNzdcbiAgICAgIG1lbW8gPSBCb29sZWFuKHdpbmRvdyAmJiBkb2N1bWVudCAmJiBkb2N1bWVudC5hbGwgJiYgIXdpbmRvdy5hdG9iKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbWVtbztcbiAgfTtcbn0oKTtcblxudmFyIGdldFRhcmdldCA9IGZ1bmN0aW9uIGdldFRhcmdldCgpIHtcbiAgdmFyIG1lbW8gPSB7fTtcbiAgcmV0dXJuIGZ1bmN0aW9uIG1lbW9yaXplKHRhcmdldCkge1xuICAgIGlmICh0eXBlb2YgbWVtb1t0YXJnZXRdID09PSAndW5kZWZpbmVkJykge1xuICAgICAgdmFyIHN0eWxlVGFyZ2V0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0YXJnZXQpOyAvLyBTcGVjaWFsIGNhc2UgdG8gcmV0dXJuIGhlYWQgb2YgaWZyYW1lIGluc3RlYWQgb2YgaWZyYW1lIGl0c2VsZlxuXG4gICAgICBpZiAod2luZG93LkhUTUxJRnJhbWVFbGVtZW50ICYmIHN0eWxlVGFyZ2V0IGluc3RhbmNlb2Ygd2luZG93LkhUTUxJRnJhbWVFbGVtZW50KSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gVGhpcyB3aWxsIHRocm93IGFuIGV4Y2VwdGlvbiBpZiBhY2Nlc3MgdG8gaWZyYW1lIGlzIGJsb2NrZWRcbiAgICAgICAgICAvLyBkdWUgdG8gY3Jvc3Mtb3JpZ2luIHJlc3RyaWN0aW9uc1xuICAgICAgICAgIHN0eWxlVGFyZ2V0ID0gc3R5bGVUYXJnZXQuY29udGVudERvY3VtZW50LmhlYWQ7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAvLyBpc3RhbmJ1bCBpZ25vcmUgbmV4dFxuICAgICAgICAgIHN0eWxlVGFyZ2V0ID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBtZW1vW3RhcmdldF0gPSBzdHlsZVRhcmdldDtcbiAgICB9XG5cbiAgICByZXR1cm4gbWVtb1t0YXJnZXRdO1xuICB9O1xufSgpO1xuXG52YXIgc3R5bGVzSW5Eb20gPSBbXTtcblxuZnVuY3Rpb24gZ2V0SW5kZXhCeUlkZW50aWZpZXIoaWRlbnRpZmllcikge1xuICB2YXIgcmVzdWx0ID0gLTE7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHlsZXNJbkRvbS5sZW5ndGg7IGkrKykge1xuICAgIGlmIChzdHlsZXNJbkRvbVtpXS5pZGVudGlmaWVyID09PSBpZGVudGlmaWVyKSB7XG4gICAgICByZXN1bHQgPSBpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gbW9kdWxlc1RvRG9tKGxpc3QsIG9wdGlvbnMpIHtcbiAgdmFyIGlkQ291bnRNYXAgPSB7fTtcbiAgdmFyIGlkZW50aWZpZXJzID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGl0ZW0gPSBsaXN0W2ldO1xuICAgIHZhciBpZCA9IG9wdGlvbnMuYmFzZSA/IGl0ZW1bMF0gKyBvcHRpb25zLmJhc2UgOiBpdGVtWzBdO1xuICAgIHZhciBjb3VudCA9IGlkQ291bnRNYXBbaWRdIHx8IDA7XG4gICAgdmFyIGlkZW50aWZpZXIgPSBcIlwiLmNvbmNhdChpZCwgXCIgXCIpLmNvbmNhdChjb3VudCk7XG4gICAgaWRDb3VudE1hcFtpZF0gPSBjb3VudCArIDE7XG4gICAgdmFyIGluZGV4ID0gZ2V0SW5kZXhCeUlkZW50aWZpZXIoaWRlbnRpZmllcik7XG4gICAgdmFyIG9iaiA9IHtcbiAgICAgIGNzczogaXRlbVsxXSxcbiAgICAgIG1lZGlhOiBpdGVtWzJdLFxuICAgICAgc291cmNlTWFwOiBpdGVtWzNdXG4gICAgfTtcblxuICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgIHN0eWxlc0luRG9tW2luZGV4XS5yZWZlcmVuY2VzKys7XG4gICAgICBzdHlsZXNJbkRvbVtpbmRleF0udXBkYXRlcihvYmopO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdHlsZXNJbkRvbS5wdXNoKHtcbiAgICAgICAgaWRlbnRpZmllcjogaWRlbnRpZmllcixcbiAgICAgICAgdXBkYXRlcjogYWRkU3R5bGUob2JqLCBvcHRpb25zKSxcbiAgICAgICAgcmVmZXJlbmNlczogMVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWRlbnRpZmllcnMucHVzaChpZGVudGlmaWVyKTtcbiAgfVxuXG4gIHJldHVybiBpZGVudGlmaWVycztcbn1cblxuZnVuY3Rpb24gaW5zZXJ0U3R5bGVFbGVtZW50KG9wdGlvbnMpIHtcbiAgdmFyIHN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcbiAgdmFyIGF0dHJpYnV0ZXMgPSBvcHRpb25zLmF0dHJpYnV0ZXMgfHwge307XG5cbiAgaWYgKHR5cGVvZiBhdHRyaWJ1dGVzLm5vbmNlID09PSAndW5kZWZpbmVkJykge1xuICAgIHZhciBub25jZSA9IHR5cGVvZiBfX3dlYnBhY2tfbm9uY2VfXyAhPT0gJ3VuZGVmaW5lZCcgPyBfX3dlYnBhY2tfbm9uY2VfXyA6IG51bGw7XG5cbiAgICBpZiAobm9uY2UpIHtcbiAgICAgIGF0dHJpYnV0ZXMubm9uY2UgPSBub25jZTtcbiAgICB9XG4gIH1cblxuICBPYmplY3Qua2V5cyhhdHRyaWJ1dGVzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICBzdHlsZS5zZXRBdHRyaWJ1dGUoa2V5LCBhdHRyaWJ1dGVzW2tleV0pO1xuICB9KTtcblxuICBpZiAodHlwZW9mIG9wdGlvbnMuaW5zZXJ0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgb3B0aW9ucy5pbnNlcnQoc3R5bGUpO1xuICB9IGVsc2Uge1xuICAgIHZhciB0YXJnZXQgPSBnZXRUYXJnZXQob3B0aW9ucy5pbnNlcnQgfHwgJ2hlYWQnKTtcblxuICAgIGlmICghdGFyZ2V0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb3VsZG4ndCBmaW5kIGEgc3R5bGUgdGFyZ2V0LiBUaGlzIHByb2JhYmx5IG1lYW5zIHRoYXQgdGhlIHZhbHVlIGZvciB0aGUgJ2luc2VydCcgcGFyYW1ldGVyIGlzIGludmFsaWQuXCIpO1xuICAgIH1cblxuICAgIHRhcmdldC5hcHBlbmRDaGlsZChzdHlsZSk7XG4gIH1cblxuICByZXR1cm4gc3R5bGU7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZVN0eWxlRWxlbWVudChzdHlsZSkge1xuICAvLyBpc3RhbmJ1bCBpZ25vcmUgaWZcbiAgaWYgKHN0eWxlLnBhcmVudE5vZGUgPT09IG51bGwpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBzdHlsZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHN0eWxlKTtcbn1cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICAqL1xuXG5cbnZhciByZXBsYWNlVGV4dCA9IGZ1bmN0aW9uIHJlcGxhY2VUZXh0KCkge1xuICB2YXIgdGV4dFN0b3JlID0gW107XG4gIHJldHVybiBmdW5jdGlvbiByZXBsYWNlKGluZGV4LCByZXBsYWNlbWVudCkge1xuICAgIHRleHRTdG9yZVtpbmRleF0gPSByZXBsYWNlbWVudDtcbiAgICByZXR1cm4gdGV4dFN0b3JlLmZpbHRlcihCb29sZWFuKS5qb2luKCdcXG4nKTtcbiAgfTtcbn0oKTtcblxuZnVuY3Rpb24gYXBwbHlUb1NpbmdsZXRvblRhZyhzdHlsZSwgaW5kZXgsIHJlbW92ZSwgb2JqKSB7XG4gIHZhciBjc3MgPSByZW1vdmUgPyAnJyA6IG9iai5tZWRpYSA/IFwiQG1lZGlhIFwiLmNvbmNhdChvYmoubWVkaWEsIFwiIHtcIikuY29uY2F0KG9iai5jc3MsIFwifVwiKSA6IG9iai5jc3M7IC8vIEZvciBvbGQgSUVcblxuICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgICovXG5cbiAgaWYgKHN0eWxlLnN0eWxlU2hlZXQpIHtcbiAgICBzdHlsZS5zdHlsZVNoZWV0LmNzc1RleHQgPSByZXBsYWNlVGV4dChpbmRleCwgY3NzKTtcbiAgfSBlbHNlIHtcbiAgICB2YXIgY3NzTm9kZSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGNzcyk7XG4gICAgdmFyIGNoaWxkTm9kZXMgPSBzdHlsZS5jaGlsZE5vZGVzO1xuXG4gICAgaWYgKGNoaWxkTm9kZXNbaW5kZXhdKSB7XG4gICAgICBzdHlsZS5yZW1vdmVDaGlsZChjaGlsZE5vZGVzW2luZGV4XSk7XG4gICAgfVxuXG4gICAgaWYgKGNoaWxkTm9kZXMubGVuZ3RoKSB7XG4gICAgICBzdHlsZS5pbnNlcnRCZWZvcmUoY3NzTm9kZSwgY2hpbGROb2Rlc1tpbmRleF0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdHlsZS5hcHBlbmRDaGlsZChjc3NOb2RlKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHlUb1RhZyhzdHlsZSwgb3B0aW9ucywgb2JqKSB7XG4gIHZhciBjc3MgPSBvYmouY3NzO1xuICB2YXIgbWVkaWEgPSBvYmoubWVkaWE7XG4gIHZhciBzb3VyY2VNYXAgPSBvYmouc291cmNlTWFwO1xuXG4gIGlmIChtZWRpYSkge1xuICAgIHN0eWxlLnNldEF0dHJpYnV0ZSgnbWVkaWEnLCBtZWRpYSk7XG4gIH0gZWxzZSB7XG4gICAgc3R5bGUucmVtb3ZlQXR0cmlidXRlKCdtZWRpYScpO1xuICB9XG5cbiAgaWYgKHNvdXJjZU1hcCAmJiB0eXBlb2YgYnRvYSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBjc3MgKz0gXCJcXG4vKiMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LFwiLmNvbmNhdChidG9hKHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChKU09OLnN0cmluZ2lmeShzb3VyY2VNYXApKSkpLCBcIiAqL1wiKTtcbiAgfSAvLyBGb3Igb2xkIElFXG5cbiAgLyogaXN0YW5idWwgaWdub3JlIGlmICAqL1xuXG5cbiAgaWYgKHN0eWxlLnN0eWxlU2hlZXQpIHtcbiAgICBzdHlsZS5zdHlsZVNoZWV0LmNzc1RleHQgPSBjc3M7XG4gIH0gZWxzZSB7XG4gICAgd2hpbGUgKHN0eWxlLmZpcnN0Q2hpbGQpIHtcbiAgICAgIHN0eWxlLnJlbW92ZUNoaWxkKHN0eWxlLmZpcnN0Q2hpbGQpO1xuICAgIH1cblxuICAgIHN0eWxlLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGNzcykpO1xuICB9XG59XG5cbnZhciBzaW5nbGV0b24gPSBudWxsO1xudmFyIHNpbmdsZXRvbkNvdW50ZXIgPSAwO1xuXG5mdW5jdGlvbiBhZGRTdHlsZShvYmosIG9wdGlvbnMpIHtcbiAgdmFyIHN0eWxlO1xuICB2YXIgdXBkYXRlO1xuICB2YXIgcmVtb3ZlO1xuXG4gIGlmIChvcHRpb25zLnNpbmdsZXRvbikge1xuICAgIHZhciBzdHlsZUluZGV4ID0gc2luZ2xldG9uQ291bnRlcisrO1xuICAgIHN0eWxlID0gc2luZ2xldG9uIHx8IChzaW5nbGV0b24gPSBpbnNlcnRTdHlsZUVsZW1lbnQob3B0aW9ucykpO1xuICAgIHVwZGF0ZSA9IGFwcGx5VG9TaW5nbGV0b25UYWcuYmluZChudWxsLCBzdHlsZSwgc3R5bGVJbmRleCwgZmFsc2UpO1xuICAgIHJlbW92ZSA9IGFwcGx5VG9TaW5nbGV0b25UYWcuYmluZChudWxsLCBzdHlsZSwgc3R5bGVJbmRleCwgdHJ1ZSk7XG4gIH0gZWxzZSB7XG4gICAgc3R5bGUgPSBpbnNlcnRTdHlsZUVsZW1lbnQob3B0aW9ucyk7XG4gICAgdXBkYXRlID0gYXBwbHlUb1RhZy5iaW5kKG51bGwsIHN0eWxlLCBvcHRpb25zKTtcblxuICAgIHJlbW92ZSA9IGZ1bmN0aW9uIHJlbW92ZSgpIHtcbiAgICAgIHJlbW92ZVN0eWxlRWxlbWVudChzdHlsZSk7XG4gICAgfTtcbiAgfVxuXG4gIHVwZGF0ZShvYmopO1xuICByZXR1cm4gZnVuY3Rpb24gdXBkYXRlU3R5bGUobmV3T2JqKSB7XG4gICAgaWYgKG5ld09iaikge1xuICAgICAgaWYgKG5ld09iai5jc3MgPT09IG9iai5jc3MgJiYgbmV3T2JqLm1lZGlhID09PSBvYmoubWVkaWEgJiYgbmV3T2JqLnNvdXJjZU1hcCA9PT0gb2JqLnNvdXJjZU1hcCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHVwZGF0ZShvYmogPSBuZXdPYmopO1xuICAgIH0gZWxzZSB7XG4gICAgICByZW1vdmUoKTtcbiAgICB9XG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGxpc3QsIG9wdGlvbnMpIHtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307IC8vIEZvcmNlIHNpbmdsZS10YWcgc29sdXRpb24gb24gSUU2LTksIHdoaWNoIGhhcyBhIGhhcmQgbGltaXQgb24gdGhlICMgb2YgPHN0eWxlPlxuICAvLyB0YWdzIGl0IHdpbGwgYWxsb3cgb24gYSBwYWdlXG5cbiAgaWYgKCFvcHRpb25zLnNpbmdsZXRvbiAmJiB0eXBlb2Ygb3B0aW9ucy5zaW5nbGV0b24gIT09ICdib29sZWFuJykge1xuICAgIG9wdGlvbnMuc2luZ2xldG9uID0gaXNPbGRJRSgpO1xuICB9XG5cbiAgbGlzdCA9IGxpc3QgfHwgW107XG4gIHZhciBsYXN0SWRlbnRpZmllcnMgPSBtb2R1bGVzVG9Eb20obGlzdCwgb3B0aW9ucyk7XG4gIHJldHVybiBmdW5jdGlvbiB1cGRhdGUobmV3TGlzdCkge1xuICAgIG5ld0xpc3QgPSBuZXdMaXN0IHx8IFtdO1xuXG4gICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChuZXdMaXN0KSAhPT0gJ1tvYmplY3QgQXJyYXldJykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGFzdElkZW50aWZpZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgaWRlbnRpZmllciA9IGxhc3RJZGVudGlmaWVyc1tpXTtcbiAgICAgIHZhciBpbmRleCA9IGdldEluZGV4QnlJZGVudGlmaWVyKGlkZW50aWZpZXIpO1xuICAgICAgc3R5bGVzSW5Eb21baW5kZXhdLnJlZmVyZW5jZXMtLTtcbiAgICB9XG5cbiAgICB2YXIgbmV3TGFzdElkZW50aWZpZXJzID0gbW9kdWxlc1RvRG9tKG5ld0xpc3QsIG9wdGlvbnMpO1xuXG4gICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGxhc3RJZGVudGlmaWVycy5sZW5ndGg7IF9pKyspIHtcbiAgICAgIHZhciBfaWRlbnRpZmllciA9IGxhc3RJZGVudGlmaWVyc1tfaV07XG5cbiAgICAgIHZhciBfaW5kZXggPSBnZXRJbmRleEJ5SWRlbnRpZmllcihfaWRlbnRpZmllcik7XG5cbiAgICAgIGlmIChzdHlsZXNJbkRvbVtfaW5kZXhdLnJlZmVyZW5jZXMgPT09IDApIHtcbiAgICAgICAgc3R5bGVzSW5Eb21bX2luZGV4XS51cGRhdGVyKCk7XG5cbiAgICAgICAgc3R5bGVzSW5Eb20uc3BsaWNlKF9pbmRleCwgMSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbGFzdElkZW50aWZpZXJzID0gbmV3TGFzdElkZW50aWZpZXJzO1xuICB9O1xufTsiLCIvLyBUaGUgbW9kdWxlIGNhY2hlXG52YXIgX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fID0ge307XG5cbi8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG5mdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuXHR2YXIgY2FjaGVkTW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXTtcblx0aWYgKGNhY2hlZE1vZHVsZSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0cmV0dXJuIGNhY2hlZE1vZHVsZS5leHBvcnRzO1xuXHR9XG5cdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG5cdHZhciBtb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdID0ge1xuXHRcdGlkOiBtb2R1bGVJZCxcblx0XHQvLyBubyBtb2R1bGUubG9hZGVkIG5lZWRlZFxuXHRcdGV4cG9ydHM6IHt9XG5cdH07XG5cblx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG5cdF9fd2VicGFja19tb2R1bGVzX19bbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG5cdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXG5cdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbn1cblxuLy8gZXhwb3NlIHRoZSBtb2R1bGVzIG9iamVjdCAoX193ZWJwYWNrX21vZHVsZXNfXylcbl9fd2VicGFja19yZXF1aXJlX18ubSA9IF9fd2VicGFja19tb2R1bGVzX187XG5cbiIsIi8vIGdldERlZmF1bHRFeHBvcnQgZnVuY3Rpb24gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBub24taGFybW9ueSBtb2R1bGVzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSAobW9kdWxlKSA9PiB7XG5cdHZhciBnZXR0ZXIgPSBtb2R1bGUgJiYgbW9kdWxlLl9fZXNNb2R1bGUgP1xuXHRcdCgpID0+IChtb2R1bGVbJ2RlZmF1bHQnXSkgOlxuXHRcdCgpID0+IChtb2R1bGUpO1xuXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCB7IGE6IGdldHRlciB9KTtcblx0cmV0dXJuIGdldHRlcjtcbn07IiwiLy8gZGVmaW5lIGdldHRlciBmdW5jdGlvbnMgZm9yIGhhcm1vbnkgZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5kID0gKGV4cG9ydHMsIGRlZmluaXRpb24pID0+IHtcblx0Zm9yKHZhciBrZXkgaW4gZGVmaW5pdGlvbikge1xuXHRcdGlmKF9fd2VicGFja19yZXF1aXJlX18ubyhkZWZpbml0aW9uLCBrZXkpICYmICFfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZXhwb3J0cywga2V5KSkge1xuXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIGtleSwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGRlZmluaXRpb25ba2V5XSB9KTtcblx0XHR9XG5cdH1cbn07IiwiX193ZWJwYWNrX3JlcXVpcmVfXy5vID0gKG9iaiwgcHJvcCkgPT4gKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApKSIsIi8vIG5vIGJhc2VVUklcblxuLy8gb2JqZWN0IHRvIHN0b3JlIGxvYWRlZCBhbmQgbG9hZGluZyBjaHVua3Ncbi8vIHVuZGVmaW5lZCA9IGNodW5rIG5vdCBsb2FkZWQsIG51bGwgPSBjaHVuayBwcmVsb2FkZWQvcHJlZmV0Y2hlZFxuLy8gW3Jlc29sdmUsIHJlamVjdCwgUHJvbWlzZV0gPSBjaHVuayBsb2FkaW5nLCAwID0gY2h1bmsgbG9hZGVkXG52YXIgaW5zdGFsbGVkQ2h1bmtzID0ge1xuXHQxMzg6IDAsXG5cdDExODogMCxcblx0NzY2OiAwXG59O1xuXG4vLyBubyBjaHVuayBvbiBkZW1hbmQgbG9hZGluZ1xuXG4vLyBubyBwcmVmZXRjaGluZ1xuXG4vLyBubyBwcmVsb2FkZWRcblxuLy8gbm8gSE1SXG5cbi8vIG5vIEhNUiBtYW5pZmVzdFxuXG5fX3dlYnBhY2tfcmVxdWlyZV9fLk8uaiA9IChjaHVua0lkKSA9PiAoaW5zdGFsbGVkQ2h1bmtzW2NodW5rSWRdID09PSAwKTtcblxuLy8gaW5zdGFsbCBhIEpTT05QIGNhbGxiYWNrIGZvciBjaHVuayBsb2FkaW5nXG52YXIgd2VicGFja0pzb25wQ2FsbGJhY2sgPSAocGFyZW50Q2h1bmtMb2FkaW5nRnVuY3Rpb24sIGRhdGEpID0+IHtcblx0dmFyIFtjaHVua0lkcywgbW9yZU1vZHVsZXMsIHJ1bnRpbWVdID0gZGF0YTtcblx0Ly8gYWRkIFwibW9yZU1vZHVsZXNcIiB0byB0aGUgbW9kdWxlcyBvYmplY3QsXG5cdC8vIHRoZW4gZmxhZyBhbGwgXCJjaHVua0lkc1wiIGFzIGxvYWRlZCBhbmQgZmlyZSBjYWxsYmFja1xuXHR2YXIgbW9kdWxlSWQsIGNodW5rSWQsIGkgPSAwO1xuXHRpZihjaHVua0lkcy5zb21lKChpZCkgPT4gKGluc3RhbGxlZENodW5rc1tpZF0gIT09IDApKSkge1xuXHRcdGZvcihtb2R1bGVJZCBpbiBtb3JlTW9kdWxlcykge1xuXHRcdFx0aWYoX193ZWJwYWNrX3JlcXVpcmVfXy5vKG1vcmVNb2R1bGVzLCBtb2R1bGVJZCkpIHtcblx0XHRcdFx0X193ZWJwYWNrX3JlcXVpcmVfXy5tW21vZHVsZUlkXSA9IG1vcmVNb2R1bGVzW21vZHVsZUlkXTtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYocnVudGltZSkgdmFyIHJlc3VsdCA9IHJ1bnRpbWUoX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cdH1cblx0aWYocGFyZW50Q2h1bmtMb2FkaW5nRnVuY3Rpb24pIHBhcmVudENodW5rTG9hZGluZ0Z1bmN0aW9uKGRhdGEpO1xuXHRmb3IoO2kgPCBjaHVua0lkcy5sZW5ndGg7IGkrKykge1xuXHRcdGNodW5rSWQgPSBjaHVua0lkc1tpXTtcblx0XHRpZihfX3dlYnBhY2tfcmVxdWlyZV9fLm8oaW5zdGFsbGVkQ2h1bmtzLCBjaHVua0lkKSAmJiBpbnN0YWxsZWRDaHVua3NbY2h1bmtJZF0pIHtcblx0XHRcdGluc3RhbGxlZENodW5rc1tjaHVua0lkXVswXSgpO1xuXHRcdH1cblx0XHRpbnN0YWxsZWRDaHVua3NbY2h1bmtJZF0gPSAwO1xuXHR9XG5cdHJldHVybiBfX3dlYnBhY2tfcmVxdWlyZV9fLk8ocmVzdWx0KTtcbn1cblxudmFyIGNodW5rTG9hZGluZ0dsb2JhbCA9IHNlbGZbXCJ3ZWJwYWNrQ2h1bmtcIl0gPSBzZWxmW1wid2VicGFja0NodW5rXCJdIHx8IFtdO1xuY2h1bmtMb2FkaW5nR2xvYmFsLmZvckVhY2god2VicGFja0pzb25wQ2FsbGJhY2suYmluZChudWxsLCAwKSk7XG5jaHVua0xvYWRpbmdHbG9iYWwucHVzaCA9IHdlYnBhY2tKc29ucENhbGxiYWNrLmJpbmQobnVsbCwgY2h1bmtMb2FkaW5nR2xvYmFsLnB1c2guYmluZChjaHVua0xvYWRpbmdHbG9iYWwpKTsiLCJfX3dlYnBhY2tfcmVxdWlyZV9fLm5jID0gdW5kZWZpbmVkOyIsIi8vIHN0YXJ0dXBcbi8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuLy8gVGhpcyBlbnRyeSBtb2R1bGUgZGVwZW5kcyBvbiBvdGhlciBsb2FkZWQgY2h1bmtzIGFuZCBleGVjdXRpb24gbmVlZCB0byBiZSBkZWxheWVkXG5fX3dlYnBhY2tfcmVxdWlyZV9fLk8odW5kZWZpbmVkLCBbMTE4LDc2Nl0sICgpID0+IChfX3dlYnBhY2tfcmVxdWlyZV9fKDgzMCkpKVxuX193ZWJwYWNrX3JlcXVpcmVfXy5PKHVuZGVmaW5lZCwgWzExOCw3NjZdLCAoKSA9PiAoX193ZWJwYWNrX3JlcXVpcmVfXygxNTgpKSlcbnZhciBfX3dlYnBhY2tfZXhwb3J0c19fID0gX193ZWJwYWNrX3JlcXVpcmVfXy5PKHVuZGVmaW5lZCwgWzExOCw3NjZdLCAoKSA9PiAoX193ZWJwYWNrX3JlcXVpcmVfXyg5MzcpKSlcbl9fd2VicGFja19leHBvcnRzX18gPSBfX3dlYnBhY2tfcmVxdWlyZV9fLk8oX193ZWJwYWNrX2V4cG9ydHNfXyk7XG4iXSwibmFtZXMiOlsiZGVmZXJyZWQiLCJqUXVlcnkiLCJvcHRpb25zIiwiJCIsImRvY3VtZW50Iiwib24iLCJlYWNoIiwidGhpcyIsImRhdGFzZXQiLCJkaXNwb3NhYmxlIiwibW9kZVZhbHVlIiwiJHByZSIsImNvZGVWYWx1ZSIsInRleHQiLCJkYXRhIiwibmFtZSIsImJhc2UiLCJlbXB0eSIsIkNvZGVNaXJyb3IiLCJ2YWx1ZSIsIm1vZGUiLCJsaW5lTnVtYmVycyIsInJlYWRPbmx5IiwiY2xvc2VzdCIsInJlbW92ZUNsYXNzIiwibXVsdGlwbGV4aW5nTW9kZSIsIm91dGVyIiwib3RoZXJzIiwiQXJyYXkiLCJwcm90b3R5cGUiLCJzbGljZSIsImNhbGwiLCJhcmd1bWVudHMiLCJpbmRleE9mIiwic3RyaW5nIiwicGF0dGVybiIsImZyb20iLCJyZXR1cm5FbmQiLCJmb3VuZCIsImxlbmd0aCIsIm0iLCJleGVjIiwiaW5kZXgiLCJzdGFydFN0YXRlIiwiaW5uZXJBY3RpdmUiLCJpbm5lciIsInN0YXJ0aW5nSW5uZXIiLCJjb3B5U3RhdGUiLCJzdGF0ZSIsInRva2VuIiwic3RyZWFtIiwiY3VySW5uZXIiLCJvbGRDb250ZW50IiwiY2xvc2UiLCJzb2wiLCJwb3MiLCJwYXJzZURlbGltaXRlcnMiLCJtYXRjaCIsImRlbGltU3R5bGUiLCJpbm5lclRva2VuIiwic3RhcnQiLCJpbm5lclN0eWxlIiwiY3V0T2ZmIiwiSW5maW5pdHkiLCJpIiwib3RoZXIiLCJvcGVuIiwib3V0ZXJJbmRlbnQiLCJpbmRlbnQiLCJwb3NzaWJsZU91dGVySW5kZW50IiwiUGFzcyIsIm91dGVyVG9rZW4iLCJ0ZXh0QWZ0ZXIiLCJsaW5lIiwiYmxhbmtMaW5lIiwiZWxlY3RyaWNDaGFycyIsImlubmVyTW9kZSIsIm1vZCIsIm1vZHVsZSIsImV4cG9ydHMiLCJ1c2VyQWdlbnQiLCJuYXZpZ2F0b3IiLCJwbGF0Zm9ybSIsImdlY2tvIiwidGVzdCIsImllX3VwdG8xMCIsImllXzExdXAiLCJlZGdlIiwiaWUiLCJpZV92ZXJzaW9uIiwiZG9jdW1lbnRNb2RlIiwid2Via2l0IiwicXR3ZWJraXQiLCJjaHJvbWUiLCJjaHJvbWVfdmVyc2lvbiIsInByZXN0byIsInNhZmFyaSIsInZlbmRvciIsIm1hY19nZU1vdW50YWluTGlvbiIsInBoYW50b20iLCJpb3MiLCJtYXhUb3VjaFBvaW50cyIsImFuZHJvaWQiLCJtb2JpbGUiLCJtYWMiLCJjaHJvbWVPUyIsIndpbmRvd3MiLCJwcmVzdG9fdmVyc2lvbiIsIk51bWJlciIsImZsaXBDdHJsQ21kIiwiY2FwdHVyZVJpZ2h0Q2xpY2siLCJjbGFzc1Rlc3QiLCJjbHMiLCJSZWdFeHAiLCJyYW5nZSIsInJtQ2xhc3MiLCJub2RlIiwiY3VycmVudCIsImNsYXNzTmFtZSIsImFmdGVyIiwicmVtb3ZlQ2hpbGRyZW4iLCJlIiwiY291bnQiLCJjaGlsZE5vZGVzIiwicmVtb3ZlQ2hpbGQiLCJmaXJzdENoaWxkIiwicmVtb3ZlQ2hpbGRyZW5BbmRBZGQiLCJwYXJlbnQiLCJhcHBlbmRDaGlsZCIsImVsdCIsInRhZyIsImNvbnRlbnQiLCJzdHlsZSIsImNyZWF0ZUVsZW1lbnQiLCJjc3NUZXh0IiwiY3JlYXRlVGV4dE5vZGUiLCJlbHRQIiwic2V0QXR0cmlidXRlIiwiY29udGFpbnMiLCJjaGlsZCIsIm5vZGVUeXBlIiwicGFyZW50Tm9kZSIsImhvc3QiLCJhY3RpdmVFbHQiLCJhY3RpdmVFbGVtZW50IiwiYm9keSIsInNoYWRvd1Jvb3QiLCJhZGRDbGFzcyIsImpvaW5DbGFzc2VzIiwiYSIsImIiLCJhcyIsInNwbGl0IiwiY3JlYXRlUmFuZ2UiLCJlbmQiLCJlbmROb2RlIiwiciIsInNldEVuZCIsInNldFN0YXJ0IiwiY3JlYXRlVGV4dFJhbmdlIiwibW92ZVRvRWxlbWVudFRleHQiLCJjb2xsYXBzZSIsIm1vdmVFbmQiLCJtb3ZlU3RhcnQiLCJzZWxlY3RJbnB1dCIsInNlbGVjdCIsImJpbmQiLCJmIiwiYXJncyIsImFwcGx5IiwiY29weU9iaiIsIm9iaiIsInRhcmdldCIsIm92ZXJ3cml0ZSIsInByb3AiLCJoYXNPd25Qcm9wZXJ0eSIsImNvdW50Q29sdW1uIiwidGFiU2l6ZSIsInN0YXJ0SW5kZXgiLCJzdGFydFZhbHVlIiwic2VhcmNoIiwibiIsIm5leHRUYWIiLCJzZWxlY3Rpb25TdGFydCIsInNlbGVjdGlvbkVuZCIsIl9lIiwiRGVsYXllZCIsImlkIiwidGltZSIsImhhbmRsZXIiLCJvblRpbWVvdXQiLCJhcnJheSIsInNlbGYiLCJEYXRlIiwic2V0VGltZW91dCIsInNldCIsIm1zIiwiY2xlYXJUaW1lb3V0Iiwic2Nyb2xsZXJHYXAiLCJ0b1N0cmluZyIsInNlbF9kb250U2Nyb2xsIiwic2Nyb2xsIiwic2VsX21vdXNlIiwib3JpZ2luIiwic2VsX21vdmUiLCJmaW5kQ29sdW1uIiwiZ29hbCIsImNvbCIsInNraXBwZWQiLCJNYXRoIiwibWluIiwic3BhY2VTdHJzIiwic3BhY2VTdHIiLCJwdXNoIiwibHN0IiwiYXJyIiwibWFwIiwib3V0IiwiaW5zZXJ0U29ydGVkIiwic2NvcmUiLCJwcmlvcml0eSIsInNwbGljZSIsIm5vdGhpbmciLCJjcmVhdGVPYmoiLCJwcm9wcyIsImluc3QiLCJPYmplY3QiLCJjcmVhdGUiLCJub25BU0NJSVNpbmdsZUNhc2VXb3JkQ2hhciIsImlzV29yZENoYXJCYXNpYyIsImNoIiwidG9VcHBlckNhc2UiLCJ0b0xvd2VyQ2FzZSIsImlzV29yZENoYXIiLCJoZWxwZXIiLCJzb3VyY2UiLCJpc0VtcHR5IiwiZXh0ZW5kaW5nQ2hhcnMiLCJpc0V4dGVuZGluZ0NoYXIiLCJjaGFyQ29kZUF0Iiwic2tpcEV4dGVuZGluZ0NoYXJzIiwic3RyIiwiZGlyIiwiY2hhckF0IiwiZmluZEZpcnN0IiwicHJlZCIsInRvIiwibWlkRiIsIm1pZCIsImNlaWwiLCJmbG9vciIsIml0ZXJhdGVCaWRpU2VjdGlvbnMiLCJvcmRlciIsInBhcnQiLCJtYXgiLCJsZXZlbCIsImJpZGlPdGhlciIsImdldEJpZGlQYXJ0QXQiLCJzdGlja3kiLCJjdXIiLCJiaWRpT3JkZXJpbmciLCJsb3dUeXBlcyIsImFyYWJpY1R5cGVzIiwiY2hhclR5cGUiLCJjb2RlIiwiYmlkaVJFIiwiaXNOZXV0cmFsIiwiaXNTdHJvbmciLCJjb3VudHNBc0xlZnQiLCJjb3VudHNBc051bSIsIkJpZGlTcGFuIiwiZGlyZWN0aW9uIiwib3V0ZXJUeXBlIiwibGVuIiwidHlwZXMiLCJpJDEiLCJwcmV2IiwidHlwZSIsImkkMiIsInR5cGUkMSIsImkkMyIsInByZXYkMSIsInR5cGUkMiIsImkkNCIsInR5cGUkMyIsInJlcGxhY2UiLCJqIiwiaSQ1IiwiY3VyJDEiLCJ0eXBlJDQiLCJpJDYiLCJlbmQkMSIsImJlZm9yZSIsInJlcGxhY2UkMSIsImokMSIsImkkNyIsImF0IiwiaXNSVEwiLCJqJDIiLCJuc3RhcnQiLCJ1bnNoaWZ0IiwicmV2ZXJzZSIsImdldE9yZGVyIiwibm9IYW5kbGVycyIsImVtaXR0ZXIiLCJhZGRFdmVudExpc3RlbmVyIiwiYXR0YWNoRXZlbnQiLCJfaGFuZGxlcnMiLCJjb25jYXQiLCJnZXRIYW5kbGVycyIsIm9mZiIsInJlbW92ZUV2ZW50TGlzdGVuZXIiLCJkZXRhY2hFdmVudCIsInNpZ25hbCIsImhhbmRsZXJzIiwic2lnbmFsRE9NRXZlbnQiLCJjbSIsIm92ZXJyaWRlIiwicHJldmVudERlZmF1bHQiLCJkZWZhdWx0UHJldmVudGVkIiwiZV9kZWZhdWx0UHJldmVudGVkIiwiY29kZW1pcnJvcklnbm9yZSIsInNpZ25hbEN1cnNvckFjdGl2aXR5IiwiY3Vyc29yQWN0aXZpdHkiLCJjdXJPcCIsImN1cnNvckFjdGl2aXR5SGFuZGxlcnMiLCJoYXNIYW5kbGVyIiwiZXZlbnRNaXhpbiIsImN0b3IiLCJlX3ByZXZlbnREZWZhdWx0IiwicmV0dXJuVmFsdWUiLCJlX3N0b3BQcm9wYWdhdGlvbiIsInN0b3BQcm9wYWdhdGlvbiIsImNhbmNlbEJ1YmJsZSIsImVfc3RvcCIsImVfdGFyZ2V0Iiwic3JjRWxlbWVudCIsImVfYnV0dG9uIiwid2hpY2giLCJidXR0b24iLCJjdHJsS2V5IiwiendzcFN1cHBvcnRlZCIsImJhZEJpZGlSZWN0cyIsImRyYWdBbmREcm9wIiwiZGl2IiwiemVyb1dpZHRoRWxlbWVudCIsIm1lYXN1cmUiLCJvZmZzZXRIZWlnaHQiLCJvZmZzZXRXaWR0aCIsImhhc0JhZEJpZGlSZWN0cyIsInR4dCIsInIwIiwiZ2V0Qm91bmRpbmdDbGllbnRSZWN0IiwicjEiLCJsZWZ0IiwicmlnaHQiLCJzcGxpdExpbmVzQXV0byIsInJlc3VsdCIsImwiLCJubCIsInJ0IiwiaGFzU2VsZWN0aW9uIiwid2luZG93IiwiZ2V0U2VsZWN0aW9uIiwidGUiLCJvd25lckRvY3VtZW50Iiwic2VsZWN0aW9uIiwicGFyZW50RWxlbWVudCIsImNvbXBhcmVFbmRQb2ludHMiLCJoYXNDb3B5RXZlbnQiLCJvbmNvcHkiLCJiYWRab29tZWRSZWN0cyIsImhhc0JhZFpvb21lZFJlY3RzIiwibm9ybWFsIiwiZnJvbVJhbmdlIiwiYWJzIiwibW9kZXMiLCJtaW1lTW9kZXMiLCJkZWZpbmVNb2RlIiwiZGVwZW5kZW5jaWVzIiwiZGVmaW5lTUlNRSIsIm1pbWUiLCJzcGVjIiwicmVzb2x2ZU1vZGUiLCJnZXRNb2RlIiwibWZhY3RvcnkiLCJtb2RlT2JqIiwibW9kZUV4dGVuc2lvbnMiLCJleHRzIiwiaGVscGVyVHlwZSIsIm1vZGVQcm9wcyIsInByb3AkMSIsImV4dGVuZE1vZGUiLCJwcm9wZXJ0aWVzIiwibnN0YXRlIiwidmFsIiwiaW5mbyIsImExIiwiYTIiLCJTdHJpbmdTdHJlYW0iLCJsaW5lT3JhY2xlIiwibGFzdENvbHVtblBvcyIsImxhc3RDb2x1bW5WYWx1ZSIsImxpbmVTdGFydCIsImdldExpbmUiLCJkb2MiLCJmaXJzdCIsInNpemUiLCJFcnJvciIsImNodW5rIiwibGluZXMiLCJjaGlsZHJlbiIsInN6IiwiY2h1bmtTaXplIiwiZ2V0QmV0d2VlbiIsIml0ZXIiLCJnZXRMaW5lcyIsInVwZGF0ZUxpbmVIZWlnaHQiLCJoZWlnaHQiLCJkaWZmIiwibGluZU5vIiwibm8iLCJsaW5lQXRIZWlnaHQiLCJoIiwibGgiLCJpc0xpbmUiLCJsaW5lTnVtYmVyRm9yIiwiU3RyaW5nIiwibGluZU51bWJlckZvcm1hdHRlciIsImZpcnN0TGluZU51bWJlciIsIlBvcyIsImNtcCIsImVxdWFsQ3Vyc29yUG9zIiwiY29weVBvcyIsIngiLCJtYXhQb3MiLCJtaW5Qb3MiLCJjbGlwTGluZSIsImNsaXBQb3MiLCJsYXN0IiwiY2xpcFRvTGVuIiwibGluZWxlbiIsImNsaXBQb3NBcnJheSIsImVvbCIsInBlZWsiLCJ1bmRlZmluZWQiLCJuZXh0IiwiZWF0IiwiZWF0V2hpbGUiLCJlYXRTcGFjZSIsInNraXBUb0VuZCIsInNraXBUbyIsImJhY2tVcCIsImNvbHVtbiIsImluZGVudGF0aW9uIiwiY29uc3VtZSIsImNhc2VJbnNlbnNpdGl2ZSIsImNhc2VkIiwic3Vic3RyIiwiaGlkZUZpcnN0Q2hhcnMiLCJsb29rQWhlYWQiLCJvcmFjbGUiLCJiYXNlVG9rZW4iLCJTYXZlZENvbnRleHQiLCJDb250ZXh0IiwibWF4TG9va0FoZWFkIiwiYmFzZVRva2VucyIsImJhc2VUb2tlblBvcyIsImhpZ2hsaWdodExpbmUiLCJjb250ZXh0IiwiZm9yY2VUb0VuZCIsInN0IiwibW9kZUdlbiIsImxpbmVDbGFzc2VzIiwicnVuTW9kZSIsImxvb3AiLCJvIiwib3ZlcmxheSIsIm92ZXJsYXlzIiwiaV9lbmQiLCJvcGFxdWUiLCJzdHlsZXMiLCJjbGFzc2VzIiwiYmdDbGFzcyIsInRleHRDbGFzcyIsImdldExpbmVTdHlsZXMiLCJ1cGRhdGVGcm9udGllciIsImdldENvbnRleHRCZWZvcmUiLCJyZXNldFN0YXRlIiwibWF4SGlnaGxpZ2h0TGVuZ3RoIiwic3RhdGVBZnRlciIsInNhdmUiLCJzdHlsZUNsYXNzZXMiLCJoaWdobGlnaHRGcm9udGllciIsIm1vZGVGcm9udGllciIsInByZWNpc2UiLCJkaXNwbGF5IiwiZmluZFN0YXJ0TGluZSIsInNhdmVkIiwiZnJvbVNhdmVkIiwicHJvY2Vzc0xpbmUiLCJ2aWV3RnJvbSIsInZpZXdUbyIsIm5leHRMaW5lIiwic3RhcnRBdCIsImNhbGxCbGFua0xpbmUiLCJyZWFkVG9rZW4iLCJjb3B5IiwiVG9rZW4iLCJ0YWtlVG9rZW4iLCJhc0FycmF5IiwidG9rZW5zIiwiZXh0cmFjdExpbmVDbGFzc2VzIiwib3V0cHV0IiwibGluZUNsYXNzIiwiZmxhdHRlblNwYW5zIiwiY3VyU3RhcnQiLCJjdXJTdHlsZSIsImFkZE1vZGVDbGFzcyIsIm1OYW1lIiwibWluaW5kZW50IiwibWlubGluZSIsImxpbSIsImluZGVudGVkIiwicmV0cmVhdEZyb250aWVyIiwic2F3UmVhZE9ubHlTcGFucyIsInNhd0NvbGxhcHNlZFNwYW5zIiwic2VlUmVhZE9ubHlTcGFucyIsInNlZUNvbGxhcHNlZFNwYW5zIiwiTWFya2VkU3BhbiIsIm1hcmtlciIsImdldE1hcmtlZFNwYW5Gb3IiLCJzcGFucyIsInNwYW4iLCJyZW1vdmVNYXJrZWRTcGFuIiwiYWRkTWFya2VkU3BhbiIsIm9wIiwiaW5UaGlzT3AiLCJXZWFrU2V0IiwibWFya2VkU3BhbnMiLCJoYXMiLCJhZGQiLCJhdHRhY2hMaW5lIiwibWFya2VkU3BhbnNCZWZvcmUiLCJvbGQiLCJzdGFydENoIiwiaXNJbnNlcnQiLCJudyIsImluY2x1c2l2ZUxlZnQiLCJpbnNlcnRMZWZ0IiwiZW5kc0FmdGVyIiwiaW5jbHVzaXZlUmlnaHQiLCJtYXJrZWRTcGFuc0FmdGVyIiwiZW5kQ2giLCJzdGFydHNCZWZvcmUiLCJzdHJldGNoU3BhbnNPdmVyQ2hhbmdlIiwiY2hhbmdlIiwiZnVsbCIsIm9sZEZpcnN0Iiwib2xkTGFzdCIsInNhbWVMaW5lIiwib2Zmc2V0Iiwic3BhbiQxIiwiY2xlYXJFbXB0eVNwYW5zIiwibmV3TWFya2VycyIsImdhcE1hcmtlcnMiLCJnYXAiLCJjbGVhcldoZW5FbXB0eSIsInJlbW92ZVJlYWRPbmx5UmFuZ2VzIiwibWFya2VycyIsIm1hcmsiLCJwYXJ0cyIsIm1rIiwiZmluZCIsInAiLCJuZXdQYXJ0cyIsImRmcm9tIiwiZHRvIiwiZGV0YWNoTWFya2VkU3BhbnMiLCJkZXRhY2hMaW5lIiwiYXR0YWNoTWFya2VkU3BhbnMiLCJleHRyYUxlZnQiLCJleHRyYVJpZ2h0IiwiY29tcGFyZUNvbGxhcHNlZE1hcmtlcnMiLCJsZW5EaWZmIiwiYVBvcyIsImJQb3MiLCJmcm9tQ21wIiwidG9DbXAiLCJjb2xsYXBzZWRTcGFuQXRTaWRlIiwic3BzIiwic3AiLCJjb2xsYXBzZWQiLCJjb2xsYXBzZWRTcGFuQXRTdGFydCIsImNvbGxhcHNlZFNwYW5BdEVuZCIsImNvbGxhcHNlZFNwYW5Bcm91bmQiLCJjb25mbGljdGluZ0NvbGxhcHNlZFJhbmdlIiwidmlzdWFsTGluZSIsIm1lcmdlZCIsInZpc3VhbExpbmVFbmQiLCJ2aXN1YWxMaW5lQ29udGludWVkIiwidmlzdWFsTGluZU5vIiwibGluZU4iLCJ2aXMiLCJ2aXN1YWxMaW5lRW5kTm8iLCJsYXN0TGluZSIsImxpbmVJc0hpZGRlbiIsIndpZGdldE5vZGUiLCJsaW5lSXNIaWRkZW5Jbm5lciIsImhlaWdodEF0TGluZSIsImxpbmVPYmoiLCJsaW5lTGVuZ3RoIiwiZm91bmQkMSIsImZpbmRNYXhMaW5lIiwiZCIsIm1heExpbmUiLCJtYXhMaW5lTGVuZ3RoIiwibWF4TGluZUNoYW5nZWQiLCJMaW5lIiwiZXN0aW1hdGVIZWlnaHQiLCJ1cGRhdGVMaW5lIiwiZXN0SGVpZ2h0IiwiY2xlYW5VcExpbmUiLCJzdHlsZVRvQ2xhc3NDYWNoZSIsInN0eWxlVG9DbGFzc0NhY2hlV2l0aE1vZGUiLCJpbnRlcnByZXRUb2tlblN0eWxlIiwiY2FjaGUiLCJidWlsZExpbmVDb250ZW50IiwibGluZVZpZXciLCJidWlsZGVyIiwicHJlIiwidHJhaWxpbmdTcGFjZSIsInNwbGl0U3BhY2VzIiwiZ2V0T3B0aW9uIiwicmVzdCIsImFkZFRva2VuIiwiYnVpbGRUb2tlbiIsImJ1aWxkVG9rZW5CYWRCaWRpIiwiaW5zZXJ0TGluZUNvbnRlbnQiLCJleHRlcm5hbE1lYXN1cmVkIiwibWFwcyIsImNhY2hlcyIsImxhc3RDaGlsZCIsInF1ZXJ5U2VsZWN0b3IiLCJkZWZhdWx0U3BlY2lhbENoYXJQbGFjZWhvbGRlciIsInRpdGxlIiwic3RhcnRTdHlsZSIsImVuZFN0eWxlIiwiY3NzIiwiYXR0cmlidXRlcyIsImRpc3BsYXlUZXh0Iiwic3BlY2lhbCIsInNwZWNpYWxDaGFycyIsIm11c3RXcmFwIiwiY3JlYXRlRG9jdW1lbnRGcmFnbWVudCIsImxhc3RJbmRleCIsInR4dCQxIiwidGFiV2lkdGgiLCJzcGVjaWFsQ2hhclBsYWNlaG9sZGVyIiwiZnVsbFN0eWxlIiwiYXR0ciIsInRyYWlsaW5nQmVmb3JlIiwic3BhY2VCZWZvcmUiLCJidWlsZENvbGxhcHNlZFNwYW4iLCJpZ25vcmVXaWRnZXQiLCJ3aWRnZXQiLCJpbnB1dCIsIm5lZWRzQ29udGVudEF0dHJpYnV0ZSIsInNldFVuZWRpdGFibGUiLCJhbGxUZXh0Iiwic3BhblN0eWxlIiwic3BhbkVuZFN0eWxlIiwic3BhblN0YXJ0U3R5bGUiLCJuZXh0Q2hhbmdlIiwiZm91bmRCb29rbWFya3MiLCJlbmRTdHlsZXMiLCJ1cHRvIiwidG9rZW5UZXh0IiwiTGluZVZpZXciLCJoaWRkZW4iLCJidWlsZFZpZXdBcnJheSIsIm5leHRQb3MiLCJ2aWV3Iiwib3BlcmF0aW9uR3JvdXAiLCJwdXNoT3BlcmF0aW9uIiwib3BzIiwib3duc0dyb3VwIiwiZGVsYXllZENhbGxiYWNrcyIsImZpcmVDYWxsYmFja3NGb3JPcHMiLCJncm91cCIsImNhbGxiYWNrcyIsImN1cnNvckFjdGl2aXR5Q2FsbGVkIiwiZmluaXNoT3BlcmF0aW9uIiwiZW5kQ2IiLCJvcnBoYW5EZWxheWVkQ2FsbGJhY2tzIiwic2lnbmFsTGF0ZXIiLCJsaXN0IiwiZmlyZU9ycGhhbkRlbGF5ZWQiLCJkZWxheWVkIiwidXBkYXRlTGluZUZvckNoYW5nZXMiLCJkaW1zIiwiY2hhbmdlcyIsInVwZGF0ZUxpbmVUZXh0IiwidXBkYXRlTGluZUd1dHRlciIsInVwZGF0ZUxpbmVDbGFzc2VzIiwidXBkYXRlTGluZVdpZGdldHMiLCJlbnN1cmVMaW5lV3JhcHBlZCIsInJlcGxhY2VDaGlsZCIsInpJbmRleCIsInVwZGF0ZUxpbmVCYWNrZ3JvdW5kIiwiYmFja2dyb3VuZCIsIndyYXAiLCJpbnNlcnRCZWZvcmUiLCJnZXRMaW5lQ29udGVudCIsImV4dCIsImJ1aWx0Iiwid3JhcENsYXNzIiwiZ3V0dGVyIiwiZ3V0dGVyQmFja2dyb3VuZCIsImd1dHRlckNsYXNzIiwiZml4ZWRHdXR0ZXIiLCJmaXhlZFBvcyIsImd1dHRlclRvdGFsV2lkdGgiLCJndXR0ZXJNYXJrZXJzIiwid3JhcCQxIiwiZ3V0dGVyV3JhcCIsImxpbmVOdW1iZXIiLCJndXR0ZXJMZWZ0IiwiayIsImd1dHRlclNwZWNzIiwiZ3V0dGVyV2lkdGgiLCJhbGlnbmFibGUiLCJpc1dpZGdldCIsIm5leHRTaWJsaW5nIiwiaW5zZXJ0TGluZVdpZGdldHMiLCJidWlsZExpbmVFbGVtZW50IiwiaW5zZXJ0TGluZVdpZGdldHNGb3IiLCJhbGxvd0Fib3ZlIiwid2lkZ2V0cyIsIndzIiwiaGFuZGxlTW91c2VFdmVudHMiLCJwb3NpdGlvbkxpbmVXaWRnZXQiLCJhYm92ZSIsIm5vSFNjcm9sbCIsIndpZHRoIiwid3JhcHBlcldpZHRoIiwiY292ZXJHdXR0ZXIiLCJwYWRkaW5nTGVmdCIsInBvc2l0aW9uIiwibWFyZ2luTGVmdCIsIndpZGdldEhlaWdodCIsInBhcmVudFN0eWxlIiwiZ3V0dGVycyIsIndyYXBwZXIiLCJjbGllbnRXaWR0aCIsImV2ZW50SW5XaWRnZXQiLCJnZXRBdHRyaWJ1dGUiLCJzaXplciIsIm1vdmVyIiwicGFkZGluZ1RvcCIsImxpbmVTcGFjZSIsIm9mZnNldFRvcCIsInBhZGRpbmdWZXJ0IiwicGFkZGluZ0giLCJjYWNoZWRQYWRkaW5nSCIsImdldENvbXB1dGVkU3R5bGUiLCJjdXJyZW50U3R5bGUiLCJwYXJzZUludCIsInBhZGRpbmdSaWdodCIsImlzTmFOIiwic2Nyb2xsR2FwIiwibmF0aXZlQmFyV2lkdGgiLCJkaXNwbGF5V2lkdGgiLCJzY3JvbGxlciIsImJhcldpZHRoIiwiZGlzcGxheUhlaWdodCIsImNsaWVudEhlaWdodCIsImJhckhlaWdodCIsImVuc3VyZUxpbmVIZWlnaHRzIiwicmVjdCIsIndyYXBwaW5nIiwibGluZVdyYXBwaW5nIiwiY3VyV2lkdGgiLCJoZWlnaHRzIiwicmVjdHMiLCJnZXRDbGllbnRSZWN0cyIsImJvdHRvbSIsInRvcCIsIm1hcEZyb21MaW5lVmlldyIsInVwZGF0ZUV4dGVybmFsTWVhc3VyZW1lbnQiLCJsaW5lTWVhc3VyZSIsIm1lYXN1cmVDaGFyIiwiYmlhcyIsIm1lYXN1cmVDaGFyUHJlcGFyZWQiLCJwcmVwYXJlTWVhc3VyZUZvckxpbmUiLCJmaW5kVmlld0ZvckxpbmUiLCJmaW5kVmlld0luZGV4IiwiZ2V0RGltZW5zaW9ucyIsImZvcmNlVXBkYXRlIiwiaGFzSGVpZ2h0cyIsInByZXBhcmVkIiwidmFySGVpZ2h0Iiwia2V5IiwibWVhc3VyZUNoYXJJbm5lciIsImJvZ3VzIiwicnRvcCIsInJib3R0b20iLCJtZWFzdXJlVGV4dCIsIm51bGxSZWN0Iiwibm9kZUFuZE9mZnNldEluTGluZU1hcCIsIm1TdGFydCIsIm1FbmQiLCJjb3ZlclN0YXJ0IiwiY292ZXJFbmQiLCJnZXRVc2VmdWxSZWN0IiwicGxhY2UiLCJtYXliZVVwZGF0ZVJlY3RGb3Jab29taW5nIiwiclNwYW4iLCJjaGFyV2lkdGgiLCJyYm90IiwiYm90Iiwic2luZ2xlQ3Vyc29ySGVpZ2h0UGVyTGluZSIsInNjcmVlbiIsImxvZ2ljYWxYRFBJIiwiZGV2aWNlWERQSSIsInNjYWxlWCIsInNjYWxlWSIsImxvZ2ljYWxZRFBJIiwiZGV2aWNlWURQSSIsImNsZWFyTGluZU1lYXN1cmVtZW50Q2FjaGVGb3IiLCJjbGVhckxpbmVNZWFzdXJlbWVudENhY2hlIiwiZXh0ZXJuYWxNZWFzdXJlIiwiY2xlYXJDYWNoZXMiLCJjYWNoZWRDaGFyV2lkdGgiLCJjYWNoZWRUZXh0SGVpZ2h0IiwibGluZU51bUNoYXJzIiwicGFnZVNjcm9sbFgiLCJwYWdlWE9mZnNldCIsImRvY3VtZW50RWxlbWVudCIsInNjcm9sbExlZnQiLCJwYWdlU2Nyb2xsWSIsIm1hcmdpblRvcCIsInBhZ2VZT2Zmc2V0Iiwic2Nyb2xsVG9wIiwid2lkZ2V0VG9wSGVpZ2h0IiwiaW50b0Nvb3JkU3lzdGVtIiwiaW5jbHVkZVdpZGdldHMiLCJ5T2ZmIiwidmlld09mZnNldCIsImxPZmYiLCJ4T2ZmIiwiZnJvbUNvb3JkU3lzdGVtIiwiY29vcmRzIiwibG9jYWxCb3giLCJsaW5lU3BhY2VCb3giLCJjaGFyQ29vcmRzIiwiY3Vyc29yQ29vcmRzIiwicHJlcGFyZWRNZWFzdXJlIiwiZ2V0IiwiZ2V0QmlkaSIsInBhcnRQb3MiLCJpbnZlcnQiLCJlc3RpbWF0ZUNvb3JkcyIsIlBvc1dpdGhJbmZvIiwib3V0c2lkZSIsInhSZWwiLCJjb29yZHNDaGFyIiwieSIsImNvb3Jkc0NoYXJJbm5lciIsInJhbmdlRW5kIiwid3JhcHBlZExpbmVFeHRlbnQiLCJiZWdpbiIsIndyYXBwZWRMaW5lRXh0ZW50Q2hhciIsImJveElzQWZ0ZXIiLCJib3giLCJsdHIiLCJjb29yZHNCaWRpUGFydFdyYXBwZWQiLCJjb29yZHNCaWRpUGFydCIsImJhc2VYIiwiY2hBcm91bmQiLCJib3hBcm91bmQiLCJhdExlZnQiLCJhdFN0YXJ0IiwiX2xpbmVObyIsInJlZiIsImNsb3Nlc3REaXN0IiwiZW5kWCIsImRpc3QiLCJ0ZXh0SGVpZ2h0IiwiYW5jaG9yIiwiY2xpZW50TGVmdCIsIm9mZnNldExlZnQiLCJjb21wZW5zYXRlRm9ySFNjcm9sbCIsInRoIiwicGVyTGluZSIsIndpZGdldHNIZWlnaHQiLCJlc3RpbWF0ZUxpbmVIZWlnaHRzIiwiZXN0IiwicG9zRnJvbU1vdXNlIiwibGliZXJhbCIsImZvclJlY3QiLCJzcGFjZSIsImNsaWVudFgiLCJjbGllbnRZIiwiZSQxIiwiY29sRGlmZiIsInJvdW5kIiwicmVnQ2hhbmdlIiwibGVuZGlmZiIsInVwZGF0ZUxpbmVOdW1iZXJzIiwidmlld0NoYW5nZWQiLCJyZXNldFZpZXciLCJjdXQiLCJ2aWV3Q3V0dGluZ1BvaW50IiwiY3V0JDEiLCJjdXRUb3AiLCJjdXRCb3QiLCJyZWdMaW5lQ2hhbmdlIiwib2xkTiIsIm5ld04iLCJhZGp1c3RWaWV3IiwiY291bnREaXJ0eVZpZXciLCJkaXJ0eSIsInVwZGF0ZVNlbGVjdGlvbiIsInNob3dTZWxlY3Rpb24iLCJwcmVwYXJlU2VsZWN0aW9uIiwicHJpbWFyeSIsImN1ckZyYWdtZW50IiwiY3Vyc29ycyIsInNlbEZyYWdtZW50IiwiY3VzdG9tQ3Vyc29yIiwiJGN1c3RvbUN1cnNvciIsInNlbCIsInJhbmdlcyIsInByaW1JbmRleCIsImhlYWQiLCJkcmF3U2VsZWN0aW9uQ3Vyc29yIiwic2hvd0N1cnNvcldoZW5TZWxlY3RpbmciLCJkcmF3U2VsZWN0aW9uUmFuZ2UiLCJjdXJzb3IiLCJjdXJzb3JIZWlnaHQiLCJnZXRXcmFwcGVyRWxlbWVudCIsImNoYXJQb3MiLCJkZWZhdWx0Q2hhcldpZHRoIiwib3RoZXJDdXJzb3IiLCJjbXBDb29yZHMiLCJmcmFnbWVudCIsInBhZGRpbmciLCJsZWZ0U2lkZSIsInJpZ2h0U2lkZSIsInNpemVyV2lkdGgiLCJkb2NMVFIiLCJkcmF3Rm9yTGluZSIsImZyb21BcmciLCJ0b0FyZyIsImxpbmVMZW4iLCJ3cmFwWCIsInNpZGUiLCJleHRlbnQiLCJmcm9tUG9zIiwidG9Qb3MiLCJvcGVuU3RhcnQiLCJvcGVuRW5kIiwib3BlblJpZ2h0IiwidG9wTGVmdCIsInRvcFJpZ2h0IiwiYm90TGVmdCIsImJvdFJpZ2h0Iiwic0Zyb20iLCJzVG8iLCJmcm9tTGluZSIsInRvTGluZSIsInNpbmdsZVZMaW5lIiwibGVmdEVuZCIsInJpZ2h0U3RhcnQiLCJyZXN0YXJ0QmxpbmsiLCJmb2N1c2VkIiwiY2xlYXJJbnRlcnZhbCIsImJsaW5rZXIiLCJjdXJzb3JEaXYiLCJ2aXNpYmlsaXR5IiwiY3Vyc29yQmxpbmtSYXRlIiwic2V0SW50ZXJ2YWwiLCJoYXNGb2N1cyIsIm9uQmx1ciIsImVuc3VyZUZvY3VzIiwiZm9jdXMiLCJvbkZvY3VzIiwiZGVsYXlCbHVyRXZlbnQiLCJkZWxheWluZ0JsdXJFdmVudCIsImRyYWdnaW5nVGV4dCIsInNlbEZvckNvbnRleHRNZW51IiwicmVzZXQiLCJyZWNlaXZlZEZvY3VzIiwic2hpZnQiLCJ1cGRhdGVIZWlnaHRzSW5WaWV3cG9ydCIsInByZXZCb3R0b20iLCJsaW5lRGl2Iiwidmlld1RvcCIsIm9sZEhlaWdodCIsIm11c3RTY3JvbGwiLCJ1cGRhdGVXaWRnZXRIZWlnaHQiLCJjaFdpZHRoIiwidyIsInZpc2libGVMaW5lcyIsInZpZXdwb3J0IiwiZW5zdXJlIiwiZW5zdXJlRnJvbSIsImVuc3VyZVRvIiwibWF5YmVTY3JvbGxXaW5kb3ciLCJkb1Njcm9sbCIsImlubmVySGVpZ2h0Iiwic2Nyb2xsTm9kZSIsInNjcm9sbEludG9WaWV3Iiwic2Nyb2xsUG9zSW50b1ZpZXciLCJtYXJnaW4iLCJsaW1pdCIsImNoYW5nZWQiLCJlbmRDb29yZHMiLCJzY3JvbGxQb3MiLCJjYWxjdWxhdGVTY3JvbGxQb3MiLCJzdGFydFRvcCIsInN0YXJ0TGVmdCIsInVwZGF0ZVNjcm9sbFRvcCIsInNldFNjcm9sbExlZnQiLCJzbmFwTWFyZ2luIiwic2NyZWVudG9wIiwiZG9jQm90dG9tIiwiYXRUb3AiLCJhdEJvdHRvbSIsIm5ld1RvcCIsImd1dHRlclNwYWNlIiwic2NyZWVubGVmdCIsInNjcmVlbnciLCJ0b29XaWRlIiwiYWRkVG9TY3JvbGxUb3AiLCJyZXNvbHZlU2Nyb2xsVG9Qb3MiLCJlbnN1cmVDdXJzb3JWaXNpYmxlIiwiZ2V0Q3Vyc29yIiwic2Nyb2xsVG9Qb3MiLCJjdXJzb3JTY3JvbGxNYXJnaW4iLCJzY3JvbGxUb0Nvb3JkcyIsInNjcm9sbFRvUmFuZ2UiLCJzY3JvbGxUb0Nvb3Jkc1JhbmdlIiwic1BvcyIsInVwZGF0ZURpc3BsYXlTaW1wbGUiLCJzZXRTY3JvbGxUb3AiLCJzdGFydFdvcmtlciIsImZvcmNlU2Nyb2xsIiwic2Nyb2xsSGVpZ2h0Iiwic2Nyb2xsYmFycyIsImlzU2Nyb2xsZXIiLCJzY3JvbGxXaWR0aCIsImFsaWduSG9yaXpvbnRhbGx5IiwibWVhc3VyZUZvclNjcm9sbGJhcnMiLCJndXR0ZXJXIiwiZG9jSCIsInZpZXdIZWlnaHQiLCJ2aWV3V2lkdGgiLCJiYXJMZWZ0IiwiZG9jSGVpZ2h0IiwiTmF0aXZlU2Nyb2xsYmFycyIsInZlcnQiLCJob3JpeiIsInRhYkluZGV4IiwiY2hlY2tlZFplcm9XaWR0aCIsIm1pbkhlaWdodCIsIm1pbldpZHRoIiwidXBkYXRlIiwibmVlZHNIIiwibmVlZHNWIiwic1dpZHRoIiwidG90YWxIZWlnaHQiLCJ0b3RhbFdpZHRoIiwiemVyb1dpZHRoSGFjayIsImRpc2FibGVIb3JpeiIsImVuYWJsZVplcm9XaWR0aEJhciIsImRpc2FibGVWZXJ0IiwicG9pbnRlckV2ZW50cyIsImJhciIsImRlbGF5IiwibWF5YmVEaXNhYmxlIiwiZWxlbWVudEZyb21Qb2ludCIsImNsZWFyIiwiTnVsbFNjcm9sbGJhcnMiLCJ1cGRhdGVTY3JvbGxiYXJzIiwic3RhcnRXaWR0aCIsInN0YXJ0SGVpZ2h0IiwidXBkYXRlU2Nyb2xsYmFyc0lubmVyIiwic2l6ZXMiLCJwYWRkaW5nQm90dG9tIiwiaGVpZ2h0Rm9yY2VyIiwiYm9yZGVyQm90dG9tIiwic2Nyb2xsYmFyRmlsbGVyIiwiY292ZXJHdXR0ZXJOZXh0VG9TY3JvbGxiYXIiLCJndXR0ZXJGaWxsZXIiLCJzY3JvbGxiYXJNb2RlbCIsImluaXRTY3JvbGxiYXJzIiwic2Nyb2xsYmFyU3R5bGUiLCJheGlzIiwibmV4dE9wSWQiLCJzdGFydE9wZXJhdGlvbiIsInVwZGF0ZUlucHV0IiwidHlwaW5nIiwiY2hhbmdlT2JqcyIsInNlbGVjdGlvbkNoYW5nZWQiLCJ1cGRhdGVNYXhMaW5lIiwibWFya0FycmF5cyIsImVuZE9wZXJhdGlvbiIsImVuZE9wZXJhdGlvbnMiLCJlbmRPcGVyYXRpb25fUjEiLCJlbmRPcGVyYXRpb25fVzEiLCJlbmRPcGVyYXRpb25fUjIiLCJlbmRPcGVyYXRpb25fVzIiLCJlbmRPcGVyYXRpb25fZmluaXNoIiwibWF5YmVDbGlwU2Nyb2xsYmFycyIsIm11c3RVcGRhdGUiLCJEaXNwbGF5VXBkYXRlIiwidXBkYXRlZERpc3BsYXkiLCJ1cGRhdGVEaXNwbGF5SWZOZWVkZWQiLCJiYXJNZWFzdXJlIiwiYWRqdXN0V2lkdGhUbyIsIm1heFNjcm9sbExlZnQiLCJwcmVwYXJlZFNlbGVjdGlvbiIsInRha2VGb2N1cyIsInNldERvY3VtZW50SGVpZ2h0IiwicG9zdFVwZGF0ZURpc3BsYXkiLCJ3aGVlbFN0YXJ0WCIsIndoZWVsU3RhcnRZIiwibWF5YmVIaWRkZW5NYXJrZXJzIiwidW5oaWRkZW4iLCJtYXliZVVuaGlkZGVuTWFya2VycyIsImZpbmlzaCIsInJ1bkluT3AiLCJvcGVyYXRpb24iLCJtZXRob2RPcCIsImRvY01ldGhvZE9wIiwiaGlnaGxpZ2h0IiwiaGlnaGxpZ2h0V29ya2VyIiwid29ya1RpbWUiLCJjaGFuZ2VkTGluZXMiLCJvbGRTdHlsZXMiLCJoaWdobGlnaHRlZCIsIm9sZENscyIsIm5ld0NscyIsImlzY2hhbmdlIiwid29ya0RlbGF5IiwiZm9yY2UiLCJ2aXNpYmxlIiwiZWRpdG9ySXNIaWRkZW4iLCJ3cmFwcGVySGVpZ2h0Iiwib2xkRGlzcGxheVdpZHRoIiwiZXZlbnRzIiwic2Nyb2xsYmFyc0NsaXBwZWQiLCJtYXJnaW5Cb3R0b20iLCJib3JkZXJSaWdodFdpZHRoIiwic2VsZWN0aW9uU25hcHNob3QiLCJhY3RpdmUiLCJhbmNob3JOb2RlIiwiZXh0ZW5kIiwiYW5jaG9yT2Zmc2V0IiwiZm9jdXNOb2RlIiwiZm9jdXNPZmZzZXQiLCJyZXN0b3JlU2VsZWN0aW9uIiwic25hcHNob3QiLCJub2RlTmFtZSIsInJlbW92ZUFsbFJhbmdlcyIsImFkZFJhbmdlIiwicmVuZGVyZWRWaWV3IiwibWF5YmVVcGRhdGVMaW5lTnVtYmVyV2lkdGgiLCJ2aWV3cG9ydE1hcmdpbiIsImRpZmZlcmVudCIsImxhc3RXcmFwSGVpZ2h0IiwibGFzdFdyYXBXaWR0aCIsInRvVXBkYXRlIiwic2VsU25hcHNob3QiLCJwYXRjaERpc3BsYXkiLCJzZWxlY3Rpb25EaXYiLCJyZXBvcnRlZFZpZXdGcm9tIiwicmVwb3J0ZWRWaWV3VG8iLCJ1cGRhdGVOdW1iZXJzRnJvbSIsImNvbnRhaW5lciIsInJtIiwiY3VycmVudFdoZWVsVGFyZ2V0IiwidXBkYXRlTnVtYmVyIiwidXBkYXRlR3V0dGVyU3BhY2UiLCJhbGlnbldpZGdldHMiLCJjb21wIiwiYWxpZ24iLCJpbm5lclciLCJsaW5lR3V0dGVyIiwibGluZU51bUlubmVyV2lkdGgiLCJsaW5lTnVtV2lkdGgiLCJnZXRHdXR0ZXJzIiwic2F3TGluZU51bWJlcnMiLCJyZW5kZXJHdXR0ZXJzIiwic3BlY3MiLCJnRWx0IiwidXBkYXRlR3V0dGVycyIsIkRpc3BsYXkiLCJkcmFnZ2FibGUiLCJ3aGVlbERYIiwid2hlZWxEWSIsImFjdGl2ZVRvdWNoIiwiaW5pdCIsIndoZWVsU2FtcGxlcyIsIndoZWVsUGl4ZWxzUGVyVW5pdCIsIndoZWVsRXZlbnREZWx0YSIsImR4Iiwid2hlZWxEZWx0YVgiLCJkeSIsIndoZWVsRGVsdGFZIiwiZGV0YWlsIiwiSE9SSVpPTlRBTF9BWElTIiwiVkVSVElDQUxfQVhJUyIsIndoZWVsRGVsdGEiLCJ3aGVlbEV2ZW50UGl4ZWxzIiwiZGVsdGEiLCJvblNjcm9sbFdoZWVsIiwiY2hyb21lU2Nyb2xsSGFjayIsInBpeGVsc1BlclVuaXQiLCJkZWx0YU1vZGUiLCJkZWx0YVgiLCJkZWx0YVkiLCJjYW5TY3JvbGxYIiwiY2FuU2Nyb2xsWSIsInBpeGVscyIsIm1vdmVkWCIsIm1vdmVkWSIsInNhbXBsZSIsIlNlbGVjdGlvbiIsImVxdWFscyIsImhlcmUiLCJ0aGVyZSIsImRlZXBDb3B5IiwiUmFuZ2UiLCJzb21ldGhpbmdTZWxlY3RlZCIsIm5vcm1hbGl6ZVNlbGVjdGlvbiIsIm1heVRvdWNoIiwic2VsZWN0aW9uc01heVRvdWNoIiwicHJpbSIsInNvcnQiLCJpbnYiLCJzaW1wbGVTZWxlY3Rpb24iLCJjaGFuZ2VFbmQiLCJhZGp1c3RGb3JDaGFuZ2UiLCJjb21wdXRlU2VsQWZ0ZXJDaGFuZ2UiLCJvZmZzZXRQb3MiLCJjb21wdXRlUmVwbGFjZWRTZWwiLCJoaW50Iiwib2xkUHJldiIsIm5ld1ByZXYiLCJsb2FkTW9kZSIsIm1vZGVPcHRpb24iLCJyZXNldE1vZGVTdGF0ZSIsImlzV2hvbGVMaW5lVXBkYXRlIiwid2hvbGVMaW5lVXBkYXRlQmVmb3JlIiwidXBkYXRlRG9jIiwic3BhbnNGb3IiLCJsaW5lc0ZvciIsImZpcnN0TGluZSIsImxhc3RUZXh0IiwibGFzdFNwYW5zIiwibmxpbmVzIiwiaW5zZXJ0IiwicmVtb3ZlIiwiYWRkZWQiLCJhZGRlZCQxIiwiYWRkZWQkMiIsImxpbmtlZERvY3MiLCJzaGFyZWRIaXN0T25seSIsInByb3BhZ2F0ZSIsInNraXAiLCJzaGFyZWRIaXN0IiwibGlua2VkIiwicmVsIiwic2hhcmVkIiwiYXR0YWNoRG9jIiwic2V0RGlyZWN0aW9uQ2xhc3MiLCJkaXJlY3Rpb25DaGFuZ2VkIiwiSGlzdG9yeSIsImRvbmUiLCJ1bmRvbmUiLCJ1bmRvRGVwdGgiLCJsYXN0TW9kVGltZSIsImxhc3RTZWxUaW1lIiwibGFzdE9wIiwibGFzdFNlbE9wIiwibGFzdE9yaWdpbiIsImxhc3RTZWxPcmlnaW4iLCJnZW5lcmF0aW9uIiwibWF4R2VuZXJhdGlvbiIsImhpc3RvcnlDaGFuZ2VGcm9tQ2hhbmdlIiwiaGlzdENoYW5nZSIsImF0dGFjaExvY2FsU3BhbnMiLCJjbGVhclNlbGVjdGlvbkV2ZW50cyIsInBvcCIsImxhc3RDaGFuZ2VFdmVudCIsImhpc3QiLCJhZGRDaGFuZ2VUb0hpc3RvcnkiLCJzZWxBZnRlciIsIm9wSWQiLCJoaXN0b3J5IiwiaGlzdG9yeUV2ZW50RGVsYXkiLCJwdXNoU2VsZWN0aW9uVG9IaXN0b3J5Iiwic2VsZWN0aW9uRXZlbnRDYW5CZU1lcmdlZCIsImFkZFNlbGVjdGlvblRvSGlzdG9yeSIsImNsZWFyUmVkbyIsImRlc3QiLCJleGlzdGluZyIsInJlbW92ZUNsZWFyZWRTcGFucyIsImV4cGxpY2l0bHlDbGVhcmVkIiwiZ2V0T2xkU3BhbnMiLCJtZXJnZU9sZFNwYW5zIiwic3RyZXRjaGVkIiwib2xkQ3VyIiwic3RyZXRjaEN1ciIsImNvcHlIaXN0b3J5QXJyYXkiLCJuZXdHcm91cCIsImluc3RhbnRpYXRlU2VsIiwiZXZlbnQiLCJuZXdDaGFuZ2VzIiwiZXh0ZW5kUmFuZ2UiLCJwb3NCZWZvcmUiLCJleHRlbmRTZWxlY3Rpb24iLCJzZXRTZWxlY3Rpb24iLCJleHRlbmRTZWxlY3Rpb25zIiwiaGVhZHMiLCJyZXBsYWNlT25lU2VsZWN0aW9uIiwic2V0U2ltcGxlU2VsZWN0aW9uIiwiZmlsdGVyU2VsZWN0aW9uQ2hhbmdlIiwic2V0U2VsZWN0aW9uUmVwbGFjZUhpc3RvcnkiLCJzZXRTZWxlY3Rpb25Ob1VuZG8iLCJOYU4iLCJzZXRTZWxlY3Rpb25Jbm5lciIsInNraXBBdG9taWNJblNlbGVjdGlvbiIsInJlQ2hlY2tTZWxlY3Rpb24iLCJtYXlDbGVhciIsIm5ld0FuY2hvciIsInNraXBBdG9taWMiLCJuZXdIZWFkIiwic2tpcEF0b21pY0lubmVyIiwib2xkUG9zIiwicHJldmVudEN1cnNvckxlZnQiLCJzZWxlY3RMZWZ0IiwicHJldmVudEN1cnNvclJpZ2h0Iiwic2VsZWN0UmlnaHQiLCJhdG9taWMiLCJuZWFyIiwibW92ZVBvcyIsImZhciIsImNhbnRFZGl0Iiwic2VsZWN0QWxsIiwiZmlsdGVyQ2hhbmdlIiwiY2FuY2VsZWQiLCJjYW5jZWwiLCJtYWtlQ2hhbmdlIiwiaWdub3JlUmVhZE9ubHkiLCJzdXBwcmVzc0VkaXRzIiwibWFrZUNoYW5nZUlubmVyIiwibWFrZUNoYW5nZVNpbmdsZURvYyIsInJlYmFzZWQiLCJyZWJhc2VIaXN0IiwibWFrZUNoYW5nZUZyb21IaXN0b3J5IiwiYWxsb3dTZWxlY3Rpb25Pbmx5Iiwic3VwcHJlc3MiLCJhbnRpQ2hhbmdlcyIsImZpbHRlciIsInJldHVybmVkIiwidiIsInNoaWZ0RG9jIiwiZGlzdGFuY2UiLCJyZW1vdmVkIiwibWFrZUNoYW5nZVNpbmdsZURvY0luRWRpdG9yIiwicmVjb21wdXRlTWF4TGVuZ3RoIiwiY2hlY2tXaWR0aFN0YXJ0IiwiY2hhbmdlc0hhbmRsZXIiLCJjaGFuZ2VIYW5kbGVyIiwicmVwbGFjZVJhbmdlIiwiYXNzaWduIiwic3BsaXRMaW5lcyIsInJlYmFzZUhpc3RTZWxTaW5nbGUiLCJyZWJhc2VIaXN0QXJyYXkiLCJzdWIiLCJvayIsImNvcGllZCIsImNoYW5nZUxpbmUiLCJoYW5kbGUiLCJjaGFuZ2VUeXBlIiwiTGVhZkNodW5rIiwiQnJhbmNoQ2h1bmsiLCJyZW1vdmVJbm5lciIsImluc2VydElubmVyIiwiaXRlck4iLCJyZW1haW5pbmciLCJsZWFmIiwibWF5YmVTcGlsbCIsIm1lIiwic2libGluZyIsIm15SW5kZXgiLCJ1c2VkIiwiTGluZVdpZGdldCIsIm9wdCIsImFkanVzdFNjcm9sbFdoZW5BYm92ZVZpc2libGUiLCJhZGRMaW5lV2lkZ2V0IiwiaW5zZXJ0QXQiLCJhYm92ZVZpc2libGUiLCJ0aGlzJDEiLCJvbGRIIiwibmV4dE1hcmtlcklkIiwiVGV4dE1hcmtlciIsIm1hcmtUZXh0IiwibWFya1RleHRTaGFyZWQiLCJyZXBsYWNlZFdpdGgiLCJhZGRUb0hpc3RvcnkiLCJjdXJMaW5lIiwiY2xlYXJPbkVudGVyIiwiY2xlYXJIaXN0b3J5Iiwid2l0aE9wIiwidmlzdWFsIiwiZEhlaWdodCIsIlNoYXJlZFRleHRNYXJrZXIiLCJjbG9uZU5vZGUiLCJpc1BhcmVudCIsImZpbmRTaGFyZWRNYXJrZXJzIiwiZmluZE1hcmtzIiwiY29weVNoYXJlZE1hcmtlcnMiLCJtRnJvbSIsIm1UbyIsInN1Yk1hcmsiLCJkZXRhY2hTaGFyZWRNYXJrZXJzIiwic3ViTWFya2VyIiwibmV4dERvY0lkIiwiRG9jIiwibGluZVNlcCIsImNsZWFuR2VuZXJhdGlvbiIsImNvbnN0cnVjdG9yIiwiZ2V0VmFsdWUiLCJqb2luIiwibGluZVNlcGFyYXRvciIsInNldFZhbHVlIiwiZ2V0UmFuZ2UiLCJnZXRMaW5lSGFuZGxlIiwiZ2V0TGluZU51bWJlciIsImdldExpbmVIYW5kbGVWaXN1YWxTdGFydCIsImxpbmVDb3VudCIsImxpc3RTZWxlY3Rpb25zIiwic2V0Q3Vyc29yIiwiZXh0ZW5kU2VsZWN0aW9uc0J5Iiwic2V0U2VsZWN0aW9ucyIsImFkZFNlbGVjdGlvbiIsImdldFNlbGVjdGlvbnMiLCJyZXBsYWNlU2VsZWN0aW9uIiwiZHVwIiwicmVwbGFjZVNlbGVjdGlvbnMiLCJuZXdTZWwiLCJ1bmRvIiwicmVkbyIsInVuZG9TZWxlY3Rpb24iLCJyZWRvU2VsZWN0aW9uIiwic2V0RXh0ZW5kaW5nIiwiZ2V0RXh0ZW5kaW5nIiwiaGlzdG9yeVNpemUiLCJtYXJrQ2xlYW4iLCJjaGFuZ2VHZW5lcmF0aW9uIiwiZm9yY2VTcGxpdCIsImlzQ2xlYW4iLCJnZW4iLCJnZXRIaXN0b3J5Iiwic2V0SGlzdG9yeSIsImhpc3REYXRhIiwic2V0R3V0dGVyTWFya2VyIiwiZ3V0dGVySUQiLCJjbGVhckd1dHRlciIsImxpbmVJbmZvIiwiYWRkTGluZUNsYXNzIiwid2hlcmUiLCJyZW1vdmVMaW5lQ2xhc3MiLCJyZW1vdmVMaW5lV2lkZ2V0Iiwic2V0Qm9va21hcmsiLCJyZWFsT3B0cyIsImZpbmRNYXJrc0F0IiwiZ2V0QWxsTWFya3MiLCJwb3NGcm9tSW5kZXgiLCJzZXBTaXplIiwiaW5kZXhGcm9tUG9zIiwiY29weUhpc3RvcnkiLCJsaW5rZWREb2MiLCJ1bmxpbmtEb2MiLCJzcGxpdElkcyIsIml0ZXJMaW5rZWREb2NzIiwiZ2V0RWRpdG9yIiwic2V0RGlyZWN0aW9uIiwiZWFjaExpbmUiLCJsYXN0RHJvcCIsIm9uRHJvcCIsImNsZWFyRHJhZ0N1cnNvciIsImZpbGVzIiwiZGF0YVRyYW5zZmVyIiwiaXNSZWFkT25seSIsIkZpbGVSZWFkZXIiLCJGaWxlIiwicmVhZCIsIm1hcmtBc1JlYWRBbmRQYXN0ZUlmQWxsRmlsZXNBcmVSZWFkIiwidCIsInJlYWRUZXh0RnJvbUZpbGUiLCJmaWxlIiwiYWxsb3dEcm9wRmlsZVR5cGVzIiwicmVhZGVyIiwib25lcnJvciIsIm9ubG9hZCIsInJlYWRBc1RleHQiLCJ0ZXh0JDEiLCJnZXREYXRhIiwic2VsZWN0ZWQiLCJvbkRyYWdTdGFydCIsInNldERhdGEiLCJlZmZlY3RBbGxvd2VkIiwic2V0RHJhZ0ltYWdlIiwiaW1nIiwic3JjIiwiX3RvcCIsIm9uRHJhZ092ZXIiLCJmcmFnIiwiZHJhZ0N1cnNvciIsImZvckVhY2hDb2RlTWlycm9yIiwiZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSIsImJ5Q2xhc3MiLCJlZGl0b3JzIiwiZ2xvYmFsc1JlZ2lzdGVyZWQiLCJlbnN1cmVHbG9iYWxIYW5kbGVycyIsInJlZ2lzdGVyR2xvYmFsSGFuZGxlcnMiLCJyZXNpemVUaW1lciIsIm9uUmVzaXplIiwic2V0U2l6ZSIsImtleU5hbWVzIiwiZnJvbUNoYXJDb2RlIiwia2V5TWFwIiwibm9ybWFsaXplS2V5TmFtZSIsImFsdCIsImN0cmwiLCJjbWQiLCJub3JtYWxpemVLZXlNYXAiLCJrZXltYXAiLCJrZXluYW1lIiwia2V5cyIsImxvb2t1cEtleSIsImdldEtleU1hcCIsImZhbGx0aHJvdWdoIiwiaXNNb2RpZmllcktleSIsImtleUNvZGUiLCJhZGRNb2RpZmllck5hbWVzIiwibm9TaGlmdCIsImFsdEtleSIsIm1ldGFLZXkiLCJzaGlmdEtleSIsImtleU5hbWUiLCJhbHRHcmFwaEtleSIsImRlbGV0ZU5lYXJTZWxlY3Rpb24iLCJjb21wdXRlIiwia2lsbCIsInRvS2lsbCIsInJlcGxhY2VkIiwibW92ZUNoYXJMb2dpY2FsbHkiLCJtb3ZlTG9naWNhbGx5IiwiZW5kT2ZMaW5lIiwidmlzdWFsbHkiLCJwcmVwIiwidGFyZ2V0VG9wIiwibW92ZVZpc3VhbGx5IiwiYmlkaSIsIm12IiwiZ2V0V3JhcHBlZExpbmVFeHRlbnQiLCJtb3ZlSW5TdG9yYWdlT3JkZXIiLCJzZWFyY2hJblZpc3VhbExpbmUiLCJnZXRSZXMiLCJyZXMiLCJuZXh0Q2giLCJiYXNpYyIsInBjRGVmYXVsdCIsImVtYWNzeSIsIm1hY0RlZmF1bHQiLCJjb21tYW5kcyIsInNpbmdsZVNlbGVjdGlvbiIsImtpbGxMaW5lIiwiZGVsZXRlTGluZSIsImRlbExpbmVMZWZ0IiwiZGVsV3JhcHBlZExpbmVMZWZ0IiwiZGVsV3JhcHBlZExpbmVSaWdodCIsInJpZ2h0UG9zIiwiZ29Eb2NTdGFydCIsImdvRG9jRW5kIiwiZ29MaW5lU3RhcnQiLCJnb0xpbmVTdGFydFNtYXJ0IiwibGluZVN0YXJ0U21hcnQiLCJnb0xpbmVFbmQiLCJsaW5lRW5kIiwiZ29MaW5lUmlnaHQiLCJnb0xpbmVMZWZ0IiwiZ29MaW5lTGVmdFNtYXJ0IiwiZ29MaW5lVXAiLCJtb3ZlViIsImdvTGluZURvd24iLCJnb1BhZ2VVcCIsImdvUGFnZURvd24iLCJnb0NoYXJMZWZ0IiwibW92ZUgiLCJnb0NoYXJSaWdodCIsImdvQ29sdW1uTGVmdCIsImdvQ29sdW1uUmlnaHQiLCJnb1dvcmRMZWZ0IiwiZ29Hcm91cFJpZ2h0IiwiZ29Hcm91cExlZnQiLCJnb1dvcmRSaWdodCIsImRlbENoYXJCZWZvcmUiLCJkZWxldGVIIiwiZGVsQ2hhckFmdGVyIiwiZGVsV29yZEJlZm9yZSIsImRlbFdvcmRBZnRlciIsImRlbEdyb3VwQmVmb3JlIiwiZGVsR3JvdXBBZnRlciIsImluZGVudEF1dG8iLCJpbmRlbnRTZWxlY3Rpb24iLCJpbmRlbnRNb3JlIiwiaW5kZW50TGVzcyIsImluc2VydFRhYiIsImluc2VydFNvZnRUYWIiLCJzcGFjZXMiLCJkZWZhdWx0VGFiIiwiZXhlY0NvbW1hbmQiLCJ0cmFuc3Bvc2VDaGFycyIsIm5ld2xpbmVBbmRJbmRlbnQiLCJzZWxzIiwiaW5kZW50TGluZSIsIm9wZW5MaW5lIiwidG9nZ2xlT3ZlcndyaXRlIiwiZmlyc3ROb25XUyIsImluV1MiLCJkb0hhbmRsZUJpbmRpbmciLCJib3VuZCIsImRyb3BTaGlmdCIsImVuc3VyZVBvbGxlZCIsInByZXZTaGlmdCIsImxvb2t1cEtleUZvckVkaXRvciIsImtleU1hcHMiLCJleHRyYUtleXMiLCJzdG9wU2VxIiwiZGlzcGF0Y2hLZXkiLCJzZXEiLCJrZXlTZXEiLCJkaXNwYXRjaEtleUlubmVyIiwiaGFuZGxlS2V5QmluZGluZyIsIm1vdGlvbiIsImhhbmRsZUNoYXJCaW5kaW5nIiwibGFzdFN0b3BwZWRLZXkiLCJvbktleURvd24iLCJnZXRGaWVsZCIsImhhbmRsZWQiLCJzaG93Q3Jvc3NIYWlyIiwidXAiLCJvbktleVVwIiwib25LZXlQcmVzcyIsImNoYXJDb2RlIiwibGFzdENsaWNrIiwibGFzdERvdWJsZUNsaWNrIiwiRE9VQkxFQ0xJQ0tfREVMQVkiLCJQYXN0Q2xpY2siLCJjbGlja1JlcGVhdCIsIm5vdyIsImNvbXBhcmUiLCJvbk1vdXNlRG93biIsInN1cHBvcnRzVG91Y2giLCJjbGlja0luR3V0dGVyIiwicmVwZWF0Iiwic2VsZWN0aW5nVGV4dCIsImhhbmRsZU1hcHBlZEJ1dHRvbiIsImxlZnRCdXR0b25Eb3duIiwib25Db250ZXh0TWVudSIsImNvbmZpZ3VyZU1vdXNlIiwib3B0aW9uIiwidW5pdCIsImFkZE5ldyIsIm1vdmVPbkRyYWciLCJjb250YWluZWQiLCJiZWhhdmlvciIsImRyYWdEcm9wIiwibGVmdEJ1dHRvblN0YXJ0RHJhZyIsImxlZnRCdXR0b25TZWxlY3QiLCJtb3ZlZCIsImRyYWdFbmQiLCJtb3VzZU1vdmUiLCJkcmFnU3RhcnQiLCJwcmV2ZW50U2Nyb2xsIiwiZTIiLCJyYW5nZUZvclVuaXQiLCJmaW5kV29yZEF0Iiwib3VyUmFuZ2UiLCJvdXJJbmRleCIsInN0YXJ0U2VsIiwibGFzdFBvcyIsImV4dGVuZFRvIiwic3RhcnRDb2wiLCJwb3NDb2wiLCJsZWZ0UG9zIiwib2xkUmFuZ2UiLCJyYW5nZXMkMSIsImJpZGlTaW1wbGlmeSIsImVkaXRvclNpemUiLCJjb3VudGVyIiwiY3VyQ291bnQiLCJtb3ZlIiwiYnV0dG9ucyIsImFuY2hvckxpbmUiLCJib3VuZGFyeSIsImhlYWRJbmRleCIsInVzZVBhcnQiLCJndXR0ZXJFdmVudCIsInByZXZlbnQiLCJtWCIsIm1ZIiwidG91Y2hlcyIsImxpbmVCb3giLCJnIiwiY29udGV4dE1lbnVJbkd1dHRlciIsInRoZW1lQ2hhbmdlZCIsInRoZW1lIiwiSW5pdCIsImRlZmF1bHRzIiwib3B0aW9uSGFuZGxlcnMiLCJkZWZpbmVPcHRpb25zIiwiZGVmbHQiLCJub3RPbkluaXQiLCJkZWZpbmVPcHRpb24iLCJuZXdCcmVha3MiLCJyZWZyZXNoIiwiZ2V0SW5wdXRGaWVsZCIsInNwZWxsY2hlY2siLCJhdXRvY29ycmVjdCIsImF1dG9jYXBpdGFsaXplIiwiZGV0YWNoIiwiYXR0YWNoIiwid3JhcHBpbmdDaGFuZ2VkIiwiaW50ZWdlciIsImJsdXIiLCJyZWFkT25seUNoYW5nZWQiLCJzY3JlZW5SZWFkZXJMYWJlbENoYW5nZWQiLCJkcmFnRHJvcENoYW5nZWQiLCJyZXNldFBvc2l0aW9uIiwiZnVuY3MiLCJkcmFnRnVuY3Rpb25zIiwidG9nZ2xlIiwiZW50ZXIiLCJvdmVyIiwibGVhdmUiLCJkcm9wIiwiaW5wdXRTdHlsZXMiLCJpbnB1dFN0eWxlIiwicGFzdGVJbmNvbWluZyIsImN1dEluY29taW5nIiwiYXV0b2ZvY3VzIiwicmVnaXN0ZXJFdmVudEhhbmRsZXJzIiwiZmluaXNoSW5pdCIsImluaXRIb29rcyIsInRleHRSZW5kZXJpbmciLCJ3b3JkIiwidG91Y2hGaW5pc2hlZCIsInByZXZUb3VjaCIsImZpbmlzaFRvdWNoIiwiaXNNb3VzZUxpa2VUb3VjaEV2ZW50IiwidG91Y2giLCJyYWRpdXNYIiwicmFkaXVzWSIsImZhckF3YXkiLCJwYWdlWCIsInBhZ2VZIiwiaW5wIiwiaG93IiwiYWdncmVzc2l2ZSIsImN1clNwYWNlIiwiY3VyU3BhY2VTdHJpbmciLCJpbmRlbnRVbml0IiwiaW5kZW50U3RyaW5nIiwiaW5kZW50V2l0aFRhYnMiLCJwb3MkMSIsImRlZmluZUluaXRIb29rIiwibGFzdENvcGllZCIsInNldExhc3RDb3BpZWQiLCJuZXdMYXN0Q29waWVkIiwiYXBwbHlUZXh0SW5wdXQiLCJpbnNlcnRlZCIsImRlbGV0ZWQiLCJyZWNlbnQiLCJwYXN0ZSIsInRleHRMaW5lcyIsIm11bHRpUGFzdGUiLCJwYXN0ZUxpbmVzUGVyU2VsZWN0aW9uIiwibGluZVdpc2UiLCJjaGFuZ2VFdmVudCIsInRyaWdnZXJFbGVjdHJpYyIsImhhbmRsZVBhc3RlIiwicGFzdGVkIiwiY2xpcGJvYXJkRGF0YSIsImRpc2FibGVJbnB1dCIsInNtYXJ0SW5kZW50IiwiZ2V0TW9kZUF0IiwiZWxlY3RyaWNJbnB1dCIsImNvcHlhYmxlUmFuZ2VzIiwibGluZVJhbmdlIiwiZGlzYWJsZUJyb3dzZXJNYWdpYyIsImZpZWxkIiwiaGlkZGVuVGV4dGFyZWEiLCJib3JkZXIiLCJhZGRFZGl0b3JNZXRob2RzIiwiaGVscGVycyIsInNldE9wdGlvbiIsImdldERvYyIsImFkZEtleU1hcCIsInJlbW92ZUtleU1hcCIsImFkZE92ZXJsYXkiLCJtb2RlU3BlYyIsInJlbW92ZU92ZXJsYXkiLCJuZXdSYW5nZXMiLCJnZXRUb2tlbkF0IiwiZ2V0TGluZVRva2VucyIsImdldFRva2VuVHlwZUF0IiwiZ2V0SGVscGVyIiwiZ2V0SGVscGVycyIsImhlbHAiLCJfZ2xvYmFsIiwiZ2V0U3RhdGVBZnRlciIsImRlZmF1bHRUZXh0SGVpZ2h0IiwiZ2V0Vmlld3BvcnQiLCJhZGRXaWRnZXQiLCJ2c3BhY2UiLCJoc3BhY2UiLCJ0cmlnZ2VyT25LZXlEb3duIiwidHJpZ2dlck9uS2V5UHJlc3MiLCJ0cmlnZ2VyT25LZXlVcCIsInRyaWdnZXJPbk1vdXNlRG93biIsImZpbmRQb3NIIiwiYW1vdW50IiwiaGl0U2lkZSIsInJ0bE1vdmVWaXN1YWxseSIsImZpbmRQb3NWIiwiZ29hbENvbHVtbiIsImdvYWxzIiwiaGVhZFBvcyIsInN0YXJ0Q2hhciIsImNoZWNrIiwic2Nyb2xsVG8iLCJnZXRTY3JvbGxJbmZvIiwiaW50ZXJwcmV0Iiwic3dhcERvYyIsInBocmFzZSIsInBocmFzZVRleHQiLCJwaHJhc2VzIiwiZ2V0U2Nyb2xsZXJFbGVtZW50IiwiZ2V0R3V0dGVyRWxlbWVudCIsInJlZ2lzdGVySGVscGVyIiwicmVnaXN0ZXJHbG9iYWxIZWxwZXIiLCJwcmVkaWNhdGUiLCJvcmlnRGlyIiwibGluZURpciIsImZpbmROZXh0TGluZSIsIm1vdmVPbmNlIiwiYm91bmRUb0xpbmUiLCJhc3RyYWwiLCJzYXdUeXBlIiwicGFnZVNpemUiLCJtb3ZlQW1vdW50IiwiQ29udGVudEVkaXRhYmxlSW5wdXQiLCJsYXN0QW5jaG9yTm9kZSIsImxhc3RBbmNob3JPZmZzZXQiLCJsYXN0Rm9jdXNOb2RlIiwibGFzdEZvY3VzT2Zmc2V0IiwicG9sbGluZyIsImNvbXBvc2luZyIsImdyYWNlUGVyaW9kIiwicmVhZERPTVRpbWVvdXQiLCJwb3NUb0RPTSIsImlzSW5HdXR0ZXIiLCJzY2FuIiwiYmFkUG9zIiwiYmFkIiwiZG9tVGV4dEJldHdlZW4iLCJjbG9zaW5nIiwiZXh0cmFMaW5lYnJlYWsiLCJyZWNvZ25pemVNYXJrZXIiLCJhZGRUZXh0Iiwid2FsayIsImNtVGV4dCIsIm1hcmtlcklEIiwiaXNCbG9jayIsInRleHRDb250ZW50Iiwibm9kZVZhbHVlIiwiZG9tVG9Qb3MiLCJsaW5lTm9kZSIsImxvY2F0ZU5vZGVJbkxpbmVWaWV3IiwidGV4dE5vZGUiLCJ0b3BOb2RlIiwiY3VyTm9kZSIsInByZXZpb3VzU2libGluZyIsImRpc3QkMSIsImJlbG9uZ3NUb0lucHV0Iiwib25Db3B5Q3V0IiwibGluZVdpc2VDb3B5Q3V0IiwiY2xlYXJEYXRhIiwia2x1ZGdlIiwiaGFkRm9jdXMiLCJzaG93UHJpbWFyeVNlbGVjdGlvbiIsImNvbnRlbnRFZGl0YWJsZSIsInVwZGF0ZUZyb21ET00iLCJyZWFkRnJvbURPTVNvb24iLCJmb3JjZUNvbXBvc2l0aW9uRW5kIiwibGFiZWwiLCJyZW1vdmVBdHRyaWJ1dGUiLCJzaG93TXVsdGlwbGVTZWxlY3Rpb25zIiwiY3VyQW5jaG9yIiwiY3VyRm9jdXMiLCJybmciLCJyYW5nZUNvdW50IiwiZ2V0UmFuZ2VBdCIsInN0YXJ0R3JhY2VQZXJpb2QiLCJyZW1lbWJlclNlbGVjdGlvbiIsInNlbGVjdGlvbkluRWRpdG9yIiwiY29tbW9uQW5jZXN0b3JDb250YWluZXIiLCJwb2xsIiwicG9sbFNlbGVjdGlvbiIsInBvbGxJbnRlcnZhbCIsInBvbGxDb250ZW50IiwiZnJvbUluZGV4IiwiZnJvbU5vZGUiLCJ0b05vZGUiLCJ0b0luZGV4IiwibmV3VGV4dCIsIm9sZFRleHQiLCJjdXRGcm9udCIsImN1dEVuZCIsIm9sZFRvcCIsIm1heEN1dEZyb250IiwibmV3Qm90Iiwib2xkQm90IiwibWF4Q3V0RW5kIiwiY2hGcm9tIiwiY2hUbyIsIlRleHRhcmVhSW5wdXQiLCJwcmV2SW5wdXQiLCJwb2xsaW5nRmFzdCIsImZyb21UZXh0QXJlYSIsInRleHRhcmVhIiwidGFiaW5kZXgiLCJwbGFjZWhvbGRlciIsInJlYWxTdWJtaXQiLCJmb3JtIiwibGVhdmVTdWJtaXRNZXRob2RBbG9uZSIsInN1Ym1pdCIsIndyYXBwZWRTdWJtaXQiLCJnZXRUZXh0QXJlYSIsInRvVGV4dEFyZWEiLCJhZGRMZWdhY3lQcm9wcyIsImNtcFBvcyIsImNyZWF0ZUZpZWxkIiwicHJlcGFyZUNvcHlDdXQiLCJmYXN0UG9sbCIsImRpc3BhdGNoRXZlbnQiLCJFdmVudCIsIl9kaXNwbGF5IiwibW92ZUlucHV0V2l0aEN1cnNvciIsIndyYXBPZmYiLCJsaW5lT2ZmIiwidGVUb3AiLCJ0ZUxlZnQiLCJkcmF3biIsImNvbnRleHRNZW51UGVuZGluZyIsInNsb3dQb2xsIiwibWlzc2VkIiwic2FtZSIsInJlc2V0U2VsZWN0aW9uT25Db250ZXh0TWVudSIsIm9sZFNjcm9sbFkiLCJvbGRDU1MiLCJvbGRXcmFwcGVyQ1NTIiwid3JhcHBlckJveCIsIm9mZnNldFBhcmVudCIsInNjcm9sbFkiLCJyZWhpZGUiLCJkZXRlY3RpbmdTZWxlY3RBbGwiLCJwcmVwYXJlU2VsZWN0QWxsSGFjayIsIm1vdXNldXAiLCJleHR2YWwiLCJkaXNhYmxlZCIsImRvbnREZWxlZ2F0ZSIsIm1ldGhvZCIsImRlZmluZUV4dGVuc2lvbiIsImZ1bmMiLCJkZWZpbmVEb2NFeHRlbnNpb24iLCJ2ZXJzaW9uIiwiZmFjdG9yeSIsInB1c2hDb250ZXh0IiwicG9wQ29udGV4dCIsInR5cGVCZWZvcmUiLCJwcmV2VG9rZW4iLCJ0eXBlQXRFbmRPZkxpbmUiLCJpc1RvcFNjb3BlIiwid29yZHMiLCJwcm9wZXJ0eUlzRW51bWVyYWJsZSIsImNvbmZpZyIsInBhcnNlckNvbmZpZyIsImN1clB1bmMiLCJpc0RlZktleXdvcmQiLCJzdGF0ZW1lbnRJbmRlbnRVbml0IiwiZG9udEFsaWduQ2FsbHMiLCJrZXl3b3JkcyIsImJ1aWx0aW4iLCJibG9ja0tleXdvcmRzIiwiZGVmS2V5d29yZHMiLCJhdG9tcyIsImhvb2tzIiwibXVsdGlMaW5lU3RyaW5ncyIsImluZGVudFN0YXRlbWVudHMiLCJpbmRlbnRTd2l0Y2giLCJuYW1lc3BhY2VTZXBhcmF0b3IiLCJpc1B1bmN0dWF0aW9uQ2hhciIsIm51bWJlclN0YXJ0IiwibnVtYmVyIiwiaXNPcGVyYXRvckNoYXIiLCJpc0lkZW50aWZpZXJDaGFyIiwiaXNSZXNlcnZlZElkZW50aWZpZXIiLCJ0b2tlbkJhc2UiLCJ0b2tlbml6ZSIsInRva2VuU3RyaW5nIiwidG9rZW5Db21tZW50IiwicXVvdGUiLCJlc2NhcGVkIiwibWF5YmVFbmQiLCJtYXliZUVPTCIsInR5cGVGaXJzdERlZmluaXRpb25zIiwiYmFzZWNvbHVtbiIsInN0YXJ0T2ZMaW5lIiwiY3R4Iiwic3R5bGVEZWZzIiwiZmlyc3RDaGFyIiwiZG9udEluZGVudFN0YXRlbWVudHMiLCJob29rIiwic3dpdGNoQmxvY2siLCJhbGxtYW5JbmRlbnRhdGlvbiIsImJsb2NrQ29tbWVudFN0YXJ0IiwiYmxvY2tDb21tZW50RW5kIiwiYmxvY2tDb21tZW50Q29udGludWUiLCJsaW5lQ29tbWVudCIsImZvbGQiLCJjS2V5d29yZHMiLCJjcHBLZXl3b3JkcyIsIm9iakNLZXl3b3JkcyIsIm9iakNCdWlsdGlucyIsImJhc2ljQ1R5cGVzIiwiYmFzaWNPYmpDVHlwZXMiLCJjVHlwZXMiLCJpZGVudGlmaWVyIiwib2JqQ1R5cGVzIiwiY0Jsb2NrS2V5d29yZHMiLCJjRGVmS2V5d29yZHMiLCJjcHBIb29rIiwicG9pbnRlckhvb2siLCJfc3RyZWFtIiwiY0lzUmVzZXJ2ZWRJZGVudGlmaWVyIiwiY3BwMTRMaXRlcmFsIiwiY3BwMTFTdHJpbmdIb29rIiwiY3BwMTFSYXdTdHJpbmdEZWxpbSIsInRva2VuUmF3U3RyaW5nIiwiY3BwTG9va3NMaWtlQ29uc3RydWN0b3IiLCJsYXN0VHdvIiwidG9rZW5BdFN0cmluZyIsImRlbGltIiwiZGVmIiwibWltZXMiLCJ0b2tlblRyaXBsZVN0cmluZyIsInRva2VuTmVzdGVkQ29tbWVudCIsImRlcHRoIiwidG9rZW5Lb3RsaW5TdHJpbmciLCJ0cmlwbGVTdHJpbmciLCJjeCIsImNsb3NlQnJhY2tldHMiLCJwYWlycyIsInRyaXBsZXMiLCJpbnRlbmRTd2l0Y2giLCJzdHJpbmdUb2tlbml6ZXIiLCJ0b2tlbkNleWxvblN0cmluZyIsImtleVNldCIsImlubGluZSIsInByb3BlcnR5S2V5d29yZHMiLCJ0b2tlbkhvb2tzIiwiZG9jdW1lbnRUeXBlcyIsIm1lZGlhVHlwZXMiLCJtZWRpYUZlYXR1cmVzIiwibWVkaWFWYWx1ZUtleXdvcmRzIiwibm9uU3RhbmRhcmRQcm9wZXJ0eUtleXdvcmRzIiwiZm9udFByb3BlcnRpZXMiLCJjb3VudGVyRGVzY3JpcHRvcnMiLCJjb2xvcktleXdvcmRzIiwidmFsdWVLZXl3b3JkcyIsImFsbG93TmVzdGVkIiwic3VwcG9ydHNBdENvbXBvbmVudCIsImhpZ2hsaWdodE5vblN0YW5kYXJkUHJvcGVydHlLZXl3b3JkcyIsInJldCIsInRwIiwidG9rZW5QYXJlbnRoZXNpemVkIiwicGFzcyIsInN0YXRlcyIsInBvcEFuZFBhc3MiLCJ3b3JkQXNWYWx1ZSIsInN0YXRlQXJnIiwiYXRCbG9jayIsImRvY3VtZW50VHlwZXNfIiwibWVkaWFUeXBlc18iLCJtZWRpYUZlYXR1cmVzXyIsIm1lZGlhVmFsdWVLZXl3b3Jkc18iLCJwcm9wZXJ0eUtleXdvcmRzXyIsIm5vblN0YW5kYXJkUHJvcGVydHlLZXl3b3Jkc18iLCJjb2xvcktleXdvcmRzXyIsInZhbHVlS2V5d29yZHNfIiwiYWxsV29yZHMiLCJ0b2tlbkNDb21tZW50IiwiZGVmYXVsdFRhZ3MiLCJzY3JpcHQiLCJtYXliZUJhY2t1cCIsInBhdCIsImF0dHJSZWdleHBDYWNoZSIsImdldEF0dHJSZWdleHAiLCJyZWdleHAiLCJnZXRBdHRyVmFsdWUiLCJnZXRUYWdSZWdleHAiLCJ0YWdOYW1lIiwiYW5jaG9yZWQiLCJhZGRUYWdzIiwiZmluZE1hdGNoaW5nTW9kZSIsInRhZ0luZm8iLCJ0YWdUZXh0IiwiaHRtbE1vZGUiLCJtdWx0aWxpbmVUYWdJbmRlbnRGYWN0b3IiLCJtdWx0aWxpbmVUYWdJbmRlbnRQYXN0VGFnIiwiYWxsb3dNaXNzaW5nVGFnTmFtZSIsInRhZ3MiLCJjb25maWdUYWdzIiwiY29uZmlnU2NyaXB0Iiwic2NyaXB0VHlwZXMiLCJtYXRjaGVzIiwiaHRtbCIsImh0bWxTdGF0ZSIsImluVGFnIiwiZW5kVGFnQSIsImVuZFRhZyIsImxvY2FsU3RhdGUiLCJsb2NhbE1vZGUiLCJsb2NhbCIsInN0YXRlbWVudEluZGVudCIsImpzb25sZE1vZGUiLCJqc29ubGQiLCJqc29uTW9kZSIsImpzb24iLCJ0cmFja1Njb3BlIiwiaXNUUyIsInR5cGVzY3JpcHQiLCJ3b3JkUkUiLCJ3b3JkQ2hhcmFjdGVycyIsImt3IiwiQSIsIkIiLCJDIiwiRCIsIm9wZXJhdG9yIiwiYXRvbSIsImlzSnNvbmxkS2V5d29yZCIsInJlYWRSZWdleHAiLCJpblNldCIsImNvbnQiLCJleHByZXNzaW9uQWxsb3dlZCIsInRva2VuUXVhc2kiLCJsZXhpY2FsIiwibGFzdFR5cGUiLCJicmFja2V0cyIsImZpbmRGYXRBcnJvdyIsImZhdEFycm93QXQiLCJhcnJvdyIsInNhd1NvbWV0aGluZyIsImJyYWNrZXQiLCJhdG9taWNUeXBlcyIsIkpTTGV4aWNhbCIsImluU2NvcGUiLCJ2YXJuYW1lIiwibG9jYWxWYXJzIiwidmFycyIsInBhcnNlSlMiLCJjYyIsIm1hcmtlZCIsImV4cHJlc3Npb24iLCJzdGF0ZW1lbnQiLCJsZXgiLCJpbkxpc3QiLCJyZWdpc3RlciIsImJsb2NrIiwibmV3Q29udGV4dCIsInJlZ2lzdGVyVmFyU2NvcGVkIiwiVmFyIiwiZ2xvYmFsVmFycyIsImlzTW9kaWZpZXIiLCJkZWZhdWx0VmFycyIsInB1c2hjb250ZXh0IiwicHVzaGJsb2NrY29udGV4dCIsInBvcGNvbnRleHQiLCJwdXNobGV4IiwicG9wbGV4IiwiZXhwZWN0Iiwid2FudGVkIiwiZXhwIiwidmFyZGVmIiwicGFyZW5FeHByIiwibWF5YmVleHByZXNzaW9uIiwibWF5YmVlbHNlIiwiZnVuY3Rpb25kZWYiLCJmb3JzcGVjIiwiZW51bWRlZiIsInR5cGVuYW1lIiwidHlwZWV4cHIiLCJtYXliZWxhYmVsIiwibWF5YmVDYXRjaEJpbmRpbmciLCJhZnRlckV4cG9ydCIsImFmdGVySW1wb3J0IiwiZnVuYXJnIiwiZXhwcmVzc2lvbklubmVyIiwiZXhwcmVzc2lvbk5vQ29tbWEiLCJub0NvbW1hIiwiYXJyb3dCb2R5Tm9Db21tYSIsImFycm93Qm9keSIsImNvbW1hc2VwIiwibWF5YmVvcCIsIm1heWJlb3BlcmF0b3JOb0NvbW1hIiwibWF5YmVvcGVyYXRvckNvbW1hIiwiY2xhc3NFeHByZXNzaW9uIiwiYXJyYXlMaXRlcmFsIiwiY29udENvbW1hc2VwIiwib2JqcHJvcCIsInF1YXNpIiwibWF5YmVUYXJnZXQiLCJleHByIiwicHJvcGVydHkiLCJjb250aW51ZVF1YXNpIiwidGFyZ2V0Tm9Db21tYSIsIm1heWJlVHlwZUFyZ3MiLCJfIiwiZ2V0dGVyU2V0dGVyIiwiYWZ0ZXJwcm9wIiwibWF5YmV0eXBlIiwid2hhdCIsInNlcCIsInByb2NlZWQiLCJtYXliZXR5cGVPckluIiwibWF5YmVyZXR0eXBlIiwiaXNLVyIsImFmdGVyVHlwZSIsInR5cGVwcm9wcyIsInR5cGVhcmciLCJtYXliZVJldHVyblR5cGUiLCJxdWFzaVR5cGUiLCJ0eXBlcHJvcCIsImZ1bmN0aW9uZGVjbCIsImNvbnRpbnVlUXVhc2lUeXBlIiwidHlwZXBhcmFtIiwibWF5YmVUeXBlRGVmYXVsdCIsIm1heWJlQXNzaWduIiwidmFyZGVmQ29udCIsImVsdHBhdHRlcm4iLCJwcm9wcGF0dGVybiIsIl90eXBlIiwiZm9yc3BlYzEiLCJmb3JzcGVjMiIsImNsYXNzTmFtZUFmdGVyIiwiY2xhc3NCb2R5IiwiY2xhc3NmaWVsZCIsIm1heWJlRnJvbSIsImV4cG9ydEZpZWxkIiwiaW1wb3J0U3BlYyIsIm1heWJlTW9yZUltcG9ydHMiLCJtYXliZUFzIiwiZW51bW1lbWJlciIsImlzQ29udGludWVkU3RhdGVtZW50IiwiYyIsImRvdWJsZUluZGVudFN3aXRjaCIsInNraXBFeHByZXNzaW9uIiwibWF0Y2hTZXF1ZW5jZSIsImVzY2FwZXMiLCJwaHBTdHJpbmciLCJwYXR0ZXJucyIsInBocFN0cmluZ18iLCJ0b2tTdGFjayIsInBocEtleXdvcmRzIiwicGhwQXRvbXMiLCJwaHBCdWlsdGluIiwicGhwQ29uZmlnIiwicXVvdGVkIiwicGhwTW9kZSIsImRpc3BhdGNoIiwiaXNQSFAiLCJjdXJNb2RlIiwicGVuZGluZyIsInBocCIsImN1clN0YXRlIiwib3BlblBIUCIsInN0YXJ0T3BlbiIsImh0bWxOZXciLCJwaHBOZXciLCJzaWduIiwiaW5jb21tZW50IiwiaW50YWciLCJpbnN0cmluZyIsInR3aWdJbm5lciIsImh0bWxDb25maWciLCJhdXRvU2VsZkNsb3NlcnMiLCJpbXBsaWNpdGx5Q2xvc2VkIiwiY29udGV4dEdyYWJiZXJzIiwiZG9Ob3RJbmRlbnQiLCJhbGxvd1VucXVvdGVkIiwiYWxsb3dNaXNzaW5nIiwiY2FzZUZvbGQiLCJ4bWxDb25maWciLCJlZGl0b3JDb25mIiwiY29uZmlnXyIsInNldFN0eWxlIiwiaW5UZXh0IiwiY2hhaW4iLCJwYXJzZXIiLCJpbkJsb2NrIiwiZG9jdHlwZSIsImJhc2VTdGF0ZSIsInRhZ1N0YXJ0IiwiaW5BdHRyaWJ1dGUiLCJzdHJpbmdTdGFydENvbCIsImNsb3N1cmUiLCJpc0luQXR0cmlidXRlIiwidGVybWluYXRvciIsImxvd2VyIiwibm9JbmRlbnQiLCJtYXliZVBvcENvbnRleHQiLCJuZXh0VGFnTmFtZSIsInBhcmVudFRhZ05hbWUiLCJ0YWdOYW1lU3RhdGUiLCJjbG9zZVRhZ05hbWVTdGF0ZSIsImF0dHJTdGF0ZSIsIm1hdGNoQ2xvc2luZyIsImNsb3NlU3RhdGUiLCJjbG9zZVN0YXRlRXJyIiwiYXR0ckVxU3RhdGUiLCJhdHRyVmFsdWVTdGF0ZSIsImF0dHJDb250aW51ZWRTdGF0ZSIsImlzSW5UZXh0IiwiYmFzZUluZGVudCIsImZ1bGxMaW5lIiwiYWxpZ25DREFUQSIsInRhZ0FmdGVyIiwiZ3JhYmJlcnMiLCJjb25maWd1cmF0aW9uIiwic2tpcEF0dHJpYnV0ZSIsInhtbEN1cnJlbnRUYWciLCJ4bWxDdXJyZW50Q29udGV4dCIsIl9fX0NTU19MT0FERVJfRVhQT1JUX19fIiwiY3NzV2l0aE1hcHBpbmdUb1N0cmluZyIsIml0ZW0iLCJtb2R1bGVzIiwibWVkaWFRdWVyeSIsImRlZHVwZSIsImFscmVhZHlJbXBvcnRlZE1vZHVsZXMiLCJfaSIsIl9zbGljZWRUb0FycmF5IiwiaXNBcnJheSIsIl9hcnJheVdpdGhIb2xlcyIsIlN5bWJvbCIsIml0ZXJhdG9yIiwiX3MiLCJfYXJyIiwiX24iLCJfZCIsImVyciIsIl9pdGVyYWJsZVRvQXJyYXlMaW1pdCIsIm1pbkxlbiIsIl9hcnJheUxpa2VUb0FycmF5IiwiX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5IiwiVHlwZUVycm9yIiwiX25vbkl0ZXJhYmxlUmVzdCIsImFycjIiLCJfaXRlbSIsImNzc01hcHBpbmciLCJidG9hIiwiYmFzZTY0IiwidW5lc2NhcGUiLCJlbmNvZGVVUklDb21wb25lbnQiLCJKU09OIiwic3RyaW5naWZ5Iiwic291cmNlTWFwcGluZyIsInNvdXJjZVVSTHMiLCJzb3VyY2VzIiwic291cmNlUm9vdCIsIm1lbW8iLCJpc09sZElFIiwiQm9vbGVhbiIsImFsbCIsImF0b2IiLCJnZXRUYXJnZXQiLCJzdHlsZVRhcmdldCIsIkhUTUxJRnJhbWVFbGVtZW50IiwiY29udGVudERvY3VtZW50Iiwic3R5bGVzSW5Eb20iLCJnZXRJbmRleEJ5SWRlbnRpZmllciIsIm1vZHVsZXNUb0RvbSIsImlkQ291bnRNYXAiLCJpZGVudGlmaWVycyIsIm1lZGlhIiwic291cmNlTWFwIiwicmVmZXJlbmNlcyIsInVwZGF0ZXIiLCJhZGRTdHlsZSIsImluc2VydFN0eWxlRWxlbWVudCIsIm5vbmNlIiwiZm9yRWFjaCIsInRleHRTdG9yZSIsInJlcGxhY2VUZXh0IiwicmVwbGFjZW1lbnQiLCJhcHBseVRvU2luZ2xldG9uVGFnIiwic3R5bGVTaGVldCIsImNzc05vZGUiLCJhcHBseVRvVGFnIiwic2luZ2xldG9uIiwic2luZ2xldG9uQ291bnRlciIsInN0eWxlSW5kZXgiLCJyZW1vdmVTdHlsZUVsZW1lbnQiLCJuZXdPYmoiLCJsYXN0SWRlbnRpZmllcnMiLCJuZXdMaXN0IiwibmV3TGFzdElkZW50aWZpZXJzIiwiX2luZGV4IiwiX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fIiwiX193ZWJwYWNrX3JlcXVpcmVfXyIsIm1vZHVsZUlkIiwiY2FjaGVkTW9kdWxlIiwiX193ZWJwYWNrX21vZHVsZXNfXyIsIk8iLCJjaHVua0lkcyIsImZuIiwibm90RnVsZmlsbGVkIiwiZnVsZmlsbGVkIiwiZXZlcnkiLCJnZXR0ZXIiLCJfX2VzTW9kdWxlIiwiZGVmaW5pdGlvbiIsImRlZmluZVByb3BlcnR5IiwiZW51bWVyYWJsZSIsImluc3RhbGxlZENodW5rcyIsImNodW5rSWQiLCJ3ZWJwYWNrSnNvbnBDYWxsYmFjayIsInBhcmVudENodW5rTG9hZGluZ0Z1bmN0aW9uIiwibW9yZU1vZHVsZXMiLCJydW50aW1lIiwic29tZSIsImNodW5rTG9hZGluZ0dsb2JhbCIsIm5jIiwiX193ZWJwYWNrX2V4cG9ydHNfXyJdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/themes/demo/assets/vendor/jquery.min.js b/themes/demo/assets/vendor/jquery.min.js new file mode 100644 index 0000000..c4c6022 --- /dev/null +++ b/themes/demo/assets/vendor/jquery.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.0 | (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(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=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))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(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&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(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&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(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 ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);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&&E){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=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(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(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===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]||se.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]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(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(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(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=se.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 j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.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 S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(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 je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.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)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.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),m(t)&&(t=t.call(e,n,S.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)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.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"===S.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"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(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)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(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?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.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.mouseenter(e).mouseleave(t||e)}}),S.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){S.fn[n]=function(e,t){return 0{this.initPlugin()}))}initPlugin(){this.pswp=this.lightbox.pswp,this.isCaptionHidden=!1,this.tempCaption=!1,this.captionElement=!1,this.pswp.on("uiRegister",(()=>{this.pswp.ui.registerElement({name:"dynamic-caption",order:9,isButton:!1,appendTo:"root",html:"",onInit:i=>{this.captionElement=i,this.initCaption()}})}))}initCaption(){const{pswp:i}=this;i.on("change",(()=>{this.updateCaptionHTML(),this.updateCurrentCaptionPosition(),this.showCaption()})),i.on("calcSlideSize",(i=>this.onCalcSlideSize(i))),i.on("moveMainScroll",(()=>{this.useMobileLayout()||(this.pswp.mainScroll.isShifted()?this.hideCaption():this.showCaption())})),i.on("zoomPanUpdate",(()=>{i.currSlide.currZoomLevel>i.currSlide.zoomLevels.initial?this.hideCaption():this.showCaption()})),i.on("beforeZoomTo",(t=>{const{currSlide:e}=i;e.__dcAdjustedPanAreaSize&&(t.destZoomLevel>e.zoomLevels.initial?(e.panAreaSize.x=e.__dcOriginalPanAreaSize.x,e.panAreaSize.y=e.__dcOriginalPanAreaSize.y):(e.panAreaSize.x=e.__dcAdjustedPanAreaSize.x,e.panAreaSize.y=e.__dcAdjustedPanAreaSize.y))}))}useMobileLayout(){const{mobileLayoutBreakpoint:i}=this.options;return"function"==typeof i?i.call(this):"number"==typeof i&&window.innerWidth{this.captionElement.style.visibility="hidden",this.captionFadeTimeout=null}),400))}showCaption(){this.isCaptionHidden&&(this.isCaptionHidden=!1,this.captionElement.style.visibility="visible",clearTimeout(this.captionFadeTimeout),this.captionFadeTimeout=setTimeout((()=>{this.captionElement.classList.remove("pswp__dynamic-caption--faded"),this.captionFadeTimeout=null}),50))}setCaptionPosition(i,t){const e=i<=this.options.horizontalEdgeThreshold;this.captionElement.classList[e?"add":"remove"]("pswp__dynamic-caption--on-hor-edge"),this.captionElement.style.left=i+"px",this.captionElement.style.top=t+"px"}setCaptionWidth(i,t){t?i.style.width=t+"px":i.style.removeProperty("width")}setCaptionType(i,t){const e=i.dataset.pswpCaptionType;t!==e&&(i.classList.add("pswp__dynamic-caption--"+t),i.classList.remove("pswp__dynamic-caption--"+e),i.dataset.pswpCaptionType=t)}updateCurrentCaptionPosition(){const i=this.pswp.currSlide;if(!i.dynamicCaptionType)return;if("mobile"===i.dynamicCaptionType)return this.setCaptionType(this.captionElement,i.dynamicCaptionType),this.captionElement.style.removeProperty("left"),this.captionElement.style.removeProperty("top"),void this.setCaptionWidth(this.captionElement,!1);const t=i.zoomLevels.initial,e=Math.ceil(i.width*t),n=Math.ceil(i.height*t);this.setCaptionType(this.captionElement,i.dynamicCaptionType),"aside"===i.dynamicCaptionType?(this.setCaptionPosition(this.pswp.currSlide.bounds.center.x+e,this.pswp.currSlide.bounds.center.y),this.setCaptionWidth(this.captionElement,!1)):"below"===i.dynamicCaptionType&&(this.setCaptionPosition(this.pswp.currSlide.bounds.center.x,this.pswp.currSlide.bounds.center.y+n),this.setCaptionWidth(this.captionElement,e))}createTemporaryCaption(){this.tempCaption=document.createElement("div"),this.tempCaption.className="pswp__dynamic-caption pswp__dynamic-caption--temp",this.tempCaption.style.visibility="hidden",this.tempCaption.setAttribute("aria-hidden","true"),this.pswp.bg.after(this.captionElement),this.captionElement.after(this.tempCaption)}onCalcSlideSize(i){const{slide:t}=i;let e,n=!1;if(!this.getCaptionHTML(i.slide))return void(t.dynamicCaptionType=!1);this.storeOriginalPanAreaSize(t),t.bounds.update(t.zoomLevels.initial),this.useMobileLayout()?(t.dynamicCaptionType="mobile",n=!0):"auto"===this.options.type?t.bounds.center.x>t.bounds.center.y?t.dynamicCaptionType="aside":t.dynamicCaptionType="below":t.dynamicCaptionType=this.options.type;const o=Math.ceil(t.width*t.zoomLevels.initial),a=Math.ceil(t.height*t.zoomLevels.initial);if(this.tempCaption||this.createTemporaryCaption(),this.setCaptionType(this.tempCaption,t.dynamicCaptionType),"aside"===t.dynamicCaptionType){this.tempCaption.innerHTML=this.getCaptionHTML(i.slide),this.setCaptionWidth(this.tempCaption,!1),e=this.measureCaptionSize(this.tempCaption,i.slide);const n=e.x,a=o+t.bounds.center.x;t.panAreaSize.x-a<=n&&(t.panAreaSize.x-=n,this.recalculateZoomLevelAndBounds(t))}else if("below"===t.dynamicCaptionType||n){this.setCaptionWidth(this.tempCaption,n?this.pswp.viewportSize.x:o),this.tempCaption.innerHTML=this.getCaptionHTML(i.slide),e=this.measureCaptionSize(this.tempCaption,i.slide);const s=e.y,p=a+t.bounds.center.y,d=t.panAreaSize.y-p,c=t.panAreaSize.y;if(d<=s){t.panAreaSize.y-=Math.min(2*(s-d),s),this.recalculateZoomLevelAndBounds(t);const i=t.panAreaSize.x*this.options.mobileCaptionOverlapRatio/2;n&&t.bounds.center.x>i&&(t.panAreaSize.y=c,this.recalculateZoomLevelAndBounds(t))}}this.storeAdjustedPanAreaSize(t),t===this.pswp.currSlide&&this.updateCurrentCaptionPosition()}measureCaptionSize(i,t){const e=i.getBoundingClientRect();return this.pswp.dispatch("dynamicCaptionMeasureSize",{captionEl:i,slide:t,captionSize:{x:e.width,y:e.height}}).captionSize}recalculateZoomLevelAndBounds(i){i.zoomLevels.update(i.width,i.height,i.panAreaSize),i.bounds.update(i.zoomLevels.initial)}storeAdjustedPanAreaSize(i){i.__dcAdjustedPanAreaSize||(i.__dcAdjustedPanAreaSize={}),i.__dcAdjustedPanAreaSize.x=i.panAreaSize.x,i.__dcAdjustedPanAreaSize.y=i.panAreaSize.y}storeOriginalPanAreaSize(i){i.__dcOriginalPanAreaSize||(i.__dcOriginalPanAreaSize={}),i.__dcOriginalPanAreaSize.x=i.panAreaSize.x,i.__dcOriginalPanAreaSize.y=i.panAreaSize.y}getCaptionHTML(i){if("function"==typeof this.options.captionContent)return this.options.captionContent.call(this,i);const t=i.data.element;let e="";if(t){const i=t.querySelector(this.options.captionContent);if(i)e=i.innerHTML;else{const i=t.querySelector("img");i&&(e=i.getAttribute("alt"))}}return e}updateCaptionHTML(){const i=this.getCaptionHTML(pswp.currSlide);this.captionElement.style.visibility=i?"visible":"hidden",this.captionElement.innerHTML=i||"",this.pswp.dispatch("dynamicCaptionUpdateHTML",{captionElement:this.captionElement})}}export default PhotoSwipeDynamicCaption; diff --git a/themes/demo/assets/vendor/photoswipe/LICENSE.txt b/themes/demo/assets/vendor/photoswipe/LICENSE.txt new file mode 100644 index 0000000..5e0ff4d --- /dev/null +++ b/themes/demo/assets/vendor/photoswipe/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2022 Dmitry Semenov, https://dimsemenov.com + +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. \ No newline at end of file diff --git a/themes/demo/assets/vendor/photoswipe/photoswipe-lightbox.esm.min.js b/themes/demo/assets/vendor/photoswipe/photoswipe-lightbox.esm.min.js new file mode 100644 index 0000000..ce97948 --- /dev/null +++ b/themes/demo/assets/vendor/photoswipe/photoswipe-lightbox.esm.min.js @@ -0,0 +1 @@ +function t(t,e,i){const s=document.createElement(e||"div");return t&&(s.className=t),i&&i.appendChild(s),s}function i(t,e,i){t.style.width="number"==typeof e?e+"px":e,t.style.height="number"==typeof i?i+"px":i}const s="idle",h="loading",e="loaded",n="error";function o(t,e,i=document){let s=[];if(t instanceof Element)s=[t];else if(t instanceof NodeList||Array.isArray(t))s=Array.from(t);else{const n="string"==typeof t?t:e;n&&(s=Array.from(i.querySelectorAll(n)))}return s}class r{constructor(t,e){this.type=t,e&&Object.assign(this,e)}preventDefault(){this.defaultPrevented=!0}}class a{constructor(e,i){this.element=t("pswp__img pswp__img--placeholder",e?"img":"",i),e&&(this.element.decoding="async",this.element.alt="",this.element.src=e,this.element.setAttribute("role","presentation")),this.element.setAttribute("aria-hiden","true")}setDisplayedSize(t,e){this.element&&("IMG"===this.element.tagName?(i(this.element,250,"auto"),this.element.style.transformOrigin="0 0",this.element.style.transform=function(t,e,i){let s="translate3d(0px,0px,0)";return void 0!==i&&(s+=" scale3d("+i+","+i+",1)"),s}(0,0,t/250)):i(this.element,t,e))}destroy(){this.element.parentNode&&this.element.remove(),this.element=null}}class c{constructor(t,e,i){this.instance=e,this.data=t,this.index=i,this.width=Number(this.data.w)||Number(this.data.width)||0,this.height=Number(this.data.h)||Number(this.data.height)||0,this.isAttached=!1,this.hasSlide=!1,this.state=s,this.data.type?this.type=this.data.type:this.data.src?this.type="image":this.type="html",this.instance.dispatch("contentInit",{content:this})}removePlaceholder(){this.placeholder&&!this.keepPlaceholder()&&setTimeout((()=>{this.placeholder&&(this.placeholder.destroy(),this.placeholder=null)}),500)}load(e,i){if(!this.placeholder&&this.slide&&this.usePlaceholder()){const t=this.instance.applyFilters("placeholderSrc",!(!this.data.msrc||!this.slide.isFirstSlide)&&this.data.msrc,this);this.placeholder=new a(t,this.slide.container)}this.element&&!i||this.instance.dispatch("contentLoad",{content:this,isLazy:e}).defaultPrevented||(this.isImageContent()?this.loadImage(e):(this.element=t("pswp__content"),this.element.innerHTML=this.data.html||""),i&&this.slide&&this.slide.updateContentSize(!0))}loadImage(e){this.element=t("pswp__img","img"),this.instance.dispatch("contentLoadImage",{content:this,isLazy:e}).defaultPrevented||(this.data.srcset&&(this.element.srcset=this.data.srcset),this.element.src=this.data.src,this.element.alt=this.data.alt||"",this.state=h,this.element.complete?this.onLoaded():(this.element.onload=()=>{this.onLoaded()},this.element.onerror=()=>{this.onError()}))}setSlide(t){this.slide=t,this.hasSlide=!0,this.instance=t.pswp}onLoaded(){this.state=e,this.slide&&(this.instance.dispatch("loadComplete",{slide:this.slide,content:this}),this.slide.isActive&&this.slide.heavyAppended&&!this.element.parentNode&&(this.slide.container.innerHTML="",this.append(),this.slide.updateContentSize(!0)))}onError(){this.state=n,this.slide&&(this.displayError(),this.instance.dispatch("loadComplete",{slide:this.slide,isError:!0,content:this}),this.instance.dispatch("loadError",{slide:this.slide,content:this}))}isLoading(){return this.instance.applyFilters("isContentLoading",this.state===h,this)}isError(){return this.state===n}isImageContent(){return"image"===this.type}setDisplayedSize(t,e){if(this.element&&(this.placeholder&&this.placeholder.setDisplayedSize(t,e),!this.instance.dispatch("contentResize",{content:this,width:t,height:e}).defaultPrevented&&(i(this.element,t,e),this.isImageContent()&&!this.isError()))){const i=this.element;i.srcset&&(!i.dataset.largestUsedSize||t>i.dataset.largestUsedSize)&&(i.sizes=t+"px",i.dataset.largestUsedSize=t),this.slide&&this.instance.dispatch("imageSizeChange",{slide:this.slide,width:t,height:e,content:this})}}isZoomable(){return this.instance.applyFilters("isContentZoomable",this.isImageContent()&&this.state!==n,this)}usePlaceholder(){return this.instance.applyFilters("useContentPlaceholder",this.isImageContent(),this)}lazyLoad(){this.instance.dispatch("contentLazyLoad",{content:this}).defaultPrevented||this.load(!0)}keepPlaceholder(){return this.instance.applyFilters("isKeepingPlaceholder",this.isLoading(),this)}destroy(){this.hasSlide=!1,this.slide=null,this.instance.dispatch("contentDestroy",{content:this}).defaultPrevented||(this.remove(),this.isImageContent()&&this.element&&(this.element.onload=null,this.element.onerror=null,this.element=null))}displayError(){if(this.slide){let e=t("pswp__error-msg");e.innerText=this.instance.options.errorMsg,e=this.instance.applyFilters("contentErrorElement",e,this),this.element=t("pswp__content pswp__error-msg-container"),this.element.appendChild(e),this.slide.container.innerHTML="",this.slide.container.appendChild(this.element),this.slide.updateContentSize(!0),this.removePlaceholder()}}append(){this.isAttached=!0,this.state!==n?this.instance.dispatch("contentAppend",{content:this}).defaultPrevented||(this.isImageContent()?this.slide&&!this.slide.isActive&&"decode"in this.element?(this.isDecoding=!0,requestAnimationFrame((()=>{this.element&&"IMG"===this.element.tagName&&this.element.decode().then((()=>{this.isDecoding=!1,requestAnimationFrame((()=>{this.appendImage()}))})).catch((()=>{this.isDecoding=!1}))}))):(!this.placeholder||this.state!==e&&this.state!==n||this.removePlaceholder(),this.appendImage()):this.element&&!this.element.parentNode&&this.slide.container.appendChild(this.element)):this.displayError()}activate(){this.instance.dispatch("contentActivate",{content:this}).defaultPrevented||this.slide&&(this.isImageContent()&&this.isDecoding?this.appendImage():this.isError()&&this.load(!1,!0))}deactivate(){this.instance.dispatch("contentDeactivate",{content:this})}remove(){this.isAttached=!1,this.instance.dispatch("contentRemove",{content:this}).defaultPrevented||this.element&&this.element.parentNode&&this.element.remove()}appendImage(){this.isAttached&&(this.instance.dispatch("contentAppendImage",{content:this}).defaultPrevented||this.slide&&this.element&&!this.element.parentNode&&(this.slide.container.appendChild(this.element),!this.placeholder||this.state!==e&&this.state!==n||this.removePlaceholder()))}}function l(t,e,i,s,n){let h;if(e.paddingFn)h=e.paddingFn(i,s,n)[t];else if(e.padding)h=e.padding[t];else{const i="padding"+t[0].toUpperCase()+t.slice(1);e[i]&&(h=e[i])}return h||0}class u{constructor(t,e,i,s){this.pswp=s,this.options=t,this.itemData=e,this.index=i}update(t,e,i){this.elementSize={x:t,y:e},this.panAreaSize=i;const s=this.panAreaSize.x/this.elementSize.x,n=this.panAreaSize.y/this.elementSize.y;this.fit=Math.min(1,sn?s:n),this.vFill=Math.min(1,n),this.initial=this.t(),this.secondary=this.i(),this.max=Math.max(this.initial,this.secondary,this.o()),this.min=Math.min(this.fit,this.initial,this.secondary),this.pswp&&this.pswp.dispatch("zoomLevelsUpdate",{zoomLevels:this,slideData:this.itemData})}l(t){const e=this.options[t+"ZoomLevel"];if(e)return"function"==typeof e?e(this):"fill"===e?this.fill:"fit"===e?this.fit:Number(e)}i(){let t=this.l("secondary");return t||(t=Math.min(1,3*this.fit),t*this.elementSize.x>4e3&&(t=4e3/this.elementSize.x),t)}t(){return this.l("initial")||this.fit}o(){return this.l("max")||Math.max(1,4*this.fit)}}function d(t,e,i){const s=e.createContentFromData(t,i);if(!s||!s.lazyLoad)return;const{options:n}=e,h=e.viewportSize||function(t,e){if(t.getViewportSizeFn){const e=t.getViewportSizeFn(t,void 0);if(e)return e}return{x:document.documentElement.clientWidth,y:window.innerHeight}}(n),a=function(t,e,i,s){return{x:e.x-l("left",t,e,i,s)-l("right",t,e,i,s),y:e.y-l("top",t,e,i,s)-l("bottom",t,e,i,s)}}(n,h,t,i),o=new u(n,t,-1);return o.update(s.width,s.height,a),s.lazyLoad(),s.setDisplayedSize(Math.ceil(s.width*o.initial),Math.ceil(s.height*o.initial)),s}export default class extends class extends class{constructor(){this.u={},this.m={}}addFilter(t,e,i=100){this.m[t]||(this.m[t]=[]),this.m[t].push({fn:e,priority:i}),this.m[t].sort(((t,e)=>t.priority-e.priority)),this.pswp&&this.pswp.addFilter(t,e,i)}removeFilter(t,e){this.m[t]&&(this.m[t]=this.m[t].filter((t=>t.fn!==e))),this.pswp&&this.pswp.removeFilter(t,e)}applyFilters(t,...e){return this.m[t]&&this.m[t].forEach((t=>{e[0]=t.fn.apply(this,e)})),e[0]}on(t,e){this.u[t]||(this.u[t]=[]),this.u[t].push(e),this.pswp&&this.pswp.on(t,e)}off(t,e){this.u[t]&&(this.u[t]=this.u[t].filter((t=>e!==t))),this.pswp&&this.pswp.off(t,e)}dispatch(t,e){if(this.pswp)return this.pswp.dispatch(t,e);const i=new r(t,e);return this.u?(this.u[t]&&this.u[t].forEach((t=>{t.call(this,i)})),i):i}}{getNumItems(){let t;const{dataSource:e}=this.options;e?e.length?t=e.length:e.gallery&&(e.items||(e.items=this.p(e.gallery)),e.items&&(t=e.items.length)):t=0;const i=this.dispatch("numItems",{dataSource:e,numItems:t});return this.applyFilters("numItems",i.numItems,e)}createContentFromData(t,e){return new c(t,this,e)}getItemData(t){const{dataSource:e}=this.options;let i;Array.isArray(e)?i=e[t]:e&&e.gallery&&(e.items||(e.items=this.p(e.gallery)),i=e.items[t]);let s=i;s instanceof Element&&(s=this.g(s));const n=this.dispatch("itemData",{itemData:s||{},index:t});return this.applyFilters("itemData",n.itemData,t)}p(t){return this.options.children||this.options.childSelector?o(this.options.children,this.options.childSelector,t)||[]:[t]}g(t){const e={element:t},i="A"===t.tagName?t:t.querySelector("a");if(i){e.src=i.dataset.pswpSrc||i.href,i.dataset.pswpSrcset&&(e.srcset=i.dataset.pswpSrcset),e.width=parseInt(i.dataset.pswpWidth,10),e.height=parseInt(i.dataset.pswpHeight,10),e.w=e.width,e.h=e.height,i.dataset.pswpType&&(e.type=i.dataset.pswpType);const s=t.querySelector("img");s&&(e.msrc=s.currentSrc||s.src,e.alt=s.getAttribute("alt")),(i.dataset.pswpCropped||i.dataset.cropped)&&(e.thumbCropped=!0)}return this.applyFilters("domItemData",e,t,i),e}}{constructor(t){super(),this.options=t||{},this._=0}init(){this.onThumbnailsClick=this.onThumbnailsClick.bind(this),o(this.options.gallery,this.options.gallerySelector).forEach((t=>{t.addEventListener("click",this.onThumbnailsClick,!1)}))}onThumbnailsClick(t){if(function(t){if(2===t.which||t.ctrlKey||t.metaKey||t.altKey||t.shiftKey)return!0}(t)||window.pswp||!1===window.navigator.onLine)return;let e={x:t.clientX,y:t.clientY};e.x||e.y||(e=null);let i=this.getClickedIndex(t);i=this.applyFilters("clickedIndex",i,t,this);const s={gallery:t.currentTarget};i>=0&&(t.preventDefault(),this.loadAndOpen(i,s,e))}getClickedIndex(t){if(this.options.getClickedIndexFn)return this.options.getClickedIndexFn.call(this,t);const e=t.target,i=o(this.options.children,this.options.childSelector,t.currentTarget).findIndex((t=>t===e||t.contains(e)));return-1!==i?i:this.options.children||this.options.childSelector?-1:0}loadAndOpen(t,e,i){return!window.pswp&&(this.options.index=t,this.options.initialPointerPos=i,this.shouldOpen=!0,this.preload(t,e),!0)}preload(t,e){const{options:i}=this;e&&(i.dataSource=e);const s=[],n=typeof i.pswpModule;if("function"==typeof(h=i.pswpModule)&&h.prototype&&h.prototype.goTo)s.push(i.pswpModule);else{if("string"===n)throw new Error("pswpModule as string is no longer supported");if("function"!==n)throw new Error("pswpModule is not valid");s.push(i.pswpModule())}var h;"function"==typeof i.openPromise&&s.push(i.openPromise()),!1!==i.preloadFirstSlide&&t>=0&&(this.I=function(t,e){const i=e.getItemData(t);if(!e.dispatch("lazyLoadSlide",{index:t,itemData:i}).defaultPrevented)return d(i,e,t)}(t,this));const a=++this._;Promise.all(s).then((t=>{if(this.shouldOpen){const e=t[0];this.v(e,a)}}))}v(t,e){if(e!==this._&&this.shouldOpen)return;if(this.shouldOpen=!1,window.pswp)return;const i="object"==typeof t?new t.default(this.options):new t(this.options);this.pswp=i,window.pswp=i,Object.keys(this.u).forEach((t=>{this.u[t].forEach((e=>{i.on(t,e)}))})),Object.keys(this.m).forEach((t=>{this.m[t].forEach((e=>{i.addFilter(t,e.fn,e.priority)}))})),this.I&&(i.contentLoader.addToCache(this.I),this.I=null),i.on("destroy",(()=>{this.pswp=null,window.pswp=null})),i.init()}destroy(){this.pswp&&this.pswp.destroy(),this.shouldOpen=!1,this.u=null,o(this.options.gallery,this.options.gallerySelector).forEach((t=>{t.removeEventListener("click",this.onThumbnailsClick,!1)}))}} diff --git a/themes/demo/assets/vendor/photoswipe/photoswipe.css b/themes/demo/assets/vendor/photoswipe/photoswipe.css new file mode 100644 index 0000000..57156bc --- /dev/null +++ b/themes/demo/assets/vendor/photoswipe/photoswipe.css @@ -0,0 +1 @@ +/*! PhotoSwipe main CSS by Dmytro Semenov | photoswipe.com */.pswp{--pswp-bg:#000;--pswp-placeholder-bg:#222;--pswp-root-z-index:100000;--pswp-preloader-color:rgba(79, 79, 79, 0.4);--pswp-preloader-color-secondary:rgba(255, 255, 255, 0.9);--pswp-icon-color:#fff;--pswp-icon-color-secondary:#4f4f4f;--pswp-icon-stroke-color:#4f4f4f;--pswp-icon-stroke-width:2px;--pswp-error-text-color:var(--pswp-icon-color)}.pswp{position:fixed;z-index:var(--pswp-root-z-index);display:none;touch-action:none;outline:0;opacity:.003;contain:layout style size;-webkit-tap-highlight-color:transparent}.pswp:focus{outline:0}.pswp *{box-sizing:border-box}.pswp img{max-width:none}.pswp--open{display:block}.pswp,.pswp__bg{transform:translateZ(0);will-change:opacity}.pswp__bg{opacity:.005;background:var(--pswp-bg)}.pswp,.pswp__scroll-wrap{overflow:hidden}.pswp,.pswp__bg,.pswp__container,.pswp__content,.pswp__img,.pswp__item,.pswp__scroll-wrap,.pswp__zoom-wrap{position:absolute;top:0;left:0;width:100%;height:100%}.pswp{position:fixed}.pswp__img,.pswp__zoom-wrap{width:auto;height:auto}.pswp--click-to-zoom.pswp--zoom-allowed .pswp__img{cursor:-webkit-zoom-in;cursor:-moz-zoom-in;cursor:zoom-in}.pswp--click-to-zoom.pswp--zoomed-in .pswp__img{cursor:move;cursor:-webkit-grab;cursor:-moz-grab;cursor:grab}.pswp--click-to-zoom.pswp--zoomed-in .pswp__img:active{cursor:-webkit-grabbing;cursor:-moz-grabbing;cursor:grabbing}.pswp--no-mouse-drag.pswp--zoomed-in .pswp__img,.pswp--no-mouse-drag.pswp--zoomed-in .pswp__img:active,.pswp__img{cursor:-webkit-zoom-out;cursor:-moz-zoom-out;cursor:zoom-out}.pswp__button,.pswp__container,.pswp__counter,.pswp__img{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.pswp__item{z-index:1;overflow:hidden}.pswp__hidden{display:none!important}.pswp__content{pointer-events:none}.pswp__content>*{pointer-events:auto}.pswp__error-msg-container{display:grid}.pswp__error-msg{margin:auto;font-size:1em;line-height:1;color:var(--pswp-error-text-color)}.pswp .pswp__hide-on-close{opacity:.005;will-change:opacity;transition:opacity var(--pswp-transition-duration) cubic-bezier(.4, 0, .22, 1);z-index:10;pointer-events:none}.pswp--ui-visible .pswp__hide-on-close{opacity:1;pointer-events:auto}.pswp__button{position:relative;display:block;width:50px;height:60px;padding:0;margin:0;overflow:hidden;cursor:pointer;background:0 0;border:0;box-shadow:none;opacity:.85;-webkit-appearance:none;-webkit-touch-callout:none}.pswp__button:active,.pswp__button:focus,.pswp__button:hover{transition:none;padding:0;background:0 0;border:0;box-shadow:none;opacity:1}.pswp__button:disabled{opacity:.3;cursor:auto}.pswp__icn{fill:var(--pswp-icon-color);color:var(--pswp-icon-color-secondary)}.pswp__icn{position:absolute;top:14px;left:9px;width:32px;height:32px;overflow:hidden;pointer-events:none}.pswp__icn-shadow{stroke:var(--pswp-icon-stroke-color);stroke-width:var(--pswp-icon-stroke-width);fill:none}.pswp__icn:focus{outline:0}.pswp__img--with-bg,div.pswp__img--placeholder{background:var(--pswp-placeholder-bg)}.pswp__top-bar{position:absolute;left:0;top:0;width:100%;height:60px;display:flex;flex-direction:row;justify-content:flex-end;z-index:10;pointer-events:none!important}.pswp__top-bar>*{pointer-events:auto;will-change:opacity}.pswp__button--close{margin-right:6px}.pswp__button--arrow{position:absolute;top:0;width:75px;height:100px;top:50%;margin-top:-50px}.pswp__button--arrow:disabled{display:none;cursor:default}.pswp__button--arrow .pswp__icn{top:50%;margin-top:-30px;width:60px;height:60px;background:0 0;border-radius:0}.pswp--one-slide .pswp__button--arrow{display:none}.pswp--touch .pswp__button--arrow{visibility:hidden}.pswp--has_mouse .pswp__button--arrow{visibility:visible}.pswp__button--arrow--prev{right:auto;left:0}.pswp__button--arrow--next{right:0}.pswp__button--arrow--next .pswp__icn{left:auto;right:14px;transform:scale(-1,1)}.pswp__button--zoom{display:none}.pswp--zoom-allowed .pswp__button--zoom{display:block}.pswp--zoomed-in .pswp__zoom-icn-bar-v{display:none}.pswp__preloader{position:relative;overflow:hidden;width:50px;height:60px;margin-right:auto}.pswp__preloader .pswp__icn{opacity:0;transition:opacity .2s linear;animation:pswp-clockwise .6s linear infinite}.pswp__preloader--active .pswp__icn{opacity:.85}@keyframes pswp-clockwise{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.pswp__counter{height:30px;margin:15px 0 0 20px;font-size:14px;line-height:30px;color:var(--pswp-icon-color);text-shadow:1px 1px 3px var(--pswp-icon-color-secondary);opacity:.85}.pswp--one-slide .pswp__counter{display:none} diff --git a/themes/demo/assets/vendor/photoswipe/photoswipe.esm.min.js b/themes/demo/assets/vendor/photoswipe/photoswipe.esm.min.js new file mode 100644 index 0000000..4292320 --- /dev/null +++ b/themes/demo/assets/vendor/photoswipe/photoswipe.esm.min.js @@ -0,0 +1 @@ +function t(t,i,s){const e=document.createElement(i||"div");return t&&(e.className=t),s&&s.appendChild(e),e}function i(t,i){return t.x=i.x,t.y=i.y,void 0!==i.id&&(t.id=i.id),t}function s(t){t.x=Math.round(t.x),t.y=Math.round(t.y)}function h(t,i){const s=Math.abs(t.x-i.x),e=Math.abs(t.y-i.y);return Math.sqrt(s*s+e*e)}function e(t,i){return t.x===i.x&&t.y===i.y}function n(t,i,s){return Math.min(Math.max(t,i),s)}function o(t,i,s){let e="translate3d("+t+"px,"+(i||0)+"px,0)";return void 0!==s&&(e+=" scale3d("+s+","+s+",1)"),e}function r(t,i,s,e){t.style.transform=o(i,s,e)}function a(t,i,s,e){t.style.transition=i?i+" "+s+"ms "+(e||"cubic-bezier(.4,0,.22,1)"):"none"}function c(t,i,s){t.style.width="number"==typeof i?i+"px":i,t.style.height="number"==typeof s?s+"px":s}const l="idle",p="loading",u="loaded",d="error";let m=!1;try{window.addEventListener("test",null,Object.defineProperty({},"passive",{get:()=>{m=!0}}))}catch(t){}class f{constructor(){this.t=[]}add(t,i,s,e){this.i(t,i,s,e)}remove(t,i,s,e){this.i(t,i,s,e,!0)}removeAll(){this.t.forEach((t=>{this.i(t.target,t.type,t.listener,t.passive,!0,!0)})),this.t=[]}i(t,i,s,e,n,o){if(!t)return;const h=(n?"remove":"add")+"EventListener";(i=i.split(" ")).forEach((i=>{if(i){o||(n?this.t=this.t.filter((e=>e.type!==i||e.listener!==s||e.target!==t)):this.t.push({target:t,type:i,listener:s,passive:e}));const a=!!m&&{passive:e||!1};t[h](i,s,a)}}))}}function w(t,i){if(t.getViewportSizeFn){const s=t.getViewportSizeFn(t,i);if(s)return s}return{x:document.documentElement.clientWidth,y:window.innerHeight}}function g(t,i,s,e,n){let o;if(i.paddingFn)o=i.paddingFn(s,e,n)[t];else if(i.padding)o=i.padding[t];else{const s="padding"+t[0].toUpperCase()+t.slice(1);i[s]&&(o=i[s])}return o||0}function _(t,i,s,e){return{x:i.x-g("left",t,i,s,e)-g("right",t,i,s,e),y:i.y-g("top",t,i,s,e)-g("bottom",t,i,s,e)}}class v{constructor(t){this.slide=t,this.currZoomLevel=1,this.center={},this.max={},this.min={},this.reset()}update(t){this.currZoomLevel=t,this.slide.width?(this.o("x"),this.o("y"),this.slide.pswp.dispatch("calcBounds",{slide:this.slide})):this.reset()}o(t){const{pswp:i}=this.slide,s=this.slide["x"===t?"width":"height"]*this.currZoomLevel,e=g("x"===t?"left":"top",i.options,i.viewportSize,this.slide.data,this.slide.index),n=this.slide.panAreaSize[t];this.center[t]=Math.round((n-s)/2)+e,this.max[t]=s>n?Math.round(n-s)+e:this.center[t],this.min[t]=s>n?e:this.center[t]}reset(){this.center.x=0,this.center.y=0,this.max.x=0,this.max.y=0,this.min.x=0,this.min.y=0}correctPan(t,i){return n(i,this.max[t],this.min[t])}}class y{constructor(t,i,s,e){this.pswp=e,this.options=t,this.itemData=i,this.index=s}update(t,i,s){this.elementSize={x:t,y:i},this.panAreaSize=s;const e=this.panAreaSize.x/this.elementSize.x,n=this.panAreaSize.y/this.elementSize.y;this.fit=Math.min(1,en?e:n),this.vFill=Math.min(1,n),this.initial=this.l(),this.secondary=this.p(),this.max=Math.max(this.initial,this.secondary,this.u()),this.min=Math.min(this.fit,this.initial,this.secondary),this.pswp&&this.pswp.dispatch("zoomLevelsUpdate",{zoomLevels:this,slideData:this.itemData})}m(t){const i=this.options[t+"ZoomLevel"];if(i)return"function"==typeof i?i(this):"fill"===i?this.fill:"fit"===i?this.fit:Number(i)}p(){let t=this.m("secondary");return t||(t=Math.min(1,3*this.fit),t*this.elementSize.x>4e3&&(t=4e3/this.elementSize.x),t)}l(){return this.m("initial")||this.fit}u(){return this.m("max")||Math.max(1,4*this.fit)}}class b{constructor(i,s,e){this.data=i,this.index=s,this.pswp=e,this.isActive=s===e.currIndex,this.currentResolution=0,this.panAreaSize={},this.isFirstSlide=this.isActive&&!e.opener.isOpen,this.zoomLevels=new y(e.options,i,s,e),this.pswp.dispatch("gettingData",{slide:this,data:this.data,index:s}),this.pan={x:0,y:0},this.content=this.pswp.contentLoader.getContentBySlide(this),this.container=t("pswp__zoom-wrap"),this.currZoomLevel=1,this.width=this.content.width,this.height=this.content.height,this.bounds=new v(this),this.prevDisplayedWidth=-1,this.prevDisplayedHeight=-1,this.pswp.dispatch("slideInit",{slide:this})}setIsActive(t){t&&!this.isActive?this.activate():!t&&this.isActive&&this.deactivate()}append(t){this.holderElement=t,this.data?(this.calculateSize(),this.container.transformOrigin="0 0",this.load(),this.appendHeavy(),this.updateContentSize(),this.holderElement.innerHTML="",this.holderElement.appendChild(this.container),this.zoomAndPanToInitial(),this.pswp.dispatch("firstZoomPan",{slide:this}),this.applyCurrentZoomPan(),this.pswp.dispatch("afterSetContent",{slide:this}),this.isActive&&this.activate()):this.holderElement.innerHTML=""}load(){this.content.load(),this.pswp.dispatch("slideLoad",{slide:this})}appendHeavy(){const{pswp:t}=this;!this.heavyAppended&&t.opener.isOpen&&!t.mainScroll.isShifted()&&(this.isActive,1)&&(this.pswp.dispatch("appendHeavy",{slide:this}).defaultPrevented||(this.heavyAppended=!0,this.content.append(),this.pswp.dispatch("appendHeavyContent",{slide:this})))}activate(){this.isActive=!0,this.appendHeavy(),this.content.activate(),this.pswp.dispatch("slideActivate",{slide:this})}deactivate(){this.isActive=!1,this.content.deactivate(),this.currentResolution=0,this.zoomAndPanToInitial(),this.applyCurrentZoomPan(),this.updateContentSize(),this.pswp.dispatch("slideDeactivate",{slide:this})}destroy(){this.content.hasSlide=!1,this.content.remove(),this.pswp.dispatch("slideDestroy",{slide:this})}resize(){this.currZoomLevel!==this.zoomLevels.initial&&this.isActive?(this.calculateSize(),this.bounds.update(this.currZoomLevel),this.panTo(this.pan.x,this.pan.y)):(this.calculateSize(),this.currentResolution=0,this.zoomAndPanToInitial(),this.applyCurrentZoomPan(),this.updateContentSize())}updateContentSize(t){const i=this.currentResolution||this.zoomLevels.initial;if(!i)return;const s=Math.round(this.width*i)||this.pswp.viewportSize.x,e=Math.round(this.height*i)||this.pswp.viewportSize.y;(this.sizeChanged(s,e)||t)&&this.content.setDisplayedSize(s,e)}sizeChanged(t,i){return(t!==this.prevDisplayedWidth||i!==this.prevDisplayedHeight)&&(this.prevDisplayedWidth=t,this.prevDisplayedHeight=i,!0)}getPlaceholderElement(){if(this.content.placeholder)return this.content.placeholder.element}zoomTo(t,i,e,o){const{pswp:h}=this;if(!this.isZoomable()||h.mainScroll.isShifted())return;h.dispatch("beforeZoomTo",{destZoomLevel:t,centerPoint:i,transitionDuration:e}),h.animations.stopAllPan();const a=this.currZoomLevel;o||(t=n(t,this.zoomLevels.min,this.zoomLevels.max)),this.setZoomLevel(t),this.pan.x=this.calculateZoomToPanOffset("x",i,a),this.pan.y=this.calculateZoomToPanOffset("y",i,a),s(this.pan);const r=()=>{this.g(t),this.applyCurrentZoomPan()};e?h.animations.startTransition({isPan:!0,name:"zoomTo",target:this.container,transform:this.getCurrentTransform(),onComplete:r,duration:e,easing:h.options.easing}):r()}toggleZoom(t){this.zoomTo(this.currZoomLevel===this.zoomLevels.initial?this.zoomLevels.secondary:this.zoomLevels.initial,t,this.pswp.options.zoomAnimationDuration)}setZoomLevel(t){this.currZoomLevel=t,this.bounds.update(this.currZoomLevel)}calculateZoomToPanOffset(t,i,s){if(0==this.bounds.max[t]-this.bounds.min[t])return this.bounds.center[t];i||(i=this.pswp.getViewportCenterPoint());const e=this.currZoomLevel/s;return this.bounds.correctPan(t,(this.pan[t]-i[t])*e+i[t])}panTo(t,i){this.pan.x=this.bounds.correctPan("x",t),this.pan.y=this.bounds.correctPan("y",i),this.applyCurrentZoomPan()}isPannable(){return this.width&&this.currZoomLevel>this.zoomLevels.fit}isZoomable(){return this.width&&this.content.isZoomable()}applyCurrentZoomPan(){this._(this.pan.x,this.pan.y,this.currZoomLevel),this===this.pswp.currSlide&&this.pswp.dispatch("zoomPanUpdate",{slide:this})}zoomAndPanToInitial(){this.currZoomLevel=this.zoomLevels.initial,this.bounds.update(this.currZoomLevel),i(this.pan,this.bounds.center),this.pswp.dispatch("initialZoomPan",{slide:this})}_(t,i,s){s/=this.currentResolution||this.zoomLevels.initial,r(this.container,t,i,s)}calculateSize(){const{pswp:t}=this;i(this.panAreaSize,_(t.options,t.viewportSize,this.data,this.index)),this.zoomLevels.update(this.width,this.height,this.panAreaSize),t.dispatch("calcSlideSize",{slide:this})}getCurrentTransform(){const t=this.currZoomLevel/(this.currentResolution||this.zoomLevels.initial);return o(this.pan.x,this.pan.y,t)}g(t){t!==this.currentResolution&&(this.currentResolution=t,this.updateContentSize(),this.pswp.dispatch("resolutionChanged"))}}class x{constructor(t){this.gestures=t,this.pswp=t.pswp,this.startPan={}}start(){i(this.startPan,this.pswp.currSlide.pan),this.pswp.animations.stopAll()}change(){const{p1:t,prevP1:i,dragAxis:e,pswp:n}=this.gestures,{currSlide:o}=n;if("y"===e&&n.options.closeOnVerticalDrag&&o.currZoomLevel<=o.zoomLevels.fit&&!this.gestures.isMultitouch){const s=o.pan.y+(t.y-i.y);if(!n.dispatch("verticalDrag",{panY:s}).defaultPrevented){this.v("y",s,.6);const t=1-Math.abs(this.M(o.pan.y));n.applyBgOpacity(t),o.applyCurrentZoomPan()}}else this.S("x")||(this.S("y"),s(o.pan),o.applyCurrentZoomPan())}end(){const{pswp:t,velocity:i}=this.gestures,{mainScroll:s}=t;let e=0;if(t.animations.stopAll(),s.isShifted()){const n=(s.x-s.getCurrSlideX())/t.viewportSize.x;i.x<-.5&&n<0||i.x<.1&&n<-.5?(e=1,i.x=Math.min(i.x,0)):(i.x>.5&&n>0||i.x>-.1&&n>.5)&&(e=-1,i.x=Math.max(i.x,0)),s.moveIndexBy(e,!0,i.x)}t.currSlide.currZoomLevel>t.currSlide.zoomLevels.max||this.gestures.isMultitouch?this.gestures.zoomLevels.correctZoomPan(!0):(this.P("x"),this.P("y"))}P(t){const{pswp:i}=this,{currSlide:s}=i,{velocity:e}=this.gestures,{pan:o,bounds:h}=s,a=o[t],r=i.bgOpacity<1&&"y"===t,l=a+function(t,i){return.995*t/(1-.995)}(e[t]);if(r){const t=this.M(a),s=this.M(l);if(t<0&&s<-.4||t>0&&s>.4)return void i.close()}const p=h.correctPan(t,l);if(a===p)return;const d=p===l?1:.82,c=i.bgOpacity,m=p-a;i.animations.startSpring({name:"panGesture"+t,isPan:!0,start:a,end:p,velocity:e[t],dampingRatio:d,onUpdate:e=>{if(r&&i.bgOpacity<1){const t=1-(p-e)/m;i.applyBgOpacity(n(c+(1-c)*t,0,1))}o[t]=Math.floor(e),s.applyCurrentZoomPan()}})}S(t){const{p1:i,pswp:s,dragAxis:e,prevP1:n,isMultitouch:o}=this.gestures,{currSlide:h,mainScroll:a}=s,r=i[t]-n[t],l=a.x+r;if(!r)return;if("x"===t&&!h.isPannable()&&!o)return a.moveTo(l,!0),!0;const{bounds:p}=h,d=h.pan[t]+r;if(s.options.allowPanToNext&&"x"===e&&"x"===t&&!o){const i=a.getCurrSlideX(),s=a.x-i,e=r>0,n=!e;if(d>p.min[t]&&e){if(p.min[t]<=this.startPan[t])return a.moveTo(l,!0),!0;this.v(t,d)}else if(d0)return a.moveTo(Math.max(l,i),!0),!0;if(s<0)return a.moveTo(Math.min(l,i),!0),!0}else this.v(t,d)}else"y"===t&&(a.isShifted()||p.min.y===p.max.y)||this.v(t,d)}M(t){return(t-this.pswp.currSlide.bounds.center.y)/(this.pswp.viewportSize.y/3)}v(t,i,s){const{pan:e,bounds:n}=this.pswp.currSlide;if(n.correctPan(t,i)!==i||s){const n=Math.round(i-e[t]);e[t]+=n*(s||.35)}else e[t]=i}}function M(t,i,s){return t.x=(i.x+s.x)/2,t.y=(i.y+s.y)/2,t}class S{constructor(t){this.gestures=t,this.pswp=this.gestures.pswp,this.C={},this.T={},this.D={}}start(){this.A=this.pswp.currSlide.currZoomLevel,i(this.C,this.pswp.currSlide.pan),this.pswp.animations.stopAllPan(),this.I=!1}change(){const{p1:t,startP1:i,p2:s,startP2:e,pswp:n}=this.gestures,{currSlide:o}=n,a=o.zoomLevels.min,r=o.zoomLevels.max;if(!o.isZoomable()||n.mainScroll.isShifted())return;M(this.T,i,e),M(this.D,t,s);let l=1/h(i,e)*h(t,s)*this.A;if(l>o.zoomLevels.initial+o.zoomLevels.initial/15&&(this.I=!0),lr&&(l=r+.05*(l-r));o.pan.x=this.L("x",l),o.pan.y=this.L("y",l),o.setZoomLevel(l),o.applyCurrentZoomPan()}end(){const{pswp:t}=this,{currSlide:i}=t;i.currZoomLevelo.zoomLevels.max?a=o.zoomLevels.max:(r=!1,a=h);const l=s.bgOpacity,p=s.bgOpacity<1,d=i({},o.pan);let c=i({},d);t&&(this.D.x=0,this.D.y=0,this.T.x=0,this.T.y=0,this.A=h,i(this.C,d)),r&&(c={x:this.L("x",a),y:this.L("y",a)}),o.setZoomLevel(a),c={x:o.bounds.correctPan("x",c.x),y:o.bounds.correctPan("y",c.y)},o.setZoomLevel(h);let m=!0;if(e(c,d)&&(m=!1),!m&&!r&&!p)return o.g(a),void o.applyCurrentZoomPan();s.animations.stopAllPan(),s.animations.startSpring({isPan:!0,start:0,end:1e3,velocity:0,dampingRatio:1,naturalFrequency:40,onUpdate:t=>{if(t/=1e3,m||r){if(m&&(o.pan.x=d.x+(c.x-d.x)*t,o.pan.y=d.y+(c.y-d.y)*t),r){const i=h+(a-h)*t;o.setZoomLevel(i)}o.applyCurrentZoomPan()}p&&s.bgOpacity<1&&s.applyBgOpacity(n(l+(1-l)*t,0,1))},onComplete:()=>{o.g(a),o.applyCurrentZoomPan()}})}}function z(t){return!!t.target.closest(".pswp__container")}class P{constructor(t){this.gestures=t}click(t,i){const s=i.target.classList,e=s.contains("pswp__img"),n=s.contains("pswp__item")||s.contains("pswp__zoom-wrap");e?this.k("imageClick",t,i):n&&this.k("bgClick",t,i)}tap(t,i){z(i)&&this.k("tap",t,i)}doubleTap(t,i){z(i)&&this.k("doubleTap",t,i)}k(t,i,s){const{pswp:e}=this.gestures,{currSlide:n}=e,o=e.options[t+"Action"];if(!e.dispatch(t+"Action",{point:i,originalEvent:s}).defaultPrevented)if("function"!=typeof o)switch(o){case"close":case"next":e[o]();break;case"zoom":n.toggleZoom(i);break;case"zoom-or-close":n.isZoomable()&&n.zoomLevels.secondary!==n.zoomLevels.initial?n.toggleZoom(i):e.options.clickToCloseNonZoomable&&e.close();break;case"toggle-controls":this.gestures.pswp.element.classList.toggle("pswp--ui-visible")}else o.call(e,i,s)}}class C{constructor(t){this.pswp=t,this.p1={},this.p2={},this.prevP1={},this.prevP2={},this.startP1={},this.startP2={},this.velocity={},this.Z={},this.F={},this.O=0,this.B=[],this.R="ontouchstart"in window,this.N=!!window.PointerEvent,this.supportsTouch=this.R||this.N&&navigator.maxTouchPoints>1,this.supportsTouch||(t.options.allowPanToNext=!1),this.drag=new x(this),this.zoomLevels=new S(this),this.tapHandler=new P(this),t.on("bindEvents",(()=>{t.events.add(t.scrollWrap,"click",(t=>this.G(t))),this.N?this.V("pointer","down","up","cancel"):this.R?(this.V("touch","start","end","cancel"),t.scrollWrap.ontouchmove=()=>{},t.scrollWrap.ontouchend=()=>{}):this.V("mouse","down","up")}))}V(t,i,s,e){const{pswp:n}=this,{events:o}=n,h=e?t+e:"";o.add(n.scrollWrap,t+i,this.onPointerDown.bind(this)),o.add(window,t+"move",this.onPointerMove.bind(this)),o.add(window,t+s,this.onPointerUp.bind(this)),h&&o.add(n.scrollWrap,h,this.onPointerUp.bind(this))}onPointerDown(t){let s;if("mousedown"!==t.type&&"mouse"!==t.pointerType||(s=!0),s&&t.button>0)return;const{pswp:e}=this;e.opener.isOpen?e.dispatch("pointerDown",{originalEvent:t}).defaultPrevented||(s&&(e.mouseDetected(),this.U(t)),e.animations.stopAll(),this.q(t,"down"),this.pointerDown=!0,1===this.O&&(this.dragAxis=null,i(this.startP1,this.p1)),this.O>1?(this.H(),this.isMultitouch=!0):this.isMultitouch=!1):t.preventDefault()}onPointerMove(t){t.preventDefault(),this.O&&(this.q(t,"move"),this.pswp.dispatch("pointerMove",{originalEvent:t}).defaultPrevented||(1!==this.O||this.isDragging?this.O>1&&!this.isZooming&&(this.K(),this.isZooming=!0,this.W(),this.zoomLevels.start(),this.j(),this.X()):(this.dragAxis||this.Y(),this.dragAxis&&!this.isDragging&&(this.isZooming&&(this.isZooming=!1,this.zoomLevels.end()),this.isDragging=!0,this.H(),this.W(),this.$=Date.now(),this.J=!1,i(this.F,this.p1),this.velocity.x=0,this.velocity.y=0,this.drag.start(),this.j(),this.X()))))}K(){this.isDragging&&(this.isDragging=!1,this.J||this.tt(!0),this.drag.end(),this.dragAxis=null)}onPointerUp(t){this.O&&(this.q(t,"up"),this.pswp.dispatch("pointerUp",{originalEvent:t}).defaultPrevented||(0===this.O&&(this.pointerDown=!1,this.j(),this.isDragging?this.K():this.isZooming||this.isMultitouch||this.it(t)),this.O<2&&this.isZooming&&(this.isZooming=!1,this.zoomLevels.end(),1===this.O&&(this.dragAxis=null,this.W()))))}X(){(this.isDragging||this.isZooming)&&(this.tt(),this.isDragging?e(this.p1,this.prevP1)||this.drag.change():e(this.p1,this.prevP1)&&e(this.p2,this.prevP2)||this.zoomLevels.change(),this.st(),this.raf=requestAnimationFrame(this.X.bind(this)))}tt(t){const s=Date.now(),e=s-this.$;e<50&&!t||(this.velocity.x=this.ht("x",e),this.velocity.y=this.ht("y",e),this.$=s,i(this.F,this.p1),this.J=!0)}it(t){const{mainScroll:s}=this.pswp;if(s.isShifted())return void s.moveIndexBy(0,!0);if(t.type.indexOf("cancel")>0)return;if("mouseup"===t.type||"mouse"===t.pointerType)return void this.tapHandler.click(this.startP1,t);const e=this.pswp.options.doubleTapAction?300:0;this.et?(this.H(),h(this.Z,this.startP1)<25&&this.tapHandler.doubleTap(this.startP1,t)):(i(this.Z,this.startP1),this.et=setTimeout((()=>{this.tapHandler.tap(this.startP1,t),this.H()}),e))}H(){this.et&&(clearTimeout(this.et),this.et=null)}ht(t,i){const s=this.p1[t]-this.F[t];return Math.abs(s)>1&&i>5?s/i:0}j(){this.raf&&(cancelAnimationFrame(this.raf),this.raf=null)}U(t){return t.preventDefault(),!0}q(t,s){if(this.N){const e=this.B.findIndex((i=>i.id===t.pointerId));"up"===s&&e>-1?this.B.splice(e,1):"down"===s&&-1===e?this.B.push(this.nt(t,{})):e>-1&&this.nt(t,this.B[e]),this.O=this.B.length,this.O>0&&i(this.p1,this.B[0]),this.O>1&&i(this.p2,this.B[1])}else this.O=0,t.type.indexOf("touch")>-1?t.touches&&t.touches.length>0&&(this.nt(t.touches[0],this.p1),this.O++,t.touches.length>1&&(this.nt(t.touches[1],this.p2),this.O++)):(this.nt(t,this.p1),"up"===s?this.O=0:this.O++)}st(){i(this.prevP1,this.p1),i(this.prevP2,this.p2)}W(){i(this.startP1,this.p1),i(this.startP2,this.p2),this.st()}Y(){if(this.pswp.mainScroll.isShifted())this.dragAxis="x";else{const t=Math.abs(this.p1.x-this.startP1.x)-Math.abs(this.p1.y-this.startP1.y);if(0!==t){const i=t>0?"x":"y";Math.abs(this.p1[i]-this.startP1[i])>=10&&(this.dragAxis=i)}}}nt(t,i){return i.x=t.pageX-this.pswp.offset.x,i.y=t.pageY-this.pswp.offset.y,void 0!==t.pointerId?i.id=t.pointerId:void 0!==t.identifier&&(i.id=t.identifier),i}G(t){this.pswp.mainScroll.isShifted()&&(t.preventDefault(),t.stopPropagation())}}class T{constructor(t){this.pswp=t,this.x=0,this.resetPosition()}resize(t){const{pswp:i}=this,s=Math.round(i.viewportSize.x+i.viewportSize.x*i.options.spacing),e=s!==this.slideWidth;e&&(this.slideWidth=s,this.moveTo(this.getCurrSlideX())),this.itemHolders.forEach(((i,s)=>{e&&r(i.el,(s+this.ot)*this.slideWidth),t&&i.slide&&i.slide.resize()}))}resetPosition(){this.rt=0,this.at=0,this.slideWidth=0,this.ot=-1}appendHolders(){this.itemHolders=[];for(let i=0;i<3;i++){const s=t("pswp__item",!1,this.pswp.container);s.style.display=1===i?"block":"none",this.itemHolders.push({el:s})}}canBeSwiped(){return this.pswp.getNumItems()>1}moveIndexBy(t,i,s){const{pswp:e}=this;let n=e.potentialIndex+t;const o=e.getNumItems();if(e.canLoop()){n=e.getLoopedIndex(n);const i=(t+o)%o;t=i<=o/2?i:i-o}else n<0?n=0:n>=o&&(n=o-1),t=n-e.potentialIndex;e.potentialIndex=n,this.rt-=t,e.animations.stopMainScroll();const h=this.getCurrSlideX();if(i){e.animations.startSpring({isMainScroll:!0,start:this.x,end:h,velocity:s||0,naturalFrequency:30,dampingRatio:1,onUpdate:t=>{this.moveTo(t)},onComplete:()=>{this.updateCurrItem(),e.appendHeavy()}});let t=e.potentialIndex-e.currIndex;if(e.canLoop()){const i=(t+o)%o;t=i<=o/2?i:i-o}Math.abs(t)>1&&this.updateCurrItem()}else this.moveTo(h),this.updateCurrItem();if(t)return!0}getCurrSlideX(){return this.slideWidth*this.rt}isShifted(){return this.x!==this.getCurrSlideX()}updateCurrItem(){const{pswp:t}=this,i=this.at-this.rt;if(!i)return;this.at=this.rt,t.currIndex=t.potentialIndex;let s,e=Math.abs(i);e>=3&&(this.ot+=i+(i>0?-3:3),e=3);for(let n=0;n0?(s=this.itemHolders.shift(),this.itemHolders[2]=s,this.ot++,r(s.el,(this.ot+2)*this.slideWidth),t.setContent(s,t.currIndex-e+n+2)):(s=this.itemHolders.pop(),this.itemHolders.unshift(s),this.ot--,r(s.el,this.ot*this.slideWidth),t.setContent(s,t.currIndex+e-n-2));Math.abs(this.ot)>50&&!this.isShifted()&&(this.resetPosition(),this.resize()),t.animations.stopAllPan(),this.itemHolders.forEach(((t,i)=>{t.slide&&t.slide.setIsActive(1===i)})),t.currSlide=this.itemHolders[1].slide,t.contentLoader.updateLazy(i),t.currSlide.applyCurrentZoomPan(),t.dispatch("change")}moveTo(t,i){let s,e;!this.pswp.canLoop()&&i&&(s=(this.slideWidth*this.rt-t)/this.slideWidth,s+=this.pswp.currIndex,e=Math.round(t-this.x),(s<0&&e>0||s>=this.pswp.getNumItems()-1&&e<0)&&(t=this.x+.35*e)),this.x=t,r(this.pswp.container,t),this.pswp.dispatch("moveMainScroll",{x:t,dragging:i})}}class D{constructor(t){this.pswp=t,t.on("bindEvents",(()=>{t.options.initialPointerPos||this.ct(),t.events.add(document,"focusin",this.lt.bind(this)),t.events.add(document,"keydown",this.ut.bind(this))}));const i=document.activeElement;t.on("destroy",(()=>{t.options.returnFocus&&i&&this.dt&&i.focus()}))}ct(){this.dt||(this.pswp.element.focus(),this.dt=!0)}ut(t){const{pswp:i}=this;if(i.dispatch("keydown",{originalEvent:t}).defaultPrevented)return;if(function(t){if(2===t.which||t.ctrlKey||t.metaKey||t.altKey||t.shiftKey)return!0}(t))return;let s,e,n;switch(t.keyCode){case 27:i.options.escKey&&(s="close");break;case 90:s="toggleZoom";break;case 37:e="x";break;case 38:e="y";break;case 39:e="x",n=!0;break;case 40:n=!0,e="y";break;case 9:this.ct()}if(e){t.preventDefault();const{currSlide:o}=i;i.options.arrowKeys&&"x"===e&&i.getNumItems()>1?s=n?"next":"prev":o&&o.currZoomLevel>o.zoomLevels.fit&&(o.pan[e]+=n?-80:80,o.panTo(o.pan.x,o.pan.y))}s&&(t.preventDefault(),i[s]())}lt(t){const{template:i}=this.pswp;document===t.target||i===t.target||i.contains(t.target)||i.focus()}}class A{constructor(t){this.props=t;const{target:i,onComplete:s,transform:e}=t;let{duration:n,easing:o}=t;const h=e?"transform":"opacity",r=t[h];this.ft=i,this.wt=s,n=n||333,o=o||"cubic-bezier(.4,0,.22,1)",this.gt=this.gt.bind(this),this._t=setTimeout((()=>{a(i,h,n,o),this._t=setTimeout((()=>{i.addEventListener("transitionend",this.gt,!1),i.addEventListener("transitioncancel",this.gt,!1),i.style[h]=r}),30)}),0)}gt(t){t.target===this.ft&&this.vt()}vt(){this.yt||(this.yt=!0,this.onFinish(),this.wt&&this.wt())}destroy(){this._t&&clearTimeout(this._t),a(this.ft),this.ft.removeEventListener("transitionend",this.gt,!1),this.ft.removeEventListener("transitioncancel",this.gt,!1),this.yt||this.vt()}}class I{constructor(t,i,s){this.velocity=1e3*t,this.bt=i||.75,this.xt=s||12,this.bt<1&&(this.Mt=this.xt*Math.sqrt(1-this.bt*this.bt))}easeFrame(t,i){let s,e=0;i/=1e3;const n=Math.E**(-this.bt*this.xt*i);if(1===this.bt)s=this.velocity+this.xt*t,e=(t+s*i)*n,this.velocity=e*-this.xt+s*n;else if(this.bt<1){s=1/this.Mt*(this.bt*this.xt*t+this.velocity);const o=Math.cos(this.Mt*i),h=Math.sin(this.Mt*i);e=n*(t*o+s*h),this.velocity=e*-this.xt*this.bt+n*(-this.Mt*t*h+this.Mt*s*o)}return e}}class E{constructor(t){this.props=t;const{start:i,end:s,velocity:e,onUpdate:n,onComplete:o,onFinish:h,dampingRatio:a,naturalFrequency:r}=t,l=new I(e,a,r);let p=Date.now(),d=i-s;this.St=h;const c=()=>{this.zt&&(d=l.easeFrame(d,Date.now()-p),Math.abs(d)<1&&Math.abs(l.velocity)<50?(n(s),o&&o(),this.onFinish()):(p=Date.now(),n(d+s),this.zt=requestAnimationFrame(c)))};this.zt=requestAnimationFrame(c)}destroy(){this.zt>=0&&cancelAnimationFrame(this.zt),this.zt=null}}class L{constructor(){this.activeAnimations=[]}startSpring(t){this.Pt(t,!0)}startTransition(t){this.Pt(t)}Pt(t,i){let s;return s=i?new E(t):new A(t),this.activeAnimations.push(s),s.onFinish=()=>this.stop(s),s}stop(t){t.destroy();const i=this.activeAnimations.indexOf(t);i>-1&&this.activeAnimations.splice(i,1)}stopAll(){this.activeAnimations.forEach((t=>{t.destroy()})),this.activeAnimations=[]}stopAllPan(){this.activeAnimations=this.activeAnimations.filter((t=>!t.props.isPan||(t.destroy(),!1)))}stopMainScroll(){this.activeAnimations=this.activeAnimations.filter((t=>!t.props.isMainScroll||(t.destroy(),!1)))}isPanRunning(){return this.activeAnimations.some((t=>t.props.isPan))}}class k{constructor(t){this.pswp=t,t.events.add(t.element,"wheel",this.Ct.bind(this))}Ct(t){t.preventDefault();const{currSlide:i}=this.pswp;let{deltaX:s,deltaY:e}=t;if(i&&!this.pswp.dispatch("wheel",{originalEvent:t}).defaultPrevented)if(t.ctrlKey||this.pswp.options.wheelToZoom){if(i.isZoomable()){let s=-e;1===t.deltaMode?s*=.05:s*=t.deltaMode?1:.002,s=2**s;const n=i.currZoomLevel*s;i.zoomTo(n,{x:t.clientX,y:t.clientY})}}else i.isPannable()&&(1===t.deltaMode&&(s*=18,e*=18),i.panTo(i.pan.x-s,i.pan.y-e))}}class Z{constructor(i,s){const e=s.name||s.className;let n=s.html;if(!1===i.options[e])return;"string"==typeof i.options[e+"SVG"]&&(n=i.options[e+"SVG"]),i.dispatch("uiElementCreate",{data:s});let o,h="";s.isButton?(h+="pswp__button ",h+=s.className||`pswp__button--${s.name}`):h+=s.className||`pswp__${s.name}`;let a=s.isButton?s.tagName||"button":s.tagName||"div";if(a=a.toLowerCase(),o=t(h,a),s.isButton){o=t(h,a),"button"===a&&(o.type="button");let{title:n}=s;const{ariaLabel:r}=s;"string"==typeof i.options[e+"Title"]&&(n=i.options[e+"Title"]),n&&(o.title=n),(r||n)&&o.setAttribute("aria-label",r||n)}o.innerHTML=function(t){if("string"==typeof t)return t;if(!t||!t.isCustomSVG)return"";const i=t;let s='",s}(n),s.onInit&&s.onInit(o,i),s.onClick&&(o.onclick=t=>{"string"==typeof s.onClick?i[s.onClick]():s.onClick(t,o,i)});const r=s.appendTo||"bar";let l;"bar"===r?(i.topBar||(i.topBar=t("pswp__top-bar pswp__hide-on-close",!1,i.scrollWrap)),l=i.topBar):(o.classList.add("pswp__hide-on-close"),l="wrapper"===r?i.scrollWrap:i.element),l.appendChild(i.applyFilters("uiElement",o,s))}}function F(t,i,s){t.classList.add("pswp__button--arrow"),i.on("change",(()=>{i.options.loop||(t.disabled=s?!(i.currIndex0))}))}const O={name:"arrowPrev",className:"pswp__button--arrow--prev",title:"Previous",order:10,isButton:!0,appendTo:"wrapper",html:{isCustomSVG:!0,size:60,inner:'',outlineID:"pswp__icn-arrow"},onClick:"prev",onInit:F},B={name:"arrowNext",className:"pswp__button--arrow--next",title:"Next",order:11,isButton:!0,appendTo:"wrapper",html:{isCustomSVG:!0,size:60,inner:'',outlineID:"pswp__icn-arrow"},onClick:"next",onInit:(t,i)=>{F(t,i,!0)}},R={name:"close",title:"Close",order:20,isButton:!0,html:{isCustomSVG:!0,inner:'',outlineID:"pswp__icn-close"},onClick:"close"},N={name:"zoom",title:"Zoom",order:10,isButton:!0,html:{isCustomSVG:!0,inner:'',outlineID:"pswp__icn-zoom"},onClick:"toggleZoom"},G={name:"preloader",appendTo:"bar",order:7,html:{isCustomSVG:!0,inner:'',outlineID:"pswp__icn-loading"},onInit:(t,i)=>{let s,e;const n=i=>{var e;s!==i&&(s=i,"active",e=i,t.classList[e?"add":"remove"]("pswp__preloader--active"))},o=()=>{if(!i.currSlide.content.isLoading())return n(!1),void(e&&(clearTimeout(e),e=null));e||(e=setTimeout((()=>{n(i.currSlide.content.isLoading()),e=null}),i.options.preloaderDelay))};i.on("change",o),i.on("loadComplete",(t=>{i.currSlide===t.slide&&o()})),i.ui.updatePreloaderVisibility=o}},V={name:"counter",order:5,onInit:(t,i)=>{i.on("change",(()=>{t.innerText=i.currIndex+1+i.options.indexIndicatorSep+i.getNumItems()}))}};function U(t,i){t.classList[i?"add":"remove"]("pswp--zoomed-in")}class q{constructor(t){this.pswp=t}init(){const{pswp:t}=this;this.isRegistered=!1,this.uiElementsData=[R,O,B,N,G,V],t.dispatch("uiRegister"),this.uiElementsData.sort(((t,i)=>(t.order||0)-(i.order||0))),this.items=[],this.isRegistered=!0,this.uiElementsData.forEach((t=>{this.registerElement(t)})),t.on("change",(()=>{t.element.classList[1===t.getNumItems()?"add":"remove"]("pswp--one-slide")})),t.on("zoomPanUpdate",(()=>this.Tt()))}registerElement(t){this.isRegistered?this.items.push(new Z(this.pswp,t)):this.uiElementsData.push(t)}Tt(){const{template:t,currSlide:i,options:s}=this.pswp;let{currZoomLevel:e}=i;if(this.pswp.opener.isClosing)return;if(this.pswp.opener.isOpen||(e=i.zoomLevels.initial),e===this.Dt)return;this.Dt=e;const n=i.zoomLevels.initial-i.zoomLevels.secondary;if(Math.abs(n)<.01||!i.isZoomable())return U(t,!1),void t.classList.remove("pswp--zoom-allowed");t.classList.add("pswp--zoom-allowed");const o=n<0;e===i.zoomLevels.secondary?U(t,o):e>i.zoomLevels.secondary?U(t,!0):U(t,!1),"zoom"!==s.imageClickAction&&"zoom-or-close"!==s.imageClickAction||t.classList.add("pswp--click-to-zoom")}}class H{constructor(t,i){this.type=t,i&&Object.assign(this,i)}preventDefault(){this.defaultPrevented=!0}}class K{constructor(i,s){this.element=t("pswp__img pswp__img--placeholder",i?"img":"",s),i&&(this.element.decoding="async",this.element.alt="",this.element.src=i,this.element.setAttribute("role","presentation")),this.element.setAttribute("aria-hiden","true")}setDisplayedSize(t,i){this.element&&("IMG"===this.element.tagName?(c(this.element,250,"auto"),this.element.style.transformOrigin="0 0",this.element.style.transform=o(0,0,t/250)):c(this.element,t,i))}destroy(){this.element.parentNode&&this.element.remove(),this.element=null}}class W{constructor(t,i,s){this.instance=i,this.data=t,this.index=s,this.width=Number(this.data.w)||Number(this.data.width)||0,this.height=Number(this.data.h)||Number(this.data.height)||0,this.isAttached=!1,this.hasSlide=!1,this.state=l,this.data.type?this.type=this.data.type:this.data.src?this.type="image":this.type="html",this.instance.dispatch("contentInit",{content:this})}removePlaceholder(){this.placeholder&&!this.keepPlaceholder()&&setTimeout((()=>{this.placeholder&&(this.placeholder.destroy(),this.placeholder=null)}),500)}load(i,s){if(!this.placeholder&&this.slide&&this.usePlaceholder()){const t=this.instance.applyFilters("placeholderSrc",!(!this.data.msrc||!this.slide.isFirstSlide)&&this.data.msrc,this);this.placeholder=new K(t,this.slide.container)}this.element&&!s||this.instance.dispatch("contentLoad",{content:this,isLazy:i}).defaultPrevented||(this.isImageContent()?this.loadImage(i):(this.element=t("pswp__content"),this.element.innerHTML=this.data.html||""),s&&this.slide&&this.slide.updateContentSize(!0))}loadImage(i){this.element=t("pswp__img","img"),this.instance.dispatch("contentLoadImage",{content:this,isLazy:i}).defaultPrevented||(this.data.srcset&&(this.element.srcset=this.data.srcset),this.element.src=this.data.src,this.element.alt=this.data.alt||"",this.state=p,this.element.complete?this.onLoaded():(this.element.onload=()=>{this.onLoaded()},this.element.onerror=()=>{this.onError()}))}setSlide(t){this.slide=t,this.hasSlide=!0,this.instance=t.pswp}onLoaded(){this.state=u,this.slide&&(this.instance.dispatch("loadComplete",{slide:this.slide,content:this}),this.slide.isActive&&this.slide.heavyAppended&&!this.element.parentNode&&(this.slide.container.innerHTML="",this.append(),this.slide.updateContentSize(!0)))}onError(){this.state=d,this.slide&&(this.displayError(),this.instance.dispatch("loadComplete",{slide:this.slide,isError:!0,content:this}),this.instance.dispatch("loadError",{slide:this.slide,content:this}))}isLoading(){return this.instance.applyFilters("isContentLoading",this.state===p,this)}isError(){return this.state===d}isImageContent(){return"image"===this.type}setDisplayedSize(t,i){if(this.element&&(this.placeholder&&this.placeholder.setDisplayedSize(t,i),!this.instance.dispatch("contentResize",{content:this,width:t,height:i}).defaultPrevented&&(c(this.element,t,i),this.isImageContent()&&!this.isError()))){const s=this.element;s.srcset&&(!s.dataset.largestUsedSize||t>s.dataset.largestUsedSize)&&(s.sizes=t+"px",s.dataset.largestUsedSize=t),this.slide&&this.instance.dispatch("imageSizeChange",{slide:this.slide,width:t,height:i,content:this})}}isZoomable(){return this.instance.applyFilters("isContentZoomable",this.isImageContent()&&this.state!==d,this)}usePlaceholder(){return this.instance.applyFilters("useContentPlaceholder",this.isImageContent(),this)}lazyLoad(){this.instance.dispatch("contentLazyLoad",{content:this}).defaultPrevented||this.load(!0)}keepPlaceholder(){return this.instance.applyFilters("isKeepingPlaceholder",this.isLoading(),this)}destroy(){this.hasSlide=!1,this.slide=null,this.instance.dispatch("contentDestroy",{content:this}).defaultPrevented||(this.remove(),this.isImageContent()&&this.element&&(this.element.onload=null,this.element.onerror=null,this.element=null))}displayError(){if(this.slide){let i=t("pswp__error-msg");i.innerText=this.instance.options.errorMsg,i=this.instance.applyFilters("contentErrorElement",i,this),this.element=t("pswp__content pswp__error-msg-container"),this.element.appendChild(i),this.slide.container.innerHTML="",this.slide.container.appendChild(this.element),this.slide.updateContentSize(!0),this.removePlaceholder()}}append(){this.isAttached=!0,this.state!==d?this.instance.dispatch("contentAppend",{content:this}).defaultPrevented||(this.isImageContent()?this.slide&&!this.slide.isActive&&"decode"in this.element?(this.isDecoding=!0,requestAnimationFrame((()=>{this.element&&"IMG"===this.element.tagName&&this.element.decode().then((()=>{this.isDecoding=!1,requestAnimationFrame((()=>{this.appendImage()}))})).catch((()=>{this.isDecoding=!1}))}))):(!this.placeholder||this.state!==u&&this.state!==d||this.removePlaceholder(),this.appendImage()):this.element&&!this.element.parentNode&&this.slide.container.appendChild(this.element)):this.displayError()}activate(){this.instance.dispatch("contentActivate",{content:this}).defaultPrevented||this.slide&&(this.isImageContent()&&this.isDecoding?this.appendImage():this.isError()&&this.load(!1,!0))}deactivate(){this.instance.dispatch("contentDeactivate",{content:this})}remove(){this.isAttached=!1,this.instance.dispatch("contentRemove",{content:this}).defaultPrevented||this.element&&this.element.parentNode&&this.element.remove()}appendImage(){this.isAttached&&(this.instance.dispatch("contentAppendImage",{content:this}).defaultPrevented||this.slide&&this.element&&!this.element.parentNode&&(this.slide.container.appendChild(this.element),!this.placeholder||this.state!==u&&this.state!==d||this.removePlaceholder()))}}class j{constructor(t){this.pswp=t,this.isClosed=!0,this.At=this.At.bind(this),t.on("firstZoomPan",this.At)}open(){this.At(),this.Pt()}close(){if(this.isClosed||this.isClosing||this.isOpening)return!1;const t=this.pswp.currSlide;return this.isOpen=!1,this.isOpening=!1,this.isClosing=!0,this.It=this.pswp.options.hideAnimationDuration,t&&t.currZoomLevel*t.width>=this.pswp.options.maxWidthToAnimate&&(this.It=0),this.Et(),setTimeout((()=>{this.Pt()}),this.Lt?30:0),!0}At(){if(this.pswp.off("firstZoomPan",this.At),!this.isOpening){const t=this.pswp.currSlide;this.isOpening=!0,this.isClosing=!1,this.It=this.pswp.options.showAnimationDuration,t&&t.zoomLevels.initial*t.width>=this.pswp.options.maxWidthToAnimate&&(this.It=0),this.Et()}}Et(){const{pswp:t}=this,i=this.pswp.currSlide,{options:s}=t;if("fade"===s.showHideAnimationType?(s.showHideOpacity=!0,this.kt=!1):"none"===s.showHideAnimationType?(s.showHideOpacity=!1,this.It=0,this.kt=!1):this.isOpening&&t.Zt?this.kt=t.Zt:this.kt=this.pswp.getThumbBounds(),this.Ft=i.getPlaceholderElement(),t.animations.stopAll(),this.Ot=this.It>50,this.Bt=Boolean(this.kt)&&i.content&&i.content.usePlaceholder()&&(!this.isClosing||!t.mainScroll.isShifted()),this.Bt?this.Rt=s.showHideOpacity:(this.Rt=!0,this.isOpening&&(i.zoomAndPanToInitial(),i.applyCurrentZoomPan())),this.Nt=!this.Rt&&this.pswp.options.bgOpacity>.003,this.Gt=this.Rt?t.element:t.bg,!this.Ot)return this.It=0,this.Bt=!1,this.Nt=!1,this.Rt=!0,void(this.isOpening&&(t.element.style.opacity=.003,t.applyBgOpacity(1)));this.Bt&&this.kt.innerRect?(this.Lt=!0,this.Vt=this.pswp.container,this.Ut=this.pswp.currSlide.holderElement,t.container.style.overflow="hidden",t.container.style.width=t.viewportSize.x+"px"):this.Lt=!1,this.isOpening?(this.Rt?(t.element.style.opacity=.003,t.applyBgOpacity(1)):(this.Nt&&(t.bg.style.opacity=.003),t.element.style.opacity=1),this.Bt&&(this.qt(),this.Ft&&(this.Ft.willChange="transform",this.Ft.style.opacity=.003))):this.isClosing&&(t.mainScroll.itemHolders[0].el.style.display="none",t.mainScroll.itemHolders[2].el.style.display="none",this.Lt&&0!==t.mainScroll.x&&(t.mainScroll.resetPosition(),t.mainScroll.resize()))}Pt(){this.isOpening&&this.Ot&&this.Ft&&"IMG"===this.Ft.tagName?new Promise((t=>{let i=!1,s=!0;var e;(e=this.Ft,"decode"in e?e.decode():e.complete?Promise.resolve(e):new Promise(((t,i)=>{e.onload=()=>t(e),e.onerror=i}))).finally((()=>{i=!0,s||t()})),setTimeout((()=>{s=!1,i&&t()}),50),setTimeout(t,250)})).finally((()=>this.Ht())):this.Ht()}Ht(){this.pswp.element.style.setProperty("--pswp-transition-duration",this.It+"ms"),this.pswp.dispatch(this.isOpening?"openingAnimationStart":"closingAnimationStart"),this.pswp.dispatch("initialZoom"+(this.isOpening?"In":"Out")),this.pswp.element.classList[this.isOpening?"add":"remove"]("pswp--ui-visible"),this.isOpening?(this.Ft&&(this.Ft.style.opacity=1),this.Kt()):this.isClosing&&this.Wt(),this.Ot||this.jt()}jt(){const{pswp:t}=this;this.isOpen=this.isOpening,this.isClosed=this.isClosing,this.isOpening=!1,this.isClosing=!1,t.dispatch(this.isOpen?"openingAnimationEnd":"closingAnimationEnd"),t.dispatch("initialZoom"+(this.isOpen?"InEnd":"OutEnd")),this.isClosed?t.destroy():this.isOpen&&(this.Bt&&(t.container.style.overflow="visible",t.container.style.width="100%"),t.currSlide.applyCurrentZoomPan())}Kt(){const{pswp:t}=this;this.Bt&&(this.Lt&&(this.Xt(this.Vt,"transform","translate3d(0,0,0)"),this.Xt(this.Ut,"transform","none")),t.currSlide.zoomAndPanToInitial(),this.Xt(t.currSlide.container,"transform",t.currSlide.getCurrentTransform())),this.Nt&&this.Xt(t.bg,"opacity",t.options.bgOpacity),this.Rt&&this.Xt(t.element,"opacity",1)}Wt(){const{pswp:t}=this;this.Bt&&this.qt(!0),this.Nt&&t.bgOpacity>.01&&this.Xt(t.bg,"opacity",0),this.Rt&&this.Xt(t.element,"opacity",0)}qt(t){const{pswp:s}=this,{innerRect:e}=this.kt,{currSlide:n,viewportSize:h}=s;if(this.Lt){const i=-h.x+(this.kt.x-e.x)+e.w,s=-h.y+(this.kt.y-e.y)+e.h,n=h.x-e.w,a=h.y-e.h;t?(this.Xt(this.Vt,"transform",o(i,s)),this.Xt(this.Ut,"transform",o(n,a))):(r(this.Vt,i,s),r(this.Ut,n,a))}i(n.pan,e||this.kt),n.currZoomLevel=this.kt.w/n.width,t?this.Xt(n.container,"transform",n.getCurrentTransform()):n.applyCurrentZoomPan()}Xt(t,i,s){if(!this.It)return void(t.style[i]=s);const{animations:e}=this.pswp,n={duration:this.It,easing:this.pswp.options.easing,onComplete:()=>{e.activeAnimations.length||this.jt()},target:t};n[i]=s,e.startTransition(n)}}function X(t,i){const s=i.getItemData(t);if(!i.dispatch("lazyLoadSlide",{index:t,itemData:s}).defaultPrevented)return function(t,i,s){const e=i.createContentFromData(t,s);if(!e||!e.lazyLoad)return;const{options:n}=i,o=_(n,i.viewportSize||w(n),t,s),h=new y(n,t,-1);return h.update(e.width,e.height,o),e.lazyLoad(),e.setDisplayedSize(Math.ceil(e.width*h.initial),Math.ceil(e.height*h.initial)),e}(s,i,t)}class Y{constructor(t){this.pswp=t,this.limit=Math.max(t.options.preload[0]+t.options.preload[1]+1,5),this.Yt=[]}updateLazy(t){const{pswp:i}=this;if(i.dispatch("lazyLoad").defaultPrevented)return;const{preload:s}=i.options,e=void 0===t||t>=0;let n;for(n=0;n<=s[1];n++)this.loadSlideByIndex(i.currIndex+(e?n:-n));for(n=1;n<=s[0];n++)this.loadSlideByIndex(i.currIndex+(e?-n:n))}loadSlideByIndex(t){t=this.pswp.getLoopedIndex(t);let i=this.getContentByIndex(t);i||(i=X(t,this.pswp),i&&this.addToCache(i))}getContentBySlide(t){let i=this.getContentByIndex(t.index);return i||(i=this.pswp.createContentFromData(t.data,t.index),i&&this.addToCache(i)),i&&i.setSlide(t),i}addToCache(t){if(this.removeByIndex(t.index),this.Yt.push(t),this.Yt.length>this.limit){const t=this.Yt.findIndex((t=>!t.isAttached&&!t.hasSlide));-1!==t&&this.Yt.splice(t,1)[0].destroy()}}removeByIndex(t){const i=this.Yt.findIndex((i=>i.index===t));-1!==i&&this.Yt.splice(i,1)}getContentByIndex(t){return this.Yt.find((i=>i.index===t))}destroy(){this.Yt.forEach((t=>t.destroy())),this.Yt=null}}const $={allowPanToNext:!0,spacing:.1,loop:!0,pinchToClose:!0,closeOnVerticalDrag:!0,hideAnimationDuration:333,showAnimationDuration:333,zoomAnimationDuration:333,escKey:!0,arrowKeys:!0,returnFocus:!0,maxWidthToAnimate:4e3,clickToCloseNonZoomable:!0,imageClickAction:"zoom-or-close",bgClickAction:"close",tapAction:"toggle-controls",doubleTapAction:"zoom",indexIndicatorSep:" / ",preloaderDelay:2e3,bgOpacity:.8,index:0,errorMsg:"The image cannot be loaded",preload:[1,2],easing:"cubic-bezier(.4,0,.22,1)"};export default class extends class extends class{constructor(){this.$t={},this.Jt={}}addFilter(t,i,s=100){this.Jt[t]||(this.Jt[t]=[]),this.Jt[t].push({fn:i,priority:s}),this.Jt[t].sort(((t,i)=>t.priority-i.priority)),this.pswp&&this.pswp.addFilter(t,i,s)}removeFilter(t,i){this.Jt[t]&&(this.Jt[t]=this.Jt[t].filter((t=>t.fn!==i))),this.pswp&&this.pswp.removeFilter(t,i)}applyFilters(t,...i){return this.Jt[t]&&this.Jt[t].forEach((t=>{i[0]=t.fn.apply(this,i)})),i[0]}on(t,i){this.$t[t]||(this.$t[t]=[]),this.$t[t].push(i),this.pswp&&this.pswp.on(t,i)}off(t,i){this.$t[t]&&(this.$t[t]=this.$t[t].filter((t=>i!==t))),this.pswp&&this.pswp.off(t,i)}dispatch(t,i){if(this.pswp)return this.pswp.dispatch(t,i);const s=new H(t,i);return this.$t?(this.$t[t]&&this.$t[t].forEach((t=>{t.call(this,s)})),s):s}}{getNumItems(){let t;const{dataSource:i}=this.options;i?i.length?t=i.length:i.gallery&&(i.items||(i.items=this.Qt(i.gallery)),i.items&&(t=i.items.length)):t=0;const s=this.dispatch("numItems",{dataSource:i,numItems:t});return this.applyFilters("numItems",s.numItems,i)}createContentFromData(t,i){return new W(t,this,i)}getItemData(t){const{dataSource:i}=this.options;let s;Array.isArray(i)?s=i[t]:i&&i.gallery&&(i.items||(i.items=this.Qt(i.gallery)),s=i.items[t]);let e=s;e instanceof Element&&(e=this.ti(e));const n=this.dispatch("itemData",{itemData:e||{},index:t});return this.applyFilters("itemData",n.itemData,t)}Qt(t){return this.options.children||this.options.childSelector?function(t,i,s=document){let e=[];if(t instanceof Element)e=[t];else if(t instanceof NodeList||Array.isArray(t))e=Array.from(t);else{const n="string"==typeof t?t:i;n&&(e=Array.from(s.querySelectorAll(n)))}return e}(this.options.children,this.options.childSelector,t)||[]:[t]}ti(t){const i={element:t},s="A"===t.tagName?t:t.querySelector("a");if(s){i.src=s.dataset.pswpSrc||s.href,s.dataset.pswpSrcset&&(i.srcset=s.dataset.pswpSrcset),i.width=parseInt(s.dataset.pswpWidth,10),i.height=parseInt(s.dataset.pswpHeight,10),i.w=i.width,i.h=i.height,s.dataset.pswpType&&(i.type=s.dataset.pswpType);const e=t.querySelector("img");e&&(i.msrc=e.currentSrc||e.src,i.alt=e.getAttribute("alt")),(s.dataset.pswpCropped||s.dataset.cropped)&&(i.thumbCropped=!0)}return this.applyFilters("domItemData",i,t,s),i}}{constructor(t){super(),this.ii(t),this.offset={},this.si={},this.viewportSize={},this.bgOpacity=1,this.events=new f,this.animations=new L,this.mainScroll=new T(this),this.gestures=new C(this),this.opener=new j(this),this.keyboard=new D(this),this.contentLoader=new Y(this)}init(){if(this.isOpen||this.isDestroying)return;this.isOpen=!0,this.dispatch("init"),this.dispatch("beforeOpen"),this.hi();let t="pswp--open";return this.gestures.supportsTouch&&(t+=" pswp--touch"),this.options.mainClass&&(t+=" "+this.options.mainClass),this.element.className+=" "+t,this.currIndex=this.options.index||0,this.potentialIndex=this.currIndex,this.dispatch("firstUpdate"),this.scrollWheel=new k(this),(Number.isNaN(this.currIndex)||this.currIndex<0||this.currIndex>=this.getNumItems())&&(this.currIndex=0),this.gestures.supportsTouch||this.mouseDetected(),this.updateSize(),this.offset.y=window.pageYOffset,this.ei=this.getItemData(this.currIndex),this.dispatch("gettingData",this.currIndex,this.ei,!0),this.Zt=this.getThumbBounds(),this.dispatch("initialLayout"),this.on("openingAnimationEnd",(()=>{this.setContent(this.mainScroll.itemHolders[0],this.currIndex-1),this.setContent(this.mainScroll.itemHolders[2],this.currIndex+1),this.mainScroll.itemHolders[0].el.style.display="block",this.mainScroll.itemHolders[2].el.style.display="block",this.appendHeavy(),this.contentLoader.updateLazy(),this.events.add(window,"resize",this.ni.bind(this)),this.events.add(window,"scroll",this.oi.bind(this)),this.dispatch("bindEvents")})),this.setContent(this.mainScroll.itemHolders[1],this.currIndex),this.dispatch("change"),this.opener.open(),this.dispatch("afterInit"),!0}getLoopedIndex(t){const i=this.getNumItems();return this.options.loop&&(t>i-1&&(t-=i),t<0&&(t+=i)),n(t,0,i-1)}appendHeavy(){this.mainScroll.itemHolders.forEach((t=>{t.slide&&t.slide.appendHeavy()}))}goTo(t){this.mainScroll.moveIndexBy(this.getLoopedIndex(t)-this.potentialIndex)}next(){this.goTo(this.potentialIndex+1)}prev(){this.goTo(this.potentialIndex-1)}zoomTo(...t){this.currSlide.zoomTo(...t)}toggleZoom(){this.currSlide.toggleZoom()}close(){this.opener.isOpen&&!this.isDestroying&&(this.isDestroying=!0,this.dispatch("close"),this.events.removeAll(),this.opener.close())}destroy(){if(!this.isDestroying)return this.options.showHideAnimationType="none",void this.close();this.dispatch("destroy"),this.listeners=null,this.scrollWrap.ontouchmove=null,this.scrollWrap.ontouchend=null,this.element.remove(),this.mainScroll.itemHolders.forEach((t=>{t.slide&&t.slide.destroy()})),this.contentLoader.destroy(),this.events.removeAll()}refreshSlideContent(t){this.contentLoader.removeByIndex(t),this.mainScroll.itemHolders.forEach(((i,s)=>{let e=this.currSlide.index-1+s;this.canLoop()&&(e=this.getLoopedIndex(e)),e===t&&(this.setContent(i,t,!0),1===s&&(this.currSlide=i.slide,i.slide.setIsActive(!0)))})),this.dispatch("change")}setContent(t,i,s){if(this.canLoop()&&(i=this.getLoopedIndex(i)),t.slide){if(t.slide.index===i&&!s)return;t.slide.destroy(),t.slide=null}if(!this.canLoop()&&(i<0||i>=this.getNumItems()))return;const e=this.getItemData(i);t.slide=new b(e,i,this),i===this.currIndex&&(this.currSlide=t.slide),t.slide.append(t.el)}getViewportCenterPoint(){return{x:this.viewportSize.x/2,y:this.viewportSize.y/2}}updateSize(t){if(this.isDestroying)return;const s=w(this.options,this);!t&&e(s,this.si)||(i(this.si,s),this.dispatch("beforeResize"),i(this.viewportSize,this.si),this.oi(),this.dispatch("viewportSize"),this.mainScroll.resize(this.opener.isOpen),!this.hasMouse&&window.matchMedia("(any-hover: hover)").matches&&this.mouseDetected(),this.dispatch("resize"))}applyBgOpacity(t){this.bgOpacity=Math.max(t,0),this.bg.style.opacity=this.bgOpacity*this.options.bgOpacity}mouseDetected(){this.hasMouse||(this.hasMouse=!0,this.element.classList.add("pswp--has_mouse"))}ni(){this.updateSize(),/iPhone|iPad|iPod/i.test(window.navigator.userAgent)&&setTimeout((()=>{this.updateSize()}),500)}oi(){this.setScrollOffset(0,window.pageYOffset)}setScrollOffset(t,i){this.offset.x=t,this.offset.y=i,this.dispatch("updateScrollOffset")}hi(){this.element=t("pswp"),this.element.setAttribute("tabindex",-1),this.element.setAttribute("role","dialog"),this.template=this.element,this.bg=t("pswp__bg",!1,this.element),this.scrollWrap=t("pswp__scroll-wrap",!1,this.element),this.container=t("pswp__container",!1,this.scrollWrap),this.mainScroll.appendHolders(),this.ui=new q(this),this.ui.init(),(this.options.appendToEl||document.body).appendChild(this.element)}getThumbBounds(){return function(t,i,s){const e=s.dispatch("thumbBounds",{index:t,itemData:i,instance:s});if(e.thumbBounds)return e.thumbBounds;const{element:n}=i;let o,h;if(n&&!1!==s.options.thumbSelector){const t=s.options.thumbSelector||"img";h=n.matches(t)?n:n.querySelector(t)}return h=s.applyFilters("thumbEl",h,i,t),h&&(o=i.thumbCropped?function(t,i,s){const e=t.getBoundingClientRect(),n=e.width/i,o=e.height/s,h=n>o?n:o,a=(e.width-i*h)/2,r=(e.height-s*h)/2,l={x:e.left+a,y:e.top+r,w:i*h};return l.innerRect={w:e.width,h:e.height,x:a,y:r},l}(h,i.w,i.h):function(t){const i=t.getBoundingClientRect();return{x:i.left,y:i.top,w:i.width}}(h)),s.applyFilters("thumbBounds",o,i,t)}(this.currIndex,this.currSlide?this.currSlide.data:this.ei,this)}canLoop(){return this.options.loop&&this.getNumItems()>2}ii(t){window.matchMedia("(prefers-reduced-motion), (update: slow)").matches&&(t.showHideAnimationType="none",t.zoomAnimationDuration=0),this.options={...$,...t}}} diff --git a/themes/demo/assets/vendor/slick-carousel/ajax-loader.gif b/themes/demo/assets/vendor/slick-carousel/ajax-loader.gif new file mode 100644 index 0000000..e0e6e97 Binary files /dev/null and b/themes/demo/assets/vendor/slick-carousel/ajax-loader.gif differ diff --git a/themes/demo/assets/vendor/slick-carousel/config.rb b/themes/demo/assets/vendor/slick-carousel/config.rb new file mode 100644 index 0000000..81f5ae3 --- /dev/null +++ b/themes/demo/assets/vendor/slick-carousel/config.rb @@ -0,0 +1,10 @@ +css_dir = "." +sass_dir = "." +images_dir = "." +fonts_dir = "fonts" +relative_assets = true + +output_style = :compact +line_comments = false + +preferred_syntax = :scss \ No newline at end of file diff --git a/themes/demo/assets/vendor/slick-carousel/fonts/slick.eot b/themes/demo/assets/vendor/slick-carousel/fonts/slick.eot new file mode 100644 index 0000000..2cbab9c Binary files /dev/null and b/themes/demo/assets/vendor/slick-carousel/fonts/slick.eot differ diff --git a/themes/demo/assets/vendor/slick-carousel/fonts/slick.svg b/themes/demo/assets/vendor/slick-carousel/fonts/slick.svg new file mode 100644 index 0000000..b36a66a --- /dev/null +++ b/themes/demo/assets/vendor/slick-carousel/fonts/slick.svg @@ -0,0 +1,14 @@ + + + +Generated by Fontastic.me + + + + + + + + + + diff --git a/themes/demo/assets/vendor/slick-carousel/fonts/slick.ttf b/themes/demo/assets/vendor/slick-carousel/fonts/slick.ttf new file mode 100644 index 0000000..9d03461 Binary files /dev/null and b/themes/demo/assets/vendor/slick-carousel/fonts/slick.ttf differ diff --git a/themes/demo/assets/vendor/slick-carousel/fonts/slick.woff b/themes/demo/assets/vendor/slick-carousel/fonts/slick.woff new file mode 100644 index 0000000..8ee9972 Binary files /dev/null and b/themes/demo/assets/vendor/slick-carousel/fonts/slick.woff differ diff --git a/themes/demo/assets/vendor/slick-carousel/slick-theme.css b/themes/demo/assets/vendor/slick-carousel/slick-theme.css new file mode 100644 index 0000000..5473e4a --- /dev/null +++ b/themes/demo/assets/vendor/slick-carousel/slick-theme.css @@ -0,0 +1 @@ +@charset 'UTF-8';.slick-loading .slick-list{background:#fff url('./ajax-loader.gif') center center no-repeat}@font-face{font-family:slick;font-weight:400;font-style:normal;src:url('./fonts/slick.eot');src:url('./fonts/slick.eot?#iefix') format('embedded-opentype'),url('./fonts/slick.woff') format('woff'),url('./fonts/slick.ttf') format('truetype'),url('./fonts/slick.svg#slick') format('svg')}.slick-next,.slick-prev{font-size:0;line-height:0;position:absolute;top:50%;display:block;width:20px;height:20px;padding:0;-webkit-transform:translate(0,-50%);-ms-transform:translate(0,-50%);transform:translate(0,-50%);cursor:pointer;color:transparent;border:none;outline:0;background:0 0}.slick-next:focus,.slick-next:hover,.slick-prev:focus,.slick-prev:hover{color:transparent;outline:0;background:0 0}.slick-next:focus:before,.slick-next:hover:before,.slick-prev:focus:before,.slick-prev:hover:before{opacity:1}.slick-next.slick-disabled:before,.slick-prev.slick-disabled:before{opacity:.25}.slick-next:before,.slick-prev:before{font-family:slick;font-size:20px;line-height:1;opacity:.75;color:#fff;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.slick-prev{left:-25px}[dir=rtl] .slick-prev{right:-25px;left:auto}.slick-prev:before{content:'←'}[dir=rtl] .slick-prev:before{content:'→'}.slick-next{right:-25px}[dir=rtl] .slick-next{right:auto;left:-25px}.slick-next:before{content:'→'}[dir=rtl] .slick-next:before{content:'←'}.slick-dotted.slick-slider{margin-bottom:30px}.slick-dots{position:absolute;bottom:-25px;display:block;width:100%;padding:0;margin:0;list-style:none;text-align:center}.slick-dots li{position:relative;display:inline-block;width:20px;height:20px;margin:0 5px;padding:0;cursor:pointer}.slick-dots li button{font-size:0;line-height:0;display:block;width:20px;height:20px;padding:5px;cursor:pointer;color:transparent;border:0;outline:0;background:0 0}.slick-dots li button:focus,.slick-dots li button:hover{outline:0}.slick-dots li button:focus:before,.slick-dots li button:hover:before{opacity:1}.slick-dots li button:before{font-family:slick;font-size:6px;line-height:20px;position:absolute;top:0;left:0;width:20px;height:20px;content:'•';text-align:center;opacity:.25;color:#000;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.slick-dots li.slick-active button:before{opacity:.75;color:#000} diff --git a/themes/demo/assets/vendor/slick-carousel/slick-theme.less b/themes/demo/assets/vendor/slick-carousel/slick-theme.less new file mode 100644 index 0000000..e06fc18 --- /dev/null +++ b/themes/demo/assets/vendor/slick-carousel/slick-theme.less @@ -0,0 +1,168 @@ +@charset "UTF-8"; + +// Default Variables + +@slick-font-path: "./fonts/"; +@slick-font-family: "slick"; +@slick-loader-path: "./"; +@slick-arrow-color: white; +@slick-dot-color: black; +@slick-dot-color-active: @slick-dot-color; +@slick-prev-character: "←"; +@slick-next-character: "→"; +@slick-dot-character: "•"; +@slick-dot-size: 6px; +@slick-opacity-default: 0.75; +@slick-opacity-on-hover: 1; +@slick-opacity-not-active: 0.25; + +/* Slider */ +.slick-loading .slick-list{ + background: #fff url('@{slick-loader-path}ajax-loader.gif') center center no-repeat; +} + +/* Arrows */ +.slick-prev, +.slick-next { + position: absolute; + display: block; + height: 20px; + width: 20px; + line-height: 0px; + font-size: 0px; + cursor: pointer; + background: transparent; + color: transparent; + top: 50%; + -webkit-transform: translate(0, -50%); + -ms-transform: translate(0, -50%); + transform: translate(0, -50%); + padding: 0; + border: none; + outline: none; + &:hover, &:focus { + outline: none; + background: transparent; + color: transparent; + &:before { + opacity: @slick-opacity-on-hover; + } + } + &.slick-disabled:before { + opacity: @slick-opacity-not-active; + } +} + +.slick-prev:before, .slick-next:before { + font-family: @slick-font-family; + font-size: 20px; + line-height: 1; + color: @slick-arrow-color; + opacity: @slick-opacity-default; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + & when ( @slick-font-family = 'slick' ) { + /* Icons */ + @font-face { + font-family: 'slick'; + font-weight: normal; + font-style: normal; + src: url('@{slick-font-path}slick.eot'); + src: url('@{slick-font-path}slick.eot?#iefix') format('embedded-opentype'), url('@{slick-font-path}slick.woff') format('woff'), url('@{slick-font-path}slick.ttf') format('truetype'), url('@{slick-font-path}slick.svg#slick') format('svg'); + } + } +} + +.slick-prev { + left: -25px; + [dir="rtl"] & { + left: auto; + right: -25px; + } + &:before { + content: @slick-prev-character; + [dir="rtl"] & { + content: @slick-next-character; + } + } +} + +.slick-next { + right: -25px; + [dir="rtl"] & { + left: -25px; + right: auto; + } + &:before { + content: @slick-next-character; + [dir="rtl"] & { + content: @slick-prev-character; + } + } +} + +/* Dots */ + +.slick-dotted .slick-slider { + margin-bottom: 30px; +} + +.slick-dots { + position: absolute; + bottom: -25px; + list-style: none; + display: block; + text-align: center; + padding: 0; + margin: 0; + width: 100%; + li { + position: relative; + display: inline-block; + height: 20px; + width: 20px; + margin: 0 5px; + padding: 0; + cursor: pointer; + button { + border: 0; + background: transparent; + display: block; + height: 20px; + width: 20px; + outline: none; + line-height: 0px; + font-size: 0px; + color: transparent; + padding: 5px; + cursor: pointer; + &:hover, &:focus { + outline: none; + &:before { + opacity: @slick-opacity-on-hover; + } + } + &:before { + position: absolute; + top: 0; + left: 0; + content: @slick-dot-character; + width: 20px; + height: 20px; + font-family: @slick-font-family; + font-size: @slick-dot-size; + line-height: 20px; + text-align: center; + color: @slick-dot-color; + opacity: @slick-opacity-not-active; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + } + &.slick-active button:before { + color: @slick-dot-color-active; + opacity: @slick-opacity-default; + } + } +} diff --git a/themes/demo/assets/vendor/slick-carousel/slick-theme.scss b/themes/demo/assets/vendor/slick-carousel/slick-theme.scss new file mode 100644 index 0000000..7fe63e1 --- /dev/null +++ b/themes/demo/assets/vendor/slick-carousel/slick-theme.scss @@ -0,0 +1,194 @@ +@charset "UTF-8"; + +// Default Variables + +// Slick icon entity codes outputs the following +// "\2190" outputs ascii character "←" +// "\2192" outputs ascii character "→" +// "\2022" outputs ascii character "•" + +$slick-font-path: "./fonts/" !default; +$slick-font-family: "slick" !default; +$slick-loader-path: "./" !default; +$slick-arrow-color: white !default; +$slick-dot-color: black !default; +$slick-dot-color-active: $slick-dot-color !default; +$slick-prev-character: "\2190" !default; +$slick-next-character: "\2192" !default; +$slick-dot-character: "\2022" !default; +$slick-dot-size: 6px !default; +$slick-opacity-default: 0.75 !default; +$slick-opacity-on-hover: 1 !default; +$slick-opacity-not-active: 0.25 !default; + +@function slick-image-url($url) { + @if function-exists(image-url) { + @return image-url($url); + } + @else { + @return url($slick-loader-path + $url); + } +} + +@function slick-font-url($url) { + @if function-exists(font-url) { + @return font-url($url); + } + @else { + @return url($slick-font-path + $url); + } +} + +/* Slider */ + +.slick-list { + .slick-loading & { + background: #fff slick-image-url("ajax-loader.gif") center center no-repeat; + } +} + +/* Icons */ +@if $slick-font-family == "slick" { + @font-face { + font-family: "slick"; + src: slick-font-url("slick.eot"); + src: slick-font-url("slick.eot?#iefix") format("embedded-opentype"), slick-font-url("slick.woff") format("woff"), slick-font-url("slick.ttf") format("truetype"), slick-font-url("slick.svg#slick") format("svg"); + font-weight: normal; + font-style: normal; + } +} + +/* Arrows */ + +.slick-prev, +.slick-next { + position: absolute; + display: block; + height: 20px; + width: 20px; + line-height: 0px; + font-size: 0px; + cursor: pointer; + background: transparent; + color: transparent; + top: 50%; + -webkit-transform: translate(0, -50%); + -ms-transform: translate(0, -50%); + transform: translate(0, -50%); + padding: 0; + border: none; + outline: none; + &:hover, &:focus { + outline: none; + background: transparent; + color: transparent; + &:before { + opacity: $slick-opacity-on-hover; + } + } + &.slick-disabled:before { + opacity: $slick-opacity-not-active; + } + &:before { + font-family: $slick-font-family; + font-size: 20px; + line-height: 1; + color: $slick-arrow-color; + opacity: $slick-opacity-default; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } +} + +.slick-prev { + left: -25px; + [dir="rtl"] & { + left: auto; + right: -25px; + } + &:before { + content: $slick-prev-character; + [dir="rtl"] & { + content: $slick-next-character; + } + } +} + +.slick-next { + right: -25px; + [dir="rtl"] & { + left: -25px; + right: auto; + } + &:before { + content: $slick-next-character; + [dir="rtl"] & { + content: $slick-prev-character; + } + } +} + +/* Dots */ + +.slick-dotted.slick-slider { + margin-bottom: 30px; +} + +.slick-dots { + position: absolute; + bottom: -25px; + list-style: none; + display: block; + text-align: center; + padding: 0; + margin: 0; + width: 100%; + li { + position: relative; + display: inline-block; + height: 20px; + width: 20px; + margin: 0 5px; + padding: 0; + cursor: pointer; + button { + border: 0; + background: transparent; + display: block; + height: 20px; + width: 20px; + outline: none; + line-height: 0px; + font-size: 0px; + color: transparent; + padding: 5px; + cursor: pointer; + &:hover, &:focus { + outline: none; + &:before { + opacity: $slick-opacity-on-hover; + } + } + &:before { + position: absolute; + top: 0; + left: 0; + content: $slick-dot-character; + width: 20px; + height: 20px; + font-family: $slick-font-family; + font-size: $slick-dot-size; + line-height: 20px; + text-align: center; + color: $slick-dot-color; + opacity: $slick-opacity-not-active; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + } + &.slick-active button:before { + color: $slick-dot-color-active; + opacity: $slick-opacity-default; + } + } +} diff --git a/themes/demo/assets/vendor/slick-carousel/slick.css b/themes/demo/assets/vendor/slick-carousel/slick.css new file mode 100644 index 0000000..05282a3 --- /dev/null +++ b/themes/demo/assets/vendor/slick-carousel/slick.css @@ -0,0 +1 @@ +.slick-slider{position:relative;display:block;box-sizing:border-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-khtml-user-select:none;-ms-touch-action:pan-y;touch-action:pan-y;-webkit-tap-highlight-color:transparent}.slick-list{position:relative;display:block;overflow:hidden;margin:0;padding:0}.slick-list:focus{outline:0}.slick-list.dragging{cursor:pointer;cursor:hand}.slick-slider .slick-list,.slick-slider .slick-track{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.slick-track{position:relative;top:0;left:0;display:block;margin-left:auto;margin-right:auto}.slick-track:after,.slick-track:before{display:table;content:''}.slick-track:after{clear:both}.slick-loading .slick-track{visibility:hidden}.slick-slide{display:none;float:left;height:100%;min-height:1px}[dir=rtl] .slick-slide{float:right}.slick-slide img{display:block}.slick-slide.slick-loading img{display:none}.slick-slide.dragging img{pointer-events:none}.slick-initialized .slick-slide{display:block}.slick-loading .slick-slide{visibility:hidden}.slick-vertical .slick-slide{display:block;height:auto;border:1px solid transparent}.slick-arrow.slick-hidden{display:none} diff --git a/themes/demo/assets/vendor/slick-carousel/slick.js b/themes/demo/assets/vendor/slick-carousel/slick.js new file mode 100644 index 0000000..ac91b17 --- /dev/null +++ b/themes/demo/assets/vendor/slick-carousel/slick.js @@ -0,0 +1 @@ +!function(i){"use strict";"function"==typeof define&&define.amd?define(["jquery"],i):"undefined"!=typeof exports?module.exports=i(require("jquery")):i(jQuery)}((function(i){"use strict";var e,t=window.Slick||{};e=0,(t=function(t,o){var s,n=this;n.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:i(t),appendDots:i(t),arrows:!0,asNavFor:null,prevArrow:'',nextArrow:'',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(e,t){return i('',nextArrow:'',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(e,t){return i(' + + + +
    {% partial "calcresult" %}"
    \ No newline at end of file diff --git a/themes/demo/content/ajax/handler.txt b/themes/demo/content/ajax/handler.txt new file mode 100644 index 0000000..a0ceef1 --- /dev/null +++ b/themes/demo/content/ajax/handler.txt @@ -0,0 +1,21 @@ +function onTest() +{ + $value1 = input('value1'); + $value2 = input('value2'); + $operation = input('operation'); + + switch ($operation) { + case '+' : + $this['result'] = $value1 + $value2; + break; + case '-' : + $this['result'] = $value1 - $value2; + break; + case '*' : + $this['result'] = $value1 * $value2; + break; + default : + $this['result'] = $value2 != 0 ? round($value1 / $value2, 2) : 'NaN'; + break; + } +} \ No newline at end of file diff --git a/themes/demo/layouts/blog.htm b/themes/demo/layouts/blog.htm new file mode 100644 index 0000000..62299aa --- /dev/null +++ b/themes/demo/layouts/blog.htm @@ -0,0 +1,55 @@ +## +description = "Blog layout" + +[resources] +vars[activeBlogCategory] = "" +== + + + + {% partial 'site/meta' %} + + + + +
    + {% partial 'site/header' %} +
    + + +
    +
    + {% set pageTitle = placeholder('pageTitle') %} + {% if pageTitle %} +
    +

    {{ pageTitle }}

    +
    + {% endif %} +
    +
    +
    + {% page %} +
    +
    + +
    +
    + {% partial 'blog/sidebar' %} +
    +
    +
    +
    +
    + + +
    + {% partial 'site/footer' %} +
    + + + {% partial 'site/mobile' %} + + + {% partial 'site/how-its-made' %} + + diff --git a/themes/demo/layouts/default.htm b/themes/demo/layouts/default.htm new file mode 100644 index 0000000..3f717fd --- /dev/null +++ b/themes/demo/layouts/default.htm @@ -0,0 +1,32 @@ +## +description = "Default layout" +== + + + + {% partial 'site/meta' %} + + + + +
    + {% partial 'site/header' %} +
    + + +
    + {% page %} +
    + + +
    + {% partial 'site/footer' %} +
    + + + {% partial 'site/mobile' %} + + + {% partial 'site/how-its-made' %} + + diff --git a/themes/demo/layouts/home.htm b/themes/demo/layouts/home.htm new file mode 100644 index 0000000..f213da1 --- /dev/null +++ b/themes/demo/layouts/home.htm @@ -0,0 +1,46 @@ +## +description = "Default layout" +== + + + + {% partial 'site/meta' %} + + + + + + + + +
    + {% page %} +
    + + +
    + {% partial 'site/footer' %} +
    + + + {% partial 'site/mobile' %} + + + {% partial 'site/how-its-made' %} + + + diff --git a/themes/demo/layouts/wiki.htm b/themes/demo/layouts/wiki.htm new file mode 100644 index 0000000..eb69ed8 --- /dev/null +++ b/themes/demo/layouts/wiki.htm @@ -0,0 +1,44 @@ +## +description = "Wiki layout" +== + + + + {% partial 'site/meta' %} + + + + +
    + {% partial 'site/header' %} +
    + + +
    +
    +
    +
    +
    + {% partial 'wiki/sidebar' %} +
    +
    +
    + {% page %} +
    +
    +
    +
    + + +
    + {% partial 'site/footer' %} +
    + + + {% partial 'site/mobile' %} + + + {% partial 'site/how-its-made' %} + + + diff --git a/themes/demo/mix-manifest.json b/themes/demo/mix-manifest.json new file mode 100644 index 0000000..4fbf578 --- /dev/null +++ b/themes/demo/mix-manifest.json @@ -0,0 +1,28 @@ +{ + "/assets/vendor/codeblocks/codeblocks.min.js": "/assets/vendor/codeblocks/codeblocks.min.js", + "/assets/vendor/bootstrap/bootstrap.min.js": "/assets/vendor/bootstrap/bootstrap.min.js", + "/assets/vendor/bootstrap-icons/bootstrap-icons.css": "/assets/vendor/bootstrap-icons/bootstrap-icons.css", + "/assets/vendor/bootstrap/bootstrap.css": "/assets/vendor/bootstrap/bootstrap.css", + "/assets/vendor/jquery.min.js": "/assets/vendor/jquery.min.js", + "/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff": "/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff", + "/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2": "/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2", + "/assets/vendor/slick-carousel/ajax-loader.gif": "/assets/vendor/slick-carousel/ajax-loader.gif", + "/assets/vendor/slick-carousel/config.rb": "/assets/vendor/slick-carousel/config.rb", + "/assets/vendor/slick-carousel/fonts/slick.eot": "/assets/vendor/slick-carousel/fonts/slick.eot", + "/assets/vendor/slick-carousel/fonts/slick.svg": "/assets/vendor/slick-carousel/fonts/slick.svg", + "/assets/vendor/slick-carousel/fonts/slick.ttf": "/assets/vendor/slick-carousel/fonts/slick.ttf", + "/assets/vendor/slick-carousel/fonts/slick.woff": "/assets/vendor/slick-carousel/fonts/slick.woff", + "/assets/vendor/slick-carousel/slick-theme.css": "/assets/vendor/slick-carousel/slick-theme.css", + "/assets/vendor/slick-carousel/slick-theme.less": "/assets/vendor/slick-carousel/slick-theme.less", + "/assets/vendor/slick-carousel/slick-theme.scss": "/assets/vendor/slick-carousel/slick-theme.scss", + "/assets/vendor/slick-carousel/slick.css": "/assets/vendor/slick-carousel/slick.css", + "/assets/vendor/slick-carousel/slick.js": "/assets/vendor/slick-carousel/slick.js", + "/assets/vendor/slick-carousel/slick.less": "/assets/vendor/slick-carousel/slick.less", + "/assets/vendor/slick-carousel/slick.min.js": "/assets/vendor/slick-carousel/slick.min.js", + "/assets/vendor/slick-carousel/slick.scss": "/assets/vendor/slick-carousel/slick.scss", + "/assets/vendor/photoswipe/photoswipe.css": "/assets/vendor/photoswipe/photoswipe.css", + "/assets/vendor/photoswipe/photoswipe-lightbox.esm.min.js": "/assets/vendor/photoswipe/photoswipe-lightbox.esm.min.js", + "/assets/vendor/photoswipe/photoswipe.esm.min.js": "/assets/vendor/photoswipe/photoswipe.esm.min.js", + "/assets/vendor/photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.esm.js": "/assets/vendor/photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.esm.js", + "/assets/vendor/photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.css": "/assets/vendor/photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.css" +} diff --git a/themes/demo/package.json b/themes/demo/package.json new file mode 100644 index 0000000..f0dbf77 --- /dev/null +++ b/themes/demo/package.json @@ -0,0 +1,26 @@ +{ + "private": true, + "scripts": { + "dev": "npm run development", + "development": "mix", + "watch": "mix watch", + "watch-poll": "mix watch -- --watch-options-poll=1000", + "hot": "mix watch --hot", + "prod": "npm run production", + "production": "mix --production" + }, + "devDependencies": { + "laravel-mix": "^6.0.39", + "sass": "^1.45.0", + "sass-loader": "^12.1.0" + }, + "dependencies": { + "bootstrap": "^5.1.3", + "bootstrap-icons": "^1.7.2", + "codemirror": "^5.64.0", + "jquery": "^3.6.0", + "slick-carousel": "^1.8.1", + "photoswipe": "^5.2.4", + "photoswipe-dynamic-caption-plugin": "^1.1.1" + } +} diff --git a/themes/demo/pages/404.htm b/themes/demo/pages/404.htm new file mode 100644 index 0000000..7fef836 --- /dev/null +++ b/themes/demo/pages/404.htm @@ -0,0 +1,14 @@ +title = "Page Not Found (404)" +url = "/404" +layout = "default" + +[resources] +less[] = "pages/404.less" +vars[howItsMadeCmsTemplate] = 'cms:cms-page:404.htm' +== +
    + +
    diff --git a/themes/demo/pages/about.htm b/themes/demo/pages/about.htm new file mode 100644 index 0000000..1ae824e --- /dev/null +++ b/themes/demo/pages/about.htm @@ -0,0 +1,28 @@ +## +url = "/about" +layout = "default" +title = "About Page" +meta_title = "{{ landingPage.title }}" + +[section landingPage] +handle = "LandingPage" + +[resources] +vars[activeNavLink] = 'about' +vars[howItsMadeCmsTemplate] = 'cms:cms-page:about.htm' +vars[howItsMadeTailorBlueprint] = 'tailor:tailor-blueprint:landing/landing-page.yaml' +vars[howItsMadeTailorContent] = 'entries/landing_page' +== +{% put headerAfter %} +
    +
    +

    Hello! This is October CMS!

    +

    A company proving that making websites is not rocket science.

    +
    +
    +{% endput %} +
    + {% for block in landingPage.blocks %} + {% partial 'blocks/' ~ str_slug(block.type) block=block %} + {% endfor %} +
    diff --git a/themes/demo/pages/ajax.htm b/themes/demo/pages/ajax.htm new file mode 100644 index 0000000..d6a043c --- /dev/null +++ b/themes/demo/pages/ajax.htm @@ -0,0 +1,118 @@ +## +title = "AJAX Framework" +url = "/ajax" +layout = "default" +meta_title = "AJAX Framework" + +[resources] +less[] = "pages/ajax.less" +vars[blueFooterStyle] = 1 +vars[howItsMadeCmsTemplate] = 'cms:cms-page:ajax.htm' +== + +== +
    +
    +
    +
    +

    AJAX Framework

    +

    The built-in JavaScript framework provides simple but powerful AJAX capabilities. In most cases, you don't need to write JavaScript code to post data to the server and update elements of your page. The data- attributes can solve a lot of typical tasks. For more complex cases you can employ the full power of JavaScript. You can find more information in the documentation. Check out the calculator example below!

    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + +
    + + + + +
    + +
    + +
    + +
    + +
    +
    +
    +
    +
    +
    {% partial "calcresult" %}
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +

    The HTML markup for that example

    + +

    The markup defines a form with the inputs for numbers, operation and buttons. Note the data-request and data-request-update attributes on the FORM tag. Those two attributes tell the AJAX framework which PHP function must handle the request and what page element must be updated when the result comes back from the server.

    + + + +

    The calcresult partial

    + +

    The partial is referred in the form's data-request-update attribute together with the ID of the element that must be updated with the AJAX request. The partial is also rendered when the page first loads to display the default value.

    + +
    +
    {% content "ajax/calcresult.txt" %}
    +
    + +

    The onTest PHP function

    + +

    That PHP function is referred in the form's data-request attribute and acts as the AJAX handler. It loads the submitted values, performs the requested operation, and assigns the calculated value to the result page variable, which is then used in the calcresult partial. The function is defined right in the page file, in the PHP section.

    + + + +
    +
    +
    +
    +
    +
    diff --git a/themes/demo/pages/blog/archive.htm b/themes/demo/pages/blog/archive.htm new file mode 100644 index 0000000..d094f8e --- /dev/null +++ b/themes/demo/pages/blog/archive.htm @@ -0,0 +1,27 @@ +## +url = "/blog/archive/:year|(^[0-9]{4}$)/:month|(^0?[1-9]$)|(^1[0-2]$)" +title = "Blog Archive" +layout = "blog" + +[section blog] +handle = "Blog\Post" + +[resources] +vars[activeNavLink] = 'blog' +vars[howItsMadeCmsTemplate] = 'cms:cms-page:blog/archive.htm' +vars[howItsMadeTailorBlueprint] = 'tailor:tailor-blueprint:blog/post.yaml' +vars[howItsMadeTailorContent] = 'entries/blog_post' +== +{% set dateParsed = date('1-'~this.param.month~'-'~this.param.year) %} +{% set posts = blog + .where('published_at_year', this.param.year) + .where('published_at_month', this.param.month) + .get() +%} +{% put pageTitle = 'Articles from ' ~ dateParsed|date('F Y') %} + + diff --git a/themes/demo/pages/blog/author.htm b/themes/demo/pages/blog/author.htm new file mode 100644 index 0000000..ae26477 --- /dev/null +++ b/themes/demo/pages/blog/author.htm @@ -0,0 +1,47 @@ +## +url = "/blog/author/:slug" +layout = "default" +title = "Display a Blog Author" + +[section author] +handle = "Blog\Author" +entrySlug = "{{ :slug }}" + +[collection blog] +handle = "Blog\Post" + +[resources] +vars[activeNavLink] = 'blog' +vars[howItsMadeCmsTemplate] = 'cms:cms-page:blog/author.htm' +vars[howItsMadeTailorBlueprint] = 'tailor:tailor-blueprint:blog/author.yaml' +vars[howItsMadeTailorContent] = 'entries/blog_author/{{ author.id }}' +== +{% if author is empty %} + {% do abort(404) %} +{% endif %} + +{% set authorPosts = blog.whereRelation('author', 'slug', author.slug).paginate(16) %} +{% put pageTitle = author.title %} + +
    +
    +

    Posts by {{ author.title }}

    +
    + + + +
    diff --git a/themes/demo/pages/blog/category.htm b/themes/demo/pages/blog/category.htm new file mode 100644 index 0000000..bd3433e --- /dev/null +++ b/themes/demo/pages/blog/category.htm @@ -0,0 +1,34 @@ +## +url = "/blog/category/:slug" +layout = "blog" +title = "Display a Blog Category" + +[section category] +handle = "Blog\Category" +entrySlug = "{{ :slug }}" + +[collection blog] +handle = "Blog\Post" + +[resources] +vars[activeNavLink] = 'blog' +vars[activeBlogCategory] = "{{ :slug }}" +vars[howItsMadeCmsTemplate] = 'cms:cms-page:blog/category.htm' +vars[howItsMadeTailorBlueprint] = 'tailor:tailor-blueprint:blog/category.yaml' +vars[howItsMadeTailorContent] = 'entries/blog_category/{{ category.id }}' +== +{% if category is empty %} + {% do abort(404) %} +{% endif %} + +{% set posts = blog.whereRelation('categories', 'slug', category.slug).paginate(16) %} +{% put pageTitle = 'Articles in ' ~ category.title %} + + + diff --git a/themes/demo/pages/blog/index.htm b/themes/demo/pages/blog/index.htm new file mode 100644 index 0000000..a6550c3 --- /dev/null +++ b/themes/demo/pages/blog/index.htm @@ -0,0 +1,31 @@ +## +url = "/blog" +layout = "blog" +title = "Blog Homepage" + +[collection blog] +handle = "Blog\Post" + +[global blogConfig] +handle = "Blog\Config" + +[resources] +vars[activeNavLink] = 'blog' +vars[howItsMadeCmsTemplate] = 'cms:cms-page:blog/index.htm' +vars[howItsMadeTailorBlueprint] = 'tailor:tailor-blueprint:blog/post.yaml' +vars[howItsMadeTailorContent] = 'entries/blog_post' +== +{% set posts = blog.paginate(5) %} +{% set archiveDates = blog + .selectRaw("count(*) as post_count, published_at_month, published_at_year") + .groupBy('published_at_month', 'published_at_year').get() +%} +{% put pageTitle = blogConfig.blog_name ?: 'Blog' %} + +{% for post in posts %} + {% partial 'blog/post-card' post=post bannerCss='banner-lg' %} +{% endfor %} + + diff --git a/themes/demo/pages/blog/post.htm b/themes/demo/pages/blog/post.htm new file mode 100644 index 0000000..ffe5559 --- /dev/null +++ b/themes/demo/pages/blog/post.htm @@ -0,0 +1,87 @@ +## +url = "/blog/post/:slug" +layout = "blog" +title = "Display a Blog Post" +meta_title = "{{ blog.title }} - Blog" + +[section blog] +handle = "Blog\Post" +entrySlug = "{{ :slug }}" + +[collection blogCategories] +handle = "Blog\Category" + +[resources] +vars[activeNavLink] = 'blog' +vars[howItsMadeCmsTemplate] = 'cms:cms-page:blog/post.htm' +vars[howItsMadeTailorBlueprint] = 'tailor:tailor-blueprint:blog/post.yaml' +vars[howItsMadeTailorContent] = 'entries/blog_post/{{ blog.id }}' +== +{% set post = blog %} +{% if post is empty %} + {% do abort(404) %} +{% endif %} + +
    + {% if post.banner %} + + {% else %} + + {% endif %} + +
    +

    + {{ post.title }} +

    + + {% if post.entry_type == 'markdown_post' %} + {{ post.content|md|content }} + {% else %} + {{ post.content|content }} + {% endif %} + +
    + {% partial 'controls/image-carousel' gallery=post.gallery %} +
    + +
    +
    + +
    +
    +
    + {% partial 'share-button' %} +
    +
    +
    +
    + {% if post.author %} +
    +
    + {% partial 'elements/user-panel-author' user=post.author %} +
    + {% endif %} +
    +
    + {% partial 'blog/comment-list' %} +
    +
    +
    + {% partial 'blog/comment-form' %} +
    +
    diff --git a/themes/demo/pages/blog/rss.htm b/themes/demo/pages/blog/rss.htm new file mode 100644 index 0000000..7b7fe11 --- /dev/null +++ b/themes/demo/pages/blog/rss.htm @@ -0,0 +1,27 @@ +## +url = "/blog/rss" +title = "Blog RSS Feed" + +[collection blog] +handle = "Blog\Post" + +[resources] +headers[Content-Type] = 'text/xml' +== + + + + {{ this.page.meta_title ?: this.page.title }} + {{ 'blog/index'|page }} + {{ this.page.meta_description ?: this.page.description }} + + {% for post in blog %} + {{ post.title }} + {{ 'blog/post'|page({ slug: post.slug }) }} + {{ post.slug }} + {{ post.published_at_date.toRfc2822String }} + {{ post.featured_text }} + + {% endfor %} + + diff --git a/themes/demo/pages/blog/search.htm b/themes/demo/pages/blog/search.htm new file mode 100644 index 0000000..b319952 --- /dev/null +++ b/themes/demo/pages/blog/search.htm @@ -0,0 +1,45 @@ +## +url = "/blog/search" +layout = "default" +title = "Search Blog Posts" +meta_title = "Search - Blog" + +[collection blog] +handle = "Blog\Post" + +[resources] +vars[activeNavLink] = 'blog' +vars[howItsMadeCmsTemplate] = 'cms:cms-page:blog/search.htm' +vars[howItsMadeTailorBlueprint] = 'tailor:tailor-blueprint:blog/post.yaml' +vars[howItsMadeTailorContent] = 'entries/blog_post' +== +{% set searchTerm = get('term')|trim %} +{% set posts = blog.searchWhere(searchTerm, ['title', 'content']).paginate(16) %} +{% put pageTitle=searchTerm ~ ' - Search Results' %} + +
    +
    +

    {{ searchTerm }} - Search Results

    +
    +
    +
    +
    +
    + +
    +
    + + + +
    +
    +
    diff --git a/themes/demo/pages/components.htm b/themes/demo/pages/components.htm new file mode 100644 index 0000000..001af23 --- /dev/null +++ b/themes/demo/pages/components.htm @@ -0,0 +1,58 @@ +## +title = "Components Demo" +url = "/components" +layout = "default" +meta_title = "CMS Component Demo" + +[demoTodo] +max = 3 +addDefault = 1 + +[resources] +vars[activeNavLink] = 'demo' +vars[blueFooterStyle] = 1 +less[] = "pages/components.less" +vars[howItsMadeCmsTemplate] = 'cms:cms-page:components.htm' +== +
    +
    +
    +
    +

    CMS Component Demo

    +

    Plugins can provide CMS components, simple building blocks that can enrich pages, layouts, and partials. Check out the To Do example below.

    +
    +
    +
    +
    + {% component 'demoTodo' %} +
    +
    +
    +
    + + +
    +
    +
    +
    +

    HTML Markup for that example

    + +
    +
    {% autoescape %}{{ "{% component 'demoTodo' %}" }}{% endautoescape %}
    +
    + +

    Wait, only one line is needed? Yes! CMS components are simple building blocks that can be used with a small amount of code. Components encapsulate PHP code and partials and can be included in a page, layout or partial with a single line of code. By sharing plugins between multiple projects, you can reuse CMS components and be more productive. The demoTodo component used here is provided by the plugin called October\Demo, you can find it in the plugins/october/demo folder.

    + + +
    +
    +
    +
    +
    +
    diff --git a/themes/demo/pages/contact.htm b/themes/demo/pages/contact.htm new file mode 100644 index 0000000..2e84b87 --- /dev/null +++ b/themes/demo/pages/contact.htm @@ -0,0 +1,65 @@ +## +title = "Contact Us" +url = "/contact" +layout = "default" +meta_title = "Get in touch!" + +[resources] +vars[activeNavLink] = 'contact' +vars[blueFooterStyle] = 1 +less[] = "pages/contact.less" +vars[howItsMadeCmsTemplate] = 'cms:cms-page:contact.htm' +== +
    +
    +
    +

    Ready for something new? Get in touch!

    +

    Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.

    + +
    +
    +
    + +
    +
    +

    Address

    +

    Cupertino, California, United States

    +
    +
    +
    +
    + +
    +
    +

    Email

    +

    example@example.tld

    +
    +
    +
    +
    + +
    +
    +

    Phone

    +

    0 (123) 456 7890

    +
    +
    +
    +
    +
    + Team Shot +
    +
    +
    + +
    +
    +
    +
    + {% partial 'about/contact-form' %} +
    +
    +
    +
    +
    +
    diff --git a/themes/demo/pages/error.htm b/themes/demo/pages/error.htm new file mode 100644 index 0000000..9a9e8ad --- /dev/null +++ b/themes/demo/pages/error.htm @@ -0,0 +1,14 @@ +title = "Error Page (500)" +url = "/error" +layout = "default" + +[resources] +less[] = "pages/404.less" +vars[howItsMadeCmsTemplate] = 'cms:cms-page:error.htm' +== +
    + +
    diff --git a/themes/demo/pages/index.htm b/themes/demo/pages/index.htm new file mode 100644 index 0000000..fabf950 --- /dev/null +++ b/themes/demo/pages/index.htm @@ -0,0 +1,145 @@ +## +title = "Demonstration" +url = "/" +layout = "home" +meta_title = "Welcome" + +[collection blog] +handle = "Blog\Post" + +[resources] +less[] = "pages/index.less" +vars[howItsMadeCmsTemplate] = 'cms:cms-page:index.htm' +== +{% set latestPosts = blog.limit(3).get %} + +
    +
    +
    +
    +
    +

    Welcome to October CMS!

    +

    + This is the October CMS demo theme that explores the core features. You can use it as a foundation for your new website. +

    +

    + {% if backendUrl %} + + Explore the Backend Area + + {% else %} + + Explore the Platform Features + + {% endif %} +

    +
    +
    + +
    +
    + Product Shot +
    +
    +
    +
    +
    +
    +
    + + +
    +
    + October CMS +

    About This Page

    +

    + This page demonstrates the basic CMS features. Usually each page built with October CMS is a combination of a layout, page, partials and content blocks, although in simple cases you can just use a page without anything else. +

    +
    +
    + +
    +
    +
    +
    +
    +

    CMS Feature

    +

    Layouts

    +

    Layouts define the page scaffold. Layout files include everything that repeats on each page, such as the HTML, HEAD and BODY tags, CSS and JavaScript references. The page menu and footer in the Demo theme are defined in the layout as well. Layouts are optional — you can define everything right in a page file.

    + Learn more about Layouts +
    +
    +
    +
    + CMS Layouts +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + CMS Pages +
    +
    +
    +
    +

    Included

    +

    Pages

    +

    Pages hold the content for each URL. A page file defines the page URL and the page content. Pages are rendered inside layouts with the page tag that should be called in the layout code.

    + Learn more about Pages +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +

    CMS Feature

    +

    Partials

    +

    + Partials contain chunks of HTML code that are used anywhere throughout your website. They allow you to simplify the code of complex pages and reuse code in multiple places. + Also, partials are an important part of the built-in AJAX framework. +

    + Learn more about Partials +
    +
    +
    +
    + CMS Layouts +
    +
    +
    +
    +
    + +
    +
    +

    There are more great CMS features!

    +

    Visit the October CMS Documentation website to learn everything about the CMS features.

    + Learn more about October CMS +
    +
    +
    +
    +
    + +
    +
    +

    Latest News

    + + +
    +
    diff --git a/themes/demo/pages/sitemap.htm b/themes/demo/pages/sitemap.htm new file mode 100644 index 0000000..8f8676a --- /dev/null +++ b/themes/demo/pages/sitemap.htm @@ -0,0 +1,42 @@ +## +title = "Sitemap" +url = "/sitemap.xml" + +[resources] +headers[Content-Type] = 'application/xml' + +[collection sitemap] +handle = "Site\Sitemap" +== +{% macro render_sitemap_item(item, reference, isRoot) %} + {% import _self as nav %} + {% set hideRootItem = isRoot and item.replace %} + {% if reference.url and not hideRootItem %} + + {{ reference.url }} + {{ reference.mtime|date('c') }} + {{ item.changefreq }} + {{ item.priority }} + + {% endif %} + {% if reference.items %} + {% for child in reference.items %} + {{ nav.render_sitemap_item(item, child) }} + {% endfor %} + {% endif %} +{% endmacro %} +{% import _self as nav %} + + {% for item in sitemap %} + {{ nav.render_sitemap_item( + item, + link(item.reference, { nesting: item.nesting }), + true + ) }} + {% endfor %} + diff --git a/themes/demo/pages/wiki/article.htm b/themes/demo/pages/wiki/article.htm new file mode 100644 index 0000000..555d916 --- /dev/null +++ b/themes/demo/pages/wiki/article.htm @@ -0,0 +1,59 @@ +## +url = "/wiki/:slug*" +layout = "wiki" +title = "Wiki Article" +meta_title = "{{ wiki.title }}" + +[section wiki] +handle = "Wiki\Article" +entrySlug = "{{ :slug }}" + +[resources] +vars[activeNavLink] = 'wiki' +vars[howItsMadeCmsTemplate] = 'cms:cms-page:wiki/article.htm' +vars[howItsMadeTailorBlueprint] = 'tailor:tailor-blueprint:wiki/article.yaml' +vars[howItsMadeTailorContent] = 'entries/wiki_article/{{ wiki.id }}' +== +{% set article = wiki %} +{% if article is empty %} + {% do abort(404) %} +{% endif %} + +
    + +
    + {% partial 'wiki/breadcrumb' article=article %} +
    + +
    +

    {{ article.title }}

    +

    {{ article.summary_text }}

    + +
    + {% if article.banner %} +
    + {% else %} +
    + {% endif %} +
    + + {{ article.content|raw }} + +
    + {% partial 'controls/image-carousel' gallery=article.gallery %} +
    +
    + + {% partial 'wiki/continue' article=article %} + + {% if article.external_links %} +
    +

    External Links

    + + {% endif %} + +
    diff --git a/themes/demo/pages/wiki/index.htm b/themes/demo/pages/wiki/index.htm new file mode 100644 index 0000000..4fb8e1a --- /dev/null +++ b/themes/demo/pages/wiki/index.htm @@ -0,0 +1,43 @@ +## +url = "/wiki" +layout = "wiki" +title = "Wiki Docs Demo" +meta_title = "Wiki" + +[collection wiki] +handle = "Wiki\Article" + +[resources] +vars[activeNavLink] = 'wiki' +vars[howItsMadeCmsTemplate] = 'cms:cms-page:wiki/index.htm' +vars[howItsMadeTailorBlueprint] = 'tailor:tailor-blueprint:wiki/article.yaml' +vars[howItsMadeTailorContent] = 'entries/wiki_article' +== +{% set article = wiki.first() %} + +
    +
    +

    {{ article.title }}

    +

    {{ article.summary_text }}

    + +
    + {% if article.banner %} +
    + {% else %} +
    + {% endif %} +
    + + {{ article.content|raw }} +
    + + {% if article.external_links %} +
    +

    External Links

    + + {% endif %} +
    diff --git a/themes/demo/pages/wiki/search.htm b/themes/demo/pages/wiki/search.htm new file mode 100644 index 0000000..da7a75a --- /dev/null +++ b/themes/demo/pages/wiki/search.htm @@ -0,0 +1,52 @@ +## +url = "/wiki/search" +layout = "default" +title = "Search Wiki Articles" +meta_title = "Search - Wiki" + +[collection wiki] +handle = "Wiki\Article" + +[resources] +vars[activeNavLink] = "wiki" +vars[howItsMadeCmsTemplate] = 'cms:cms-page:wiki/search.htm' +vars[howItsMadeTailorBlueprint] = 'tailor:tailor-blueprint:wiki/article.yaml' +vars[howItsMadeTailorContent] = 'entries/wiki_article' +== +{% set searchTerm = get('term')|trim %} +{% set articles = wiki.searchWhere(searchTerm, ['title', 'content']).paginate(4) %} +{% put pageTitle=searchTerm ~ ' - Search Results' %} + +
    +
    +

    {{ searchTerm }} - Search Results

    +
    +
    +
    +
    +
    + +
    +
    + +
    + {% for article in articles %} +
    +
    +
    + {{ article.title }} +
    + {{ article.content|html_limit(250)|raw }} +
    +
    + {% endfor %} +
    + +
    +
    +
    diff --git a/themes/demo/partials/about/contact-form.htm b/themes/demo/partials/about/contact-form.htm new file mode 100644 index 0000000..068698e --- /dev/null +++ b/themes/demo/partials/about/contact-form.htm @@ -0,0 +1,34 @@ +
    +

    Drop Us a Line

    +

    Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

    + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    + +
    +
    +
    +
    diff --git a/themes/demo/partials/blocks/detailed-block.htm b/themes/demo/partials/blocks/detailed-block.htm new file mode 100644 index 0000000..1bb1cb7 --- /dev/null +++ b/themes/demo/partials/blocks/detailed-block.htm @@ -0,0 +1,27 @@ +{% set blockImage = block.image ? block.image|media : 'assets/images/about-team.png'|theme %} + +
    +
    +
    +

    {{ block.title }}

    + {{ block.content|raw }} + + {% if block.list_items %} +
      + {% for item in block.list_items %} +
    • {{ item.text }}
    • + {% endfor %} +
    + {% endif %} + +

    + + {{ block.button_text }} + +

    +
    +
    + +
    +
    +
    diff --git a/themes/demo/partials/blocks/image-slice.htm b/themes/demo/partials/blocks/image-slice.htm new file mode 100644 index 0000000..3eb96e5 --- /dev/null +++ b/themes/demo/partials/blocks/image-slice.htm @@ -0,0 +1,8 @@ +## +[resources] +less[] = "blocks/hero-image.less" +== +{% set heroImage = block.image ? block.image|media : 'assets/images/stock/desks-cropped.png'|theme %} + +
    +
    diff --git a/themes/demo/partials/blocks/paragraph-block.htm b/themes/demo/partials/blocks/paragraph-block.htm new file mode 100644 index 0000000..9543a93 --- /dev/null +++ b/themes/demo/partials/blocks/paragraph-block.htm @@ -0,0 +1,13 @@ +{% set blockImage = block.image ? block.image|media : 'assets/images/about-chart.png'|theme %} + +
    +

    {{ block.title }}

    +
    +
    + {{ block.content|raw }} +
    +
    + +
    +
    +
    diff --git a/themes/demo/partials/blocks/scoreboard-metrics.htm b/themes/demo/partials/blocks/scoreboard-metrics.htm new file mode 100644 index 0000000..1f34e91 --- /dev/null +++ b/themes/demo/partials/blocks/scoreboard-metrics.htm @@ -0,0 +1,18 @@ +## +[resources] +less[] = "blocks/scoreboard-metrics.less" +== +
    +
    +
    + {% for metric in block.metrics|default([]) %} +
    + +

    {{ metric.number }}

    +

    {{ metric.description }}

    +
    + {% endfor %} +
    +
    +
    +
    diff --git a/themes/demo/partials/blocks/team-leaders.htm b/themes/demo/partials/blocks/team-leaders.htm new file mode 100644 index 0000000..8cba0c1 --- /dev/null +++ b/themes/demo/partials/blocks/team-leaders.htm @@ -0,0 +1,29 @@ +## +[resources] +less[] = "blocks/team-leaders.less" +js[] = "blocks/team-leaders.js" +== +
    +
    +
    +

    Meet the Team!

    +

    Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.

    +
    +
    +
    + +
    +
    +
    + {% for member in block.members|default([]) %} +
    +
    +
    + {% partial 'elements/user-panel-team' user=member %} +
    +
    +
    + {% endfor %} +
    +
    +
    diff --git a/themes/demo/partials/blog/comment-form.htm b/themes/demo/partials/blog/comment-form.htm new file mode 100644 index 0000000..a1383fe --- /dev/null +++ b/themes/demo/partials/blog/comment-form.htm @@ -0,0 +1,32 @@ +
    +

    Tell us what you think!

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

    + You are replying to Mary Williams. You can post a new comment instead. +

    +
    +
    +
    diff --git a/themes/demo/partials/blog/comment-list.htm b/themes/demo/partials/blog/comment-list.htm new file mode 100644 index 0000000..458faa0 --- /dev/null +++ b/themes/demo/partials/blog/comment-list.htm @@ -0,0 +1,10 @@ +
    +

    2 comments

    + +
    + {% partial 'elements/user-panel' user={ title:'Andy Anderson', role:'', slug:'', avatar:null } %} +
    +
    + {% partial 'elements/user-panel' user={ title:'Mary Williams', role:'', slug:'', avatar:null } %} +
    +
    diff --git a/themes/demo/partials/blog/post-card.htm b/themes/demo/partials/blog/post-card.htm new file mode 100644 index 0000000..aa8b059 --- /dev/null +++ b/themes/demo/partials/blog/post-card.htm @@ -0,0 +1,49 @@ +
    +
    + {% if post.banner %} +
    + {% else %} +
    + {% endif %} + +
    + {% if post.categories %} +
    + +
    + {% endif %} + +

    + {{ post.title }} +

    + +
    +

    {{ post.featured_text }}

    +
    +
    + + +
    +
    diff --git a/themes/demo/partials/blog/sidebar.htm b/themes/demo/partials/blog/sidebar.htm new file mode 100644 index 0000000..ff8b4bf --- /dev/null +++ b/themes/demo/partials/blog/sidebar.htm @@ -0,0 +1,68 @@ +## +[collection blog] +handle = "Blog\Post" + +[collection blogCategories] +handle = "Blog\Category" + +[global blogConfig] +handle = "Blog\Config" +== +{% set archiveDates = blog + .selectRaw("count(*) as post_count, published_at_month, published_at_year") + .groupBy('published_at_month', 'published_at_year').get() +%} + + + + + + + + + + + diff --git a/themes/demo/partials/calcresult.htm b/themes/demo/partials/calcresult.htm new file mode 100644 index 0000000..6c66cc8 --- /dev/null +++ b/themes/demo/partials/calcresult.htm @@ -0,0 +1 @@ +{{ result|default(75) }} \ No newline at end of file diff --git a/themes/demo/partials/controls/image-carousel.htm b/themes/demo/partials/controls/image-carousel.htm new file mode 100644 index 0000000..c989e18 --- /dev/null +++ b/themes/demo/partials/controls/image-carousel.htm @@ -0,0 +1,35 @@ +## +[resources] +js[] = "controls/image-carousel.js" +less[] = "controls/image-carousel.less" +== +{% set galleryId = 'carousel' ~ random() %} + +
    + {% if gallery %} + {% for image in gallery %} +
    +
    + + + +
    +

    {{ image.title }}

    +

    {{ image.description }}

    +
    +
    +
    + {% endfor %} + {% else %} + {% for defaultImage in ['workspace', 'desktop', 'pancakes', 'doughnuts'] %} + {% set image = ('assets/images/stock/' ~ defaultImage ~ '.png')|theme %} +
    +
    + + + +
    +
    + {% endfor %} + {% endif %} +
    diff --git a/themes/demo/partials/elements/social-links.htm b/themes/demo/partials/elements/social-links.htm new file mode 100644 index 0000000..de0c5be --- /dev/null +++ b/themes/demo/partials/elements/social-links.htm @@ -0,0 +1,18 @@ + diff --git a/themes/demo/partials/elements/user-panel-author.htm b/themes/demo/partials/elements/user-panel-author.htm new file mode 100644 index 0000000..bc0baad --- /dev/null +++ b/themes/demo/partials/elements/user-panel-author.htm @@ -0,0 +1,30 @@ +
    +
    +
    +
    + {% if user.avatar %} + {{ user.title }} + {% else %} + {{ user.title }} + {% endif %} +
    +
    +

    {{ user.title }}

    +

    {{ user.role }}

    +
    +
    + {% if not hideAllPosts %} + + {% endif %} +
    + +
    + {% partial 'elements/social-links' links=user.social_links %} +
    +
    diff --git a/themes/demo/partials/elements/user-panel-team.htm b/themes/demo/partials/elements/user-panel-team.htm new file mode 100644 index 0000000..89b3277 --- /dev/null +++ b/themes/demo/partials/elements/user-panel-team.htm @@ -0,0 +1,23 @@ +
    +
    + {% if user.avatar %} + {{ user.title }} + {% else %} + {{ user.title }} + {% endif %} +
    +
    +

    {{ user.title }}

    +

    + {{ user.role }} +

    +
    + +
    + {% partial 'elements/social-links' links=user.social_links %} +
    + + +
    diff --git a/themes/demo/partials/elements/user-panel.htm b/themes/demo/partials/elements/user-panel.htm new file mode 100644 index 0000000..1e9be08 --- /dev/null +++ b/themes/demo/partials/elements/user-panel.htm @@ -0,0 +1,27 @@ +
    +
    +
    +
    + {% if user.avatar %} + {{ user.title }} + {% else %} + {{ user.title }} + {% endif %} +
    +
    +

    {{ user.title }}

    +

    + March 12, 2022 +

    +
    +
    + +
    + +
    diff --git a/themes/demo/partials/helpers/random-avatar-image.htm b/themes/demo/partials/helpers/random-avatar-image.htm new file mode 100644 index 0000000..29f2e7a --- /dev/null +++ b/themes/demo/partials/helpers/random-avatar-image.htm @@ -0,0 +1,7 @@ +{% set images = [ + 'avatar-1', + 'avatar-2', + 'avatar-3', + 'avatar-4', + 'avatar-5' +] %}{{ ('assets/images/avatars/' ~ random(images) ~ '.png')|theme }} diff --git a/themes/demo/partials/helpers/random-stock-image.htm b/themes/demo/partials/helpers/random-stock-image.htm new file mode 100644 index 0000000..b0274a1 --- /dev/null +++ b/themes/demo/partials/helpers/random-stock-image.htm @@ -0,0 +1,6 @@ +{% set images = [ + 'workspace', + 'desktop', + 'pancakes', + 'doughnuts' +] %}{{ ('assets/images/stock/' ~ random(images) ~ '.png')|theme }} diff --git a/themes/demo/partials/share-button.htm b/themes/demo/partials/share-button.htm new file mode 100644 index 0000000..98796a8 --- /dev/null +++ b/themes/demo/partials/share-button.htm @@ -0,0 +1,28 @@ + + diff --git a/themes/demo/partials/site/footer.htm b/themes/demo/partials/site/footer.htm new file mode 100644 index 0000000..4c88507 --- /dev/null +++ b/themes/demo/partials/site/footer.htm @@ -0,0 +1,104 @@ + \ No newline at end of file diff --git a/themes/demo/partials/site/header.htm b/themes/demo/partials/site/header.htm new file mode 100644 index 0000000..bd43f49 --- /dev/null +++ b/themes/demo/partials/site/header.htm @@ -0,0 +1,24 @@ + +{% placeholder headerBefore %} + +
    + +
    +{% placeholder headerAfter %} diff --git a/themes/demo/partials/site/how-its-made.htm b/themes/demo/partials/site/how-its-made.htm new file mode 100644 index 0000000..f942e88 --- /dev/null +++ b/themes/demo/partials/site/how-its-made.htm @@ -0,0 +1,19 @@ +[backendLink] +== +{% if backendUrl and howItsMadeCmsTemplate %} +
    +
    +

    Wondering how this page is made? View the + {% if howItsMadeCmsTemplate|default(false) %} + CMS Template + {% endif %} + {% if howItsMadeTailorBlueprint|default(false) %} + • Tailor Blueprint + {% endif %} + {% if howItsMadeTailorContent|default(false) %} + • Tailor Content + {% endif %} +

    +
    +
    +{% endif %} diff --git a/themes/demo/partials/site/meta.htm b/themes/demo/partials/site/meta.htm new file mode 100644 index 0000000..991f9e1 --- /dev/null +++ b/themes/demo/partials/site/meta.htm @@ -0,0 +1,33 @@ + +October CMS - {{ this.page.meta_title ?: placeholder('pageTitle') }} + + + + + + + + + + + + + +{% styles %} + + + + + +{% framework extras turbo %} +{% scripts %} + + diff --git a/themes/demo/partials/site/mobile.htm b/themes/demo/partials/site/mobile.htm new file mode 100644 index 0000000..a3a197e --- /dev/null +++ b/themes/demo/partials/site/mobile.htm @@ -0,0 +1,12 @@ + diff --git a/themes/demo/partials/site/nav.htm b/themes/demo/partials/site/nav.htm new file mode 100644 index 0000000..dba9668 --- /dev/null +++ b/themes/demo/partials/site/nav.htm @@ -0,0 +1,40 @@ +[backendLink] +[sitePicker] +== +{% set activeNavLink = activeNavLink|default(this.page.id) %} + + + + + + +{% if sitePicker.isEnabled %} + +{% elseif backendUrl %} + +{% endif %} diff --git a/themes/demo/partials/wiki/article-toc.htm b/themes/demo/partials/wiki/article-toc.htm new file mode 100644 index 0000000..bf03924 --- /dev/null +++ b/themes/demo/partials/wiki/article-toc.htm @@ -0,0 +1,19 @@ +{% macro render_toc(articles) %} + {% for article in articles %} +
  • + {{ article.title }} + - {{ article.summary_text }} +
      + {% if article.children %} + {{ _self.render_toc(article.children) }} + {% endif %} +
    +
  • + {% endfor %} +{% endmacro %} + +{% import _self as nav %} + +
      + {{ nav.render_toc(articles) }} +
    diff --git a/themes/demo/partials/wiki/breadcrumb.htm b/themes/demo/partials/wiki/breadcrumb.htm new file mode 100644 index 0000000..d6440d9 --- /dev/null +++ b/themes/demo/partials/wiki/breadcrumb.htm @@ -0,0 +1,19 @@ +{% macro render_breadcrumb(article) %} + {% if article.parent %} + {{ _self.render_breadcrumb(article.parent) }} + + {% endif %} +{% endmacro %} + +{% import _self as nav %} + + diff --git a/themes/demo/partials/wiki/continue.htm b/themes/demo/partials/wiki/continue.htm new file mode 100644 index 0000000..d0d7feb --- /dev/null +++ b/themes/demo/partials/wiki/continue.htm @@ -0,0 +1,30 @@ +{% set parent = article.parent %} + +
      + {% if parent %} + {% set prevLink = null %} + {% set nextLink = null %} + {% for sibling in parent.children %} + {% if nextLink == true %} +
    • + Next: {{ sibling.title }} +
    • + {% set nextLink = null %} + {% endif %} + + {% if sibling.id == article.id %} + {% if prevLink %} +
    • + Previous: {{ prevLink.title }} +
    • + {% endif %} + {% set nextLink = true %} + {% endif %} + {% set prevLink = sibling %} + {% endfor %} + +
    • + Return to {{ parent.title }} +
    • + {% endif %} +
    diff --git a/themes/demo/partials/wiki/sidebar-toc.htm b/themes/demo/partials/wiki/sidebar-toc.htm new file mode 100644 index 0000000..ac40d70 --- /dev/null +++ b/themes/demo/partials/wiki/sidebar-toc.htm @@ -0,0 +1,23 @@ +{% macro render_toc(articles, activeSlug) %} + {% for article in articles %} + {% set hasChildren = article.children %} + {% set isActive = article.slug == activeSlug %} +
  • + + {{ article.title }} + {% if hasChildren %} +
      + {% if article.children %} + {{ _self.render_toc(article.children, activeSlug) }} + {% endif %} +
    + {% endif %} +
  • + {% endfor %} +{% endmacro %} + +{% import _self as nav %} + +
      + {{ nav.render_toc(articles, activeSlug|default(this.param.slug|default(''))) }} +
    diff --git a/themes/demo/partials/wiki/sidebar.htm b/themes/demo/partials/wiki/sidebar.htm new file mode 100644 index 0000000..10300fa --- /dev/null +++ b/themes/demo/partials/wiki/sidebar.htm @@ -0,0 +1,20 @@ +## + +[collection wiki] +handle = "Wiki\Article" +== +{% set articles = wiki.getNested() %} + + + + diff --git a/themes/demo/seeds/blueprints/blog/author.yaml b/themes/demo/seeds/blueprints/blog/author.yaml new file mode 100644 index 0000000..c76eff1 --- /dev/null +++ b/themes/demo/seeds/blueprints/blog/author.yaml @@ -0,0 +1,30 @@ +uuid: 6947ff28-b660-47d7-9240-24ca6d58aeae +handle: Blog\Author +type: entry +name: Author +drafts: false + +navigation: + parent: Blog\Post + icon: octo-icon-user + order: 200 + +fields: + avatar: + label: Avatar + type: mediafinder + mode: image + + role: + label: Role + type: text + + about: + label: About + type: textarea + + _social_links: + type: mixin + label: Social Links + source: Fields\SocialLinks + tab: Social diff --git a/themes/demo/seeds/blueprints/blog/category.yaml b/themes/demo/seeds/blueprints/blog/category.yaml new file mode 100644 index 0000000..528c246 --- /dev/null +++ b/themes/demo/seeds/blueprints/blog/category.yaml @@ -0,0 +1,17 @@ +uuid: b022a74b-15e6-4c6b-9eb9-17efc5103543 +type: structure +handle: Blog\Category +name: Category +drafts: false + +structure: + maxDepth: 1 + +navigation: + parent: Blog\Post + icon: octo-icon-list-ul + order: 150 + +fields: + description: + label: Description diff --git a/themes/demo/seeds/blueprints/blog/config.yaml b/themes/demo/seeds/blueprints/blog/config.yaml new file mode 100644 index 0000000..b1fdf6e --- /dev/null +++ b/themes/demo/seeds/blueprints/blog/config.yaml @@ -0,0 +1,32 @@ +uuid: 3328c303-7989-462e-b866-27e7037ba275 +handle: Blog\Config +type: global +name: Blog Settings + +navigation: + parent: Blog\Post + icon: octo-icon-cog + order: 200 + +fields: + blog_name: + label: Blog Name + tab: General + placeholder: Latest News + + about_this_blog: + label: About This Blog + comment: Customize this section to tell your visitors a little bit about your publication, writers, content, or something else entirely. Totally up to you. + type: textarea + size: small + tab: General + + _section1: + label: Social Links + type: section + tab: General + + _social_links: + type: mixin + source: Fields\SocialLinks + tab: General diff --git a/themes/demo/seeds/blueprints/blog/post-content.yaml b/themes/demo/seeds/blueprints/blog/post-content.yaml new file mode 100644 index 0000000..dfa7d7c --- /dev/null +++ b/themes/demo/seeds/blueprints/blog/post-content.yaml @@ -0,0 +1,47 @@ +uuid: 4d7fd1e4-85f2-48f5-947e-92819fc8664b +handle: Blog\PostContent +type: mixin +name: Blog Post Content + +fields: + banner: + tab: Manage + label: Banner + type: fileupload + mode: image + maxFiles: 1 + + author: + tab: Manage + label: Author + commentAbove: 'Select the author for this blog post' + type: entries + maxItems: 1 + source: Blog\Author + + categories: + tab: Manage + label: Categories + commentAbove: 'Select categories the blog post belongs to' + type: entries + source: Blog\Category + + featured_text: + tab: Featured + label: Featured Text + type: textarea + size: small + + gallery: + label: Gallery + type: fileupload + mode: image + span: adaptive + tab: Gallery + + gallery_media: + label: Media + type: mediafinder + mode: image + span: adaptive + tab: Media diff --git a/themes/demo/seeds/blueprints/blog/post.yaml b/themes/demo/seeds/blueprints/blog/post.yaml new file mode 100644 index 0000000..fb881b8 --- /dev/null +++ b/themes/demo/seeds/blueprints/blog/post.yaml @@ -0,0 +1,42 @@ +uuid: edcd102e-0525-4e4d-b07e-633ae6c18db6 +handle: Blog\Post +type: stream +name: Post +drafts: true + +primaryNavigation: + label: Blog + icon: octo-icon-file + iconSvg: modules/tailor/assets/images/blog-icon.svg + order: 95 + +navigation: + icon: octo-icon-pencil + order: 100 + +groups: + regular_post: + name: Regular Post + fields: + content: + tab: Edit + label: Content + type: richeditor + span: adaptive + + _blog_post_content: + type: mixin + source: Blog\PostContent + + markdown_post: + name: Markdown Post + fields: + content: + tab: Edit + label: Content + type: markdown + span: adaptive + + _blog_post_content: + type: mixin + source: Blog\PostContent diff --git a/themes/demo/seeds/blueprints/fields/social-links.yaml b/themes/demo/seeds/blueprints/fields/social-links.yaml new file mode 100644 index 0000000..fa766d3 --- /dev/null +++ b/themes/demo/seeds/blueprints/fields/social-links.yaml @@ -0,0 +1,27 @@ +uuid: ae2d2c25-3a0e-4765-8b36-d1666fc0e31f +name: Social Links +type: mixin +handle: Fields\SocialLinks + +fields: + social_links: + type: repeater + prompt: Add Link + form: + fields: + platform: + span: auto + label: Platform + type: dropdown + options: + facebook: Facebook + linkedin: LinkedIn + dribbble: Dribbble + twitter: Twitter + youtube: YouTube + + url: + span: auto + label: Social Link + type: text + placeholder: "https://..." diff --git a/themes/demo/seeds/blueprints/landing/block-builder.yaml b/themes/demo/seeds/blueprints/landing/block-builder.yaml new file mode 100644 index 0000000..46c58dc --- /dev/null +++ b/themes/demo/seeds/blueprints/landing/block-builder.yaml @@ -0,0 +1,57 @@ +uuid: 7b193500-ac0b-481f-a79c-2a362646364d +handle: BlockBuilder +type: mixin +name: Block Builder + +fields: + blocks: + label: Blocks + type: repeater + displayMode: builder + span: adaptive + tab: Blocks + groups: + image_slice: + name: Image Slice + description: A large image with an angled slice. + icon: octo-icon-picture + fields: + _mixin: + type: mixin + source: Blocks\ImageSlice + + paragraph_block: + name: Paragraph Block + description: Simple paragraph with image + icon: octo-icon-text-h1 + fields: + _mixin: + type: mixin + source: Blocks\ParagraphBlock + + detailed_block: + name: Detailed Block + description: Detailed paragraph with image and list + icon: octo-icon-diamond + fields: + _mixin: + type: mixin + source: Blocks\DetailedBlock + + scoreboard_metrics: + name: Scoreboard Metrics + description: Show some impressive metrics about the business. + icon: icon-quote-right + fields: + _mixin: + type: mixin + source: Blocks\ScoreboardMetrics + + team_leaders: + name: Team Leaders + description: Display the team members. + icon: octo-icon-comment + fields: + _mixin: + type: mixin + source: Blocks\TeamLeaders diff --git a/themes/demo/seeds/blueprints/landing/blocks/detailed-block.yaml b/themes/demo/seeds/blueprints/landing/blocks/detailed-block.yaml new file mode 100644 index 0000000..c486018 --- /dev/null +++ b/themes/demo/seeds/blueprints/landing/blocks/detailed-block.yaml @@ -0,0 +1,39 @@ +uuid: da034c4f-0e24-4906-94b9-66b26c0549c9 +name: Detailed Block +type: mixin +handle: Blocks\DetailedBlock + +fields: + title: + label: Title + type: text + + content: + label: Description + type: richeditor + size: small + + list_items: + label: List Items + type: datatable + btnAddRowLabel: Add Item + btnDeleteRowLabel: Delete Item + columns: + text: + type: string + title: Text + + button_text: + label: Button Text + span: auto + placeholder: Main call to action + + button_url: + label: Button URL + span: auto + + image: + label: Image + type: mediafinder + mode: image + maxItems: 1 diff --git a/themes/demo/seeds/blueprints/landing/blocks/image-slice.yaml b/themes/demo/seeds/blueprints/landing/blocks/image-slice.yaml new file mode 100644 index 0000000..7d0beed --- /dev/null +++ b/themes/demo/seeds/blueprints/landing/blocks/image-slice.yaml @@ -0,0 +1,11 @@ +uuid: 21aad99b-d3c6-4f5e-b271-15471c81e11b +name: Image Slice +type: mixin +handle: Blocks\ImageSlice + +fields: + image: + label: Image + type: mediafinder + mode: image + maxItems: 1 diff --git a/themes/demo/seeds/blueprints/landing/blocks/paragraph-block.yaml b/themes/demo/seeds/blueprints/landing/blocks/paragraph-block.yaml new file mode 100644 index 0000000..87ab650 --- /dev/null +++ b/themes/demo/seeds/blueprints/landing/blocks/paragraph-block.yaml @@ -0,0 +1,20 @@ +uuid: 015fde4b-23d8-4ba3-8e78-9c6ebfb5fcf7 +name: Paragraph Block +type: mixin +handle: Blocks\ParagraphBlock + +fields: + title: + label: Title + type: text + + content: + label: Description + type: richeditor + size: small + + image: + label: Image + type: mediafinder + mode: image + maxItems: 1 diff --git a/themes/demo/seeds/blueprints/landing/blocks/scoreboard-metrics.yaml b/themes/demo/seeds/blueprints/landing/blocks/scoreboard-metrics.yaml new file mode 100644 index 0000000..00163b6 --- /dev/null +++ b/themes/demo/seeds/blueprints/landing/blocks/scoreboard-metrics.yaml @@ -0,0 +1,32 @@ +uuid: 55615b16-120f-4be9-9429-6ae6dabc523c +name: Scoreboard Metrics +type: mixin +handle: Blocks\ScoreboardMetrics + +fields: + metrics: + label: Metrics + type: repeater + form: + fields: + number: + label: Number + type: number + span: row + spanClass: col-md-3 + + description: + label: Description + type: text + span: row + spanClass: col-md-9 + + icon: + label: Icon + type: radio + cssClass: inline-options + options: + notepad: Notepad + shield: Shield + basket: Basket + briefcase: Briefcase diff --git a/themes/demo/seeds/blueprints/landing/blocks/team-leaders.yaml b/themes/demo/seeds/blueprints/landing/blocks/team-leaders.yaml new file mode 100644 index 0000000..5d27c42 --- /dev/null +++ b/themes/demo/seeds/blueprints/landing/blocks/team-leaders.yaml @@ -0,0 +1,35 @@ +uuid: 8c4041cf-f16d-46f8-86be-9372a266ae6d +name: Team Leaders +type: mixin +handle: Blocks\TeamLeaders + +fields: + members: + label: Members + type: repeater + itemsExpanded: false + form: + fields: + title: + label: Title + span: left + + role: + label: Role + span: right + + description: + label: Description + type: textarea + size: tiny + + avatar: + label: Image + type: mediafinder + mode: image + maxItems: 1 + + _social_links: + label: Social Links + type: mixin + source: Fields\SocialLinks diff --git a/themes/demo/seeds/blueprints/landing/landing-page.yaml b/themes/demo/seeds/blueprints/landing/landing-page.yaml new file mode 100644 index 0000000..715beb8 --- /dev/null +++ b/themes/demo/seeds/blueprints/landing/landing-page.yaml @@ -0,0 +1,13 @@ +uuid: a63fabaf-7c0b-4c74-b36f-7abf1a3ad1c1 +handle: LandingPage +type: single +name: Landing Page +drafts: true + +navigation: + icon: icon-rocket + +fields: + block_builder: + type: mixin + source: BlockBuilder diff --git a/themes/demo/seeds/blueprints/site/sitemap.yaml b/themes/demo/seeds/blueprints/site/sitemap.yaml new file mode 100644 index 0000000..1357ae0 --- /dev/null +++ b/themes/demo/seeds/blueprints/site/sitemap.yaml @@ -0,0 +1,68 @@ +uuid: 6743a1c3-3e57-4cfa-a886-e0c0a277fd71 +handle: Site\Sitemap +type: structure +name: Sitemap +drafts: false +pagefinder: false + +structure: + maxDepth: 1 + +navigation: + parent: settings + icon: icon-sitemap + description: Specify pages to appear in the sitemap for your website. + category: CATEGORY_CMS + +fields: + reference: + label: Reference + type: pagefinder + + priority: + label: Priority + commentAbove: The priority of this URL relative to other URLs on your site. + type: radio + inlineOptions: true + options: + '0.1': '0.1' + '0.2': '0.2' + '0.3': '0.3' + '0.4': '0.4' + '0.5': '0.5' + '0.6': '0.6' + '0.7': '0.7' + '0.8': '0.8' + '0.9': '0.9' + '1.0': '1.0' + + changefreq: + commentAbove: How frequently the page is likely to change. + label: Change Frequency + type: radio + inlineOptions: true + options: + always: Always + hourly: Hourly + daily: Daily + weekly: Weekly + monthly: Monthly + yearly: Yearly + never: Never + + nesting: + label: Include nested items + shortLabel: Nesting + comment: Nested items could be generated dynamically by supported page references. + type: checkbox + + replace: + label: Replace this item with its generated children + comment: Use this checkbox to push generated menu items to the same level with this item. This item itself will be hidden. + type: checkbox + column: false + scope: false + trigger: + action: disable|empty + field: nesting + condition: unchecked diff --git a/themes/demo/seeds/blueprints/wiki/article.yaml b/themes/demo/seeds/blueprints/wiki/article.yaml new file mode 100644 index 0000000..72ed774 --- /dev/null +++ b/themes/demo/seeds/blueprints/wiki/article.yaml @@ -0,0 +1,53 @@ +uuid: 339b11b7-69ad-43c4-9be1-6953e7738827 +handle: Wiki\Article +type: structure +name: Article +drafts: true + +structure: + maxDepth: 3 + +navigation: + icon: icon-wikipedia-w + +fields: + content: + label: Content + tab: Edit + type: richeditor + span: adaptive + + banner: + label: Banner + type: fileupload + mode: image + maxFiles: 1 + + show_in_toc: + label: Show in TOC + comment: Include this article in the table of contents + type: checkbox + + summary_text: + label: Summary Text + type: textarea + size: small + + gallery: + label: Gallery + type: fileupload + mode: image + + external_links: + label: External Links + tab: Links + type: repeater + form: + fields: + link_text: + label: Link Text + span: auto + + link_url: + label: Link URL + span: auto diff --git a/themes/demo/seeds/data.yaml b/themes/demo/seeds/data.yaml new file mode 100644 index 0000000..b909975 --- /dev/null +++ b/themes/demo/seeds/data.yaml @@ -0,0 +1,35 @@ +- + name: Blog Category Data + class: Tailor\Models\EntryRecordImport + file: seeds/data/blog/category.json + attributes: + file_format: json + blueprint_uuid: b022a74b-15e6-4c6b-9eb9-17efc5103543 +- + name: Blog Author Data + class: Tailor\Models\EntryRecordImport + file: seeds/data/blog/author.json + attributes: + file_format: json + blueprint_uuid: 6947ff28-b660-47d7-9240-24ca6d58aeae +- + name: Blog Post Data + class: Tailor\Models\EntryRecordImport + file: seeds/data/blog/post.json + attributes: + file_format: json + blueprint_uuid: edcd102e-0525-4e4d-b07e-633ae6c18db6 +- + name: Wiki Data + class: Tailor\Models\EntryRecordImport + file: seeds/data/wiki/article.json + attributes: + file_format: json + blueprint_uuid: 339b11b7-69ad-43c4-9be1-6953e7738827 +- + name: About Page Data + class: Tailor\Models\EntryRecordImport + file: seeds/data/landing/landing-page.json + attributes: + file_format: json + blueprint_uuid: a63fabaf-7c0b-4c74-b36f-7abf1a3ad1c1 diff --git a/themes/demo/seeds/data/blog/author.json b/themes/demo/seeds/data/blog/author.json new file mode 100644 index 0000000..248ab42 --- /dev/null +++ b/themes/demo/seeds/data/blog/author.json @@ -0,0 +1,32 @@ +[ + { + "id": 1, + "title": "John Smith", + "slug": "john-smith", + "is_enabled": 1, + "role": "Manager", + "about": "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", + "social_links": [ + { + "platform": "twitter", + "url": "https:\/\/twitter.com\/octobercms", + "sort_order": 1 + }, + { + "platform": "youtube", + "url": "https:\/\/www.youtube.com\/c\/OctoberCMSOfficial", + "sort_order": 2 + }, + { + "platform": "facebook", + "url": "https:\/\/facebook.com\/octobercms", + "sort_order": 3 + }, + { + "platform": "linkedin", + "url": "https:\/\/www.linkedin.com\/company\/october-cms\/", + "sort_order": 4 + } + ] + } +] diff --git a/themes/demo/seeds/data/blog/category.json b/themes/demo/seeds/data/blog/category.json new file mode 100644 index 0000000..267a49c --- /dev/null +++ b/themes/demo/seeds/data/blog/category.json @@ -0,0 +1,37 @@ +[ + { + "id": 1, + "title": "Announcements", + "slug": "announcements", + "is_enabled": 1, + "description": "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt molliti" + }, + { + "id": 2, + "title": "News", + "slug": "news", + "is_enabled": 1, + "description": "Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt." + }, + { + "id": 3, + "title": "Startup Ideas", + "slug": "startup-ideas", + "is_enabled": 1, + "description": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proide" + }, + { + "id": 4, + "title": "Updates", + "slug": "updates", + "is_enabled": 1, + "description": "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt molliti" + }, + { + "id": 5, + "title": "Automation", + "slug": "automation", + "is_enabled": 1, + "description": "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo." + } +] diff --git a/themes/demo/seeds/data/blog/post.json b/themes/demo/seeds/data/blog/post.json new file mode 100644 index 0000000..76a5d4b --- /dev/null +++ b/themes/demo/seeds/data/blog/post.json @@ -0,0 +1,28 @@ +[ + { + "id": 1, + "title": "Consectetur adipiscing elit", + "slug": "consectetur-adipiscing-elit", + "is_enabled": 1, + "content_group": "regular_post", + "content": "

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<\/p>

    Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?<\/p>", + "author": 1, + "categories": [ + 1 + ], + "featured_text": "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo." + }, + { + "id": 2, + "title": "Nemo enim ipsam", + "slug": "nemo-enim-ipsam", + "is_enabled": 1, + "content_group": "regular_post", + "content": "

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<\/p>

    Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?<\/p>", + "author": 1, + "categories": [ + 2 + ], + "featured_text": "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga." + } +] diff --git a/themes/demo/seeds/data/landing/landing-page.json b/themes/demo/seeds/data/landing/landing-page.json new file mode 100644 index 0000000..40b12ed --- /dev/null +++ b/themes/demo/seeds/data/landing/landing-page.json @@ -0,0 +1,218 @@ +[ + { + "id": 1, + "title": "About Us", + "slug": "about-us", + "is_enabled": 1, + "content_group": null, + "blocks": [ + { + "image": "", + "content_group": "image_slice", + "sort_order": 1 + }, + { + "title": "Outstanding performance", + "content": "

    Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.<\/p>", + "image": "", + "content_group": "paragraph_block", + "sort_order": 2 + }, + { + "title": "Why work with us", + "content": "

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<\/p>", + "list_items": [ + { + "text": "Doloremque" + }, + { + "text": "Beatae vitae" + }, + { + "text": "Totam rem aperiam" + } + ], + "button_text": "Learn more about our process", + "button_url": "https:\/\/octobercms.com\/features", + "image": "", + "content_group": "detailed_block", + "sort_order": 3 + }, + { + "content_group": "scoreboard_metrics", + "sort_order": 4, + "metrics": [ + { + "number": 3912, + "description": "Sed ut perspiciatis", + "icon": "notepad", + "content_group": null, + "sort_order": 1 + }, + { + "number": 223, + "description": "Nemo enim ipsam", + "icon": "shield", + "content_group": null, + "sort_order": 2 + }, + { + "number": 863, + "description": "Nam libero tempore", + "icon": "basket", + "content_group": null, + "sort_order": 3 + }, + { + "number": 865, + "description": "Et harum quidem rerum", + "icon": "briefcase", + "content_group": null, + "sort_order": 4 + } + ] + }, + { + "content_group": "team_leaders", + "sort_order": 5, + "members": [ + { + "title": "Andy Anderson", + "role": "Sales Manager", + "description": "Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam.", + "avatar": "", + "content_group": null, + "sort_order": 1, + "social_links": [ + { + "platform": "twitter", + "url": "https:\/\/twitter.com\/octobercms", + "sort_order": 1 + }, + { + "platform": "linkedin", + "url": "https:\/\/www.linkedin.com\/company\/october-cms\/", + "sort_order": 2 + }, + { + "platform": "facebook", + "url": "https:\/\/facebook.com\/octobercms", + "sort_order": 3 + } + ] + }, + { + "title": "Bob Harris", + "role": "Product Designer", + "description": "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque.", + "avatar": "", + "content_group": null, + "sort_order": 2, + "social_links": [ + { + "platform": "twitter", + "url": "https:\/\/twitter.com\/octobercms", + "sort_order": 1 + }, + { + "platform": "youtube", + "url": "https:\/\/www.youtube.com\/c\/OctoberCMSOfficial", + "sort_order": 2 + }, + { + "platform": "dribbble", + "url": "https:\/\/www.dribbble.com", + "sort_order": 3 + }, + { + "platform": "facebook", + "url": "https:\/\/facebook.com\/octobercms", + "sort_order": 4 + } + ] + }, + { + "title": "Ann Lewis", + "role": "Marketing Manager", + "description": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla.", + "avatar": "", + "content_group": null, + "sort_order": 3, + "social_links": [ + { + "platform": "twitter", + "url": "https:\/\/twitter.com\/octobercms", + "sort_order": 1 + }, + { + "platform": "linkedin", + "url": "https:\/\/www.linkedin.com\/company\/october-cms\/", + "sort_order": 2 + }, + { + "platform": "facebook", + "url": "https:\/\/facebook.com\/octobercms", + "sort_order": 3 + } + ] + }, + { + "title": "Christina Thompson", + "role": "System Analyst", + "description": "Et harum quidem rerum facilis est et expedita distinctio.", + "avatar": "", + "content_group": null, + "sort_order": 4, + "social_links": [ + { + "platform": "twitter", + "url": "https:\/\/twitter.com\/octobercms", + "sort_order": 1 + }, + { + "platform": "youtube", + "url": "https:\/\/www.youtube.com\/c\/OctoberCMSOfficial", + "sort_order": 2 + }, + { + "platform": "dribbble", + "url": "https:\/\/www.dribbble.com", + "sort_order": 3 + }, + { + "platform": "facebook", + "url": "https:\/\/facebook.com\/octobercms", + "sort_order": 4 + } + ] + }, + { + "title": "John Smith", + "role": "President", + "description": "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.", + "avatar": "", + "content_group": null, + "sort_order": 5, + "social_links": [ + { + "platform": "dribbble", + "url": "https:\/\/www.dribbble.com", + "sort_order": 1 + }, + { + "platform": "linkedin", + "url": "https:\/\/www.linkedin.com\/company\/october-cms\/", + "sort_order": 2 + }, + { + "platform": "youtube", + "url": "https:\/\/www.youtube.com\/c\/OctoberCMSOfficial", + "sort_order": 3 + } + ] + } + ] + } + ] + } +] diff --git a/themes/demo/seeds/data/wiki/article.json b/themes/demo/seeds/data/wiki/article.json new file mode 100644 index 0000000..89fe7c2 --- /dev/null +++ b/themes/demo/seeds/data/wiki/article.json @@ -0,0 +1,86 @@ +[ + { + "id": 1, + "title": "Our Locations", + "content": "

    The term location generally implies a higher degree of certainty than place, the latter often indicating an entity with an ambiguous boundary, relying more on human or social attributes of place identity and sense of place than on geometry. An absolute location can be designated using a specific pairing of latitude and longitude in a Cartesian coordinate grid (for example, a spherical coordinate system or an ellipsoid-based system such as the World Geodetic System) or similar methods. For instance, the position of Lake Maracaibo in Venezuela can be expressed using the coordinate system as the location 9.80\u00b0N (latitude), 71.56\u00b0W (longitude).<\/p>", + "slug": "our-locations", + "is_enabled": 1, + "content_group": null, + "parent_id": null, + "banner": null, + "show_in_toc": 1, + "summary_text": "In geography, location or place are used to denote a region (point, line, or area) on Earth's surface or elsewhere.", + "external_links": [] + }, + { + "id": 2, + "title": "Canberra", + "content": "

    Unusual among Australian cities, it is an entirely planned city. The city is located at the northern end of the Australian Capital Territory[11] at the northern tip of the Australian Alps, the country's highest mountain range. As of June 2020, Canberra's estimated population was 431,380.[12]<\/p>

    The area chosen for the capital had been inhabited by Indigenous Australians for up to 21,000 years,[13] with the principal group being the Ngunnawal people. European settlement commenced in the first half of the 19th century, as evidenced by surviving landmarks such as St John's Anglican Church and Blundells Cottage. On 1 January 1901, federation of the colonies of Australia was achieved. Following a long dispute over whether Sydney or Melbourne should be the national capital,[14] a compromise was reached: the new capital would be built in New South Wales, so long as it was at least 100 miles (160 km) from Sydney. The capital city was founded and formally named as Canberra in 1913. A blueprint by American architects Walter Burley Griffin and Marion Mahony Griffin was selected after an international design contest, and construction commenced in 1913.[15] The Griffins' plan featured geometric motifs and was centred on axes aligned with significant topographical landmarks such as Black Mountain, Mount Ainslie, Capital Hill and City Hill. Canberra's mountainous location makes it the only mainland Australian city where snow-capped mountains can be seen in winter; although snow in the city itself is rare.<\/p>

    As the seat of the Government of Australia, Canberra is home to many important institutions of the federal government, national monuments and museums. This includes Parliament House, Government House, the High Court and the headquarters of numerous government agencies. It is the location of many social and cultural institutions of national significance such as the Australian War Memorial, the Australian National University, the Royal Australian Mint, the Australian Institute of Sport, the National Gallery, the National Museum and the National Library. The city is home to many important institutions of the Australian Defence Force including the Royal Military College Duntroon and the Australian Defence Force Academy. It hosts all foreign embassies in Australia as well as regional headquarters of many international organisations, not-for-profit groups, lobbying groups and professional associations.<\/p>", + "slug": "canberra", + "is_enabled": 1, + "content_group": null, + "parent_id": 1, + "banner": null, + "show_in_toc": 1, + "summary_text": "Canberra (\/\u02c8k\u00e6nb\u0259r\u0259\/ KAN-b\u0259-r\u0259) is the capital city of Australia. Founded following the federation of the colonies of Australia as the seat of government for the new nation, it is Australia's largest inland city and the eighth-largest city overall.", + "external_links": [ + { + "link_text": "Canberra travel guide from Wikivoyage", + "link_url": "https:\/\/en.wikivoyage.org\/wiki\/Canberra", + "content_group": null, + "sort_order": 1 + }, + { + "link_text": "Official Tourism Website", + "link_url": "https:\/\/visitcanberra.com.au\/", + "content_group": null, + "sort_order": 2 + }, + { + "link_text": "Canberra 100 \u2013 Celebrating Canberra's 100th anniversary", + "link_url": "https:\/\/www.canberra100.com.au\/", + "content_group": null, + "sort_order": 3 + } + ] + }, + { + "id": 3, + "title": "Sydney", + "content": "

    Located on Australia's east coast, the metropolis surrounds Port Jackson and extends about 70 km (43.5 mi) on its periphery towards the Blue Mountains to the west, Hawkesbury to the north, the Royal National Park to the south and Macarthur to the south-west. Sydney is made up of 658 suburbs, spread across 33 local government areas. Residents of the city are known as \"Sydneysiders\". As of June 2020, Sydney's estimated metropolitan population was 5,361,466, meaning the city is home to approximately 66% of the state's population. Nicknames of the city include the 'Emerald City' and the 'Harbour City'.<\/p>

    Indigenous Australians have inhabited the Sydney area for at least 30,000 years, and thousands of Aboriginal engravings remain throughout the region. During his first Pacific voyage in 1770, Lieutenant James Cook and his crew became the first Europeans to chart the eastern coast of Australia, making landfall at Botany Bay. In 1788, the First Fleet of convicts, led by Arthur Phillip, founded Sydney as a British penal colony, the first European settlement in Australia. After World War II, it experienced mass migration and became one of the most multicultural cities in the world. Furthermore, 45.4% of the population reported having been born overseas, and the city has the third-largest foreign-born population of any city in the world after London and New York City.<\/p>

    Despite being one of the most expensive cities in the world, Sydney frequently ranks in the top ten most liveable cities in the world. It is classified as an Alpha global city by the Globalization and World Cities Research Network, indicating its influence in the region and throughout the world. Ranked eleventh in the world for economic opportunity, Sydney has an advanced market economy with strengths in finance, manufacturing and tourism. Established in 1850, the University of Sydney was Australia's first university and is regarded as one of the world's leading universities.<\/p>", + "slug": "sydney", + "is_enabled": 1, + "content_group": null, + "parent_id": 1, + "banner": null, + "show_in_toc": 1, + "summary_text": "Sydney is the capital city of the state of New South Wales, and the most populous city in Australia and Oceania.", + "external_links": [] + }, + { + "id": 4, + "title": "Vancouver", + "content": "

    As the most populous city in the province, the 2021 census recorded 662,248 people in the city, up from 631,486 in 2016. The Greater Vancouver area had a population of 2,642,825 in 2021, making it the third-largest metropolitan area in Canada. Vancouver has the highest population density in Canada, with over 5,400 people per square kilometre. Vancouver is one of the most ethnically and linguistically diverse cities in Canada: 52 percent of its residents are not native English speakers, 48.9 percent are native speakers of neither English nor French, and 50.6 percent of residents belong to visible minority groups.<\/p>

    Vancouver is one of the most livable cities in Canada and in the world. In terms of housing affordability, Vancouver is also one of the most expensive cities in Canada and in the world. Vancouver plans to become the greenest city in the world. Vancouverism is the city's urban planning design philosophy.<\/p>

    Indigenous settlement of Vancouver began more than 10,000 years ago, and the city is on the traditional and unceded territories of the Squamish, Musqueam, and Tsleil-Waututh (Burrard) peoples. The beginnings of the modern city, which was originally named Gastown, grew around the site of a makeshift tavern on the western edges of Hastings Mill that was built on July 1, 1867, and owned by proprietor Gassy Jack. The original site is marked by the Gastown steam clock. Gastown then formally registered as a townsite dubbed Granville, Burrard Inlet. The city was renamed \"Vancouver\" in 1886, through a deal with the Canadian Pacific Railway (CPR). The Canadian Pacific transcontinental railway was extended to the city by 1887. The city's large natural seaport on the Pacific Ocean became a vital link in the trade between Asia-Pacific, East Asia, Europe, and Eastern Canada.<\/p>", + "slug": "vancouver", + "is_enabled": 1, + "content_group": null, + "parent_id": 1, + "banner": null, + "show_in_toc": 1, + "summary_text": "Vancouver is a major city in western Canada, located in the Lower Mainland region of British Columbia.", + "external_links": [] + }, + { + "id": 5, + "title": "Knowledge Base", + "content": "

    Knowledge Base<\/p>", + "slug": "knowledge-base", + "is_enabled": 1, + "content_group": null, + "parent_id": null, + "banner": null, + "show_in_toc": 1, + "summary_text": "", + "external_links": [] + } +] \ No newline at end of file diff --git a/themes/demo/theme.yaml b/themes/demo/theme.yaml new file mode 100644 index 0000000..70e2ef0 --- /dev/null +++ b/themes/demo/theme.yaml @@ -0,0 +1,5 @@ +name: Demo +description: 'Demo October CMS theme. Demonstrates the basic concepts of the front-end theming: layouts, pages, partials, components, content blocks, AJAX framework.' +author: October CMS +homepage: 'http://octobercms.com' +code: '' diff --git a/themes/demo/webpack.config.js b/themes/demo/webpack.config.js new file mode 100644 index 0000000..76b3c20 --- /dev/null +++ b/themes/demo/webpack.config.js @@ -0,0 +1,17 @@ +const webpack = require('webpack'); + +module.exports = { + devtool: 'inline-source-map', + plugins: [ + new webpack.ProvidePlugin({ + $: 'jquery', + jQuery: 'jquery', + 'window.jQuery': 'jquery', + 'window.$': 'jquery', + }), + ], + externals: { + // Use external version of jQuery + jquery: 'jQuery' + }, +}; diff --git a/themes/demo/webpack.mix.js b/themes/demo/webpack.mix.js new file mode 100644 index 0000000..d7bb00d --- /dev/null +++ b/themes/demo/webpack.mix.js @@ -0,0 +1,29 @@ +const mix = require('laravel-mix'); +const webpackConfig = require('./webpack.config'); + +/* + |-------------------------------------------------------------------------- + | Mix Asset Management + |-------------------------------------------------------------------------- + | + | Mix provides a clean, fluent API for defining some Webpack build steps + | for your theme assets. By default, we are compiling the CSS + | file for the application as well as bundling up all the JS files. + | + */ + +mix.webpackConfig(webpackConfig) + .options({ processCssUrls: false }) + .copy('node_modules/jquery/dist/jquery.min.js', 'assets/vendor/jquery.min.js') + .js('assets/vendor/codeblocks/codeblocks.js', 'assets/vendor/codeblocks/codeblocks.min.js') + .js('assets/vendor/bootstrap/bootstrap.js', 'assets/vendor/bootstrap/bootstrap.min.js') + .sass('assets/vendor/bootstrap/bootstrap.scss', 'assets/vendor/bootstrap/bootstrap.css') + .sass('assets/vendor/bootstrap-icons/bootstrap-icons.scss', 'assets/vendor/bootstrap-icons/bootstrap-icons.css') + .copy('node_modules/bootstrap-icons/font/fonts/', 'assets/vendor/bootstrap-icons/fonts/') + .copy('node_modules/slick-carousel/slick', 'assets/vendor/slick-carousel/') + .copy('node_modules/photoswipe/dist/photoswipe.css', 'assets/vendor/photoswipe/photoswipe.css') + .copy('node_modules/photoswipe/dist/photoswipe-lightbox.esm.min.js', 'assets/vendor/photoswipe/photoswipe-lightbox.esm.min.js') + .copy('node_modules/photoswipe/dist/photoswipe.esm.min.js', 'assets/vendor/photoswipe/photoswipe.esm.min.js') + .copy('node_modules/photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.esm.js', 'assets/vendor/photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.esm.js') + .copy('node_modules/photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.css', 'assets/vendor/photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.css') +; diff --git a/themes/nurgul/assets/css/font-icons.css b/themes/nurgul/assets/css/font-icons.css new file mode 100644 index 0000000..6bc8600 --- /dev/null +++ b/themes/nurgul/assets/css/font-icons.css @@ -0,0 +1,802 @@ +/* =================================================== +>>> TABLE OF CONTENTS: +====================================================== + 1. Font Awesome + 2. Simple Line Icons + + +=================================================== */ + +/*--------------------------------------------------------------- + 1. Font Awesome 5 Icon +---------------------------------------------------------------*/ +/*! + * Font Awesome Free 5.5.0 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ + +.fa,.fab,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{animation:fa-spin 2s infinite linear}.fa-pulse{animation:fa-spin 1s infinite steps(8)}@keyframes fa-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";transform:scaleX(-1)}.fa-flip-vertical{transform:scaleY(-1)}.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-horizontal.fa-flip-vertical{transform:scale(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-balance-scale:before{content:"\f24e"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-concierge-bell:before{content:"\f562"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-diagnoses:before{content:"\f470"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edit:before{content:"\f044"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-git:before{content:"\f1d3"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-handshake:before{content:"\f2b5"}.fa-hanukiah:before{content:"\f6e6"}.fa-hashtag:before{content:"\f292"}.fa-hat-wizard:before{content:"\f6e8"}.fa-haykal:before{content:"\f666"}.fa-hdd:before{content:"\f0a0"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hockey-puck:before{content:"\f453"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hot-tub:before{content:"\f593"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-instagram:before{content:"\f16d"}.fa-internet-explorer:before{content:"\f26b"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse-pointer:before{content:"\f245"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-nintendo-switch:before{content:"\f418"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-carry:before{content:"\f4ce"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-volume:before{content:"\f2a0"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-sass:before{content:"\f41e"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-simplybuilt:before{content:"\f215"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowflake:before{content:"\f2dc"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-swatchbook:before{content:"\f5c3"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet-paper:before{content:"\f71e"}.fa-toolbox:before{content:"\f552"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-train:before{content:"\f238"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-uikit:before{content:"\f403"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-water:before{content:"\f773"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:normal;src:url("../webfonts/fa-brands-400.eot");src:url("../webfonts/fa-brands-400-.eot#iefix") format("embedded-opentype"),url("../webfonts/fa-brands-400.woff2") format("woff2"),url("../webfonts/fa-brands-400.woff") format("woff"),url("../webfonts/fa-brands-400.ttf") format("truetype"),url("../webfonts/fa-brands-400.svg#fontawesome") format("svg")}.fab{font-family:"Font Awesome 5 Brands"}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;src:url("../webfonts/fa-regular-400.eot");src:url("../webfonts/fa-regular-400-.eot#iefix") format("embedded-opentype"),url("../webfonts/fa-regular-400.woff2") format("woff2"),url("../webfonts/fa-regular-400.woff") format("woff"),url("../webfonts/fa-regular-400.ttf") format("truetype"),url("../webfonts/fa-regular-400.svg#fontawesome") format("svg")}.far{font-weight:400}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;src:url("../webfonts/fa-solid-900.eot");src:url("../webfonts/fa-solid-900-.eot#iefix") format("embedded-opentype"),url("../webfonts/fa-solid-900.woff2") format("woff2"),url("../webfonts/fa-solid-900.woff") format("woff"),url("../webfonts/fa-solid-900.ttf") format("truetype"),url("../webfonts/fa-solid-900.svg#fontawesome") format("svg")}.fa,.far,.fas{font-family:"Font Awesome 5 Free"}.fa,.fas{font-weight:900} + + +/*--------------------------------------------------------------- + 2. Simple Line Icons +---------------------------------------------------------------*/ +@font-face { + font-family: 'simple-line-icons'; + src: url('../fonts/Simple-Line-Icons-v=2.4.0.eot'); + src: url('../fonts/Simple-Line-Icons-v=2.4.0.eot#iefix') format('embedded-opentype'), url('../fonts/Simple-Line-Icons-v=2.4.0.woff2') format('woff2'), url('../fonts/Simple-Line-Icons-v=2.4.0.ttf') format('truetype'), url('../fonts/Simple-Line-Icons-v=2.4.0.woff') format('woff'), url('../fonts/Simple-Line-Icons-v=2.4.0.svg#simple-line-icons') format('svg'); + font-weight: normal; + font-style: normal; +} +/* + Use the following CSS code if you want to have a class per icon. + Instead of a list of all class selectors, you can use the generic [class*="icon-"] selector, but it's slower: +*/ +.icon-user, +.icon-people, +.icon-user-female, +.icon-user-follow, +.icon-user-following, +.icon-user-unfollow, +.icon-login, +.icon-logout, +.icon-emotsmile, +.icon-phone, +.icon-call-end, +.icon-call-in, +.icon-call-out, +.icon-map, +.icon-location-pin, +.icon-direction, +.icon-directions, +.icon-compass, +.icon-layers, +.icon-menu, +.icon-list, +.icon-options-vertical, +.icon-options, +.icon-arrow-down, +.icon-arrow-left, +.icon-arrow-right, +.icon-arrow-up, +.icon-arrow-up-circle, +.icon-arrow-left-circle, +.icon-arrow-right-circle, +.icon-arrow-down-circle, +.icon-check, +.icon-clock, +.icon-plus, +.icon-minus, +.icon-close, +.icon-event, +.icon-exclamation, +.icon-organization, +.icon-trophy, +.icon-screen-smartphone, +.icon-screen-desktop, +.icon-plane, +.icon-notebook, +.icon-mustache, +.icon-mouse, +.icon-magnet, +.icon-energy, +.icon-disc, +.icon-cursor, +.icon-cursor-move, +.icon-crop, +.icon-chemistry, +.icon-speedometer, +.icon-shield, +.icon-screen-tablet, +.icon-magic-wand, +.icon-hourglass, +.icon-graduation, +.icon-ghost, +.icon-game-controller, +.icon-fire, +.icon-eyeglass, +.icon-envelope-open, +.icon-envelope-letter, +.icon-bell, +.icon-badge, +.icon-anchor, +.icon-wallet, +.icon-vector, +.icon-speech, +.icon-puzzle, +.icon-printer, +.icon-present, +.icon-playlist, +.icon-pin, +.icon-picture, +.icon-handbag, +.icon-globe-alt, +.icon-globe, +.icon-folder-alt, +.icon-folder, +.icon-film, +.icon-feed, +.icon-drop, +.icon-drawer, +.icon-docs, +.icon-doc, +.icon-diamond, +.icon-cup, +.icon-calculator, +.icon-bubbles, +.icon-briefcase, +.icon-book-open, +.icon-basket-loaded, +.icon-basket, +.icon-bag, +.icon-action-undo, +.icon-action-redo, +.icon-wrench, +.icon-umbrella, +.icon-trash, +.icon-tag, +.icon-support, +.icon-frame, +.icon-size-fullscreen, +.icon-size-actual, +.icon-shuffle, +.icon-share-alt, +.icon-share, +.icon-rocket, +.icon-question, +.icon-pie-chart, +.icon-pencil, +.icon-note, +.icon-loop, +.icon-home, +.icon-grid, +.icon-graph, +.icon-microphone, +.icon-music-tone-alt, +.icon-music-tone, +.icon-earphones-alt, +.icon-earphones, +.icon-equalizer, +.icon-like, +.icon-dislike, +.icon-control-start, +.icon-control-rewind, +.icon-control-play, +.icon-control-pause, +.icon-control-forward, +.icon-control-end, +.icon-volume-1, +.icon-volume-2, +.icon-volume-off, +.icon-calendar, +.icon-bulb, +.icon-chart, +.icon-ban, +.icon-bubble, +.icon-camrecorder, +.icon-camera, +.icon-cloud-download, +.icon-cloud-upload, +.icon-envelope, +.icon-eye, +.icon-flag, +.icon-heart, +.icon-info, +.icon-key, +.icon-link, +.icon-lock, +.icon-lock-open, +.icon-magnifier, +.icon-magnifier-add, +.icon-magnifier-remove, +.icon-paper-clip, +.icon-paper-plane, +.icon-power, +.icon-refresh, +.icon-reload, +.icon-settings, +.icon-star, +.icon-symbol-female, +.icon-symbol-male, +.icon-target, +.icon-credit-card, +.icon-paypal, +.icon-social-tumblr, +.icon-social-twitter, +.icon-social-facebook, +.icon-social-instagram, +.icon-social-linkedin, +.icon-social-pinterest, +.icon-social-github, +.icon-social-google, +.icon-social-reddit, +.icon-social-skype, +.icon-social-dribbble, +.icon-social-behance, +.icon-social-foursqare, +.icon-social-soundcloud, +.icon-social-spotify, +.icon-social-stumbleupon, +.icon-social-youtube, +.icon-social-dropbox, +.icon-social-vkontakte, +.icon-social-steam { + font-family: 'simple-line-icons'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.icon-user:before { + content: "\e005"; +} +.icon-people:before { + content: "\e001"; +} +.icon-user-female:before { + content: "\e000"; +} +.icon-user-follow:before { + content: "\e002"; +} +.icon-user-following:before { + content: "\e003"; +} +.icon-user-unfollow:before { + content: "\e004"; +} +.icon-login:before { + content: "\e066"; +} +.icon-logout:before { + content: "\e065"; +} +.icon-emotsmile:before { + content: "\e021"; +} +.icon-phone:before { + content: "\e600"; +} +.icon-call-end:before { + content: "\e048"; +} +.icon-call-in:before { + content: "\e047"; +} +.icon-call-out:before { + content: "\e046"; +} +.icon-map:before { + content: "\e033"; +} +.icon-location-pin:before { + content: "\e096"; +} +.icon-direction:before { + content: "\e042"; +} +.icon-directions:before { + content: "\e041"; +} +.icon-compass:before { + content: "\e045"; +} +.icon-layers:before { + content: "\e034"; +} +.icon-menu:before { + content: "\e601"; +} +.icon-list:before { + content: "\e067"; +} +.icon-options-vertical:before { + content: "\e602"; +} +.icon-options:before { + content: "\e603"; +} +.icon-arrow-down:before { + content: "\e604"; +} +.icon-arrow-left:before { + content: "\e605"; +} +.icon-arrow-right:before { + content: "\e606"; +} +.icon-arrow-up:before { + content: "\e607"; +} +.icon-arrow-up-circle:before { + content: "\e078"; +} +.icon-arrow-left-circle:before { + content: "\e07a"; +} +.icon-arrow-right-circle:before { + content: "\e079"; +} +.icon-arrow-down-circle:before { + content: "\e07b"; +} +.icon-check:before { + content: "\e080"; +} +.icon-clock:before { + content: "\e081"; +} +.icon-plus:before { + content: "\e095"; +} +.icon-minus:before { + content: "\e615"; +} +.icon-close:before { + content: "\e082"; +} +.icon-event:before { + content: "\e619"; +} +.icon-exclamation:before { + content: "\e617"; +} +.icon-organization:before { + content: "\e616"; +} +.icon-trophy:before { + content: "\e006"; +} +.icon-screen-smartphone:before { + content: "\e010"; +} +.icon-screen-desktop:before { + content: "\e011"; +} +.icon-plane:before { + content: "\e012"; +} +.icon-notebook:before { + content: "\e013"; +} +.icon-mustache:before { + content: "\e014"; +} +.icon-mouse:before { + content: "\e015"; +} +.icon-magnet:before { + content: "\e016"; +} +.icon-energy:before { + content: "\e020"; +} +.icon-disc:before { + content: "\e022"; +} +.icon-cursor:before { + content: "\e06e"; +} +.icon-cursor-move:before { + content: "\e023"; +} +.icon-crop:before { + content: "\e024"; +} +.icon-chemistry:before { + content: "\e026"; +} +.icon-speedometer:before { + content: "\e007"; +} +.icon-shield:before { + content: "\e00e"; +} +.icon-screen-tablet:before { + content: "\e00f"; +} +.icon-magic-wand:before { + content: "\e017"; +} +.icon-hourglass:before { + content: "\e018"; +} +.icon-graduation:before { + content: "\e019"; +} +.icon-ghost:before { + content: "\e01a"; +} +.icon-game-controller:before { + content: "\e01b"; +} +.icon-fire:before { + content: "\e01c"; +} +.icon-eyeglass:before { + content: "\e01d"; +} +.icon-envelope-open:before { + content: "\e01e"; +} +.icon-envelope-letter:before { + content: "\e01f"; +} +.icon-bell:before { + content: "\e027"; +} +.icon-badge:before { + content: "\e028"; +} +.icon-anchor:before { + content: "\e029"; +} +.icon-wallet:before { + content: "\e02a"; +} +.icon-vector:before { + content: "\e02b"; +} +.icon-speech:before { + content: "\e02c"; +} +.icon-puzzle:before { + content: "\e02d"; +} +.icon-printer:before { + content: "\e02e"; +} +.icon-present:before { + content: "\e02f"; +} +.icon-playlist:before { + content: "\e030"; +} +.icon-pin:before { + content: "\e031"; +} +.icon-picture:before { + content: "\e032"; +} +.icon-handbag:before { + content: "\e035"; +} +.icon-globe-alt:before { + content: "\e036"; +} +.icon-globe:before { + content: "\e037"; +} +.icon-folder-alt:before { + content: "\e039"; +} +.icon-folder:before { + content: "\e089"; +} +.icon-film:before { + content: "\e03a"; +} +.icon-feed:before { + content: "\e03b"; +} +.icon-drop:before { + content: "\e03e"; +} +.icon-drawer:before { + content: "\e03f"; +} +.icon-docs:before { + content: "\e040"; +} +.icon-doc:before { + content: "\e085"; +} +.icon-diamond:before { + content: "\e043"; +} +.icon-cup:before { + content: "\e044"; +} +.icon-calculator:before { + content: "\e049"; +} +.icon-bubbles:before { + content: "\e04a"; +} +.icon-briefcase:before { + content: "\e04b"; +} +.icon-book-open:before { + content: "\e04c"; +} +.icon-basket-loaded:before { + content: "\e04d"; +} +.icon-basket:before { + content: "\e04e"; +} +.icon-bag:before { + content: "\e04f"; +} +.icon-action-undo:before { + content: "\e050"; +} +.icon-action-redo:before { + content: "\e051"; +} +.icon-wrench:before { + content: "\e052"; +} +.icon-umbrella:before { + content: "\e053"; +} +.icon-trash:before { + content: "\e054"; +} +.icon-tag:before { + content: "\e055"; +} +.icon-support:before { + content: "\e056"; +} +.icon-frame:before { + content: "\e038"; +} +.icon-size-fullscreen:before { + content: "\e057"; +} +.icon-size-actual:before { + content: "\e058"; +} +.icon-shuffle:before { + content: "\e059"; +} +.icon-share-alt:before { + content: "\e05a"; +} +.icon-share:before { + content: "\e05b"; +} +.icon-rocket:before { + content: "\e05c"; +} +.icon-question:before { + content: "\e05d"; +} +.icon-pie-chart:before { + content: "\e05e"; +} +.icon-pencil:before { + content: "\e05f"; +} +.icon-note:before { + content: "\e060"; +} +.icon-loop:before { + content: "\e064"; +} +.icon-home:before { + content: "\e069"; +} +.icon-grid:before { + content: "\e06a"; +} +.icon-graph:before { + content: "\e06b"; +} +.icon-microphone:before { + content: "\e063"; +} +.icon-music-tone-alt:before { + content: "\e061"; +} +.icon-music-tone:before { + content: "\e062"; +} +.icon-earphones-alt:before { + content: "\e03c"; +} +.icon-earphones:before { + content: "\e03d"; +} +.icon-equalizer:before { + content: "\e06c"; +} +.icon-like:before { + content: "\e068"; +} +.icon-dislike:before { + content: "\e06d"; +} +.icon-control-start:before { + content: "\e06f"; +} +.icon-control-rewind:before { + content: "\e070"; +} +.icon-control-play:before { + content: "\e071"; +} +.icon-control-pause:before { + content: "\e072"; +} +.icon-control-forward:before { + content: "\e073"; +} +.icon-control-end:before { + content: "\e074"; +} +.icon-volume-1:before { + content: "\e09f"; +} +.icon-volume-2:before { + content: "\e0a0"; +} +.icon-volume-off:before { + content: "\e0a1"; +} +.icon-calendar:before { + content: "\e075"; +} +.icon-bulb:before { + content: "\e076"; +} +.icon-chart:before { + content: "\e077"; +} +.icon-ban:before { + content: "\e07c"; +} +.icon-bubble:before { + content: "\e07d"; +} +.icon-camrecorder:before { + content: "\e07e"; +} +.icon-camera:before { + content: "\e07f"; +} +.icon-cloud-download:before { + content: "\e083"; +} +.icon-cloud-upload:before { + content: "\e084"; +} +.icon-envelope:before { + content: "\e086"; +} +.icon-eye:before { + content: "\e087"; +} +.icon-flag:before { + content: "\e088"; +} +.icon-heart:before { + content: "\e08a"; +} +.icon-info:before { + content: "\e08b"; +} +.icon-key:before { + content: "\e08c"; +} +.icon-link:before { + content: "\e08d"; +} +.icon-lock:before { + content: "\e08e"; +} +.icon-lock-open:before { + content: "\e08f"; +} +.icon-magnifier:before { + content: "\e090"; +} +.icon-magnifier-add:before { + content: "\e091"; +} +.icon-magnifier-remove:before { + content: "\e092"; +} +.icon-paper-clip:before { + content: "\e093"; +} +.icon-paper-plane:before { + content: "\e094"; +} +.icon-power:before { + content: "\e097"; +} +.icon-refresh:before { + content: "\e098"; +} +.icon-reload:before { + content: "\e099"; +} +.icon-settings:before { + content: "\e09a"; +} +.icon-star:before { + content: "\e09b"; +} +.icon-symbol-female:before { + content: "\e09c"; +} +.icon-symbol-male:before { + content: "\e09d"; +} +.icon-target:before { + content: "\e09e"; +} +.icon-credit-card:before { + content: "\e025"; +} +.icon-paypal:before { + content: "\e608"; +} +.icon-social-tumblr:before { + content: "\e00a"; +} +.icon-social-twitter:before { + content: "\e009"; +} +.icon-social-facebook:before { + content: "\e00b"; +} +.icon-social-instagram:before { + content: "\e609"; +} +.icon-social-linkedin:before { + content: "\e60a"; +} +.icon-social-pinterest:before { + content: "\e60b"; +} +.icon-social-github:before { + content: "\e60c"; +} +.icon-social-google:before { + content: "\e60d"; +} +.icon-social-reddit:before { + content: "\e60e"; +} +.icon-social-skype:before { + content: "\e60f"; +} +.icon-social-dribbble:before { + content: "\e00d"; +} +.icon-social-behance:before { + content: "\e610"; +} +.icon-social-foursqare:before { + content: "\e611"; +} +.icon-social-soundcloud:before { + content: "\e612"; +} +.icon-social-spotify:before { + content: "\e613"; +} +.icon-social-stumbleupon:before { + content: "\e614"; +} +.icon-social-youtube:before { + content: "\e008"; +} +.icon-social-dropbox:before { + content: "\e00c"; +} +.icon-social-vkontakte:before { + content: "\e618"; +} +.icon-social-steam:before { + content: "\e620"; +} + diff --git a/themes/nurgul/assets/css/plugins.css b/themes/nurgul/assets/css/plugins.css new file mode 100644 index 0000000..354f079 --- /dev/null +++ b/themes/nurgul/assets/css/plugins.css @@ -0,0 +1,85 @@ +/* =================================================== +>>> TABLE OF CONTENTS: +====================================================== +1. Bootstrap v4.1.3 +2. Slick slider +3. Animate css +4. Lightcase +5. Nice Select JS +6. jQuery UI + + +=================================================== */ + +/*--------------------------------------------------------------- + 1. Bootstrap v5.0.2 +---------------------------------------------------------------*/ + +@charset "UTF-8";/*! + * Bootstrap v5.0.2 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors + * Copyright 2011-2021 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0))}*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-font-sans-serif);font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}.small,small{font-size:.875em}.mark,mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:#6c757d}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{width:100%;padding-right:var(--bs-gutter-x,.75rem);padding-left:var(--bs-gutter-x,.75rem);margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}@media (min-width:1400px){.container,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{max-width:1320px}}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-top:calc(var(--bs-gutter-y) * -1);margin-right:calc(var(--bs-gutter-x) * -.5);margin-left:calc(var(--bs-gutter-x) * -.5)}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-top:var(--bs-gutter-y)}.col{flex:1 0 0%}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.6666666667%}@media (min-width:576px){.col-sm{flex:1 0 0%}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.6666666667%}}@media (min-width:768px){.col-md{flex:1 0 0%}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.6666666667%}}@media (min-width:992px){.col-lg{flex:1 0 0%}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.6666666667%}}@media (min-width:1200px){.col-xl{flex:1 0 0%}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.6666666667%}}@media (min-width:1400px){.col-xxl{flex:1 0 0%}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.6666666667%}}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.33333333%}.col-2{flex:0 0 auto;width:16.66666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.33333333%}.col-5{flex:0 0 auto;width:41.66666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.33333333%}.col-8{flex:0 0 auto;width:66.66666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.33333333%}.col-11{flex:0 0 auto;width:91.66666667%}.col-12{flex:0 0 auto;width:100%}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}.g-0,.gx-0{--bs-gutter-x:0}.g-0,.gy-0{--bs-gutter-y:0}.g-1,.gx-1{--bs-gutter-x:0.25rem}.g-1,.gy-1{--bs-gutter-y:0.25rem}.g-2,.gx-2{--bs-gutter-x:0.5rem}.g-2,.gy-2{--bs-gutter-y:0.5rem}.g-3,.gx-3{--bs-gutter-x:1rem}.g-3,.gy-3{--bs-gutter-y:1rem}.g-4,.gx-4{--bs-gutter-x:1.5rem}.g-4,.gy-4{--bs-gutter-y:1.5rem}.g-5,.gx-5{--bs-gutter-x:3rem}.g-5,.gy-5{--bs-gutter-y:3rem}@media (min-width:576px){.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.33333333%}.col-sm-2{flex:0 0 auto;width:16.66666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.33333333%}.col-sm-5{flex:0 0 auto;width:41.66666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.33333333%}.col-sm-8{flex:0 0 auto;width:66.66666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.33333333%}.col-sm-11{flex:0 0 auto;width:91.66666667%}.col-sm-12{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}.g-sm-0,.gx-sm-0{--bs-gutter-x:0}.g-sm-0,.gy-sm-0{--bs-gutter-y:0}.g-sm-1,.gx-sm-1{--bs-gutter-x:0.25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y:0.25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x:0.5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y:0.5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x:1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y:1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x:1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y:1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x:3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y:3rem}}@media (min-width:768px){.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.33333333%}.col-md-2{flex:0 0 auto;width:16.66666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.33333333%}.col-md-5{flex:0 0 auto;width:41.66666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.33333333%}.col-md-8{flex:0 0 auto;width:66.66666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.33333333%}.col-md-11{flex:0 0 auto;width:91.66666667%}.col-md-12{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}.g-md-0,.gx-md-0{--bs-gutter-x:0}.g-md-0,.gy-md-0{--bs-gutter-y:0}.g-md-1,.gx-md-1{--bs-gutter-x:0.25rem}.g-md-1,.gy-md-1{--bs-gutter-y:0.25rem}.g-md-2,.gx-md-2{--bs-gutter-x:0.5rem}.g-md-2,.gy-md-2{--bs-gutter-y:0.5rem}.g-md-3,.gx-md-3{--bs-gutter-x:1rem}.g-md-3,.gy-md-3{--bs-gutter-y:1rem}.g-md-4,.gx-md-4{--bs-gutter-x:1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y:1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x:3rem}.g-md-5,.gy-md-5{--bs-gutter-y:3rem}}@media (min-width:992px){.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.33333333%}.col-lg-2{flex:0 0 auto;width:16.66666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.33333333%}.col-lg-5{flex:0 0 auto;width:41.66666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.33333333%}.col-lg-8{flex:0 0 auto;width:66.66666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.33333333%}.col-lg-11{flex:0 0 auto;width:91.66666667%}.col-lg-12{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}.g-lg-0,.gx-lg-0{--bs-gutter-x:0}.g-lg-0,.gy-lg-0{--bs-gutter-y:0}.g-lg-1,.gx-lg-1{--bs-gutter-x:0.25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y:0.25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x:0.5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y:0.5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x:1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y:1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x:1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y:1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x:3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y:3rem}}@media (min-width:1200px){.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.33333333%}.col-xl-2{flex:0 0 auto;width:16.66666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.33333333%}.col-xl-5{flex:0 0 auto;width:41.66666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.33333333%}.col-xl-8{flex:0 0 auto;width:66.66666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.33333333%}.col-xl-11{flex:0 0 auto;width:91.66666667%}.col-xl-12{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}.g-xl-0,.gx-xl-0{--bs-gutter-x:0}.g-xl-0,.gy-xl-0{--bs-gutter-y:0}.g-xl-1,.gx-xl-1{--bs-gutter-x:0.25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y:0.25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x:0.5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y:0.5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x:1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y:1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x:1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y:1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x:3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y:3rem}}@media (min-width:1400px){.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.33333333%}.col-xxl-2{flex:0 0 auto;width:16.66666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.33333333%}.col-xxl-5{flex:0 0 auto;width:41.66666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.33333333%}.col-xxl-8{flex:0 0 auto;width:66.66666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.33333333%}.col-xxl-11{flex:0 0 auto;width:91.66666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.33333333%}.offset-xxl-2{margin-left:16.66666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.33333333%}.offset-xxl-5{margin-left:41.66666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.33333333%}.offset-xxl-8{margin-left:66.66666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.33333333%}.offset-xxl-11{margin-left:91.66666667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x:0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y:0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x:0.25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y:0.25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x:0.5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y:0.5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x:1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y:1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x:1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y:1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x:3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y:3rem}}.table{--bs-table-bg:transparent;--bs-table-accent-bg:transparent;--bs-table-striped-color:#212529;--bs-table-striped-bg:rgba(0, 0, 0, 0.05);--bs-table-active-color:#212529;--bs-table-active-bg:rgba(0, 0, 0, 0.1);--bs-table-hover-color:#212529;--bs-table-hover-bg:rgba(0, 0, 0, 0.075);width:100%;margin-bottom:1rem;color:#212529;vertical-align:top;border-color:#dee2e6}.table>:not(caption)>*>*{padding:.5rem .5rem;background-color:var(--bs-table-bg);border-bottom-width:1px;box-shadow:inset 0 0 0 9999px var(--bs-table-accent-bg)}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table>:not(:last-child)>:last-child>*{border-bottom-color:currentColor}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:1px 0}.table-bordered>:not(caption)>*>*{border-width:0 1px}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-striped>tbody>tr:nth-of-type(odd){--bs-table-accent-bg:var(--bs-table-striped-bg);color:var(--bs-table-striped-color)}.table-active{--bs-table-accent-bg:var(--bs-table-active-bg);color:var(--bs-table-active-color)}.table-hover>tbody>tr:hover{--bs-table-accent-bg:var(--bs-table-hover-bg);color:var(--bs-table-hover-color)}.table-primary{--bs-table-bg:#cfe2ff;--bs-table-striped-bg:#c5d7f2;--bs-table-striped-color:#000;--bs-table-active-bg:#bacbe6;--bs-table-active-color:#000;--bs-table-hover-bg:#bfd1ec;--bs-table-hover-color:#000;color:#000;border-color:#bacbe6}.table-secondary{--bs-table-bg:#e2e3e5;--bs-table-striped-bg:#d7d8da;--bs-table-striped-color:#000;--bs-table-active-bg:#cbccce;--bs-table-active-color:#000;--bs-table-hover-bg:#d1d2d4;--bs-table-hover-color:#000;color:#000;border-color:#cbccce}.table-success{--bs-table-bg:#d1e7dd;--bs-table-striped-bg:#c7dbd2;--bs-table-striped-color:#000;--bs-table-active-bg:#bcd0c7;--bs-table-active-color:#000;--bs-table-hover-bg:#c1d6cc;--bs-table-hover-color:#000;color:#000;border-color:#bcd0c7}.table-info{--bs-table-bg:#cff4fc;--bs-table-striped-bg:#c5e8ef;--bs-table-striped-color:#000;--bs-table-active-bg:#badce3;--bs-table-active-color:#000;--bs-table-hover-bg:#bfe2e9;--bs-table-hover-color:#000;color:#000;border-color:#badce3}.table-warning{--bs-table-bg:#fff3cd;--bs-table-striped-bg:#f2e7c3;--bs-table-striped-color:#000;--bs-table-active-bg:#e6dbb9;--bs-table-active-color:#000;--bs-table-hover-bg:#ece1be;--bs-table-hover-color:#000;color:#000;border-color:#e6dbb9}.table-danger{--bs-table-bg:#f8d7da;--bs-table-striped-bg:#eccccf;--bs-table-striped-color:#000;--bs-table-active-bg:#dfc2c4;--bs-table-active-color:#000;--bs-table-hover-bg:#e5c7ca;--bs-table-hover-color:#000;color:#000;border-color:#dfc2c4}.table-light{--bs-table-bg:#f8f9fa;--bs-table-striped-bg:#ecedee;--bs-table-striped-color:#000;--bs-table-active-bg:#dfe0e1;--bs-table-active-color:#000;--bs-table-hover-bg:#e5e6e7;--bs-table-hover-color:#000;color:#000;border-color:#dfe0e1}.table-dark{--bs-table-bg:#212529;--bs-table-striped-bg:#2c3034;--bs-table-striped-color:#fff;--bs-table-active-bg:#373b3e;--bs-table-active-color:#fff;--bs-table-hover-bg:#323539;--bs-table-hover-color:#fff;color:#fff;border-color:#373b3e}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media (max-width:575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem}.form-text{margin-top:.25rem;font-size:.875em;color:#6c757d}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:#212529;background-color:#fff;border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-control::-webkit-date-and-time-value{height:1.5em}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}.form-control::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:#212529;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:#dde0e3}.form-control::-webkit-file-upload-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:#212529;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::-webkit-file-upload-button{-webkit-transition:none;transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:#dde0e3}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + (.5rem + 2px));padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-sm::-webkit-file-upload-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + (1rem + 2px));padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}.form-control-lg::-webkit-file-upload-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + (.75rem + 2px))}textarea.form-control-sm{min-height:calc(1.5em + (.5rem + 2px))}textarea.form-control-lg{min-height:calc(1.5em + (1rem + 2px))}.form-control-color{max-width:3rem;height:auto;padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{height:1.5em;border-radius:.25rem}.form-control-color::-webkit-color-swatch{height:1.5em;border-radius:.25rem}.form-select{display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;-moz-padding-start:calc(0.75rem - 3px);font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-select{transition:none}}.form-select:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:#e9ecef}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #212529}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.form-check{display:block;min-height:1.5rem;padding-left:1.5em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-input{width:1em;height:1em;margin-top:.25em;vertical-align:top;background-color:#fff;background-repeat:no-repeat;background-position:center;background-size:contain;border:1px solid rgba(0,0,0,.25);-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-print-color-adjust:exact;color-adjust:exact}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-check-input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-input:checked[type=checkbox]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:#0d6efd;border-color:#0d6efd;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{width:2em;margin-left:-2.5em;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn-check:disabled+.btn,.btn-check[disabled]+.btn{pointer-events:none;filter:none;opacity:.65}.form-range{width:100%;height:1.5rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#0d6efd;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b6d4fe}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#0d6efd;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-range::-moz-range-thumb{-moz-transition:none;transition:none}}.form-range::-moz-range-thumb:active{background-color:#b6d4fe}.form-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.form-range:disabled::-moz-range-thumb{background-color:#adb5bd}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-select{height:calc(3.5rem + 2px);line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;height:100%;padding:1rem .75rem;pointer-events:none;border:1px solid transparent;transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media (prefers-reduced-motion:reduce){.form-floating>label{transition:none}}.form-floating>.form-control{padding:1rem .75rem}.form-floating>.form-control::-moz-placeholder{color:transparent}.form-floating>.form-control::placeholder{color:transparent}.form-floating>.form-control:not(:-moz-placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:not(:-moz-placeholder-shown)~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:-webkit-autofill~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-select{position:relative;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-select:focus{z-index:3}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:3}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-lg>.btn,.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.input-group-sm>.btn,.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:-1px;border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#198754}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(25,135,84,.9);border-radius:.25rem}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#198754;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-valid,.was-validated .form-select:valid{border-color:#198754}.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"],.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-valid:focus,.was-validated .form-select:valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.form-check-input.is-valid,.was-validated .form-check-input:valid{border-color:#198754}.form-check-input.is-valid:checked,.was-validated .form-check-input:valid:checked{background-color:#198754}.form-check-input.is-valid:focus,.was-validated .form-check-input:valid:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#198754}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.input-group .form-control.is-valid,.input-group .form-select.is-valid,.was-validated .input-group .form-control:valid,.was-validated .input-group .form-select:valid{z-index:1}.input-group .form-control.is-valid:focus,.input-group .form-select.is-valid:focus,.was-validated .input-group .form-control:valid:focus,.was-validated .input-group .form-select:valid:focus{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-invalid,.was-validated .form-select:invalid{border-color:#dc3545}.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"],.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-invalid:focus,.was-validated .form-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.form-check-input.is-invalid,.was-validated .form-check-input:invalid{border-color:#dc3545}.form-check-input.is-invalid:checked,.was-validated .form-check-input:invalid:checked{background-color:#dc3545}.form-check-input.is-invalid:focus,.was-validated .form-check-input:invalid:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.input-group .form-control.is-invalid,.input-group .form-select.is-invalid,.was-validated .input-group .form-control:invalid,.was-validated .input-group .form-select:invalid{z-index:2}.input-group .form-control.is-invalid:focus,.input-group .form-select.is-invalid:focus,.was-validated .input-group .form-control:invalid:focus,.was-validated .input-group .form-select:invalid:focus{z-index:3}.btn{display:inline-block;font-weight:400;line-height:1.5;color:#212529;text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529}.btn-check:focus+.btn,.btn:focus{outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.btn.disabled,.btn:disabled,fieldset:disabled .btn{pointer-events:none;opacity:.65}.btn-primary{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-primary:hover{color:#fff;background-color:#0b5ed7;border-color:#0a58ca}.btn-check:focus+.btn-primary,.btn-primary:focus{color:#fff;background-color:#0b5ed7;border-color:#0a58ca;box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.btn-check:active+.btn-primary,.btn-check:checked+.btn-primary,.btn-primary.active,.btn-primary:active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0a58ca;border-color:#0a53be}.btn-check:active+.btn-primary:focus,.btn-check:checked+.btn-primary:focus,.btn-primary.active:focus,.btn-primary:active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5c636a;border-color:#565e64}.btn-check:focus+.btn-secondary,.btn-secondary:focus{color:#fff;background-color:#5c636a;border-color:#565e64;box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.btn-check:active+.btn-secondary,.btn-check:checked+.btn-secondary,.btn-secondary.active,.btn-secondary:active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#565e64;border-color:#51585e}.btn-check:active+.btn-secondary:focus,.btn-check:checked+.btn-secondary:focus,.btn-secondary.active:focus,.btn-secondary:active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-success{color:#fff;background-color:#198754;border-color:#198754}.btn-success:hover{color:#fff;background-color:#157347;border-color:#146c43}.btn-check:focus+.btn-success,.btn-success:focus{color:#fff;background-color:#157347;border-color:#146c43;box-shadow:0 0 0 .25rem rgba(60,153,110,.5)}.btn-check:active+.btn-success,.btn-check:checked+.btn-success,.btn-success.active,.btn-success:active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#146c43;border-color:#13653f}.btn-check:active+.btn-success:focus,.btn-check:checked+.btn-success:focus,.btn-success.active:focus,.btn-success:active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(60,153,110,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#198754;border-color:#198754}.btn-info{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-info:hover{color:#000;background-color:#31d2f2;border-color:#25cff2}.btn-check:focus+.btn-info,.btn-info:focus{color:#000;background-color:#31d2f2;border-color:#25cff2;box-shadow:0 0 0 .25rem rgba(11,172,204,.5)}.btn-check:active+.btn-info,.btn-check:checked+.btn-info,.btn-info.active,.btn-info:active,.show>.btn-info.dropdown-toggle{color:#000;background-color:#3dd5f3;border-color:#25cff2}.btn-check:active+.btn-info:focus,.btn-check:checked+.btn-info:focus,.btn-info.active:focus,.btn-info:active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(11,172,204,.5)}.btn-info.disabled,.btn-info:disabled{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-warning{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#000;background-color:#ffca2c;border-color:#ffc720}.btn-check:focus+.btn-warning,.btn-warning:focus{color:#000;background-color:#ffca2c;border-color:#ffc720;box-shadow:0 0 0 .25rem rgba(217,164,6,.5)}.btn-check:active+.btn-warning,.btn-check:checked+.btn-warning,.btn-warning.active,.btn-warning:active,.show>.btn-warning.dropdown-toggle{color:#000;background-color:#ffcd39;border-color:#ffc720}.btn-check:active+.btn-warning:focus,.btn-check:checked+.btn-warning:focus,.btn-warning.active:focus,.btn-warning:active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(217,164,6,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#bb2d3b;border-color:#b02a37}.btn-check:focus+.btn-danger,.btn-danger:focus{color:#fff;background-color:#bb2d3b;border-color:#b02a37;box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.btn-check:active+.btn-danger,.btn-check:checked+.btn-danger,.btn-danger.active,.btn-danger:active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#b02a37;border-color:#a52834}.btn-check:active+.btn-danger:focus,.btn-check:checked+.btn-danger:focus,.btn-danger.active:focus,.btn-danger:active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-light{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#000;background-color:#f9fafb;border-color:#f9fafb}.btn-check:focus+.btn-light,.btn-light:focus{color:#000;background-color:#f9fafb;border-color:#f9fafb;box-shadow:0 0 0 .25rem rgba(211,212,213,.5)}.btn-check:active+.btn-light,.btn-check:checked+.btn-light,.btn-light.active,.btn-light:active,.show>.btn-light.dropdown-toggle{color:#000;background-color:#f9fafb;border-color:#f9fafb}.btn-check:active+.btn-light:focus,.btn-check:checked+.btn-light:focus,.btn-light.active:focus,.btn-light:active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(211,212,213,.5)}.btn-light.disabled,.btn-light:disabled{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-dark{color:#fff;background-color:#212529;border-color:#212529}.btn-dark:hover{color:#fff;background-color:#1c1f23;border-color:#1a1e21}.btn-check:focus+.btn-dark,.btn-dark:focus{color:#fff;background-color:#1c1f23;border-color:#1a1e21;box-shadow:0 0 0 .25rem rgba(66,70,73,.5)}.btn-check:active+.btn-dark,.btn-check:checked+.btn-dark,.btn-dark.active,.btn-dark:active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1a1e21;border-color:#191c1f}.btn-check:active+.btn-dark:focus,.btn-check:checked+.btn-dark:focus,.btn-dark.active:focus,.btn-dark:active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(66,70,73,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#212529;border-color:#212529}.btn-outline-primary{color:#0d6efd;border-color:#0d6efd}.btn-outline-primary:hover{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-check:focus+.btn-outline-primary,.btn-outline-primary:focus{box-shadow:0 0 0 .25rem rgba(13,110,253,.5)}.btn-check:active+.btn-outline-primary,.btn-check:checked+.btn-outline-primary,.btn-outline-primary.active,.btn-outline-primary.dropdown-toggle.show,.btn-outline-primary:active{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-check:active+.btn-outline-primary:focus,.btn-check:checked+.btn-outline-primary:focus,.btn-outline-primary.active:focus,.btn-outline-primary.dropdown-toggle.show:focus,.btn-outline-primary:active:focus{box-shadow:0 0 0 .25rem rgba(13,110,253,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#0d6efd;background-color:transparent}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-check:focus+.btn-outline-secondary,.btn-outline-secondary:focus{box-shadow:0 0 0 .25rem rgba(108,117,125,.5)}.btn-check:active+.btn-outline-secondary,.btn-check:checked+.btn-outline-secondary,.btn-outline-secondary.active,.btn-outline-secondary.dropdown-toggle.show,.btn-outline-secondary:active{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-check:active+.btn-outline-secondary:focus,.btn-check:checked+.btn-outline-secondary:focus,.btn-outline-secondary.active:focus,.btn-outline-secondary.dropdown-toggle.show:focus,.btn-outline-secondary:active:focus{box-shadow:0 0 0 .25rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-success{color:#198754;border-color:#198754}.btn-outline-success:hover{color:#fff;background-color:#198754;border-color:#198754}.btn-check:focus+.btn-outline-success,.btn-outline-success:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.5)}.btn-check:active+.btn-outline-success,.btn-check:checked+.btn-outline-success,.btn-outline-success.active,.btn-outline-success.dropdown-toggle.show,.btn-outline-success:active{color:#fff;background-color:#198754;border-color:#198754}.btn-check:active+.btn-outline-success:focus,.btn-check:checked+.btn-outline-success:focus,.btn-outline-success.active:focus,.btn-outline-success.dropdown-toggle.show:focus,.btn-outline-success:active:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#198754;background-color:transparent}.btn-outline-info{color:#0dcaf0;border-color:#0dcaf0}.btn-outline-info:hover{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-check:focus+.btn-outline-info,.btn-outline-info:focus{box-shadow:0 0 0 .25rem rgba(13,202,240,.5)}.btn-check:active+.btn-outline-info,.btn-check:checked+.btn-outline-info,.btn-outline-info.active,.btn-outline-info.dropdown-toggle.show,.btn-outline-info:active{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-check:active+.btn-outline-info:focus,.btn-check:checked+.btn-outline-info:focus,.btn-outline-info.active:focus,.btn-outline-info.dropdown-toggle.show:focus,.btn-outline-info:active:focus{box-shadow:0 0 0 .25rem rgba(13,202,240,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#0dcaf0;background-color:transparent}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-check:focus+.btn-outline-warning,.btn-outline-warning:focus{box-shadow:0 0 0 .25rem rgba(255,193,7,.5)}.btn-check:active+.btn-outline-warning,.btn-check:checked+.btn-outline-warning,.btn-outline-warning.active,.btn-outline-warning.dropdown-toggle.show,.btn-outline-warning:active{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-check:active+.btn-outline-warning:focus,.btn-check:checked+.btn-outline-warning:focus,.btn-outline-warning.active:focus,.btn-outline-warning.dropdown-toggle.show:focus,.btn-outline-warning:active:focus{box-shadow:0 0 0 .25rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-check:focus+.btn-outline-danger,.btn-outline-danger:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.5)}.btn-check:active+.btn-outline-danger,.btn-check:checked+.btn-outline-danger,.btn-outline-danger.active,.btn-outline-danger.dropdown-toggle.show,.btn-outline-danger:active{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-check:active+.btn-outline-danger:focus,.btn-check:checked+.btn-outline-danger:focus,.btn-outline-danger.active:focus,.btn-outline-danger.dropdown-toggle.show:focus,.btn-outline-danger:active:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-check:focus+.btn-outline-light,.btn-outline-light:focus{box-shadow:0 0 0 .25rem rgba(248,249,250,.5)}.btn-check:active+.btn-outline-light,.btn-check:checked+.btn-outline-light,.btn-outline-light.active,.btn-outline-light.dropdown-toggle.show,.btn-outline-light:active{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-check:active+.btn-outline-light:focus,.btn-check:checked+.btn-outline-light:focus,.btn-outline-light.active:focus,.btn-outline-light.dropdown-toggle.show:focus,.btn-outline-light:active:focus{box-shadow:0 0 0 .25rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-dark{color:#212529;border-color:#212529}.btn-outline-dark:hover{color:#fff;background-color:#212529;border-color:#212529}.btn-check:focus+.btn-outline-dark,.btn-outline-dark:focus{box-shadow:0 0 0 .25rem rgba(33,37,41,.5)}.btn-check:active+.btn-outline-dark,.btn-check:checked+.btn-outline-dark,.btn-outline-dark.active,.btn-outline-dark.dropdown-toggle.show,.btn-outline-dark:active{color:#fff;background-color:#212529;border-color:#212529}.btn-check:active+.btn-outline-dark:focus,.btn-check:checked+.btn-outline-dark:focus,.btn-outline-dark.active:focus,.btn-outline-dark.dropdown-toggle.show:focus,.btn-outline-dark:active:focus{box-shadow:0 0 0 .25rem rgba(33,37,41,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#212529;background-color:transparent}.btn-link{font-weight:400;color:#0d6efd;text-decoration:underline}.btn-link:hover{color:#0a58ca}.btn-link.disabled,.btn-link:disabled{color:#6c757d}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropend,.dropstart,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;z-index:1000;display:none;min-width:10rem;padding:.5rem 0;margin:0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:.125rem}.dropdown-menu-start{--bs-position:start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position:end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-start{--bs-position:start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position:end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-start{--bs-position:start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position:end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-start{--bs-position:start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position:end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-start{--bs-position:start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position:end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1400px){.dropdown-menu-xxl-start{--bs-position:start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position:end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid rgba(0,0,0,.15)}.dropdown-item{display:block;width:100%;padding:.25rem 1rem;clear:both;font-weight:400;color:#212529;text-align:inherit;text-decoration:none;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#1e2125;background-color:#e9ecef}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#0d6efd}.dropdown-item.disabled,.dropdown-item:disabled{color:#adb5bd;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1rem;color:#212529}.dropdown-menu-dark{color:#dee2e6;background-color:#343a40;border-color:rgba(0,0,0,.15)}.dropdown-menu-dark .dropdown-item{color:#dee2e6}.dropdown-menu-dark .dropdown-item:focus,.dropdown-menu-dark .dropdown-item:hover{color:#fff;background-color:rgba(255,255,255,.15)}.dropdown-menu-dark .dropdown-item.active,.dropdown-menu-dark .dropdown-item:active{color:#fff;background-color:#0d6efd}.dropdown-menu-dark .dropdown-item.disabled,.dropdown-menu-dark .dropdown-item:disabled{color:#adb5bd}.dropdown-menu-dark .dropdown-divider{border-color:rgba(0,0,0,.15)}.dropdown-menu-dark .dropdown-item-text{color:#dee2e6}.dropdown-menu-dark .dropdown-header{color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;flex:1 1 auto}.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn~.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem;color:#0d6efd;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link:focus,.nav-link:hover{color:#0a58ca}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link{margin-bottom:-1px;background:0 0;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6;isolation:isolate}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{background:0 0;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#0d6efd}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-basis:0;flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding-top:.5rem;padding-bottom:.5rem}.navbar>.container,.navbar>.container-fluid,.navbar>.container-lg,.navbar>.container-md,.navbar>.container-sm,.navbar>.container-xl,.navbar>.container-xxl{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;text-decoration:none;white-space:nowrap}.navbar-nav{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem;transition:box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 .25rem}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height,75vh);overflow-y:auto}@media (min-width:576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (min-width:768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (min-width:992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (min-width:1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}@media (min-width:1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.55)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.55);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.55)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.55)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.55);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.55)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:flex;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;padding:1rem 1rem}.card-title{margin-bottom:.5rem}.card-subtitle{margin-top:-.25rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1rem}.card-header{padding:.5rem 1rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.5rem 1rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.5rem;margin-bottom:-.5rem;margin-left:-.5rem;border-bottom:0}.card-header-pills{margin-right:-.5rem;margin-left:-.5rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom,.card-img-top{width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-group>.card{margin-bottom:.75rem}@media (min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.accordion-button{position:relative;display:flex;align-items:center;width:100%;padding:1rem 1.25rem;font-size:1rem;color:#212529;text-align:left;background-color:#fff;border:0;border-radius:0;overflow-anchor:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,border-radius .15s ease}@media (prefers-reduced-motion:reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:#0c63e4;background-color:#e7f1ff;box-shadow:inset 0 -1px 0 rgba(0,0,0,.125)}.accordion-button:not(.collapsed)::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");transform:rotate(-180deg)}.accordion-button::after{flex-shrink:0;width:1.25rem;height:1.25rem;margin-left:auto;content:"";background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-size:1.25rem;transition:transform .2s ease-in-out}@media (prefers-reduced-motion:reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.accordion-header{margin-bottom:0}.accordion-item{background-color:#fff;border:1px solid rgba(0,0,0,.125)}.accordion-item:first-of-type{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.accordion-item:first-of-type .accordion-button{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.accordion-item:last-of-type .accordion-button.collapsed{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.accordion-item:last-of-type .accordion-collapse{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.accordion-body{padding:1rem 1.25rem}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush .accordion-item:first-child{border-top:0}.accordion-flush .accordion-item:last-child{border-bottom:0}.accordion-flush .accordion-item .accordion-button{border-radius:0}.breadcrumb{display:flex;flex-wrap:wrap;padding:0 0;margin-bottom:1rem;list-style:none}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:.5rem;color:#6c757d;content:var(--bs-breadcrumb-divider, "/")}.breadcrumb-item.active{color:#6c757d}.pagination{display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;color:#0d6efd;text-decoration:none;background-color:#fff;border:1px solid #dee2e6;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:#0a58ca;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;color:#0a58ca;background-color:#e9ecef;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.page-item:not(:first-child) .page-link{margin-left:-1px}.page-item.active .page-link{z-index:3;color:#fff;background-color:#0d6efd;border-color:#0d6efd}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;background-color:#fff;border-color:#dee2e6}.page-link{padding:.375rem .75rem}.page-item:first-child .page-link{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{position:relative;padding:1rem 1rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-primary{color:#084298;background-color:#cfe2ff;border-color:#b6d4fe}.alert-primary .alert-link{color:#06357a}.alert-secondary{color:#41464b;background-color:#e2e3e5;border-color:#d3d6d8}.alert-secondary .alert-link{color:#34383c}.alert-success{color:#0f5132;background-color:#d1e7dd;border-color:#badbcc}.alert-success .alert-link{color:#0c4128}.alert-info{color:#055160;background-color:#cff4fc;border-color:#b6effb}.alert-info .alert-link{color:#04414d}.alert-warning{color:#664d03;background-color:#fff3cd;border-color:#ffecb5}.alert-warning .alert-link{color:#523e02}.alert-danger{color:#842029;background-color:#f8d7da;border-color:#f5c2c7}.alert-danger .alert-link{color:#6a1a21}.alert-light{color:#636464;background-color:#fefefe;border-color:#fdfdfe}.alert-light .alert-link{color:#4f5050}.alert-dark{color:#141619;background-color:#d3d3d4;border-color:#bcbebf}.alert-dark .alert-link{color:#101214}@-webkit-keyframes progress-bar-stripes{0%{background-position-x:1rem}}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress{display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#0d6efd;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:1s linear infinite progress-bar-stripes;animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.list-group{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>li::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.5rem 1rem;color:#212529;text-decoration:none;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#0d6efd;border-color:#0d6efd}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#084298;background-color:#cfe2ff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#084298;background-color:#bacbe6}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#084298;border-color:#084298}.list-group-item-secondary{color:#41464b;background-color:#e2e3e5}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#41464b;background-color:#cbccce}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#41464b;border-color:#41464b}.list-group-item-success{color:#0f5132;background-color:#d1e7dd}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#0f5132;background-color:#bcd0c7}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#0f5132;border-color:#0f5132}.list-group-item-info{color:#055160;background-color:#cff4fc}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#055160;background-color:#badce3}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#055160;border-color:#055160}.list-group-item-warning{color:#664d03;background-color:#fff3cd}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#664d03;background-color:#e6dbb9}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#664d03;border-color:#664d03}.list-group-item-danger{color:#842029;background-color:#f8d7da}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#842029;background-color:#dfc2c4}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#842029;border-color:#842029}.list-group-item-light{color:#636464;background-color:#fefefe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#636464;background-color:#e5e5e5}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#636464;border-color:#636464}.list-group-item-dark{color:#141619;background-color:#d3d3d4}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#141619;background-color:#bebebf}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#141619;border-color:#141619}.btn-close{box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:#000;background:transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat;border:0;border-radius:.25rem;opacity:.5}.btn-close:hover{color:#000;text-decoration:none;opacity:.75}.btn-close:focus{outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25);opacity:1}.btn-close.disabled,.btn-close:disabled{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;opacity:.25}.btn-close-white{filter:invert(1) grayscale(100%) brightness(200%)}.toast{width:350px;max-width:100%;font-size:.875rem;pointer-events:auto;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .5rem 1rem rgba(0,0,0,.15);border-radius:.25rem}.toast:not(.showing):not(.show){opacity:0}.toast.hide{display:none}.toast-container{width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:.75rem}.toast-header{display:flex;align-items:center;padding:.5rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.toast-header .btn-close{margin-right:-.375rem;margin-left:.75rem}.toast-body{padding:.75rem;word-wrap:break-word}.modal{position:fixed;top:0;left:0;z-index:1060;display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - 1rem)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:flex;flex-shrink:0;align-items:center;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .btn-close{padding:.5rem .5rem;margin:-.5rem -.5rem -.5rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;flex:1 1 auto;padding:1rem}.modal-footer{display:flex;flex-wrap:wrap;flex-shrink:0;align-items:center;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{height:calc(100% - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}.modal-fullscreen .modal-footer{border-radius:0}@media (max-width:575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}.modal-fullscreen-sm-down .modal-footer{border-radius:0}}@media (max-width:767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}.modal-fullscreen-md-down .modal-footer{border-radius:0}}@media (max-width:991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}.modal-fullscreen-lg-down .modal-footer{border-radius:0}}@media (max-width:1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}.modal-fullscreen-xl-down .modal-footer{border-radius:0}}@media (max-width:1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}.modal-fullscreen-xxl-down .modal-footer{border-radius:0}}.tooltip{position:absolute;z-index:1080;display:block;margin:0;font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .tooltip-arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[data-popper-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow,.bs-tooltip-top .tooltip-arrow{bottom:0}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before,.bs-tooltip-top .tooltip-arrow::before{top:-1px;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[data-popper-placement^=right],.bs-tooltip-end{padding:0 .4rem}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow,.bs-tooltip-end .tooltip-arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before,.bs-tooltip-end .tooltip-arrow::before{right:-1px;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[data-popper-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow,.bs-tooltip-bottom .tooltip-arrow{top:0}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before,.bs-tooltip-bottom .tooltip-arrow::before{bottom:-1px;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[data-popper-placement^=left],.bs-tooltip-start{padding:0 .4rem}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow,.bs-tooltip-start .tooltip-arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before,.bs-tooltip-start .tooltip-arrow::before{left:-1px;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1070;display:block;max-width:276px;font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .popover-arrow{position:absolute;display:block;width:1rem;height:.5rem}.popover .popover-arrow::after,.popover .popover-arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow,.bs-popover-top>.popover-arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-top>.popover-arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow,.bs-popover-end>.popover-arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-end>.popover-arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow,.bs-popover-bottom>.popover-arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f0f0f0}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow,.bs-popover-start>.popover-arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-start>.popover-arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem 1rem;margin-bottom:0;font-size:1rem;background-color:#f0f0f0;border-bottom:1px solid rgba(0,0,0,.2);border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:1rem 1rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-end,.carousel-item-next:not(.carousel-item-start){transform:translateX(100%)}.active.carousel-item-start,.carousel-item-prev:not(.carousel-item-end){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%;list-style:none}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border:0;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:#fff;text-align:center}.carousel-dark .carousel-control-next-icon,.carousel-dark .carousel-control-prev-icon{filter:invert(1) grayscale(100)}.carousel-dark .carousel-indicators [data-bs-target]{background-color:#000}.carousel-dark .carousel-caption{color:#000}@-webkit-keyframes spinner-border{to{transform:rotate(360deg)}}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:.75s linear infinite spinner-border;animation:.75s linear infinite spinner-border}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:.75s linear infinite spinner-grow;animation:.75s linear infinite spinner-grow}.spinner-grow-sm{width:1rem;height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{-webkit-animation-duration:1.5s;animation-duration:1.5s}}.offcanvas{position:fixed;bottom:0;z-index:1050;display:flex;flex-direction:column;max-width:100%;visibility:hidden;background-color:#fff;background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}@media (prefers-reduced-motion:reduce){.offcanvas{transition:none}}.offcanvas-header{display:flex;align-items:center;justify-content:space-between;padding:1rem 1rem}.offcanvas-header .btn-close{padding:.5rem .5rem;margin-top:-.5rem;margin-right:-.5rem;margin-bottom:-.5rem}.offcanvas-title{margin-bottom:0;line-height:1.5}.offcanvas-body{flex-grow:1;padding:1rem 1rem;overflow-y:auto}.offcanvas-start{top:0;left:0;width:400px;border-right:1px solid rgba(0,0,0,.2);transform:translateX(-100%)}.offcanvas-end{top:0;right:0;width:400px;border-left:1px solid rgba(0,0,0,.2);transform:translateX(100%)}.offcanvas-top{top:0;right:0;left:0;height:30vh;max-height:100%;border-bottom:1px solid rgba(0,0,0,.2);transform:translateY(-100%)}.offcanvas-bottom{right:0;left:0;height:30vh;max-height:100%;border-top:1px solid rgba(0,0,0,.2);transform:translateY(100%)}.offcanvas.show{transform:none}.clearfix::after{display:block;clear:both;content:""}.link-primary{color:#0d6efd}.link-primary:focus,.link-primary:hover{color:#0a58ca}.link-secondary{color:#6c757d}.link-secondary:focus,.link-secondary:hover{color:#565e64}.link-success{color:#198754}.link-success:focus,.link-success:hover{color:#146c43}.link-info{color:#0dcaf0}.link-info:focus,.link-info:hover{color:#3dd5f3}.link-warning{color:#ffc107}.link-warning:focus,.link-warning:hover{color:#ffcd39}.link-danger{color:#dc3545}.link-danger:focus,.link-danger:hover{color:#b02a37}.link-light{color:#f8f9fa}.link-light:focus,.link-light:hover{color:#f9fafb}.link-dark{color:#212529}.link-dark:focus,.link-dark:hover{color:#1a1e21}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio:100%}.ratio-4x3{--bs-aspect-ratio:calc(3 / 4 * 100%)}.ratio-16x9{--bs-aspect-ratio:calc(9 / 16 * 100%)}.ratio-21x9{--bs-aspect-ratio:calc(9 / 21 * 100%)}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}@media (min-width:576px){.sticky-sm-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:768px){.sticky-md-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:992px){.sticky-lg-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:1200px){.sticky-xl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:1400px){.sticky-xxl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.float-start{float:left!important}.float-end{float:right!important}.float-none{float:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-scroll{overflow:scroll!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-grid{display:grid!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}.d-none{display:none!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.top-0{top:0!important}.top-50{top:50%!important}.top-100{top:100%!important}.bottom-0{bottom:0!important}.bottom-50{bottom:50%!important}.bottom-100{bottom:100%!important}.start-0{left:0!important}.start-50{left:50%!important}.start-100{left:100%!important}.end-0{right:0!important}.end-50{right:50%!important}.end-100{right:100%!important}.translate-middle{transform:translate(-50%,-50%)!important}.translate-middle-x{transform:translateX(-50%)!important}.translate-middle-y{transform:translateY(-50%)!important}.border{border:1px solid #dee2e6!important}.border-0{border:0!important}.border-top{border-top:1px solid #dee2e6!important}.border-top-0{border-top:0!important}.border-end{border-right:1px solid #dee2e6!important}.border-end-0{border-right:0!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-bottom-0{border-bottom:0!important}.border-start{border-left:1px solid #dee2e6!important}.border-start-0{border-left:0!important}.border-primary{border-color:#0d6efd!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#198754!important}.border-info{border-color:#0dcaf0!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#212529!important}.border-white{border-color:#fff!important}.border-1{border-width:1px!important}.border-2{border-width:2px!important}.border-3{border-width:3px!important}.border-4{border-width:4px!important}.border-5{border-width:5px!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mh-100{max-height:100%!important}.vh-100{height:100vh!important}.min-vh-100{min-height:100vh!important}.flex-fill{flex:1 1 auto!important}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:1rem!important}.gap-4{gap:1.5rem!important}.gap-5{gap:3rem!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.justify-content-evenly{justify-content:space-evenly!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}.order-first{order:-1!important}.order-0{order:0!important}.order-1{order:1!important}.order-2{order:2!important}.order-3{order:3!important}.order-4{order:4!important}.order-5{order:5!important}.order-last{order:6!important}.m-0{margin:0!important}.m-1{margin:.25rem!important}.m-2{margin:.5rem!important}.m-3{margin:1rem!important}.m-4{margin:1.5rem!important}.m-5{margin:3rem!important}.m-auto{margin:auto!important}.mx-0{margin-right:0!important;margin-left:0!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-5{margin-right:3rem!important;margin-left:3rem!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-0{margin-top:0!important;margin-bottom:0!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:3rem!important}.mt-auto{margin-top:auto!important}.me-0{margin-right:0!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.me-3{margin-right:1rem!important}.me-4{margin-right:1.5rem!important}.me-5{margin-right:3rem!important}.me-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:3rem!important}.mb-auto{margin-bottom:auto!important}.ms-0{margin-left:0!important}.ms-1{margin-left:.25rem!important}.ms-2{margin-left:.5rem!important}.ms-3{margin-left:1rem!important}.ms-4{margin-left:1.5rem!important}.ms-5{margin-left:3rem!important}.ms-auto{margin-left:auto!important}.p-0{padding:0!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:3rem!important}.px-0{padding-right:0!important;padding-left:0!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-5{padding-right:3rem!important;padding-left:3rem!important}.py-0{padding-top:0!important;padding-bottom:0!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:3rem!important}.pe-0{padding-right:0!important}.pe-1{padding-right:.25rem!important}.pe-2{padding-right:.5rem!important}.pe-3{padding-right:1rem!important}.pe-4{padding-right:1.5rem!important}.pe-5{padding-right:3rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-3{padding-bottom:1rem!important}.pb-4{padding-bottom:1.5rem!important}.pb-5{padding-bottom:3rem!important}.ps-0{padding-left:0!important}.ps-1{padding-left:.25rem!important}.ps-2{padding-left:.5rem!important}.ps-3{padding-left:1rem!important}.ps-4{padding-left:1.5rem!important}.ps-5{padding-left:3rem!important}.font-monospace{font-family:var(--bs-font-monospace)!important}.fs-1{font-size:calc(1.375rem + 1.5vw)!important}.fs-2{font-size:calc(1.325rem + .9vw)!important}.fs-3{font-size:calc(1.3rem + .6vw)!important}.fs-4{font-size:calc(1.275rem + .3vw)!important}.fs-5{font-size:1.25rem!important}.fs-6{font-size:1rem!important}.fst-italic{font-style:italic!important}.fst-normal{font-style:normal!important}.fw-light{font-weight:300!important}.fw-lighter{font-weight:lighter!important}.fw-normal{font-weight:400!important}.fw-bold{font-weight:700!important}.fw-bolder{font-weight:bolder!important}.lh-1{line-height:1!important}.lh-sm{line-height:1.25!important}.lh-base{line-height:1.5!important}.lh-lg{line-height:2!important}.text-start{text-align:left!important}.text-end{text-align:right!important}.text-center{text-align:center!important}.text-decoration-none{text-decoration:none!important}.text-decoration-underline{text-decoration:underline!important}.text-decoration-line-through{text-decoration:line-through!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-primary{color:#0d6efd!important}.text-secondary{color:#6c757d!important}.text-success{color:#198754!important}.text-info{color:#0dcaf0!important}.text-warning{color:#ffc107!important}.text-danger{color:#dc3545!important}.text-light{color:#f8f9fa!important}.text-dark{color:#212529!important}.text-white{color:#fff!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-reset{color:inherit!important}.bg-primary{background-color:#0d6efd!important}.bg-secondary{background-color:#6c757d!important}.bg-success{background-color:#198754!important}.bg-info{background-color:#0dcaf0!important}.bg-warning{background-color:#ffc107!important}.bg-danger{background-color:#dc3545!important}.bg-light{background-color:#f8f9fa!important}.bg-dark{background-color:#212529!important}.bg-body{background-color:#fff!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.bg-gradient{background-image:var(--bs-gradient)!important}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.pe-none{pointer-events:none!important}.pe-auto{pointer-events:auto!important}.rounded{border-radius:.25rem!important}.rounded-0{border-radius:0!important}.rounded-1{border-radius:.2rem!important}.rounded-2{border-radius:.25rem!important}.rounded-3{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-end{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-start{border-bottom-left-radius:.25rem!important;border-top-left-radius:.25rem!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media (min-width:576px){.float-sm-start{float:left!important}.float-sm-end{float:right!important}.float-sm-none{float:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-grid{display:grid!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}.d-sm-none{display:none!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-sm-0{gap:0!important}.gap-sm-1{gap:.25rem!important}.gap-sm-2{gap:.5rem!important}.gap-sm-3{gap:1rem!important}.gap-sm-4{gap:1.5rem!important}.gap-sm-5{gap:3rem!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.justify-content-sm-evenly{justify-content:space-evenly!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}.order-sm-first{order:-1!important}.order-sm-0{order:0!important}.order-sm-1{order:1!important}.order-sm-2{order:2!important}.order-sm-3{order:3!important}.order-sm-4{order:4!important}.order-sm-5{order:5!important}.order-sm-last{order:6!important}.m-sm-0{margin:0!important}.m-sm-1{margin:.25rem!important}.m-sm-2{margin:.5rem!important}.m-sm-3{margin:1rem!important}.m-sm-4{margin:1.5rem!important}.m-sm-5{margin:3rem!important}.m-sm-auto{margin:auto!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-sm-5{margin-right:3rem!important;margin-left:3rem!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-sm-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:.25rem!important}.mt-sm-2{margin-top:.5rem!important}.mt-sm-3{margin-top:1rem!important}.mt-sm-4{margin-top:1.5rem!important}.mt-sm-5{margin-top:3rem!important}.mt-sm-auto{margin-top:auto!important}.me-sm-0{margin-right:0!important}.me-sm-1{margin-right:.25rem!important}.me-sm-2{margin-right:.5rem!important}.me-sm-3{margin-right:1rem!important}.me-sm-4{margin-right:1.5rem!important}.me-sm-5{margin-right:3rem!important}.me-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:.25rem!important}.mb-sm-2{margin-bottom:.5rem!important}.mb-sm-3{margin-bottom:1rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.mb-sm-5{margin-bottom:3rem!important}.mb-sm-auto{margin-bottom:auto!important}.ms-sm-0{margin-left:0!important}.ms-sm-1{margin-left:.25rem!important}.ms-sm-2{margin-left:.5rem!important}.ms-sm-3{margin-left:1rem!important}.ms-sm-4{margin-left:1.5rem!important}.ms-sm-5{margin-left:3rem!important}.ms-sm-auto{margin-left:auto!important}.p-sm-0{padding:0!important}.p-sm-1{padding:.25rem!important}.p-sm-2{padding:.5rem!important}.p-sm-3{padding:1rem!important}.p-sm-4{padding:1.5rem!important}.p-sm-5{padding:3rem!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-sm-5{padding-right:3rem!important;padding-left:3rem!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-sm-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:.25rem!important}.pt-sm-2{padding-top:.5rem!important}.pt-sm-3{padding-top:1rem!important}.pt-sm-4{padding-top:1.5rem!important}.pt-sm-5{padding-top:3rem!important}.pe-sm-0{padding-right:0!important}.pe-sm-1{padding-right:.25rem!important}.pe-sm-2{padding-right:.5rem!important}.pe-sm-3{padding-right:1rem!important}.pe-sm-4{padding-right:1.5rem!important}.pe-sm-5{padding-right:3rem!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:.25rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pb-sm-3{padding-bottom:1rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pb-sm-5{padding-bottom:3rem!important}.ps-sm-0{padding-left:0!important}.ps-sm-1{padding-left:.25rem!important}.ps-sm-2{padding-left:.5rem!important}.ps-sm-3{padding-left:1rem!important}.ps-sm-4{padding-left:1.5rem!important}.ps-sm-5{padding-left:3rem!important}.text-sm-start{text-align:left!important}.text-sm-end{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.float-md-start{float:left!important}.float-md-end{float:right!important}.float-md-none{float:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-grid{display:grid!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}.d-md-none{display:none!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-md-0{gap:0!important}.gap-md-1{gap:.25rem!important}.gap-md-2{gap:.5rem!important}.gap-md-3{gap:1rem!important}.gap-md-4{gap:1.5rem!important}.gap-md-5{gap:3rem!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.justify-content-md-evenly{justify-content:space-evenly!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}.order-md-first{order:-1!important}.order-md-0{order:0!important}.order-md-1{order:1!important}.order-md-2{order:2!important}.order-md-3{order:3!important}.order-md-4{order:4!important}.order-md-5{order:5!important}.order-md-last{order:6!important}.m-md-0{margin:0!important}.m-md-1{margin:.25rem!important}.m-md-2{margin:.5rem!important}.m-md-3{margin:1rem!important}.m-md-4{margin:1.5rem!important}.m-md-5{margin:3rem!important}.m-md-auto{margin:auto!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-md-5{margin-right:3rem!important;margin-left:3rem!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-md-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:.25rem!important}.mt-md-2{margin-top:.5rem!important}.mt-md-3{margin-top:1rem!important}.mt-md-4{margin-top:1.5rem!important}.mt-md-5{margin-top:3rem!important}.mt-md-auto{margin-top:auto!important}.me-md-0{margin-right:0!important}.me-md-1{margin-right:.25rem!important}.me-md-2{margin-right:.5rem!important}.me-md-3{margin-right:1rem!important}.me-md-4{margin-right:1.5rem!important}.me-md-5{margin-right:3rem!important}.me-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:.25rem!important}.mb-md-2{margin-bottom:.5rem!important}.mb-md-3{margin-bottom:1rem!important}.mb-md-4{margin-bottom:1.5rem!important}.mb-md-5{margin-bottom:3rem!important}.mb-md-auto{margin-bottom:auto!important}.ms-md-0{margin-left:0!important}.ms-md-1{margin-left:.25rem!important}.ms-md-2{margin-left:.5rem!important}.ms-md-3{margin-left:1rem!important}.ms-md-4{margin-left:1.5rem!important}.ms-md-5{margin-left:3rem!important}.ms-md-auto{margin-left:auto!important}.p-md-0{padding:0!important}.p-md-1{padding:.25rem!important}.p-md-2{padding:.5rem!important}.p-md-3{padding:1rem!important}.p-md-4{padding:1.5rem!important}.p-md-5{padding:3rem!important}.px-md-0{padding-right:0!important;padding-left:0!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-md-5{padding-right:3rem!important;padding-left:3rem!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-md-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:.25rem!important}.pt-md-2{padding-top:.5rem!important}.pt-md-3{padding-top:1rem!important}.pt-md-4{padding-top:1.5rem!important}.pt-md-5{padding-top:3rem!important}.pe-md-0{padding-right:0!important}.pe-md-1{padding-right:.25rem!important}.pe-md-2{padding-right:.5rem!important}.pe-md-3{padding-right:1rem!important}.pe-md-4{padding-right:1.5rem!important}.pe-md-5{padding-right:3rem!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:.25rem!important}.pb-md-2{padding-bottom:.5rem!important}.pb-md-3{padding-bottom:1rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pb-md-5{padding-bottom:3rem!important}.ps-md-0{padding-left:0!important}.ps-md-1{padding-left:.25rem!important}.ps-md-2{padding-left:.5rem!important}.ps-md-3{padding-left:1rem!important}.ps-md-4{padding-left:1.5rem!important}.ps-md-5{padding-left:3rem!important}.text-md-start{text-align:left!important}.text-md-end{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.float-lg-start{float:left!important}.float-lg-end{float:right!important}.float-lg-none{float:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-grid{display:grid!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}.d-lg-none{display:none!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-lg-0{gap:0!important}.gap-lg-1{gap:.25rem!important}.gap-lg-2{gap:.5rem!important}.gap-lg-3{gap:1rem!important}.gap-lg-4{gap:1.5rem!important}.gap-lg-5{gap:3rem!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.justify-content-lg-evenly{justify-content:space-evenly!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}.order-lg-first{order:-1!important}.order-lg-0{order:0!important}.order-lg-1{order:1!important}.order-lg-2{order:2!important}.order-lg-3{order:3!important}.order-lg-4{order:4!important}.order-lg-5{order:5!important}.order-lg-last{order:6!important}.m-lg-0{margin:0!important}.m-lg-1{margin:.25rem!important}.m-lg-2{margin:.5rem!important}.m-lg-3{margin:1rem!important}.m-lg-4{margin:1.5rem!important}.m-lg-5{margin:3rem!important}.m-lg-auto{margin:auto!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-lg-5{margin-right:3rem!important;margin-left:3rem!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-lg-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:.25rem!important}.mt-lg-2{margin-top:.5rem!important}.mt-lg-3{margin-top:1rem!important}.mt-lg-4{margin-top:1.5rem!important}.mt-lg-5{margin-top:3rem!important}.mt-lg-auto{margin-top:auto!important}.me-lg-0{margin-right:0!important}.me-lg-1{margin-right:.25rem!important}.me-lg-2{margin-right:.5rem!important}.me-lg-3{margin-right:1rem!important}.me-lg-4{margin-right:1.5rem!important}.me-lg-5{margin-right:3rem!important}.me-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:.25rem!important}.mb-lg-2{margin-bottom:.5rem!important}.mb-lg-3{margin-bottom:1rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.mb-lg-5{margin-bottom:3rem!important}.mb-lg-auto{margin-bottom:auto!important}.ms-lg-0{margin-left:0!important}.ms-lg-1{margin-left:.25rem!important}.ms-lg-2{margin-left:.5rem!important}.ms-lg-3{margin-left:1rem!important}.ms-lg-4{margin-left:1.5rem!important}.ms-lg-5{margin-left:3rem!important}.ms-lg-auto{margin-left:auto!important}.p-lg-0{padding:0!important}.p-lg-1{padding:.25rem!important}.p-lg-2{padding:.5rem!important}.p-lg-3{padding:1rem!important}.p-lg-4{padding:1.5rem!important}.p-lg-5{padding:3rem!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-lg-5{padding-right:3rem!important;padding-left:3rem!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-lg-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:.25rem!important}.pt-lg-2{padding-top:.5rem!important}.pt-lg-3{padding-top:1rem!important}.pt-lg-4{padding-top:1.5rem!important}.pt-lg-5{padding-top:3rem!important}.pe-lg-0{padding-right:0!important}.pe-lg-1{padding-right:.25rem!important}.pe-lg-2{padding-right:.5rem!important}.pe-lg-3{padding-right:1rem!important}.pe-lg-4{padding-right:1.5rem!important}.pe-lg-5{padding-right:3rem!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:.25rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pb-lg-3{padding-bottom:1rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pb-lg-5{padding-bottom:3rem!important}.ps-lg-0{padding-left:0!important}.ps-lg-1{padding-left:.25rem!important}.ps-lg-2{padding-left:.5rem!important}.ps-lg-3{padding-left:1rem!important}.ps-lg-4{padding-left:1.5rem!important}.ps-lg-5{padding-left:3rem!important}.text-lg-start{text-align:left!important}.text-lg-end{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.float-xl-start{float:left!important}.float-xl-end{float:right!important}.float-xl-none{float:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-grid{display:grid!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}.d-xl-none{display:none!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-xl-0{gap:0!important}.gap-xl-1{gap:.25rem!important}.gap-xl-2{gap:.5rem!important}.gap-xl-3{gap:1rem!important}.gap-xl-4{gap:1.5rem!important}.gap-xl-5{gap:3rem!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.justify-content-xl-evenly{justify-content:space-evenly!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}.order-xl-first{order:-1!important}.order-xl-0{order:0!important}.order-xl-1{order:1!important}.order-xl-2{order:2!important}.order-xl-3{order:3!important}.order-xl-4{order:4!important}.order-xl-5{order:5!important}.order-xl-last{order:6!important}.m-xl-0{margin:0!important}.m-xl-1{margin:.25rem!important}.m-xl-2{margin:.5rem!important}.m-xl-3{margin:1rem!important}.m-xl-4{margin:1.5rem!important}.m-xl-5{margin:3rem!important}.m-xl-auto{margin:auto!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:.25rem!important}.mt-xl-2{margin-top:.5rem!important}.mt-xl-3{margin-top:1rem!important}.mt-xl-4{margin-top:1.5rem!important}.mt-xl-5{margin-top:3rem!important}.mt-xl-auto{margin-top:auto!important}.me-xl-0{margin-right:0!important}.me-xl-1{margin-right:.25rem!important}.me-xl-2{margin-right:.5rem!important}.me-xl-3{margin-right:1rem!important}.me-xl-4{margin-right:1.5rem!important}.me-xl-5{margin-right:3rem!important}.me-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:.25rem!important}.mb-xl-2{margin-bottom:.5rem!important}.mb-xl-3{margin-bottom:1rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.mb-xl-5{margin-bottom:3rem!important}.mb-xl-auto{margin-bottom:auto!important}.ms-xl-0{margin-left:0!important}.ms-xl-1{margin-left:.25rem!important}.ms-xl-2{margin-left:.5rem!important}.ms-xl-3{margin-left:1rem!important}.ms-xl-4{margin-left:1.5rem!important}.ms-xl-5{margin-left:3rem!important}.ms-xl-auto{margin-left:auto!important}.p-xl-0{padding:0!important}.p-xl-1{padding:.25rem!important}.p-xl-2{padding:.5rem!important}.p-xl-3{padding:1rem!important}.p-xl-4{padding:1.5rem!important}.p-xl-5{padding:3rem!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:.25rem!important}.pt-xl-2{padding-top:.5rem!important}.pt-xl-3{padding-top:1rem!important}.pt-xl-4{padding-top:1.5rem!important}.pt-xl-5{padding-top:3rem!important}.pe-xl-0{padding-right:0!important}.pe-xl-1{padding-right:.25rem!important}.pe-xl-2{padding-right:.5rem!important}.pe-xl-3{padding-right:1rem!important}.pe-xl-4{padding-right:1.5rem!important}.pe-xl-5{padding-right:3rem!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:.25rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pb-xl-3{padding-bottom:1rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pb-xl-5{padding-bottom:3rem!important}.ps-xl-0{padding-left:0!important}.ps-xl-1{padding-left:.25rem!important}.ps-xl-2{padding-left:.5rem!important}.ps-xl-3{padding-left:1rem!important}.ps-xl-4{padding-left:1.5rem!important}.ps-xl-5{padding-left:3rem!important}.text-xl-start{text-align:left!important}.text-xl-end{text-align:right!important}.text-xl-center{text-align:center!important}}@media (min-width:1400px){.float-xxl-start{float:left!important}.float-xxl-end{float:right!important}.float-xxl-none{float:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!important}.d-xxl-grid{display:grid!important}.d-xxl-table{display:table!important}.d-xxl-table-row{display:table-row!important}.d-xxl-table-cell{display:table-cell!important}.d-xxl-flex{display:flex!important}.d-xxl-inline-flex{display:inline-flex!important}.d-xxl-none{display:none!important}.flex-xxl-fill{flex:1 1 auto!important}.flex-xxl-row{flex-direction:row!important}.flex-xxl-column{flex-direction:column!important}.flex-xxl-row-reverse{flex-direction:row-reverse!important}.flex-xxl-column-reverse{flex-direction:column-reverse!important}.flex-xxl-grow-0{flex-grow:0!important}.flex-xxl-grow-1{flex-grow:1!important}.flex-xxl-shrink-0{flex-shrink:0!important}.flex-xxl-shrink-1{flex-shrink:1!important}.flex-xxl-wrap{flex-wrap:wrap!important}.flex-xxl-nowrap{flex-wrap:nowrap!important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-xxl-0{gap:0!important}.gap-xxl-1{gap:.25rem!important}.gap-xxl-2{gap:.5rem!important}.gap-xxl-3{gap:1rem!important}.gap-xxl-4{gap:1.5rem!important}.gap-xxl-5{gap:3rem!important}.justify-content-xxl-start{justify-content:flex-start!important}.justify-content-xxl-end{justify-content:flex-end!important}.justify-content-xxl-center{justify-content:center!important}.justify-content-xxl-between{justify-content:space-between!important}.justify-content-xxl-around{justify-content:space-around!important}.justify-content-xxl-evenly{justify-content:space-evenly!important}.align-items-xxl-start{align-items:flex-start!important}.align-items-xxl-end{align-items:flex-end!important}.align-items-xxl-center{align-items:center!important}.align-items-xxl-baseline{align-items:baseline!important}.align-items-xxl-stretch{align-items:stretch!important}.align-content-xxl-start{align-content:flex-start!important}.align-content-xxl-end{align-content:flex-end!important}.align-content-xxl-center{align-content:center!important}.align-content-xxl-between{align-content:space-between!important}.align-content-xxl-around{align-content:space-around!important}.align-content-xxl-stretch{align-content:stretch!important}.align-self-xxl-auto{align-self:auto!important}.align-self-xxl-start{align-self:flex-start!important}.align-self-xxl-end{align-self:flex-end!important}.align-self-xxl-center{align-self:center!important}.align-self-xxl-baseline{align-self:baseline!important}.align-self-xxl-stretch{align-self:stretch!important}.order-xxl-first{order:-1!important}.order-xxl-0{order:0!important}.order-xxl-1{order:1!important}.order-xxl-2{order:2!important}.order-xxl-3{order:3!important}.order-xxl-4{order:4!important}.order-xxl-5{order:5!important}.order-xxl-last{order:6!important}.m-xxl-0{margin:0!important}.m-xxl-1{margin:.25rem!important}.m-xxl-2{margin:.5rem!important}.m-xxl-3{margin:1rem!important}.m-xxl-4{margin:1.5rem!important}.m-xxl-5{margin:3rem!important}.m-xxl-auto{margin:auto!important}.mx-xxl-0{margin-right:0!important;margin-left:0!important}.mx-xxl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xxl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xxl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xxl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xxl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xxl-auto{margin-right:auto!important;margin-left:auto!important}.my-xxl-0{margin-top:0!important;margin-bottom:0!important}.my-xxl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xxl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xxl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xxl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xxl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xxl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:.25rem!important}.mt-xxl-2{margin-top:.5rem!important}.mt-xxl-3{margin-top:1rem!important}.mt-xxl-4{margin-top:1.5rem!important}.mt-xxl-5{margin-top:3rem!important}.mt-xxl-auto{margin-top:auto!important}.me-xxl-0{margin-right:0!important}.me-xxl-1{margin-right:.25rem!important}.me-xxl-2{margin-right:.5rem!important}.me-xxl-3{margin-right:1rem!important}.me-xxl-4{margin-right:1.5rem!important}.me-xxl-5{margin-right:3rem!important}.me-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:.25rem!important}.mb-xxl-2{margin-bottom:.5rem!important}.mb-xxl-3{margin-bottom:1rem!important}.mb-xxl-4{margin-bottom:1.5rem!important}.mb-xxl-5{margin-bottom:3rem!important}.mb-xxl-auto{margin-bottom:auto!important}.ms-xxl-0{margin-left:0!important}.ms-xxl-1{margin-left:.25rem!important}.ms-xxl-2{margin-left:.5rem!important}.ms-xxl-3{margin-left:1rem!important}.ms-xxl-4{margin-left:1.5rem!important}.ms-xxl-5{margin-left:3rem!important}.ms-xxl-auto{margin-left:auto!important}.p-xxl-0{padding:0!important}.p-xxl-1{padding:.25rem!important}.p-xxl-2{padding:.5rem!important}.p-xxl-3{padding:1rem!important}.p-xxl-4{padding:1.5rem!important}.p-xxl-5{padding:3rem!important}.px-xxl-0{padding-right:0!important;padding-left:0!important}.px-xxl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xxl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xxl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xxl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xxl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xxl-0{padding-top:0!important;padding-bottom:0!important}.py-xxl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xxl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xxl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xxl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xxl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:.25rem!important}.pt-xxl-2{padding-top:.5rem!important}.pt-xxl-3{padding-top:1rem!important}.pt-xxl-4{padding-top:1.5rem!important}.pt-xxl-5{padding-top:3rem!important}.pe-xxl-0{padding-right:0!important}.pe-xxl-1{padding-right:.25rem!important}.pe-xxl-2{padding-right:.5rem!important}.pe-xxl-3{padding-right:1rem!important}.pe-xxl-4{padding-right:1.5rem!important}.pe-xxl-5{padding-right:3rem!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:.25rem!important}.pb-xxl-2{padding-bottom:.5rem!important}.pb-xxl-3{padding-bottom:1rem!important}.pb-xxl-4{padding-bottom:1.5rem!important}.pb-xxl-5{padding-bottom:3rem!important}.ps-xxl-0{padding-left:0!important}.ps-xxl-1{padding-left:.25rem!important}.ps-xxl-2{padding-left:.5rem!important}.ps-xxl-3{padding-left:1rem!important}.ps-xxl-4{padding-left:1.5rem!important}.ps-xxl-5{padding-left:3rem!important}.text-xxl-start{text-align:left!important}.text-xxl-end{text-align:right!important}.text-xxl-center{text-align:center!important}}@media (min-width:1200px){.fs-1{font-size:2.5rem!important}.fs-2{font-size:2rem!important}.fs-3{font-size:1.75rem!important}.fs-4{font-size:1.5rem!important}}@media print{.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-grid{display:grid!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}.d-print-none{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ + + + + + +/* --------------------------------------------------------------- + 2. Slick Slider +--------------------------------------------------------------- */ +/* Slick Slider */ +.slick-slider{position:relative;display:block;box-sizing:border-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-khtml-user-select:none;-ms-touch-action:pan-y;touch-action:pan-y;-webkit-tap-highlight-color:transparent}.slick-list{position:relative;display:block;overflow:hidden;margin:0;padding:0}.slick-list:focus{outline:0}.slick-list.dragging{cursor:pointer;cursor:hand}.slick-slider .slick-list,.slick-slider .slick-track{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.slick-track{position:relative;top:0;left:0;display:block;margin-left:auto;margin-right:auto}.slick-track:after,.slick-track:before{display:table;content:''}.slick-track:after{clear:both}.slick-loading .slick-track{visibility:hidden}.slick-slide{display:none;float:left;height:100%;min-height:1px}[dir=rtl] .slick-slide{float:right}.slick-slide img{display:block}.slick-slide.slick-loading img{display:none}.slick-slide.dragging img{pointer-events:none}.slick-initialized .slick-slide{display:block}.slick-loading .slick-slide{visibility:hidden}.slick-vertical .slick-slide{display:block;height:auto;border:1px solid transparent}.slick-arrow.slick-hidden{display:none} + + +/*--------------------------------------------------------------- + 3. Animate css +---------------------------------------------------------------*/ +/*! + * animate.css -http://daneden.me/animate + * Version - 3.7.0 + * Licensed under the MIT license - http://opensource.org/licenses/MIT + * + * Copyright (c) 2018 Daniel Eden + */ + +@-webkit-keyframes bounce{0%,20%,53%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);-webkit-transform:translateZ(0);animation-timing-function:cubic-bezier(.215,.61,.355,1);transform:translateZ(0)}40%,43%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-30px,0);animation-timing-function:cubic-bezier(.755,.05,.855,.06);transform:translate3d(0,-30px,0)}70%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-15px,0);animation-timing-function:cubic-bezier(.755,.05,.855,.06);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}@keyframes bounce{0%,20%,53%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);-webkit-transform:translateZ(0);animation-timing-function:cubic-bezier(.215,.61,.355,1);transform:translateZ(0)}40%,43%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-30px,0);animation-timing-function:cubic-bezier(.755,.05,.855,.06);transform:translate3d(0,-30px,0)}70%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-15px,0);animation-timing-function:cubic-bezier(.755,.05,.855,.06);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}.bounce{-webkit-animation-name:bounce;-webkit-transform-origin:center bottom;animation-name:bounce;transform-origin:center bottom}@-webkit-keyframes flash{0%,50%,to{opacity:1}25%,75%{opacity:0}}@keyframes flash{0%,50%,to{opacity:1}25%,75%{opacity:0}}.flash{-webkit-animation-name:flash;animation-name:flash}@-webkit-keyframes pulse{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@keyframes pulse{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}.pulse{-webkit-animation-name:pulse;animation-name:pulse}@-webkit-keyframes rubberBand{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(.75,1.25,1);transform:scale3d(.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@keyframes rubberBand{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(.75,1.25,1);transform:scale3d(.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}.rubberBand{-webkit-animation-name:rubberBand;animation-name:rubberBand}@-webkit-keyframes shake{0%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}@keyframes shake{0%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}.shake{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes headShake{0%{-webkit-transform:translateX(0);transform:translateX(0)}6.5%{-webkit-transform:translateX(-6px) rotateY(-9deg);transform:translateX(-6px) rotateY(-9deg)}18.5%{-webkit-transform:translateX(5px) rotateY(7deg);transform:translateX(5px) rotateY(7deg)}31.5%{-webkit-transform:translateX(-3px) rotateY(-5deg);transform:translateX(-3px) rotateY(-5deg)}43.5%{-webkit-transform:translateX(2px) rotateY(3deg);transform:translateX(2px) rotateY(3deg)}50%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes headShake{0%{-webkit-transform:translateX(0);transform:translateX(0)}6.5%{-webkit-transform:translateX(-6px) rotateY(-9deg);transform:translateX(-6px) rotateY(-9deg)}18.5%{-webkit-transform:translateX(5px) rotateY(7deg);transform:translateX(5px) rotateY(7deg)}31.5%{-webkit-transform:translateX(-3px) rotateY(-5deg);transform:translateX(-3px) rotateY(-5deg)}43.5%{-webkit-transform:translateX(2px) rotateY(3deg);transform:translateX(2px) rotateY(3deg)}50%{-webkit-transform:translateX(0);transform:translateX(0)}}.headShake{-webkit-animation-name:headShake;-webkit-animation-timing-function:ease-in-out;animation-name:headShake;animation-timing-function:ease-in-out}@-webkit-keyframes swing{20%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}40%{-webkit-transform:rotate(-10deg);transform:rotate(-10deg)}60%{-webkit-transform:rotate(5deg);transform:rotate(5deg)}80%{-webkit-transform:rotate(-5deg);transform:rotate(-5deg)}to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@keyframes swing{20%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}40%{-webkit-transform:rotate(-10deg);transform:rotate(-10deg)}60%{-webkit-transform:rotate(5deg);transform:rotate(5deg)}80%{-webkit-transform:rotate(-5deg);transform:rotate(-5deg)}to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}.swing{-webkit-animation-name:swing;-webkit-transform-origin:top center;animation-name:swing;transform-origin:top center}@-webkit-keyframes tada{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate(-3deg);transform:scale3d(.9,.9,.9) rotate(-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate(3deg);transform:scale3d(1.1,1.1,1.1) rotate(3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate(-3deg);transform:scale3d(1.1,1.1,1.1) rotate(-3deg)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@keyframes tada{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate(-3deg);transform:scale3d(.9,.9,.9) rotate(-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate(3deg);transform:scale3d(1.1,1.1,1.1) rotate(3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate(-3deg);transform:scale3d(1.1,1.1,1.1) rotate(-3deg)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}.tada{-webkit-animation-name:tada;animation-name:tada}@-webkit-keyframes wobble{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-25%,0,0) rotate(-5deg);transform:translate3d(-25%,0,0) rotate(-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate(3deg);transform:translate3d(20%,0,0) rotate(3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate(-3deg);transform:translate3d(-15%,0,0) rotate(-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate(2deg);transform:translate3d(10%,0,0) rotate(2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate(-1deg);transform:translate3d(-5%,0,0) rotate(-1deg)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes wobble{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-25%,0,0) rotate(-5deg);transform:translate3d(-25%,0,0) rotate(-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate(3deg);transform:translate3d(20%,0,0) rotate(3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate(-3deg);transform:translate3d(-15%,0,0) rotate(-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate(2deg);transform:translate3d(10%,0,0) rotate(2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate(-1deg);transform:translate3d(-5%,0,0) rotate(-1deg)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.wobble{-webkit-animation-name:wobble;animation-name:wobble}@-webkit-keyframes jello{0%,11.1%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}22.2%{-webkit-transform:skewX(-12.5deg) skewY(-12.5deg);transform:skewX(-12.5deg) skewY(-12.5deg)}33.3%{-webkit-transform:skewX(6.25deg) skewY(6.25deg);transform:skewX(6.25deg) skewY(6.25deg)}44.4%{-webkit-transform:skewX(-3.125deg) skewY(-3.125deg);transform:skewX(-3.125deg) skewY(-3.125deg)}55.5%{-webkit-transform:skewX(1.5625deg) skewY(1.5625deg);transform:skewX(1.5625deg) skewY(1.5625deg)}66.6%{-webkit-transform:skewX(-.78125deg) skewY(-.78125deg);transform:skewX(-.78125deg) skewY(-.78125deg)}77.7%{-webkit-transform:skewX(.390625deg) skewY(.390625deg);transform:skewX(.390625deg) skewY(.390625deg)}88.8%{-webkit-transform:skewX(-.1953125deg) skewY(-.1953125deg);transform:skewX(-.1953125deg) skewY(-.1953125deg)}}@keyframes jello{0%,11.1%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}22.2%{-webkit-transform:skewX(-12.5deg) skewY(-12.5deg);transform:skewX(-12.5deg) skewY(-12.5deg)}33.3%{-webkit-transform:skewX(6.25deg) skewY(6.25deg);transform:skewX(6.25deg) skewY(6.25deg)}44.4%{-webkit-transform:skewX(-3.125deg) skewY(-3.125deg);transform:skewX(-3.125deg) skewY(-3.125deg)}55.5%{-webkit-transform:skewX(1.5625deg) skewY(1.5625deg);transform:skewX(1.5625deg) skewY(1.5625deg)}66.6%{-webkit-transform:skewX(-.78125deg) skewY(-.78125deg);transform:skewX(-.78125deg) skewY(-.78125deg)}77.7%{-webkit-transform:skewX(.390625deg) skewY(.390625deg);transform:skewX(.390625deg) skewY(.390625deg)}88.8%{-webkit-transform:skewX(-.1953125deg) skewY(-.1953125deg);transform:skewX(-.1953125deg) skewY(-.1953125deg)}}.jello{-webkit-animation-name:jello;-webkit-transform-origin:center;animation-name:jello;transform-origin:center}@-webkit-keyframes heartBeat{0%{-webkit-transform:scale(1);transform:scale(1)}14%{-webkit-transform:scale(1.3);transform:scale(1.3)}28%{-webkit-transform:scale(1);transform:scale(1)}42%{-webkit-transform:scale(1.3);transform:scale(1.3)}70%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes heartBeat{0%{-webkit-transform:scale(1);transform:scale(1)}14%{-webkit-transform:scale(1.3);transform:scale(1.3)}28%{-webkit-transform:scale(1);transform:scale(1)}42%{-webkit-transform:scale(1.3);transform:scale(1.3)}70%{-webkit-transform:scale(1);transform:scale(1)}}.heartBeat{-webkit-animation-duration:1.3s;-webkit-animation-name:heartBeat;-webkit-animation-timing-function:ease-in-out;animation-duration:1.3s;animation-name:heartBeat;animation-timing-function:ease-in-out}@-webkit-keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.3,.3,.3);opacity:0;transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{-webkit-transform:scale3d(1.03,1.03,1.03);opacity:1;transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{-webkit-transform:scaleX(1);opacity:1;transform:scaleX(1)}}@keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.3,.3,.3);opacity:0;transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{-webkit-transform:scale3d(1.03,1.03,1.03);opacity:1;transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{-webkit-transform:scaleX(1);opacity:1;transform:scaleX(1)}}.bounceIn{-webkit-animation-duration:.75s;-webkit-animation-name:bounceIn;animation-duration:.75s;animation-name:bounceIn}@-webkit-keyframes bounceInDown{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:translate3d(0,-3000px,0);opacity:0;transform:translate3d(0,-3000px,0)}60%{-webkit-transform:translate3d(0,25px,0);opacity:1;transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes bounceInDown{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:translate3d(0,-3000px,0);opacity:0;transform:translate3d(0,-3000px,0)}60%{-webkit-transform:translate3d(0,25px,0);opacity:1;transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.bounceInDown{-webkit-animation-name:bounceInDown;animation-name:bounceInDown}@-webkit-keyframes bounceInLeft{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:translate3d(-3000px,0,0);opacity:0;transform:translate3d(-3000px,0,0)}60%{-webkit-transform:translate3d(25px,0,0);opacity:1;transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes bounceInLeft{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:translate3d(-3000px,0,0);opacity:0;transform:translate3d(-3000px,0,0)}60%{-webkit-transform:translate3d(25px,0,0);opacity:1;transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.bounceInLeft{-webkit-animation-name:bounceInLeft;animation-name:bounceInLeft}@-webkit-keyframes bounceInRight{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:translate3d(3000px,0,0);opacity:0;transform:translate3d(3000px,0,0)}60%{-webkit-transform:translate3d(-25px,0,0);opacity:1;transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes bounceInRight{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:translate3d(3000px,0,0);opacity:0;transform:translate3d(3000px,0,0)}60%{-webkit-transform:translate3d(-25px,0,0);opacity:1;transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.bounceInRight{-webkit-animation-name:bounceInRight;animation-name:bounceInRight}@-webkit-keyframes bounceInUp{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:translate3d(0,3000px,0);opacity:0;transform:translate3d(0,3000px,0)}60%{-webkit-transform:translate3d(0,-20px,0);opacity:1;transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes bounceInUp{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:translate3d(0,3000px,0);opacity:0;transform:translate3d(0,3000px,0)}60%{-webkit-transform:translate3d(0,-20px,0);opacity:1;transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.bounceInUp{-webkit-animation-name:bounceInUp;animation-name:bounceInUp}@-webkit-keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{-webkit-transform:scale3d(1.1,1.1,1.1);opacity:1;transform:scale3d(1.1,1.1,1.1)}to{-webkit-transform:scale3d(.3,.3,.3);opacity:0;transform:scale3d(.3,.3,.3)}}@keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{-webkit-transform:scale3d(1.1,1.1,1.1);opacity:1;transform:scale3d(1.1,1.1,1.1)}to{-webkit-transform:scale3d(.3,.3,.3);opacity:0;transform:scale3d(.3,.3,.3)}}.bounceOut{-webkit-animation-duration:.75s;-webkit-animation-name:bounceOut;animation-duration:.75s;animation-name:bounceOut}@-webkit-keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{-webkit-transform:translate3d(0,-20px,0);opacity:1;transform:translate3d(0,-20px,0)}to{-webkit-transform:translate3d(0,2000px,0);opacity:0;transform:translate3d(0,2000px,0)}}@keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{-webkit-transform:translate3d(0,-20px,0);opacity:1;transform:translate3d(0,-20px,0)}to{-webkit-transform:translate3d(0,2000px,0);opacity:0;transform:translate3d(0,2000px,0)}}.bounceOutDown{-webkit-animation-name:bounceOutDown;animation-name:bounceOutDown}@-webkit-keyframes bounceOutLeft{20%{-webkit-transform:translate3d(20px,0,0);opacity:1;transform:translate3d(20px,0,0)}to{-webkit-transform:translate3d(-2000px,0,0);opacity:0;transform:translate3d(-2000px,0,0)}}@keyframes bounceOutLeft{20%{-webkit-transform:translate3d(20px,0,0);opacity:1;transform:translate3d(20px,0,0)}to{-webkit-transform:translate3d(-2000px,0,0);opacity:0;transform:translate3d(-2000px,0,0)}}.bounceOutLeft{-webkit-animation-name:bounceOutLeft;animation-name:bounceOutLeft}@-webkit-keyframes bounceOutRight{20%{-webkit-transform:translate3d(-20px,0,0);opacity:1;transform:translate3d(-20px,0,0)}to{-webkit-transform:translate3d(2000px,0,0);opacity:0;transform:translate3d(2000px,0,0)}}@keyframes bounceOutRight{20%{-webkit-transform:translate3d(-20px,0,0);opacity:1;transform:translate3d(-20px,0,0)}to{-webkit-transform:translate3d(2000px,0,0);opacity:0;transform:translate3d(2000px,0,0)}}.bounceOutRight{-webkit-animation-name:bounceOutRight;animation-name:bounceOutRight}@-webkit-keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{-webkit-transform:translate3d(0,20px,0);opacity:1;transform:translate3d(0,20px,0)}to{-webkit-transform:translate3d(0,-2000px,0);opacity:0;transform:translate3d(0,-2000px,0)}}@keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{-webkit-transform:translate3d(0,20px,0);opacity:1;transform:translate3d(0,20px,0)}to{-webkit-transform:translate3d(0,-2000px,0);opacity:0;transform:translate3d(0,-2000px,0)}}.bounceOutUp{-webkit-animation-name:bounceOutUp;animation-name:bounceOutUp}@-webkit-keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes fadeInDown{0%{-webkit-transform:translate3d(0,-100%,0);opacity:0;transform:translate3d(0,-100%,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}@keyframes fadeInDown{0%{-webkit-transform:translate3d(0,-100%,0);opacity:0;transform:translate3d(0,-100%,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}.fadeInDown{-webkit-animation-name:fadeInDown;animation-name:fadeInDown}@-webkit-keyframes fadeInDownBig{0%{-webkit-transform:translate3d(0,-2000px,0);opacity:0;transform:translate3d(0,-2000px,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}@keyframes fadeInDownBig{0%{-webkit-transform:translate3d(0,-2000px,0);opacity:0;transform:translate3d(0,-2000px,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}.fadeInDownBig{-webkit-animation-name:fadeInDownBig;animation-name:fadeInDownBig}@-webkit-keyframes fadeInLeft{0%{-webkit-transform:translate3d(-100%,0,0);opacity:0;transform:translate3d(-100%,0,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}@keyframes fadeInLeft{0%{-webkit-transform:translate3d(-100%,0,0);opacity:0;transform:translate3d(-100%,0,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}.fadeInLeft{-webkit-animation-name:fadeInLeft;animation-name:fadeInLeft}@-webkit-keyframes fadeInLeftBig{0%{-webkit-transform:translate3d(-2000px,0,0);opacity:0;transform:translate3d(-2000px,0,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}@keyframes fadeInLeftBig{0%{-webkit-transform:translate3d(-2000px,0,0);opacity:0;transform:translate3d(-2000px,0,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}.fadeInLeftBig{-webkit-animation-name:fadeInLeftBig;animation-name:fadeInLeftBig}@-webkit-keyframes fadeInRight{0%{-webkit-transform:translate3d(100%,0,0);opacity:0;transform:translate3d(100%,0,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}@keyframes fadeInRight{0%{-webkit-transform:translate3d(100%,0,0);opacity:0;transform:translate3d(100%,0,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}.fadeInRight{-webkit-animation-name:fadeInRight;animation-name:fadeInRight}@-webkit-keyframes fadeInRightBig{0%{-webkit-transform:translate3d(2000px,0,0);opacity:0;transform:translate3d(2000px,0,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}@keyframes fadeInRightBig{0%{-webkit-transform:translate3d(2000px,0,0);opacity:0;transform:translate3d(2000px,0,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}.fadeInRightBig{-webkit-animation-name:fadeInRightBig;animation-name:fadeInRightBig}@-webkit-keyframes fadeInUp{0%{-webkit-transform:translate3d(0,100%,0);opacity:0;transform:translate3d(0,100%,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}@keyframes fadeInUp{0%{-webkit-transform:translate3d(0,100%,0);opacity:0;transform:translate3d(0,100%,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}.fadeInUp{-webkit-animation-name:fadeInUp;animation-name:fadeInUp}@-webkit-keyframes fadeInUpBig{0%{-webkit-transform:translate3d(0,2000px,0);opacity:0;transform:translate3d(0,2000px,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}@keyframes fadeInUpBig{0%{-webkit-transform:translate3d(0,2000px,0);opacity:0;transform:translate3d(0,2000px,0)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}.fadeInUpBig{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes fadeOut{0%{opacity:1}to{opacity:0}}@keyframes fadeOut{0%{opacity:1}to{opacity:0}}.fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeOutDown{0%{opacity:1}to{-webkit-transform:translate3d(0,100%,0);opacity:0;transform:translate3d(0,100%,0)}}@keyframes fadeOutDown{0%{opacity:1}to{-webkit-transform:translate3d(0,100%,0);opacity:0;transform:translate3d(0,100%,0)}}.fadeOutDown{-webkit-animation-name:fadeOutDown;animation-name:fadeOutDown}@-webkit-keyframes fadeOutDownBig{0%{opacity:1}to{-webkit-transform:translate3d(0,2000px,0);opacity:0;transform:translate3d(0,2000px,0)}}@keyframes fadeOutDownBig{0%{opacity:1}to{-webkit-transform:translate3d(0,2000px,0);opacity:0;transform:translate3d(0,2000px,0)}}.fadeOutDownBig{-webkit-animation-name:fadeOutDownBig;animation-name:fadeOutDownBig}@-webkit-keyframes fadeOutLeft{0%{opacity:1}to{-webkit-transform:translate3d(-100%,0,0);opacity:0;transform:translate3d(-100%,0,0)}}@keyframes fadeOutLeft{0%{opacity:1}to{-webkit-transform:translate3d(-100%,0,0);opacity:0;transform:translate3d(-100%,0,0)}}.fadeOutLeft{-webkit-animation-name:fadeOutLeft;animation-name:fadeOutLeft}@-webkit-keyframes fadeOutLeftBig{0%{opacity:1}to{-webkit-transform:translate3d(-2000px,0,0);opacity:0;transform:translate3d(-2000px,0,0)}}@keyframes fadeOutLeftBig{0%{opacity:1}to{-webkit-transform:translate3d(-2000px,0,0);opacity:0;transform:translate3d(-2000px,0,0)}}.fadeOutLeftBig{-webkit-animation-name:fadeOutLeftBig;animation-name:fadeOutLeftBig}@-webkit-keyframes fadeOutRight{0%{opacity:1}to{-webkit-transform:translate3d(100%,0,0);opacity:0;transform:translate3d(100%,0,0)}}@keyframes fadeOutRight{0%{opacity:1}to{-webkit-transform:translate3d(100%,0,0);opacity:0;transform:translate3d(100%,0,0)}}.fadeOutRight{-webkit-animation-name:fadeOutRight;animation-name:fadeOutRight}@-webkit-keyframes fadeOutRightBig{0%{opacity:1}to{-webkit-transform:translate3d(2000px,0,0);opacity:0;transform:translate3d(2000px,0,0)}}@keyframes fadeOutRightBig{0%{opacity:1}to{-webkit-transform:translate3d(2000px,0,0);opacity:0;transform:translate3d(2000px,0,0)}}.fadeOutRightBig{-webkit-animation-name:fadeOutRightBig;animation-name:fadeOutRightBig}@-webkit-keyframes fadeOutUp{0%{opacity:1}to{-webkit-transform:translate3d(0,-100%,0);opacity:0;transform:translate3d(0,-100%,0)}}@keyframes fadeOutUp{0%{opacity:1}to{-webkit-transform:translate3d(0,-100%,0);opacity:0;transform:translate3d(0,-100%,0)}}.fadeOutUp{-webkit-animation-name:fadeOutUp;animation-name:fadeOutUp}@-webkit-keyframes fadeOutUpBig{0%{opacity:1}to{-webkit-transform:translate3d(0,-2000px,0);opacity:0;transform:translate3d(0,-2000px,0)}}@keyframes fadeOutUpBig{0%{opacity:1}to{-webkit-transform:translate3d(0,-2000px,0);opacity:0;transform:translate3d(0,-2000px,0)}}.fadeOutUpBig{-webkit-animation-name:fadeOutUpBig;animation-name:fadeOutUpBig}@-webkit-keyframes flip{0%{-webkit-animation-timing-function:ease-out;-webkit-transform:perspective(400px) scaleX(1) translateZ(0) rotateY(-1turn);animation-timing-function:ease-out;transform:perspective(400px) scaleX(1) translateZ(0) rotateY(-1turn)}40%{-webkit-animation-timing-function:ease-out;-webkit-transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-190deg);animation-timing-function:ease-out;transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-190deg)}50%{-webkit-animation-timing-function:ease-in;-webkit-transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-170deg);animation-timing-function:ease-in;transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-170deg)}80%{-webkit-animation-timing-function:ease-in;-webkit-transform:perspective(400px) scale3d(.95,.95,.95) translateZ(0) rotateY(0deg);animation-timing-function:ease-in;transform:perspective(400px) scale3d(.95,.95,.95) translateZ(0) rotateY(0deg)}to{-webkit-animation-timing-function:ease-in;-webkit-transform:perspective(400px) scaleX(1) translateZ(0) rotateY(0deg);animation-timing-function:ease-in;transform:perspective(400px) scaleX(1) translateZ(0) rotateY(0deg)}}@keyframes flip{0%{-webkit-animation-timing-function:ease-out;-webkit-transform:perspective(400px) scaleX(1) translateZ(0) rotateY(-1turn);animation-timing-function:ease-out;transform:perspective(400px) scaleX(1) translateZ(0) rotateY(-1turn)}40%{-webkit-animation-timing-function:ease-out;-webkit-transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-190deg);animation-timing-function:ease-out;transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-190deg)}50%{-webkit-animation-timing-function:ease-in;-webkit-transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-170deg);animation-timing-function:ease-in;transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-170deg)}80%{-webkit-animation-timing-function:ease-in;-webkit-transform:perspective(400px) scale3d(.95,.95,.95) translateZ(0) rotateY(0deg);animation-timing-function:ease-in;transform:perspective(400px) scale3d(.95,.95,.95) translateZ(0) rotateY(0deg)}to{-webkit-animation-timing-function:ease-in;-webkit-transform:perspective(400px) scaleX(1) translateZ(0) rotateY(0deg);animation-timing-function:ease-in;transform:perspective(400px) scaleX(1) translateZ(0) rotateY(0deg)}}.animated.flip{-webkit-animation-name:flip;-webkit-backface-visibility:visible;animation-name:flip;backface-visibility:visible}@-webkit-keyframes flipInX{0%{-webkit-animation-timing-function:ease-in;-webkit-transform:perspective(400px) rotateX(90deg);animation-timing-function:ease-in;opacity:0;transform:perspective(400px) rotateX(90deg)}40%{-webkit-animation-timing-function:ease-in;-webkit-transform:perspective(400px) rotateX(-20deg);animation-timing-function:ease-in;transform:perspective(400px) rotateX(-20deg)}60%{-webkit-transform:perspective(400px) rotateX(10deg);opacity:1;transform:perspective(400px) rotateX(10deg)}80%{-webkit-transform:perspective(400px) rotateX(-5deg);transform:perspective(400px) rotateX(-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInX{0%{-webkit-animation-timing-function:ease-in;-webkit-transform:perspective(400px) rotateX(90deg);animation-timing-function:ease-in;opacity:0;transform:perspective(400px) rotateX(90deg)}40%{-webkit-animation-timing-function:ease-in;-webkit-transform:perspective(400px) rotateX(-20deg);animation-timing-function:ease-in;transform:perspective(400px) rotateX(-20deg)}60%{-webkit-transform:perspective(400px) rotateX(10deg);opacity:1;transform:perspective(400px) rotateX(10deg)}80%{-webkit-transform:perspective(400px) rotateX(-5deg);transform:perspective(400px) rotateX(-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInX{-webkit-animation-name:flipInX;-webkit-backface-visibility:visible!important;animation-name:flipInX;backface-visibility:visible!important}@-webkit-keyframes flipInY{0%{-webkit-animation-timing-function:ease-in;-webkit-transform:perspective(400px) rotateY(90deg);animation-timing-function:ease-in;opacity:0;transform:perspective(400px) rotateY(90deg)}40%{-webkit-animation-timing-function:ease-in;-webkit-transform:perspective(400px) rotateY(-20deg);animation-timing-function:ease-in;transform:perspective(400px) rotateY(-20deg)}60%{-webkit-transform:perspective(400px) rotateY(10deg);opacity:1;transform:perspective(400px) rotateY(10deg)}80%{-webkit-transform:perspective(400px) rotateY(-5deg);transform:perspective(400px) rotateY(-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInY{0%{-webkit-animation-timing-function:ease-in;-webkit-transform:perspective(400px) rotateY(90deg);animation-timing-function:ease-in;opacity:0;transform:perspective(400px) rotateY(90deg)}40%{-webkit-animation-timing-function:ease-in;-webkit-transform:perspective(400px) rotateY(-20deg);animation-timing-function:ease-in;transform:perspective(400px) rotateY(-20deg)}60%{-webkit-transform:perspective(400px) rotateY(10deg);opacity:1;transform:perspective(400px) rotateY(10deg)}80%{-webkit-transform:perspective(400px) rotateY(-5deg);transform:perspective(400px) rotateY(-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInY{-webkit-animation-name:flipInY;-webkit-backface-visibility:visible!important;animation-name:flipInY;backface-visibility:visible!important}@-webkit-keyframes flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotateX(-20deg);opacity:1;transform:perspective(400px) rotateX(-20deg)}to{-webkit-transform:perspective(400px) rotateX(90deg);opacity:0;transform:perspective(400px) rotateX(90deg)}}@keyframes flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotateX(-20deg);opacity:1;transform:perspective(400px) rotateX(-20deg)}to{-webkit-transform:perspective(400px) rotateX(90deg);opacity:0;transform:perspective(400px) rotateX(90deg)}}.flipOutX{-webkit-animation-duration:.75s;-webkit-animation-name:flipOutX;-webkit-backface-visibility:visible!important;animation-duration:.75s;animation-name:flipOutX;backface-visibility:visible!important}@-webkit-keyframes flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotateY(-15deg);opacity:1;transform:perspective(400px) rotateY(-15deg)}to{-webkit-transform:perspective(400px) rotateY(90deg);opacity:0;transform:perspective(400px) rotateY(90deg)}}@keyframes flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotateY(-15deg);opacity:1;transform:perspective(400px) rotateY(-15deg)}to{-webkit-transform:perspective(400px) rotateY(90deg);opacity:0;transform:perspective(400px) rotateY(90deg)}}.flipOutY{-webkit-animation-duration:.75s;-webkit-animation-name:flipOutY;-webkit-backface-visibility:visible!important;animation-duration:.75s;animation-name:flipOutY;backface-visibility:visible!important}@-webkit-keyframes lightSpeedIn{0%{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);opacity:0;transform:translate3d(100%,0,0) skewX(-30deg)}60%{-webkit-transform:skewX(20deg);opacity:1;transform:skewX(20deg)}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes lightSpeedIn{0%{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);opacity:0;transform:translate3d(100%,0,0) skewX(-30deg)}60%{-webkit-transform:skewX(20deg);opacity:1;transform:skewX(20deg)}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.lightSpeedIn{-webkit-animation-name:lightSpeedIn;-webkit-animation-timing-function:ease-out;animation-name:lightSpeedIn;animation-timing-function:ease-out}@-webkit-keyframes lightSpeedOut{0%{opacity:1}to{-webkit-transform:translate3d(100%,0,0) skewX(30deg);opacity:0;transform:translate3d(100%,0,0) skewX(30deg)}}@keyframes lightSpeedOut{0%{opacity:1}to{-webkit-transform:translate3d(100%,0,0) skewX(30deg);opacity:0;transform:translate3d(100%,0,0) skewX(30deg)}}.lightSpeedOut{-webkit-animation-name:lightSpeedOut;-webkit-animation-timing-function:ease-in;animation-name:lightSpeedOut;animation-timing-function:ease-in}@-webkit-keyframes rotateIn{0%{-webkit-transform:rotate(-200deg);-webkit-transform-origin:center;opacity:0;transform:rotate(-200deg);transform-origin:center}to{-webkit-transform:translateZ(0);-webkit-transform-origin:center;opacity:1;transform:translateZ(0);transform-origin:center}}@keyframes rotateIn{0%{-webkit-transform:rotate(-200deg);-webkit-transform-origin:center;opacity:0;transform:rotate(-200deg);transform-origin:center}to{-webkit-transform:translateZ(0);-webkit-transform-origin:center;opacity:1;transform:translateZ(0);transform-origin:center}}.rotateIn{-webkit-animation-name:rotateIn;animation-name:rotateIn}@-webkit-keyframes rotateInDownLeft{0%{-webkit-transform:rotate(-45deg);-webkit-transform-origin:left bottom;opacity:0;transform:rotate(-45deg);transform-origin:left bottom}to{-webkit-transform:translateZ(0);-webkit-transform-origin:left bottom;opacity:1;transform:translateZ(0);transform-origin:left bottom}}@keyframes rotateInDownLeft{0%{-webkit-transform:rotate(-45deg);-webkit-transform-origin:left bottom;opacity:0;transform:rotate(-45deg);transform-origin:left bottom}to{-webkit-transform:translateZ(0);-webkit-transform-origin:left bottom;opacity:1;transform:translateZ(0);transform-origin:left bottom}}.rotateInDownLeft{-webkit-animation-name:rotateInDownLeft;animation-name:rotateInDownLeft}@-webkit-keyframes rotateInDownRight{0%{-webkit-transform:rotate(45deg);-webkit-transform-origin:right bottom;opacity:0;transform:rotate(45deg);transform-origin:right bottom}to{-webkit-transform:translateZ(0);-webkit-transform-origin:right bottom;opacity:1;transform:translateZ(0);transform-origin:right bottom}}@keyframes rotateInDownRight{0%{-webkit-transform:rotate(45deg);-webkit-transform-origin:right bottom;opacity:0;transform:rotate(45deg);transform-origin:right bottom}to{-webkit-transform:translateZ(0);-webkit-transform-origin:right bottom;opacity:1;transform:translateZ(0);transform-origin:right bottom}}.rotateInDownRight{-webkit-animation-name:rotateInDownRight;animation-name:rotateInDownRight}@-webkit-keyframes rotateInUpLeft{0%{-webkit-transform:rotate(45deg);-webkit-transform-origin:left bottom;opacity:0;transform:rotate(45deg);transform-origin:left bottom}to{-webkit-transform:translateZ(0);-webkit-transform-origin:left bottom;opacity:1;transform:translateZ(0);transform-origin:left bottom}}@keyframes rotateInUpLeft{0%{-webkit-transform:rotate(45deg);-webkit-transform-origin:left bottom;opacity:0;transform:rotate(45deg);transform-origin:left bottom}to{-webkit-transform:translateZ(0);-webkit-transform-origin:left bottom;opacity:1;transform:translateZ(0);transform-origin:left bottom}}.rotateInUpLeft{-webkit-animation-name:rotateInUpLeft;animation-name:rotateInUpLeft}@-webkit-keyframes rotateInUpRight{0%{-webkit-transform:rotate(-90deg);-webkit-transform-origin:right bottom;opacity:0;transform:rotate(-90deg);transform-origin:right bottom}to{-webkit-transform:translateZ(0);-webkit-transform-origin:right bottom;opacity:1;transform:translateZ(0);transform-origin:right bottom}}@keyframes rotateInUpRight{0%{-webkit-transform:rotate(-90deg);-webkit-transform-origin:right bottom;opacity:0;transform:rotate(-90deg);transform-origin:right bottom}to{-webkit-transform:translateZ(0);-webkit-transform-origin:right bottom;opacity:1;transform:translateZ(0);transform-origin:right bottom}}.rotateInUpRight{-webkit-animation-name:rotateInUpRight;animation-name:rotateInUpRight}@-webkit-keyframes rotateOut{0%{-webkit-transform-origin:center;opacity:1;transform-origin:center}to{-webkit-transform:rotate(200deg);-webkit-transform-origin:center;opacity:0;transform:rotate(200deg);transform-origin:center}}@keyframes rotateOut{0%{-webkit-transform-origin:center;opacity:1;transform-origin:center}to{-webkit-transform:rotate(200deg);-webkit-transform-origin:center;opacity:0;transform:rotate(200deg);transform-origin:center}}.rotateOut{-webkit-animation-name:rotateOut;animation-name:rotateOut}@-webkit-keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;opacity:1;transform-origin:left bottom}to{-webkit-transform:rotate(45deg);-webkit-transform-origin:left bottom;opacity:0;transform:rotate(45deg);transform-origin:left bottom}}@keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;opacity:1;transform-origin:left bottom}to{-webkit-transform:rotate(45deg);-webkit-transform-origin:left bottom;opacity:0;transform:rotate(45deg);transform-origin:left bottom}}.rotateOutDownLeft{-webkit-animation-name:rotateOutDownLeft;animation-name:rotateOutDownLeft}@-webkit-keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;opacity:1;transform-origin:right bottom}to{-webkit-transform:rotate(-45deg);-webkit-transform-origin:right bottom;opacity:0;transform:rotate(-45deg);transform-origin:right bottom}}@keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;opacity:1;transform-origin:right bottom}to{-webkit-transform:rotate(-45deg);-webkit-transform-origin:right bottom;opacity:0;transform:rotate(-45deg);transform-origin:right bottom}}.rotateOutDownRight{-webkit-animation-name:rotateOutDownRight;animation-name:rotateOutDownRight}@-webkit-keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;opacity:1;transform-origin:left bottom}to{-webkit-transform:rotate(-45deg);-webkit-transform-origin:left bottom;opacity:0;transform:rotate(-45deg);transform-origin:left bottom}}@keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;opacity:1;transform-origin:left bottom}to{-webkit-transform:rotate(-45deg);-webkit-transform-origin:left bottom;opacity:0;transform:rotate(-45deg);transform-origin:left bottom}}.rotateOutUpLeft{-webkit-animation-name:rotateOutUpLeft;animation-name:rotateOutUpLeft}@-webkit-keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;opacity:1;transform-origin:right bottom}to{-webkit-transform:rotate(90deg);-webkit-transform-origin:right bottom;opacity:0;transform:rotate(90deg);transform-origin:right bottom}}@keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;opacity:1;transform-origin:right bottom}to{-webkit-transform:rotate(90deg);-webkit-transform-origin:right bottom;opacity:0;transform:rotate(90deg);transform-origin:right bottom}}.rotateOutUpRight{-webkit-animation-name:rotateOutUpRight;animation-name:rotateOutUpRight}@-webkit-keyframes hinge{0%{-webkit-animation-timing-function:ease-in-out;-webkit-transform-origin:top left;animation-timing-function:ease-in-out;transform-origin:top left}20%,60%{-webkit-animation-timing-function:ease-in-out;-webkit-transform:rotate(80deg);-webkit-transform-origin:top left;animation-timing-function:ease-in-out;transform:rotate(80deg);transform-origin:top left}40%,80%{-webkit-animation-timing-function:ease-in-out;-webkit-transform:rotate(60deg);-webkit-transform-origin:top left;animation-timing-function:ease-in-out;opacity:1;transform:rotate(60deg);transform-origin:top left}to{-webkit-transform:translate3d(0,700px,0);opacity:0;transform:translate3d(0,700px,0)}}@keyframes hinge{0%{-webkit-animation-timing-function:ease-in-out;-webkit-transform-origin:top left;animation-timing-function:ease-in-out;transform-origin:top left}20%,60%{-webkit-animation-timing-function:ease-in-out;-webkit-transform:rotate(80deg);-webkit-transform-origin:top left;animation-timing-function:ease-in-out;transform:rotate(80deg);transform-origin:top left}40%,80%{-webkit-animation-timing-function:ease-in-out;-webkit-transform:rotate(60deg);-webkit-transform-origin:top left;animation-timing-function:ease-in-out;opacity:1;transform:rotate(60deg);transform-origin:top left}to{-webkit-transform:translate3d(0,700px,0);opacity:0;transform:translate3d(0,700px,0)}}.hinge{-webkit-animation-duration:2s;-webkit-animation-name:hinge;animation-duration:2s;animation-name:hinge}@-webkit-keyframes jackInTheBox{0%{-webkit-transform:scale(.1) rotate(30deg);-webkit-transform-origin:center bottom;opacity:0;transform:scale(.1) rotate(30deg);transform-origin:center bottom}50%{-webkit-transform:rotate(-10deg);transform:rotate(-10deg)}70%{-webkit-transform:rotate(3deg);transform:rotate(3deg)}to{-webkit-transform:scale(1);opacity:1;transform:scale(1)}}@keyframes jackInTheBox{0%{-webkit-transform:scale(.1) rotate(30deg);-webkit-transform-origin:center bottom;opacity:0;transform:scale(.1) rotate(30deg);transform-origin:center bottom}50%{-webkit-transform:rotate(-10deg);transform:rotate(-10deg)}70%{-webkit-transform:rotate(3deg);transform:rotate(3deg)}to{-webkit-transform:scale(1);opacity:1;transform:scale(1)}}.jackInTheBox{-webkit-animation-name:jackInTheBox;animation-name:jackInTheBox}@-webkit-keyframes rollIn{0%{-webkit-transform:translate3d(-100%,0,0) rotate(-120deg);opacity:0;transform:translate3d(-100%,0,0) rotate(-120deg)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}@keyframes rollIn{0%{-webkit-transform:translate3d(-100%,0,0) rotate(-120deg);opacity:0;transform:translate3d(-100%,0,0) rotate(-120deg)}to{-webkit-transform:translateZ(0);opacity:1;transform:translateZ(0)}}.rollIn{-webkit-animation-name:rollIn;animation-name:rollIn}@-webkit-keyframes rollOut{0%{opacity:1}to{-webkit-transform:translate3d(100%,0,0) rotate(120deg);opacity:0;transform:translate3d(100%,0,0) rotate(120deg)}}@keyframes rollOut{0%{opacity:1}to{-webkit-transform:translate3d(100%,0,0) rotate(120deg);opacity:0;transform:translate3d(100%,0,0) rotate(120deg)}}.rollOut{-webkit-animation-name:rollOut;animation-name:rollOut}@-webkit-keyframes zoomIn{0%{-webkit-transform:scale3d(.3,.3,.3);opacity:0;transform:scale3d(.3,.3,.3)}50%{opacity:1}}@keyframes zoomIn{0%{-webkit-transform:scale3d(.3,.3,.3);opacity:0;transform:scale3d(.3,.3,.3)}50%{opacity:1}}.zoomIn{-webkit-animation-name:zoomIn;animation-name:zoomIn}@-webkit-keyframes zoomInDown{0%{-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0)}60%{-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,60px,0)}}@keyframes zoomInDown{0%{-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0)}60%{-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,60px,0)}}.zoomInDown{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}@-webkit-keyframes zoomInLeft{0%{-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0)}60%{-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(10px,0,0)}}@keyframes zoomInLeft{0%{-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0)}60%{-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(10px,0,0)}}.zoomInLeft{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}@-webkit-keyframes zoomInRight{0%{-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(1000px,0,0)}60%{-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(-10px,0,0)}}@keyframes zoomInRight{0%{-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(1000px,0,0)}60%{-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(-10px,0,0)}}.zoomInRight{-webkit-animation-name:zoomInRight;animation-name:zoomInRight}@-webkit-keyframes zoomInUp{0%{-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,1000px,0)}60%{-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,-60px,0)}}@keyframes zoomInUp{0%{-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,1000px,0)}60%{-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,-60px,0)}}.zoomInUp{-webkit-animation-name:zoomInUp;animation-name:zoomInUp}@-webkit-keyframes zoomOut{0%{opacity:1}50%{-webkit-transform:scale3d(.3,.3,.3);opacity:0;transform:scale3d(.3,.3,.3)}to{opacity:0}}@keyframes zoomOut{0%{opacity:1}50%{-webkit-transform:scale3d(.3,.3,.3);opacity:0;transform:scale3d(.3,.3,.3)}to{opacity:0}}.zoomOut{-webkit-animation-name:zoomOut;animation-name:zoomOut}@-webkit-keyframes zoomOutDown{40%{-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,-60px,0)}to{-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform-origin:center bottom}}@keyframes zoomOutDown{40%{-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,-60px,0)}to{-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform-origin:center bottom}}.zoomOutDown{-webkit-animation-name:zoomOutDown;animation-name:zoomOutDown}@-webkit-keyframes zoomOutLeft{40%{-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);opacity:1;transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}to{-webkit-transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;opacity:0;transform:scale(.1) translate3d(-2000px,0,0);transform-origin:left center}}@keyframes zoomOutLeft{40%{-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);opacity:1;transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}to{-webkit-transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;opacity:0;transform:scale(.1) translate3d(-2000px,0,0);transform-origin:left center}}.zoomOutLeft{-webkit-animation-name:zoomOutLeft;animation-name:zoomOutLeft}@-webkit-keyframes zoomOutRight{40%{-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);opacity:1;transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}to{-webkit-transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;opacity:0;transform:scale(.1) translate3d(2000px,0,0);transform-origin:right center}}@keyframes zoomOutRight{40%{-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);opacity:1;transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}to{-webkit-transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;opacity:0;transform:scale(.1) translate3d(2000px,0,0);transform-origin:right center}}.zoomOutRight{-webkit-animation-name:zoomOutRight;animation-name:zoomOutRight}@-webkit-keyframes zoomOutUp{40%{-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,60px,0)}to{-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform-origin:center bottom}}@keyframes zoomOutUp{40%{-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,60px,0)}to{-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform-origin:center bottom}}.zoomOutUp{-webkit-animation-name:zoomOutUp;animation-name:zoomOutUp}@-webkit-keyframes slideInDown{0%{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes slideInDown{0%{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.slideInDown{-webkit-animation-name:slideInDown;animation-name:slideInDown}@-webkit-keyframes slideInLeft{0%{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes slideInLeft{0%{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.slideInLeft{-webkit-animation-name:slideInLeft;animation-name:slideInLeft}@-webkit-keyframes slideInRight{0%{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes slideInRight{0%{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.slideInRight{-webkit-animation-name:slideInRight;animation-name:slideInRight}@-webkit-keyframes slideInUp{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes slideInUp{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.slideInUp{-webkit-animation-name:slideInUp;animation-name:slideInUp}@-webkit-keyframes slideOutDown{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:hidden}}@keyframes slideOutDown{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:hidden}}.slideOutDown{-webkit-animation-name:slideOutDown;animation-name:slideOutDown}@-webkit-keyframes slideOutLeft{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:hidden}}@keyframes slideOutLeft{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:hidden}}.slideOutLeft{-webkit-animation-name:slideOutLeft;animation-name:slideOutLeft}@-webkit-keyframes slideOutRight{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:hidden}}@keyframes slideOutRight{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:hidden}}.slideOutRight{-webkit-animation-name:slideOutRight;animation-name:slideOutRight}@-webkit-keyframes slideOutUp{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:hidden}}@keyframes slideOutUp{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:hidden}}.slideOutUp{-webkit-animation-name:slideOutUp;animation-name:slideOutUp}.animated{-webkit-animation-duration:1s;-webkit-animation-fill-mode:both;animation-duration:1s;animation-fill-mode:both}.animated.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.animated.delay-1s{-webkit-animation-delay:1s;animation-delay:1s}.animated.delay-2s{-webkit-animation-delay:2s;animation-delay:2s}.animated.delay-3s{-webkit-animation-delay:3s;animation-delay:3s}.animated.delay-4s{-webkit-animation-delay:4s;animation-delay:4s}.animated.delay-5s{-webkit-animation-delay:5s;animation-delay:5s}.animated.fast{-webkit-animation-duration:.8s;animation-duration:.8s}.animated.faster{-webkit-animation-duration:.5s;animation-duration:.5s}.animated.slow{-webkit-animation-duration:2s;animation-duration:2s}.animated.slower{-webkit-animation-duration:3s;animation-duration:3s}@media (prefers-reduced-motion){.animated{-webkit-animation:unset!important;-webkit-transition:none!important;animation:unset!important;transition:none!important}} + + +/*--------------------------------------------------------------- + 4. Lightcase +---------------------------------------------------------------*/ +/* + * Lightcase - jQuery Plugin + * The smart and flexible Lightbox Plugin. + * @author Cornel Boppart + * @copyright Author + * @version 2.5.0 (11/03/2018) + */ +@font-face{font-family:lightcase;src:url("../fonts/lightcase-55356177.eot");src:url("../fonts/lightcase-55356177.eot#iefix") format("embedded-opentype"),url("../fonts/lightcase-55356177.woff") format("woff"),url("../fonts/lightcase-55356177.ttf") format("truetype"),url("../fonts/lightcase-55356177.svg#lightcase") format("svg");font-weight:400;font-style:normal}[class*=lightcase-icon-]:before{font-family:lightcase,sans-serif;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;text-align:center;font-variant:normal;text-transform:none;line-height:1em}.lightcase-icon-play:before{content:'\e800'}.lightcase-icon-pause:before{content:'\e801'}.lightcase-icon-close:before{content:'\e802'}.lightcase-icon-prev:before{content:'\e803'}.lightcase-icon-next:before{content:'\e804'}.lightcase-icon-spin:before{content:'\e805'}@-webkit-keyframes lightcase-spin{0%{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);-moz-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}@-moz-keyframes lightcase-spin{0%{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);-moz-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}@-o-keyframes lightcase-spin{0%{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);-moz-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}@-ms-keyframes lightcase-spin{0%{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);-moz-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes lightcase-spin{0%{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);-moz-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}#lightcase-case{display:none;position:fixed;z-index:2002;top:50%;left:50%;font-family:arial,sans-serif;font-size:13px;line-height:1.5;text-align:left;text-shadow:0 0 10px rgba(0,0,0,.5)}#lightcase-loading>span,a[class*=lightcase-icon-]>span{display:inline-block;text-indent:-9999px}@media screen and (min-width:641px){html:not([data-lc-type=error]) #lightcase-content{position:relative;z-index:1;text-shadow:none;background-color:#fff;-webkit-box-shadow:0 0 30px rgba(0,0,0,.5);-moz-box-shadow:0 0 30px rgba(0,0,0,.5);-o-box-shadow:0 0 30px rgba(0,0,0,.5);box-shadow:0 0 30px rgba(0,0,0,.5);-webkit-backface-visibility:hidden}html[data-lc-type=image] #lightcase-content,html[data-lc-type=video] #lightcase-content{background-color:#333}}html[data-lc-type=ajax] #lightcase-content,html[data-lc-type=error] #lightcase-content,html[data-lc-type=inline] #lightcase-content{-webkit-box-shadow:none;-moz-box-shadow:none;-o-box-shadow:none;box-shadow:none}html[data-lc-type=ajax] #lightcase-content .lightcase-contentInner,html[data-lc-type=error] #lightcase-content .lightcase-contentInner,html[data-lc-type=inline] #lightcase-content .lightcase-contentInner{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}@media screen and (max-width:640px){html[data-lc-type=ajax] #lightcase-case,html[data-lc-type=inline] #lightcase-case{position:fixed!important;top:0!important;left:0!important;right:0!important;bottom:0!important;margin:0!important;padding:55px 0 70px;width:100%!important;height:100%!important;overflow:auto!important}html[data-lc-type=ajax] #lightcase-content,html[data-lc-type=error] #lightcase-content,html[data-lc-type=inline] #lightcase-content{position:relative!important;top:auto!important;left:auto!important;width:auto!important;height:auto!important;margin:0!important;padding:0!important;border:none!important;background:0 0!important}html[data-lc-type=ajax] #lightcase-content .lightcase-contentInner,html[data-lc-type=error] #lightcase-content .lightcase-contentInner,html[data-lc-type=inline] #lightcase-content .lightcase-contentInner{padding:15px}html[data-lc-type=ajax] #lightcase-content .lightcase-contentInner,html[data-lc-type=ajax] #lightcase-content .lightcase-contentInner>*,html[data-lc-type=error] #lightcase-content .lightcase-contentInner,html[data-lc-type=error] #lightcase-content .lightcase-contentInner>*,html[data-lc-type=inline] #lightcase-content .lightcase-contentInner,html[data-lc-type=inline] #lightcase-content .lightcase-contentInner>*{width:100%!important;max-width:none!important}html[data-lc-type=ajax] #lightcase-content .lightcase-contentInner>:not(iframe),html[data-lc-type=error] #lightcase-content .lightcase-contentInner>:not(iframe),html[data-lc-type=inline] #lightcase-content .lightcase-contentInner>:not(iframe){height:auto!important;max-height:none!important}html.lightcase-isMobileDevice[data-lc-type=iframe] #lightcase-content .lightcase-contentInner iframe{overflow:auto;-webkit-overflow-scrolling:touch}}@media screen and (max-width:640px) and (min-width:641px){html[data-lc-type=image] #lightcase-content .lightcase-contentInner,html[data-lc-type=video] #lightcase-content .lightcase-contentInner{line-height:.75}}html[data-lc-type=image] #lightcase-content .lightcase-contentInner{position:relative;overflow:hidden!important}@media screen and (max-width:640px){html[data-lc-type=ajax] #lightcase-content .lightcase-contentInner .lightcase-inlineWrap,html[data-lc-type=error] #lightcase-content .lightcase-contentInner .lightcase-inlineWrap,html[data-lc-type=inline] #lightcase-content .lightcase-contentInner .lightcase-inlineWrap{position:relative!important;top:auto!important;left:auto!important;width:auto!important;height:auto!important;margin:0!important;padding:0!important;border:none!important;background:0 0!important}#lightcase-content h1,#lightcase-content h2,#lightcase-content h3,#lightcase-content h4,#lightcase-content h5,#lightcase-content h6,#lightcase-content p{}}#lightcase-loading,a[class*=lightcase-icon-]{width:1.123em;height:auto;line-height:1;text-align:center;position:fixed}@media screen and (min-width:641px){html:not([data-lc-type=error]) #lightcase-content .lightcase-contentInner .lightcase-inlineWrap{padding:30px;overflow:auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}#lightcase-content h1,#lightcase-content h2,#lightcase-content h3,#lightcase-content h4,#lightcase-content h5,#lightcase-content h6,#lightcase-content p{}}#lightcase-case p.lightcase-error{margin:0;font-size:17px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}@media screen and (max-width:640px){#lightcase-case p.lightcase-error{padding:30px 0}}@media screen and (min-width:641px){#lightcase-case p.lightcase-error{padding:0}}.lightcase-open body{overflow:hidden}.lightcase-isMobileDevice .lightcase-open body{max-width:100%;max-height:100%}#lightcase-info{position:absolute;padding-top:15px}#lightcase-info #lightcase-caption,#lightcase-info #lightcase-title{margin:0;padding:0;line-height:1.5;font-weight:400;text-overflow:ellipsis}#lightcase-info #lightcase-title{font-size:17px;}#lightcase-info #lightcase-caption{clear:both;font-size:13px;}#lightcase-info #lightcase-sequenceInfo{font-size:11px;}@media screen and (max-width:640px){#lightcase-info #lightcase-title{position:fixed;top:10px;left:0;max-width:87.5%;padding:5px 15px;background:#333}.lightcase-fullScreenMode #lightcase-info{padding-left:15px;padding-right:15px}html:not([data-lc-type=image]):not([data-lc-type=video]):not([data-lc-type=flash]):not([data-lc-type=error]) #lightcase-info{position:static}}#lightcase-loading{z-index:2001;top:50%;left:50%;margin-top:-.5em;margin-left:-.5em;opacity:1;font-size:32px;text-shadow:0 0 15px #fff;-moz-transform-origin:50% 53%;-webkit-animation:lightcase-spin .5s infinite linear;-moz-animation:lightcase-spin .5s infinite linear;-o-animation:lightcase-spin .5s infinite linear;animation:lightcase-spin .5s infinite linear}#lightcase-loading,#lightcase-loading:focus{text-decoration:none;color:#fff;-webkit-tap-highlight-color:transparent;-webkit-transition:color,opacity,ease-in-out .25s;-moz-transition:color,opacity,ease-in-out .25s;-o-transition:color,opacity,ease-in-out .25s;transition:color,opacity,ease-in-out .25s}a[class*=lightcase-icon-]{z-index:9999;font-size:38px;text-shadow:none;outline:0;cursor:pointer}a[class*=lightcase-icon-],a[class*=lightcase-icon-]:focus{text-decoration:none;color:rgba(255,255,255,.6);-webkit-tap-highlight-color:transparent;-webkit-transition:color,opacity,ease-in-out .25s;-moz-transition:color,opacity,ease-in-out .25s;-o-transition:color,opacity,ease-in-out .25s;transition:color,opacity,ease-in-out .25s}a[class*=lightcase-icon-]:hover{color:#fff;text-shadow:0 0 15px #fff}.lightcase-isMobileDevice a[class*=lightcase-icon-]:hover{text-shadow:none}a[class*=lightcase-icon-].lightcase-icon-close{position:fixed;top:15px;right:15px;bottom:auto;margin:0;opacity:0;outline:0}a[class*=lightcase-icon-].lightcase-icon-prev{left:15px}a[class*=lightcase-icon-].lightcase-icon-next{right:15px}a[class*=lightcase-icon-].lightcase-icon-pause,a[class*=lightcase-icon-].lightcase-icon-play{left:50%;margin-left:-.5em}@media screen and (max-width:640px){a[class*=lightcase-icon-]{bottom:15px;font-size:24px}}@media screen and (min-width:641px){a[class*=lightcase-icon-].lightcase-icon-pause,a[class*=lightcase-icon-].lightcase-icon-play{opacity:0}a[class*=lightcase-icon-]{bottom:50%;margin-bottom:-.5em}#lightcase-case:hover~a[class*=lightcase-icon-],a[class*=lightcase-icon-]:hover{opacity:1}}#lightcase-overlay{display:none;width:100%;min-height:100%;position:fixed;z-index:2000;top:-9999px;bottom:-9999px;left:0;background:#333}@media screen and (max-width:640px){#lightcase-overlay{opacity:1!important}} + + +/*--------------------------------------------------------------- + 5. Nice Select JS +---------------------------------------------------------------*/ +.nice-select{-webkit-tap-highlight-color:transparent;background-color:#fff;border-radius:5px;border:solid 1px #e8e8e8;box-sizing:border-box;clear:both;cursor:pointer;display:block;float:left;font-family:inherit;font-size:14px;font-weight:400;height:42px;line-height:40px;outline:0;padding-left:18px;padding-right:30px;position:relative;text-align:left!important;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;white-space:nowrap;width:auto}.nice-select:hover{border-color:#dbdbdb}.nice-select.open,.nice-select:active,.nice-select:focus{border-color:#999}.nice-select:after{border-bottom:2px solid #999;border-right:2px solid #999;content:'';display:block;height:5px;margin-top:-4px;pointer-events:none;position:absolute;right:12px;top:50%;-webkit-transform-origin:66% 66%;-ms-transform-origin:66% 66%;transform-origin:66% 66%;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);-webkit-transition:all .15s ease-in-out;transition:all .15s ease-in-out;width:5px}.nice-select.open:after{-webkit-transform:rotate(-135deg);-ms-transform:rotate(-135deg);transform:rotate(-135deg)}.nice-select.open .list{opacity:1;pointer-events:auto;-webkit-transform:scale(1) translateY(0);-ms-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}.nice-select.disabled{border-color:#ededed;color:#999;pointer-events:none}.nice-select.disabled:after{border-color:#ccc}.nice-select.wide{width:100%}.nice-select.wide .list{left:0!important;right:0!important}.nice-select.right{float:right}.nice-select.right .list{left:auto;right:0}.nice-select.small{font-size:12px;height:36px;line-height:34px}.nice-select.small:after{height:4px;width:4px}.nice-select.small .option{line-height:34px;min-height:34px}.nice-select .list{background-color:#fff;border-radius:5px;box-shadow:0 0 0 1px rgba(68,68,68,.11);box-sizing:border-box;margin-top:4px;opacity:0;overflow:hidden;padding:0;pointer-events:none;position:absolute;top:100%;left:0;-webkit-transform-origin:50% 0;-ms-transform-origin:50% 0;transform-origin:50% 0;-webkit-transform:scale(.75) translateY(-21px);-ms-transform:scale(.75) translateY(-21px);transform:scale(.75) translateY(-21px);-webkit-transition:all .2s cubic-bezier(.5,0,0,1.25),opacity .15s ease-out;transition:all .2s cubic-bezier(.5,0,0,1.25),opacity .15s ease-out;z-index:9}.nice-select .list:hover .option:not(:hover){background-color:transparent!important}.nice-select .option{cursor:pointer;font-weight:400;line-height:40px;list-style:none;min-height:40px;outline:0;padding-left:18px;padding-right:29px;text-align:left;-webkit-transition:all .2s;transition:all .2s}.nice-select .option.focus,.nice-select .option.selected.focus,.nice-select .option:hover{background-color:#f6f6f6}.nice-select .option.selected{font-weight:700}.nice-select .option.disabled{background-color:transparent;color:#999;cursor:default}.no-csspointerevents .nice-select .list{display:none}.no-csspointerevents .nice-select.open .list{display:block} + + +/*--------------------------------------------------------------- + 6. jQuery UI +---------------------------------------------------------------*/ +/*! jQuery UI - v1.11.4 - 2016-06-07 +* http://jqueryui.com +* Includes: core.css, slider.css, theme.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande%2CLucida%20Sans%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=gloss_wave&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=inset_hard&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=glass&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=inset_hard&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=flat&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-widget{font-family:Lucida Grande,Lucida Sans,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Lucida Grande,Lucida Sans,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #a6c9e2;background:#fcfdfd url("https://tunatheme.com/tf/html/fiama-preview/fiama/css/images/ui-bg_inset-hard_100_fcfdfd_1x100.png") 50% bottom repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #4297d7;background:#5c9ccc url("https://tunatheme.com/tf/html/fiama-preview/fiama/css/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png") 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #c5dbec;background:#dfeffc url("https://tunatheme.com/tf/html/fiama-preview/fiama/css/images/ui-bg_glass_85_dfeffc_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#2e6e9e}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#2e6e9e;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #79b7e7;background:#d0e5f5 url("https://tunatheme.com/tf/html/fiama-preview/fiama/css/images/ui-bg_glass_75_d0e5f5_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#1d5987}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#1d5987;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #79b7e7;background:#f5f8f9 url("https://tunatheme.com/tf/html/fiama-preview/fiama/css/images/ui-bg_inset-hard_100_f5f8f9_1x100.png") 50% 50% repeat-x;font-weight:bold;color:#e17009}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#e17009;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fad42e;background:#fbec88;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url("https://tunatheme.com/tf/html/fiama-preview/fiama/css/images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("https://tunatheme.com/tf/html/fiama-preview/fiama/css/images/ui-icons_469bdd_256x240.png")}.ui-widget-header .ui-icon{background-image:url("https://tunatheme.com/tf/html/fiama-preview/fiama/css/images/ui-icons_d8e7f3_256x240.png")}.ui-state-default .ui-icon{background-image:url("https://tunatheme.com/tf/html/fiama-preview/fiama/css/images/ui-icons_6da8d5_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("https://tunatheme.com/tf/html/fiama-preview/fiama/css/images/ui-icons_217bc0_256x240.png")}.ui-state-active .ui-icon{background-image:url("https://tunatheme.com/tf/html/fiama-preview/fiama/css/images/ui-icons_f9bd01_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("https://tunatheme.com/tf/html/fiama-preview/fiama/css/images/ui-icons_2e83ff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("https://tunatheme.com/tf/html/fiama-preview/fiama/css/images/ui-icons_cd0a0a_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:5px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:5px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:5px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:5px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px} + + + +/*--------------------------------------------------------------- + END +---------------------------------------------------------------*/ \ No newline at end of file diff --git a/themes/nurgul/assets/css/responsive.css b/themes/nurgul/assets/css/responsive.css new file mode 100644 index 0000000..ba5da3c --- /dev/null +++ b/themes/nurgul/assets/css/responsive.css @@ -0,0 +1,101 @@ +/* ==================================================== + Responsive +==================================================== */ +/* Desktop 1200 - up */ +@media (min-width: 1200px) { + .container { + max-width: 1200px; + } +} +/* Desktop 1400 - up */ +@media (min-width: 1400px) { + .container { + max-width: 1300px; + } +} + +/* Normal desktop :992px. (Laptop 14") */ +@media (min-width: 992px) and (max-width: 1199px) { + /* Global */ + h1 { + font-size: 30px; + } + h2 { + font-size: 26px; + } + h3 { + font-size: 22px; + } + h4 { + font-size: 20px; + } + h5 { + font-size: 18px; + } + h6 { + font-size: 16px; + } + +} + + +/* Tablet device :768px. */ +@media (min-width: 768px) and (max-width: 991px) { + /* Global */ + body { + font-size: 14px; + } + h1 { + font-size: 26px; + } + h2 { + font-size: 22px; + } + h3 { + font-size: 20px; + } + h4 { + font-size: 18px; + } + h5 { + font-size: 16px; + } + h6 { + font-size: 15px; + } + p { + font-size: 14px; + } + +} + + +/* small mobile :320px. */ +@media (max-width: 767px) { + /* Global */ + body { + font-size: 14px; + } + h1 { + font-size: 24px; + } + h2 { + font-size: 20px; + } + h3 { + font-size: 18px; + } + h4 { + font-size: 17px; + } + h5 { + font-size: 16px; + } + h6 { + font-size: 14px; + } + p { + font-size: 14px; + } + +} diff --git a/themes/nurgul/assets/css/style.css b/themes/nurgul/assets/css/style.css new file mode 100644 index 0000000..198d5c6 --- /dev/null +++ b/themes/nurgul/assets/css/style.css @@ -0,0 +1,12940 @@ +/* + Template Name: Fiama + Description: Flower Shop eCommerce HTML Template + Version: 1.0.0 +*/ +/* Single side border-radius */ +/* BORDER RADIUS */ +/* user select */ +/* box sizing */ +/* placeholder */ +/* transition */ +/* transform */ +/* rotate */ +/* scale */ +/* translate */ +/* translate rotate */ +/* skew */ +/* ============================================================ +>>> TABLE OF CONTENTS: +=============================================================== +# Google fonts +# Gutter Code +# Normalize +# Typography +# Custom Class +# input and button type focus outline disable +# Form input box +# Text meant only for screen readers. +# Transition + +# Accessibility +# Globals + +# Alignments +# Clearings +# Posts and pages +# Captions +# Galleries +# Unit test +# ScrollUp +# Owl Carousel +# Slick Slider +# Background Overlay +# Scrollbar +# Padding Top +# Padding Bottom +# Margin Top +# Margin Bottom +# Custom margin Padding + +============================================================= */ +/* ------------------------------------- + Google fonts +------------------------------------- */ +@import url("https://fonts.googleapis.com/css2?family=Lora:wght@400;500;600;700&family=Montserrat:wght@400;500;600;700;800&family=Poppins:wght@300;400;500;600;700&display=swap"); +/* +font-family: 'Lora', serif; +font-family: 'Montserrat', sans-serif; +font-family: 'Poppins', sans-serif; +*/ +/* ==================================================== + Gutter Code +==================================================== */ +.container, +.container-fluid { + padding-right: 15px; + padding-left: 15px; } + +.row { + margin-left: -15px; + margin-right: -15px; } + +.col, +.col-1, +.col-10, +.col-11, +.col-12, +.col-2, +.col-3, +.col-4, +.col-5, +.col-6, +.col-7, +.col-8, +.col-9, +.col-auto, +.col-lg, +.col-lg-1, +.col-lg-10, +.col-lg-11, +.col-lg-12, +.col-lg-2, +.col-lg-3, +.col-lg-4, +.col-lg-5, +.col-lg-6, +.col-lg-7, +.col-lg-8, +.col-lg-9, +.col-lg-auto, +.col-md, +.col-md-1, +.col-md-10, +.col-md-11, +.col-md-12, +.col-md-2, +.col-md-3, +.col-md-4, +.col-md-5, +.col-md-6, +.col-md-7, +.col-md-8, +.col-md-9, +.col-md-auto, +.col-sm, +.col-sm-1, +.col-sm-10, +.col-sm-11, +.col-sm-12, +.col-sm-2, +.col-sm-3, +.col-sm-4, +.col-sm-5, +.col-sm-6, +.col-sm-7, +.col-sm-8, +.col-sm-9, +.col-sm-auto, +.col-xl, +.col-xl-1, +.col-xl-10, +.col-xl-11, +.col-xl-12, +.col-xl-2, +.col-xl-3, +.col-xl-4, +.col-xl-5, +.col-xl-6, +.col-xl-7, +.col-xl-8, +.col-xl-9, +.col-xl-auto { + padding-right: 15px; + padding-left: 15px; + position: relative; } + +.ltn__no-gutter > [class*='col-'] { + /* No padding only for child columns */ + padding-right: 0; + padding-left: 0; } + +.ltn__no-gutter-all [class*='col-'] { + /* No padding for every columns */ + padding-right: 0; + padding-left: 0; } + +@media (min-width: 992px) { + /* Modify this based on column def */ + .row { + margin-left: -20px; + margin-right: -20px; } + .col, + .col-1, + .col-10, + .col-11, + .col-12, + .col-2, + .col-3, + .col-4, + .col-5, + .col-6, + .col-7, + .col-8, + .col-9, + .col-auto, + .col-lg, + .col-lg-1, + .col-lg-10, + .col-lg-11, + .col-lg-12, + .col-lg-2, + .col-lg-3, + .col-lg-4, + .col-lg-5, + .col-lg-6, + .col-lg-7, + .col-lg-8, + .col-lg-9, + .col-lg-auto, + .col-md, + .col-md-1, + .col-md-10, + .col-md-11, + .col-md-12, + .col-md-2, + .col-md-3, + .col-md-4, + .col-md-5, + .col-md-6, + .col-md-7, + .col-md-8, + .col-md-9, + .col-md-auto, + .col-sm, + .col-sm-1, + .col-sm-10, + .col-sm-11, + .col-sm-12, + .col-sm-2, + .col-sm-3, + .col-sm-4, + .col-sm-5, + .col-sm-6, + .col-sm-7, + .col-sm-8, + .col-sm-9, + .col-sm-auto, + .col-xl, + .col-xl-1, + .col-xl-10, + .col-xl-11, + .col-xl-12, + .col-xl-2, + .col-xl-3, + .col-xl-4, + .col-xl-5, + .col-xl-6, + .col-xl-7, + .col-xl-8, + .col-xl-9, + .col-xl-auto { + padding-right: 20px; + padding-left: 20px; } + .ltn__custom-gutter { + margin-left: -20px; + margin-right: -20px; } + .ltn__custom-gutter > [class*='col-'] { + padding-right: 20px; + padding-left: 20px; } + .ltn__custom-gutter-all .row { + margin-left: -20px; + margin-right: -20px; } + .ltn__custom-gutter-all .row [class*='col-'] { + padding-right: 20px; + padding-left: 20px; } } + +@media (max-width: 991px) { + /* Modify this based on column def */ + .ltn__custom-gutter { + margin-left: -15px; + margin-right: -15px; } + .ltn__custom-gutter > [class*='col-'] { + padding-right: 15px; + padding-left: 15px; } + .ltn__custom-gutter-all { + margin-left: -15px; + margin-right: -15px; } + .ltn__custom-gutter-all [class*='col-'] { + padding-right: 15px; + padding-left: 15px; } } + +@media (max-width: 576px) { + /* Modify this based on column def */ + .ltn__product-gutter .row { + margin-left: -8px; + margin-right: -8px; } + .ltn__product-gutter [class*='col-'] { + padding-right: 8px; + padding-left: 8px; } } + +/* ---------------------------------------------------- + Normalize 071C1F 0E292D +---------------------------------------------------- */ +:root { + --ltn__primary-color: #565656; + --ltn__secondary-color: #cc1155; + --ltn__heading-color: #010101; + --ltn__paragraph-color: #000000; + --ltn__body-color: #666666; + --ltn__primary-color-2: #041113; + /* Darken */ + --ltn__primary-color-3: #133236; + /* Lighten */ + --ltn__secondary-color-2: #cc1155; + /* Darken */ + --ltn__secondary-color-3: #cc1155; + /* Lighten */ + /* Google Fonts */ + --ltn__heading-font: 'Montserrat', sans-serif; + --ltn__paragraph-font: 'Poppins', sans-serif; + --ltn__body-font: 'Montserrat', sans-serif; + --ltn__google-font-3: 'Lora', serif; + /* Footer */ + --ltn__color-1: #8cb2b2; + --ltn__color-2: #ACD2D8; + --ltn__color-3: #A3BCC0; + --ltn__color-4: #84A2A6; + /* Gradient Colors */ + --gradient-color-1: linear-gradient(90deg, rgba(242,139,194,1) 0%, rgba(216,177,242,1) 50%); + --gradient-color-2: linear-gradient(to top, rgba(7,28,31,0) 0%, rgba(7,28,31,1) 90%); + --gradient-color-3: linear-gradient(to bottom, rgba(7,28,31,0) 0%, rgba(7,28,31,1) 90%); + --gradient-color-4: linear-gradient(to top, rgba(242,246,247,0) 0%, rgba(242,246,247,1) 90%); + /* Background Colors 1, 2, 3, 4, 5 */ + --section-bg-1: #F9F9F9; + /* White */ + --section-bg-2: #071c1f; + /* Black */ + --section-bg-5: #272829; + /* Black */ + --section-bg-6: #FDFDFD; + /* White */ + /* Border Colors */ + --border-color-1: #f0f0f0; + /* White */ + --border-color-2: #1e2021; + /* Black */ + --border-color-3: #576466; + /* Black */ + --border-color-4: #eb6954; + /* Red */ + --border-color-5: #bc3928; + /* Red */ + --border-color-6: #103034; + /* Black */ + --border-color-7: #d1dae0; + /* White */ + --border-color-8: #f6f6f6; + /* White */ + --border-color-9: #e4ecf2; + /* White */ + --border-color-10: #ebeeee; + /* White */ + --border-color-11: #ededed; + /* White */ + --border-color-12: #e1e6ff; + /* White */ + /* Box Shadow Colors */ + --ltn__box-shadow-1: 0 16px 32px 0 rgba(7, 28, 31, 0.1); + --ltn__box-shadow-2: 0 0 4px rgba(0, 0, 0, 0.1); + /* like border */ + --ltn__box-shadow-3: 0 1px 6px 0 rgba(32, 33, 36, .28); + /* like border GGL */ + --ltn__box-shadow-4: 0 5px 20px 0 rgba(23, 44, 82, 0.1); + --ltn__box-shadow-5: 0 8px 16px 0 rgba(93, 93, 93, 0.1); + --ltn__box-shadow-6: 0 0 25px 2px rgba(93, 93, 93, 0.2); + /* Common Colors */ + --black: #000000; + --black-2: #434343; + --black-3: #333333; + --black-4: #4F4F4F; + --black-5: #888888; + --black-6: #3B3C3D; + --black-7: #424242; + --black-8: #717171; + --black-9: #B4B4B4; + --white: #fff; + --white-2: #F2F6F7; + --white-3: #e8edee; + --white-4: #e6ecf0; + --white-5: #f0f4f7; + --white-6: #f1f1f1; + --white-7: #F7F7F7; + --white-8: #FAFAFA; + --white-9: #F2F7FA; + --white-10: #999999; + --white-11: #FDFDFD; + --white-12: #E2E1E1; + --white-13: #F0F0F0; + --white-14: #DFDFDF; + --white-15: #A9A9A9; + --white-16: #ECECEC; + --white-17: #F4F7FC; + --white-18: #E1E1E1; + --red: #FF0000; + --red-2: #f34f3f; + --red-3: #DB483B; + --silver: #C0C0C0; + --gray: #808080; + --maroon: #800000; + --yellow: #FFFF00; + --olive: #808000; + --lime: #00FF00; + --green: #008000; + --green-2: #9AC45C; + --aqua: #00FFFF; + --teal: #008080; + --blue: #0000FF; + --blue-2: #6D5CC4; + --navy: #000080; + --fuchsia: #FF00FF; + --purple: #800080; + --pink: #FFC0CB; + --nude: #ebc8b2; + --orange: #ffa500; + --ratings: #FFB800; + /* social media colors */ + --facebook: #365493; + --twitter: #3CF; + --linkedin: #0077B5; + --pinterest: #c8232c; + --dribbble: #ea4c89; + --behance: #131418; + --google-plus: #dd4b39; + --instagram: #e4405f; + --vk: #3b5998; + --wechat: #7bb32e; + --youtube: #CB2027; + --email: #F89A1E; } + +/* ------------------------------------- + Typography +------------------------------------- */ +html { + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + font-family: var(--ltn__body-font); } + +* { + -webkit-box-sizing: border-box; + box-sizing: border-box; + outline: none; + -moz-osx-font-smoothing: grayscale; + /* Firefox */ + -webkit-font-smoothing: antialiased; + /* WebKit */ } + +body { + color: var(--ltn__body-color); + font-weight: 400; + font-style: normal; + font-size: 16px; + font-family: var(--ltn__body-font); + line-height: 1.8; + margin: 0 auto; } + +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + color: var(--ltn__heading-color); + clear: both; + font-family: var(--ltn__heading-font); + font-weight: 600; + line-height: 1.3; + margin-bottom: 15px; } + +h4, +h5, +h6, +.h4, +.h5, +.h6 { + font-weight: 500; } + +h1, .h1 { + font-size: 36px; + line-height: 1.2; } + +h2, .h2 { + font-size: 30px; } + +h3, .h3 { + font-size: 24px; } + +h4, .h4 { + font-size: 20px; } + +h5, .h5 { + font-size: 18px; } + +h6, .h6 { + font-size: 16px; } + +p { + color: var(--ltn__paragraph-color); + font-family: var(--ltn__paragraph-font); + font-weight: 300; + margin-bottom: 1.5em; + -webkit-hyphens: auto; + -moz-hyphens: auto; + -ms-hyphens: auto; + hyphens: auto; } + +a { + color: inherit; + text-decoration: none; + color: var(--ltn__paragraph-color); + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + +a, +a:hover, +a:focus, +a:active { + text-decoration: none; + outline: none; + color: inherit; } + +a:hover { + color: var(--ltn__secondary-color); } + +button, +input, +optgroup, +select, +textarea { + font-family: var(--ltn__body-font); } + +pre, +code, +kbd, +tt, +var, +samp { + font-family: var(--ltn__body-font); } + +pre { + word-break: break-word; } + +a i { + padding: 0 2px; } + +img { + max-width: 100%; } + +ul li, +ol li { + margin-top: 1rem; } + +/* ------------------------------------- + Custom Class +------------------------------------- */ +.section-bg-1 { + background-color: var(--section-bg-1); } + .section-bg-1 .ltn__separate-line .separate-icon { + background-color: var(--section-bg-1); } + +.section-bg-2 { + background-color: var(--section-bg-2); } + .section-bg-2 h1, + .section-bg-2 h2, + .section-bg-2 h3, + .section-bg-2 h4, + .section-bg-2 h5, + .section-bg-2 h6, + .section-bg-2 p, + .section-bg-2 li, + .section-bg-2 i, + .section-bg-2 span, + .section-bg-2 tr, + .section-bg-2 td { + color: var(--white); } + .section-bg-2 .ltn__separate-line .separate-icon { + background-color: var(--black-2); } + +.section-bg-3 { + position: relative; } + .section-bg-3:before { + position: absolute; + content: ""; + top: 0; + left: 0; + right: 0; + width: 100%; + height: 100%; + background: var(--gradient-color-1); + opacity: 0.9; } + .section-bg-3 h1, + .section-bg-3 h2, + .section-bg-3 h3, + .section-bg-3 h4, + .section-bg-3 h5, + .section-bg-3 h6, + .section-bg-3 p, + .section-bg-3 li, + .section-bg-3 i, + .section-bg-3 span, + .section-bg-3 tr, + .section-bg-3 td { + color: var(--white); } + .section-bg-3 .slick-arrow-1 .slick-arrow { + background-color: transparent; } + .section-bg-3 input[type="text"], + .section-bg-3 input[type="email"], + .section-bg-3 input[type="password"], + .section-bg-3 input[type="submit"] { + border-color: var(--white); + color: var(--white); } + .section-bg-3 .btn-wrapper button { + color: var(--white); } + .section-bg-3 input::-webkit-input-placeholder { + color: var(--white); } + .section-bg-3 input::-moz-placeholder { + color: var(--white); } + .section-bg-3 input:-ms-input-placeholder { + color: var(--white); } + .section-bg-3 input:-moz-placeholder { + color: var(--white); } + .section-bg-3 .ltn__separate-line .separate-icon { + background: var(--gradient-color-1); } + .section-bg-3 .ltn__separate-line .separate-icon i { + color: var(--white); } + +.section-bg-4 { + background-color: var(--ltn__primary-color-2); } + .section-bg-4 h1, + .section-bg-4 h2, + .section-bg-4 h3, + .section-bg-4 h4, + .section-bg-4 h5, + .section-bg-4 h6, + .section-bg-4 p, + .section-bg-4 li, + .section-bg-4 i, + .section-bg-4 span, + .section-bg-4 tr, + .section-bg-4 td { + color: var(--white); } + .section-bg-4 .ltn__separate-line .separate-icon { + background-color: var(--black-2); } + .section-bg-4 .ltn__copyright-design h6, .section-bg-4 .ltn__copyright-design h4 { + color: var(--ltn__color-1); } + +.section-bg-5 { + background-color: var(--section-bg-5); } + +.section-bg-6 { + background-color: var(--section-bg-6); } + +.text-color-white { + color: var(--white); } + .text-color-white h1, + .text-color-white h2, + .text-color-white h3, + .text-color-white h4, + .text-color-white h5, + .text-color-white h6, + .text-color-white p, + .text-color-white li, + .text-color-white i, + .text-color-white span, + .text-color-white tr, + .text-color-white td { + color: var(--white); } + +.ltn__primary-color { + color: var(--ltn__primary-color) !important; } + +.ltn__primary-color-2 { + color: var(--ltn__primary-color-2) !important; } + +.ltn__primary-color-3 { + color: var(--ltn__primary-color-3) !important; } + +.ltn__secondary-color { + color: var(--ltn__secondary-color) !important; } + +.ltn__secondary-color-2 { + color: var(--ltn__secondary-color-2) !important; } + +.ltn__secondary-color-3 { + color: var(--ltn__secondary-color-3) !important; } + +.ltn__heading-color { + color: var(--ltn__heading-color) !important; } + +.ltn__paragraph-color { + color: var(--ltn__paragraph-color) !important; } + +.ltn__body-color { + color: var(--ltn__body-color) !important; } + +.ltn__color-1 { + color: var(--ltn__color-1); } + +.white-color { + color: var(--white); } + +.white-color-im { + color: var(--white) !important; } + +.ltn__primary-bg { + background-color: var(--ltn__primary-color); } + +.ltn__primary-bg-2 { + background-color: var(--ltn__primary-color-2); } + +.ltn__secondary-bg { + background-color: var(--ltn__secondary-color); } + +.ltn__secondary-bg-2 { + background-color: var(--ltn__secondary-color-2); } + +.white-bg { + background-color: var(--white); } + +.gradient-color-1 { + background: var(--gradient-color-1); } + +.gradient-color-2 { + background: var(--gradient-color-2); } + +.gradient-color-3 { + background: var(--gradient-color-3); } + +.gradient-color-4 { + background: var(--gradient-color-4); } + +.before-bg-1 { + position: relative; } + .before-bg-1:before { + position: absolute; + content: ""; + width: 100%; + height: 34.2%; + left: 0; + bottom: 0; + background-color: var(--section-bg-1); } + +.before-bg-bottom { + position: relative; } + .before-bg-bottom:before { + position: absolute; + content: ""; + width: 100%; + height: 55%; + left: 0; + bottom: 0; + background-color: var(--section-bg-2); } + +.before-bg-bottom-2 { + position: relative; } + .before-bg-bottom-2:before { + position: absolute; + content: ""; + width: 100%; + height: 50%; + left: 0; + bottom: 0; + background-color: var(--section-bg-1); } + +.before-bg-right { + position: relative; } + .before-bg-right:before { + position: absolute; + content: ""; + width: 25%; + height: 100%; + left: auto; + right: 0; + top: 0; + background-color: var(--ltn__primary-color); } + +.before-bg-left { + position: relative; } + .before-bg-left:before { + position: absolute; + content: ""; + width: 25%; + height: 100%; + left: 0; + right: auto; + top: 0; + background-color: var(--ltn__primary-color); } + +.box-shadow { + -webkit-box-shadow: var(--ltn__box-shadow-2); + box-shadow: var(--ltn__box-shadow-2); } + +.ltn__custom-icon { + position: relative; } + .ltn__custom-icon::before { + content: "\f063"; + font-family: 'Font Awesome\ 5 Free'; + font-weight: 900; } + +.ltn__border { + border: 1px solid var(--border-color-1); } + +.ltn__border-top { + border-top: 1px solid var(--border-color-1); } + +.ltn__border-top-2 { + border-top: 1px solid var(--black-6); } + +.ltn__border-bottom { + border-bottom: 1px solid var(--border-color-1); } + +.border-color-1 { + border-color: var(--border-color-1) !important; } + +.border-color-2 { + border-color: var(--border-color-2) !important; } + +.border-color-3 { + border-color: var(--border-color-3) !important; } + +mark { + background-color: var(--ltn__primary-color); + padding: 3px 15px; + color: var(--white); + border-radius: 25px; } + +hr { + margin-top: 40px; + margin-bottom: 40px; + border-top: 1px solid var(--white-6); } + +a.text-decoration, +.text-decoration a { + text-decoration: underline; } + +fieldset { + padding: 30px 40px; + border: 1px solid #eee; } + +fieldset legend { + font-size: 18px; + font-weight: 400; + line-height: 1; + width: auto; + margin-top: -9px; + margin-bottom: 0; + padding: 0 15px; + text-transform: uppercase; + color: #333; + background-color: #fff; } + +@media (max-width: 991px) { + .before-bg-right:before { + width: 0; } + .before-bg-left:before { + width: 0; } } + +.position-relative { + position: relative; } + +.font-weight-5 { + font-weight: 500; } + +.font-weight-6 { + font-weight: 600; } + +/* ---------------------------------------------------- + input and button type focus outline disable +---------------------------------------------------- */ +input[type="text"]:focus, +input[type="email"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +input[type="search"]:focus, +input[type="tel"]:focus, +input[type="number"]:focus, +textarea:focus, +input[type="button"]:focus, +input[type="reset"]:focus, +input[type="submit"]:focus, +select:focus { + outline: none; + -webkit-box-shadow: none; + box-shadow: none; + border: 1px solid #ddd; } + +code { + color: #faa603; } + +/* ---------------------------------------------------- + Form input box +---------------------------------------------------- */ +input[type="text"], +input[type="email"], +input[type="password"], +input[type="submit"], +textarea { + background-color: var(--white-7); + border: none; + border-color: var(--border-color-9); + height: 50px; + -webkit-box-shadow: none; + box-shadow: none; + padding-left: 20px; + font-size: 16px; + color: var(--ltn__paragraph-color); + width: 100%; + margin-bottom: 30px; + border-radius: 0; + padding-right: 40px; } + +input[type="text"]::-webkit-input-placeholder, +input[type="email"]::-webkit-input-placeholder, +input[type="password"]::-webkit-input-placeholder, +input[type="submit"]::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { + /* Chrome/Opera/Safari */ + color: var(--ltn__paragraph-color); + font-size: 14px; } + +input[type="text"]:focus, +input[type="email"]:focus, +input[type="password"]:focus, +textarea:focus { + border-color: var(--ltn__secondary-color); } + +input[type="password"] { + letter-spacing: 3px; + font-size: 16px; } + +textarea { + resize: vertical; + padding: 15px 20px; + min-height: 150px; } + +button { + outline: none; + border: none; + cursor: pointer; } + +button:focus { + outline: none; } + +.form-input-box { + position: relative; } + +.form-input-box input[type="text"] { + width: 100%; + height: 50px; + padding: 0 70px 0 15px; + border-radius: 0 15px 0px 0px; + border: 1px solid var(--ltn__primary-color); + margin-bottom: 0; } + +.form-input-box button[type="submit"] { + background-color: var(--ltn__primary-color); + color: var(--white); + padding: 0 18px; + height: 100%; + border: 1px solid var(--ltn__primary-color); + position: absolute; + right: 0; + top: 0; + cursor: pointer; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + +.form-input-box button[type="submit"]:hover { + background-color: var(--ltn__secondary-color); + border-color: var(--ltn__secondary-color); + color: var(--white); } + +/* input-item */ +.input-item { + position: relative; } + .input-item.ltn__custom-icon::before { + position: absolute; + top: 35%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + right: 20px; + color: var(--ltn__secondary-color); } + +.input-item-name.ltn__custom-icon::before { + content: "\f007"; } + +.input-item-email.ltn__custom-icon::before { + content: "\f0e0"; } + +.input-item-phone.ltn__custom-icon::before { + content: "\f095"; } + +.input-item-subject.ltn__custom-icon::before { + content: "\f06e"; } + +.input-item-website.ltn__custom-icon::before { + content: "\f0ac"; } + +.input-item-date.ltn__custom-icon::before { + content: "\f073"; } + +.input-item-textarea.ltn__custom-icon::before { + content: "\f303"; + top: 30px; } + +.input-info-save { + font-size: 14px; } + +label.checkbox-inline { + font-size: 14px; } + +/* ---------------------------------------------------- + Text meant only for screen readers. +---------------------------------------------------- */ +.screen-reader-text { + border: 0; + clip: rect(1px, 1px, 1px, 1px); + -webkit-clip-path: inset(50%); + clip-path: inset(50%); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute !important; + width: 1px; + word-wrap: normal !important; + /* Many screen reader and browser combinations announce broken words as they would appear visually. */ } + +.screen-reader-text:focus { + background-color: #f1f1f1; + border-radius: 3px; + -webkit-box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6); + box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6); + clip: auto !important; + -webkit-clip-path: none; + clip-path: none; + color: #21759b; + display: block; + font-size: 14px; + font-size: 0.875rem; + font-weight: bold; + height: auto; + left: 5px; + line-height: normal; + padding: 15px 23px 14px; + text-decoration: none; + top: 5px; + width: auto; + z-index: 100000; + /* Above WP toolbar. */ } + +/* Do not show the outline on the skip link target. */ +#content[tabindex="-1"]:focus { + outline: 0; } + +/* ------------------------------------- + Transition +------------------------------------- */ +/* ---------------------------------------------------- + Alignments +---------------------------------------------------- */ +.alignleft { + float: left; + clear: both; + margin-right: 20px; } + +.alignright { + float: right; + clear: both; + margin-left: 20px; } + +.aligncenter { + clear: both; + display: block; + margin: 0 auto 1.75em; } + +.alignfull { + margin: 1.5em 0; + max-width: 100%; } + +.alignwide { + max-width: 1100px; } + +.fix { + overflow: hidden; } + +/* ---------------------------------------------------- + Clearings +---------------------------------------------------- */ +.clear:before, +.clear:after, +.entry-content:before, +.entry-content:after, +.comment-content:before, +.comment-content:after, +.site-header:before, +.site-header:after, +.site-content:before, +.site-content:after, +.site-footer:before, +.site-footer:after { + content: ""; + display: table; + table-layout: fixed; } + +.clear:after, +.entry-content:after, +.comment-content:after, +.site-header:after, +.site-content:after, +.site-footer:after { + clear: both; } + +/* ---------------------------------------------------- + Posts and pages +---------------------------------------------------- */ +.sticky { + display: block; } + +.updated:not(.published) { + display: none; } + +.blog-pagination ul li { + display: inline-block; } + +.blog-pagination ul li + li { + margin: 0 5px; } + +.blog-pagination { + display: block; + width: 100%; } + +.blog-pagination ul { + margin: 0; + padding: 0; + list-style: none; } + +.blog-pagination ul li a, +.blog-pagination ul li span { + display: block; + width: 40px; + height: 40px; + border: 1px solid #e2e2e2; + line-height: 40px; + text-align: center; + font-weight: 600; + -webkit-transition: .3s ease-in; + -o-transition: .3s ease-in; + transition: .3s ease-in; } + +.blog-pagination ul li span.current, +.blog-pagination ul li a:hover { + background-color: var(--ltn__primary-color); + color: #fff; } + +/* ---------------------------------------------------- + Media +---------------------------------------------------- */ +.page-content .wp-smiley, +.entry-content .wp-smiley, +.comment-content .wp-smiley { + border: none; + margin-bottom: 0; + margin-top: 0; + padding: 0; } + +/* Make sure embeds and iframes fit their containers. */ +embed, +iframe, +object { + max-width: 100%; } + +/* Make sure logo link wraps around logo image. */ +.custom-logo-link { + display: inline-block; } + +/* ---------------------------------------------------- + Captions +---------------------------------------------------- */ +.wp-caption { + margin-bottom: 1.5em; + max-width: 100%; + clear: both; } + +.wp-caption img[class*="wp-image-"] { + display: block; + margin-left: auto; + margin-right: auto; } + +.wp-caption .wp-caption-text { + margin: 0.8075em 0; } + +.wp-caption-text { + text-align: center; } + +/* ---------------------------------------------------- + Galleries +---------------------------------------------------- */ +.gallery { + margin-bottom: 1.5em; } + +.gallery-item { + display: inline-block; + text-align: center; + vertical-align: top; + width: 100%; } + +.gallery-columns-2 .gallery-item { + max-width: 50%; } + +.gallery-columns-3 .gallery-item { + max-width: 33.33%; } + +.gallery-columns-4 .gallery-item { + max-width: 25%; } + +.gallery-columns-5 .gallery-item { + max-width: 20%; } + +.gallery-columns-6 .gallery-item { + max-width: 16.66%; } + +.gallery-columns-7 .gallery-item { + max-width: 14.28%; } + +.gallery-columns-8 .gallery-item { + max-width: 12.5%; } + +.gallery-columns-9 .gallery-item { + max-width: 11.11%; } + +.gallery-caption { + display: block; } + +/* ---------------------------------------------------- + Unit test +---------------------------------------------------- */ +.wp-link-pages a { + margin: 0 5px; + -webkit-transition: .3s ease-in; + -o-transition: .3s ease-in; + transition: .3s ease-in; } + +.wp-link-pages { + margin-bottom: 30px; + margin-top: 25px; } + +.wp-link-pages span, +.wp-link-pages a { + border: 1px solid #e2e2e2; + padding: 5px 15px; + display: inline-block; } + +.wp-link-pages .current, +.wp-link-pages a:hover { + background-color: var(--ltn__primary-color); + color: #fff; + border-color: var(--ltn__primary-color); } + +.wp-link-pages span:first-child { + margin-right: 5px; } + +dl, +ol, +ul { + padding-left: 20px; } + +.post-password-form input { + display: block; + border: 1px solid #e2e2e2; + height: 50px; + border-radius: 3px; + padding: 0 20px; } + +.post-password-form label { + font-weight: 600; + color: #333; } + +.post-password-form input[type=submit] { + width: 100px; + height: 50px; + background-color: var(--ltn__primary-color); + color: #fff; + font-size: 16px; + font-weight: 600; + letter-spacing: 1px; + border: none; + cursor: pointer; + -webkit-transition: .3s ease-in; + -o-transition: .3s ease-in; + transition: .3s ease-in; } + +.post-password-form input[type=submit]:hover { + background-color: #121A2F; } + +.footer-widget .table td, +.footer-widget .table th { + padding: 0.50rem !important; } + +/* ---------------------------------------------------- + ScrollUp +---------------------------------------------------- */ +#scrollUp { + background-color: var(--section-bg-1); + color: var(--ltn__heading-color); + bottom: 70px; + font-size: 20px; + font-weight: bold; + height: 40px; + width: 40px; + right: 3%; + text-align: center; + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + -webkit-box-shadow: var(--ltn__box-shadow-3); + box-shadow: var(--ltn__box-shadow-3); } + #scrollUp i { + line-height: 40px; + -webkit-transform: rotate(-45deg); + -ms-transform: rotate(-45deg); + transform: rotate(-45deg); } + #scrollUp:hover { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +/* ---------------------------------------------------- + Owl Carousel +---------------------------------------------------- */ +.owl-dots { + display: block; + text-align: center; + margin-top: 20px; } + +.owl-dots .owl-dot { + display: inline-block; + background-color: var(--ltn__secondary-color); + height: 10px; + width: 10px; + margin-right: 30px; + border-radius: 100%; } + +.owl-dots .owl-dot:last-child { + margin-right: 0px; } + +.owl-dots .owl-dot:hover, +.owl-dots .owl-dot.active { + background-color: var(--ltn__primary-color); } + +/* owl-arrow-1 */ +.owl-arrow-1 .owl-nav > div { + position: absolute; + left: -60px; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + right: auto; } + +.owl-arrow-1 .owl-nav > div.owl-next { + left: auto; + right: -60px; } + +@media only screen and (max-width: 1200px) { + .owl-arrow-1 .owl-nav > div { + right: auto; + left: 0px; } + .owl-arrow-1 .owl-nav > div.owl-next { + right: 0px; + left: auto; } } + +/* ---------------------------------------------------- + Slick Slider Dots, Arrow +---------------------------------------------------- */ +/* Slick dots */ +.slick-dots { + margin: 0 0 30px; + padding: 0; + display: block; + text-align: center; + line-height: 1; } + .slick-dots li { + display: inline-block; + list-style: none; + display: inline-block; + font-size: 0; + height: 10px; + width: 10px; + border-radius: 100%; + margin-right: 20px; + background-color: var(--silver); + cursor: pointer; + margin-top: 0; } + .slick-dots li button { + display: none; } + .slick-dots li:hover, .slick-dots li.slick-active { + background-color: var(--ltn__secondary-color); } + +/* slick-arrow */ +.slick-arrow { + cursor: pointer; + z-index: 9; } + +/* slick-arrow-1 */ +.slick-arrow-1 .slick-arrow { + background-color: var(--white); + cursor: pointer; + position: absolute; + top: 50%; + left: 15px; + right: auto; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + width: 50px; + height: 50px; + line-height: 50px; + display: block; + border: 1px solid var(--white-4); + border-radius: 100%; + text-align: center; + font-size: 16px; + color: var(--ltn__primary-color) !important; + z-index: 1; + opacity: 0; + visibility: hidden; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } + .slick-arrow-1 .slick-arrow:hover { + background-color: var(--ltn__secondary-color); + border-color: var(--ltn__secondary-color); + color: var(--white) !important; } + +.slick-arrow-1 .slick-next { + right: 15px; + left: auto; } + +.slick-arrow-1:hover .slick-arrow { + opacity: 1; + visibility: visible; } + +.slick-arrow-1-inner.slick-arrow-1:hover .slick-arrow { + left: 50px; + right: auto; } + +.slick-arrow-1-inner.slick-arrow-1:hover .slick-next { + right: 50px; + left: auto; } + +@media (min-width: 1350px) { + .slick-arrow-1:hover .slick-arrow { + left: -50px; + right: auto; } + .slick-arrow-1:hover .slick-next { + right: -50px; + left: auto; } } + +/* slick-arrow-2 */ +.slick-arrow-2 .slick-arrow { + color: var(--ltn__primary-color) !important; + cursor: pointer; + position: absolute; + bottom: -30px; + height: 30px; + width: 30px; + line-height: 28px; + display: block; + left: 15px; + border: 1px solid var(--border-color-1); + text-align: center; } + .slick-arrow-2 .slick-arrow:hover { + background-color: var(--ltn__secondary-color); + border-color: var(--ltn__secondary-color); + color: var(--white) !important; } + +.slick-arrow-2 .slick-next { + left: 60px; } + +/* slick-arrow-3 */ +.slick-arrow-3 .slick-arrow { + cursor: pointer; + position: absolute; + top: -120px; + height: 60px; + width: 60px; + line-height: 58px; + display: block; + left: auto; + right: 100px; + border: 2px solid; + text-align: center; + -webkit-box-shadow: var(--ltn__box-shadow-2); + box-shadow: var(--ltn__box-shadow-2); } + .slick-arrow-3 .slick-arrow:hover { + background-color: var(--ltn__secondary-color); + border-color: var(--border-color-4); + color: var(--white) !important; } + +.slick-arrow-3 .slick-next { + right: 15px; + background-color: var(--white); + border-color: var(--white); + color: var(--ltn__primary-color) !important; } + +.slick-arrow-3 .slick-prev { + background-color: var(--ltn__secondary-color); + border-color: var(--border-color-4); + color: var(--white) !important; } + +/* slick-arrow-4 */ +.slick-arrow-4 { + margin: 0; } + .slick-arrow-4 .slick-arrow { + position: absolute; + bottom: -50px; + left: 0; + right: 0; + text-align: center; + height: 50px; + width: 50px; + line-height: 50px; + margin: 0 auto; + border: 1px solid; + border-radius: 100%; } + .slick-arrow-4 .slick-arrow:hover { + background-color: var(--ltn__secondary-color); + border-color: var(--border-color-4); + color: var(--white) !important; } + .slick-arrow-4 .slick-next { + right: -60px; } + .slick-arrow-4 .slick-prev { + left: -60px; } + +@media (max-width: 767px) { + .slick-dots { + margin: 0 0 15px; } } + +/* ---------------------------------------------------- + Background Overlay +---------------------------------------------------- */ +.bg-overlay-black-10, +.bg-overlay-black-20, +.bg-overlay-black-30, +.bg-overlay-black-40, +.bg-overlay-black-50, +.bg-overlay-black-60, +.bg-overlay-black-70, +.bg-overlay-black-80, +.bg-overlay-black-90, +.bg-overlay-white-10, +.bg-overlay-white-20, +.bg-overlay-white-30, +.bg-overlay-white-40, +.bg-overlay-white-50, +.bg-overlay-white-60, +.bg-overlay-white-70, +.bg-overlay-white-80, +.bg-overlay-white-90 { + z-index: 8; + position: relative; } + +.bg-overlay-black-10:before, +.bg-overlay-black-20:before, +.bg-overlay-black-30:before, +.bg-overlay-black-40:before, +.bg-overlay-black-50:before, +.bg-overlay-black-60:before, +.bg-overlay-black-70:before, +.bg-overlay-black-80:before, +.bg-overlay-black-90:before, +.bg-overlay-white-10:before, +.bg-overlay-white-20:before, +.bg-overlay-white-30:before, +.bg-overlay-white-40:before, +.bg-overlay-white-50:before, +.bg-overlay-white-60:before, +.bg-overlay-white-70:before, +.bg-overlay-white-80:before, +.bg-overlay-white-90:before { + position: absolute; + content: ""; + left: 0; + top: 0; + height: 100%; + width: 100%; + z-index: -1; } + +.bg-overlay-black-10:before { + background: rgba(0, 0, 0, 0.1); } + +.bg-overlay-black-20:before { + background: rgba(0, 0, 0, 0.2); } + +.bg-overlay-black-30:before { + background: rgba(0, 0, 0, 0.3); } + +.bg-overlay-black-40:before { + background: rgba(0, 0, 0, 0.4); } + +.bg-overlay-black-50:before { + background: rgba(0, 0, 0, 0.5); } + +.bg-overlay-black-60:before { + background: rgba(0, 0, 0, 0.6); } + +.bg-overlay-black-70:before { + background: rgba(0, 0, 0, 0.7); } + +.bg-overlay-black-80:before { + background: rgba(0, 0, 0, 0.8); } + +.bg-overlay-black-90:before { + background: rgba(0, 0, 0, 0.9); } + +.bg-overlay-white-10:before { + background: rgba(255, 255, 255, 0.1); } + +.bg-overlay-white-20:before { + background: rgba(255, 255, 255, 0.2); } + +.bg-overlay-white-30:before { + background: rgba(255, 255, 255, 0.3); } + +.bg-overlay-white-40:before { + background: rgba(255, 255, 255, 0.4); } + +.bg-overlay-white-50:before { + background: rgba(255, 255, 255, 0.5); } + +.bg-overlay-white-60:before { + background: rgba(255, 255, 255, 0.6); } + +.bg-overlay-white-70:before { + background: rgba(255, 255, 255, 0.7); } + +.bg-overlay-white-80:before { + background: rgba(255, 255, 255, 0.8); } + +.bg-overlay-white-90:before { + background: rgba(255, 255, 255, 0.9); } + +.bg-overlay-theme-10, +.bg-overlay-theme-20, +.bg-overlay-theme-30, +.bg-overlay-theme-40, +.bg-overlay-theme-50, +.bg-overlay-theme-60, +.bg-overlay-theme-70, +.bg-overlay-theme-80, +.bg-overlay-theme-90 { + z-index: 9; + position: relative; } + +.bg-overlay-theme-10:before, +.bg-overlay-theme-20:before, +.bg-overlay-theme-30:before, +.bg-overlay-theme-40:before, +.bg-overlay-theme-50:before, +.bg-overlay-theme-60:before, +.bg-overlay-theme-70:before, +.bg-overlay-theme-80:before, +.bg-overlay-theme-90:before { + position: absolute; + content: ""; + left: 0; + top: 0; + height: 100%; + width: 100%; + z-index: -1; } + +.bg-overlay-theme-10:before { + background: rgba(229, 62, 41, 0.1); } + +.bg-overlay-theme-20:before { + background: rgba(229, 62, 41, 0.2); } + +.bg-overlay-theme-30:before { + background: rgba(229, 62, 41, 0.3); } + +.bg-overlay-theme-40:before { + background: rgba(229, 62, 41, 0.4); } + +.bg-overlay-theme-50:before { + background: rgba(229, 62, 41, 0.5); } + +.bg-overlay-theme-60:before { + background: rgba(229, 62, 41, 0.6); } + +.bg-overlay-theme-70:before { + background: rgba(229, 62, 41, 0.7); } + +.bg-overlay-theme-80:before { + background: rgba(229, 62, 41, 0.8); } + +.bg-overlay-theme-90:before { + background: rgba(229, 62, 41, 0.9); } + +.bg-overlay-theme-black-10, +.bg-overlay-theme-black-20, +.bg-overlay-theme-black-30, +.bg-overlay-theme-black-40, +.bg-overlay-theme-black-50, +.bg-overlay-theme-black-60, +.bg-overlay-theme-black-70, +.bg-overlay-theme-black-80, +.bg-overlay-theme-black-90 { + z-index: 9; + position: relative; } + +.bg-overlay-theme-black-10:before, +.bg-overlay-theme-black-20:before, +.bg-overlay-theme-black-30:before, +.bg-overlay-theme-black-40:before, +.bg-overlay-theme-black-50:before, +.bg-overlay-theme-black-60:before, +.bg-overlay-theme-black-70:before, +.bg-overlay-theme-black-80:before, +.bg-overlay-theme-black-90:before { + position: absolute; + content: ""; + left: 0; + top: 0; + height: 100%; + width: 100%; + z-index: -1; } + +.bg-overlay-theme-black-10:before { + background: rgba(7, 28, 31, 0.1); } + +.bg-overlay-theme-black-20:before { + background: rgba(7, 28, 31, 0.2); } + +.bg-overlay-theme-black-30:before { + background: rgba(7, 28, 31, 0.3); } + +.bg-overlay-theme-black-40:before { + background: rgba(7, 28, 31, 0.4); } + +.bg-overlay-theme-black-50:before { + background: rgba(7, 28, 31, 0.5); } + +.bg-overlay-theme-black-60:before { + background: rgba(7, 28, 31, 0.6); } + +.bg-overlay-theme-black-70:before { + background: rgba(7, 28, 31, 0.7); } + +.bg-overlay-theme-black-80:before { + background: rgba(7, 28, 31, 0.8); } + +.bg-overlay-theme-black-90:before { + background: rgba(7, 28, 31, 0.9); } + +/* ---------------------------------------------- + Scrollbar +---------------------------------------------- */ +.ltn__scrollbar { + overflow-y: auto; } + +.ltn__scrollbar::-webkit-scrollbar { + width: 2px; + background-color: #f5f5f5; + border-radius: 30px; } + +.ltn__scrollbar::-webkit-scrollbar-thumb { + background-color: #ddd; } + +.mean-nav { + overflow-y: auto; } + +.mean-nav::-webkit-scrollbar { + width: 3px; + background-color: var(--ltn__primary-color); + border-radius: 30px; } + +.mean-nav::-webkit-scrollbar-thumb { + background-color: var(--ltn__secondary-color); } + +/* ---------------------------------------------------- + Padding Top +---------------------------------------------------- */ +.pt-0 { + padding-top: 0px !important; } + +.pt-10 { + padding-top: 10px !important; } + +.pt-15 { + padding-top: 15px !important; } + +.pt-20 { + padding-top: 20px !important; } + +.pt-25 { + padding-top: 25px; } + +.pt-30 { + padding-top: 30px; } + +.pt-35 { + padding-top: 35px; } + +.pt-40 { + padding-top: 40px; } + +.pt-45 { + padding-top: 45px; } + +.pt-50 { + padding-top: 50px; } + +.pt-55 { + padding-top: 55px; } + +.pt-60 { + padding-top: 60px; } + +.pt-65 { + padding-top: 65px; } + +.pt-70 { + padding-top: 70px; } + +.pt-75 { + padding-top: 75px; } + +.pt-80 { + padding-top: 80px; } + +.pt-85 { + padding-top: 85px; } + +.pt-90 { + padding-top: 90px; } + +.pt-95 { + padding-top: 95px; } + +.pt-97 { + padding-top: 97px; } + +.pt-100 { + padding-top: 100px; } + +.pt-105 { + padding-top: 105px; } + +.pt-110 { + padding-top: 110px; } + +.pt-112 { + padding-top: 112px; } + +.pt-115 { + padding-top: 115px; } + +.pt-118 { + padding-top: 118px; } + +.pt-120 { + padding-top: 120px; } + +.pt-122 { + padding-top: 122px; } + +.pt-125 { + padding-top: 125px; } + +.pt-130 { + padding-top: 130px; } + +.pt-135 { + padding-top: 135px; } + +.pt-140 { + padding-top: 140px; } + +.pt-145 { + padding-top: 145px; } + +.pt-150 { + padding-top: 150px; } + +.pt-155 { + padding-top: 155px; } + +.pt-160 { + padding-top: 160px; } + +.pt-170 { + padding-top: 170px; } + +.pt-180 { + padding-top: 180px; } + +.pt-190 { + padding-top: 190px; } + +.pt-200 { + padding-top: 200px; } + +.pt-210 { + padding-top: 210px; } + +.pt-220 { + padding-top: 220px; } + +.pt-230 { + padding-top: 230px; } + +.pt-250 { + padding-top: 250px; } + +.pt-280 { + padding-top: 280px; } + +.pt-290 { + padding-top: 290px; } + +.pt-300 { + padding-top: 300px; } + +.pt-310 { + padding-top: 310px; } + +.pt-320 { + padding-top: 320px; } + +.pt-350 { + padding-top: 350px; } + +/* ---------------------------------------------------- + Padding Bottom +---------------------------------------------------- */ +.pb-0 { + padding-bottom: 0px !important; } + +.pb-10 { + padding-bottom: 10px !important; } + +.pb-15 { + padding-bottom: 15px !important; } + +.pb-20 { + padding-bottom: 20px !important; } + +.pb-25 { + padding-bottom: 25px; } + +.pb-30 { + padding-bottom: 30px; } + +.pb-35 { + padding-bottom: 35px; } + +.pb-40 { + padding-bottom: 40px; } + +.pb-45 { + padding-bottom: 45px; } + +.pb-50 { + padding-bottom: 50px; } + +.pb-55 { + padding-bottom: 55px; } + +.pb-60 { + padding-bottom: 60px; } + +.pb-65 { + padding-bottom: 65px; } + +.pb-70 { + padding-bottom: 70px; } + +.pb-75 { + padding-bottom: 75px; } + +.pb-80 { + padding-bottom: 80px; } + +.pb-85 { + padding-bottom: 85px; } + +.pb-90 { + padding-bottom: 90px; } + +.pb-95 { + padding-bottom: 95px; } + +.pb-97 { + padding-bottom: 97px; } + +.pb-100 { + padding-bottom: 100px; } + +.pb-105 { + padding-bottom: 105px; } + +.pb-107 { + padding-bottom: 107px; } + +.pb-110 { + padding-bottom: 110px; } + +.pb-112 { + padding-bottom: 112px; } + +.pb-115 { + padding-bottom: 115px; } + +.pb-118 { + padding-bottom: 118px; } + +.pb-120 { + padding-bottom: 120px; } + +.pb-122 { + padding-bottom: 122px; } + +.pb-125 { + padding-bottom: 125px; } + +.pb-130 { + padding-bottom: 130px; } + +.pb-140 { + padding-bottom: 140px; } + +.pb-145 { + padding-bottom: 145px; } + +.pb-150 { + padding-bottom: 150px; } + +.pb-155 { + padding-bottom: 155px; } + +.pb-160 { + padding-bottom: 160px; } + +.pb-170 { + padding-bottom: 170px; } + +.pb-180 { + padding-bottom: 180px; } + +.pb-190 { + padding-bottom: 190px; } + +.pb-200 { + padding-bottom: 200px; } + +.pb-210 { + padding-bottom: 210px; } + +.pb-220 { + padding-bottom: 220px; } + +.pb-250 { + padding-bottom: 250px; } + +.pb-280 { + padding-bottom: 280px; } + +.pb-290 { + padding-bottom: 290px; } + +.pb-300 { + padding-bottom: 300px; } + +.pb-310 { + padding-bottom: 310px; } + +.pb-320 { + padding-bottom: 320px; } + +.pb-350 { + padding-bottom: 350px; } + +/* ---------------------------------------------------- + Margin Top +---------------------------------------------------- */ +.mt-0 { + margin-top: 0px !important; } + +.mt-10 { + margin-top: 10px !important; } + +.mt-12 { + margin-top: 12px !important; } + +.mt-15 { + margin-top: 15px !important; } + +.mt-20 { + margin-top: 20px !important; } + +.mt-25 { + margin-top: 25px; } + +.mt-30 { + margin-top: 30px; } + +.mt-35 { + margin-top: 35px; } + +.mt-37 { + margin-top: 37px; } + +.mt-40 { + margin-top: 40px; } + +.mt-45 { + margin-top: 45px; } + +.mt-50 { + margin-top: 50px; } + +.mt-55 { + margin-top: 55px; } + +.mt-60 { + margin-top: 60px; } + +.mt-65 { + margin-top: 65px; } + +.mt-70 { + margin-top: 70px; } + +.mt-80 { + margin-top: 80px; } + +.mt-90 { + margin-top: 90px; } + +.mt-95 { + margin-top: 95px; } + +.mt-100 { + margin-top: 100px; } + +.mt-105 { + margin-top: 105px; } + +.mt-110 { + margin-top: 110px; } + +.mt-115 { + margin-top: 115px; } + +.mt-118 { + margin-top: 118px; } + +.mt-120 { + margin-top: 120px; } + +.mt-122 { + margin-top: 122px; } + +.mt-125 { + margin-top: 125px; } + +.mt-130 { + margin-top: 130px; } + +.mt-140 { + margin-top: 140px; } + +.mt-150 { + margin-top: 150px; } + +.mt-160 { + margin-top: 160px; } + +.mt-170 { + margin-top: 170px; } + +/* ---------------------------------------------------- + Margin Bottom +---------------------------------------------------- */ +.mb-0 { + margin-bottom: 0px !important; } + +.mb-10 { + margin-bottom: 10px !important; } + +.mb-12 { + margin-bottom: 12px !important; } + +.mb-15 { + margin-bottom: 15px !important; } + +.mb-20 { + margin-bottom: 20px !important; } + +.mb-25 { + margin-bottom: 25px; } + +.mb-30 { + margin-bottom: 30px; } + +.mb-35 { + margin-bottom: 35px; } + +.mb-40 { + margin-bottom: 40px; } + +.mb-45 { + margin-bottom: 45px; } + +.mb-50 { + margin-bottom: 50px; } + +.mb-55 { + margin-bottom: 55px; } + +.mb-60 { + margin-bottom: 60px; } + +.mb-65 { + margin-bottom: 65px; } + +.mb-70 { + margin-bottom: 70px; } + +.mb-75 { + margin-bottom: 75px; } + +.mb-80 { + margin-bottom: 80px; } + +.mb-85 { + margin-bottom: 85px; } + +.mb-90 { + margin-bottom: 90px; } + +.mb-95 { + margin-bottom: 95px; } + +.mb-100 { + margin-bottom: 100px; } + +.mb-105 { + margin-bottom: 105px; } + +.mb-110 { + margin-bottom: 110px; } + +.mb-115 { + margin-bottom: 115px; } + +.mb-118 { + margin-bottom: 118px; } + +.mb-120 { + margin-bottom: 120px; } + +.mb-122 { + margin-bottom: 122px; } + +.mb-125 { + margin-bottom: 125px; } + +.mb-130 { + margin-bottom: 130px; } + +.mb-140 { + margin-bottom: 140px; } + +.mb-150 { + margin-bottom: 150px; } + +/* ---------------------------------------------------- + Custom margin Padding +---------------------------------------------------- */ +.mr-30 { + margin-right: 30px; } + +.ml-30 { + margin-left: 30px; } + +.pl-70 { + padding-left: 70px; } + +.pr-70 { + padding-right: 70px; } + +/* Padding left right */ +.plr--2 { + padding-left: 2%; + padding-right: 2%; } + +.plr--3 { + padding-left: 3%; + padding-right: 3%; } + +.plr--4 { + padding-left: 4%; + padding-right: 4%; } + +.plr--5 { + padding-left: 5%; + padding-right: 5%; } + +.plr--6 { + padding-left: 6%; + padding-right: 6%; } + +.plr--7 { + padding-left: 7%; + padding-right: 7%; } + +.plr--8 { + padding-left: 8%; + padding-right: 8%; } + +.plr--9 { + /* used */ + padding-left: 9%; + padding-right: 9%; } + +.plr--10 { + padding-left: 10%; + padding-right: 10%; } + +.plr--11 { + padding-left: 11%; + padding-right: 11%; } + +.plr--12 { + padding-left: 12%; + padding-right: 12%; } + +@media (max-width: 1599px) { + .plr--2, + .plr--3, + .plr--4, + .plr--5, + .plr--6, + .plr--7, + .plr--8, + .plr--9, + .plr--10, + .plr--11, + .plr--12 { + padding-left: 2%; + padding-right: 2%; } } + +@media (max-width: 1399px) { + .plr--2, + .plr--3, + .plr--4, + .plr--5, + .plr--6, + .plr--7, + .plr--8, + .plr--9, + .plr--10, + .plr--11, + .plr--12 { + padding-left: 15px; + padding-right: 15px; } } + +@media (min-width: 1200px) { + /* Margin Top Minus */ + .mt--30 { + margin-top: -30px !important; } + .mt--65 { + margin-top: -65px; } + .mt--80 { + margin-top: -80px; } + .mt--90 { + margin-top: -90px; } + .mt--100 { + margin-top: -100px; } + .mt--110 { + margin-top: -110px; } + .mt--120 { + margin-top: -120px; } + .mt--150 { + margin-top: -150px; } } + +/* Margin Bottom Minus */ +.mb--30 { + margin-bottom: -30px; } + +.mb--80 { + margin-bottom: -100px; } + +.mb--90 { + margin-bottom: -100px; } + +.mb--100 { + margin-bottom: -100px; } + +.mb--110 { + margin-bottom: -100px; } + +.mb--120 { + margin-bottom: -100px; } + +.mb--150 { + margin-bottom: -100px; } + +/* -------------------------------------------------------------- +# Gutenberg Default Style +-------------------------------------------------------------- */ +.single-post-details-item .entry-content > .alignwide { + max-width: 1100px; } + +.single-post-details-item .entry-content > .alignfull { + margin: 1.5em 0; + max-width: 100%; } + +.wp-block-video video { + max-width: 636px; } + +.wp-block-image img { + display: block; } + +.wp-block-image.alignleft, +.wp-block-image.alignright { + width: 100%; } + +.wp-block-image.alignfull img { + width: 100vw; } + +.wp-block-gallery:not(.components-placeholder) { + margin: 1.5em auto; } + +.wp-block-cover-text p { + padding: 1.5em 14px; } + +ul.wp-block-latest-posts.alignwide, +ul.wp-block-latest-posts.alignfull, +ul.wp-block-latest-posts.is-grid.alignwide, +ul.wp-block-latest-posts.is-grid.alignwide { + padding: 0 14px; } + +.wp-block-table { + display: block; + overflow-x: auto; } + +.wp-block-table table { + border-collapse: collapse; + width: 100%; } + +.wp-block-table td, .wp-block-table th { + padding: .5em; } + +.wp-block-embed.type-video > .wp-block-embed__wrapper { + position: relative; + width: 100%; + height: 0; + padding-top: 56.25%; } + +.wp-block-embed.type-video > .wp-block-embed__wrapper > iframe { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + bottom: 0; + right: 0; } + +.wp-block-quote.is-large { + margin: 0 auto 16px; } + +.wp-block-pullquote > p:first-child { + margin-top: 0; } + +.wp-block-separator { + margin: 3em auto; + padding: 0; } + +@media screen and (min-width: 768px) { + .wp-block-cover-text p { + padding: 1.5em 0; } } + +.wp-block-video video { + max-width: 636px; } + +.wp-block-image img { + display: block; } + +.wp-block-image.alignleft, +.wp-block-image.alignright { + width: 100%; } + +.wp-block-image.alignfull img { + width: 100vw; } + +.wp-block-gallery:not(.components-placeholder) { + margin: 1.5em auto; } + +.wp-block-cover-text p { + padding: 1.5em 14px; } + +ul.wp-block-latest-posts.alignwide, +ul.wp-block-latest-posts.alignfull, +ul.wp-block-latest-posts.is-grid.alignwide, +ul.wp-block-latest-posts.is-grid.alignwide { + padding: 0 14px; } + +.wp-block-table { + display: block; + overflow-x: auto; } + +.wp-block-table table { + border-collapse: collapse; + width: 100%; } + +.wp-block-table td, .wp-block-table th { + padding: .5em; } + +.wp-block-embed.type-video > .wp-block-embed__wrapper { + position: relative; + width: 100%; + height: 0; + padding-top: 56.25%; } + +.wp-block-embed.type-video > .wp-block-embed__wrapper > iframe { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + bottom: 0; + right: 0; } + +.wp-block-quote.is-large { + margin: 0 auto 16px; } + +.wp-block-pullquote > p:first-child { + margin-top: 0; } + +.wp-block-quote:not(.is-large):not(.is-style-large) { + border-left: 4px solid #000; + padding-left: 1em; } + +.wp-block-separator { + margin: 3em auto; + padding: 0; } + +@media screen and (min-width: 768px) { + .wp-block-cover-text p { + padding: 1.5em 0; } } + +.wp-block-pullquote { + border-top: 4px solid #555d66; + border-bottom: 4px solid #555d66; + color: #40464d; } + +/* -------------------------------------------------------------- +## Block Color Palette Colors +-------------------------------------------------------------- */ +.has-strong-blue-color { + color: #0073aa; } + +.has-strong-blue-background-color { + background-color: #0073aa; } + +.has-lighter-blue-color { + color: #229fd8; } + +.has-lighter-blue-background-color { + background-color: #229fd8; } + +.has-very-light-gray-color { + color: #eee; } + +.has-very-light-gray-background-color { + background-color: #eee; } + +.has-very-dark-gray-color { + color: #444; } + +.has-very-dark-gray-background-color { + background-color: #444; } + +/* ---------------------------------------------------- + Animation Custom Class +---------------------------------------------------- */ +.ltn__effect-img { + position: absolute; } + +.ltn__effect-img-top-left { + top: 6%; + left: 5%; } + +.ltn__effect-img-top-right { + top: 5%; + right: 5%; } + +.ltn__effect-img-center-left { + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + left: 3%; } + +.ltn__effect-img-center-center { + top: 50%; + -webkit-transform: translateY(-50%) translateX(-50%); + -ms-transform: translateY(-50%) translateX(-50%); + transform: translateY(-50%) translateX(-50%); + left: 50%; } + +.ltn__effect-img-center-right { + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + right: 3%; } + +.ltn__effect-img-bottom-left { + bottom: 5%; + left: 0; } + +.ltn__effect-img-bottom-right { + bottom: 5%; + right: 5%; } + +/* ---------------------------------------------------- + Animation CSS +---------------------------------------------------- */ +.ltn__parallax-effect-wrap, +.layer { + display: block; + height: 100%; + width: 100%; + padding: 0; + margin: 0; } + +.ltn__parallax-effect-wrap { + min-height: 600px; + position: relative; + overflow: hidden; } + +.layer { + position: absolute; } + +.layer div { + -webkit-transform: translate3d(0, 0, 0); + -moz-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + -webkit-transform-style: preserve-3d; + -moz-transform-style: preserve-3d; + transform-style: preserve-3d; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; } + +.background { + background: url("https://tunatheme.com/tf/html/fiama-preview/fiama/img/effect/1.png") no-repeat 50% 100%; + bottom: 96px; + background-size: cover; + position: absolute; + width: 110%; + left: -5%; + top: -5%; } + +.lighthouse { + -webkit-transform-origin: 50% 90%; + -moz-transform-origin: 50% 90%; + -ms-transform-origin: 50% 90%; + transform-origin: 50% 90%; + -webkit-animation: lighthouse 4s 0.1s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); + -moz-animation: lighthouse 4s 0.1s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); + animation: lighthouse 4s 0.1s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); + margin: 0px -64px; + background-size: 128px 224px; + height: 224px; + width: 128px; + background-image: url("https://tunatheme.com/tf/html/fiama-preview/fiama/img/effect/2.png"); + background-repeat: no-repeat; + bottom: 64px; + position: absolute; + right: 20%; } + +.wave.plain { + background-image: url("https://tunatheme.com/tf/html/fiama-preview/fiama/img/effect/3.png"); } + +.wave.paint { + background-image: url("https://tunatheme.com/tf/html/fiama-preview/fiama/img/effect/4.png"); } + +.light { + margin: -120px -120px; + background-size: 240px 240px; + height: 240px; + width: 240px; + background-repeat: no-repeat; + bottom: 112px; + position: absolute; + left: 50%; } + +.light.orange { + background-image: url("https://tunatheme.com/tf/html/fiama-preview/fiama/img/effect/5.png"); } + +.light.purple { + background-image: url("https://tunatheme.com/tf/html/fiama-preview/fiama/img/effect/6.png"); } + +.light.a { + bottom: 80px; + left: 20%; } + +.light.b { + bottom: 80px; + left: 30%; } + +.light.c { + bottom: 112px; + left: 45%; } + +.light.d { + bottom: 96px; + left: 60%; } + +.light.e { + bottom: 112px; + left: 75%; } + +.light.f { + bottom: 64px; + left: 80%; } + +.light.phase-1 { + -webkit-animation: phase 20s 0.1s infinite linear; + -moz-animation: phase 20s 0.1s infinite linear; + animation: phase 20s 0.1s infinite linear; } + +.light.phase-2 { + -webkit-animation: phase 18s 0.1s infinite linear; + -moz-animation: phase 18s 0.1s infinite linear; + animation: phase 18s 0.1s infinite linear; } + +.light.phase-3 { + -webkit-animation: phase 16s 0.1s infinite linear; + -moz-animation: phase 16s 0.1s infinite linear; + animation: phase 16s 0.1s infinite linear; } + +.light.phase-4 { + -webkit-animation: phase 14s 0.1s infinite linear; + -moz-animation: phase 14s 0.1s infinite linear; + animation: phase 14s 0.1s infinite linear; } + +.light.phase-5 { + -webkit-animation: phase 12s 0.1s infinite linear; + -moz-animation: phase 12s 0.1s infinite linear; + animation: phase 12s 0.1s infinite linear; } + +.light.phase-6 { + -webkit-animation: phase 10s 0.1s infinite linear; + -moz-animation: phase 10s 0.1s infinite linear; + animation: phase 10s 0.1s infinite linear; } + +.hanger { + -webkit-transform-origin: 0% 0%; + -moz-transform-origin: 0% 0%; + -ms-transform-origin: 0% 0%; + transform-origin: 0% 0%; + position: absolute; } + +.hanger.position-1 { + top: 28%; } + +.hanger.position-2 { + top: 46%; } + +.hanger.position-3 { + top: 59%; } + +.hanger.position-4 { + top: 66.5%; } + +.hanger.position-5 { + top: 69.5%; } + +.hanger.position-6 { + top: 66.5%; } + +.hanger.position-7 { + top: 59%; } + +.hanger.position-8 { + top: 46%; } + +.hanger.position-9 { + top: 28%; } + +.hanger.position-1 { + left: 10%; } + +.hanger.position-2 { + left: 20%; } + +.hanger.position-3 { + left: 30%; } + +.hanger.position-4 { + left: 40%; } + +.hanger.position-5 { + left: 50%; } + +.hanger.position-6 { + left: 60%; } + +.hanger.position-7 { + left: 70%; } + +.hanger.position-8 { + left: 80%; } + +.hanger.position-9 { + left: 90%; } + +.board { + -webkit-transform-origin: 50% 0%; + -moz-transform-origin: 50% 0%; + -ms-transform-origin: 50% 0%; + transform-origin: 50% 0%; + margin: 0px -140px; + background-size: 280px 280px; + height: 280px; + width: 280px; + background-repeat: no-repeat; + position: absolute; + top: -4px; + left: 0; } + +.board.birds { + background-image: url("https://tunatheme.com/tf/html/fiama-preview/fiama/img/effect/5.png"); } + +.board.cloud-1 { + background-image: url("https://tunatheme.com/tf/html/fiama-preview/fiama/img/effect/1.png"); } + +.board.cloud-2 { + background-image: url("https://tunatheme.com/tf/html/fiama-preview/fiama/img/effect/2.png"); } + +.board.cloud-3 { + background-image: url("https://tunatheme.com/tf/html/fiama-preview/fiama/img/effect/3.png"); } + +.board.cloud-4 { + background-image: url("https://tunatheme.com/tf/html/fiama-preview/fiama/img/effect/4.png"); } + +.swing-1 { + -webkit-animation: swing 4s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); + -moz-animation: swing 4s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); + animation: swing 4s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); } + +.swing-2 { + -webkit-animation: swing 3.5s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); + -moz-animation: swing 3.5s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); + animation: swing 3.5s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); } + +.swing-3 { + -webkit-animation: swing 3s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); + -moz-animation: swing 3s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); + animation: swing 3s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); } + +.swing-4 { + -webkit-animation: swing 2.5s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); + -moz-animation: swing 2.5s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); + animation: swing 2.5s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); } + +.swing-5 { + -webkit-animation: swing 2s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); + -moz-animation: swing 2s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); + animation: swing 2s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955); } + +/* --------------- */ +.wave { + background: transparent repeat-x; + position: absolute; + width: 100%; + left: 0; + margin: 0px 0px; + background-position: center bottom; + background-size: auto 101%; + height: 30%; + -webkit-animation: wave 5.33333s 0.1s infinite linear; + -moz-animation: wave 5.33333s 0.1s infinite linear; + animation: wave 5.33333s 0.1s infinite linear; } + +.ltn__animation-wave-3s { + -webkit-animation: wave 3s 0.1s infinite linear; + -moz-animation: wave 3s 0.1s infinite linear; + animation: wave 3s 0.1s infinite linear; } + +.ltn__animation-wave-4s { + -webkit-animation: wave 4s 0.1s infinite linear; + -moz-animation: wave 4s 0.1s infinite linear; + animation: wave 4s 0.1s infinite linear; } + +.ltn__animation-wave-5s { + -webkit-animation: wave 5.33333s 0.1s infinite linear; + -moz-animation: wave 5.33333s 0.1s infinite linear; + animation: wave 5.33333s 0.1s infinite linear; } + +.ltn__animation-wave-6s { + -webkit-animation: wave 6.22222s 0.1s infinite linear; + -moz-animation: wave 6.22222s 0.1s infinite linear; + animation: wave 6.22222s 0.1s infinite linear; } + +.ltn__animation-wave-7s { + -webkit-animation: wave 7.11111s 0.1s infinite linear; + -moz-animation: wave 7.11111s 0.1s infinite linear; + animation: wave 7.11111s 0.1s infinite linear; } + +.ltn__animation-wave-8s { + -webkit-animation: wave 8s 0.1s infinite linear; + -moz-animation: wave 8s 0.1s infinite linear; + animation: wave 8s 0.1s infinite linear; } + +.cross, .x, .y { + -webkit-transition: all 0.3s cubic-bezier(0.165, 0.84, 0.44, 1); + -moz-transition: all 0.3s cubic-bezier(0.165, 0.84, 0.44, 1); + -o-transition: all 0.3s cubic-bezier(0.165, 0.84, 0.44, 1); + transition: all 0.3s cubic-bezier(0.165, 0.84, 0.44, 1); } + +@-webkit-keyframes phase { + 0% { + opacity: 1; } + 25% { + opacity: 0.4; } + 50% { + opacity: 0.8; } + 75% { + opacity: 0.4; } + 100% { + opacity: 1; } } + +@-moz-keyframes phase { + 0% { + opacity: 1; } + 25% { + opacity: 0.4; } + 50% { + opacity: 0.8; } + 75% { + opacity: 0.4; } + 100% { + opacity: 1; } } + +@-ms-keyframes phase { + 0% { + opacity: 1; } + 25% { + opacity: 0.4; } + 50% { + opacity: 0.8; } + 75% { + opacity: 0.4; } + 100% { + opacity: 1; } } + +@keyframes phase { + 0% { + opacity: 1; } + 25% { + opacity: 0.4; } + 50% { + opacity: 0.8; } + 75% { + opacity: 0.4; } + 100% { + opacity: 1; } } + +@-webkit-keyframes tilt { + 0% { + -webkit-transform: rotateX(-30deg); + -moz-transform: rotateX(-30deg); + transform: rotateX(-30deg); } + 25% { + -webkit-transform: rotateX(30deg); + -moz-transform: rotateX(30deg); + transform: rotateX(30deg); } + 50% { + -webkit-transform: rotateY(-30deg); + -moz-transform: rotateY(-30deg); + transform: rotateY(-30deg); } + 75% { + -webkit-transform: rotateY(30deg); + -moz-transform: rotateY(30deg); + transform: rotateY(30deg); } + 100% { + -webkit-transform: rotateZ(20deg); + -moz-transform: rotateZ(20deg); + transform: rotateZ(20deg); } } + +@-moz-keyframes tilt { + 0% { + -webkit-transform: rotateX(-30deg); + -moz-transform: rotateX(-30deg); + transform: rotateX(-30deg); } + 25% { + -webkit-transform: rotateX(30deg); + -moz-transform: rotateX(30deg); + transform: rotateX(30deg); } + 50% { + -webkit-transform: rotateY(-30deg); + -moz-transform: rotateY(-30deg); + transform: rotateY(-30deg); } + 75% { + -webkit-transform: rotateY(30deg); + -moz-transform: rotateY(30deg); + transform: rotateY(30deg); } + 100% { + -webkit-transform: rotateZ(20deg); + -moz-transform: rotateZ(20deg); + transform: rotateZ(20deg); } } + +@-ms-keyframes tilt { + 0% { + -webkit-transform: rotateX(-30deg); + -moz-transform: rotateX(-30deg); + transform: rotateX(-30deg); } + 25% { + -webkit-transform: rotateX(30deg); + -moz-transform: rotateX(30deg); + transform: rotateX(30deg); } + 50% { + -webkit-transform: rotateY(-30deg); + -moz-transform: rotateY(-30deg); + transform: rotateY(-30deg); } + 75% { + -webkit-transform: rotateY(30deg); + -moz-transform: rotateY(30deg); + transform: rotateY(30deg); } + 100% { + -webkit-transform: rotateZ(20deg); + -moz-transform: rotateZ(20deg); + -ms-transform: rotate(20deg); + transform: rotateZ(20deg); } } + +@keyframes tilt { + 0% { + -webkit-transform: rotateX(-30deg); + -moz-transform: rotateX(-30deg); + transform: rotateX(-30deg); } + 25% { + -webkit-transform: rotateX(30deg); + -moz-transform: rotateX(30deg); + transform: rotateX(30deg); } + 50% { + -webkit-transform: rotateY(-30deg); + -moz-transform: rotateY(-30deg); + transform: rotateY(-30deg); } + 75% { + -webkit-transform: rotateY(30deg); + -moz-transform: rotateY(30deg); + transform: rotateY(30deg); } + 100% { + -webkit-transform: rotateZ(20deg); + -moz-transform: rotateZ(20deg); + transform: rotateZ(20deg); } } + +@-webkit-keyframes wave { + 0% { + -webkit-transform: rotateZ(0deg) translate3d(0, 10%, 0) rotateZ(0deg); + -moz-transform: rotateZ(0deg) translate3d(0, 10%, 0) rotateZ(0deg); + transform: rotateZ(0deg) translate3d(0, 10%, 0) rotateZ(0deg); } + 100% { + -webkit-transform: rotateZ(360deg) translate3d(0, 10%, 0) rotateZ(-360deg); + -moz-transform: rotateZ(360deg) translate3d(0, 10%, 0) rotateZ(-360deg); + transform: rotateZ(360deg) translate3d(0, 10%, 0) rotateZ(-360deg); } } + +@-moz-keyframes wave { + 0% { + -webkit-transform: rotateZ(0deg) translate3d(0, 10%, 0) rotateZ(0deg); + -moz-transform: rotateZ(0deg) translate3d(0, 10%, 0) rotateZ(0deg); + transform: rotateZ(0deg) translate3d(0, 10%, 0) rotateZ(0deg); } + 100% { + -webkit-transform: rotateZ(360deg) translate3d(0, 10%, 0) rotateZ(-360deg); + -moz-transform: rotateZ(360deg) translate3d(0, 10%, 0) rotateZ(-360deg); + transform: rotateZ(360deg) translate3d(0, 10%, 0) rotateZ(-360deg); } } + +@-ms-keyframes wave { + 0% { + -webkit-transform: rotateZ(0deg) translate3d(0, 10%, 0) rotateZ(0deg); + -moz-transform: rotateZ(0deg) translate3d(0, 10%, 0) rotateZ(0deg); + transform: rotateZ(0deg) translate3d(0, 10%, 0) rotateZ(0deg); } + 100% { + -webkit-transform: rotateZ(360deg) translate3d(0, 10%, 0) rotateZ(-360deg); + -moz-transform: rotateZ(360deg) translate3d(0, 10%, 0) rotateZ(-360deg); + transform: rotateZ(360deg) translate3d(0, 10%, 0) rotateZ(-360deg); } } + +@keyframes wave { + 0% { + -webkit-transform: rotateZ(0deg) translate3d(0, 10%, 0) rotateZ(0deg); + -moz-transform: rotateZ(0deg) translate3d(0, 10%, 0) rotateZ(0deg); + transform: rotateZ(0deg) translate3d(0, 10%, 0) rotateZ(0deg); } + 100% { + -webkit-transform: rotateZ(360deg) translate3d(0, 10%, 0) rotateZ(-360deg); + -moz-transform: rotateZ(360deg) translate3d(0, 10%, 0) rotateZ(-360deg); + transform: rotateZ(360deg) translate3d(0, 10%, 0) rotateZ(-360deg); } } + +@-webkit-keyframes lighthouse { + 0% { + -webkit-transform: translate3d(15%, 0, 0) rotateZ(10deg); + -moz-transform: translate3d(15%, 0, 0) rotateZ(10deg); + transform: translate3d(15%, 0, 0) rotateZ(10deg); } + 100% { + -webkit-transform: translate3d(-15%, 0, 0) rotateZ(-10deg); + -moz-transform: translate3d(-15%, 0, 0) rotateZ(-10deg); + transform: translate3d(-15%, 0, 0) rotateZ(-10deg); } } + +@-moz-keyframes lighthouse { + 0% { + -webkit-transform: translate3d(15%, 0, 0) rotateZ(10deg); + -moz-transform: translate3d(15%, 0, 0) rotateZ(10deg); + transform: translate3d(15%, 0, 0) rotateZ(10deg); } + 100% { + -webkit-transform: translate3d(-15%, 0, 0) rotateZ(-10deg); + -moz-transform: translate3d(-15%, 0, 0) rotateZ(-10deg); + transform: translate3d(-15%, 0, 0) rotateZ(-10deg); } } + +@-ms-keyframes lighthouse { + 0% { + -webkit-transform: translate3d(15%, 0, 0) rotateZ(10deg); + -moz-transform: translate3d(15%, 0, 0) rotateZ(10deg); + transform: translate3d(15%, 0, 0) rotateZ(10deg); } + 100% { + -webkit-transform: translate3d(-15%, 0, 0) rotateZ(-10deg); + -moz-transform: translate3d(-15%, 0, 0) rotateZ(-10deg); + transform: translate3d(-15%, 0, 0) rotateZ(-10deg); } } + +@keyframes lighthouse { + 0% { + -webkit-transform: translate3d(15%, 0, 0) rotateZ(10deg); + -moz-transform: translate3d(15%, 0, 0) rotateZ(10deg); + transform: translate3d(15%, 0, 0) rotateZ(10deg); } + 100% { + -webkit-transform: translate3d(-15%, 0, 0) rotateZ(-10deg); + -moz-transform: translate3d(-15%, 0, 0) rotateZ(-10deg); + transform: translate3d(-15%, 0, 0) rotateZ(-10deg); } } + +@-webkit-keyframes swing { + 0% { + -webkit-transform: rotateZ(10deg); + -moz-transform: rotateZ(10deg); + transform: rotateZ(10deg); } + 100% { + -webkit-transform: rotateZ(-10deg); + -moz-transform: rotateZ(-10deg); + transform: rotateZ(-10deg); } } + +@-moz-keyframes swing { + 0% { + -webkit-transform: rotateZ(10deg); + -moz-transform: rotateZ(10deg); + transform: rotateZ(10deg); } + 100% { + -webkit-transform: rotateZ(-10deg); + -moz-transform: rotateZ(-10deg); + transform: rotateZ(-10deg); } } + +@-ms-keyframes swing { + 0% { + -webkit-transform: rotateZ(10deg); + -moz-transform: rotateZ(10deg); + -ms-transform: rotate(10deg); + transform: rotateZ(10deg); } + 100% { + -webkit-transform: rotateZ(-10deg); + -moz-transform: rotateZ(-10deg); + -ms-transform: rotate(-10deg); + transform: rotateZ(-10deg); } } + +@keyframes swing { + 0% { + -webkit-transform: rotateZ(10deg); + -moz-transform: rotateZ(10deg); + transform: rotateZ(10deg); } + 100% { + -webkit-transform: rotateZ(-10deg); + -moz-transform: rotateZ(-10deg); + transform: rotateZ(-10deg); } } + +/* ---------------------------------------------------- + End Animation +---------------------------------------------------- */ +/* ---------------------------------------------------- + Breadcurmb Area +---------------------------------------------------- */ +.ltn__breadcrumb-area { + background-color: var(--white-13); + margin-bottom: 100px; + padding-top: 45px; + padding-bottom: 40px; } + +.ltn__breadcrumb-list ul { + margin: 0; + padding: 0; } + +.ltn__breadcrumb-list ul li { + display: inline-block; + margin-right: 30px; + position: relative; + font-weight: 500; + font-size: 14px; + margin-top: 5px; + color: var(--ltn__paragraph-color); } + +.ltn__breadcrumb-list ul li:last-child { + margin-right: 0; + color: var(--ltn__paragraph-color); } + +.ltn__breadcrumb-list ul li:after { + position: absolute; + content: "\f054"; + font-family: 'Font Awesome\ 5 Free'; + font-weight: 900; + font-size: 10px; + right: -20px; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + +.ltn__breadcrumb-list ul li:last-child:after { + display: none; } + +.ltn__page-title { + font-size: 30px; + font-weight: 800; + margin-bottom: 0; } + +/* breadcrumb-area-2 */ +.ltn__breadcrumb-area-2 { + padding-top: 250px; + padding-bottom: 130px; } + +.ltn__breadcrumb-inner-2 { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + .ltn__breadcrumb-inner-2 .section-title-area { + margin-bottom: 0; } + .ltn__breadcrumb-inner-2 .ltn__section-title-2 .section-title { + margin-bottom: 0; } + .ltn__breadcrumb-inner-2 .ltn__breadcrumb-list { + margin-left: 100px; } + .ltn__breadcrumb-inner-2 .ltn__breadcrumb-list ul li:after { + position: absolute; + content: ""; + right: -20px; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + height: 10px; + width: 2px; + background-color: var(--ltn__color-1); + opacity: 0.5; } + +.ltn__breadcrumb-color-white .ltn__breadcrumb-list li { + color: var(--ltn__color-1); } + .ltn__breadcrumb-color-white .ltn__breadcrumb-list li:last-child { + color: var(--ltn__secondary-color); } + +/* breadcrumb-area-3 */ +.ltn__breadcrumb-area-3 { + padding-top: 350px; + padding-bottom: 130px; } + +/* breadcrumb-area-4 */ +.ltn__breadcrumb-inner-4 .section-title-area { + margin-bottom: 0; } + +.ltn__breadcrumb-inner-4 .ltn__breadcrumb-list ul li:last-child { + opacity: 0.5; } + +/* ---------------------------------------------------- + Responsive +---------------------------------------------------- */ +@media (max-width: 767px) { + .ltn__breadcrumb-area-2 { + padding-top: 240px; + padding-bottom: 80px; } + .ltn__breadcrumb-inner-2 { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-flow: column; + flex-flow: column; + text-align: center; } + .ltn__breadcrumb-inner-2 .ltn__breadcrumb-list { + margin-left: 0; } + .ltn__breadcrumb-list ul li { + font-size: 14px; } } + +/* ---------------------------------------------------- + END +---------------------------------------------------- */ +/* ============================================================ +>>> TABLE OF CONTENTS: +=============================================================== +# Widgets +# Search Widget +# Newsletter Widget +# Tag Cloud Widget +# Color Widget +# Menu Widget +# Popular Post Widget +# Banner Widget +# Top Rated Product Widget +# Price Filter Widget +# Instagram Widget +# Video Widget +# Author Widget +# Widget Responsive + +============================================================= */ +/* -------------------------------------------------------------- + Widgets +-------------------------------------------------------------- */ +.widget { + margin-bottom: 40px; } + .widget:last-child { + margin-bottom: 0; } + +.ltn__widget-title { + font-size: 18px; + margin-bottom: 25px; + border-bottom: 1px solid var(--white-16); + text-transform: capitalize; + padding-bottom: 5px; + font-weight: 500; } + +.ltn__widget-title-border { + position: relative; + padding-left: 45px; } + .ltn__widget-title-border::after, .ltn__widget-title-border::before { + position: absolute; + content: ""; + background-color: var(--ltn__secondary-color); + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + left: 0; } + .ltn__widget-title-border::before { + width: 18px; + height: 4px; + border-radius: 25px; } + .ltn__widget-title-border::after { + width: 4px; + height: 4px; + left: 22px; + border-radius: 100%; } + +/* widget-2 */ +.widget-2 { + margin-bottom: 40px; } + +.blog-sidebar .widget { + margin-bottom: 40px; + border: 2px solid var(--white-6); + background-color: var(--section-bg-6); + padding: 40px; } + .blog-sidebar .widget:last-child { + margin-bottom: 0; } + +/* ---------------------------------------------------- + Search Widget +---------------------------------------------------- */ +.ltn__search-widget form { + position: relative; } + +.ltn__search-widget input[type="text"] { + margin-bottom: 0; + padding-right: 65px; + padding-left: 20px; + height: 45px; + border: 1px solid; + background-color: var(--white); + border-color: var(--white-14); + font-weight: 600; + font-size: 14px; } + +.ltn__search-widget input[type="text"]::-webkit-input-placeholder { + color: var(--ltn__primary-color); + font-size: 12px; } + +.ltn__search-widget button { + position: absolute; + right: 0; + height: 100%; + padding: 0 20px; + color: var(--white-15); + border: 0px solid; + background-color: transparent; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + +.ltn__search-widget button:hover { + color: var(--ltn__secondary-color); } + +/* ---------------------------------------------------- + Newsletter Widget +---------------------------------------------------- */ +.ltn__newsletter-widget { + background-color: var(--ltn__primary-color); + padding: 50px 35px; + position: relative; + z-index: 2; } + .ltn__newsletter-widget h6 { + color: var(--ltn__secondary-color); + margin-bottom: 5px; } + .ltn__newsletter-widget h4 { + color: var(--white); + font-size: 40px; } + .ltn__newsletter-widget input[type="text"] { + background-color: #133236; + color: var(--white); + border-color: #133236; + height: 70px; + padding-left: 25px; + padding-right: 70px; } + .ltn__newsletter-widget input[type="text"]::-webkit-input-placeholder { + color: var(--white); } + .ltn__newsletter-widget input[type="text"]:-ms-input-placeholder { + color: var(--white); } + .ltn__newsletter-widget input[type="text"]::-ms-input-placeholder { + color: var(--white); } + .ltn__newsletter-widget input[type="text"]::placeholder { + color: var(--white); } + .ltn__newsletter-widget button { + background-color: var(--ltn__secondary-color); + border-color: var(--ltn__secondary-color); + color: var(--white); + padding: 0 25px; } + .ltn__newsletter-widget button:hover { + background-color: var(--ltn__secondary-color-2); + border-color: var(--ltn__secondary-color-2); + color: var(--white); } + +.ltn__newsletter-bg-icon { + position: absolute; + right: 20px; + top: 15%; + font-size: 120px; + color: var(--ltn__color-1); + opacity: 0.1; + z-index: -1; + line-height: 1; } + +/* ---------------------------------------------------- + Tag Cloud Widget +---------------------------------------------------- */ +.ltn__tagcloud-widget ul { + margin: 0; + padding: 0; } + .ltn__tagcloud-widget ul li { + list-style: none; + display: inline-block; + margin-right: 20px; + position: relative; } + .ltn__tagcloud-widget ul li::before { + position: absolute; + content: ""; + right: -12px; + top: 50%; + width: 1px; + height: 18px; + background-color: var(--ltn__body-color); + -webkit-transform: translateY(-50%) rotate(20deg); + -ms-transform: translateY(-50%) rotate(20deg); + transform: translateY(-50%) rotate(20deg); } + .ltn__tagcloud-widget ul li:last-child::before { + display: none; } + .ltn__tagcloud-widget ul li a { + display: block; + font-size: 16px; + font-weight: 400; + font-family: var(--ltn__paragraph-font); } + .ltn__tagcloud-widget ul li a:hover { + color: var(--ltn__secondary-color); } + +.ltn__size-widget ul { + margin: 0; + padding: 0; } + .ltn__size-widget ul li { + list-style: none; + display: inline-block; + margin-right: 20px; + margin-top: 0; } + .ltn__size-widget ul li:last-child { + margin-right: 0; } + .ltn__size-widget ul li a { + padding: 0; + font-size: 16px; + text-transform: uppercase; + font-weight: 400; + font-family: var(--ltn__paragraph-font); } + .ltn__size-widget ul li a:hover { + color: var(--ltn__secondary-color); } + +/* ---------------------------------------------------- + Color Widget +---------------------------------------------------- */ +.ltn__color-widget ul { + padding: 0; + margin: 0; } + .ltn__color-widget ul li { + list-style: none; + display: inline-block; + margin-top: 3px; + margin-right: 5px; + background-color: var(--section-bg-1); + border: 1px solid var(--border-color-1); + height: 30px; + width: 30px; + border-radius: 100%; } + .ltn__color-widget ul li a { + display: block; } + .ltn__color-widget ul li:hover { + outline: 2px solid var(--ltn__secondary-color); + outline-offset: 1px; } + .ltn__color-widget ul .theme { + background-color: var(--ltn__secondary-color); } + .ltn__color-widget ul .black { + background-color: var(--black); } + .ltn__color-widget ul .white { + background-color: var(--white); } + .ltn__color-widget ul .red { + background-color: var(--red); } + .ltn__color-widget ul .silver { + background-color: var(--silver); } + .ltn__color-widget ul .gray { + background-color: var(--gray); } + .ltn__color-widget ul .maroon { + background-color: var(--maroon); } + .ltn__color-widget ul .yellow { + background-color: var(--yellow); } + .ltn__color-widget ul .olive { + background-color: var(--olive); } + .ltn__color-widget ul .lime { + background-color: var(--lime); } + .ltn__color-widget ul .green { + background-color: var(--green); } + .ltn__color-widget ul .green-2 { + background-color: var(--green-2); } + .ltn__color-widget ul .aqua { + background-color: var(--aqua); } + .ltn__color-widget ul .teal { + background-color: var(--teal); } + .ltn__color-widget ul .blue { + background-color: var(--blue); } + .ltn__color-widget ul .blue-2 { + background-color: var(--blue-2); } + .ltn__color-widget ul .navy { + background-color: var(--navy); } + .ltn__color-widget ul .fuchsia { + background-color: var(--fuchsia); } + .ltn__color-widget ul .purple { + background-color: var(--purple); } + .ltn__color-widget ul .pink { + background-color: var(--pink); } + .ltn__color-widget ul .nude { + background-color: var(--nude); } + .ltn__color-widget ul .orange { + background-color: var(--orange); } + +/* ---------------------------------------------------- + Menu Widget +---------------------------------------------------- */ +.ltn__menu-widget > ul { + padding: 0; + margin: 0; } + .ltn__menu-widget > ul li { + list-style: none; + margin-top: 10px; + font-family: var(--ltn__paragraph-font); } + .ltn__menu-widget > ul li a { + display: block; + font-size: 16px; + font-weight: 400; } + .ltn__menu-widget > ul li a span { + float: right; + color: var(--ltn__color-1); } + +/* menu-widget-2 */ +.ltn__menu-widget-2 { + background-color: transparent; } + .ltn__menu-widget-2 ul li a { + background-color: var(--section-bg-1); + padding: 20px 10px 20px 30px; } + .ltn__menu-widget-2 ul li a span { + background-color: var(--white); + color: var(--ltn__primary-color); + position: relative; + top: -11px; + width: 50px; + height: 50px; + line-height: 50px; + text-align: center; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__menu-widget-2 ul li.active a, .ltn__menu-widget-2 ul li:hover > a { + background-color: var(--ltn__secondary-color); + color: var(--white); } + .ltn__menu-widget-2 ul li.active a span, .ltn__menu-widget-2 ul li:hover > a span { + background-color: var(--ltn__secondary-color-2); + color: var(--white); } + .ltn__menu-widget-2 ul li.active a span:hover, .ltn__menu-widget-2 ul li:hover > a span:hover { + background-color: var(--ltn__primary-color); + color: var(--white); } + .ltn__menu-widget-2 > ul > li:first-child { + margin-top: 0; } + .ltn__menu-widget-2.ltn__menu-widget-2-color-2 ul li a { + background-color: var(--ltn__primary-color); + color: var(--white); } + .ltn__menu-widget-2.ltn__menu-widget-2-color-2 ul li a span { + background-color: var(--ltn__primary-color-2); + color: var(--white); } + .ltn__menu-widget-2.ltn__menu-widget-2-color-2 ul li.active a, .ltn__menu-widget-2.ltn__menu-widget-2-color-2 ul li:hover > a { + background-color: var(--ltn__secondary-color); + color: var(--white); } + .ltn__menu-widget-2.ltn__menu-widget-2-color-2 ul li.active a span, .ltn__menu-widget-2.ltn__menu-widget-2-color-2 ul li:hover > a span { + background-color: var(--ltn__secondary-color-2); + color: var(--white); } + .ltn__menu-widget-2.ltn__menu-widget-2-color-2 ul li.active a span:hover, .ltn__menu-widget-2.ltn__menu-widget-2-color-2 ul li:hover > a span:hover { + background-color: var(--ltn__primary-color); + color: var(--white); } + +/* ---------------------------------------------------- + Popular Post Widget +---------------------------------------------------- */ +.ltn__popular-post-widget ul { + padding: 0; + margin: 0; } + .ltn__popular-post-widget ul li { + list-style: none; } + +.ltn__popular-post-widget > ul > li { + margin-bottom: 30px; + border-bottom: 1px solid var(--border-color-1); + padding-bottom: 30px; } + +.ltn__popular-post-widget > ul > li:last-child { + margin-bottom: 0; + border-bottom: 0; + padding-bottom: 0px; } + +.popular-post-widget-img { + float: left; + margin-right: 20px; } + .popular-post-widget-img img { + max-width: 80px; } + +.popular-post-widget-brief { + overflow: hidden; } + .popular-post-widget-brief .ltn__blog-title { + margin-bottom: 5px; + font-size: 14px; } + .popular-post-widget-brief .blog-title-line { + padding-bottom: 15px; } + .popular-post-widget-brief .blog-title-line::before { + width: 30px; } + .popular-post-widget-brief .ltn__blog-meta { + margin-bottom: 0; } + .popular-post-widget-brief .ltn__blog-meta li { + color: var(--ltn__secondary-color); } + +.ltn__twitter-post-widget .popular-post-widget-img { + float: left; + margin-right: 20px; } + .ltn__twitter-post-widget .popular-post-widget-img img { + max-width: 60px; + border-radius: 100%; } + .ltn__twitter-post-widget .popular-post-widget-img a { + color: var(--ltn__secondary-color); } + +.ltn__twitter-post-widget .popular-post-widget-brief p { + margin-bottom: 5px; } + .ltn__twitter-post-widget .popular-post-widget-brief p a { + color: var(--ltn__secondary-color); } + +/* ---------------------------------------------------- + Banner Widget +---------------------------------------------------- */ +.ltn__banner-widget { + padding: 0 !important; + border: 0; } + +/* ---------------------------------------------------- + Top Rated Product Widget +---------------------------------------------------- */ +.ltn__top-rated-product-widget ul { + padding: 0; + margin: 0; } + .ltn__top-rated-product-widget ul li { + list-style: none; } + +.ltn__top-rated-product-widget > ul > li { + margin-bottom: 25px; + padding-bottom: 25px; + border-bottom: 1px solid; + border-color: var(--white-4); } + +.ltn__top-rated-product-widget > ul > li:last-child { + margin-bottom: 0; + padding-bottom: 0; + border-bottom: 0; } + +.top-rated-product-img { + max-width: 70px; + float: left; + margin-right: 18px; } + +.top-rated-product-info { + overflow: hidden; } + .top-rated-product-info h6 { + margin-bottom: 3px; + font-weight: 400; } + .top-rated-product-info .product-ratting { + margin-bottom: 0; } + .top-rated-product-info .product-ratting li { + font-size: 12px; } + .top-rated-product-info .product-price { + margin-bottom: 0; + font-size: 14px; + color: var(--ltn__secondary-color); + font-weight: 500; } + +/* ---------------------------------------------------- + Price Filter Widget +---------------------------------------------------- */ +.price_filter { + padding-bottom: 13px; } + +.price_slider_amount { + overflow: hidden; } + +.price_slider_amount > input[type="text"], +.price_slider_amount > input[type="submit"] { + background: transparent none repeat scroll 0 0; + border: medium none; + -webkit-box-shadow: none; + box-shadow: none; + float: left; + height: 25px; + padding: 0; + text-align: left; + width: 140px; + margin-bottom: 20px; + font-family: var(--ltn__paragraph-font); + font-weight: 400; } + +.price_slider_amount > input[type="text"] { + font-weight: 400; } + +.price_filter .ui-widget-content { + background-color: var(--ltn__primary-color); + border: medium none; + color: #222; + height: 3px; + width: 98%; + background-image: none; } + +.price_filter .ui-slider .ui-slider-range { + background-color: var(--ltn__secondary-color); + background-image: none; } + +.price_filter .ui-state-default, +.price_filter .ui-widget-content .ui-state-default, +.price_filter .ui-widget-header .ui-state-default { + background-color: var(--ltn__secondary-color); + border: medium none; + border-radius: 100%; + height: 12px; + margin-left: 0; + margin-top: -6px; + top: 50%; + width: 12px; + background-image: none; } + +/* ---------------------------------------------------- + Instagram Widget +---------------------------------------------------- */ +.ltn__instafeed-grid { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; } + .ltn__instafeed-grid .instagram_gallery { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + width: 100%; } + .ltn__instafeed-grid .instagram_gallery a, + .ltn__instafeed-grid .instagram_gallery .instagram-image { + display: block; + -webkit-box-flex: 1; + -webkit-flex: 1 0 16.6666%; + -ms-flex: 1 0 16.6666%; + flex: 1 0 16.6666%; + max-width: 16.6666%; } + +.ltn__instagram-widget .ltn__instafeed-grid .instagram_gallery a, +.ltn__instagram-widget .ltn__instafeed-grid .instagram_gallery .instagram-image { + -webkit-flex: 0 0 33.333333%; + -ms-flex: 0 0 33.333333%; + -webkit-box-flex: 0; + flex: 0 0 33.333333%; + max-width: 33.333333%; } + +.ltn__instagram-widget .ltn__instafeed-grid .instagram_gallery > a:nth-child(n+10) { + display: none; } + +.ltn__instafeed-slider .slick-list .slick-slide { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; } + +.insta-slide-gutter .slick-list { + margin-right: -7.5px !important; + margin-left: -7.5px !important; } + .insta-slide-gutter .slick-list .slick-slide { + padding-right: 7.5px; + padding-left: 7.5px; } + +.insta-grid-gutter .instagram_gallery { + margin-right: -7.5px !important; + margin-left: -7.5px !important; } + .insta-grid-gutter .instagram_gallery a, + .insta-grid-gutter .instagram_gallery .instagram-image { + padding-right: 7.5px; + padding-left: 7.5px; + margin: 7px 0; } + +/* ---------------------------------------------------- + Video Widget +---------------------------------------------------- */ +.ltn__video-icon-1 { + background-color: transparent; + color: var(--white); + height: 80px; + width: 80px; + border: 6px solid; + border-color: var(--white); + border-radius: 100%; + font-size: 22px; + z-index: 9; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } + .ltn__video-icon-1:hover { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +.ltn__video-icon-2 { + height: 80px; + width: 80px; + background-color: var(--white); + color: var(--ltn__secondary-color); + font-size: 20px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + z-index: 9; } + .ltn__video-icon-2 i { + color: var(--ltn__secondary-color); } + .ltn__video-icon-2:hover { + outline: outset; } + +.ltn__video-icon-2-border { + outline-offset: 15px; + outline: 4px solid var(--border-color-9); + margin: 20px; } + +.ltn__video-bg-img { + min-height: 350px; + position: relative; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-flow: column; + flex-flow: column; + z-index: 99; } + +.ltn__video-img { + position: relative; + display: inline-block; } + .ltn__video-img::before { + position: absolute; + content: ""; + left: 0; + top: 0; + width: 100%; + height: 100%; + opacity: 0.3; + background-color: var(--ltn__primary-color); } + .ltn__video-img img { + margin: 0; } + .ltn__video-img .ltn__video-icon-1, + .ltn__video-img .ltn__video-icon-2 { + position: absolute; + left: 0; + right: 0; + margin: auto; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + +.ltn__video-info { + position: relative; } + +.ltn__video-popup-height-300 { + height: 300px; } + +.ltn__video-popup-height-400 { + height: 400px; } + +.ltn__video-popup-height-500 { + height: 500px; } + +.ltn__video-popup-height-600 { + height: 600px; } + +.text-center .slide-video { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } + +.ltn__secondary-bg.ltn__video-icon-2 { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +.ltn__secondary-bg.ltn__video-icon-2 i { + color: var(--white); } + +.ltn__video-icon-2-small { + height: 60px; + width: 60px; + font-size: 16px; } + +@media (min-width: 992px) and (max-width: 1199px) { + .ltn__video-popup-height-500, + .ltn__video-popup-height-600 { + height: 450px; } + .blog-sidebar .widget { + margin-bottom: 40px; + padding: 30px 20px; } + .blog-sidebar .popular-post-widget-img img { + max-width: 70px; } } + +@media (max-width: 991px) { + .ltn__video-icon-2 { + height: 50px; + width: 50px; + font-size: 18px; } + .ltn__video-popup-height-500, + .ltn__video-popup-height-600 { + height: initial; } } + +@media (max-width: 767px) { + .ltn__video-bg-img { + min-height: 320px; } + .ltn__video-bg-img.ml-30 { + margin-left: 0; } + .ltn__video-img.ml-30, + .ltn__video-bg-img.ml-30 { + margin-left: 0; } } + +/* ---------------------------------------------------- + Author Widget +---------------------------------------------------- */ +.ltn__author-widget-inner img { + margin-bottom: 25px; } + +.ltn__author-widget-inner h5 { + color: var(--black-8); + margin-bottom: 5px; } + +.ltn__author-widget-inner h6 { + color: var(--black-9); + font-size: 14px; + font-family: var(--ltn__paragraph-font); + margin-bottom: 0px; } + +.ltn__author-widget-inner p { + font-size: 14px; + margin-top: 10px; } + +.ltn__author-widget-inner .ltn__social-media ul li { + color: var(--ltn__color-1); } + +.ltn__author-widget-2 .ltn__author-widget-inner img { + margin-bottom: 25px; + max-width: 100%; + border-radius: inherit; } + +/* ---------------------------------------------------- + Footer About Widget +---------------------------------------------------- */ +/* ---------------------------------------------------- + Widget Responsive +---------------------------------------------------- */ +@media (max-width: 1199px) { + .widget { + padding: 35px 20px 40px 20px; } + .top-rated-product-img { + max-width: 70px; + margin-right: 15px; } } + +@media (max-width: 991px) { + .ltn__right-sidebar { + margin-top: 100px; } } + +@media (max-width: 767px) { + .car-price-filter-range .price_filter .ui-state-default:last-child::after { + display: none; } } + +/* ---------------------------------------------------- + END +---------------------------------------------------- */ +/* ============================================================ +>>> TABLE OF CONTENTS: +=============================================================== +# Header +# Header Top Area +# Header Middle Area +# Header Bottom Area +# Header Feature Area +# Main Menu +# Header Options +# Mini Cart +# Header Searchbox +# Currency Menu +# Header Sticky +# Utilize Mobile Menu + +============================================================= */ +/* -------------------------------------------------------------- + Header +-------------------------------------------------------------- */ +.ltn__header-area { + z-index: 999; + position: relative; } + +/* ---------------------------------------------- + Header Top Area +---------------------------------------------- */ +.ltn__header-top-area { + border-bottom: 1px solid; + border-color: var(--border-color-1); } + .ltn__header-top-area .ltn__social-media ul li { + font-size: 14px; + margin: 0 10px 0 0; } + +.top-area-color-white { + background-color: var(--ltn__primary-color); } + .top-area-color-white p, + .top-area-color-white a, + .top-area-color-white li, + .top-area-color-white .welcome p, + .top-area-color-white .welcome a, + .top-area-color-white .ltn__drop-menu > ul > li > a, + .top-area-color-white .ltn__drop-menu > ul > li:hover > a { + color: var(--white); } + +.ltn__header-top-area .row { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + +/* welcome */ +.welcome p { + margin-bottom: 0; + font-size: 14px; + line-height: 40px; } + +.ltn__top-bar-menu > ul { + padding: 0; + margin: 0; } + .ltn__top-bar-menu > ul > li { + list-style: none; + display: inline-block; + margin: 0 30px 0 0; + font-size: 14px; + font-weight: 700; } + .ltn__top-bar-menu > ul > li:last-child { + margin-right: 0; } + .ltn__top-bar-menu > ul > li > i, .ltn__top-bar-menu > ul > li > a > i { + margin-right: 3px; + color: var(--ltn__secondary-color); } + +.ltn__top-bar-menu .ltn__currency-menu .active-currency { + font-size: 14px; + font-weight: 700; } + +/* ---------------------------------------------- + Header Middle Area +---------------------------------------------- */ +.ltn__header-middle-area { + z-index: 999; } + +.ltn__header-middle-area > .container-fluid > .row, +.ltn__header-middle-area > .container > .row { + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + position: relative; } + +.ltn__header-middle-area > .container-fluid > .row > .col, +.ltn__header-middle-area > .container > .row > .col { + -webkit-box-flex: 0; + -ms-flex-positive: 0; + flex-grow: 1; + position: static; } + +.site-logo { + min-width: 185px; + height: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + white-space: nowrap; } + .site-logo a { + color: var(--ltn__primary-color); + font-size: 30px; + font-weight: 600; + letter-spacing: 1px; + display: contents; } + .site-logo i { + color: var(--ltn__secondary-color); + margin-right: 5px; + font-size: 24px; + position: relative; + top: -2px; } + +.ltn__header-1 .ltn__header-middle-area { + padding-top: 10px; + padding-bottom: 10px; } + +/* ---------------------------------------------- + Header Bottom Area (header-2) +---------------------------------------------- */ +.header-bottom-area .row { + position: relative; } + .header-bottom-area .row .col { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + +.sticky-logo { + max-width: 200px; + -ms-flex-item-align: center; + -ms-grid-row-align: center; + align-self: center; + height: 100%; + float: left; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + display: none; } + +.header-menu-2 { + text-align: center; } + .header-menu-2 .ltn__main-menu > ul { + display: inline-block; } + +/* ---------------------------------------------- + Header Feature Area +---------------------------------------------- */ +.header-feature-area { + display: -webkit-box; + display: -ms-flexbox; + display: flex; } + +.header-feature-item { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + white-space: nowrap; + margin-right: 50px; + padding: 25px 0; + max-width: 50%; } + .header-feature-item:last-child { + margin-right: 0; } + .header-feature-item h6 { + margin-bottom: 0; + color: var(--ltn__body-color); + font-weight: 500; + text-transform: uppercase; + font-size: 13px; } + .header-feature-item p { + margin-bottom: 0; + font-size: 13px; + font-family: var(--ltn__heading-font); } + +.header-feature-icon { + margin-right: 20px; + font-size: 20px; + line-height: 1; + color: var(--ltn__heading-color); } + +/* ---------------------------------------------- + Main Menu +---------------------------------------------- */ +.header-menu-wrap, +.header-menu-column { + position: inherit; } + +.ltn__main-menu ul { + margin-bottom: 0; } + +.ltn__main-menu > ul { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + padding: 0; } + +.ltn__main-menu li { + list-style: none; + display: block; + margin-top: 0; } + +.ltn__main-menu li > a { + position: relative; } + +.ltn__main-menu > ul > li { + display: inline-block; + position: relative; + margin-right: 25px; } + +.ltn__main-menu > ul > li:last-child { + margin-right: 0px; } + +.ltn__main-menu > ul > li > a { + font-size: 14px; + padding: 22px 10px; + display: inline-block; + white-space: nowrap; + font-weight: 500; + font-family: var(--ltn__heading-font); + text-transform: uppercase; + color: var(--ltn__body-color); } + +.ltn__main-menu li:hover > a { + color: var(--ltn__secondary-color); } + +/* Submenu */ +.ltn__main-menu li > ul, +.ltn__main-menu .sub-menu { + position: absolute; + margin: 0; + top: 130%; + -webkit-transition: opacity .2s ease .1s,visibility .2s ease .1s,top .2s ease .1s; + -o-transition: opacity .2s ease .1s,visibility .2s ease .1s,top .2s ease .1s; + transition: opacity .2s ease .1s,visibility .2s ease .1s,top .2s ease .1s; + min-width: 230px; + padding: 15px 0; + -webkit-box-shadow: var(--ltn__box-shadow-4); + box-shadow: var(--ltn__box-shadow-4); + background-color: var(--white); + left: inherit; + right: inherit; + opacity: 0; + visibility: hidden; + text-align: left; + z-index: 999; + border-top: 2px solid var(--ltn__secondary-color); } + +.ltn__main-menu li ul li, +.ltn__main-menu .sub-menu li { + line-height: 1.3; + padding: 12px 25px 12px 30px; + font-size: 14px; } + +.mega-menu li ul { + border-top: 0; } + +.mega-menu li ul li { + padding-left: 10px; + padding-right: 0; } + +.ltn__main-menu li:hover > ul, +.ltn__main-menu li:hover > .sub-menu { + top: 100%; + opacity: 1; + visibility: visible; } + +.ltn__main-menu li ul li > ul, +.ltn__main-menu .sub-menu li > .sub-menu { + left: 100%; } + +.ltn__main-menu li ul li:hover > ul, +.ltn__main-menu .sub-menu li:hover > .sub-menu { + top: 0; } + +.ltn__main-menu li ul li, +.ltn__main-menu .sub-menu li { + position: relative; } + +.ltn__main-menu > ul > li:last-child ul li > ul, +.ltn__main-menu > ul > li:last-child .sub-menu li > .sub-menu, +.ltn__main-menu > ul > li:nth-last-child(2) ul li > ul, +.ltn__main-menu > ul > li:nth-last-child(2) .sub-menu li > .sub-menu, +.ltn__main-menu > ul > li:nth-last-child(3) ul li > ul, +.ltn__main-menu > ul > li:nth-last-child(3) .sub-menu li > .sub-menu { + left: auto; + right: 100%; } + +/* Menu Reverse */ +.ltn__main-menu > ul > li:last-child, +.ltn__main-menu > ul > li:nth-last-child(2) { + position: relative; } + +.ltn__main-menu > ul > li:last-child > ul, +.ltn__main-menu > ul > li:last-child > .sub-menu, +.ltn__main-menu > ul > li:nth-last-child(2) > ul, +.ltn__main-menu > ul > li:nth-last-child(2) > .sub-menu { + left: auto; + right: 0; } + +/* Mega Menu */ +.ltn__main-menu .mega-menu { + left: 0; + right: auto; + overflow: hidden; } + +.mega-menu > li { + float: left; + padding-bottom: 0 !important; + min-width: 250px !important; } + +.mega-menu > li { + min-width: 220px; } + +.ltn__main-menu li:hover ul.mega-menu { + opacity: 1; + visibility: visible; + -webkit-transform: scaley(1); + -ms-transform: scaley(1); + transform: scaley(1); } + +.mega-menu li ul, +.mega-menu li .sub-menu { + left: 0% !important; + -webkit-box-shadow: none; + box-shadow: none; + position: inherit; } + +/* .ltn__main-menu li:hover .mega-menu li ul */ +.ltn__main-menu li .mega-menu > li > ul, +.ltn__main-menu li .mega-menu .sub-menu { + top: 0; } + +.ltn__main-menu li:hover .mega-menu > li > ul, +.ltn__main-menu li:hover .mega-menu .sub-menu { + opacity: 1; + visibility: visible; } + +.mega-menu > li > a { + margin-left: 0; + border-bottom: 1px dashed #ddd; + display: block; + font-weight: 500; + padding: 10px; + background-color: var(--section-bg-1); } + +.mega-menu.column-1, +.mega-menu.column-2 { + left: auto; } + +.mega-menu.column-2 > li { + min-width: 50%; + width: 50%; } + +.mega-menu.column-3 > li { + min-width: 33.33%; + width: 33.33%; } + +@media (min-width: 991px) { + .mega-menu.column-4 > li, + .mega-menu.column-5 > li, + .mega-menu.column-6 > li, + .mega-menu.column-7 > li, + .mega-menu.column-8 > li, + .mega-menu.column-9 > li, + .mega-menu.column-10 > li, + .mega-menu.column-11 > li, + .mega-menu.column-12 > li { + min-width: 25%; + width: 25%; } } + +@media (max-width: 991px) { + .mega-menu.column-2 > li, + .mega-menu.column-3 > li, + .mega-menu.column-4 > li, + .mega-menu.column-5 > li, + .mega-menu.column-6 > li, + .mega-menu.column-7 > li, + .mega-menu.column-8 > li, + .mega-menu.column-9 > li, + .mega-menu.column-10 > li, + .mega-menu.column-11 > li, + .mega-menu.column-12 > li { + min-width: 50%; + width: 50%; } } + +@media (max-width: 767px) { + .mega-menu.column-2 > li, + .mega-menu.column-3 > li, + .mega-menu.column-4 > li, + .mega-menu.column-5 > li, + .mega-menu.column-6 > li, + .mega-menu.column-7 > li, + .mega-menu.column-8 > li, + .mega-menu.column-9 > li, + .mega-menu.column-10 > li, + .mega-menu.column-11 > li, + .mega-menu.column-12 > li { + min-width: 100%; + width: 100%; } } + +/* Mega menu submenu submenu */ +.mega-menu li ul li ul { + left: 100% !important; + position: absolute; + opacity: 0; + visibility: hidden; + -webkit-box-shadow: var(--ltn__box-shadow-4); + box-shadow: var(--ltn__box-shadow-4); } + +.mega-menu li ul li:hover > ul { + opacity: 1; + visibility: visible; } + +@media (min-width: 991px) { + .mega-menu-parent { + position: inherit !important; } } + +/* Menu Icon */ +.menu-icon > a { + position: relative; } + .menu-icon > a::before { + content: "\f067"; + font-size: 8px; + position: absolute; + top: 50%; + right: 0; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + font-family: 'Font Awesome\ 5 Free'; + font-weight: 900; + display: none; } + +/* Menu Item Badge */ +.menu-item-badge { + position: absolute; + left: -8px; + top: -10px; + font-size: 10px; + padding: 0 3px; + background-color: var(--ltn__secondary-color); + color: var(--white); + border-radius: 2px; + text-transform: uppercase; } + +/* Menu Porduct Item */ +.menu-product-item { + margin-bottom: 30px; + margin-top: 15px; + border: 2px solid; + border-color: var(--border-color-8); + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + text-align: center; } + .menu-product-item .product-info { + padding: 25px 15px 15px; + padding-top: 0; } + .menu-product-item .product-title { + font-size: 16px; + margin-bottom: 5px; } + .menu-product-item .product-price { + font-size: 16px; + color: var(--ltn__secondary-color); + font-weight: 600; } + .menu-product-item .product-price del { + font-size: 15px; + opacity: 0.5; + color: var(--gray); } + +.menu-product-item:hover { + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); } + +/* ---------------------------------------------- + Header Options +---------------------------------------------- */ +.ltn__header-options > ul { + padding: 0; + margin: 0; } + .ltn__header-options > ul > li { + display: inline-block; + margin-right: 15px; + margin-top: 0; } + .ltn__header-options > ul > li:last-child { + margin-right: 0; } + +.ltn__header-options { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; } + .ltn__header-options > div { + margin-right: 20px; } + .ltn__header-options > div:last-child { + margin-right: 0; } + .ltn__header-options i { + color: var(--ltn__heading-color); + font-size: 20px; } + .ltn__header-options .ltn__drop-menu > ul > li > a { + padding: 0; } + .ltn__header-options .ltn__drop-menu ul { + padding: 0; } + .ltn__header-options .ltn__drop-menu ul li ul { + padding: 10px 0; } + +.ltn__header-options-2 > div { + margin-right: 10px; } + +.ltn__header-options-2 .header-search-1, +.ltn__header-options-2 .ltn__drop-menu > ul > li > a, +.ltn__header-options-2 .mini-cart-icon a, +.ltn__header-options-2 .header-wishlist { + height: 50px; + width: 50px; + line-height: 50px; + background: var(--white); + color: var(--ltn__heading-color); + text-align: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + padding: 0; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); } + .ltn__header-options-2 .header-search-1:hover, + .ltn__header-options-2 .ltn__drop-menu > ul > li > a:hover, + .ltn__header-options-2 .mini-cart-icon a:hover, + .ltn__header-options-2 .header-wishlist:hover { + background: var(--ltn__secondary-color); + color: var(--white); } + +.ltn__header-options-2 .header-search-1:hover, +.ltn__header-options-2 .ltn__drop-menu > ul > li:hover > a, +.ltn__header-options-2 .mini-cart-icon a:hover { + background: var(--ltn__secondary-color); + color: var(--white); } + +.ltn__header-options-2 .ltn__drop-menu.ltn__currency-menu > ul > li > a { + height: inherit; + width: inherit; + line-height: inherit; + background: inherit; + color: inherit; } + +.ltn__header-options-2 .mobile-menu-toggle > a { + width: 50px; + height: 50px; + background: var(--white); + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); } + +.ltn__header-options-color-white .mini-cart-icon-2 > a .mini-cart-icon i { + color: var(--white); } + +.ltn__header-options-color-white .mini-cart-icon-2 > a .mini-cart-icon sup { + background-color: var(--white); + color: var(--ltn__secondary-color); } + +.ltn__header-options-color-white .mini-cart-icon-2 > a h6 { + color: var(--white); } + .ltn__header-options-color-white .mini-cart-icon-2 > a h6 span { + color: var(--white) !important; } + +/* ltn__drop-menu */ +.ltn__drop-menu { + display: inline-block; + text-align: left; } + +.ltn__drop-menu li { + margin-top: 0; } + +.ltn__drop-menu + .ltn__drop-menu { + margin-left: 10px; } + +.ltn__drop-menu ul { + margin-bottom: 0; } + +.ltn__drop-menu > ul > li { + display: inline-block; + position: relative; } + +.ltn__drop-menu > ul > li > a { + display: block; + text-decoration: none; + padding: 0 10px; + height: 40px; + line-height: 40px; } + +.ltn__drop-menu ul li ul { + position: absolute; + min-width: 150px; + right: 0; + background-color: #fff; + z-index: 999; + -webkit-box-shadow: var(--ltn__box-shadow-4); + box-shadow: var(--ltn__box-shadow-4); + border-top: 1px solid #ececec; + top: 130%; + padding: 10px 0; + margin: 0; + -webkit-transition: opacity .2s ease .1s,visibility .2s ease .1s,top .2s ease .1s; + -o-transition: opacity .2s ease .1s,visibility .2s ease .1s,top .2s ease .1s; + transition: opacity .2s ease .1s,visibility .2s ease .1s,top .2s ease .1s; + opacity: 0; + visibility: hidden; } + +.ltn__drop-menu ul li ul li { + display: block; + padding: 5px 15px; + font-size: 14px; + font-weight: 400; } + +.ltn__drop-menu ul li ul li a { + color: inherit; } + +.ltn__drop-menu ul li:hover > ul { + top: 100%; + opacity: 1; + visibility: visible; } + +.ltn__drop-menu ul li:hover > a { + color: var(--ltn__secondary-color); } + +.ltn__drop-menu > ul > li, +.header-wishlist a { + font-size: 20px; } + +/* header-wishlist */ +.header-wishlist { + color: var(--ltn__heading-color); } + +/* ---------------------------------------------- + Mini Cart +---------------------------------------------- */ +.ltn__mini-cart ul { + margin: 0; + padding: 0; } + +.mini-cart-icon { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + line-height: 30px; + cursor: pointer; + color: var(--ltn__heading-color); } + .mini-cart-icon i { + font-size: 18px; } + .mini-cart-icon sup { + font-size: 14px; + font-weight: 600; } + +.mini-cart-icon-2 > a { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + min-width: 125px; } + .mini-cart-icon-2 > a .mini-cart-icon { + margin-right: 5px; } + .mini-cart-icon-2 > a .mini-cart-icon i { + color: var(--ltn__heading-color); + font-size: 20px; } + .mini-cart-icon-2 > a .mini-cart-icon sup { + font-size: 12px; + font-weight: 600; + height: 20px; + width: 20px; + line-height: 20px; + background-color: var(--ltn__secondary-color); + color: var(--white); + text-align: center; + border-radius: 100%; + right: 8px; + top: -8px; } + .mini-cart-icon-2 > a h6 { + margin-bottom: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-flow: column; + flex-flow: column; + line-height: 20px; + font-weight: 500; + color: var(--ltn__body-color); + font-size: 12px; + text-transform: uppercase; } + +.mini-cart-header h5 { + margin-bottom: 0; } + +.mini-cart-product-area { + max-height: calc(100% - (60px + 245px)); } + +.ltn__utilize-cart-menu .ltn__mini-cart { + max-height: calc(100% - (60px + 245px)); } + +.mini-cart-item { + padding-top: 20px; + padding-left: 10px; + margin-bottom: 20px; + border-top: 1px solid var(--border-color-1); } + .mini-cart-item:first-child { + border-top: 0; } + +.mini-cart-img { + float: left; + width: 80px; + margin-right: 15px; + position: relative; } + +.mini-cart-img img { + background-color: var(--section-bg-1); } + +.mini-cart-info { + overflow: hidden; } + +.mini-cart-info h6 { + margin-bottom: 5px; + font-size: 14px; + color: var(--ltn__body-color); + font-weight: 600; } + +.mini-cart-info .mini-cart-quantity { + font-size: 14px; + font-weight: 400; } + +.mini-cart-item-delete { + position: absolute; + left: -8px; + top: -8px; + height: 20px; + width: 20px; + border-radius: 100%; + display: block; + line-height: 20px; + background-color: #fff; + text-align: center; + font-size: 10px; + -webkit-box-shadow: var(--ltn__box-shadow-3); + box-shadow: var(--ltn__box-shadow-3); + cursor: pointer; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .mini-cart-item-delete:hover { + background-color: var(--red); + color: #fff; } + +.mini-cart-footer { + margin-top: 25px; } + .mini-cart-footer p { + font-size: 14px; + margin-bottom: 0; } + +.mini-cart-sub-total { + border-top: 1px solid var(--border-color-1); + border-bottom: 1px solid var(--border-color-1); + padding: 15px 0; } + .mini-cart-sub-total h5 { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin-bottom: 0; + font-size: 16px; } + .mini-cart-sub-total span { + color: var(--ltn__secondary-color); } + +.mini-cart-footer .btn-wrapper { + margin-top: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + padding: 25px 0 15px; } + +.mini-cart-footer .btn-wrapper .btn { + margin-bottom: 5px; + text-transform: uppercase; + padding: 10px 20px; + font-size: 13px; } + +/* ---------------------------------------- + Header Searchbox +---------------------------------------- */ +.header-search-1 { + cursor: pointer; + display: inline-block; } + .header-search-1 .search-icon { + min-width: 25px; + text-align: center; + font-size: 16px; } + +.header-search-wrap { + position: relative; } + +.header-search-1-form { + background-color: var(--white); + -webkit-box-shadow: var(--ltn__box-shadow-3); + box-shadow: var(--ltn__box-shadow-3); + height: 0; + margin-right: 0; + overflow: hidden; + position: absolute; + right: 0; + top: 130%; + -webkit-transition-duration: 0.4s; + -o-transition-duration: 0.4s; + transition-duration: 0.4s; + -webkit-transition-property: height; + -o-transition-property: height; + transition-property: height; + width: 320px; + z-index: 9999; } + .header-search-1-form form { + position: relative; + margin: 15px 15px 0; } + .header-search-1-form input { + height: 60px; + padding-right: 50px; } + .header-search-1-form button[type="submit"] { + background: rgba(0, 0, 0, 0) none repeat scroll 0 0; + border: medium none; + color: var(--ltn__heading-color); + display: block; + font-size: 18px; + height: 60px; + line-height: 48px; + position: absolute; + right: 8px; + text-align: center; + top: 0; + padding: 1px 6px; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .header-search-1-form button[type="submit"]:hover { + color: var(--ltn__primary-color); } + +.search-icon { + position: relative; } + .search-icon .for-search-close { + position: absolute; + top: 40%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + left: 0; + right: 0; + opacity: 0; + visibility: hidden; } + +.search-open.header-search-1-form { + height: 90px; } + +.search-open .for-search-show { + opacity: 0; + visibility: hidden; } + +.search-open .for-search-close { + opacity: 1; + visibility: visible; } + +@media (max-width: 767px) { + .header-search-wrap { + position: inherit; } + .header-search-1-form { + top: 100%; } + .header-search-1-form { + -webkit-transform: translateX(50%); + -ms-transform: translateX(50%); + transform: translateX(50%); + right: 50%; } } + +@media (max-width: 575px) { + .header-search-1-form { + width: 270px; } } + +/* search-2 */ +.header-search-2 { + min-width: 500px; + padding: 25px 0; } + .header-search-2 form { + position: relative; } + .header-search-2 input { + margin-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + border-radius: 50px; + padding-left: 20px; + padding-right: 50px; + height: 45px; + border: 1px solid var(--border-color-7); + background-color: var(--white); } + .header-search-2 button { + position: absolute; + right: 0; + background-color: transparent; + height: 45px; + top: 0; + padding: 0 15px; + font-size: 18px; } + .header-search-2 button:hover { + color: var(--ltn__secondary-color); } + +/* ---------------------------------------- + Currency Menu +---------------------------------------- */ +.ltn__currency-menu .active-currency { + font-size: 16px; } + +.ltn__currency-menu ul li ul { + min-width: 200px; } + +.ltn__currency-menu .dropdown-toggle::after { + margin-left: 3px; + border-top: 0.25em solid; + border-right: .20em solid transparent; + border-left: .20em solid transparent; } + +.ltn__language-menu .dropdown-toggle { + padding-right: 10px !important; + position: relative; } + .ltn__language-menu .dropdown-toggle::after { + display: none; } + .ltn__language-menu .dropdown-toggle::before { + content: "\e911"; + font-size: 14px; + position: absolute; + top: 50%; + right: -5px; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + font-family: 'icomoon'; + color: var(--ltn__secondary-color); } + +/* ---------------------------------------- + Header 4 +---------------------------------------- */ +.ltn__header-4 .ltn__header-middle-area, +.ltn__header-5 .ltn__header-middle-area { + padding-top: 22px; + padding-bottom: 22px; } + +.ltn__header-4 .ltn__header-top-area { + border-color: var(--border-color-3); } + +.site-logo-wrap { + display: -webkit-box; + display: -ms-flexbox; + display: flex; } + .site-logo-wrap .site-logo { + min-width: auto; } + +.get-support { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + position: relative; + padding-left: 20px; + margin-left: 20px; } + .get-support::before { + position: absolute; + content: ""; + left: 0; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + height: 30px; + width: 1px; + background-color: #999; } + .get-support .get-support-icon { + margin-right: 10px; + font-size: 35px; + line-height: 1; + color: var(--ltn__secondary-color); } + .get-support .get-support-icon i { + -webkit-transform: rotate(-45deg); + -ms-transform: rotate(-45deg); + transform: rotate(-45deg); } + .get-support .get-support-info { + margin: 0; + text-align: left; } + .get-support .get-support-info h6 { + margin: 0; + font-weight: 600; + font-size: 14px; } + .get-support .get-support-info h4 { + margin: 5px 0 0; + line-height: 1; } + +.get-support-color-white .get-support-info h6, +.get-support-color-white .get-support-info h4 { + color: var(--white); } + +.special-link { + margin-left: 15px; + -ms-flex-item-align: center; + -ms-grid-row-align: center; + align-self: center; } + .special-link a { + background-color: var(--ltn__secondary-color); + color: var(--white) !important; + padding: 15px 30px !important; } + .special-link a:hover { + background-color: var(--section-bg-1); + color: var(--ltn__primary-color) !important; } + +.menu-color-white .ltn__main-menu > ul > li > a { + color: var(--white); } + +/* ---------------------------------------------- + Header Sticky +---------------------------------------------- */ +.sticky-active { + -webkit-animation: 300ms ease-in-out 0s normal none 1 running fadeInDown; + animation: 300ms ease-in-out 0s normal none 1 running fadeInDown; + background-color: var(--white); + left: 0; + position: fixed; + top: 0; + width: 100%; + z-index: 999; + -webkit-box-shadow: 0 1px 6px 0 rgba(32, 33, 36, 0.28); + box-shadow: 0 1px 6px 0 rgba(32, 33, 36, 0.28); } + +.ltn__header-3 .header-bottom-area.sticky-active, +.ltn__header-4 .ltn__header-middle-area.sticky-active, +.ltn__header-5 .ltn__header-middle-area.sticky-active { + padding-top: 0px; + padding-bottom: 0px; } + +/* Sticky Background Black */ +.sticky-active.ltn__sticky-bg-black { + background-color: var(--section-bg-2); } + .sticky-active.ltn__sticky-bg-black .ltn__main-menu > ul > li > a, + .sticky-active.ltn__sticky-bg-black .header-wishlist a, + .sticky-active.ltn__sticky-bg-black .mini-cart-icon, + .sticky-active.ltn__sticky-bg-black .header-feature-item h6, + .sticky-active.ltn__sticky-bg-black .header-feature-item p, + .sticky-active.ltn__sticky-bg-black .header-feature-icon, + .sticky-active.ltn__sticky-bg-black .header-search-1 .search-icon, + .sticky-active.ltn__sticky-bg-black .ltn__header-options .ltn__drop-menu > ul > li > a { + color: var(--white); } + .sticky-active.ltn__sticky-bg-black .ltn__header-options-2 .header-search-1, + .sticky-active.ltn__sticky-bg-black .ltn__header-options-2 .header-search-1 i, + .sticky-active.ltn__sticky-bg-black .ltn__header-options-2 .ltn__drop-menu > ul > li > a, + .sticky-active.ltn__sticky-bg-black .ltn__header-options-2 .mini-cart-icon a, + .sticky-active.ltn__sticky-bg-black .ltn__header-options-2 .header-wishlist { + background: var(--white); + color: var(--ltn__heading-color); } + +/* Sticky Background White */ +.sticky-active.ltn__sticky-bg-white { + background-color: var(--white); } + .sticky-active.ltn__sticky-bg-white .ltn__main-menu > ul > li > a, + .sticky-active.ltn__sticky-bg-white .header-wishlist a, + .sticky-active.ltn__sticky-bg-white .mini-cart-icon, + .sticky-active.ltn__sticky-bg-white .header-feature-item h6, + .sticky-active.ltn__sticky-bg-white .header-feature-item p, + .sticky-active.ltn__sticky-bg-white .header-feature-icon, + .sticky-active.ltn__sticky-bg-white .header-search-1 .search-icon, + .sticky-active.ltn__sticky-bg-white .ltn__header-options .ltn__drop-menu > ul > li > a { + color: var(--ltn__heading-color); } + .sticky-active.ltn__sticky-bg-white .ltn__header-options-2 .header-search-1, + .sticky-active.ltn__sticky-bg-white .ltn__header-options-2 .header-search-1 i, + .sticky-active.ltn__sticky-bg-white .ltn__header-options-2 .ltn__drop-menu > ul > li > a, + .sticky-active.ltn__sticky-bg-white .ltn__header-options-2 .mini-cart-icon a, + .sticky-active.ltn__sticky-bg-white .ltn__header-options-2 .header-wishlist { + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); + background: var(--white); + color: var(--ltn__heading-color); } + +.ltn__header-2 .sticky-active .row .col, +.ltn__header-3 .sticky-active .row .col { + -webkit-box-pack: justify !important; + -ms-flex-pack: justify !important; + justify-content: space-between !important; } + +.ltn__header-2 .sticky-active .sticky-logo, +.ltn__header-3 .sticky-active .sticky-logo { + display: block; } + +.ltn__header-2 .sticky-active .header-menu-2, +.ltn__header-3 .sticky-active .header-menu-2 { + text-align: right; } + +.ltn__header-3 .ltn__header-middle-area { + padding-top: 15px; + padding-bottom: 15px; } + +.header-contact-search { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; } + +/* header-8 */ +.ltn__header-8 .ltn__header-middle-area { + padding-top: 15px; + padding-bottom: 15px; } + +.ltn__header-8 .ltn__header-options > ul > li { + margin-right: 10px; } + +.ltn__header-8 .mobile-menu-toggle { + margin-right: 0; + position: relative; + top: 7px; } + +.ltn__header-8 .sticky-active.ltn__header-middle-area { + padding-top: 5px; + padding-bottom: 5px; } + +@media (max-width: 1300px) { + .ltn__header-8 .ltn__header-middle-area > .container-fluid > .row > .col.logo-column, + .ltn__header-8 .ltn__header-middle-area > .container > .row > .col.logo-column { + max-width: 260px; } + .ltn__header-8 .ltn__main-menu > ul > li { + margin-right: 10px; } } + +/* ltn__header-transparent */ +.ltn__header-transparent { + position: absolute; + width: 100%; + z-index: 999; + background-color: transparent; } + .ltn__header-transparent .top-area-color-white { + background-color: transparent; } + +/* ---------------------------------------- + Header 5 +---------------------------------------- */ +.ltn__header-5 .get-support::before { + background-color: #e4e8ea; } + +.ltn__header-5 .ltn__header-options { + margin-left: 30px; } + +/* ---------------------------------------- + Utilize Mobile Menu +---------------------------------------- */ +.ltn__utilize { + position: fixed; + z-index: 1000; + top: 0; + right: 0; + left: auto; + display: block; + overflow: hidden; + width: 400px; + height: 100vh; + padding: 20px 10px 20px 30px; + -webkit-transition: all .5s ease 0s; + -o-transition: all .5s ease 0s; + transition: all .5s ease 0s; + -webkit-transform: translateX(100%); + -ms-transform: translateX(100%); + transform: translateX(100%); + background-color: var(--white); + -webkit-box-shadow: none; + box-shadow: none; + z-index: 99999; } + +.ltn__utilize.ltn__utilize-mobile-menu { + right: auto; + left: 0; + padding: 50px 40px; + -webkit-transform: translateX(-100%); + -ms-transform: translateX(-100%); + transform: translateX(-100%); } + +.ltn__utilize-menu-inner { + position: relative; + z-index: 9; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + height: 100%; + -ms-touch-action: auto; + touch-action: auto; + overflow-x: hidden !important; + padding-right: 20px; } + +.ltn__utilize-menu-search-form { + margin-bottom: 30px; + position: relative; } + .ltn__utilize-menu-search-form input[type="text"] { + margin-bottom: 0; } + .ltn__utilize-menu-search-form button { + background-color: transparent; + position: absolute; + right: 0; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + height: 100%; + padding: 0 15px; } + +.ltn__utilize-menu > ul { + margin: 0; + padding: 0; + list-style: none; } + +.ltn__utilize-menu > ul > li { + position: relative; } + +.ltn__utilize-menu > ul > li .menu-expand { + position: absolute; + z-index: 2; + top: 0; + right: 0; + width: 24px; + height: 44px; + cursor: pointer; + background-color: transparent; } + +.ltn__utilize-menu > ul > li .menu-expand::before, +.ltn__utilize-menu > ul > li .menu-expand::after { + position: absolute; + top: calc(50% - 1px); + left: calc(50% - 7px); + width: 14px; + height: 2px; + content: ""; + -webkit-transition: all .5s ease 0s; + -o-transition: all .5s ease 0s; + transition: all .5s ease 0s; + -webkit-transform: scale(0.75); + -ms-transform: scale(0.75); + transform: scale(0.75); + background-color: #7e7e7e; } + +.ltn__utilize-menu > ul > li .menu-expand::after { + -webkit-transform: rotate(90deg) scale(0.75); + -ms-transform: rotate(90deg) scale(0.75); + transform: rotate(90deg) scale(0.75); } + +.ltn__utilize-menu > ul > li > a { + display: block; + padding: 8px 24px 8px 0; + text-transform: uppercase; } + +.ltn__utilize-menu > ul > li .sub-menu { + position: static; + top: auto; + display: none; + visibility: visible; + width: 100%; + min-width: auto; + padding: 0; + padding-left: 15px; + -webkit-transition: none; + -o-transition: none; + transition: none; + opacity: 1; + -webkit-box-shadow: none; + box-shadow: none; } + +.ltn__utilize-menu > ul > li .sub-menu li { + line-height: inherit; + position: relative; + list-style: none; } + +.ltn__utilize-overlay { + position: fixed; + z-index: 9999; + top: 0; + right: 0; + bottom: 0; + left: 0; + display: none; + background-color: rgba(0, 0, 0, 0.5); } + +.ltn__utilize.ltn__utilize-open { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); } + +.ltn__utilize.ltn__utilize-mobile-menu.ltn__utilize-open { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); } + +.mobile-menu-toggle { + margin-right: 15px; } + +.mobile-menu-toggle > a { + width: 24px; + height: 32px; + position: relative; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + color: #333; + margin-left: auto; } + +.mobile-menu-toggle svg { + position: absolute; + top: 50%; + left: 50%; + width: 50px; + height: 60px; + margin-top: -2px; + margin-left: -2px; + cursor: pointer; + -webkit-transform: translate3d(-50%, -50%, 0); + transform: translate3d(-50%, -50%, 0); } + +.mobile-menu-toggle svg path { + -webkit-transition: stroke-dashoffset 0.5s cubic-bezier(0.25, -0.25, 0.75, 1.25), stroke-dasharray 0.5s cubic-bezier(0.25, -0.25, 0.75, 1.25); + -o-transition: stroke-dashoffset 0.5s cubic-bezier(0.25, -0.25, 0.75, 1.25), stroke-dasharray 0.5s cubic-bezier(0.25, -0.25, 0.75, 1.25); + transition: stroke-dashoffset 0.5s cubic-bezier(0.25, -0.25, 0.75, 1.25), stroke-dasharray 0.5s cubic-bezier(0.25, -0.25, 0.75, 1.25); + fill: none; + stroke: #333; + stroke-dashoffset: 0; + stroke-linecap: round; + stroke-width: 30px; } + +.mobile-menu-toggle svg path#top, .mobile-menu-toggle svg path#bottom { + stroke-dasharray: 240px 950px; } + +.mobile-menu-toggle svg path#middle { + stroke-dasharray: 240px 240px; } + +.mobile-menu-toggle .close svg path#top, .mobile-menu-toggle .close svg path#bottom { + stroke-dasharray: -650px; + stroke-dashoffset: -650px; } + +.mobile-menu-toggle .close svg path#middle { + stroke-dasharray: 1px 220px; + stroke-dashoffset: -115px; } + +.ltn__utilize-menu-head { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin-bottom: 25px; + padding-bottom: 15px; + border-bottom: 1px solid #eee; } + .ltn__utilize-menu-head .ltn__utilize-menu-title { + font-weight: 500; + text-transform: uppercase; } + .ltn__utilize-menu-head .ltn__utilize-close { + background-color: transparent; + font-size: 30px; + padding: 0 15px; } + +.ltn__utilize-buttons { + border-top: 1px solid var(--border-color-1); + padding: 5px 0px 20px; + margin: 30px 0; + border-bottom: 1px solid var(--border-color-1); } + .ltn__utilize-buttons ul { + padding: 0; + margin: 0; } + .ltn__utilize-buttons ul li { + display: inline-block; } + .ltn__utilize-buttons .utilize-btn-icon { + width: 50px; + display: inline-block; + height: 50px; + border: 2px solid var(--border-color-1); + line-height: 46px; + text-align: center; + margin-right: 10px; } + +.ltn__utilize-buttons-2 ul li { + display: block; } + +@media (max-width: 479px) { + .ltn__utilize { + width: 300px; + padding: 15px 10px 15px 30px; } + .ltn__utilize-menu-head { + margin-bottom: 20px; + padding-bottom: 5px; } + .mini-cart-footer .btn-wrapper { + padding: 20px 0 10px; } + .ltn__utilize.ltn__utilize-mobile-menu { + padding: 50px 20px; } } + +.menu-btn-white.mobile-menu-toggle > a { + color: #fff; } + +.menu-btn-white.mobile-menu-toggle svg path { + stroke: #fff; } + +.menu-btn-border a { + width: 40px; + height: 38px; + border: 1px solid; } + +/* ---------------------------------------- + Responsive +---------------------------------------- */ +@media (min-width: 1200px) and (max-width: 1300px) { + .ltn__main-menu > ul > li { + margin-right: 15px; } + .ltn__main-menu > ul > li:last-child { + margin-right: 0; } + .ltn__main-menu > ul > li > a { + font-size: 14px; } + .ltn__header-6 .ltn__main-menu > ul > li { + margin-right: 10px; } + .ltn__header-6 .ltn__main-menu > ul > li:last-child { + margin-right: 0px; } + .ltn__header-6 .special-link a { + padding: 15px 20px !important; } + .ltn__header-6 .ltn__main-menu > ul > li > a { + font-size: 14px; } } + +@media (max-width: 1199px) { + .site-logo { + min-width: 180px; } + .ltn__main-menu > ul > li > a { + padding: 20px 15px; } + .ltn__main-menu > ul > li { + margin-right: 10px; } } + +@media (max-width: 991px) { + .header-search-column, + .header-menu-column { + display: none; } + /* sticky */ + .sticky-active { + position: inherit; } + .ltn__header-2 .ltn__header-middle-area > .container > .row .header-feature-column { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + border-top: 1px solid #ddd; } + .ltn__header-2 .header-feature-area { + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; } + .ltn__header-2 .header-feature-item { + margin-right: 15px; } + .ltn__header-3 .ltn__header-middle-area > .container > .row .header-search-column { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + border-top: 1px solid #ddd; } + .ltn__header-3 .header-search-2 { + min-width: 280px; } + .ltn__header-3 .mobile-menu-toggle { + position: relative; + top: 7px; } + .ltn__header-3 .ltn__main-menu > ul > li > a { + padding: 20px 10px; } + .ltn__top-bar-menu ul li { + margin: 0 20px 0 0; } } + +@media (max-width: 767px) { + .ltn__header-top-area { + padding: 5px 0; + text-align: center; } + .ltn__header-top-area .ltn__social-media ul li { + font-size: 12px; + margin: 0 5px 0 0; } + .ltn__top-bar-menu .ltn__currency-menu .active-currency, + .ltn__top-bar-menu > ul > li { + font-size: 13px; } + .ltn__drop-menu > ul > li { + position: inherit; } + .ltn__drop-menu > ul > li > a { + height: 20px; + line-height: 20px; } + .ltn__drop-menu ul li ul { + left: 50%; + right: 50%; + -webkit-transform: translateX(-50%); + -ms-transform: translateX(-50%); + transform: translateX(-50%); } + .top-bar-right { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; } + .welcome p { + line-height: 20px; + margin: 5px 0; } + .site-logo { + min-width: 100px; } + .ltn__header-5 .top-bar-right, + .ltn__header-4 .top-bar-right { + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + margin-top: 5px; } + .ltn__header-4 .site-logo-wrap, + .ltn__header-5 .site-logo-wrap { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + margin: 10px 0 30px; } + .ltn__header-4 .ltn__header-options, + .ltn__header-5 .ltn__header-options { + margin-left: 0; + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } + .ltn__header-8 .ltn__header-middle-area > .container > .row .col, + .ltn__header-8 .ltn__header-middle-area > .container-fluid > .row .col { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; } + .ltn__header-8 .ltn__header-middle-area > .container-fluid > .row > .col.logo-column, + .ltn__header-8 .ltn__header-middle-area > .container > .row > .col.logo-column { + max-width: 100%; } + .ltn__header-8 .ltn__header-middle-area { + padding-top: 20px; + padding-bottom: 20px; } + .ltn__header-8 .site-logo { + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + margin-bottom: 20px; } + .ltn__header-8 .ltn__header-options { + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } } + +@media (max-width: 575px) { + .site-logo a { + font-size: 24px; } + .site-logo a i { + font-size: 20px; } + .ltn__header-1 .ltn__header-middle-area > .container > .row { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-flow: column; + flex-flow: column; } + .ltn__header-1 .site-logo { + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } + .ltn__header-1 .ltn__header-options { + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + margin-top: 30px; } + .ltn__header-7 .site-logo { + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } + .ltn__header-7 .ltn__header-options { + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + margin-top: 20px; } + .ltn__header-3 .ltn__header-middle-area > .container > .row .col, + .ltn__header-3 .ltn__header-middle-area > .container-fluid > .row .col, + .ltn__header-7 .ltn__header-middle-area > .container > .row .col, + .ltn__header-7 .ltn__header-middle-area > .container-fluid > .row .col { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; } + .ltn__header-3 .ltn__header-middle-area { + padding-top: 20px; + padding-bottom: 20px; } + .ltn__header-3 .site-logo { + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + margin-bottom: 20px; } + .ltn__header-3 .ltn__header-options { + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } } + +@media (max-width: 449px) { + .ltn__header-options > div { + margin-right: 10px; } + .header-feature-area { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-flow: column; + flex-flow: column; } + .header-feature-item:last-child { + padding-top: 0; } + .get-support { + padding-left: 10px; + margin-left: 10px; } + .get-support .get-support-icon { + font-size: 20px; + display: none; } + .get-support .get-support-info h6 { + display: 13px; } + .get-support .get-support-info h4 { + font-size: 16px; } } + +@media (max-width: 350px) { + .ltn__header-8 .ltn__header-options > ul > li { + margin-right: 4px; } + .ltn__header-8 .mini-cart-icon-2 > a h6 { + font-size: 11px; } } + +/* ---------------------------------------------------- + END +---------------------------------------------------- */ +/* ---------------------------------------------------- + Slider Area 1, 2, 3, 4, 5, 6 +---------------------------------------------------- */ +.ltn__slide-item { + padding-top: 100px; + padding-bottom: 100px; + height: 750px; } + +.ltn__slide-item-inner { + height: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + +.slide-item-info-inner { + width: 100%; } + +.slide-title { + font-size: 50px; + font-weight: 700; } + +/* Slider Animation Start */ +.ltn__slide-animation { + position: relative; + z-index: 9; } + .ltn__slide-animation > * { + opacity: 0; + visibility: hidden; + -webkit-animation-name: fadeOutUp; + animation-name: fadeOutUp; } + .ltn__slide-animation > *:nth-child(1) { + -webkit-animation-delay: 0.5s; + animation-delay: 0.5s; + -webkit-animation-duration: 0.5s; + animation-duration: 0.5s; } + .ltn__slide-animation > *:nth-child(2) { + -webkit-animation-delay: 1s; + animation-delay: 1s; + -webkit-animation-duration: 1s; + animation-duration: 1s; } + .ltn__slide-animation > *:nth-child(3) { + -webkit-animation-delay: 1.5s; + animation-delay: 1.5s; + -webkit-animation-duration: 1.5s; + animation-duration: 1.5s; } + .ltn__slide-animation > *:nth-child(4) { + -webkit-animation-delay: 2s; + animation-delay: 2s; + -webkit-animation-duration: 2s; + animation-duration: 2s; } + .ltn__slide-animation > *:nth-child(5) { + -webkit-animation-delay: 2.5s; + animation-delay: 2.5s; + -webkit-animation-duration: 2.5s; + animation-duration: 2.5s; } + .ltn__slide-animation > *:nth-child(6) { + -webkit-animation-delay: 3s; + animation-delay: 3s; + -webkit-animation-duration: 3s; + animation-duration: 3s; } + .ltn__slide-animation > *:nth-child(7) { + -webkit-animation-delay: 3.5s; + animation-delay: 3.5s; + -webkit-animation-duration: 3.5s; + animation-duration: 3.5s; } + .ltn__slide-animation > *:nth-child(8) { + -webkit-animation-delay: 4s; + animation-delay: 4s; + -webkit-animation-duration: 4s; + animation-duration: 4s; } + .ltn__slide-animation > *:nth-child(9) { + -webkit-animation-delay: 4.5s; + animation-delay: 4.5s; + -webkit-animation-duration: 4.5s; + animation-duration: 4.5s; } + .ltn__slide-animation > *:nth-child(11) { + -webkit-animation-delay: 5s; + animation-delay: 5s; + -webkit-animation-duration: 5s; + animation-duration: 5s; } + +.slick-current .ltn__slide-animation > *, +.ltn__slide-animation-active .ltn__slide-animation > * { + opacity: 1; + visibility: visible; + -webkit-animation-name: fadeInUp; + animation-name: fadeInUp; } + +/* Title Background Image */ +.title-bg-img { + background-image: url("../img/slider/1.jpg"); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; + word-break: break-word; } + +.title-bg-img-2 { + background-image: url("https://tunatheme.com/tf/html/fiama-preview/fiama/img/slider/2.jpg"); } + +/* Slide Arrow */ +.slick-slide-arrow-1 .slick-arrow { + cursor: pointer; + position: absolute; + top: 50%; + left: 40px; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + width: 50px; + height: 50px; + line-height: 50px; + border: 1px solid var(--black-9); + text-align: center; + font-size: 16px; + color: var(--ltn__primary-color) !important; + z-index: 1; + opacity: 0; + visibility: hidden; } + .slick-slide-arrow-1 .slick-arrow:hover { + background-color: var(--ltn__secondary-color); + border-color: var(--ltn__secondary-color); + color: var(--white) !important; } + +.slick-slide-arrow-1 .slick-next { + right: 40px; + left: auto; } + +.slick-slide-arrow-1:hover .slick-arrow { + opacity: 1; + visibility: visible; + left: 20px; } + +.slick-slide-arrow-1:hover .slick-next { + right: 20px; + left: auto; } + +.slick-slide-dots-1 .slick-dots { + position: absolute; + bottom: 50px; + width: 100%; + margin: 0; } + +.arrow-white .slick-arrow { + color: var(--white) !important; + border: 1px solid var(--white-3); } + +@media (min-width: 1400px) { + .slick-slide-arrow-1:hover .slick-arrow { + opacity: 1; + visibility: visible; + left: 60px; } + .slick-slide-arrow-1:hover .slick-next { + right: 60px; + left: auto; } } + +/* slide-item-2 */ +.ltn__slide-item-2 { + height: calc(100vh - 0px); + padding-top: 200px; } + .ltn__slide-item-2 .slide-item-info { + max-width: 650px; } + .ltn__slide-item-2 .slide-sub-title { + margin-bottom: 20px; } + .ltn__slide-item-2 .slide-sub-title span { + color: var(--ltn__secondary-color); } + .ltn__slide-item-2 .slide-title { + font-size: 72px; + line-height: 1; + margin-bottom: 20px; } + .ltn__slide-item-2 .slide-title span { + color: var(--ltn__secondary-color); } + .ltn__slide-item-2 .btn-wrapper { + margin-top: 40px; } + .ltn__slide-item-2 .slide-brief { + padding-left: 30px; + border-left: 1px solid #576466; } + +.ltn__slide-item-6 .text-right .slide-brief, +.ltn__slide-item-2 .text-right .slide-brief { + padding-left: 0px; + border-left: 0; + padding-right: 30px; + border-right: 1px solid #576466; + margin-left: auto; } + +.ltn__slide-item-6 .text-center .slide-brief, +.ltn__slide-item-2 .text-center .slide-brief { + padding-left: 0px; + border-left: 0; + padding-right: 0px; + border-right: 0; } + +.text-right .slide-item-info { + margin-left: auto; } + +.text-center .slide-item-info { + margin-left: auto; + margin-right: auto; } + +.slide-brief { + max-width: 450px; } + +.text-right .slide-brief { + margin-left: auto; } + +.text-center .slide-brief { + margin-left: auto; + margin-right: auto; } + +.ltn__product-pointer { + position: absolute; + top: 50%; + left: 50%; + z-index: 9; } + .ltn__product-pointer > ul { + padding: 0; + margin: 0; } + .ltn__product-pointer > ul > li { + display: inline-block; + list-style: none; + position: relative; } + .ltn__product-pointer > ul > li > ul { + position: absolute; + top: 80%; + min-width: 300px; + padding: 0; + background-color: white; + right: 80px; + -webkit-box-shadow: var(--ltn__box-shadow-3); + box-shadow: var(--ltn__box-shadow-3); + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + text-align: left; + opacity: 0; + visibility: hidden; } + .ltn__product-pointer > ul > li > ul > li { + list-style: none; } + .ltn__product-pointer > ul > li:hover ul { + top: 50%; + opacity: 1; + visibility: visible; } + .ltn__product-pointer > ul > li:hover .ltn__pointer-icon { + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); } + .ltn__product-pointer ul li, .ltn__product-pointer ol li { + margin-top: 5px; } + .ltn__product-pointer img { + height: inherit !important; } + .ltn__product-pointer p:last-child { + margin-bottom: 0; } + .ltn__product-pointer .ltn__pointer-icon { + cursor: pointer; + height: 60px; + width: 60px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + background-color: white; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + border-radius: 100%; + font-size: 20px; + -webkit-box-shadow: var(--ltn__box-shadow-4); + box-shadow: var(--ltn__box-shadow-4); + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__product-pointer .ltn__product-pointer-inner { + padding: 15px 30px 25px; + position: relative; } + .ltn__product-pointer .ltn__product-pointer-inner::before { + position: absolute; + content: ""; + width: 0; + height: 0; + border-top: 15px solid transparent; + border-left: 15px solid var(--white); + border-bottom: 15px solid transparent; + right: -15px; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + .ltn__product-pointer .ltn__product-pointer-inner h5 { + margin-bottom: 10px; } + .ltn__product-pointer .ltn__product-pointer-inner p { + font-size: 14px; } + .ltn__product-pointer.ltn__product-pointer-1 { + top: 38%; + left: auto; + right: 24%; } + .ltn__product-pointer.ltn__product-pointer-2 { + top: 60%; + left: 20%; } + .ltn__product-pointer.ltn__product-pointer-3 { + top: 10%; + left: 40%; } + +.slide-img-left .ltn__product-pointer > ul > li > ul { + left: 80px; + right: auto; } + +.slide-img-left .ltn__product-pointer .ltn__product-pointer-inner::before { + border-right: 15px solid var(--white); + border-left: 0; + right: auto; + left: -15px; } + +/* slide-item-3 */ +.ltn__slide-item-3 .row [class*='col-'] { + position: inherit; } + +.ltn__slide-item-3 .slide-item-info { + position: relative; + z-index: 2; } + +.ltn__slide-item-3 .slide-item-img { + width: 45%; + position: absolute; + right: 150px; + top: auto; + bottom: 100px; + height: 70%; } + .ltn__slide-item-3 .slide-item-img img { + text-align: right; + margin-left: auto; + height: 100%; + -o-object-fit: contain; + object-fit: contain; + -o-object-position: center center; + object-position: center center; } + +.ltn__slide-item-3 .text-right .slide-item-img { + right: auto; + left: 150px; } + +/* slide-item-4 */ +.ltn__slide-item-4 { + padding-bottom: 0; } + .ltn__slide-item-4 .slide-item-img { + margin-top: 100px; } + +/* slider-5 */ +.ltn__slider-5 .ltn__slide-item-2 { + padding-top: 100px; } + +/* slide-item-5 */ +.ltn__slide-item-5 .slide-item-img { + right: 200px; + bottom: 0; + height: 80%; } + +.ltn__slide-item-5 .call-to-circle-1 { + right: 14%; + left: auto; + top: 30%; + z-index: -1; + -webkit-animation: wave 8s 0.1s infinite linear; + animation: wave 8s 0.1s infinite linear; } + +.ltn__slide-item-5 .text-right .slide-item-img { + right: auto; + left: 150px; } + +.ltn__slide-item-5 .text-right .call-to-circle-1 { + left: 20%; + right: auto; } + +/* slide-item-6 */ +.ltn__slide-item-6 .slide-item-info { + max-width: 850px; } + +.ltn__slide-item-6 .slide-title { + font-size: 100px; + line-height: 1; } + +/* slide-item-7 */ +.ltn__slide-item-7 { + min-height: 800px; + height: calc(100vh - 0px); + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } + .ltn__slide-item-7 .slide-item-info { + max-width: 850px; } + .ltn__slide-item-7 .slide-title { + font-size: 70px; + line-height: 1; } + +/* slide-item-8 */ +.ltn__slide-item-8 { + min-height: 700px; + height: calc(100vh - 190px); + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } + .ltn__slide-item-8 .slide-item-info { + max-width: 850px; } + .ltn__slide-item-8 .slide-title { + font-size: 72px; + line-height: 1; + color: var(--black-2); } + .ltn__slide-item-8 .slide-sub-title { + font-size: 25px; + font-weight: 400; } + .ltn__slide-item-8 .slide-brief p { + font-weight: 300; } + .ltn__slide-item-8 .slide-title.white-color { + color: var(--white); } + +.slide-title-line-2, +.slide-title-line { + position: relative; + padding-bottom: 20px; + margin-bottom: 25px; } + .slide-title-line-2::before, + .slide-title-line::before { + position: absolute; + content: ""; + left: 0; + bottom: 0; + width: 90px; + height: 2px; + background-color: var(--ltn__secondary-color); } + +.text-right .slide-title-line::before { + left: auto; + right: 0; } + +.slide-title-line-2 { + position: relative; + padding-bottom: 0; + margin-bottom: 25px; + padding-left: 100px; } + .slide-title-line-2::before { + position: absolute; + content: ""; + left: 0; + bottom: 50%; + width: 90px; + height: 2px; + background-color: var(--ltn__secondary-color); + -webkit-transform: translateY(50%); + -ms-transform: translateY(50%); + transform: translateY(50%); } + +/* slide-item-9 */ +.ltn__slide-item-9 .slide-sub-title { + font-size: 18px; + font-weight: 400; + text-transform: uppercase; } + +.ltn__slide-item-9 .slide-title { + font-size: 60px; + line-height: 1; + color: var(--black-2); + text-transform: uppercase; } + +@media (min-width: 1600px) { + .ltn__slide-item-2 { + min-height: 800px; } + .ltn__slide-item-6 { + height: 800px; } } + +@media (max-width: 1599px) { + .liton-slide-item, + .ltn__slide-item-3, + .liton-slide-item-inner { + height: inherit; } } + +@media (min-width: 1200px) and (max-width: 1599px) { + .ltn__slide-item-2 .slide-title { + font-size: 50px; } + .ltn__slide-item-6 { + height: 620px; } + .ltn__slide-item-6 .slide-title { + font-size: 80px; } } + +@media (min-width: 1400px) and (max-width: 1599px) { + .ltn__slide-item-3 .slide-item-img { + width: 45%; + right: 60px; + top: 60%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + .ltn__slide-item-3 .slide-item-img.slide-img-left { + right: auto; + left: 60px; } + .ltn__slide-item-4 .slide-item-img { + margin-top: 50px; + width: 50%; + margin-left: auto; + margin-right: auto; } } + +@media (min-width: 1200px) and (max-width: 1399px) { + .ltn__slide-item-3 .slide-item-img { + width: 45%; + right: 60px; + top: 65%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + .ltn__slide-item-3 .slide-item-img.slide-img-left { + right: auto; + left: 60px; } + .ltn__slide-item-4 .slide-item-img { + margin-top: 50px; + width: 50%; + margin-left: auto; + margin-right: auto; } } + +@media (min-width: 992px) and (max-width: 1199px) { + .ltn__slide-item-3 .slide-item-img { + width: 45%; + right: 60px; } + .ltn__slide-item-3 .slide-item-img.slide-img-left { + right: auto; + left: 60px; } + .ltn__slide-item-6 .slide-title { + font-size: 60px; } } + +@media (max-width: 1199px) { + .slide-title { + font-size: 36px; } + .ltn__slide-item-8, + .ltn__slide-item { + height: auto; + min-height: auto; } + .liton-slide-item-inner { + height: inherit; } + .slide-item-info-inner { + margin-bottom: 5px; } + .ltn__slide-item-2 .slide-title { + font-size: 56px; } + .ltn__slide-item-2 .slide-brief { + padding-left: 15px; } + .ltn__slide-item-6 { + padding-top: 140px; } + .ltn__slide-item-7 { + min-height: 550px; + height: auto; } + .ltn__slide-item-7 .slide-title { + font-size: 60px; } } + +@media (max-width: 991px) { + .slide-title { + font-size: 26px; } + .liton-slide-item-inner { + height: inherit; } + .slick-slide-arrow-1 .slick-arrow { + width: 40px; + height: 40px; + line-height: 38px; + font-size: 16px; } + .ltn__slide-item-2 .slide-title { + font-size: 40px; } + .ltn__slide-item-2 .slide-brief { + padding-left: 15px; } + .ltn__slide-item-3 .slide-item-img { + width: 100%; + position: relative; + height: auto; + right: auto; + bottom: auto; } + .ltn__slide-item-3 .slide-item-img img { + height: auto; } + .ltn__slide-item-3 .text-right .slide-item-img { + right: auto; + left: auto; } + .ltn__product-pointer > ul > li > ul { + min-width: 280px; } + .ltn__product-pointer > ul > li > ul { + top: 110%; + left: 50%; + -webkit-transform: translateX(-50%); + -ms-transform: translateX(-50%); + transform: translateX(-50%); } + .ltn__product-pointer > ul > li:hover ul { + top: 130%; } + .ltn__product-pointer .ltn__product-pointer-inner::before { + left: 50%; + top: -25px; + -webkit-transform: translateX(-50%) rotate(-90deg); + -ms-transform: translateX(-50%) rotate(-90deg); + transform: translateX(-50%) rotate(-90deg); } + .slide-img-left .ltn__product-pointer .ltn__product-pointer-inner::before { + left: 50%; + -webkit-transform: translateX(-50%) rotate(90deg); + -ms-transform: translateX(-50%) rotate(90deg); + transform: translateX(-50%) rotate(90deg); } + .ltn__slide-item-5 .slide-item-img { + display: none; } + .ltn__slide-item-6 .slide-title { + font-size: 40px; } + .ltn__slide-item-7 { + min-height: 400px; } + .ltn__slide-item-7 .slide-title { + font-size: 40px; } + .ltn__slide-item-8 { + min-height: 400px; } + .ltn__slide-item-8 .slide-title { + font-size: 36px; } + .ltn__slide-item-8 .slide-sub-title { + font-size: 16px; } + .ltn__slide-item-8 .slide-brief { + max-width: 400px; } } + +@media (max-width: 767px) { + .liton-slide-item-inner { + height: inherit; } + .slide-title br { + display: none; } + .slide-title { + font-size: 24px; } + .ltn__slide-item-2 { + height: auto; + padding-top: 300px; } + .ltn__slide-item-2 .slide-title { + font-size: 30px; } + .ltn__slide-item-2 .slide-brief { + padding-left: 15px; } + .ltn__product-pointer { + display: none; } + .ltn__slide-item-6 .slide-title { + font-size: 30px; } + .ltn__slide-item-8 .slide-title { + font-size: 26px; } + .ltn__slide-item-8 .slide-sub-title { + font-size: 14px; } } + +/* ---------------------------------------------------- + END +---------------------------------------------------- */ +/* ---------------------------------------------------- + Product Area +---------------------------------------------------- */ +/* ltn__product-item 2, 3, 4 */ +.ltn__product-item { + position: relative; + margin-bottom: 50px; } + +.product-img { + position: relative; + overflow: hidden; } + +.product-img a { + display: block; } + +.product-img img { + position: relative; + -webkit-transition: all 3.5s ease 0s; + -o-transition: all 3.5s ease 0s; + transition: all 3.5s ease 0s; + z-index: -1; } + +.ltn__product-item:hover .product-img::before { + opacity: 0.4; + visibility: visible; } + +.product-title { + font-size: 14px; + margin-bottom: 5px; + text-transform: uppercase; + font-weight: 400; } + +.product-ratting { + margin-bottom: 5px; } + +.product-ratting ul { + margin: 0; + padding: 0; } + +.product-ratting li { + display: inline-block; + margin: 0 -2px; + font-size: 12px; } + +.product-hover-action { + position: absolute; + top: 60%; + left: 0; + right: 0; + text-align: center; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + opacity: 0; + visibility: hidden; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + +.ltn__product-item:hover .product-hover-action { + top: 50%; + opacity: 1; + visibility: visible; } + +.product-hover-action ul { + margin: 0; + padding: 0; + display: inline-block; + -webkit-box-shadow: var(--ltn__box-shadow-3); + box-shadow: var(--ltn__box-shadow-3); } + +.product-hover-action li { + height: 50px; + width: 56px; + line-height: 50px; + font-size: 14px; + text-align: center; + float: left; + margin-right: 0px; + margin-top: 0; + list-style: none; + border-right: 1px solid var(--border-color-7); } + +.product-hover-action li:last-child { + margin-right: 0; + border-right: 0; } + +.product-hover-action li a { + display: block; + background-color: var(--white); + font-weight: 700; } + +.product-hover-action li:hover a { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +/* product-hover-action-2 */ +.product-hover-action-2 { + top: auto; + bottom: -20px; + opacity: 0; + visibility: hidden; + -webkit-transform: inherit; + -ms-transform: inherit; + transform: inherit; } + .product-hover-action-2 ul { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .product-hover-action-2 ul li { + -webkit-box-flex: 1; + -ms-flex: 1 0 auto; + flex: 1 0 auto; + border-color: var(--black-5); } + .product-hover-action-2 ul li a { + background-color: var(--ltn__body-color); + font-weight: 500; + color: var(--white); } + +.ltn__product-item:hover .product-hover-action-2 { + top: auto; + bottom: 0; + opacity: 1; + visibility: visible; } + +/* product-hover-action-3 */ +.product-hover-action-3 { + top: auto; + bottom: -20px; + right: 0; + left: auto; + -webkit-transform: inherit; + -ms-transform: inherit; + transform: inherit; + opacity: 0; + visibility: hidden; } + .product-hover-action-3 ul { + display: -webkit-box; + display: -ms-flexbox; + display: flex; } + .product-hover-action-3 ul li { + border-color: var(--black-5); } + .product-hover-action-3 ul li a { + color: var(--white); + background-color: var(--ltn__body-color); } + +.ltn__product-item:hover .product-hover-action-3 { + top: auto; + bottom: 0; + opacity: 1; + visibility: visible; } + +.product-badge { + position: absolute; + top: 15px; + left: 0; } + +.product-badge ul { + margin: 0; + padding: 0; } + +.product-badge li { + list-style: none; + display: inline-block; + font-size: 13px; + font-weight: 700; + background-color: var(--ltn__secondary-color); + color: var(--white); + padding: 1px 15px; + text-transform: uppercase; + border-radius: 0px 3px 3px 0px; } + .product-badge li:first-child { + margin-top: 0; } + .product-badge li::before { + position: absolute; + content: ""; + bottom: -8px; + left: 0; + border-left: 8px solid var(--ltn__secondary-color); + width: 0; + height: 0; + border-bottom: 8px solid transparent; + display: none; } + .product-badge li.badge-1 { + background-color: var(--ltn__secondary-color); } + .product-badge li.badge-2 { + background-color: var(--green-2); } + .product-badge li.soldout-badge { + background-color: var(--red-2); } + +.product-info { + padding: 25px 0 0; } + +.product-price { + font-weight: 600; } + +.product-price del { + opacity: 0.6; + margin-left: 5px; + font-size: 80%; } + +.ltn__product-item .product-price { + margin-bottom: 12px; } + +.product-action ul { + margin: 10px 0 0; + padding: 0; } + +.product-action li { + display: inline-block; + margin-top: 0; } + +.product-action li a { + display: inline-block; + padding: 3px 15px; + border: 1px solid var(--ltn__heading-color); + color: var(--ltn__heading-color); + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + +.product-action li:hover a { + background-color: var(--ltn__secondary-color); + color: var(--white); + border-color: var(--ltn__secondary-color); } + +.button-1 a { + display: inline-block; + padding: 5px 15px; + background-color: var(--ltn__heading-color); + color: var(--white); + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + +.button-1:hover a { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +/* product-item-2 */ +.ltn__product-item-2 .product-img img { + background-color: var(--section-bg-1); } + +.ltn__product-item-2:hover .product-img img { + -webkit-transform: scale(1.1); + -ms-transform: scale(1.1); + transform: scale(1.1); } + +.ltn__product-item .add-to-cart { + width: auto; + text-transform: uppercase; } + .ltn__product-item .add-to-cart a { + padding: 0 15px; } + .ltn__product-item .add-to-cart span.cart-text { + font-size: 13px; } + +/* product-item-3 */ +.ltn__product-item-3 { + border: 2px solid; + border-color: var(--border-color-8); + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__product-item-3 .product-img::before { + display: none; } + .ltn__product-item-3 .product-info { + padding: 25px 30px 15px; } + .ltn__product-item-3 .product-title { + font-size: 16px; + margin-bottom: 0; } + .ltn__product-item-3 .product-price { + font-size: 20px; + color: var(--ltn__secondary-color); + font-weight: 700; } + .ltn__product-item-3 .product-price del { + font-size: 20px; + opacity: 0.6; } + .ltn__product-item-3 .product-info-brief { + border-top: 2px solid; + border-color: var(--border-color-8); + margin-bottom: 15px; + max-width: 400px; } + .ltn__product-item-3 .product-info-brief ul { + margin: 0; + padding: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; } + .ltn__product-item-3 .product-info-brief ul li { + list-style: none; + display: inline-block; + font-size: 14px; + font-weight: 700; } + .ltn__product-item-3 .product-info-brief ul li i { + color: var(--ltn__secondary-color); + margin-right: 5px; } + .ltn__product-item-3:hover { + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); } + .ltn__product-item-3:hover .product-hover-action { + top: 70%; } + +/* product-item-4 */ +.ltn__product-item-4 .product-title { + border-bottom: 1px solid var(--white-12); + padding-bottom: 15px; + margin-bottom: 13px; } + +.ltn__product-countdown { + position: absolute; + right: 0; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + -webkit-transition: all 0.8s ease 0s; + -o-transition: all 0.8s ease 0s; + transition: all 0.8s ease 0s; } + .ltn__product-countdown .ltn__countdown { + margin: 0; + padding: 10px 0; + width: 50px; + -webkit-box-shadow: none; + box-shadow: none; + border: 1px solid var(--border-color-1); } + .ltn__product-countdown .ltn__countdown .single { + padding: 5px 0; + margin: 0; + border-bottom: 1px solid var(--border-color-1); + display: block; } + .ltn__product-countdown .ltn__countdown .single:last-child { + border-bottom: 0; } + .ltn__product-countdown .ltn__countdown .single h1, + .ltn__product-countdown .ltn__countdown .single p { + margin: 0; + line-height: 1; + font-weight: 400; } + .ltn__product-countdown .ltn__countdown .single h1 { + font-size: 14px; + margin-bottom: 5px; } + .ltn__product-countdown .ltn__countdown .single p { + font-size: 10px; + text-transform: uppercase; } + +.ltn__product-item:hover .ltn__product-countdown { + right: -50px; + opacity: 0; + visibility: hidden; } + +/* ---------------------------------------------------- + Modal Area +---------------------------------------------------- */ +.modal-dialog { + margin-top: 150px; } + +.modal-content { + border-radius: 0; } + +.modal-header { + padding: 0; + border: 0; } + .modal-header .close { + position: absolute; + height: 40px; + width: 40px; + line-height: 40px; + padding: 0; + right: 16px; + left: auto; + top: 16px; + opacity: 1; + z-index: 1; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + background-color: var(--ltn__secondary-color); + color: var(--white); } + .modal-header .close span { + display: block; + font-size: 25px; } + .modal-header .close:not(:disabled):not(.disabled):focus, .modal-header .close:not(:disabled):not(.disabled):hover, .modal-header .close:hover { + opacity: 1; } + +@media (min-width: 992px) { + .modal-lg { + max-width: 980px; } } + +.modal-product-info h3 { + font-size: 30px; + margin-bottom: 0px; + font-weight: 500; } + +.modal-product-info hr { + margin-top: 20px; + margin-bottom: 20px; } + +.modal-product-info .product-price { + font-size: 24px; + margin-bottom: 10px; + color: var(--ltn__secondary-color); + line-height: 1.2; + font-weight: 500; + font-family: var(--ltn__paragraph-font); } + +.modal-product-info .product-ratting li { + color: var(--ratings); } + +.product-price-ratting > ul { + margin: 0; + padding: 0; } + .product-price-ratting > ul > li { + display: inline-block; + margin-right: 30px; } + .product-price-ratting > ul > li:last-child { + margin-right: 0; } + +.product-cart-wishlist-btn .btn { + padding: 13px 20px; + font-size: 14px; + font-weight: 500; } + +.product-cart-wishlist-btn .d-add-to-wishlist { + background-color: var(--white-7); } + +.modal-product-meta > ul { + margin: 0; + padding: 0; } + +.modal-product-meta > ul > li { + list-style: none; + font-size: 14px; + margin-top: 10px; } + .modal-product-meta > ul > li:first-child { + margin-top: 0; } + +.modal-product-meta li strong { + margin-right: 5px; + font-weight: 500; + min-width: 100px; + display: inline-block; } + +.d-meta-title { + font-size: 16px; + color: var(--ltn__heading-color); + font-weight: 500; } + +.modal-product-quantity input { + border: 1px solid #e5e5e5; + float: left; + height: 45px; + text-align: center; + width: 80px; + margin-right: 20px; } + +.modal-btn { + margin-top: 15px; + border-top: 1px solid #f1f1f1; + text-align: right; } + +.modal-btn a { + font-size: 14px; + color: var(--ltn__heading-color); + padding: 5px 10px; } + +.ltn__modal-area .modal-btn { + border: 0; } + +.modal-body { + padding: 30px; } + +.ltn__add-to-cart-modal-area .modal-body { + padding: 30px; } + +.ltn__add-to-cart-modal-area .modal-product-img { + float: left; + max-width: 125px; + margin-right: 30px; } + +.ltn__add-to-cart-modal-area .modal-product-info { + overflow: hidden; } + +.ltn__add-to-cart-modal-area .added-cart i { + color: var(--green); } + +.ltn__add-to-cart-modal-area .btn-wrapper { + margin-top: 20px; } + .ltn__add-to-cart-modal-area .btn-wrapper .btn { + padding: 5px 20px; + margin-right: 10px; + font-size: 14px; + font-weight: 500; } + +.ltn__add-to-cart-modal-area .additional-info { + border-top: 1px solid var(--border-color-1); + text-align: center; + padding-top: 30px; + margin-top: 40px; } + +.modal-backdrop.show { + opacity: .7; } + +@media (max-width: 992px) { + .ltn__quick-view-modal-area .modal-product-info { + padding-top: 25px; } } + +/* ---------------------------------------------------- + Product Tab +---------------------------------------------------- */ +.ltn__tab-menu { + margin-bottom: 50px; } + +.ltn__tab-menu .nav { + display: inline-block; } + +.ltn__gallery-filter-menu button, +.ltn__tab-menu a { + display: inline-block; + padding: 15px 40px; + margin-right: 5px; + margin-bottom: 10px; + color: var(--ltn__heading-color); + background-color: var(--section-bg-1); + font-weight: 700; } + .ltn__gallery-filter-menu button:last-child, + .ltn__tab-menu a:last-child { + margin-right: 0; } + .ltn__gallery-filter-menu button i, + .ltn__tab-menu a i { + margin-right: 10px; } + +.ltn__gallery-filter-menu .active, +.ltn__tab-menu a.active { + color: var(--white); + background-color: var(--ltn__primary-color); + border-color: var(--ltn__primary-color); } + +.ltn__tab-menu-top-left { + position: absolute; + left: 15px; + top: 0; } + +.ltn__tab-menu-top-right { + position: absolute; + right: 15px; + top: 0; } + +.ltn__gallery-filter-menu.text-uppercase button { + text-transform: uppercase; } + +.ltn__tab-menu-3 a, +.ltn__tab-menu-2 a { + background-color: transparent; + border-bottom: 2px solid transparent; + position: relative; } + .ltn__tab-menu-3 a.active, + .ltn__tab-menu-2 a.active { + color: var(--ltn__secondary-color); + background-color: transparent; + border-color: var(--ltn__secondary-color); } + .ltn__tab-menu-3 a::before, + .ltn__tab-menu-2 a::before { + position: absolute; + content: ""; + right: -5px; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + height: 16px; + width: 2px; + background-color: var(--ltn__color-1); + opacity: 0.4; } + .ltn__tab-menu-3 a:last-child::before, + .ltn__tab-menu-2 a:last-child::before { + display: none; } + +.ltn__tab-menu-3 a { + padding: 0px 0px; + margin-right: 40px; } + .ltn__tab-menu-3 a.active { + color: var(--ltn__heading-color); + background-color: transparent; + border-color: var(--ltn__secondary-color); } + .ltn__tab-menu-3 a::before { + display: none; } + +.ltn__gallery-menu-2 .ltn__gallery-filter-menu button { + background-color: transparent; + padding: 0px 0px; + margin-right: 40px; + border-bottom: 2px solid; + border-color: transparent; + font-weight: 400; } + .ltn__gallery-menu-2 .ltn__gallery-filter-menu button.active { + color: var(--ltn__heading-color); + background-color: transparent; + border-color: var(--ltn__secondary-color); } + .ltn__gallery-menu-2 .ltn__gallery-filter-menu button::before { + display: none; } + +@media (max-width: 991px) { + .ltn__gallery-filter-menu button, + .ltn__tab-menu a { + padding: 15px 25px; + font-size: 14px; } + .ltn__tab-menu-top-right { + position: initial; } + .ltn__tab-menu-3 a { + padding: 0px 0px; + margin-right: 30px; } } + +/* ---------------------------------------------------- + Product Details +---------------------------------------------------- */ +.ltn__small-product-item { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + padding: 30px 25px; + border: 2px solid; + border-color: var(--border-color-1); + margin-bottom: 30px; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__small-product-item:hover { + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); + border-color: transparent; } + .ltn__small-product-item .product-price { + color: var(--ltn__secondary-color); } + +.small-product-item-img { + max-width: 90px; + margin-right: 20px; } + +/* ---------------------------------------------------- + Product Details +---------------------------------------------------- */ +.product-meta-date input[type="date"] { + border: 1px solid #ddd; + height: 63px; + padding: 0 15px; + line-height: 50px; } + +.product-meta-date input[type="date"]::-webkit-input-placeholder { + /* Chrome/Opera/Safari */ + color: pink; + line-height: 50px; } + +.product-meta-date input[type="date"]::-moz-placeholder { + /* Firefox 19+ */ + color: pink; + line-height: 50px; } + +.product-meta-date input[type="date"]:-ms-input-placeholder { + /* IE 10+ */ + color: pink; + line-height: 50px; } + +.product-meta-date input[type="date"]:-moz-placeholder { + /* Firefox 18- */ + color: pink; + line-height: 50px; } + +/* ltn__shop-details-img-gallery */ +.ltn__shop-details-img-gallery { + margin-bottom: 35px; } + .ltn__shop-details-img-gallery img { + background-color: var(--white-8); } + +.ltn__shop-details-small-img { + margin-top: 20px; + margin-left: -5px; + margin-right: -5px; } + .ltn__shop-details-small-img .single-small-img { + padding: 0 5px; } + .ltn__shop-details-small-img .single-small-img.slick-current img { + border: 1px solid var(--ltn__secondary-color); + margin-bottom: 10px; } + +.ltn__shop-details-small-img.slick-arrow-2 { + margin-bottom: 35px; } + .ltn__shop-details-small-img.slick-arrow-2 .slick-arrow { + left: 5px; + bottom: -35px; } + .ltn__shop-details-small-img.slick-arrow-2 .slick-next { + left: 45px; } + +.ltn__shop-details-img-gallery-2 .ltn__shop-details-small-img { + margin-top: 20px; + margin-top: -5px; + margin-bottom: -5px; + width: 118px; + float: left; + margin-right: 10px; } + .ltn__shop-details-img-gallery-2 .ltn__shop-details-small-img .single-small-img { + padding: 5px 0px; } + .ltn__shop-details-img-gallery-2 .ltn__shop-details-small-img .single-small-img.slick-current img { + border: 1px solid var(--ltn__secondary-color); + margin-bottom: 0px; } + +.ltn__shop-details-img-gallery-2 .ltn__shop-details-large-img { + overflow: hidden; } + +.ltn__shop-details-img-gallery-2 .slick-arrow-2 .slick-arrow { + height: 35px; + width: 35px; + line-height: 33px; + border: 1px solid var(--border-color-1); + color: var(--ltn__body-color) !important; } + +.ltn__shop-details-img-gallery-2 .ltn__shop-details-small-img.slick-arrow-2 .slick-next { + left: 55px; } + +/* ltn__shop-details-content-wrap */ +.ltn__shop-details-content-wrap { + padding: 50px 50px 40px; } + +/* ltn__shop-details-tab-area */ +.ltn__shop-details-tab-menu .nav { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + border-bottom: 1px solid; + border-top: 1px solid; + border-color: var(--white-16); + margin-bottom: 30px; } + .ltn__shop-details-tab-menu .nav a { + background-color: var(--black-7); + color: var(--white); + padding: 7px 20px; + font-size: 14px; + -webkit-box-flex: inherit; + -ms-flex: inherit; + flex: inherit; + text-align: center; + font-weight: 400; + margin-right: 5px; } + .ltn__shop-details-tab-menu .nav a:last-child { + margin-right: 0; } + .ltn__shop-details-tab-menu .nav a.active { + background-color: var(--ltn__secondary-color); } + +.ltn__shop-details-tab-content-inner .ltn__comment-reply-area form { + padding: 0; } + +.add-a-review { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + .add-a-review h6 { + margin-bottom: 0; + margin-right: 15px; } + +.ltn__shop-details-tab-inner-2 .ltn__shop-details-tab-menu { + border-bottom: 2px solid var(--border-color-1); } + .ltn__shop-details-tab-inner-2 .ltn__shop-details-tab-menu .nav { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + .ltn__shop-details-tab-inner-2 .ltn__shop-details-tab-menu .nav a { + background-color: transparent; + color: var(--ltn__paragraph-color); + padding: 20px 0px; + margin-right: 50px; + -webkit-box-flex: inherit; + -ms-flex: inherit; + flex: inherit; + text-align: left; + position: relative; } + .ltn__shop-details-tab-inner-2 .ltn__shop-details-tab-menu .nav a::before { + position: absolute; + content: ""; + bottom: -2px; + left: 0; + width: 0%; + height: 2px; + background-color: transparent; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__shop-details-tab-inner-2 .ltn__shop-details-tab-menu .nav a.active { + color: var(--ltn__secondary-color); + background-color: transparent; } + .ltn__shop-details-tab-inner-2 .ltn__shop-details-tab-menu .nav a.active::before { + background-color: var(--ltn__secondary-color); + width: 100%; } + +.ltn__shop-details-tab-inner-2 .ltn__shop-details-tab-content-inner { + border: 0; + padding: 30px 0px 0px; + background-color: transparent; } + .ltn__shop-details-tab-inner-2 .ltn__shop-details-tab-content-inner .ltn__comment-reply-area form { + padding: 30px; } + +/* product-details-menu-1 */ +.ltn__product-details-menu-1 ul li a { + position: relative; + margin-right: 10px; } + .ltn__product-details-menu-1 ul li a::before { + position: absolute; + content: ","; + right: -5px; } + .ltn__product-details-menu-1 ul li a:last-child::before { + display: none; } + +.ltn__product-details-menu-1 ul li strong { + font-weight: 500; } + +.ltn__product-details-menu-1 ul li span { + font-weight: 400; + color: var(--ltn__heading-color); } + +.ltn__product-details-menu-1 .ltn__color-widget ul li a { + width: 15px; + height: 15px; } + +.ltn__product-details-menu-1 .ltn__tagcloud-widget ul li { + margin: 0; } + .ltn__product-details-menu-1 .ltn__tagcloud-widget ul li a { + padding: 3px 10px 1px; } + +/* product-details-menu-2 */ +.ltn__product-details-menu-2 ul { + padding: 0; + margin: 0; } + .ltn__product-details-menu-2 ul li { + list-style: none; + display: inline-block; + margin-right: 10px; } + .ltn__product-details-menu-2 ul li:last-child { + margin-right: 0; } + +/* product-details-menu-3 */ +.ltn__product-details-menu-3 ul { + padding: 0; + margin: 0; } + .ltn__product-details-menu-3 ul li { + list-style: none; + display: inline-block; + margin-right: 20px; + font-size: 14px; + font-weight: 600; } + .ltn__product-details-menu-3 ul li:last-child { + margin-right: 0; } + +.ltn__product-details-menu-4 .d-meta-title { + display: block; } + +/* ---------------------------------------------------- + Product Options +---------------------------------------------------- */ +.nice-select .option { + margin-top: 0; + white-space: normal; + padding-top: 10px; + padding-bottom: 10px; + line-height: 1.8; } + +.nice-select .list { + min-width: 100%; } + +.ltn__shop-options { + margin-bottom: 40px; } + .ltn__shop-options ul { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + margin-bottom: 30px; + margin: 0; + padding: 0; } + .ltn__shop-options ul li { + list-style: none; + margin-top: 0; + line-height: 45px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + .ltn__shop-options .short-by { + margin-right: 20px; + margin-left: 20px; } + .ltn__shop-options .short-by .nice-select { + border-radius: 0; + border: 1px solid var(--white-14); + height: 45px; + line-height: 43px; + min-width: 190px; } + .ltn__shop-options .short-by .nice-select .option { + width: 100%; + padding-left: 10px; + padding-right: 5px; + font-size: 13px; + font-weight: 400; } + .ltn__shop-options .short-by .nice-select .current { + font-weight: 500; } + +.ltn__grid-list-tab-menu a { + font-size: 20px; + margin-right: 20px; + width: 45px; + height: 45px; + line-height: 43px; + text-align: center; + border: 1px solid var(--white-14); + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } + .ltn__grid-list-tab-menu a:last-child { + margin-right: 0; } + +.ltn__grid-list-tab-menu .active { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +.showing-product-number span { + font-weight: 500; + font-size: 16px; + font-family: var(--ltn__heading-font); } + +.ltn__product-list-view .product-title { + font-size: 22px; + margin-bottom: 10px; } + +.ltn__product-list-view .ltn__product-item:after { + display: block; + clear: both; + content: ""; } + +.ltn__product-list-view .ltn__product-item .product-img { + max-width: 45%; + float: left; } + +.ltn__product-list-view .ltn__product-item .product-info { + overflow: hidden; + padding: 0 0 0 30px; } + +.ltn__product-list-view .ltn__product-item-3 .product-info { + overflow: hidden; + padding: 25px 25px 20px 30px; } + +.ltn__product-list-view .product-brief { + margin-top: 20px; + margin-bottom: 30px; } + +.ltn__product-list-view .product-hover-action-2 ul { + display: inline-block; } + +.ltn__product-list-view .product-hover-action { + position: inherit; + -webkit-transform: inherit; + -ms-transform: inherit; + transform: inherit; + text-align: left; + opacity: 1; + visibility: visible; + margin-top: 15px; } + +/* Bootstrap Tab with Slider Issue Fix Start */ +.tab-content { + width: 100%; } + +.tab-content .tab-pane { + display: block; + height: 0; + max-width: 100%; + visibility: hidden; + overflow: hidden; + opacity: 0; } + +.tab-content .tab-pane.active { + height: auto; + visibility: visible; + opacity: 1; + overflow: visible; } + +/* Bootstrap Tab with Slider Issue Fix End */ +@media (max-width: 1400px) { + .shop-details-info .product-price { + font-size: 26px; } + .shop-details-info .cart-plus-minus { + width: 130px; } } + +@media (max-width: 991px) { + .ltn__product-item-3 .product-info { + padding: 25px 15px 15px; } + .ltn__product-item-3 .product-price { + font-size: 16px; } + .ltn__shop-details-img-gallery { + margin-bottom: 75px; } + .mini-cart-footer .btn-wrapper .btn { + padding: 10px 15px; + font-size: 12px; } } + +@media (max-width: 767px) { + .ltn__shop-options ul li { + margin: 5px 0; } + .showing-product-number span { + font-size: 16px; } + .ltn__product-list-view .ltn__product-item .product-img { + max-width: 100%; } + .ltn__product-list-view .ltn__product-item .product-info { + padding: 25px 0 0 1px; } + .ltn__product-list-view .ltn__product-item-3 .product-info { + padding: 25px 25px 20px 30px; } + .modal-product-info h3 { + font-size: 22px; } + .modal-product-info .product-price { + font-size: 20px; } + .ltn__shop-details-tab-menu .nav a { + padding: 15px 15px; + font-size: 14px; } + .ltn__shop-details-tab-content-inner { + padding: 50px 20px 30px; } } + +@media (max-width: 576px) { + .product-title { + font-size: 12px; } + .product-hover-action li { + height: 40px; + width: 30%; + min-width: 40px; + line-height: 40px; } + .product-badge li { + font-size: 12px; + font-weight: 500; + padding: 1px 10px; } + .ltn__product-countdown .ltn__countdown .single h1 { + font-size: 13px; + margin-bottom: 3px; } } + +/* ---------------------------------------------------- + END +---------------------------------------------------- */ +/* ---------------------------------------------- + Gallery Area +---------------------------------------------- */ +.ltn__gallery-item { + margin-bottom: 40px; } + .ltn__gallery-item:hover .ltn__gallery-item-img::before { + opacity: 0.9; + visibility: visible; } + .ltn__gallery-item:hover .ltn__gallery-item-img img { + -webkit-transform: scale(1.1); + -ms-transform: scale(1.1); + transform: scale(1.1); } + .ltn__gallery-item:hover .ltn__gallery-action-icon { + top: 50%; + opacity: 1; + visibility: visible; } + +.ltn__gallery-item-inner { + position: relative; + overflow: hidden; } + .ltn__gallery-item-inner h4 { + margin-bottom: 5px; + font-size: 18px; } + .ltn__gallery-item-inner p { + margin-bottom: 0; + font-size: 14px; } + +.ltn__gallery-item-img { + position: relative; + overflow: hidden; } + .ltn__gallery-item-img::before { + position: absolute; + content: ""; + height: 100%; + width: 100%; + background-color: var(--section-bg-6); + pointer-events: none; + opacity: 0; + visibility: hidden; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + z-index: 1; } + .ltn__gallery-item-img img { + -webkit-transition: all 3.5s ease 0s; + -o-transition: all 3.5s ease 0s; + transition: all 3.5s ease 0s; } + +.ltn__gallery-action-icon { + position: absolute; + top: 45%; + left: 0; + right: 0; + margin: 0 auto; + text-align: center; + font-size: 16px; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + opacity: 0; + visibility: hidden; + -webkit-transition: all 0.5s ease 0s; + -o-transition: all 0.5s ease 0s; + transition: all 0.5s ease 0s; + z-index: 2; } + .ltn__gallery-action-icon i { + width: 50px; + height: 50px; + line-height: 50px; + background-color: var(--ltn__secondary-color); + color: var(--white); + border-radius: 100%; + margin: 3px; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__gallery-action-icon i:hover { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +.ltn__gallery-item-info { + padding: 25px 30px; + position: relative; + z-index: 2; } + +/* Gallery Style 1 */ +.ltn__gallery-style-1 .ltn__gallery-item-info { + border: 1px solid var(--border-color-1); } + +/* Gallery Style 2 */ +.ltn__gallery-style-2 .ltn__gallery-item-info { + position: absolute; + bottom: -30px; + left: 0; + right: 0; + margin: 0 auto; + text-align: center; + background: transparent; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + opacity: 0; + visibility: hidden; } + +.ltn__gallery-style-2 h4, .ltn__gallery-style-2 p { + color: var(--ltn__primary-color); } + +.ltn__gallery-style-2 .ltn__gallery-item:hover .ltn__gallery-item-info { + bottom: 0px; + opacity: 1; + visibility: visible; } + +.ltn__gallery-style-2 .ltn__gallery-item:hover .ltn__gallery-action-icon { + top: 35%; } + +.ltn__gallery-info-hide .ltn__gallery-item-info { + display: none; } + +.ltn__gallery-info-hide .ltn__gallery-item:hover .ltn__gallery-action-icon { + top: 50%; } + +/* Lightcase Default CSS */ +.lightcase-error { + color: var(--white); } + +#lightcase-info { + color: var(--ltn__color-1); } + +#lightcase-caption { + color: var(--white); } + +/* ---------------------------------------------------- + END +---------------------------------------------------- */ +/* ============================================================ +>>> TABLE OF CONTENTS: +=============================================================== +# Common CSS +# Section title +# Category Area +# Feature Area +# Countdown Area +# Blog Area +# Blog Details +# Service Details +# Pagination +# Testimonial +# Banner Area +# Team Area +# CounterUp Area +# Contact Form Area +# Cart Table Area +# Cart plus minus +# Product Details +# Shoping Cart +# Custom Content +# Newsletter +# Faq Area +# 404 Area +# Coming Soon Area +# Screenshot Area +# Pricing List Area +# Checkbox +# Body Sidebar Icons +# About Us Area +# Why Choose Us Area +# Service Area +# Call To Action +# Elements Area +# Service Form +# Get A Quote Form +# Car Dealer Form +# Video Area +# Brand Logo +# Progress Bar +# Our Journey Area +# Google Map Locations Area +# Team Details +# Our History Area +# Appointment Form Area +# Checkout Page +# Myaccount Page +# Time Schedule Area + +============================================================= */ +/* ---------------------------------------------------- + Common CSS +---------------------------------------------------- */ +.ltn__social-media ul { + margin: 0; + padding: 0; } + .ltn__social-media ul li { + list-style: none; + display: inline-block; + margin: 0 15px 0 0; } + .ltn__social-media ul li:last-child { + margin: 0; } + +.ltn__social-media-2 ul { + margin: 0; + padding: 0; } + .ltn__social-media-2 ul li { + list-style: none; + display: inline-block; + margin-right: 10px; } + .ltn__social-media-2 ul li a { + background-color: var(--section-bg-1); + color: var(--ltn__paragraph-color); + display: block; + width: 40px; + height: 40px; + line-height: 40px; + text-align: center; } + .ltn__social-media-2 ul li a i { + color: inherit; } + .ltn__social-media-2 ul li:last-child { + margin-right: 0; } + .ltn__social-media-2 ul li:hover a { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +.ltn__social-media-3 ul { + margin: 0; + padding: 0; } + .ltn__social-media-3 ul li { + list-style: none; + display: inline-block; + margin-right: 10px; } + .ltn__social-media-3 ul li a { + background-color: var(--white); + color: var(--ltn__paragraph-color); + border: 2px solid var(--border-color-11); + display: block; + width: 50px; + height: 50px; + line-height: 46px; + text-align: center; } + .ltn__social-media-3 ul li a i { + color: inherit; } + .ltn__social-media-3 ul li:last-child { + margin-right: 0; } + .ltn__social-media-3 ul li:hover a { + background-color: var(--ltn__secondary-color); + border-color: var(--ltn__secondary-color); + color: var(--white); } + +.bg-image { + background-size: cover; + background-position: center center; + background-repeat: no-repeat; } + +.bg-image-top { + background-size: auto; + background-position: top center; + background-repeat: no-repeat; } + +.bg-image-right { + background-size: 45%; + background-position: right center; + background-repeat: no-repeat; } + +.nice-select .option { + font-weight: 400; } + +/* small mobile :320px. */ +@media (max-width: 1200px) { + .bg-image-right { + background-blend-mode: overlay; } } + +@media (max-width: 991px) { + .bg-image-top { + background-size: inherit; } } + +.ltn__social-media-4 ul { + margin: 0; + padding: 0; } + .ltn__social-media-4 ul li { + list-style: none; + display: inline-block; + margin-right: 10px; } + .ltn__social-media-4 ul li a { + background-color: var(--ltn__primary-color-3); + color: var(--white); + display: block; + width: 50px; + height: 50px; + line-height: 50px; + text-align: center; + border-radius: 100%; } + .ltn__social-media-4 ul li:last-child { + margin-right: 0; } + .ltn__social-media-4 ul li:hover a { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +/* ---------------------------------------- + Section title +---------------------------------------- */ +.section-title-area { + margin-bottom: 60px; } + .section-title-area p { + margin-bottom: 0; + max-width: 500px; } + .section-title-area p + p { + margin-top: 15px; } + .section-title-area.text-right p { + margin-left: auto; } + .section-title-area.text-center p { + margin-left: auto; + margin-right: auto; } + +.section-title { + margin-bottom: 5px; + font-size: 40px; + font-weight: 800; + line-height: 1.2; } + .section-title span { + color: var(--ltn__secondary-color); } + .section-title p { + font-size: 16px; + line-height: 1.8; + color: var(--ltn__paragraph-color); + margin-top: 20px; } + .section-title.white .section-title { + color: var(--white); } + .section-title.white p { + color: rgba(var(--white), 0.7); } + .section-title.section-title-border { + margin-bottom: 15px; } + +.section-title-border { + position: relative; + padding-bottom: 10px; } + .section-title-border::before { + position: absolute; + content: ""; + width: 90px; + height: 2px; + background-color: var(--ltn__secondary-color); + left: 0; + bottom: 0; } + +.text-center .section-title-border::before { + left: 50%; + -webkit-transform: translate(-50%); + -ms-transform: translate(-50%); + transform: translate(-50%); } + +.text-right .section-title-border::before { + left: auto; + right: 0; } + +/* ltn__separate-line */ +.ltn__separate-line { + position: relative; + display: inline-block; + min-width: 200px; + margin-bottom: 3px; + text-align: center !important; } + .ltn__separate-line::before { + position: absolute; + content: ""; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + left: 0; + width: 100%; + height: 1px; + background: -webkit-gradient(linear, left top, right top, from(#f28bc2), color-stop(50%, #d8b1f2)); + background: -webkit-linear-gradient(left, #f28bc2 0%, #d8b1f2 50%); + background: -o-linear-gradient(left, #f28bc2 0%, #d8b1f2 50%); + background: linear-gradient(90deg, #f28bc2 0%, #d8b1f2 50%); } + .ltn__separate-line .separate-icon { + position: relative; + z-index: 1; + background-color: #fff; + padding: 0 15px; } + .ltn__separate-line i { + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + margin: 0 -4px; + color: var(--ltn__secondary-color); } + +/* Section Title 2 */ +.ltn__section-title-2 { + margin-bottom: 40px; } + .ltn__section-title-2 .section-subtitle { + text-transform: uppercase; } + .ltn__section-title-2 .section-title { + font-size: 72px; + font-weight: 700; + margin-bottom: 15px; + line-height: 1; } + .ltn__section-title-2 p { + padding: 0 0 0 30px; + border-width: 0 0 0 2px; + border-style: solid; + border-color: var(--ltn__secondary-color); + max-width: 450px; } + .ltn__section-title-2.text-right p { + padding: 0 30px 0 0; + border-width: 0 2px 0 0; + margin-left: auto; } + .ltn__section-title-2.text-center p { + padding: 0 0 0 30px; + border-width: 0 0 0 2px; + margin-left: auto; + margin-right: auto; + text-align: left !important; } + +/* Section Title 3 */ +.section-title-style-3 { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } + .section-title-style-3 .section-brief-in p { + padding: 0 30px 0 0; + border-width: 0 2px 0 0; + margin-left: auto; + margin-right: 30px; + text-align: right; } + +/* title-2 */ +.title-2 { + margin-bottom: 30px; + font-size: 18px; + font-weight: 500; + position: relative; + padding-bottom: 10px; } + .title-2::before { + position: absolute; + content: ""; + left: 0; + bottom: 0; + width: 290px; + height: 1px; + background-color: var(--white-6); } + +.text-center .title-2::before { + text-align: center; + left: auto; + right: 50%; + -webkit-transform: translate(50%); + -ms-transform: translate(50%); + transform: translate(50%); } + +@media (max-width: 1599px) { + .ltn__section-title-2 .section-title { + font-size: 60px; } } + +@media (max-width: 1399px) { + .ltn__section-title-2 .section-title { + font-size: 56px; } + .section-title-style-3 .section-title { + min-width: 320px; } } + +@media (max-width: 1199px) { + .section-title { + font-size: 30px; } + .ltn__section-title-2 .section-title { + font-size: 50px; } } + +@media (max-width: 991px) { + .section-title { + font-size: 26px; } + .ltn__section-title-2 .section-title { + font-size: 40px; } + .ltn__section-title-2 p { + padding: 0 0 0 15px; } } + +@media (max-width: 767px) { + .section-title { + font-size: 30px; } + .ltn__section-title-2 .section-title { + font-size: 30px; } + .ltn__section-title-2 p { + padding: 0 0 0 15px; } + .section-title-style-3 { + display: block; } + .section-title-style-3 .section-title { + min-width: 100%; } + .section-title-style-3 .section-brief-in p { + padding: 0 0px 0 15px; + border-width: 0 0px 0 2px; + margin-left: 0; + margin-right: 0; + text-align: left; + margin-bottom: 15px; } + .title-2 { + font-size: 22px; } } + +@media (max-width: 575px) { + .section-title { + font-size: 24px; } + .ltn__section-title-2 .section-title { + font-size: 24px; } } + +/* ---------------------------------------------------- + Category Area +---------------------------------------------------- */ +.ltn__category-item { + margin-bottom: 50px; } + +.ltn__category-item-img { + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + +.ltn__category-item-name { + padding: 15px 0 0; } + +.ltn__category-item:hover .ltn__category-item-img { + -webkit-box-shadow: var(--ltn__box-shadow-3); + box-shadow: var(--ltn__box-shadow-3); } + +.ltn__category-item:hover .ltn__category-item-name a { + color: var(--ltn__secondary-color); } + +/* ---------------------------------------------------- + Feature Area +---------------------------------------------------- */ +.ltn__feature-item { + padding: 40px 25px 10px; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + position: relative; } + +.ltn__feature-icon { + margin-bottom: 20px; + font-size: 60px; + line-height: 1; } + +/* feature-item-2 */ +.ltn__feature-item-2 { + padding: 40px 25px 10px; } + .ltn__feature-item-2 .ltn__feature-icon { + margin-bottom: 20px; } + .ltn__feature-item-2 .ltn__feature-icon span { + background: transparent; + height: 100px; + width: 100px; + line-height: 109px; + border-radius: 100%; + position: relative; + -webkit-transition: all 0.5s ease 0s; + -o-transition: all 0.5s ease 0s; + transition: all 0.5s ease 0s; + display: inline-block; + text-align: center; } + .ltn__feature-item-2 .ltn__feature-icon span::before, .ltn__feature-item-2 .ltn__feature-icon span::after { + position: absolute; + content: ""; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + left: 0; + right: 0; + margin: auto; + border-radius: 100%; + -webkit-transition: all 0.8s ease 0s; + -o-transition: all 0.8s ease 0s; + transition: all 0.8s ease 0s; } + .ltn__feature-item-2 .ltn__feature-icon span:before { + height: 0%; + width: 0%; + background: transparent; } + .ltn__feature-item-2 .ltn__feature-icon span:after { + height: 100%; + width: 100%; + border: 1px solid; + border-color: var(--ltn__heading-color); } + .ltn__feature-item-2 .ltn__feature-icon i { + font-size: 26px; + color: var(--ltn__heading-color); + line-height: 1; + -webkit-transition: all 0.5s ease 0s; + -o-transition: all 0.5s ease 0s; + transition: all 0.5s ease 0s; + z-index: 1; + position: relative; } + .ltn__feature-item-2.active-feature .ltn__feature-icon span, .ltn__feature-item-2:hover .ltn__feature-icon span { + color: var(--white); + border-color: transparent; } + .ltn__feature-item-2.active-feature .ltn__feature-icon span:before, .ltn__feature-item-2:hover .ltn__feature-icon span:before { + height: 100%; + width: 100%; + background: -webkit-gradient(linear, left top, right top, from(#ee91cb), color-stop(50%, #d9b0f1)); + background: -webkit-linear-gradient(left, #ee91cb 0%, #d9b0f1 50%); + background: -o-linear-gradient(left, #ee91cb 0%, #d9b0f1 50%); + background: linear-gradient(90deg, #ee91cb 0%, #d9b0f1 50%); } + .ltn__feature-item-2.active-feature .ltn__feature-icon span:after, .ltn__feature-item-2:hover .ltn__feature-icon span:after { + border-color: var(--white); + height: 80%; + width: 80%; } + .ltn__feature-item-2.active-feature .ltn__feature-icon i, .ltn__feature-item-2:hover .ltn__feature-icon i { + color: var(--white); } + .ltn__feature-item-2.active-feature .ltn__feature-info h6, .ltn__feature-item-2:hover .ltn__feature-info h6 { + color: var(--ltn__secondary-color); } + +/* feature-item-3 */ +.ltn__feature-item-3 { + padding: 35px 22px 15px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + border: 2px solid; + border-color: #f4faff; + margin-bottom: 20px; + position: relative; } + .ltn__feature-item-3 h1, .ltn__feature-item-3 h2, .ltn__feature-item-3 h3, .ltn__feature-item-3 h4, .ltn__feature-item-3 h5, .ltn__feature-item-3 h6 { + margin-bottom: 5px; } + .ltn__feature-item-3 .ltn__feature-icon { + margin: 0px 20px 0 0; + font-size: 50px; + color: var(--ltn__secondary-color); + line-height: 1.5; } + .ltn__feature-item-3 p { + font-size: 14px; } + .ltn__feature-item-3::before { + position: absolute; + content: ""; + left: -2px; + top: 50%; + width: 4px; + height: 0%; + background-color: var(--ltn__secondary-color); + -webkit-transition: all 0.5s ease 0s; + -o-transition: all 0.5s ease 0s; + transition: all 0.5s ease 0s; + opacity: 0; + visibility: hidden; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + .ltn__feature-item-3:hover { + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); } + .ltn__feature-item-3:hover::before { + height: 80%; + opacity: 1; + visibility: visible; } + .ltn__feature-item-3.text-right { + -webkit-box-orient: horizontal; + -webkit-box-direction: reverse; + -ms-flex-flow: row-reverse; + flex-flow: row-reverse; } + .ltn__feature-item-3.text-right .ltn__feature-icon { + margin: 0px 0 0 20px; } + .ltn__feature-item-3.text-right::before { + right: -2px; + left: auto; } + +/* feature-item-4 */ +.ltn__feature-item-4 { + padding: 50px 20px 15px; + background-color: var(--white); + margin-bottom: 30px; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + -webkit-box-shadow: var(--ltn__box-shadow-2); + box-shadow: var(--ltn__box-shadow-2); } + .ltn__feature-item-4:hover { + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); } + +/* feature-item-5 */ +.ltn__feature-item-5 { + padding: 70px 30px 25px; + margin-bottom: 30px; } + .ltn__feature-item-5 .ltn__feature-icon { + margin-bottom: 25px; + font-size: 80px; + line-height: 1; } + .ltn__feature-item-5 .ltn__feature-icon img { + max-width: 200px; } + .ltn__feature-item-5 .ltn__feature-icon span { + position: relative; } + .ltn__feature-item-5 .ltn__feature-icon span::before { + position: absolute; + content: "\e942"; + font-family: 'icomoon'; + right: -10px; + top: -10px; + height: 35px; + width: 35px; + line-height: 35px; + background-color: var(--ltn__primary-color); + color: var(--white); + font-size: 14px; + border-radius: 100%; } + .ltn__feature-item-5 .btn-wrapper { + position: absolute; + width: 100%; + left: 0; + bottom: 0; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + opacity: 0; + visibility: hidden; } + .ltn__feature-item-5 .btn-wrapper a { + min-height: 60px; } + .ltn__feature-item-5:hover { + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); } + .ltn__feature-item-5:hover .btn-wrapper { + bottom: -60px; + opacity: 1; + visibility: visible; } + .ltn__feature-item-5.section-bg-2 .ltn__feature-icon { + color: var(--ltn__secondary-color); } + .ltn__feature-item-5.section-bg-2 .ltn__feature-icon i { + color: var(--ltn__secondary-color); } + .ltn__feature-item-5.section-bg-2 .ltn__feature-icon span::before { + background-color: var(--white); + color: var(--ltn__primary-color); } + .ltn__feature-item-5.white-bg .ltn__feature-icon span::before { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +.feature-btn a { + display: block; + padding: 15px 20px; + background-color: #fff; + text-align: center; } + +/* feature-item-6 */ +.ltn__feature-item-6 { + border: 1px solid var(--border-color-8); + margin-bottom: 30px; + padding: 40px 30px 35px; } + .ltn__feature-item-6::before { + position: absolute; + content: ""; + left: 0; + bottom: 0; + width: 0%; + height: 4px; + background-color: var(--ltn__secondary-color); + -webkit-transition: all 0.5s ease 0s; + -o-transition: all 0.5s ease 0s; + transition: all 0.5s ease 0s; + opacity: 0; + visibility: hidden; } + .ltn__feature-item-6 .ltn__feature-icon { + color: var(--ltn__secondary-color); } + .ltn__feature-item-6 .ltn__feature-icon i { + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__feature-item-6 .ltn__feature-info p { + font-size: 14px; } + .ltn__feature-item-6 .ltn__feature-info .ltn__service-btn { + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + color: var(--ltn__color-1); + font-weight: 700; + font-size: 14px; } + .ltn__feature-item-6.active, .ltn__feature-item-6:hover { + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); } + .ltn__feature-item-6.active::before, .ltn__feature-item-6:hover::before { + width: 100%; + opacity: 1; + visibility: visible; } + .ltn__feature-item-6.active .ltn__feature-info .ltn__service-btn, + .ltn__feature-item-6.active .ltn__feature-icon, .ltn__feature-item-6:hover .ltn__feature-info .ltn__service-btn, + .ltn__feature-item-6:hover .ltn__feature-icon { + color: var(--ltn__secondary-color); } + +/* feature-item-7 */ +.ltn__feature-item-7 { + background-color: var(--white); + padding: 38px 30px 10px; + -webkit-box-shadow: var(--ltn__box-shadow-2); + box-shadow: var(--ltn__box-shadow-2); + margin-bottom: 30px; } + .ltn__feature-item-7 .ltn__feature-icon-title { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin-bottom: 15px; } + .ltn__feature-item-7 .ltn__feature-icon { + margin-bottom: 0; + margin-right: 20px; + color: var(--ltn__secondary-color); } + .ltn__feature-item-7 h3 { + margin-bottom: 0; } + +.ltn__feature-item-7-color-white { + background-color: transparent; + border: 1px solid #203336; } + .ltn__feature-item-7-color-white h3, + .ltn__feature-item-7-color-white p { + color: var(--white); } + +/* feature-item-8 */ +.ltn__feature-item-8 { + padding: 40px 30px 15px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + .ltn__feature-item-8 .ltn__feature-icon { + margin-right: 20px; + font-size: 40px; + width: 50px; } + .ltn__feature-item-8 .ltn__feature-info h4 { + margin-bottom: 5px; + font-size: 16px; + font-weight: 400; } + .ltn__feature-item-8 .ltn__feature-info p { + font-size: 14px; + font-family: var(--ltn__heading-font); + color: var(--ltn__body-color); } + +.ltn__feature-item-box-wrap { + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); } + +.ltn__feature-item-box-wrap-2 { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -ms-flex-flow: wrap; + flex-flow: wrap; + -webkit-box-shadow: none; + box-shadow: none; } + .ltn__feature-item-box-wrap-2 .ltn__feature-item-8 { + min-width: 280px; } + +.ltn__border-between-column [class*='col']::before { + position: absolute; + content: ""; + left: 0; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + height: 50%; + width: 1px; + background-color: var(--border-color-1); } + +.ltn__border-between-column [class*='col']:first-child::before { + display: none; } + +@media (max-width: 991px) { + .ltn__feature-item-box-wrap-2 { + -ms-flex-flow: wrap; + flex-flow: wrap; } } + +/* small mobile :320px. */ +@media (max-width: 767px) { + .ltn__feature-item-5 + .btn-wrapper { + margin-bottom: 30px; } + .ltn__feature-item-7 { + padding: 38px 20px 10px; } } + +/* ---------------------------------------------------- + Countdown Area +---------------------------------------------------- */ +.ltn__countdown { + margin-top: 30px; + display: inline-block; + -webkit-box-shadow: var(--ltn__box-shadow-3); + box-shadow: var(--ltn__box-shadow-3); + padding: 25px 40px 5px; } + .ltn__countdown .single { + display: inline-block; + margin-right: 30px; } + .ltn__countdown .single:last-child { + margin-right: 0; } + +/* ltn__countdown-2 */ +.ltn__countdown-2 { + margin-top: 0; + padding: 20px 30px 1px; } + .ltn__countdown-2 .single { + margin-right: 20px; } + .ltn__countdown-2 .single h1 { + font-size: 22px; + margin-bottom: 5px; } + .ltn__countdown-2 .single p { + font-size: 14px; } + +/* ltn__countdown-3 */ +.ltn__countdown-3 { + margin-top: 0; + padding: 20px 30px 1px; + -webkit-box-shadow: none; + box-shadow: none; } + .ltn__countdown-3 .single { + margin-right: 20px; + text-align: center; } + .ltn__countdown-3 .single h1 { + font-size: 24px; + margin-bottom: 5px; + height: 70px; + width: 70px; + line-height: 70px; + background-color: var(--white); + border-radius: 100%; + color: var(--ltn__heading-color); } + .ltn__countdown-3 .single p { + font-size: 20px; + text-transform: uppercase; } + .ltn__countdown-3 .btn-wrapper { + margin-top: 20px; } + +/* ltn__countdown-4 */ +.ltn__countdown-4 { + margin-top: 0; + padding: 0; + -webkit-box-shadow: none; + box-shadow: none; } + .ltn__countdown-4 .single { + margin-right: 20px; + margin-bottom: 25px; + text-align: center; + background-color: var(--ltn__secondary-color); + width: 70px; + height: 70px; + border-radius: 5px; } + .ltn__countdown-4 .single h1 { + font-size: 24px; + font-weight: 600; + margin-bottom: 5px; + margin-top: 10px; + color: var(--white); } + .ltn__countdown-4 .single p { + font-size: 16px; + margin-bottom: 0; + line-height: 1; + color: var(--white); } + .ltn__countdown-4 .btn-wrapper { + margin-top: 20px; } + +.ltn__countdown-4-info { + position: relative; } + .ltn__countdown-4-info .section-title-area { + z-index: 2; + position: relative; } + .ltn__countdown-4-info .section-title { + font-size: 48px; + font-weight: 500; } + .ltn__countdown-4-info .countdown-img { + position: absolute; + top: 50%; + right: -51%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + z-index: 1; } + +@media (min-width: 767px) { + .ltn__countdown-1 { + min-width: 380px; } } + +@media (max-width: 991px) { + .ltn__countdown-3 .single h1 { + font-size: 20px; + height: 50px; + width: 50px; + line-height: 50px; } + .ltn__countdown-3 .single p { + font-size: 14px; } + .ltn__countdown-4-info .section-title { + font-size: 36px; } } + +@media (max-width: 767px) { + .ltn__countdown-4-info .section-title { + font-size: 24px; } } + +/* ---------------------------------------------------- + Blog Area +---------------------------------------------------- */ +.ltn__blog-item { + position: relative; + margin-bottom: 30px; } + +.ltn__blog-img { + position: relative; } + .ltn__blog-img img { + margin-bottom: 0; } + +.ltn__blog-likes { + position: absolute; + bottom: 0; + left: 0; + z-index: 1; } + .ltn__blog-likes ul { + margin: 0; + padding: 0; } + .ltn__blog-likes li { + list-style: none; } + .ltn__blog-likes li a { + height: 70px; + width: 70px; + font-size: 16px; + border-radius: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + background-color: var(--white); + text-align: center; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-flow: column; + flex-flow: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-shadow: var(--ltn__box-shadow-3); + box-shadow: var(--ltn__box-shadow-3); + color: var(--ltn__heading-color); } + .ltn__blog-likes li a i { + font-size: 18px; + margin-bottom: 5px; } + .ltn__blog-likes li a span { + display: inline-block; + line-height: 1; + font-size: 12px; } + +.ltn__blog-brief { + padding: 20px 0 20px; } + +.ltn__blog-title { + margin-bottom: 20px; + font-size: 24px; + font-weight: 500; } + +.blog-title-line { + position: relative; + padding-bottom: 25px; } + .blog-title-line::before { + position: absolute; + content: ""; + left: 0; + bottom: 0; + width: 90px; + height: 3px; + background-color: var(--ltn__secondary-color); } + +.ltn__blog-meta { + margin-bottom: 13px; } + .ltn__blog-meta ul { + padding: 0; + margin: 0; } + .ltn__blog-meta li { + font-weight: 500; + font-family: var(--ltn__heading-font); + display: inline-block; + margin-right: 20px; + position: relative; + font-size: 14px; + margin-top: 0; } + .ltn__blog-meta li:last-child { + margin-right: 0; } + .ltn__blog-meta li i { + margin-right: 5px; + font-size: 16px; } + .ltn__blog-meta li img { + margin-bottom: 0; } + .ltn__blog-meta li.ltn__blog-comment i { + position: relative; + top: 3px; } + +.ltn__blog-tags a { + margin-right: 10px; + position: relative; + display: inline-block; } + .ltn__blog-tags a::before { + position: absolute; + content: ","; + right: -3px; } + .ltn__blog-tags a:last-child::before { + display: none; } + +.ltn__blog-author img { + border-radius: 100%; + margin-right: 10px; + max-width: 30px; + display: inline-block; } + +.ltn__blog-btn { + color: var(--ltn__heading-color); + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + +.ltn__blog-category a { + background-color: var(--ltn__secondary-color); + color: var(--white); + padding: 5px 15px 2px; + margin-bottom: 5px; + margin-right: 5px; + display: inline-block; + text-transform: uppercase; } + .ltn__blog-category a:last-child { + margin-right: 0; } + .ltn__blog-category a:hover { + background-color: var(--ltn__primary-color); + color: var(--white); } + +.ltn__blog-meta-btn { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + .ltn__blog-meta-btn .ltn__blog-meta { + margin-bottom: 0; } + +/* ltn__blog-item-1 */ +.ltn__blog-item-1 .ltn__blog-img img { + border-radius: 0px 0px 0px 35px; } + +.ltn__blog-item-1 .ltn__blog-meta ul li { + position: relative; } + .ltn__blog-item-1 .ltn__blog-meta ul li::before { + position: absolute; + content: ""; + width: 2px; + height: 10px; + top: 50%; + background-color: var(--ltn__primary-color); + right: -15px; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + opacity: 0.2; } + .ltn__blog-item-1 .ltn__blog-meta ul li:last-child::before { + display: none; } + +/* ltn__blog-item-2 */ +.ltn__blog-item-2 { + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__blog-item-2 .ltn__blog-brief { + padding: 30px 20px 30px; } + .ltn__blog-item-2 .ltn__blog-meta li:before { + height: 15px; + width: 2px; + top: 50%; } + .ltn__blog-item-2 .ltn__blog-meta li:before::before { + position: absolute; + content: ""; + right: -15px; + height: 15px; + width: 2px; + background-color: var(--ltn__heading-color); + top: 50%; + bottom: 6px; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + opacity: 0.6; } + .ltn__blog-item-2 .ltn__blog-meta li:before:last-child::before { + display: none; } + .ltn__blog-item-2 .ltn__blog-btn { + opacity: 0; + visibility: hidden; + margin-top: -20px; } + .ltn__blog-item-2:hover { + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); } + .ltn__blog-item-2:hover .ltn__blog-btn { + margin-top: 0; + opacity: 1; + visibility: visible; } + +/* ltn__blog-item-3 */ +/* ltn__blog-item-4 */ +.ltn__blog-item-3 .ltn__blog-brief, +.ltn__blog-item-4 .ltn__blog-brief { + padding: 30px 30px 30px; + margin-left: auto; + margin-right: auto; + background-color: var(--white); + position: relative; } + +.ltn__blog-item-3 .ltn__blog-meta, +.ltn__blog-item-4 .ltn__blog-meta { + margin-bottom: 15px; } + +.ltn__blog-item-3 .ltn__blog-meta-btn, +.ltn__blog-item-4 .ltn__blog-meta-btn { + border-top: 1px solid; + border-color: var(--border-color-1); + padding-top: 20px; } + .ltn__blog-item-3 .ltn__blog-meta-btn .ltn__blog-meta, + .ltn__blog-item-4 .ltn__blog-meta-btn .ltn__blog-meta { + margin-bottom: 0; } + +.ltn__blog-item-3 .ltn__blog-btn, +.ltn__blog-item-4 .ltn__blog-btn { + font-size: 14px; + font-weight: 700; + font-family: var(--ltn__heading-font); + color: var(--ltn__secondary-color); + text-transform: uppercase; } + +/* ltn__blog-item-3 */ +.ltn__blog-item-3 .ltn__blog-brief { + width: calc( 100% - 30px); + -webkit-box-shadow: var(--ltn__box-shadow-4); + box-shadow: var(--ltn__box-shadow-4); } + +.ltn__blog-item-3 .ltn__blog-img + .ltn__blog-brief { + margin-top: -50px; } + +.ltn__blog-item-3-normal .ltn__blog-item-3 { + margin-bottom: 50px; } + .ltn__blog-item-3-normal .ltn__blog-item-3 .ltn__blog-brief { + width: calc( 100%); } + .ltn__blog-item-3-normal .ltn__blog-item-3 .ltn__blog-img + .ltn__blog-brief { + margin-top: 0px; } + +.ltn__blog-item-3 .ltn__blog-img { + overflow: hidden; } + .ltn__blog-item-3 .ltn__blog-img img { + -webkit-transition: all 0.5s ease 0s; + -o-transition: all 0.5s ease 0s; + transition: all 0.5s ease 0s; } + +.ltn__blog-item-3:hover .ltn__blog-img img { + -webkit-transform: scale(1.1); + -ms-transform: scale(1.1); + transform: scale(1.1); } + +/* ltn__blog-item-4 */ +.ltn__blog-item-4 { + border: 2px solid var(--white-9); + margin-top: 1px; } + .ltn__blog-item-4 .ltn__blog-brief { + margin-top: 0; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__blog-item-4 p { + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__blog-item-4::before { + position: absolute; + content: ""; + left: 0; + top: 0; + width: 100%; + height: 0%; + background-color: var(--ltn__primary-color); + opacity: 0; + visibility: hidden; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__blog-item-4:hover::before { + width: 100%; + height: 100%; + opacity: 0.9; + visibility: visible; } + .ltn__blog-item-4:hover .ltn__blog-brief { + background-color: transparent; } + .ltn__blog-item-4:hover .ltn__blog-meta, + .ltn__blog-item-4:hover .ltn__blog-title, + .ltn__blog-item-4:hover p { + color: var(--white); } + +/* ltn__blog-item-5 */ +.ltn__blog-item-5 { + border: 2px solid var(--border-color-11); } + .ltn__blog-item-5 .ltn__blog-brief { + padding: 40px 30px 40px 30px; } + .ltn__blog-item-5 .ltn__blog-meta-btn { + padding-top: 10px; } + .ltn__blog-item-5 .ltn__blog-author { + font-size: 16px; } + .ltn__blog-item-5 .ltn__blog-author img { + max-width: 40px; } + .ltn__blog-item-5 .ltn__blog-btn { + font-size: 14px; + font-weight: 700; + font-family: var(--ltn__body-font); } + +/* blog-item-quote */ +.ltn__blog-item-quote { + border: 0; } + .ltn__blog-item-quote .ltn__blog-meta li { + color: var(--white); } + .ltn__blog-item-quote .ltn__blog-meta li i { + color: var(--white); } + .ltn__blog-item-quote .ltn__blog-meta li:hover a { + color: var(--white-3); } + .ltn__blog-item-quote blockquote { + font-size: 20px; + font-weight: 700; + position: relative; + background-color: transparent; + font-style: normal; + border-left: 0; + border-color: var(--ltn__heading-color); + padding: 60px 0 0; + margin: 0px 0 30px 0px; + color: var(--white); + text-align: left; } + .ltn__blog-item-quote blockquote::before { + position: absolute; + content: "\e94d"; + font-family: 'icomoon'; + font-size: 30px; + left: 0; + right: 0; + top: 0; + -webkit-transform: inherit; + -ms-transform: inherit; + transform: inherit; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__blog-item-quote blockquote a:hover, .ltn__blog-item-quote blockquote:hover { + color: var(--white-3); } + +/* blog-item-6 */ +.ltn__blog-item-6 { + -webkit-box-shadow: var(--ltn__box-shadow-5); + box-shadow: var(--ltn__box-shadow-5); + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__blog-item-6:hover { + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); } + .ltn__blog-item-6 .ltn__blog-brief { + padding: 35px 30px 15px 35px; } + .ltn__blog-item-6 .ltn__blog-title { + font-size: 22px; } + .ltn__blog-item-6 p { + font-size: 14px; } + +/* blog-item-7 */ +.ltn__blog-item-7 { + -webkit-box-shadow: var(--ltn__box-shadow-5); + box-shadow: var(--ltn__box-shadow-5); + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__blog-item-7:hover { + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); } + .ltn__blog-item-7 .ltn__blog-meta li { + color: var(--ltn__secondary-color); } + .ltn__blog-item-7 .ltn__blog-brief { + padding: 30px 30px 30px 35px; } + .ltn__blog-item-7 .ltn__blog-title { + font-size: 18px; + text-transform: uppercase; } + .ltn__blog-item-7 p { + font-size: 18px; + line-height: 28px; } + .ltn__blog-item-7 .ltn__blog-btn { + font-size: 15px; } + +/* blog-list-wrap */ +.ltn__blog-list-wrap .ltn__blog-item { + margin-bottom: 40px; } + +.ltn__blog-list-wrap .ltn__blog-title { + font-size: 40px; + line-height: 1.2; } + +.ltn__blog-list-wrap .ltn__blog-item-5 .ltn__blog-brief { + padding: 50px 40px 50px 45px; } + +.ltn__blog-list-wrap .ltn__blog-item-quote .ltn__blog-meta { + padding-left: 100px; } + +.ltn__blog-list-wrap .ltn__blog-item-quote blockquote { + font-size: 35px; + line-height: 1.2; + padding: 0 0 0 100px; } + .ltn__blog-list-wrap .ltn__blog-item-quote blockquote::before { + font-size: 80px; + left: 0; } + .ltn__blog-list-wrap .ltn__blog-item-quote blockquote a:hover, .ltn__blog-list-wrap .ltn__blog-item-quote blockquote:hover { + color: var(--white-3); } + +@media (min-width: 992px) and (max-width: 1199px) { + .ltn__blog-list-wrap .ltn__blog-title { + font-size: 26px; } + .ltn__blog-list-wrap .ltn__blog-item-quote blockquote { + font-size: 24px; + padding: 0 0 0 80px; } + .ltn__blog-list-wrap .ltn__blog-item-quote blockquote::before { + font-size: 50px; } + .ltn__blog-list-wrap .ltn__blog-item-quote .ltn__blog-meta { + padding-left: 80px; } + .ltn__blog-item-6 .ltn__blog-title { + font-size: 20px; } } + +@media (max-width: 991px) { + .ltn__blog-title { + font-size: 22px; } + .ltn__blog-item-3 .ltn__blog-brief { + width: calc( 100% - 30px); } + .ltn__blog-list-wrap .ltn__blog-title { + font-size: 26px; } + .ltn__blog-list-wrap .ltn__blog-item-quote blockquote { + font-size: 24px; + padding: 0 0 0 0px; } + .ltn__blog-list-wrap .ltn__blog-item-quote blockquote::before { + font-size: 30px; + display: block; + position: relative; + margin-bottom: 10px; } + .ltn__blog-list-wrap .ltn__blog-item-quote .ltn__blog-meta { + padding-left: 0; } } + +@media (max-width: 767px) { + .ltn__blog-title { + font-size: 18px; } + .ltn__blog-meta li { + margin-right: 10px; + font-size: 12px; } + .ltn__blog-list-wrap .ltn__blog-title { + font-size: 22px; } + .ltn__blog-list-wrap .ltn__blog-item-5 .ltn__blog-brief { + padding: 40px 20px 35px 20px; } + .ltn__blog-list-wrap .ltn__blog-item-quote blockquote { + font-size: 20px; + padding: 0 0 0 0px; } + .ltn__blog-list-wrap .ltn__blog-item-quote blockquote::before { + font-size: 30px; + display: block; + position: relative; + margin-bottom: 10px; } + .ltn__blog-list-wrap .ltn__blog-item-quote .ltn__blog-meta { + padding-left: 0; } + .ltn__blog-item-6 .ltn__blog-title { + font-size: 20px; } + .ltn__blog-item-6 .ltn__blog-brief { + padding: 35px 20px 15px 20px; } } + +/* ---------------------------------------------------- + Blog Details +---------------------------------------------------- */ +.ltn__page-details-inner h1, .ltn__page-details-inner h2, .ltn__page-details-inner h3, .ltn__page-details-inner h4, .ltn__page-details-inner h5, .ltn__page-details-inner h6 { + margin-top: 30px; } + +.ltn__page-details-inner p { + margin-top: 1.5em; } + +.ltn__page-details-inner .ltn__blog-title { + margin-top: 0; + font-size: 30px; + margin-bottom: 45px; } + +.ltn__page-details-inner .ltn__blog-img { + margin-bottom: 40px; } + +.ltn__page-details-inner .img-radius img { + border-radius: 0px 0px 0px 35px; } + +.ltn__page-details-inner label { + font-size: 14px; } + +/* blog-details-wrap */ +.ltn__blog-details-wrap .ltn__blog-details-inner { + border: 2px solid var(--white-6); + padding: 35px 40px 20px; + background-color: var(--section-bg-6); } + +blockquote { + font-size: 18px; + font-family: var(--ltn__paragraph-font); + line-height: 1.6; + font-weight: 500; + background-color: var(--section-bg-1); + padding: 30px 40px 30px 35px; + margin: 50px 0 50px 0px; + position: relative; + z-index: 1; + font-style: italic; + border-left: 3px solid var(--ltn__secondary-color); } + blockquote h6 { + font-weight: 500; } + +.ltn__comment-item { + position: relative; } + .ltn__comment-item p { + font-size: 14px; } + +.ltn__commenter-img { + float: left; + margin-right: 30px; + max-width: 80px; } + +.ltn__commenter-img img { + border-radius: 100%; } + +.ltn__commenter-comment { + overflow: hidden; + background-color: var(--white-17); + padding: 30px 30px 5px; } + +.ltn__commenter-comment h6 { + margin-bottom: 0px; + font-size: 16px; + font-weight: 500; } + +.ltn__commenter-comment .comment-date { + margin-bottom: 10px; + display: block; + font-size: 13px; + font-weight: 700; + font-family: var(--ltn__heading-font); + color: var(--ltn__secondary-color); } + +.ltn__comment-inner ul { + margin: 0; + padding: 0; } + +.ltn__comment-inner li { + list-style: none; + padding-top: 30px; + margin-top: 8px; } + +.ltn__comment-inner > ul > li:first-child { + border-top: 0; + padding-top: 0; + margin-top: 0; } + +.ltn__comment-inner ul ul { + margin: 0 0 0 70px; + padding: 0; } + +.ltn__comment-reply-btn { + position: absolute; + padding: 0 13px 0; + border: 1px solid var(--white-6); + display: inline-block; + border-radius: 25px; + font-size: 14px; + font-weight: 600; + height: 35px; + line-height: 33px; + top: 20px; + right: 20px; + background-color: var(--ltn__secondary-color); + color: var(--white); } + .ltn__comment-reply-btn i { + margin-right: 5px; } + .ltn__comment-reply-btn:hover { + border-color: var(--ltn__secondary-color); + background-color: var(--ltn__secondary-color); + color: var(--white); } + +.ltn__comment-reply-area form input[type="text"], +.ltn__comment-reply-area form input[type="email"], +.ltn__comment-reply-area form input[type="password"], +.ltn__comment-reply-area form input[type="submit"], +.ltn__comment-reply-area form textarea { + border-color: var(--white-5); + background-color: var(--white-17); } + +.ltn__comment-reply-area form .btn { + font-weight: 500; } + +.ltn__comment-inner .product-ratting ul { + padding: 0; + margin: 0; } + .ltn__comment-inner .product-ratting ul li { + padding: 0; + border: 0; } + +.ltn__first-letter { + font-size: 70px; + font-weight: 700; + float: left; + background-color: var(--ltn__secondary-color); + color: var(--white); + margin-right: 30px; + line-height: 1; + text-transform: uppercase; + width: 100px; + height: 100px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } + +.ltn__blog-tags-social-media .ltn__social-media, +.ltn__blog-tags-social-media .ltn__tagcloud-widget { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin-top: 20px; } + +.ltn__blog-tags-social-media .ltn__social-media { + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; } + +.ltn__blog-tags-social-media h4 { + margin-bottom: 0px; + font-size: 18px; + font-weight: 500; + margin-right: 10px; } + +.ltn__blog-tags-social-media ul li { + margin-top: 0; } + +.ltn__prev-next-btn { + position: relative; } + .ltn__prev-next-btn .blog-prev { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + .ltn__prev-next-btn .blog-prev-next-img { + max-width: 80px; + margin-right: 20px; } + .ltn__prev-next-btn h6 { + color: var(--ltn__secondary-color); } + .ltn__prev-next-btn .ltn__blog-title { + font-size: 20px; + margin-bottom: 0; + font-weight: 600; } + .ltn__prev-next-btn p { + font-weight: 400; + margin-bottom: 0; } + .ltn__prev-next-btn .blog-next .blog-prev-next-img { + margin-right: 0; + margin-left: 20px; } + +.ltn-author-introducing { + padding: 40px; + border: 2px solid var(--border-color-11); + margin-bottom: 50px; } + .ltn-author-introducing .author-img { + float: left; + max-width: 180px; + margin-right: 40px; } + .ltn-author-introducing .author-info { + overflow: hidden; } + .ltn-author-introducing .author-info h6 { + margin-bottom: 0; + font-size: 14px; + color: var(--ltn__secondary-color); } + .ltn-author-introducing .author-info h1 { + margin-bottom: 10px; } + .ltn-author-introducing .author-info p { + font-size: 14px; + margin-bottom: 0; } + .ltn-author-introducing .author-info p + p { + margin-top: 15px; } + +@media (min-width: 992px) and (max-width: 1199px) { + .ltn-author-introducing .author-img { + max-width: 120px; + margin-right: 30px; } } + +@media (max-width: 991px) { + .ltn__blog-tags-social-media .ltn__social-media { + text-align: left !important; + margin-top: 30px; } } + +@media (max-width: 767px) { + .ltn__page-details-inner .ltn__blog-title { + margin-top: 0; + font-size: 24px; } + .ltn__page-details-inner .ltn__blog-img { + margin-bottom: 40px; } + .ltn__blog-details-wrap { + padding: 50px 20px; } + blockquote { + font-size: 16px; + padding: 70px 20px 40px 20px; } + blockquote::before { + position: initial; + font-size: 60px; + display: block; + line-height: 1; } + .ltn__prev-next-btn .ltn__blog-title { + font-size: 18px; } + .blog-prev { + margin-bottom: 40px; } + .blog-next { + margin-top: 40px; + margin-bottom: 0; } + .ltn-author-introducing { + padding: 40px 20px; } + .ltn-author-introducing .author-img { + max-width: 100px; + margin-right: 0px; + margin-bottom: 30px; } + .ltn-author-introducing .author-info { + overflow: inherit; } + .ltn__commenter-img { + float: inherit; + margin-right: 0; + max-width: 80px; + margin-bottom: 20px; } + .ltn__commenter-comment h6 { + font-size: 18px; } + .ltn__comment-reply-btn { + position: inherit; + font-size: 12px; } + .ltn__comment-inner ul ul { + margin: 0px; } + .ltn__comment-inner li { + margin-top: 30px; } + .ltn__comment-reply-area form { + padding: 50px 20px; } + .ltn__first-letter { + font-size: 40px; + margin-right: 20px; + width: 60px; + height: 60px; } } + +/* ---------------------------------------------------- + Service Details +---------------------------------------------------- */ +.ltn__service-list-menu ul { + padding: 0; } + .ltn__service-list-menu ul li { + display: block; + border-top: 2px solid #f6f6f6; + padding: 18px 0; + margin: 0; + font-weight: 700; + font-family: var(--ltn__heading-font); } + .ltn__service-list-menu ul li:last-child { + border-bottom: 2px solid #f6f6f6; } + .ltn__service-list-menu ul li i { + margin-right: 5px; + color: var(--ltn__secondary-color); } + .ltn__service-list-menu ul li .service-price { + float: right; + text-transform: capitalize; + font-weight: 400; + font-family: var(--ltn__body-font); } + +@media (max-width: 767px) { + .ltn__service-list-menu ul li .service-price { + float: none; + display: block; } } + +/* ---------------------------------------------------- + Pagination +---------------------------------------------------- */ +/* ltn__pagination */ +.ltn__pagination ul { + margin: 0; + padding: 0; } + .ltn__pagination ul li { + list-style: none; + display: inline-block; + margin-right: 10px; } + .ltn__pagination ul li:last-child { + margin-right: 0px; } + .ltn__pagination ul li a { + height: 50px; + width: 50px; + line-height: 46px; + border: 2px solid var(--border-color-11); + text-align: center; + display: block; + font-weight: 700; } + .ltn__pagination ul li:hover a, .ltn__pagination ul li.active a { + background-color: var(--ltn__secondary-color); + border-color: var(--ltn__secondary-color); + color: var(--white); } + +.ltn__pagination-2 ul { + margin: 0; + padding: 0; } + .ltn__pagination-2 ul li { + list-style: none; + display: inline-block; + margin-right: 10px; } + .ltn__pagination-2 ul li:last-child { + margin-right: 0px; } + .ltn__pagination-2 ul li a { + height: 45px; + width: 45px; + line-height: 45px; + border: 0px solid var(--border-color-11); + text-align: center; + display: block; + font-weight: 600; + border-radius: 100%; + background-color: #F6F6F6; + font-size: 13px; } + .ltn__pagination-2 ul li:hover a, .ltn__pagination-2 ul li.active a { + background-color: var(--ltn__secondary-color); + border-color: var(--ltn__secondary-color); + color: var(--white); } + +@media (max-width: 767px) { + .ltn__pagination ul li { + margin-right: 5px; + font-size: 14px; } + .ltn__pagination ul li a { + height: 40px; + width: 40px; + line-height: 36px; } } + +/* ---------------------------------------------------- + Testimonial ( 1, 2, 3, 4, 5, 6, 7 ) +---------------------------------------------------- */ +.ltn__testimonial-item { + max-width: 80%; + margin-left: auto; + margin-right: auto; + padding-bottom: 30px; + margin-bottom: 50px; } + .ltn__testimonial-item .ltn__testimoni-img img { + border-radius: 100%; } + .ltn__testimonial-item.text-center .ltn__testimoni-img { + margin-left: auto; + margin-right: auto; } + .ltn__testimonial-item.text-right .ltn__testimoni-img { + margin-left: auto; + margin-right: 0; } + +.ltn__testimoni-img { + max-width: 120px; + margin-bottom: 30px; } + .ltn__testimoni-img img { + border-radius: 0; } + .ltn__testimoni-img i { + width: 50px; + height: 50px; + line-height: 48px; + border: 1px solid; + border-radius: 100%; + font-size: 18px; } + +/* testimonial-item-2 */ +.ltn__testimonial-item-2 { + max-width: 60%; } + .ltn__testimonial-item-2 .ltn__testimoni-img { + max-width: 85px; + outline: 8px solid; + outline-color: var(--white); + margin-top: 8px; + position: relative; } + .ltn__testimonial-item-2 .ltn__testimoni-img img { + border-radius: 0; + -webkit-box-shadow: var(--ltn__box-shadow-4); + box-shadow: var(--ltn__box-shadow-4); } + .ltn__testimonial-item-2 p { + font-size: 24px; } + .ltn__testimonial-item-2 .ltn__testimoni-info h4 { + font-size: 30px; + margin-bottom: 5px; } + .ltn__testimonial-item-2 .ltn__testimoni-info h6 { + color: var(--ltn__secondary-color); } + +/* testimonial-item-3 */ +.ltn__testimonial-item-3 { + max-width: 100%; + margin-bottom: 20px; } + .ltn__testimonial-item-3 .ltn__testimoni-info { + -webkit-box-shadow: var(--ltn__box-shadow-4); + box-shadow: var(--ltn__box-shadow-4); + width: calc(100% - 40px); + margin: -60px auto 0; + background-color: var(--white); + padding: 25px 30px 30px; + position: relative; + z-index: 9; } + .ltn__testimonial-item-3 .ltn__testimoni-info p { + margin-top: 0; } + .ltn__testimonial-item-3 .ltn__testimoni-info h4 { + margin-bottom: 5px; + margin-top: 0; } + .ltn__testimonial-item-3 .ltn__testimoni-info h6 { + margin-bottom: 5px; + margin-top: 0; + color: var(--ltn__secondary-color); } + .ltn__testimonial-item-3 .ltn__testimoni-info-inner { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + .ltn__testimonial-item-3 .ltn__testimoni-img { + max-width: 60px; + margin-bottom: 0; + margin-right: 15px; } + .ltn__testimonial-item-3 .ltn__testimoni-img img { + border-radius: 0; } + +.ltn__testimoni-bg-icon { + position: absolute; + right: 15px; + bottom: 5px; + z-index: -1; + opacity: 0.1; } + .ltn__testimoni-bg-icon i { + font-size: 110px; + line-height: 1; + color: var(--ltn__color-1); } + +/* testimonial-item-4 */ +.ltn__testimonial-item-4 { + max-width: 100%; + position: relative; + padding: 40px; + background-color: var(--white); + -webkit-box-shadow: var(--ltn__box-shadow-2); + box-shadow: var(--ltn__box-shadow-2); + z-index: 2; } + .ltn__testimonial-item-4 .ltn__testimoni-img { + max-width: 160px; + float: left; + margin-right: 40px; } + .ltn__testimonial-item-4 .ltn__testimoni-img img { + border-radius: 0; } + .ltn__testimonial-item-4 .ltn__testimoni-info { + overflow: hidden; } + .ltn__testimonial-item-4 .ltn__testimoni-info p { + margin-bottom: 15px; } + .ltn__testimonial-item-4 .ltn__testimoni-info h4 { + margin-bottom: 5px; } + .ltn__testimonial-item-4 .ltn__testimoni-info h6 { + margin-bottom: 5px; + color: var(--ltn__secondary-color); } + +/* testimonial-item-5 */ +.ltn__testimonial-slider-4 { + max-width: 45%; + margin-left: auto; + margin-right: auto; + text-align: center; } + +.ltn__testimonial-item-5 .ltn__quote-icon { + font-size: 240px; + position: absolute; + top: -15px; + line-height: 1; + color: var(--white-7); + left: 50%; + -webkit-transform: translateX(-50%); + -ms-transform: translateX(-50%); + transform: translateX(-50%); + z-index: -1; } + +.ltn__testimonial-item-5 .ltn__testimonial-image { + max-width: 85px; + margin-left: auto; + margin-right: auto; + margin-top: 50px; } + .ltn__testimonial-item-5 .ltn__testimonial-image img { + outline: 8px solid #fff; + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); } + +.ltn__testimonial-item-5 .ltn__testimonial-info { + margin-top: 30px; } + .ltn__testimonial-item-5 .ltn__testimonial-info p { + font-size: 24px; } + .ltn__testimonial-item-5 .ltn__testimonial-info h4 { + font-size: 30px; + margin-bottom: 5px; } + .ltn__testimonial-item-5 .ltn__testimonial-info h6 { + color: var(--ltn__secondary-color); } + +.ltn__testimonial-quote-menu { + position: absolute; + top: 0; + width: 100%; + height: 100%; + padding: 0; + margin: 0; } + .ltn__testimonial-quote-menu li { + list-style: none; } + .ltn__testimonial-quote-menu li img { + position: absolute; } + .ltn__testimonial-quote-menu li:nth-child(1) img { + width: 105px; + top: -15%; + left: 0; } + .ltn__testimonial-quote-menu li:nth-child(2) img { + width: 65px; + top: 0; + left: auto; + right: 3%; } + .ltn__testimonial-quote-menu li:nth-child(3) img { + width: 65px; + top: 70%; + left: 10%; } + .ltn__testimonial-quote-menu li:nth-child(4) img { + width: 125px; + top: 60%; + left: auto; + right: 10%; } + .ltn__testimonial-quote-menu li:nth-child(5) img { + width: 75px; + top: 40%; + left: 3%; } + .ltn__testimonial-quote-menu li:nth-child(6) img { + width: 75px; + top: 25%; + left: auto; + right: 15%; } + .ltn__testimonial-quote-menu li:nth-child(7) img { + width: 55px; + top: 20%; + left: 15%; } + .ltn__testimonial-quote-menu li:nth-child(8) img { + width: 55px; + top: 40%; + left: auto; + right: 3%; } + +/* testimonial-item-6 */ +.ltn__testimonial-item-6 { + padding-top: 50px; + margin-bottom: 0; } + .ltn__testimonial-item-6 .ltn__testimoni-img i { + border: 0; + color: var(--ltn__secondary-color); } + .ltn__testimonial-item-6 p { + font-size: 28px; } + +@media (max-width: 991px) { + .ltn__testimonial-item-2 { + max-width: 70%; } + .ltn__testimonial-item-2 p { + font-size: 20px; } + .ltn__testimonial-item-2 .ltn__testimoni-info h4 { + font-size: 24px; } + .ltn__testimonial-slider-4 { + max-width: 70%; } + .ltn__testimonial-item-5 .ltn__testimonial-info p { + font-size: 20px; } + .quote-animated-image { + display: none !important; } } + +@media (max-width: 767px) { + .ltn__testimonial-item-2 { + max-width: 95%; } + .ltn__testimonial-item-2 p { + font-size: 16px; } + .ltn__testimonial-item-2 .ltn__testimoni-info h4 { + font-size: 20px; } + .ltn__testimonial-item-3 .ltn__testimoni-info { + width: calc(100% - 20px); + padding: 25px 20px 30px; } + .ltn__testimonial-item-4 .ltn__testimoni-img { + float: none; } + .ltn__testimonial-slider-4 { + max-width: 95%; } + .ltn__testimonial-item-5 .ltn__testimonial-info p { + font-size: 16px; } } + +/* ---------------------------------------------------- + Banner Area ( style: 2, 3 ) +---------------------------------------------------- */ +.ltn__banner-item { + margin-bottom: 30px; + position: relative; } + +.ltn__banner-img { + overflow: hidden; } + .ltn__banner-img img { + -webkit-transition: all 1.5s ease 0s; + -o-transition: all 1.5s ease 0s; + transition: all 1.5s ease 0s; } + .ltn__banner-img:hover img { + -ms-transform: scale(1.1); + transform: scale(1.1); + -webkit-transform: scale(1.1); } + +.ltn__banner-info h4 { + margin-bottom: 10px; } + +.ltn__banner-style-2 .ltn__banner-info { + padding: 20px 30px; + border: 1px solid; + border-color: var(--border-color-1); } + +.ltn__banner-style-3 .ltn__banner-info { + position: absolute; + left: 35px; + top: 30px; } + +.ltn__banner-style-3 .banner-button { + position: absolute; + bottom: 30px; + left: 30px; } + .ltn__banner-style-3 .banner-button a { + color: var(--ltn__color-1); + padding: 12px 25px; + background-color: rgba(255, 255, 255, 0.1); + display: inline-block; } + .ltn__banner-style-3 .banner-button a:hover { + color: var(--white); } + +/* ---------------------------------------------------- + Team Area +---------------------------------------------------- */ +.ltn__team-item { + margin-bottom: 30px; + border: 1px solid #f1f1f1; + text-align: center; + -webkit-transition: .3s; + -o-transition: .3s; + transition: .3s; } + .ltn__team-item:hover { + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); } + +.team-info { + padding: 25px 15px; } + +/* team-item-2 */ +.ltn__team-item-2 { + position: relative; } + .ltn__team-item-2:before { + position: absolute; + content: ""; + left: 0; + top: 0; + width: 100%; + height: 100%; + background: var(--gradient-color-1); + opacity: 0; + visibility: hidden; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__team-item-2 .team-info { + position: absolute; + width: 100%; + top: 60%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + opacity: 0; + visibility: hidden; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__team-item-2:hover:before { + opacity: 0.7; + visibility: visible; } + .ltn__team-item-2:hover .team-info { + top: 50%; + opacity: 1; + visibility: visible; } + +/* team-item-3 */ +.ltn__team-item-3 { + padding: 45px 20px 25px; + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); + border: 0; + position: relative; } + .ltn__team-item-3 .team-img { + max-width: 180px; + margin-left: auto; + margin-right: auto; } + .ltn__team-item-3 .team-img img { + border-radius: 100%; } + .ltn__team-item-3 h6 { + text-transform: uppercase; } + .ltn__team-item-3 .team-info { + padding: 0; + margin-top: 30px; } + .ltn__team-item-3 .ltn__social-media { + -webkit-transition: .5s; + -o-transition: .5s; + transition: .5s; + position: absolute; + left: 0; + bottom: 0; + background-color: currentColor; + width: 100%; + padding: 10px 20px 20px; + opacity: 0; + visibility: hidden; + border-bottom: 3px solid transparent; } + .ltn__team-item-3:hover { + background-color: var(--ltn__primary-color); } + .ltn__team-item-3:hover h6, + .ltn__team-item-3:hover h4, + .ltn__team-item-3:hover .ltn__social-media ul li { + color: var(--white); } + .ltn__team-item-3:hover .ltn__social-media { + bottom: -25px; + opacity: 1; + visibility: visible; + z-index: 999; + border-bottom-color: var(--ltn__secondary-color); } + +/* team-item-4 */ +.ltn__team-item-4 { + border: none; + position: relative; } + .ltn__team-item-4 h4, + .ltn__team-item-4 h5 { + font-weight: 600; } + .ltn__team-item-4 h6 { + color: var(--ltn__body-color); } + .ltn__team-item-4 .ltn__social-media { + -webkit-transition: .5s; + -o-transition: .5s; + transition: .5s; + position: absolute; + left: 0; + bottom: 0; + background-color: var(--white); + width: 100%; + padding: 10px 20px 20px; + opacity: 0; + visibility: hidden; + border-bottom: 3px solid transparent; } + .ltn__team-item-4:hover { + background-color: var(--white); } + .ltn__team-item-4:hover .ltn__social-media { + bottom: -25px; + opacity: 1; + visibility: visible; + z-index: 999; + border-bottom-color: var(--ltn__secondary-color); } + +@media (max-width: 767px) { + .ltn__team-item-3 { + max-width: 300px; + margin-left: auto; + margin-right: auto; } } + +/* ---------------------------------------------------- + CounterUp Area +---------------------------------------------------- */ +.ltn__counterup-item { + margin-bottom: 50px; + text-align: center; } + .ltn__counterup-item .counter-icon { + margin-bottom: 25px; } + .ltn__counterup-item .counter-icon i { + font-size: 35px; } + .ltn__counterup-item h1 { + font-weight: 700; + font-size: 40px; + color: var(--ltn__secondary-color); } + +/* counterup-item-2 */ +.ltn__counterup-item-2 { + margin-bottom: 50px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; } + .ltn__counterup-item-2 .counter-icon { + margin-bottom: 0; + margin-right: 30px; + text-align: center; } + .ltn__counterup-item-2 .counter-icon i { + font-size: 35px; + height: 65px; + width: 65px; + line-height: 65px; + border: 1px solid; + border-radius: 5px; + color: var(--ltn__color-1); } + .ltn__counterup-item-2 h1, .ltn__counterup-item-2 h6 { + font-weight: 600; + font-size: 36px; + line-height: 1; + margin-bottom: 10px; } + .ltn__counterup-item-2 h6 { + font-size: 20px; } + +/* counterup-item-3 */ +.ltn__counterup-item-3 { + margin-bottom: 50px; } + .ltn__counterup-item-3 .counter-icon { + color: var(--ltn__color-1); } + .ltn__counterup-item-3 h1 { + font-size: 72px; + line-height: 1; + margin-bottom: 5px; } + .ltn__counterup-item-3 .counterUp-icon { + font-size: 30px; } + .ltn__counterup-item-3 h6 { + font-family: var(--ltn__body-font); } + +@media (max-width: 1199px) { + .ltn__counterup-item-3 h1 { + font-size: 56px; } } + +@media (max-width: 767px) { + .ltn__counterup-area .ltn__section-title-2 { + text-align: center; } + .ltn__counterup-item-3 { + text-align: center; } + .ltn__counterup-item-3 h1 { + font-size: 56px; } } + +/* ---------------------------------------------------- + Contact Form Area +---------------------------------------------------- */ +.ltn__contact-address-item { + padding: 40px 30px 10px; + text-align: center; + -webkit-box-shadow: var(--ltn__box-shadow-2); + box-shadow: var(--ltn__box-shadow-2); + margin-bottom: 30px; } + .ltn__contact-address-item i { + background-color: transparent; + color: var(--ltn__heading-color); + height: 60px; + width: 60px; + line-height: 60px; + -webkit-box-shadow: var(--ltn__box-shadow-2); + box-shadow: var(--ltn__box-shadow-2); + text-align: center; + border-radius: 100%; + margin-bottom: 30px; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + display: inline-block; } + .ltn__contact-address-item:hover i { + background-color: var(--ltn__primary-color); + color: var(--white); } + +.ltn__contact-address-item-2 { + padding: 30px 0 10px; + margin-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; } + .ltn__contact-address-item-2 + .ltn__contact-address-item-2 { + border-top: 1px solid; } + +.contact-form-box { + padding: 0; + position: relative; + z-index: 1; } + .contact-form-box input::-webkit-input-placeholder { + color: var(--ltn__color-1); } + .contact-form-box input::-moz-placeholder { + color: var(--ltn__color-1); } + .contact-form-box input:-ms-input-placeholder { + color: var(--ltn__color-1); } + .contact-form-box input:-moz-placeholder { + color: var(--ltn__color-1); } + .contact-form-box textarea { + min-height: 290px; } + .contact-form-box .btn { + font-weight: 500; } + +.contact-form-box-2 input, +.contact-form-box-2 textarea { + border-top: 0; + border-left: 0; + border-right: 0; + padding-left: 0; } + +.google-map { + height: 550px; } + +.ltn__contact-address-item-3 { + -webkit-box-shadow: none; + box-shadow: none; + border: 2px solid var(--border-color-11); + padding: 50px 30px 25px; } + .ltn__contact-address-item-3 i { + font-size: 50px; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; } + .ltn__contact-address-item-3 .ltn__contact-address-icon { + margin-bottom: 35px; } + .ltn__contact-address-item-3 .ltn__contact-address-icon img { + max-width: 80px; } + .ltn__contact-address-item-3:hover i { + background-color: transparent; + color: var(--ltn__secondary-color); } + +.ltn__contact-address-item-4 { + border: none; + -webkit-box-shadow: none; + box-shadow: none; + padding: 0; } + .ltn__contact-address-item-4 i { + height: 110px; + width: 110px; + line-height: 110px; + -webkit-box-shadow: none; + box-shadow: none; + text-align: center; + border-radius: 100%; + margin-bottom: 30px; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + display: inline-block; + font-size: 35px; + border: 1px solid var(--white-18); } + .ltn__contact-address-item-4 h3 { + font-weight: 500; } + .ltn__contact-address-item-4 p { + font-weight: 400; + color: var(--ltn__body-color); } + .ltn__contact-address-item-4:hover i { + background-color: var(--ltn__secondary-color); + border-color: var(--ltn__secondary-color); + color: var(--white); } + +.form-messege .error { + color: var(--red); } + +.form-messege .success { + color: var(--green); } + +@media (max-width: 767px) { + .contact-form-box { + padding: 40px 25px 50px; } } + +/* ---------------------------------------------------- + Cart Table Area +---------------------------------------------------- */ +.table-1 table { + border: 0; + text-transform: uppercase; + font-size: 13px; + width: 100%; } + .table-1 table tr:first-child { + font-weight: 700; + text-transform: uppercase; + background-color: #e5e5e6; } + .table-1 table tr:nth-child(odd) { + background-color: #e5e5e6; } + .table-1 table tr:nth-of-type(even) { + background: #f9f9f9; } + .table-1 table tr th { + font-weight: 700; + text-transform: uppercase; + background-color: #e5e5e6; + border-right: 2px solid #fff; + border-bottom: 2px solid #fff; + padding: 10px 0; + display: table-cell; + line-height: 18px; + text-align: center; + width: 12%; } + .table-1 table tr td { + border-right: 2px solid #fff; + border-bottom: 2px solid #fff; + padding: 10px 0; + display: table-cell; + line-height: 18px; + text-align: center; } + +.mobile-show { + display: none; } + +@media only screen and (max-width: 767px) { + .mobile-none { + display: none; } + .mobile-show { + display: block; } } + +/* ---------------------------------------------------- + Cart plus minus +---------------------------------------------------- */ +.cart-plus-minus { + border: 2px solid; + height: 50px; + line-height: 43px; + width: 120px; + text-align: center; } + +.qtybutton { + height: 100%; + width: 30%; } + +.dec.qtybutton { + float: left; + border-right: 2px solid; } + +.inc.qtybutton { + float: right; + border-left: 2px solid; } + +.cart-plus-minus, +.dec.qtybutton, +.inc.qtybutton { + background-color: var(--white-7); + border-color: var(--white-7); + font-size: 20px; + font-weight: 400; } + +input.cart-plus-minus-box { + background: transparent none repeat scroll 0 0; + -webkit-box-shadow: none; + box-shadow: none; + border: none; + height: 100%; + margin-bottom: 0; + padding: 0; + text-align: center; + width: 40%; + font-weight: 400; } + +/* ---------------------------------------------------- + Product Details +---------------------------------------------------- */ +.product-details-content .product-title { + font-size: 36px; + font-weight: 700; } + +.product-details-content .product-price { + font-size: 24px; + margin-top: 15px; + margin-bottom: 15px; } + +.product-details-content .product-excerpt { + margin-bottom: 30px; } + +.product-details-content .cart-plus-minus { + display: inline-block; + margin-right: 20px; } + +.product-details-content .product-details-cart-btn { + display: inline-block; + margin-top: 0; } + +.product-details-content .product-details-buy-btn .theme-btn-1 { + padding: 10px 100px 9px; } + +/* ---------------------------------------------------- + Shoping Cart +---------------------------------------------------- */ +.table tr:nth-child(odd) { + background-color: #f7f8fa; } + +.table tr:nth-child(even) { + background-color: #fafafa; } + +.shoping-cart-table tbody { + border-bottom: 1px solid #dee2e6; } + +.shoping-cart-table thead th { + vertical-align: middle; + border-bottom: 0; + background-color: #f7f8fa; } + +.shoping-cart-table .table tr { + background-color: transparent; + display: table; + width: 100%; } + +.shoping-cart-table td { + padding: 20px 25px; + vertical-align: middle; } + +.cart-product-image img { + max-width: 100px; } + +.cart-product-remove { + cursor: pointer; } + +.cart-product-remove:hover { + color: var(--ltn__secondary-color); } + +.cart-product-subtotal { + font-weight: 700; } + +.cart-coupon-row { + background-color: #f7f8fa; + text-align: right; } + +.cart-coupon { + text-align: left; } + +.cart-coupon input { + max-width: 250px; + margin-bottom: 0; } + +.submit-button-1 { + padding: 10px 30px; + background-color: var(--ltn__primary-color); + color: var(--white); + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + +.submit-button-1:hover { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +.btn.disabled { + cursor: not-allowed; } + +.shoping-cart-total { + float: right; + max-width: 450px; + width: 100%; } + .shoping-cart-total .table { + margin-bottom: 0; } + .shoping-cart-total .btn-wrapper { + margin-top: 0; } + .shoping-cart-total .btn-wrapper .theme-btn-1 { + display: block; } + +@media (min-width: 768px) and (max-width: 991px) { + .shoping-cart-table td { + padding: 20px 10px; } + .cart-product-image img { + max-width: 80px; } + .cart-product-info h4 { + font-size: 18px; } } + +@media (max-width: 767px) { + .shoping-cart-table thead th { + display: none; } + .shoping-cart-table .table tr { + display: block; + text-align: center; } + .shoping-cart-table td { + display: block; + padding: 20px 15px; } + .cart-product-image { + max-width: 100%; } + .shoping-cart-table .cart-plus-minus { + margin-left: auto; + margin-right: auto; } + .cart-coupon input { + margin-bottom: 20px; } + .shoping-cart-table .table tr:nth-child(even) { + background-color: var(--section-bg-1); } } + +/* ---------------------------------------------------- + Custom Content +---------------------------------------------------- */ +.custom-content-brief h1 { + margin-bottom: 30px; } + +.custom-content-brief .btn-wrapper { + margin-top: 40px; } + +/* ---------------------------------------------------- + Newsletter +---------------------------------------------------- */ +.ltn__newsletter-inner .ltn__form-box { + position: relative; + margin-top: 30px; } + .ltn__newsletter-inner .ltn__form-box input { + margin-bottom: 0; + padding-right: 140px; } + .ltn__newsletter-inner .ltn__form-box button { + margin-top: 0; + position: absolute; + right: 0; + top: 0; + height: 100%; + height: 100%; + -webkit-box-shadow: none; + box-shadow: none; } + +.ltn__newsletter-inner-2 .ltn__form-box input { + border-width: 0px 0px 1px 0px; + padding-right: 140px; } + +.ltn__newsletter-inner-3 .ltn__form-box input { + border-radius: 50px; + padding-left: 30px; } + +.ltn__newsletter-inner-4 h1 { + font-size: 48px; + font-weight: 500; } + +.ltn__newsletter-inner-4 .ltn__form-box input { + border-radius: 50px; } + +.ltn__newsletter-inner-4 .ltn__form-box button { + border-radius: 0px 50px 50px 0px; } + +@media (max-width: 991px) { + .ltn__newsletter-inner-4 h1 { + font-size: 36px; } } + +@media (max-width: 767px) { + .ltn__newsletter-inner-4 h1 { + font-size: 26px; } } + +/* ---------------------------------------------------- + Faq Area +---------------------------------------------------- */ +.ltn__faq-inner .card { + border: none; + border-radius: 0; + margin-bottom: 35px; } + .ltn__faq-inner .card:last-child { + margin-bottom: 0; } + .ltn__faq-inner .card .ltn__card-title { + background-color: var(--section-bg-1); + padding: 22px 15px 22px 40px; + cursor: pointer; + position: relative; + -webkit-transition: .3s; + -o-transition: .3s; + transition: .3s; + font-size: 18px; + margin-bottom: 0; } + .ltn__faq-inner .card .ltn__card-title::before { + position: absolute; + content: "\e604"; + font-family: 'simple-line-icons'; + right: 15px; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + font-size: 20px; } + .ltn__faq-inner .card .ltn__card-title[aria-expanded="true"] { + background-color: var(--ltn__secondary-color); + color: var(--white); } + .ltn__faq-inner .card .ltn__card-title[aria-expanded="true"]:before { + content: "\e607"; } + .ltn__faq-inner .card .card-body { + padding: 20px 0 0 0; } + +/* ltn__faq-inner-2 */ +.ltn__faq-inner-2 .card { + margin: 0 0 -2px 0; + border: 2px solid; + border-color: var(--border-color-10); } + .ltn__faq-inner-2 .card .ltn__card-title { + background-color: transparent; + padding: 20px 60px 20px 40px; } + .ltn__faq-inner-2 .card .ltn__card-title::before { + background-color: var(--section-bg-1); + color: var(--ltn__primary-color); + font-size: 16px; + height: 40px; + width: 40px; + text-align: center; + line-height: 40px; } + .ltn__faq-inner-2 .card .ltn__card-title[aria-expanded="true"] { + background-color: transparent; + color: var(--ltn__primary-color); } + .ltn__faq-inner-2 .card .ltn__card-title[aria-expanded="true"]:before { + color: var(--ltn__secondary-color); } + .ltn__faq-inner-2 .card .card-body { + padding: 15px 40px 25px; } + +@media (max-width: 767px) { + .ltn__faq-inner-2 .card .ltn__card-title { + padding: 20px 60px 20px 20px; + font-size: 16px; } + .ltn__faq-inner-2 .card .card-body { + padding: 15px 20px 25px; } } + +/* ---------------------------------------------------- + 404 Area +---------------------------------------------------- */ +.error-404-inner .btn-wrapper { + margin-top: 50px; } + +.error-404-title { + font-size: 120px; + line-height: 1; + margin-bottom: 40px; } + +/* 404 area 1 */ +.ltn__404-area-1 .error-404-title { + line-height: 1; + color: var(--ltn__secondary-color); + margin-bottom: 10px; } + +.ltn__404-area-1 h2 { + margin-bottom: 20px; } + +/* 404 area 2 */ +.ltn__404-area-2 { + min-height: 90vh; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + .ltn__404-area-2 .error-404-inner { + padding: 150px 0 170px; } + +@media (max-width: 1199px) { + .ltn__404-area-1 .error-404-title { + font-size: 200px; } + .ltn__404-area-1 h2 { + font-size: 30px; } } + +@media (max-width: 991px) { + .ltn__404-area-2 .error-404-inner { + padding: 80px 0 110px; } + .error-404-inner p br { + display: none; } + .error-404-title { + font-size: 80px; } + .ltn__404-area-1 .error-404-title { + font-size: 100px; } + .ltn__404-area-1 h2 { + font-size: 20px; } } + +/* ---------------------------------------------------- + Coming Soon Area +---------------------------------------------------- */ +.ltn__coming-soon-area { + min-height: 100vh; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + text-align: center; } + +.coming-soon-inner { + padding: 120px 0 100px; } + .coming-soon-inner .ltn__countdown { + margin-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + border: 2px solid var(--border-color-1); } + .coming-soon-inner .ltn__countdown .single { + margin-right: 30px; + margin-top: 15px; + margin-bottom: 15px; + min-width: 120px; + padding-top: 15px; } + .coming-soon-inner .btn-wrapper { + margin-top: 50px; } + .coming-soon-inner p { + max-width: 380px; + margin-left: auto; + margin-right: auto; } + .coming-soon-inner .ltn__form-box { + max-width: 550px; + margin-left: auto; + margin-right: auto; } + .coming-soon-inner .ltn__form-box input { + background-color: transparent; + color: var(--ltn__body-color); + border: 2px solid var(--border-color-1); } + .coming-soon-inner .ltn__form-box input[type="text"]::-webkit-input-placeholder, + .coming-soon-inner .ltn__form-box input[type="email"]::-webkit-input-placeholder { + /* Chrome/Opera/Safari */ + color: var(--ltn__body-color); } + +@media (min-width: 767px) and (max-width: 991px) { + .coming-soon-inner .ltn__countdown .single { + min-width: 110px; } } + +@media (max-width: 991px) { + .coming-soon-inner { + padding: 80px 0 110px; } + .coming-soon-inner p br { + display: none; } } + +@media (max-width: 767px) { + .coming-soon-inner .ltn__countdown { + padding: 25px 20px 5px; } + .coming-soon-inner .ltn__countdown .single { + margin-right: 20px; + min-width: 90px; } } + +/* ---------------------------------------------------- + Screenshot Area +---------------------------------------------------- */ +/* img-slide-item-1 */ +.ltn__img-slide-item-1 { + margin: 10px 0 20px 0; + padding: 0 0; } + +.slick-current .ltn__img-slide-item-1 { + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); } + +/* img-slide-item-2 */ +.ltn__img-slide-item-2 { + margin-bottom: 30px; } + +/* img-slide-item-3 */ +.ltn__img-slide-item-3 { + position: relative; + margin-bottom: 85px; } + .ltn__img-slide-item-3 .ltn__img-slide-info { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + padding: 30px 35px; + background-color: white; + position: absolute; + bottom: 0; + width: calc(100% - 60px); + margin-left: auto; + margin-right: auto; + left: 0; + right: 0; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + opacity: 0; + visibility: hidden; + -webkit-box-shadow: var(--ltn__box-shadow-2); + box-shadow: var(--ltn__box-shadow-2); } + .ltn__img-slide-item-3 .ltn__img-slide-info-brief { + padding-right: 20px; } + .ltn__img-slide-item-3 h6 { + margin-bottom: 5px; + color: var(--ltn__secondary-color); } + .ltn__img-slide-item-3 h1 { + margin-bottom: 0; + font-size: 30px; } + .ltn__img-slide-item-3 .btn-wrapper { + margin-top: 0; } + .ltn__img-slide-item-3 .btn-wrapper .btn { + padding: 15px 20px 13px; } + .ltn__img-slide-item-3:hover .ltn__img-slide-info { + bottom: -65px; + opacity: 1; + visibility: visible; } + +.slick-current .ltn__img-slide-item-3 .ltn__img-slide-info { + bottom: -65px; + opacity: 1; + visibility: visible; } + +.ltn__img-slide-item-4 { + position: relative; + margin-bottom: 30px; } + .ltn__img-slide-item-4 .ltn__img-slide-info { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + padding: 30px 35px; + position: absolute; + bottom: 5px; + width: 100%; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + background: var(--gradient-color-3); + opacity: 0; + visibility: hidden; } + .ltn__img-slide-item-4 .ltn__img-slide-info-brief { + padding-right: 20px; } + .ltn__img-slide-item-4 h6 { + margin-bottom: 5px; + color: var(--white); } + .ltn__img-slide-item-4 h1 { + margin-bottom: 0; + font-size: 30px; + color: var(--white); } + .ltn__img-slide-item-4 .btn-wrapper { + margin-top: 0; } + .ltn__img-slide-item-4 .btn-wrapper .btn { + padding: 15px 20px 13px; } + .ltn__img-slide-item-4:hover .ltn__img-slide-info { + bottom: 0; + opacity: 1; + visibility: visible; } + +@media (max-width: 1399px) { + .ltn__img-slide-item-3 .ltn__img-slide-info { + padding: 30px 20px; + width: calc(100% - 30px); } + .ltn__img-slide-item-3 .ltn__img-slide-info-brief { + padding-right: 15px; } + .ltn__img-slide-item-3 h1 { + font-size: 18px; } + .ltn__img-slide-item-3 .btn-wrapper .btn { + padding: 10px 10px 8px; } + .ltn__img-slide-item-4 .ltn__img-slide-info { + padding: 30px 20px; } + .ltn__img-slide-item-4 h1 { + font-size: 18px; } + .ltn__img-slide-item-4 .btn-wrapper .btn { + padding: 10px 10px 8px; } } + +/* ---------------------------------------------------- + Pricing List Area +---------------------------------------------------- */ +.ltn__pricing-plan-item { + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); + margin-bottom: 30px; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + position: relative; + overflow: hidden; } + .ltn__pricing-plan-item .pricing-badge { + color: var(--white); + background-color: var(--ltn__secondary-color); + padding: 4px 20px; + text-transform: uppercase; + font-size: 8px; + line-height: 20px; + font-weight: 700; + letter-spacing: 1px; + display: table; + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + top: 18px; + position: absolute; + right: -28px; + -webkit-transition: all 0.3s ease-in; + -o-transition: all 0.3s ease-in; + transition: all 0.3s ease-in; } + .ltn__pricing-plan-item .pricing-title { + margin: 0; + height: 100px; + line-height: 100px; } + .ltn__pricing-plan-item .pricing-price { + background-color: var(--section-bg-1); + height: 85px; + line-height: 85px; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__pricing-plan-item .pricing-price h2 { + margin-bottom: 0; + line-height: inherit; + font-size: 48px; } + .ltn__pricing-plan-item .pricing-price sup, + .ltn__pricing-plan-item .pricing-price sub { + font-size: 24px; } + .ltn__pricing-plan-item .pricing-price sup { + top: -.9em; } + .ltn__pricing-plan-item .pricing-price sub { + bottom: -.2em; } + .ltn__pricing-plan-item ul { + margin: 35px 0; + padding: 0; } + .ltn__pricing-plan-item ul li { + list-style: none; + font-size: 18px; } + .ltn__pricing-plan-item .btn-wrapper { + padding-bottom: 50px; } + .ltn__pricing-plan-item.active-price, .ltn__pricing-plan-item.active { + -webkit-box-shadow: var(--ltn__box-shadow-6); + box-shadow: var(--ltn__box-shadow-6); + -webkit-transform: scale(1.1); + -ms-transform: scale(1.1); + transform: scale(1.1); + overflow: hidden; + position: relative; } + .ltn__pricing-plan-item.active-price .pricing-price h2, .ltn__pricing-plan-item.active .pricing-price h2 { + color: var(--ltn__secondary-color); } + .ltn__pricing-plan-item.active-price .btn, .ltn__pricing-plan-item.active .btn { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +@media (max-width: 767px) { + .ltn__pricing-plan-item.active-price, .ltn__pricing-plan-item.active { + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); } } + +/* ---------------------------------------------------- + Checkbox +---------------------------------------------------- */ +/* checkbox-item */ +.checkbox-item { + display: block; + position: relative; + padding-left: 30px; + margin-bottom: 0; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + +/* Hide the browser's default checkbox */ +.checkbox-item input { + position: absolute; + opacity: 0; + cursor: pointer; + height: 0; + width: 0; } + +/* Create a custom checkbox */ +.checkbox-item .checkmark { + position: absolute; + top: 3px; + left: 0; + height: 16px; + width: 16px; + background-color: var(--gray); + border: 1px solid; + border-color: var(--ltn__primary-color); } + +/* On mouse-over, add a grey background color */ +.checkbox-item:hover input ~ .checkmark { + background-color: var(--ltn__secondary-color); } + +/* When the checkbox is checked, add a blue background */ +.checkbox-item input:checked ~ .checkmark { + background-color: var(--ltn__primary-color); } + +/* Create the checkmark/indicator (hidden when not checked) */ +.checkbox-item .checkmark:after { + position: absolute; + content: ""; + display: none; } + +/* Show the checkmark when checked */ +.checkbox-item input:checked ~ .checkmark:after { + display: block; } + +/* Style the checkmark/indicator */ +.checkbox-item .checkmark:after { + left: 4px; + top: 0px; + width: 5px; + height: 10px; + border: solid #fff; + border-width: 0 1px 1px 0; + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); } + +/* ---------------------------------------------------- + Body Sidebar Icons +---------------------------------------------------- */ +.body-sidebar-icons { + position: fixed; + top: 50%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + z-index: 9; + -webkit-transition: -webkit-transform .3s ease 1s; + transition: -webkit-transform .3s ease 1s; + -o-transition: transform .3s ease 1s; + transition: transform .3s ease 1s; + transition: transform .3s ease 1s, -webkit-transform .3s ease 1s; + transition: transform .3s ease 1s,-webkit-transform .3s ease 1s; + right: 0; + -webkit-transform: translate3d(100%, -50%, 0); + transform: translate3d(100%, -50%, 0); + -webkit-box-align: end; + -ms-flex-align: end; + align-items: flex-end; + -webkit-transform: translate3d(0, -50%, 0); + transform: translate3d(0, -50%, 0); } + .body-sidebar-icons a { + background-color: #ddd; + text-align: center; + color: #fff; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + width: auto; + height: 40px; + min-width: 40px; + margin: 0; + overflow: hidden; + -webkit-box-orient: horizontal; + -webkit-box-direction: reverse; + -ms-flex-direction: row-reverse; + flex-direction: row-reverse; } + .body-sidebar-icons a i { + width: 40px; + line-height: 40px; + font-size: 14px; + vertical-align: middle; } + .body-sidebar-icons a .icon-name { + white-space: nowrap; + max-width: 0; + padding: 0; + overflow: hidden; + font-size: 14px; + font-weight: 600; + -webkit-transition: padding 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.15), max-width 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.15); + -o-transition: padding 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.15), max-width 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.15); + transition: padding 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.15), max-width 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.15); } + .body-sidebar-icons a.facebook-icon { + background-color: var(--facebook); } + .body-sidebar-icons a.twitter-icon { + background-color: var(--twitter); } + .body-sidebar-icons a.pinterest-icon { + background-color: var(--pinterest); } + .body-sidebar-icons a.instagram-icon { + background-color: var(--instagram); } + .body-sidebar-icons a.dribbble-icon { + background-color: var(--dribbble); } + .body-sidebar-icons a.behance-icon { + background-color: var(--behance); } + .body-sidebar-icons a.google-plus-icon { + background-color: var(--google-plus); } + .body-sidebar-icons a.linkedin-icon { + background-color: var(--linkedin); } + .body-sidebar-icons a.youtube-icon { + background-color: var(--youtube); } + .body-sidebar-icons a.vk-icon { + background-color: var(--vk); } + .body-sidebar-icons a.wechat-icon { + background-color: var(--wechat); } + .body-sidebar-icons a.email-icon { + background-color: var(--email); } + .body-sidebar-icons a:hover { + -webkit-box-shadow: none; + box-shadow: none; } + .body-sidebar-icons a:hover .icon-name { + padding-left: 15px; + max-width: 220px; } + .body-sidebar-icons.left-side { + left: 0; + right: auto; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; } + .body-sidebar-icons.left-side a { + -webkit-box-orient: unset; + -webkit-box-direction: unset; + -ms-flex-direction: unset; + flex-direction: unset; } + .body-sidebar-icons.left-side a:hover { + -webkit-box-shadow: none; + box-shadow: none; } + .body-sidebar-icons.left-side a:hover .icon-name { + padding-right: 15px; + padding-left: 0; } + +/* ---------------------------------------------------- + About Us Area +---------------------------------------------------- */ +.about-us-img-wrap { + position: relative; } + .about-us-img-wrap img { + margin: 0; } + +.about-us-img-info { + width: 310px; + height: 310px; + background-color: var(--white); + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + text-align: center; + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); + position: absolute; + top: 70%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + left: 0; + right: 0; + margin: auto; } + .about-us-img-info h1 { + margin: 0; + font-size: 120px; + line-height: 0.8; + color: var(--ltn__secondary-color); } + .about-us-img-info h1 .counter { + font-size: 120px; + line-height: 0.8; + color: var(--ltn__secondary-color); } + .about-us-img-info h1 span { + font-size: 20px; + color: var(--ltn__heading-color); } + .about-us-img-info h6 { + margin: 0; } + .about-us-img-info h6 span { + font-size: 20px; + color: var(--ltn__secondary-color); } + .about-us-img-info .btn-wrapper { + margin-top: 50px; } + .about-us-img-info .dots-bottom { + height: 25px; + width: 25px; + background-color: var(--ltn__secondary-color); + display: inline-block; + position: absolute; + bottom: -10px; + left: 12px; } + +.about-us-img-info-2 { + width: 190px; + height: 190px; + background-color: var(--ltn__secondary-color); + border: 15px solid; + border-color: var(--white); + bottom: 0; + top: auto; + -webkit-transform: inherit; + -ms-transform: inherit; + transform: inherit; + margin-right: 0; } + .about-us-img-info-2 h1 { + font-size: 50px; + color: var(--white); } + .about-us-img-info-2 h1 .counter { + font-size: 50px; + color: var(--white); } + .about-us-img-info-2 h1 span { + font-size: 20px; + color: var(--white); } + .about-us-img-info-2 h6 { + color: var(--white); } + +.about-us-info-wrap .btn-wrapper { + margin-top: 40px; } + +.about-us-info-wrap hr { + margin-top: 40px; + margin-bottom: 40px; } + +.about-us-info-wrap p { + font-weight: 300; } + +.about-us-info-devide { + display: -webkit-box; + display: -ms-flexbox; + display: flex; } + .about-us-info-devide .list-item-with-icon { + margin-left: 30px; + margin-bottom: 30px; } + +.list-item-with-icon { + min-width: 300px; } + +.about-us-img-info-inner { + width: 100%; + height: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-flow: column; + flex-flow: column; } + +.list-item-with-icon-2 ul, +.list-item-with-icon ul { + padding: 0; + margin: 0; } + .list-item-with-icon-2 ul li, + .list-item-with-icon ul li { + position: relative; + list-style: none; + padding-left: 60px; + font-weight: 700; + margin-bottom: 25px; } + .list-item-with-icon-2 ul li:last-child, + .list-item-with-icon ul li:last-child { + margin-bottom: 0; } + .list-item-with-icon-2 ul li::before, + .list-item-with-icon ul li::before { + position: absolute; + content: "\f00c"; + font-family: 'Font Awesome\ 5 Free'; + font-weight: 900; + left: 0; + top: -5px; + background-color: var(--section-bg-1); + height: 40px; + width: 40px; + line-height: 40px; + text-align: center; + font-size: 12px; + color: var(--ltn__secondary-color); } + +.list-item-with-icon-2 ul li { + padding-left: 30px; + font-weight: 400; + margin-bottom: 0; } + .list-item-with-icon-2 ul li::before { + height: inherit; + line-height: inherit; + width: inherit; + background-color: transparent; + color: var(--ltn__heading-color); + top: 5px; } + +.about-img-left { + margin-right: 30px; } + +.about-img-right { + margin-left: 30px; } + +.ltn__img-shape-left, +.ltn__img-shape-right { + position: relative; } + .ltn__img-shape-left::before, + .ltn__img-shape-right::before { + position: absolute; + content: ""; + left: 0; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + height: 85%; + width: 30px; + background-color: var(--ltn__secondary-color); } + +.ltn__img-shape-left { + padding-left: 30px; } + .ltn__img-shape-left::before { + left: 0; } + +.ltn__img-shape-right { + padding-right: 30px; } + .ltn__img-shape-right::before { + left: auto; + right: 0; } + +.about-call-us { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + .about-call-us .call-us-icon { + font-size: 50px; + margin-right: 20px; + color: var(--ltn__secondary-color); + line-height: 1; } + .about-call-us .call-us-info p { + margin-bottom: 10px; } + .about-call-us .call-us-info h2 { + margin-bottom: 0px; } + +@media (min-width: 992px) and (max-width: 1199px) { + .about-us-info-devide { + display: block; } + .about-us-info-devide .list-item-with-icon { + margin-left: 0; } + .list-item-with-icon { + margin-top: 30px; + margin-bottom: 40px; } } + +@media (max-width: 991px) { + .about-img-left { + margin-right: 0; + margin-bottom: 40px; } + .about-img-right { + margin-left: 0; + margin-bottom: 40px; } } + +@media (max-width: 767px) { + .custom-content-brief { + margin-bottom: 30px; } + .about-us-img-info { + height: 200px; + width: 220px; } + .about-us-img-info h1 .counter { + font-size: 80px; } + .about-us-img-info-2 { + width: 150px; + height: 150px; } + .about-us-img-info-2 h1 .counter { + font-size: 30px; } + .about-us-info-devide { + display: block; } + .about-us-info-devide .list-item-with-icon { + margin-left: 0; } + .list-item-with-icon { + margin-top: 30px; + margin-bottom: 40px; } + .list-item-with-icon { + min-width: 275px; } } + +/* ---------------------------------------------------- + Why Choose Us Area +---------------------------------------------------- */ +.why-choose-us-feature-item { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + margin-bottom: 10px; + max-width: 480px; } + .why-choose-us-feature-item .why-choose-us-feature-icon { + margin-right: 20px; + font-size: 70px; + line-height: 1.2; + color: var(--ltn__secondary-color); + min-width: -webkit-fit-content; + min-width: -moz-fit-content; + min-width: fit-content; } + .why-choose-us-feature-item .why-choose-us-feature-brief h3 { + margin-bottom: 5px; } + +.why-choose-us-img-wrap img { + max-width: 65%; } + +.why-choose-us-img-2 { + margin-top: -15%; } + .why-choose-us-img-2 img { + border: 15px solid var(--white); } + +/* ---------------------------------------------------- + Service Area +---------------------------------------------------- */ +.ltn__service-item-1 { + background-color: var(--white); + margin-bottom: 50px; } + .ltn__service-item-1 .service-item-img { + position: relative; + overflow: hidden; } + .ltn__service-item-1 .service-item-img img { + -webkit-transition: all 0.5s ease 0s; + -o-transition: all 0.5s ease 0s; + transition: all 0.5s ease 0s; } + .ltn__service-item-1 .service-item-icon { + position: absolute; + right: 0; + bottom: 0; + width: 70px; + height: 70px; + background-color: white; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + font-size: 40px; + color: var(--ltn__secondary-color); } + .ltn__service-item-1 .service-item-brief { + padding: 32px 40px 10px; } + .ltn__service-item-1 .service-item-brief h3 { + margin-bottom: 5px; } + .ltn__service-item-1:hover .service-item-img img { + -webkit-transform: scale(1.1); + -ms-transform: scale(1.1); + transform: scale(1.1); } + +.ltn__service-item-2 { + padding: 0px 45px 30px; + margin-bottom: 50px; + margin-top: 35px; } + .ltn__service-item-2 .service-item-icon { + font-size: 80px; + line-height: 1; + top: -35px; + position: relative; + color: var(--ltn__secondary-color); } + .ltn__service-item-2 .service-item-brief { + padding-top: 50px; } + .ltn__service-item-2 .service-item-icon + .service-item-brief { + padding-top: 0; } + .ltn__service-item-2 ul { + margin-bottom: 10px; + padding: 0; } + .ltn__service-item-2 ul li { + list-style: none; + margin-top: 10px; } + .ltn__service-item-2 ul li span { + color: var(--ltn__color-1); } + .ltn__service-item-2 hr { + margin-top: 25px; + margin-bottom: 25px; } + +@media (max-width: 1199px) { + .ltn__service-item-2 { + padding: 0px 30px 30px; } } + +@media (max-width: 767px) { + .ltn__service-item-1 .service-item-brief { + padding: 30px 22px 10px; } } + +/* ---------------------------------------------------- + Call To Action +---------------------------------------------------- */ +/* call-to-action-2 */ +.call-to-action-2 { + background-color: var(--white-3); } + +.call-to-action-inner-2 { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + .call-to-action-inner-2 h2 { + margin: 0; } + .call-to-action-inner-2 .btn-wrapper { + margin-top: 0; } + +/* call-to-action-3 */ +.get-a-free-service-margin { + margin-bottom: -180px; } + +.get-a-free-service-inner { + position: relative; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-shadow: var(--ltn__box-shadow-1); + box-shadow: var(--ltn__box-shadow-1); + padding-right: 80px; + padding-left: 30px; } + .get-a-free-service-inner .call-to-img img { + max-width: 350px; + position: absolute; + left: 35px; + bottom: 0; + z-index: 2; } + .get-a-free-service-inner .call-to-action-inner-content { + position: relative; + z-index: 3; } + +.call-to-circle-1, +.call-to-circle-2 { + height: 265px; + width: 265px; + display: inline-block; + background-color: var(--ltn__secondary-color); + position: absolute; + left: 60px; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + border-radius: 100%; + z-index: 1; } + +.call-to-circle-2 { + height: 80px; + width: 80px; + left: 300px; + top: 10%; + -webkit-transform: inherit; + -ms-transform: inherit; + transform: inherit; + -webkit-animation: wave 8s 0.1s infinite linear; + animation: wave 8s 0.1s infinite linear; } + +.call-to-bg-icon { + position: absolute; + font-size: 220px; + right: 35px; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + z-index: 1; + color: var(--ltn__color-1); + opacity: 0.1; } + +.get-a-free-service-inner .call-to-circle-2 { + -webkit-animation: wave 8s 0.1s infinite linear; + animation: wave 8s 0.1s infinite linear; } + +/* call-to-action-4 */ +.ltn__call-to-action-4 { + position: relative; } + .ltn__call-to-action-4 .call-to-action-inner-4 { + position: relative; + z-index: 99; } + +.ltn__call-to-4-img-1 { + position: absolute; + left: 0; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + max-width: 34%; } + +.ltn__call-to-4-img-2 { + position: absolute; + right: 0; + bottom: 0; + max-width: 27%; } + +/* call-to-action-5 */ +.call-to-action-inner-5 a:hover { + text-decoration: underline; + color: var(--white); } + +/* Device :991px. */ +@media (max-width: 991px) { + .ltn__call-to-4-img-1, + .ltn__call-to-4-img-2 { + display: none; } } + +/* small mobile :320px. */ +@media (max-width: 767px) { + .call-to-action-inner-2 { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-flow: column; + flex-flow: column; } + .call-to-action-inner-2 .btn-wrapper { + margin-top: 15px; } + .get-a-free-service-inner { + display: block; + padding-right: 0; + padding-left: 0px; } + .get-a-free-service-inner .call-to-img { + margin-bottom: 40px; } + .get-a-free-service-inner .call-to-img img { + max-width: 100%; + position: relative; + left: 0; } + .call-to-circle-1, + .call-to-circle-2 { + display: none; } } + +/* ---------------------------------------------------- + Elements Area +---------------------------------------------------- */ +.ltn__elements-area { + background-color: var(--section-bg-1); + padding: 50px 0; + margin: 50px 0; } + +.elements-title-area { + text-align: center; } + +.elements-title-inner { + background-color: var(--white-3); + display: inline-block; + padding: 10px 30px; + outline: 10px solid; + outline-offset: 10px; + outline-color: var(--white-3); + margin: 20px; } + .elements-title-inner p { + margin-bottom: 0; + padding-top: 5px; + border-top: 1px solid #ddd; + margin-top: 5px; } + +.elements-title { + display: inline-block; + margin: 0; } + +/* ---------------------------------------------------- + Service Form +---------------------------------------------------- */ +.ltn__service-form-box { + margin: 0; + padding: 0 30px; } + .ltn__service-form-box > ul { + padding: 0; + margin: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + .ltn__service-form-box > ul > li { + display: inline-block; + margin-right: 20px; + list-style: none; } + .ltn__service-form-box .nice-select { + margin: 0; + height: 60px; + line-height: 58px; + padding-right: 40px; + padding-left: 20px; + border-radius: 0; + min-width: 200px; + font-size: 16px; + font-weight: 700; + font-family: var(--ltn__heading-font); } + .ltn__service-form-box .nice-select:after { + right: 20px; } + .ltn__service-form-box .nice-select UL li { + display: block; } + .ltn__service-form-box input { + margin: 0; } + .ltn__service-form-box input[type="date"] { + margin: 0; + height: 60px; + padding: 0 20px; + border: 1px solid; + font-weight: 700; + font-family: var(--ltn__heading-font); + text-transform: uppercase; } + .ltn__service-form-box .btn-wrapper { + margin: 0; } + +.ltn__service-form-color-white .ltn__service-form-box .nice-select { + background-color: transparent; + border: 2px solid; + border-color: var(--border-color-3); } + .ltn__service-form-color-white .ltn__service-form-box .nice-select .current { + color: var(--white); + text-transform: uppercase; } + .ltn__service-form-color-white .ltn__service-form-box .nice-select::after { + border-bottom: 2px solid; + border-right: 2px solid; + border-color: var(--border-color-3); } + +.ltn__service-form-color-white .ltn__service-form-box input { + background-color: transparent; + color: var(--white); + border-color: var(--border-color-3); + font-weight: 700; + height: 60px; } + +.ltn__service-form-color-white .ltn__service-form-box input[type="date"] { + background-color: transparent; + color: var(--white); } + +.ltn__service-form-color-white .ltn__service-form-box input[type="date"]::-webkit-calendar-picker-indicator { + -webkit-filter: invert(100%); + filter: invert(100%); } + +.ltn__service-form-color-white .ltn__service-form-box input::-webkit-input-placeholder { + /* Chrome/Opera/Safari */ + color: var(--white); } + +.ltn__service-form-color-white .ltn__service-form-box input::-moz-placeholder { + /* Firefox 19+ */ + color: var(--white); } + +.ltn__service-form-color-white .ltn__service-form-box input:-ms-input-placeholder { + /* IE 10+ */ + color: var(--white); } + +.ltn__service-form-color-white .ltn__service-form-box input:-moz-placeholder { + /* Firefox 18- */ + color: var(--white); } + +.ltn__service-form-color-white .input-item-date.ltn__custom-icon::before { + color: var(--white); + top: 50%; } + +.input-item-date { + margin-bottom: 30px; } + .input-item-date input[type="date"] { + background-color: transparent; + border: 2px solid var(--border-color-1); + height: 65px; + width: 100%; + padding: 0 20px; } + .input-item-date input[type="date"]::-webkit-calendar-picker-indicator { + -webkit-filter: invert(0%); + filter: invert(0%); } + +.ltn__service-form-1 .ltn__service-form-brief { + padding-left: 100px; } + +.ltn__service-form-margin { + margin-top: -160px; } + +@media (min-width: 1200px) and (max-width: 1599px) { + .ltn__service-form-box { + padding: 0; } + .ltn__service-form-box .input-item { + max-width: 200px; } } + +@media (max-width: 1199px) { + .ltn__service-form-box > ul { + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } } + +@media (max-width: 767px) { + .ltn__service-form-box > ul { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-flow: column; + flex-flow: column; } } + +@media (max-width: 575px) { + .ltn__service-form-1 .ltn__service-form-brief { + padding-left: 20px; } } + +/* ---------------------------------------------------- + Get A Quote Form +---------------------------------------------------- */ +.get-a-quote-wrap { + padding: 40px 50px 50px; + border: 2px solid; + border-color: var(--border-color-1); } + +.get-a-quote-form { + margin: 0; } + .get-a-quote-form .btn-wrapper { + padding: 0 40px; } + .get-a-quote-form .btn { + width: 100%; } + .get-a-quote-form input::-webkit-input-placeholder { + color: var(--ltn__color-1); } + .get-a-quote-form input::-moz-placeholder { + color: var(--ltn__color-1); } + .get-a-quote-form input:-ms-input-placeholder { + color: var(--ltn__color-1); } + .get-a-quote-form input:-moz-placeholder { + color: var(--ltn__color-1); } + +.input-item .nice-select { + border: 2px solid; + border-color: var(--border-color-1); + border-radius: 0; + font-size: 14px; + font-weight: 400; + height: 65px; + line-height: 60px; + width: 100%; + margin-bottom: 30px; } + .input-item .nice-select .current { + font-weight: 700; } + .input-item .nice-select::after { + display: none; } + .input-item .nice-select::before { + content: "\f063"; + font-size: 14px; + position: absolute; + top: 50%; + right: 20px; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + font-family: 'Font Awesome\ 5 Free'; + font-weight: 900; + color: var(--ltn__secondary-color); } + +.input-item::after { + display: block; + clear: both; + content: ""; } + +@media (max-width: 1199px) { + .get-a-quote-form .btn-wrapper { + padding: 0 0px; } } + +@media (max-width: 767px) { + .get-a-quote-wrap { + padding: 40px 30px 50px; } } + +/* ---------------------------------------------------- + Car Dealer Form +---------------------------------------------------- */ +.ltn__car-dealer-form-tab .ltn__tab-menu { + margin-bottom: 0; } + .ltn__car-dealer-form-tab .ltn__tab-menu .active { + border-color: var(--ltn__secondary-color); + background-color: var(--ltn__secondary-color); + color: var(--white); } + +.ltn__car-dealer-form-tab .tab-content { + padding: 40px; + background-color: var(--section-bg-1); } + +.ltn__car-dealer-form-box .ltn__car-dealer-form-item { + position: relative; + display: inline-block; + margin-bottom: 30px; } + +.ltn__car-dealer-form-box .nice-select { + margin: 0; + height: 60px; + line-height: 58px; + padding-right: 40px; + padding-left: 20px; + border-radius: 0; + min-width: 200px; + font-size: 16px; + font-weight: 700; + font-family: var(--ltn__heading-font); + width: 100%; } + .ltn__car-dealer-form-box .nice-select .list { + width: 100%; + z-index: 99; } + +.ltn__car-dealer-form-box .ltn__custom-icon::before { + display: none; } + +.ltn__car-dealer-form-box .ltn__custom-icon .nice-select::before { + content: "\f063"; + font-family: 'Font Awesome\ 5 Free'; + font-weight: 900; + margin-right: 10px; + color: var(--ltn__secondary-color); } + +.ltn__car-dealer-form-box .ltn__custom-icon.ltn__icon-calendar .nice-select::before { + content: "\f073"; } + +.ltn__car-dealer-form-box .ltn__custom-icon.ltn__icon-car .nice-select::before { + content: "\f1b9"; } + +.ltn__car-dealer-form-box .ltn__custom-icon.ltn__icon-meter .nice-select::before { + content: "\f3fd"; } + +.ltn__car-dealer-form-box .ltn__custom-icon.ltn__icon-ring .nice-select::before { + content: "\f1cd"; } + +.ltn__car-dealer-form-box .ltn__custom-icon.ltn__icon-cog .nice-select::before { + content: "\f013"; } + +.ltn__car-dealer-form-box .ltn__custom-icon.ltn__icon-transgender .nice-select::before { + content: "\f225"; } + +.car-price-filter-range .price_filter .ui-widget-content { + height: 8px; + background-color: var(--white); + margin-top: 20px; } + +.car-price-filter-range .price_filter .ui-state-default:last-child::before { + position: absolute; } + +.car-price-filter-range .price_filter .ui-state-default:last-child::after { + position: absolute; + content: ""; + top: -30px; + left: -5px; + background-image: url("../img/icons/car.png"); + z-index: 99; + width: 125px; + height: 50px; + background-repeat: no-repeat; } + +.car-price-filter-range .price_slider_amount > input[type="text"], +.car-price-filter-range .price_slider_amount > input[type="submit"] { + font-weight: 700; } + +@media (max-width: 767px) { + .ltn__car-dealer-form-tab .tab-content { + padding: 40px 25px; } } + +/* ---------------------------------------------------- + Video Area +---------------------------------------------------- */ +/* car home 3 */ +.ltn__video-popup-margin { + margin-bottom: -180px; } + +/* Service page */ +.ltn__video-popup-margin-2 { + margin-top: -295px; } + +/* ---------------------------------------------------- + Brand Logo +---------------------------------------------------- */ +.ltn__brand-logo-item { + /* + -webkit-filter: grayscale(1); + filter: grayscale(1); + */ + opacity: 1; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + margin: 10px 0; } + .ltn__brand-logo-item img { + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + margin-left: auto; + margin-right: auto; } + .ltn__brand-logo-item:hover { + /* + -webkit-filter: grayscale(0); + filter: grayscale(0); + */ + opacity: 1; } + .ltn__brand-logo-item:hover img { + -webkit-transform: scale(1.1); + -ms-transform: scale(1.1); + transform: scale(1.1); } + +/* ---------------------------------------------------- + Progress Bar +---------------------------------------------------- */ +.ltn__progress-bar-wrap { + margin-bottom: 50px; } + +.ltn__progress-bar-item { + overflow: hidden; + margin-bottom: 10px; } + .ltn__progress-bar-item > p { + font-size: 18px; + font-weight: 700; + margin: 0; } + .ltn__progress-bar-item .progress { + background: #ebeeee none repeat scroll 0 0; + border-radius: 0; + -webkit-box-shadow: none; + box-shadow: none; + font-weight: 400; + height: 3px; + letter-spacing: 1px; + margin-bottom: 15px; + margin-top: 12px; + overflow: visible; + text-transform: uppercase; + position: relative; } + .ltn__progress-bar-item .progress-bar { + background-color: var(--ltn__secondary-color); + -webkit-box-sizing: border-box; + box-sizing: border-box; + color: var(--ltn__secondary-color); + font-size: 11px; + overflow: visible; + height: 7px; + margin-top: -2px; + text-align: left; + position: relative; } + .ltn__progress-bar-item .progress-bar span { + border-radius: 15px; + display: inline-block; + height: 25px; + letter-spacing: 0; + line-height: 24px; + min-width: 25px; + padding: 0 3px; + position: absolute; + right: 0; + text-align: center; + bottom: 15px; + font-size: 18px; + font-weight: 700; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + +@media (max-width: 767px) { + .ltn__progress-bar-item > p { + font-size: 14px; } } + +/* ---------------------------------------------------- + Our Journey Area +---------------------------------------------------- */ +.ltn__our-journey-wrap ul { + margin-left: 0; + padding-left: 0; } + +.ltn__our-journey-wrap > ul { + margin: 0; + padding: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-pack: distribute; + justify-content: space-around; + position: relative; } + .ltn__our-journey-wrap > ul::before { + position: absolute; + content: ""; + background-color: #d13724; + height: 4px; + width: 100%; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } + .ltn__our-journey-wrap > ul li { + list-style: none; + margin: 0; } + .ltn__our-journey-wrap > ul > li { + display: inline-block; + position: relative; + margin: 0 10px; } + .ltn__our-journey-wrap > ul > li:nth-last-child(1) ul, .ltn__our-journey-wrap > ul > li:nth-last-child(2) ul { + left: auto; + right: 0; } + .ltn__our-journey-wrap > ul > li::before { + position: absolute; + content: ""; + top: 15px; + width: 0; + height: 0; + border-left: 15px solid transparent; + border-right: 15px solid transparent; + border-bottom: 15px solid #fff; + left: 0; + right: 0; + margin: auto; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + opacity: 0; + visibility: hidden; } + .ltn__our-journey-wrap > ul > li ul { + position: absolute; + bottom: 100%; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + opacity: 0; + visibility: hidden; } + .ltn__our-journey-wrap > ul > li.active .ltn__journey-icon, .ltn__our-journey-wrap > ul > li:hover .ltn__journey-icon { + background-color: var(--white); + color: var(--ltn__secondary-color); } + .ltn__our-journey-wrap > ul > li.active ul, .ltn__our-journey-wrap > ul > li:hover ul { + opacity: 1; + visibility: visible; } + .ltn__our-journey-wrap > ul > li.active::before, .ltn__our-journey-wrap > ul > li:hover::before { + opacity: 1; + visibility: visible; } + +.ltn__our-journey-wrap .ltn__journey-icon { + font-size: 20px; + font-weight: 700; + padding: 40px; + background-color: var(--ltn__primary-color); + color: var(--white); + display: block; + margin: 30px 0; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + -webkit-box-shadow: var(--ltn__box-shadow-2); + box-shadow: var(--ltn__box-shadow-2); + text-align: center; } + +.ltn__our-journey-wrap .dropdown-menu { + padding: 0; } + +.ltn__journey-history-item-info { + background-color: var(--white); + padding: 20px; + display: block; + width: 550px; + -webkit-box-shadow: var(--ltn__box-shadow-2); + box-shadow: var(--ltn__box-shadow-2); + position: relative; } + .ltn__journey-history-item-info .ltn__journey-history-img { + float: left; + margin-right: 20px; + max-width: 150px; } + .ltn__journey-history-item-info .ltn__journey-history-info { + overflow: hidden; } + .ltn__journey-history-item-info h3 { + margin-bottom: 5px; } + +@media (min-width: 992px) and (max-width: 1199px) { + .ltn__journey-history-item-info { + width: 500px; } } + +@media (max-width: 1199px) { + .ltn__our-journey-wrap .ltn__journey-icon { + font-size: 18px; + padding: 20px; } } + +@media (max-width: 991px) { + .ltn__journey-history-item-info { + width: 350px; } + .ltn__journey-history-item-info .ltn__journey-history-img { + float: none; + margin-bottom: 20px; + max-width: 100px; } } + +@media (max-width: 767px) { + .ltn__our-journey-wrap > ul { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-flow: column; + flex-flow: column; } + .ltn__our-journey-wrap > ul > li ul { + left: 30px; } + .ltn__our-journey-wrap > ul > li:nth-last-child(1) ul, + .ltn__our-journey-wrap > ul > li:nth-last-child(2) ul { + left: 30px; + right: auto; } } + +@media (max-width: 575px) { + .ltn__journey-history-item-info { + width: 250px; } + .ltn__journey-history-item-info .ltn__journey-history-img { + float: none; + margin-bottom: 20px; } } + +/* ---------------------------------------------------- + Google Map Locations Area +---------------------------------------------------- */ +.ltn__google-map-locations-area #gmap { + height: 90vh; } + .ltn__google-map-locations-area #gmap .gm-style .gm-style-iw-c { + padding: 20px; } + +.ltn__map-item { + padding: 30px 25px 35px; + -webkit-box-shadow: var(--ltn__box-shadow-4); + box-shadow: var(--ltn__box-shadow-4); } + .ltn__map-item .ltn__location-name { + border-bottom: 2px solid var(--border-color-1); + margin-bottom: 25px; + color: var(--ltn__secondary-color); } + .ltn__map-item .ltn__location-single-info { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } + .ltn__map-item .ltn__location-single-info i { + margin-right: 10px; + background: var(--ltn__secondary-color); + color: var(--white); + width: 40px; + height: 40px; + line-height: 40px; + text-align: center; } + .ltn__map-item .btn-wrapper { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; } + .ltn__map-item .btn { + padding: 12px 10px; + font-size: 13px; + margin-right: 10px; + font-weight: 500; } + +.ltn__google-map-locations-list-area .ltn__map-item { + margin-bottom: 50px; } + +.ltn__location-search h3 { + float: left; + margin-right: 30px; + margin-bottom: 0; + line-height: 63px; + color: var(--white); } + +.ltn__location-search .input-item { + float: left; + width: 300px; } + +.ltn__location-search form { + padding: 50px 50px 20px; + background-color: var(--ltn__secondary-color); } + +.ltn__state-location-title { + padding: 15px 30px; + background-color: var(--ltn__secondary-color); + color: var(--white); + margin: 50px 0; } + +/* ---------------------------------------------------- + Team Details +---------------------------------------------------- */ +.ltn__team-details-member-info .team-details-img { + margin-bottom: 30px; + max-width: 350px; } + +.ltn__team-details-member-info.text-right .team-details-img { + margin-left: auto; + margin-right: 0; } + +.ltn__team-details-member-info.text-center .team-details-img { + margin-left: auto; + margin-right: auto; } + +.ltn__team-details-member-about ul { + margin: 0; } + .ltn__team-details-member-about ul li { + list-style: none; + display: block; } + .ltn__team-details-member-about ul li strong { + min-width: 120px; + display: inline-block; } + +.ltn__team-details-member-about > ul { + padding: 0; } + +/* ---------------------------------------------------- + Our History Area +---------------------------------------------------- */ +.ltn__our-history-inner .ltn__tab-menu .nav { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + position: relative; } + .ltn__our-history-inner .ltn__tab-menu .nav::before { + position: absolute; + content: ""; + left: 0; + top: 50%; + width: 100%; + height: 2px; + background-color: var(--white-6); + z-index: -1; } + +.ltn__our-history-inner .ltn__tab-menu a { + background-color: var(--white); + border: 2px solid var(--white-6); } + +.ltn__our-history-inner .ltn__tab-menu .active { + border-color: var(--ltn__secondary-color); + background-color: var(--ltn__secondary-color); + color: var(--white); } + +.ltn__history-icon { + position: absolute; + bottom: 40px; + right: 0; + font-size: 160px; + line-height: 1; + color: var(--ltn__secondary-color); } + .ltn__history-icon i { + margin: 0; } + +.ltn__our-history-inner .about-img-left { + padding-right: 70px; } + +.ltn__our-history-inner .about-img-right { + padding-left: 70px; } + +.ltn__our-history-inner-2 .ltn__tab-menu { + margin-bottom: 20px; } + .ltn__our-history-inner-2 .ltn__tab-menu .nav { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + position: relative; } + .ltn__our-history-inner-2 .ltn__tab-menu .nav::before { + display: none; } + .ltn__our-history-inner-2 .ltn__tab-menu a { + background-color: transparent; + border: 2px solid transparent; + font-size: 22px; + padding: 5px 20px; } + .ltn__our-history-inner-2 .ltn__tab-menu .active { + border-color: transparent; + background-color: transparent; + color: var(--ltn__secondary-color); } + +@media (max-width: 767px) { + .ltn__history-icon { + bottom: 10px; + right: 10px; + font-size: 80px; } + .ltn__our-history-inner .about-img-left { + padding-right: 0px; } + .ltn__our-history-inner .about-img-right { + padding-left: 0px; } } + +/* ---------------------------------------------------- + Appointment Form Area +---------------------------------------------------- */ +.ltn__appointment-inner .alert { + border-radius: 0; + padding: 20px 30px; + margin-bottom: 30px; } + +.ltn__appointment-inner .alert-danger { + font-weight: 600; + font-size: 14px; } + +/* ---------------------------------------------------- + Checkout Page +---------------------------------------------------- */ +.ltn__checkout-single-content { + margin-bottom: 30px; } + .ltn__checkout-single-content h5 { + background-color: var(--section-bg-1); + padding: 20px 30px; } + +.ltn__checkout-single-content-info { + padding: 30px; + border: 1px solid var(--border-color-1); } + +.ltn__checkout-payment-method .card { + padding: 20px; + border-radius: 0; } + +.ltn__checkout-payment-method .card:not(:last-of-type) { + border-bottom: 0; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; } + +.ltn__checkout-payment-method .card-body { + padding: 15px 30px; + -webkit-box-shadow: var(--ltn__box-shadow-3); + box-shadow: var(--ltn__box-shadow-3); + margin-top: 15px; + position: relative; } + .ltn__checkout-payment-method .card-body::before { + position: absolute; + top: -3px; + left: 25px; + width: 10px; + height: 10px; + content: ""; + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + background-color: #fff; } + +.ltn__checkout-payment-method .ltn__card-title { + position: relative; + padding-left: 30px; + margin-bottom: 0; } + .ltn__checkout-payment-method .ltn__card-title::before { + position: absolute; + top: 50%; + left: 0; + width: 16px; + height: 16px; + margin-top: 2px; + content: ""; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + border: 1px solid #333; + border-radius: 50%; } + .ltn__checkout-payment-method .ltn__card-title::after { + position: absolute; + top: 50%; + left: 2px; + width: 11px; + height: 11px; + margin-top: 2px; + content: ""; + -webkit-transition: all .5s ease 0s; + -o-transition: all .5s ease 0s; + transition: all .5s ease 0s; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + opacity: 0; + border-radius: 50%; + background-color: #333; } + .ltn__checkout-payment-method .ltn__card-title img { + height: 45px; + margin-left: 10px; } + +.ltn__checkout-payment-method .ltn__card-title[aria-expanded="true"]::after { + opacity: 1; } + +.ltn__checkout-payment-method p { + font-size: 14px; } + .ltn__checkout-payment-method p:last-child { + margin-bottom: 0; } + +/* ---------------------------------------------------- + Myaccount Page +---------------------------------------------------- */ +.ltn__tab-menu-list .nav { + display: block; + margin-right: 30px; + border: 1px solid #eee; } + .ltn__tab-menu-list .nav a { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + padding: 15px 20px; + border-bottom: 1px solid var(--border-color-1); } + .ltn__tab-menu-list .nav a:last-child { + border-bottom: 0; } + .ltn__tab-menu-list .nav a i { + font-size: 14px; } + .ltn__tab-menu-list .nav a.active { + background-color: var(--section-bg-2); + color: var(--white); } + +.ltn__myaccount-tab-content-inner > p { + padding: 20px; + background-color: var(--section-bg-1); } + +/* ---------------------------------------------------- + Time Schedule Area +---------------------------------------------------- */ +.ltn__time-schedule-widget { + padding: 50px 40px; + margin-top: -10px; } + .ltn__time-schedule-widget h3 { + border-bottom: 2px solid rgba(255, 255, 255, 0.1); + padding-bottom: 20px; + margin-bottom: 25px; } + .ltn__time-schedule-widget ul { + padding: 0; + margin: 0; } + .ltn__time-schedule-widget ul li { + display: block; } + .ltn__time-schedule-widget ul li span { + float: right; } + +/* ---------------------------------------------------- + Contact Feature +---------------------------------------------------- */ +.ltn__contact-feature-item { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + padding: 25px 30px 20px; + -webkit-box-shadow: var(--ltn__box-shadow-4); + box-shadow: var(--ltn__box-shadow-4); + margin-bottom: 30px; + background-color: var(--white); } + +.ltn__contact-feature-icon { + font-size: 50px; + margin-right: 20px; + color: var(--ltn__secondary-color); + line-height: 1; + max-width: 50px; } + +.ltn__contact-feature-info .h6, +.ltn__contact-feature-info .h2 { + font-family: var(--ltn__body-font); } + +.ltn__contact-feature-info .h6 { + color: var(--ltn__color-3); } + +@media (max-width: 1400px) { + .ltn__contact-feature-icon { + font-size: 40px; + margin-right: 15px; } + .ltn__contact-feature-info .h6 { + font-size: 14px; } + .ltn__contact-feature-info .h2 { + font-size: 18px; } } + +/* ---------------------------------------------------- + Image Slide (Screenshot) +---------------------------------------------------- */ +.ltn__img-slide-item-4 > a, +.ltn__img-slide-item-3 > a, +.ltn__img-slide-item-2 > a { + display: block; + overflow: hidden; } + +.ltn__img-slide-item-4 img, +.ltn__img-slide-item-3 img, +.ltn__img-slide-item-2 img { + -webkit-transition: all 0.5s ease 0s; + -o-transition: all 0.5s ease 0s; + transition: all 0.5s ease 0s; } + +.ltn__img-slide-item-4:hover img, +.ltn__img-slide-item-3:hover img, +.ltn__img-slide-item-2:hover img { + -webkit-transform: scale(1.1); + -ms-transform: scale(1.1); + transform: scale(1.1); } + +/* ---------------------------------------------------- + Background Video +---------------------------------------------------- */ +/* Video From Local (src="myFolderName/videoName.mp4") */ +#myVideo { + position: absolute; + right: 0; + bottom: 0; + min-width: 100%; + min-height: 100%; } + +/* Video From Link (src="website.com/videoUrl") */ +.video-foreground, +.video-background iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; } + +/* YouTube Video */ +.ltn__youtube-video-background { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + z-index: -99; } + +/* ---------------------------------------------------- + END +---------------------------------------------------- */ +.ltn__testimonial-7-image-slider { + width: 160px; } + .ltn__testimonial-7-image-slider .slick-list { + padding-right: 53px; + padding-top: 25px; + padding-bottom: 15px; + margin-right: -22px; + padding-left: 20px; + border-radius: 50px; } + .ltn__testimonial-7-image-slider .slick-slide { + border-radius: 50%; + overflow: hidden; + position: relative; + z-index: 1; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .ltn__testimonial-7-image-slider .slick-active { + -webkit-transform: scale(1.4); + -ms-transform: scale(1.4); + transform: scale(1.4); + z-index: 9; } + .ltn__testimonial-7-image-slider .slick-current { + -webkit-transform: scale(1.8); + -ms-transform: scale(1.8); + transform: scale(1.8); + z-index: 99; } + .ltn__testimonial-7-image-slider .testimonial-image { + margin-bottom: 25px; } + .ltn__testimonial-7-image-slider .testimonial-image img { + max-width: 85px; + border-radius: 50%; + width: 100%; } + +.testimonial-info { + padding-right: 20px; + margin-top: 20px; } + .testimonial-info p { + font-family: var(--ltn__paragraph-font); + font-weight: 300; + font-size: 18px; } + .testimonial-info h5 { + font-weight: 600; + margin-bottom: 5px; } + .testimonial-info h6 { + font-weight: 500; } + +.text-center .ltn__testimonial-7-image-slider { + width: 220px; + margin-left: auto; + margin-right: auto; } + .text-center .ltn__testimonial-7-image-slider .slick-list { + padding-right: 1px; + padding-top: 25px; + padding-bottom: 15px; + margin-right: -2px; + padding-left: 83px; + border-radius: 50px; + margin-left: -30px; } + .text-center .ltn__testimonial-7-image-slider .slick-slide { + margin-left: 10px; + margin-right: 10px; + -ms-transform: scale(1.4); + transform: scale(1.4); + -webkit-transform: scale(1.4); } + .text-center .ltn__testimonial-7-image-slider .slick-active { + z-index: 9; } + .text-center .ltn__testimonial-7-image-slider .slick-current { + -webkit-transform: scale(1.8); + -ms-transform: scale(1.8); + transform: scale(1.8); + z-index: 99; } + +/* ---------------------------------------------------- + END +---------------------------------------------------- */ +/* ---------------------------------------------------- + Footer Default Style +---------------------------------------------------- */ +.footer-widget .footer-title { + font-size: 14px; + font-weight: 500; + text-transform: uppercase; + margin-bottom: 30px; } + +.footer-widget p, +.footer-widget ul li { + font-size: 14px; } + +.footer-copyright-right ul li, +.footer-copyright-right p, +.footer-copyright-left ul li, +.footer-copyright-left p { + font-size: 12px; + text-transform: uppercase; } + +.section-bg-5 .footer-widget .footer-title { + color: var(--white); } + +.section-bg-5 .footer-widget p, +.section-bg-5 .footer-widget ul li { + color: var(--white-10); } + +.section-bg-5 .footer-copyright-right ul li, +.section-bg-5 .footer-copyright-right p, +.section-bg-5 .footer-copyright-left ul li, +.section-bg-5 .footer-copyright-left p { + color: var(--white-10); } + +/* footer-2 */ +.ltn__footer-2 .footer-widget .footer-title { + font-size: 24px; } + +.ltn__footer-2 .footer-widget p, +.ltn__footer-2 .footer-widget li { + font-size: 16px; } + +.ltn__footer-2 .footer-about-widget .footer-logo { + position: relative; + top: -20px; + margin-bottom: 10px; } + +.ltn__footer-2 .footer-menu ul li { + margin-bottom: 30px; + font-weight: 600; } + +.ltn__footer-2 .footer-widget .ltn__blog-meta li, +.footer-widget .ltn__blog-meta li { + font-size: 14px; } + +/* footer-color-1 */ +.ltn__footer-color-1 p { + color: var(--ltn__color-2); } + .ltn__footer-color-1 p a { + color: var(--white); } + +.ltn__footer-color-1 .ltn__footer-timeline-widget-1 li span { + color: var(--ltn__color-1); } + +.ltn__footer-color-1 .ltn__footer-timeline-widget-1 li:last-child span { + color: var(--white); } + +.ltn__footer-color-1 .footer-menu ul li { + color: var(--ltn__color-2); } + +.ltn__footer-color-1 .ltn__footer-blog-item { + border-color: var(--border-color-6); } + .ltn__footer-color-1 .ltn__footer-blog-item .ltn__blog-meta li { + color: var(--ltn__color-2); } + +.ltn__footer-color-1 .ltn__copyright-area { + background-color: var(--ltn__primary-color-2); } + +.ltn__footer-color-1 .get-support-info h6 { + color: var(--ltn__color-4); } + +.ltn__footer-color-1 .get-support-info h4 { + color: var(--white); } + +.ltn__footer-color-1 .ltn__copyright-menu ul li { + color: var(--white); } + +/* footer-color-2 */ +.ltn__footer-color-2 .ltn__footer-timeline-widget-1 { + background-color: var(--white); } + .ltn__footer-color-2 .ltn__footer-timeline-widget-1 li { + border-color: transparent; } + .ltn__footer-color-2 .ltn__footer-timeline-widget-1 li:last-child span { + color: var(--ltn__secondary-color); } + +.ltn__footer-color-2 .ltn__footer-blog-item { + border-color: var(--border-color-7); } + +.ltn__footer-color-2 .ltn__copyright-area { + background-color: var(--white-4); } + +/*------------------------- + Footer Area +-------------------------*/ +.footer-top-area { + padding-top: 95px; + padding-bottom: 15px; } + +.footer-widget { + margin-bottom: 60px; } + +.footer-logo { + position: relative; + top: -10px; } + +/* ---------------------------------------------------- + Footer About Widget +---------------------------------------------------- */ +/* footer-address */ +.footer-address { + margin-bottom: 10px; } + .footer-address ul { + margin: 0; + padding: 0; } + .footer-address ul li { + list-style: none; + display: block; + margin-top: 0px; } + .footer-address ul li:after { + display: block; + clear: both; + content: ""; } + .footer-address ul li .footer-address-icon { + float: left; + margin-right: 15px; } + .footer-address ul li .footer-address-info { + overflow: hidden; } + .footer-address ul li .footer-address-info p { + margin-bottom: 0; } + +/* ---------------------------------------------------- + Footer Menu Widget +---------------------------------------------------- */ +/* footer-menu */ +.footer-menu ul { + margin: 0; + padding: 0; } + .footer-menu ul li { + list-style: none; + margin-top: 0px; + margin-bottom: 15px; + position: relative; } + .footer-menu ul li a { + position: relative; } + .footer-menu ul li a::before { + position: absolute; + content: "//"; + left: 0; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + -webkit-transition: inherit; + -o-transition: inherit; + transition: inherit; + opacity: 0; + visibility: hidden; + margin-left: -20px; + color: var(--ltn__secondary-color); } + .footer-menu ul li:hover a { + padding-left: 20px; } + .footer-menu ul li:hover a::before { + opacity: 1; + visibility: visible; + margin-left: 0; } + +.footer-menu ul ul { + margin-left: 15px; } + +/* footer-menu-widget-2-column */ +.footer-menu-widget-2-column { + padding-left: 30px; } + .footer-menu-widget-2-column .footer-menu { + width: 50%; + float: left; } + .footer-menu-widget-2-column .footer-menu:nth-child(odd) { + padding-left: 20px; } + .footer-menu-widget-2-column ul { + margin: 0; } + .footer-menu-widget-2-column ul li { + font-weight: 600; } + +/* ---------------------------------------------------- + Footer Newsletter Widget +---------------------------------------------------- */ +.footer-newsletter form { + position: relative; } + +.footer-newsletter input[type="email"] { + margin: 0; + padding-right: 50px; } + +.footer-newsletter .btn-wrapper { + position: absolute; + top: 0; + right: 0; + margin: 0; + height: 100%; } + .footer-newsletter .btn-wrapper .btn { + padding: 0 18px; + height: 100%; } + +/* ---------------------------------------------------- + Footer Timeline Widget +---------------------------------------------------- */ +.ltn__footer-timeline-widget { + padding: 50px 50px 40px; + border-bottom: 5px solid; + border-color: var(--border-color-5); + margin-top: -92px; } + .ltn__footer-timeline-widget .footer-title { + font-size: 36px; } + .ltn__footer-timeline-widget ul { + margin: 0; + padding: 0; } + .ltn__footer-timeline-widget ul li { + list-style: none; + font-family: var(--ltn__heading-font); + font-weight: 700; + border-bottom: 1px solid; + border-color: var(--border-color-6); + padding-bottom: 10px; + margin-top: 10px; } + .ltn__footer-timeline-widget ul li:last-child { + border-bottom: 0; + padding-bottom: 0; } + .ltn__footer-timeline-widget ul li:last-child span { + font-weight: 700; } + .ltn__footer-timeline-widget ul li span { + float: right; + font-weight: 600; } + +/* ---------------------------------------------------- + Footer Blog Widget +---------------------------------------------------- */ +.ltn__footer-blog-item { + border-bottom: 1px solid; + border-color: var(--border-color-6); + margin-bottom: 20px; } + .ltn__footer-blog-item:last-child { + border-bottom: 0; + margin-bottom: 0; } + .ltn__footer-blog-item .ltn__blog-meta { + margin-bottom: 5px; } + .ltn__footer-blog-item .ltn__blog-meta i { + color: var(--ltn__secondary-color); + margin-right: 5px; } + .ltn__footer-blog-item .ltn__blog-title { + font-size: 20px; } + +/* ---------------------------------------------------- + Copyright Area +---------------------------------------------------- */ +.ltn__copyright-area .container-fluid, +.ltn__copyright-area .container { + padding-top: 15px; + padding-bottom: 15px; } + +.ltn__copyright-area .payment-method { + text-align: right; } + +.ltn__copyright-design p { + margin-bottom: 0; } + +.ltn__copyright-design h6, .ltn__copyright-design h4 { + font-size: 14px; + font-family: var(--ltn__body-font); + font-weight: 700; } + +.ltn__copyright-menu ul { + margin: 0; + padding: 0; } + .ltn__copyright-menu ul li { + list-style: none; + display: inline-block; + margin-top: 0; + margin-right: 20px; + font-size: 14px; + font-family: var(--ltn__heading-font); + font-weight: 700; } + .ltn__copyright-menu ul li:last-child { + margin-right: 0; } + .ltn__copyright-menu ul li a { + margin: 0; } + +/* ---------------------------------------------------- + Responsive +---------------------------------------------------- */ +@media (max-width: 991px) { + .ltn__footer-timeline-widget { + padding: 50px 25px 40px; } + .ltn__copyright-area .payment-method { + text-align: center; + margin-top: 15px; } + .ltn__copyright-area .site-logo-wrap { + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } + .ltn__copyright-area .ltn__copyright-menu { + text-align: center !important; } + #scrollUp { + font-size: 16px; + height: 30px; + width: 30px; + bottom: 50px; } + #scrollUp i { + line-height: 30px; } } + +@media (max-width: 767px) { + .ltn__footer-timeline-widget { + padding: 50px 25px 40px; } + .footer-menu-widget-2-column { + padding-left: 0; } + .ltn__copyright-menu { + margin-top: 25px; } + .ltn__footer-2 .footer-widget p, + .ltn__footer-2 .footer-widget li { + font-size: 14px; } + .ltn__footer-2 .footer-widget .ltn__blog-meta li, + .footer-widget .ltn__blog-meta li { + font-size: 12px; } + .ltn__footer-2 .footer-menu ul li { + margin-bottom: 20px; } + .ltn__footer-blog-item .ltn__blog-title { + font-size: 18px; } + .footer-copyright-left, + .footer-copyright-right { + text-align: center !important; } + .footer-copyright-right { + margin-top: 10px; } } + +@media (max-width: 575px) { + .ltn__footer-timeline-widget { + padding: 50px 25px 40px; } + .footer-menu-widget-2-column .footer-menu { + width: 100%; } + .footer-menu-widget-2-column .footer-menu:nth-child(odd) { + padding-left: 0px; } + .ltn__copyright-menu { + margin-top: 25px; } } + +/* ---------------------------------------------------- + END +---------------------------------------------------- */ +/* ------------------------- + ## Preloader Css +--------------------------- */ +.pre-wrap { + position: fixed; + content: ''; + -webkit-transform: translate(-100%, -240%); + -ms-transform: translate(-100%, -240%); + transform: translate(-100%, -240%); + font-size: 62px; } + +.preloader-inner { + position: fixed; + left: 0; + top: 0; + z-index: 9999999; + background-color: transparent; + width: 100%; + height: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; } + .preloader-inner .cancel-preloader { + position: absolute; + bottom: 30px; + right: 30px; } + .preloader-inner .cancel-preloader a { + background-color: var(--white); + font-weight: 600; + text-transform: capitalize; + color: var(--ltn__primary-color); + width: 200px; + height: 50px; + text-align: center; + line-height: 50px; + border-radius: 30px; + display: block; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; } + .preloader-inner .cancel-preloader a:hover { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +.spinner { + margin: 120px auto; + width: 60px; + height: 60px; + position: relative; + text-align: center; + -webkit-animation: sk-rotate 2.0s infinite linear; + animation: sk-rotate 2.0s infinite linear; } + +.dot1, .dot2 { + width: 60%; + height: 60%; + display: inline-block; + position: absolute; + top: 0; + background-color: var(--ltn__secondary-color); + border-radius: 100%; + -webkit-animation: sk-bounce 2.0s infinite ease-in-out; + animation: sk-bounce 2.0s infinite ease-in-out; } + +.dot2 { + top: auto; + bottom: 0; + -webkit-animation-delay: -1.0s; + animation-delay: -1.0s; } + +@-webkit-keyframes sk-rotate { + 100% { + -webkit-transform: rotate(360deg); } } + +@keyframes sk-rotate { + 100% { + transform: rotate(360deg); + -webkit-transform: rotate(360deg); } } + +@-webkit-keyframes sk-bounce { + 0%, 100% { + -webkit-transform: scale(0); } + 50% { + -webkit-transform: scale(1); } } + +@keyframes sk-bounce { + 0%, 100% { + transform: scale(0); + -webkit-transform: scale(0); } + 50% { + transform: scale(1); + -webkit-transform: scale(1); } } + +/*---------------------------------------- + Search Popup +----------------------------------------*/ +/* --------------------------------------- + ## Button +--------------------------------------- */ +.btn-wrapper { + display: block; + margin-top: 30px; } + +.btn { + border-radius: 0; + display: inline-block; + font-size: 16px; + font-weight: 500; + font-family: var(--ltn__heading-font); + padding: 13px 40px; + text-align: center; + cursor: pointer; + -webkit-transition: all 0.3s ease 0s; + -o-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + position: relative; + z-index: 1; + margin-right: 15px; } + .btn:last-child { + margin-right: 0; } + +.theme-btn-1 { + background-color: var(--ltn__secondary-color); + color: var(--white); } + .theme-btn-1:hover { + background-color: var(--ltn__primary-color); + color: var(--white); } + +.theme-btn-2 { + background-color: var(--ltn__primary-color); + color: var(--white); } + .theme-btn-2:hover { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +.theme-btn-3 { + background-color: transparent; + border: 2px solid var(--border-color-9); } + .theme-btn-3:hover { + background-color: var(--ltn__secondary-color); + border-color: var(--ltn__secondary-color); + color: var(--white); } + +.reverse-color { + background-color: var(--ltn__secondary-color); } + .reverse-color:hover { + background-color: var(--ltn__primary-color); } + +.btn-white { + background-color: var(--white); + color: var(--ltn__primary-color); + -webkit-box-shadow: var(--ltn__box-shadow-3); + box-shadow: var(--ltn__box-shadow-3); } + .btn-white:hover { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +.btn-black { + background-color: var(--black); + color: var(--white); } + .btn-black:hover { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +.btn-transparent { + background-color: transparent; + -webkit-box-shadow: var(--ltn__box-shadow-3); + box-shadow: var(--ltn__box-shadow-3); + border-color: #ddd; } + .btn-transparent:hover { + background-color: var(--ltn__secondary-color); + color: var(--white); } + +.btn-round { + border-radius: 50px; } + +.btn-opacity-6 { + opacity: 0.6; } + .btn-opacity-6:hover { + opacity: 1; } + +.btn-opacity-7 { + opacity: 0.7; } + .btn-opacity-7:hover { + opacity: 1; } + +.btn-opacity-8 { + opacity: 0.8; } + .btn-opacity-8:hover { + opacity: 1; } + +.btn-opacity-9 { + opacity: 0.9; } + .btn-opacity-9:hover { + opacity: 1; } + +.btn:after { + content: ''; + position: absolute; + z-index: -1; + -webkit-transition: all 0.3s; + -moz-transition: all 0.3s; + -o-transition: all 0.3s; + transition: all 0.3s; } + +.btn-effect-1:after { + width: 0%; + height: 100%; + top: 0; + left: 0; + background: var(--white); } + +.btn-effect-1:hover { + color: var(--ltn__heading-color); } + .btn-effect-1:hover::after { + width: 100%; } + +.btn-effect-2:after { + width: 0%; + height: 100%; + top: 0; + right: 0; + background: var(--white); } + +.btn-effect-2:hover { + color: var(--ltn__heading-color); } + .btn-effect-2:hover::after { + width: 100%; } + +.btn-effect-3:after { + width: 0%; + height: 100%; + top: 0; + left: 0; + background: var(--ltn__primary-color); } + +.btn-effect-3:hover { + color: var(--white); } + .btn-effect-3:hover::after { + width: 100%; } + +.btn-effect-4:after { + width: 0%; + height: 100%; + top: 0; + left: 0; + background: var(--ltn__secondary-color); } + +.btn-effect-4:hover { + color: var(--white); } + .btn-effect-4:hover::after { + width: 100%; } + +.btn-full-width { + display: block; } + +.btn-border { + border: 2px solid var(--border-color-10); + -webkit-box-shadow: none; + box-shadow: none; } + +@media (min-width: 768px) and (max-width: 991px) { + .btn { + padding: 12px 25px; } + [type="submit"].btn { + padding: 15px 30px; } } + +@media only screen and (max-width: 767px) { + .btn { + padding: 10px 20px; + font-size: 14px; } + [type="submit"].btn { + padding: 12px 30px; } } + +/* ---------------------------------------------------- + END +---------------------------------------------------- */ diff --git a/themes/nurgul/assets/fonts/Simple-Line-Icons-v=2.4.0.eot b/themes/nurgul/assets/fonts/Simple-Line-Icons-v=2.4.0.eot new file mode 100644 index 0000000..f0ca6e8 Binary files /dev/null and b/themes/nurgul/assets/fonts/Simple-Line-Icons-v=2.4.0.eot differ diff --git a/themes/nurgul/assets/fonts/Simple-Line-Icons-v=2.4.0.svg b/themes/nurgul/assets/fonts/Simple-Line-Icons-v=2.4.0.svg new file mode 100644 index 0000000..4988524 --- /dev/null +++ b/themes/nurgul/assets/fonts/Simple-Line-Icons-v=2.4.0.svg @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/themes/nurgul/assets/fonts/Simple-Line-Icons-v=2.4.0.ttf b/themes/nurgul/assets/fonts/Simple-Line-Icons-v=2.4.0.ttf new file mode 100644 index 0000000..6ecb686 Binary files /dev/null and b/themes/nurgul/assets/fonts/Simple-Line-Icons-v=2.4.0.ttf differ diff --git a/themes/nurgul/assets/fonts/Simple-Line-Icons-v=2.4.0.woff b/themes/nurgul/assets/fonts/Simple-Line-Icons-v=2.4.0.woff new file mode 100644 index 0000000..b17d694 Binary files /dev/null and b/themes/nurgul/assets/fonts/Simple-Line-Icons-v=2.4.0.woff differ diff --git a/themes/nurgul/assets/fonts/Simple-Line-Icons-v=2.4.0.woff2 b/themes/nurgul/assets/fonts/Simple-Line-Icons-v=2.4.0.woff2 new file mode 100644 index 0000000..c49fccf Binary files /dev/null and b/themes/nurgul/assets/fonts/Simple-Line-Icons-v=2.4.0.woff2 differ diff --git a/themes/nurgul/assets/fonts/lightcase-55356177.eot b/themes/nurgul/assets/fonts/lightcase-55356177.eot new file mode 100644 index 0000000..0fec750 Binary files /dev/null and b/themes/nurgul/assets/fonts/lightcase-55356177.eot differ diff --git a/themes/nurgul/assets/fonts/lightcase-55356177.svg b/themes/nurgul/assets/fonts/lightcase-55356177.svg new file mode 100644 index 0000000..6465982 --- /dev/null +++ b/themes/nurgul/assets/fonts/lightcase-55356177.svg @@ -0,0 +1,17 @@ + + + +Copyright (C) 2015 by original authors @ fontello.com + + + + + + + + + + + + + \ No newline at end of file diff --git a/themes/nurgul/assets/fonts/lightcase-55356177.ttf b/themes/nurgul/assets/fonts/lightcase-55356177.ttf new file mode 100644 index 0000000..cc479b4 Binary files /dev/null and b/themes/nurgul/assets/fonts/lightcase-55356177.ttf differ diff --git a/themes/nurgul/assets/fonts/lightcase-55356177.woff b/themes/nurgul/assets/fonts/lightcase-55356177.woff new file mode 100644 index 0000000..375017c Binary files /dev/null and b/themes/nurgul/assets/fonts/lightcase-55356177.woff differ diff --git a/themes/nurgul/assets/img/banner/1.jpg b/themes/nurgul/assets/img/banner/1.jpg new file mode 100644 index 0000000..d157d14 Binary files /dev/null and b/themes/nurgul/assets/img/banner/1.jpg differ diff --git a/themes/nurgul/assets/img/banner/10.jpg b/themes/nurgul/assets/img/banner/10.jpg new file mode 100644 index 0000000..152302c Binary files /dev/null and b/themes/nurgul/assets/img/banner/10.jpg differ diff --git a/themes/nurgul/assets/img/banner/2.jpg b/themes/nurgul/assets/img/banner/2.jpg new file mode 100644 index 0000000..2d47fbe Binary files /dev/null and b/themes/nurgul/assets/img/banner/2.jpg differ diff --git a/themes/nurgul/assets/img/banner/3.jpg b/themes/nurgul/assets/img/banner/3.jpg new file mode 100644 index 0000000..0c42f12 Binary files /dev/null and b/themes/nurgul/assets/img/banner/3.jpg differ diff --git a/themes/nurgul/assets/img/banner/4.jpg b/themes/nurgul/assets/img/banner/4.jpg new file mode 100644 index 0000000..63913f1 Binary files /dev/null and b/themes/nurgul/assets/img/banner/4.jpg differ diff --git a/themes/nurgul/assets/img/banner/5.jpg b/themes/nurgul/assets/img/banner/5.jpg new file mode 100644 index 0000000..f969e3c Binary files /dev/null and b/themes/nurgul/assets/img/banner/5.jpg differ diff --git a/themes/nurgul/assets/img/banner/6.jpg b/themes/nurgul/assets/img/banner/6.jpg new file mode 100644 index 0000000..c2578f0 Binary files /dev/null and b/themes/nurgul/assets/img/banner/6.jpg differ diff --git a/themes/nurgul/assets/img/banner/7.jpg b/themes/nurgul/assets/img/banner/7.jpg new file mode 100644 index 0000000..3ef6b33 Binary files /dev/null and b/themes/nurgul/assets/img/banner/7.jpg differ diff --git a/themes/nurgul/assets/img/banner/8.jpg b/themes/nurgul/assets/img/banner/8.jpg new file mode 100644 index 0000000..814aeb4 Binary files /dev/null and b/themes/nurgul/assets/img/banner/8.jpg differ diff --git a/themes/nurgul/assets/img/banner/9.jpg b/themes/nurgul/assets/img/banner/9.jpg new file mode 100644 index 0000000..06cc963 Binary files /dev/null and b/themes/nurgul/assets/img/banner/9.jpg differ diff --git a/themes/nurgul/assets/img/bg/3.png b/themes/nurgul/assets/img/bg/3.png new file mode 100644 index 0000000..37fce26 Binary files /dev/null and b/themes/nurgul/assets/img/bg/3.png differ diff --git a/themes/nurgul/assets/img/blog/1.jpg b/themes/nurgul/assets/img/blog/1.jpg new file mode 100644 index 0000000..a0bdaca Binary files /dev/null and b/themes/nurgul/assets/img/blog/1.jpg differ diff --git a/themes/nurgul/assets/img/blog/2.jpg b/themes/nurgul/assets/img/blog/2.jpg new file mode 100644 index 0000000..cca711a Binary files /dev/null and b/themes/nurgul/assets/img/blog/2.jpg differ diff --git a/themes/nurgul/assets/img/blog/3.jpg b/themes/nurgul/assets/img/blog/3.jpg new file mode 100644 index 0000000..c3cfb0b Binary files /dev/null and b/themes/nurgul/assets/img/blog/3.jpg differ diff --git a/themes/nurgul/assets/img/blog/4.jpg b/themes/nurgul/assets/img/blog/4.jpg new file mode 100644 index 0000000..b4f3ad7 Binary files /dev/null and b/themes/nurgul/assets/img/blog/4.jpg differ diff --git a/themes/nurgul/assets/img/blog/5.jpg b/themes/nurgul/assets/img/blog/5.jpg new file mode 100644 index 0000000..6577ba6 Binary files /dev/null and b/themes/nurgul/assets/img/blog/5.jpg differ diff --git a/themes/nurgul/assets/img/blog/6.jpg b/themes/nurgul/assets/img/blog/6.jpg new file mode 100644 index 0000000..a3d9a87 Binary files /dev/null and b/themes/nurgul/assets/img/blog/6.jpg differ diff --git a/themes/nurgul/assets/img/blog/7.jpg b/themes/nurgul/assets/img/blog/7.jpg new file mode 100644 index 0000000..85238ef Binary files /dev/null and b/themes/nurgul/assets/img/blog/7.jpg differ diff --git a/themes/nurgul/assets/img/blog/8.jpg b/themes/nurgul/assets/img/blog/8.jpg new file mode 100644 index 0000000..9b38b7d Binary files /dev/null and b/themes/nurgul/assets/img/blog/8.jpg differ diff --git a/themes/nurgul/assets/img/blog/9.jpg b/themes/nurgul/assets/img/blog/9.jpg new file mode 100644 index 0000000..1d727bf Binary files /dev/null and b/themes/nurgul/assets/img/blog/9.jpg differ diff --git a/themes/nurgul/assets/img/blog/author-2.jpg b/themes/nurgul/assets/img/blog/author-2.jpg new file mode 100644 index 0000000..d7eff9b Binary files /dev/null and b/themes/nurgul/assets/img/blog/author-2.jpg differ diff --git a/themes/nurgul/assets/img/blog/author.jpg b/themes/nurgul/assets/img/blog/author.jpg new file mode 100644 index 0000000..4aab158 Binary files /dev/null and b/themes/nurgul/assets/img/blog/author.jpg differ diff --git a/themes/nurgul/assets/img/blog/blog-details/1.jpg b/themes/nurgul/assets/img/blog/blog-details/1.jpg new file mode 100644 index 0000000..8d576ed Binary files /dev/null and b/themes/nurgul/assets/img/blog/blog-details/1.jpg differ diff --git a/themes/nurgul/assets/img/blog/blog-details/11.jpg b/themes/nurgul/assets/img/blog/blog-details/11.jpg new file mode 100644 index 0000000..44d4b71 Binary files /dev/null and b/themes/nurgul/assets/img/blog/blog-details/11.jpg differ diff --git a/themes/nurgul/assets/img/blog/blog-details/2.jpg b/themes/nurgul/assets/img/blog/blog-details/2.jpg new file mode 100644 index 0000000..c68446b Binary files /dev/null and b/themes/nurgul/assets/img/blog/blog-details/2.jpg differ diff --git a/themes/nurgul/assets/img/brand-logo/1.png b/themes/nurgul/assets/img/brand-logo/1.png new file mode 100644 index 0000000..e2cbbde Binary files /dev/null and b/themes/nurgul/assets/img/brand-logo/1.png differ diff --git a/themes/nurgul/assets/img/brand-logo/2.png b/themes/nurgul/assets/img/brand-logo/2.png new file mode 100644 index 0000000..c23b70c Binary files /dev/null and b/themes/nurgul/assets/img/brand-logo/2.png differ diff --git a/themes/nurgul/assets/img/brand-logo/3.png b/themes/nurgul/assets/img/brand-logo/3.png new file mode 100644 index 0000000..7573189 Binary files /dev/null and b/themes/nurgul/assets/img/brand-logo/3.png differ diff --git a/themes/nurgul/assets/img/brand-logo/4.png b/themes/nurgul/assets/img/brand-logo/4.png new file mode 100644 index 0000000..a33b6af Binary files /dev/null and b/themes/nurgul/assets/img/brand-logo/4.png differ diff --git a/themes/nurgul/assets/img/brand-logo/5.png b/themes/nurgul/assets/img/brand-logo/5.png new file mode 100644 index 0000000..b698375 Binary files /dev/null and b/themes/nurgul/assets/img/brand-logo/5.png differ diff --git a/themes/nurgul/assets/img/favicon.png b/themes/nurgul/assets/img/favicon.png new file mode 100644 index 0000000..7ebe738 Binary files /dev/null and b/themes/nurgul/assets/img/favicon.png differ diff --git a/themes/nurgul/assets/img/icons/car.png b/themes/nurgul/assets/img/icons/car.png new file mode 100644 index 0000000..acc1a10 Binary files /dev/null and b/themes/nurgul/assets/img/icons/car.png differ diff --git a/themes/nurgul/assets/img/icons/payment-2.png b/themes/nurgul/assets/img/icons/payment-2.png new file mode 100644 index 0000000..724147e Binary files /dev/null and b/themes/nurgul/assets/img/icons/payment-2.png differ diff --git a/themes/nurgul/assets/img/icons/payment-3.png b/themes/nurgul/assets/img/icons/payment-3.png new file mode 100644 index 0000000..647ea41 Binary files /dev/null and b/themes/nurgul/assets/img/icons/payment-3.png differ diff --git a/themes/nurgul/assets/img/icons/payment-6.png b/themes/nurgul/assets/img/icons/payment-6.png new file mode 100644 index 0000000..3544dcf Binary files /dev/null and b/themes/nurgul/assets/img/icons/payment-6.png differ diff --git a/themes/nurgul/assets/img/icons/payment.png b/themes/nurgul/assets/img/icons/payment.png new file mode 100644 index 0000000..2acf721 Binary files /dev/null and b/themes/nurgul/assets/img/icons/payment.png differ diff --git a/themes/nurgul/assets/img/icons/svg/10-credit-card.svg b/themes/nurgul/assets/img/icons/svg/10-credit-card.svg new file mode 100644 index 0000000..a5cfd20 --- /dev/null +++ b/themes/nurgul/assets/img/icons/svg/10-credit-card.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/themes/nurgul/assets/img/icons/svg/11-gift-card.svg b/themes/nurgul/assets/img/icons/svg/11-gift-card.svg new file mode 100644 index 0000000..3051074 --- /dev/null +++ b/themes/nurgul/assets/img/icons/svg/11-gift-card.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/themes/nurgul/assets/img/icons/svg/8-trolley.svg b/themes/nurgul/assets/img/icons/svg/8-trolley.svg new file mode 100644 index 0000000..07dc6c7 --- /dev/null +++ b/themes/nurgul/assets/img/icons/svg/8-trolley.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/themes/nurgul/assets/img/icons/svg/9-money.svg b/themes/nurgul/assets/img/icons/svg/9-money.svg new file mode 100644 index 0000000..3920105 --- /dev/null +++ b/themes/nurgul/assets/img/icons/svg/9-money.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/themes/nurgul/assets/img/logo-2.png b/themes/nurgul/assets/img/logo-2.png new file mode 100644 index 0000000..778f53b Binary files /dev/null and b/themes/nurgul/assets/img/logo-2.png differ diff --git a/themes/nurgul/assets/img/logo.png b/themes/nurgul/assets/img/logo.png new file mode 100644 index 0000000..8158991 Binary files /dev/null and b/themes/nurgul/assets/img/logo.png differ diff --git a/themes/nurgul/assets/img/product/1.png b/themes/nurgul/assets/img/product/1.png new file mode 100644 index 0000000..b2ea91d Binary files /dev/null and b/themes/nurgul/assets/img/product/1.png differ diff --git a/themes/nurgul/assets/img/product/10.png b/themes/nurgul/assets/img/product/10.png new file mode 100644 index 0000000..020b58d Binary files /dev/null and b/themes/nurgul/assets/img/product/10.png differ diff --git a/themes/nurgul/assets/img/product/12.png b/themes/nurgul/assets/img/product/12.png new file mode 100644 index 0000000..4ccda7a Binary files /dev/null and b/themes/nurgul/assets/img/product/12.png differ diff --git a/themes/nurgul/assets/img/product/2.png b/themes/nurgul/assets/img/product/2.png new file mode 100644 index 0000000..f098d62 Binary files /dev/null and b/themes/nurgul/assets/img/product/2.png differ diff --git a/themes/nurgul/assets/img/product/3.png b/themes/nurgul/assets/img/product/3.png new file mode 100644 index 0000000..99954ec Binary files /dev/null and b/themes/nurgul/assets/img/product/3.png differ diff --git a/themes/nurgul/assets/img/product/4.png b/themes/nurgul/assets/img/product/4.png new file mode 100644 index 0000000..15ee4c7 Binary files /dev/null and b/themes/nurgul/assets/img/product/4.png differ diff --git a/themes/nurgul/assets/img/product/5.png b/themes/nurgul/assets/img/product/5.png new file mode 100644 index 0000000..8eb1a3f Binary files /dev/null and b/themes/nurgul/assets/img/product/5.png differ diff --git a/themes/nurgul/assets/img/product/6.png b/themes/nurgul/assets/img/product/6.png new file mode 100644 index 0000000..49a0105 Binary files /dev/null and b/themes/nurgul/assets/img/product/6.png differ diff --git a/themes/nurgul/assets/img/product/7.png b/themes/nurgul/assets/img/product/7.png new file mode 100644 index 0000000..b947fbe Binary files /dev/null and b/themes/nurgul/assets/img/product/7.png differ diff --git a/themes/nurgul/assets/img/product/8.png b/themes/nurgul/assets/img/product/8.png new file mode 100644 index 0000000..95f05ec Binary files /dev/null and b/themes/nurgul/assets/img/product/8.png differ diff --git a/themes/nurgul/assets/img/product/9.png b/themes/nurgul/assets/img/product/9.png new file mode 100644 index 0000000..4ee6240 Binary files /dev/null and b/themes/nurgul/assets/img/product/9.png differ diff --git a/themes/nurgul/assets/img/slider/1.jpg b/themes/nurgul/assets/img/slider/1.jpg new file mode 100644 index 0000000..93cdf77 Binary files /dev/null and b/themes/nurgul/assets/img/slider/1.jpg differ diff --git a/themes/nurgul/assets/img/slider/3.jpg b/themes/nurgul/assets/img/slider/3.jpg new file mode 100644 index 0000000..75cfb3a Binary files /dev/null and b/themes/nurgul/assets/img/slider/3.jpg differ diff --git a/themes/nurgul/assets/img/small/1.jpg b/themes/nurgul/assets/img/small/1.jpg new file mode 100644 index 0000000..43b11ff Binary files /dev/null and b/themes/nurgul/assets/img/small/1.jpg differ diff --git a/themes/nurgul/assets/img/small/2.jpg b/themes/nurgul/assets/img/small/2.jpg new file mode 100644 index 0000000..81257ac Binary files /dev/null and b/themes/nurgul/assets/img/small/2.jpg differ diff --git a/themes/nurgul/assets/img/small/3.jpg b/themes/nurgul/assets/img/small/3.jpg new file mode 100644 index 0000000..39b6837 Binary files /dev/null and b/themes/nurgul/assets/img/small/3.jpg differ diff --git a/themes/nurgul/assets/img/small/4.jpg b/themes/nurgul/assets/img/small/4.jpg new file mode 100644 index 0000000..b11eaf6 Binary files /dev/null and b/themes/nurgul/assets/img/small/4.jpg differ diff --git a/themes/nurgul/assets/img/team/1.jpg b/themes/nurgul/assets/img/team/1.jpg new file mode 100644 index 0000000..24ca35a Binary files /dev/null and b/themes/nurgul/assets/img/team/1.jpg differ diff --git a/themes/nurgul/assets/img/team/11.jpg b/themes/nurgul/assets/img/team/11.jpg new file mode 100644 index 0000000..08fa5a1 Binary files /dev/null and b/themes/nurgul/assets/img/team/11.jpg differ diff --git a/themes/nurgul/assets/img/team/12.jpg b/themes/nurgul/assets/img/team/12.jpg new file mode 100644 index 0000000..899436f Binary files /dev/null and b/themes/nurgul/assets/img/team/12.jpg differ diff --git a/themes/nurgul/assets/img/team/13.jpg b/themes/nurgul/assets/img/team/13.jpg new file mode 100644 index 0000000..fb2c61b Binary files /dev/null and b/themes/nurgul/assets/img/team/13.jpg differ diff --git a/themes/nurgul/assets/img/team/14.jpg b/themes/nurgul/assets/img/team/14.jpg new file mode 100644 index 0000000..d0f5403 Binary files /dev/null and b/themes/nurgul/assets/img/team/14.jpg differ diff --git a/themes/nurgul/assets/img/team/2.jpg b/themes/nurgul/assets/img/team/2.jpg new file mode 100644 index 0000000..082f25f Binary files /dev/null and b/themes/nurgul/assets/img/team/2.jpg differ diff --git a/themes/nurgul/assets/img/team/3.jpg b/themes/nurgul/assets/img/team/3.jpg new file mode 100644 index 0000000..7aa2b84 Binary files /dev/null and b/themes/nurgul/assets/img/team/3.jpg differ diff --git a/themes/nurgul/assets/img/team/4.jpg b/themes/nurgul/assets/img/team/4.jpg new file mode 100644 index 0000000..f2c8f05 Binary files /dev/null and b/themes/nurgul/assets/img/team/4.jpg differ diff --git a/themes/nurgul/assets/img/testimonial/1.jpg b/themes/nurgul/assets/img/testimonial/1.jpg new file mode 100644 index 0000000..0dfce75 Binary files /dev/null and b/themes/nurgul/assets/img/testimonial/1.jpg differ diff --git a/themes/nurgul/assets/img/testimonial/2.jpg b/themes/nurgul/assets/img/testimonial/2.jpg new file mode 100644 index 0000000..cb52120 Binary files /dev/null and b/themes/nurgul/assets/img/testimonial/2.jpg differ diff --git a/themes/nurgul/assets/img/testimonial/3.jpg b/themes/nurgul/assets/img/testimonial/3.jpg new file mode 100644 index 0000000..3592c00 Binary files /dev/null and b/themes/nurgul/assets/img/testimonial/3.jpg differ diff --git a/themes/nurgul/assets/img/testimonial/4.jpg b/themes/nurgul/assets/img/testimonial/4.jpg new file mode 100644 index 0000000..5a3bd59 Binary files /dev/null and b/themes/nurgul/assets/img/testimonial/4.jpg differ diff --git a/themes/nurgul/assets/js/contact.js b/themes/nurgul/assets/js/contact.js new file mode 100644 index 0000000..cba3312 --- /dev/null +++ b/themes/nurgul/assets/js/contact.js @@ -0,0 +1,50 @@ +/* Contact Form Dynamic */ + +$(function() { + + // Get the form. + var form = $('#contact-form'); + + // Get the messages div. + var formMessages = $('.form-messege'); + + // Set up an event listener for the contact form. + $(form).submit(function(e) { + // Stop the browser from submitting the form. + e.preventDefault(); + + // Serialize the form data. + var formData = $(form).serialize(); + + // Submit the form using AJAX. + $.ajax({ + type: 'POST', + url: $(form).attr('action'), + data: formData + }) + .done(function(response) { + // Make sure that the formMessages div has the 'success' class. + $(formMessages).removeClass('error'); + $(formMessages).addClass('success'); + + // Set the message text. + $(formMessages).text(response); + + // Clear the form. + $('#contact-form input,#contact-form textarea').val(''); + }) + .fail(function(data) { + // Make sure that the formMessages div has the 'error' class. + $(formMessages).removeClass('success'); + $(formMessages).addClass('error'); + + // Set the message text. + if (data.responseText !== '') { + $(formMessages).text(data.responseText); + } else { + $(formMessages).text('Oops! An error occured and your message could not be sent.'); + } + }); + }); + +}); diff --git a/themes/nurgul/assets/js/main.js b/themes/nurgul/assets/js/main.js new file mode 100644 index 0000000..3617caa --- /dev/null +++ b/themes/nurgul/assets/js/main.js @@ -0,0 +1,1357 @@ +/*================================================ +[ Table of contents ] +================================================ + +1. Variables +2. Mobile Menu +3. Mega Menu +4. One Page Navigation +5. Toogle Search +6. Current Year Copyright area +7. Background Image +8. wow js init +9. Tooltip +10. Nice Select +11. Default active and hover item active +12. Product Details Page +13. Isotope Gallery Active ( Gallery / Portfolio ) +14. LightCase jQuery Active +15. Slider One Active +16. Product Slider One +17. Tab Product Slider One +18. Blog Slider One +19. Testimonial Slider - 1 +20. Testimonial Slider - 2 +21. Testimonial Slider - 3 +22. Category Slider +23. Image Slide - 1 (Screenshot) +24. Image Slide - 2 +25. Image Slide - 3 +26. Image Slide - 4 +27. Brand Logo +28. Blog Gallery (Blog Page ) +29. Countdown +30. Counter Up +31. Instagram Feed +32. Price Slider +33. Quantity plus minus +34. scrollUp active +35. Parallax active +36. Header menu sticky + + + +====================================== +[ End table content ] +======================================*/ + +(function($) { + "use strict"; + + jQuery(document).ready(function(){ + + /* -------------------------------------------------------- + 1. Variables + --------------------------------------------------------- */ + var $window = $(window), + $body = $('body'); + + /* -------------------------------------------------------- + 2. Mobile Menu + --------------------------------------------------------- */ + /* --------------------------------- + Utilize Function + ----------------------------------- */ + (function () { + var $ltn__utilizeToggle = $('.ltn__utilize-toggle'), + $ltn__utilize = $('.ltn__utilize'), + $ltn__utilizeOverlay = $('.ltn__utilize-overlay'), + $mobileMenuToggle = $('.mobile-menu-toggle'); + $ltn__utilizeToggle.on('click', function (e) { + e.preventDefault(); + var $this = $(this), + $target = $this.attr('href'); + $body.addClass('ltn__utilize-open'); + $($target).addClass('ltn__utilize-open'); + $ltn__utilizeOverlay.fadeIn(); + if ($this.parent().hasClass('mobile-menu-toggle')) { + $this.addClass('close'); + } + }); + $('.ltn__utilize-close, .ltn__utilize-overlay').on('click', function (e) { + e.preventDefault(); + $body.removeClass('ltn__utilize-open'); + $ltn__utilize.removeClass('ltn__utilize-open'); + $ltn__utilizeOverlay.fadeOut(); + $mobileMenuToggle.find('a').removeClass('close'); + }); + })(); + + /* ------------------------------------ + Utilize Menu + ----------------------------------- */ + function mobileltn__utilizeMenu() { + var $ltn__utilizeNav = $('.ltn__utilize-menu, .overlay-menu'), + $ltn__utilizeNavSubMenu = $ltn__utilizeNav.find('.sub-menu'); + + /*Add Toggle Button With Off Canvas Sub Menu*/ + $ltn__utilizeNavSubMenu.parent().prepend(''); + + /*Category Sub Menu Toggle*/ + $ltn__utilizeNav.on('click', 'li a, .menu-expand', function (e) { + var $this = $(this); + if ($this.attr('href') === '#' || $this.hasClass('menu-expand')) { + e.preventDefault(); + if ($this.siblings('ul:visible').length) { + $this.parent('li').removeClass('active'); + $this.siblings('ul').slideUp(); + $this.parent('li').find('li').removeClass('active'); + $this.parent('li').find('ul:visible').slideUp(); + } else { + $this.parent('li').addClass('active'); + $this.closest('li').siblings('li').removeClass('active').find('li').removeClass('active'); + $this.closest('li').siblings('li').find('ul:visible').slideUp(); + $this.siblings('ul').slideDown(); + } + } + }); + } + mobileltn__utilizeMenu(); + + /* -------------------------------------------------------- + 3. Mega Menu + --------------------------------------------------------- */ + $('.mega-menu').each(function(){ + if($(this).children('li').length){ + var ulChildren = $(this).children('li').length; + $(this).addClass('column-'+ulChildren) + } + }); + + + /* Remove Attribute( href ) from sub-menu title in mega-menu */ + /* + $('.mega-menu > li > a').removeAttr('href'); + */ + + + /* Mega Munu */ + // $(".mega-menu").parent().css({"position": "inherit"}); + $(".mega-menu").parent().addClass("mega-menu-parent"); + + + /* Add space for Elementor Menu Anchor link */ + $( window ).on( 'elementor/frontend/init', function() { + elementorFrontend.hooks.addFilter( 'frontend/handlers/menu_anchor/scroll_top_distance', function( scrollTop ) { + return scrollTop - 75; + }); + }); + + + /* --------------------------------------------------------- + 4. One Page Navigation ( jQuery Easing Plugin ) + --------------------------------------------------------- */ + // jQuery for page scrolling feature - requires jQuery Easing plugin + $(function() { + $('a.page-scroll').bind('click', function(event) { + var $anchor = $(this); + $('html, body').stop().animate({ + scrollTop: $($anchor.attr('href')).offset().top + }, 1500, 'easeInOutExpo'); + event.preventDefault(); + }); + }); + + + /* -------------------------------------------------------- + 5. Toogle Search + -------------------------------------------------------- */ + // Handle click on toggle search button + $('.header-search-1').on('click', function() { + $('.header-search-1, .header-search-1-form').toggleClass('search-open'); + return false; + }); + + + /* --------------------------------------------------------- + 6. Current Year Copyright area + --------------------------------------------------------- */ + $(".current-year").text((new Date).getFullYear()); + + + /* --------------------------------------------------------- + 7. Background Image + --------------------------------------------------------- */ + var $backgroundImage = $('.bg-image, .bg-image-top, .bg-image-right'); + $backgroundImage.each(function() { + var $this = $(this), + $bgImage = $this.data('bs-bg'); + $this.css('background-image', 'url('+$bgImage+')'); + }); + + + /* --------------------------------------------------------- + 8. wow js init + --------------------------------------------------------- */ + new WOW().init(); + + + /* --------------------------------------------------------- + 9. Tooltip + --------------------------------------------------------- */ + $('[data-bs-toggle="tooltip"]').tooltip(); + + + /* -------------------------------------------------------- + 10. Nice Select + --------------------------------------------------------- */ + $('select').niceSelect(); + + + /* -------------------------------------------------------- + 11. Default active and hover item active + --------------------------------------------------------- */ + var ltn__active_item = $('.ltn__feature-item-6, .ltn__our-journey-wrap ul li, .ltn__pricing-plan-item') + ltn__active_item.mouseover(function() { + ltn__active_item.removeClass('active'); + $(this).addClass('active'); + }); + + /* -------------------------------------------------------- + 12. Product Details Page + --------------------------------------------------------- */ + $('.ltn__shop-details-large-img').slick({ + slidesToShow: 1, + slidesToScroll: 1, + arrows: false, + fade: true, + asNavFor: '.ltn__shop-details-small-img' + }); + $('.ltn__shop-details-small-img').slick({ + slidesToShow: 4, + slidesToScroll: 1, + asNavFor: '.ltn__shop-details-large-img', + dots: false, + arrows: false, + vertical: true, + focusOnSelect: true, + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 992, + settings: { + slidesToShow: 4, + slidesToScroll: 1 + } + }, + { + breakpoint: 768, + settings: { + slidesToShow: 3, + slidesToScroll: 1 + } + }, + { + breakpoint: 580, + settings: { + slidesToShow: 3, + slidesToScroll: 1 + } + } + ] + }); + + /* -------------------------------------------------------- + 13. Isotope Gallery Active ( Gallery / Portfolio ) + -------------------------------------------------------- */ + var $ltnGalleryActive = $('.ltn__gallery-active'), + $ltnGalleryFilterMenu = $('.ltn__gallery-filter-menu'); + /*Filter*/ + $ltnGalleryFilterMenu.on( 'click', 'button, a', function() { + var $this = $(this), + $filterValue = $this.attr('data-filter'); + $ltnGalleryFilterMenu.find('button, a').removeClass('active'); + $this.addClass('active'); + $ltnGalleryActive.isotope({ filter: $filterValue }); + }); + /*Grid*/ + $ltnGalleryActive.each(function(){ + var $this = $(this), + $galleryFilterItem = '.ltn__gallery-item'; + $this.imagesLoaded( function() { + $this.isotope({ + itemSelector: $galleryFilterItem, + percentPosition: true, + masonry: { + columnWidth: '.ltn__gallery-sizer', + } + }); + }); + }); + + /* -------------------------------------------------------- + 14. LightCase jQuery Active + --------------------------------------------------------- */ + $('a[data-rel^=lightcase]').lightcase({ + transition: 'elastic', /* none, fade, fadeInline, elastic, scrollTop, scrollRight, scrollBottom, scrollLeft, scrollHorizontal and scrollVertical */ + swipe: true, + maxWidth: 1170, + maxHeight: 600, + }); + + /* -------------------------------------------------------- + 15. Slider One Active + --------------------------------------------------------- */ + $('.ltn__slide-one-active').slick({ + autoplay: false, + autoplaySpeed: 2000, + arrows: true, + dots: true, + fade: true, + cssEase: 'linear', + infinite: true, + speed: 300, + slidesToShow: 1, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 1200, + settings: { + arrows: false, + dots: true, + } + } + ] + }).on('afterChange', function(){ + new WOW().init(); + }); + + /* ltn__slide-two-active */ + $('.ltn__slide-two-active').slick({ + autoplay: false, + autoplaySpeed: 2000, + arrows: false, + dots: true, + fade: true, + cssEase: 'linear', + infinite: true, + speed: 300, + slidesToShow: 1, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 1200, + settings: { + arrows: false, + dots: true, + } + } + ] + }).on('afterChange', function(){ + new WOW().init(); + }); + + + /* -------------------------------------------------------- + 16. Product Slider One + --------------------------------------------------------- */ + $('.ltn__product-slider-one-active').slick({ + arrows: true, + dots: false, + infinite: true, + speed: 300, + slidesToShow: 3, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 992, + settings: { + slidesToShow: 2, + slidesToScroll: 1 + } + }, + { + breakpoint: 768, + settings: { + slidesToShow: 2, + slidesToScroll: 1 + } + }, + { + breakpoint: 580, + settings: { + slidesToShow: 1, + slidesToScroll: 1 + } + } + ] + }); + + + /* -------------------------------------------------------- + 16. Product Slider One + --------------------------------------------------------- */ + $('.ltn__product-slider-item-four-active').slick({ + arrows: true, + dots: false, + infinite: true, + speed: 300, + slidesToShow: 4, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 992, + settings: { + slidesToShow: 3, + slidesToScroll: 1 + } + }, + { + breakpoint: 768, + settings: { + arrows: false, + dots: true, + slidesToShow: 2, + slidesToScroll: 1 + } + }, + { + breakpoint: 580, + settings: { + arrows: false, + dots: true, + slidesToShow: 2, + slidesToScroll: 1 + } + } + ] + }); + + + /* -------------------------------------------------------- + 16. Product Slider One + --------------------------------------------------------- */ + $('.ltn__related-product-slider-one-active').slick({ + arrows: true, + dots: false, + infinite: true, + speed: 300, + slidesToShow: 4, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 992, + settings: { + slidesToShow: 3, + slidesToScroll: 1 + } + }, + { + breakpoint: 768, + settings: { + slidesToShow: 2, + slidesToScroll: 1 + } + }, + { + breakpoint: 580, + settings: { + slidesToShow: 1, + slidesToScroll: 1 + } + } + ] + }); + + /* -------------------------------------------------------- + 17. Tab Product Slider One + --------------------------------------------------------- */ + $('.ltn__tab-product-slider-one-active').slick({ + arrows: true, + dots: false, + infinite: true, + speed: 300, + slidesToShow: 4, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 1200, + settings: { + slidesToShow: 3, + slidesToScroll: 1 + } + }, + { + breakpoint: 992, + settings: { + arrows: false, + dots: true, + slidesToShow: 3, + slidesToScroll: 1 + } + }, + { + breakpoint: 768, + settings: { + arrows: false, + dots: true, + slidesToShow: 2, + slidesToScroll: 1 + } + }, + { + breakpoint: 580, + settings: { + arrows: false, + dots: true, + slidesToShow: 2, + slidesToScroll: 1 + } + } + ] + }); + + /* -------------------------------------------------------- + 18. Blog Slider One + --------------------------------------------------------- */ + $('.ltn__blog-slider-one-active').slick({ + arrows: true, + dots: false, + infinite: true, + speed: 300, + slidesToShow: 3, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 1200, + settings: { + slidesToShow: 2, + slidesToScroll: 1, + arrows: false, + dots: true + } + }, + { + breakpoint: 992, + settings: { + slidesToShow: 2, + slidesToScroll: 1, + arrows: false, + dots: true + } + }, + { + breakpoint: 768, + settings: { + slidesToShow: 1, + slidesToScroll: 1, + arrows: false, + dots: true + } + }, + { + breakpoint: 580, + settings: { + arrows: false, + dots: true, + slidesToShow: 1, + slidesToScroll: 1 + } + } + ] + }); + + /* -------------------------------------------------------- + 19. Testimonial Slider - 1 + --------------------------------------------------------- */ + $('.ltn__testimonial-slider-active').slick({ + arrows: true, + dots: true, + infinite: true, + speed: 300, + slidesToShow: 1, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 992, + settings: { + slidesToShow: 1, + slidesToScroll: 1 + } + }, + { + breakpoint: 768, + settings: { + arrows: false, + slidesToShow: 1, + slidesToScroll: 1 + } + }, + { + breakpoint: 580, + settings: { + arrows: false, + slidesToShow: 1, + slidesToScroll: 1 + } + } + ] + }); + + + /* -------------------------------------------------------- + 20. Testimonial Slider - 2 + --------------------------------------------------------- */ + $('.ltn__testimonial-slider-2-active').slick({ + arrows: true, + dots: false, + infinite: true, + speed: 300, + slidesToShow: 3, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 1200, + settings: { + slidesToShow: 2, + slidesToScroll: 1 + } + }, + { + breakpoint: 992, + settings: { + slidesToShow: 2, + slidesToScroll: 1 + } + }, + { + breakpoint: 768, + settings: { + slidesToShow: 2, + slidesToScroll: 1 + } + }, + { + breakpoint: 580, + settings: { + arrows: false, + dots: true, + slidesToShow: 1, + slidesToScroll: 1 + } + } + ] + }); + + /* -------------------------------------------------------- + 21. Testimonial Slider - 3 + --------------------------------------------------------- */ + $('.ltn__testimonial-slider-3-active').slick({ + arrows: true, + centerMode: true, + centerPadding: '80px', + dots: false, + infinite: true, + speed: 300, + slidesToShow: 3, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 1600, + settings: { + slidesToShow: 2, + slidesToScroll: 1 + } + }, + { + breakpoint: 1200, + settings: { + slidesToShow: 1, + slidesToScroll: 1 + } + }, + { + breakpoint: 992, + settings: { + slidesToShow: 1, + slidesToScroll: 1 + } + }, + { + breakpoint: 768, + settings: { + arrows: false, + slidesToShow: 1, + slidesToScroll: 1 + } + }, + { + breakpoint: 580, + settings: { + centerMode: false, + slidesToShow: 1, + slidesToScroll: 1 + } + } + ] + }); + + /* -------------------------------------------------------- + 22. Category Slider + --------------------------------------------------------- */ + $('.ltn__category-slider-active').slick({ + arrows: true, + dots: false, + infinite: true, + speed: 300, + slidesToShow: 6, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 1200, + settings: { + slidesToShow: 4, + slidesToScroll: 1 + } + }, + { + breakpoint: 992, + settings: { + slidesToShow: 3, + slidesToScroll: 1 + } + }, + { + breakpoint: 768, + settings: { + slidesToShow: 2, + slidesToScroll: 1 + } + }, + { + breakpoint: 580, + settings: { + slidesToShow: 1, + slidesToScroll: 1 + } + } + ] + }); + + + /* -------------------------------------------------------- + 23. Image Slide - 1 (Screenshot) + --------------------------------------------------------- */ + $('.ltn__image-slider-1-active').slick({ + arrows: true, + dots: false, + infinite: true, + speed: 300, + slidesToShow: 5, + slidesToScroll: 1, + centerMode: true, + centerPadding: '0px', + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 992, + settings: { + slidesToShow: 3, + slidesToScroll: 1 + } + }, + { + breakpoint: 768, + settings: { + slidesToShow: 2, + slidesToScroll: 1, + arrows: false, + dots: true + } + }, + { + breakpoint: 580, + settings: { + slidesToShow: 1, + slidesToScroll: 1 + } + } + ] + }); + + /* -------------------------------------------------------- + 24. Image Slide - 2 + --------------------------------------------------------- */ + $('.ltn__image-slider-2-active').slick({ + rtl: false, + arrows: true, + dots: false, + infinite: true, + speed: 300, + slidesToShow: 3, + slidesToScroll: 1, + centerMode: true, + centerPadding: '80px', + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 992, + settings: { + arrows: false, + dots: true, + slidesToShow: 2, + slidesToScroll: 1 + } + }, + { + breakpoint: 768, + settings: { + arrows: false, + dots: true, + slidesToShow: 2, + slidesToScroll: 1, + centerPadding: '50px' + } + }, + { + breakpoint: 580, + settings: { + arrows: false, + dots: true, + slidesToShow: 1, + slidesToScroll: 1, + centerPadding: '50px' + } + } + ] + }); + + /* -------------------------------------------------------- + 25. Image Slide - 3 + --------------------------------------------------------- */ + $('.ltn__image-slider-3-active').slick({ + rtl: false, + arrows: true, + dots: false, + infinite: true, + speed: 300, + slidesToShow: 3, + slidesToScroll: 1, + centerMode: true, + centerPadding: '0px', + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 992, + settings: { + arrows: false, + dots: true, + slidesToShow: 2, + slidesToScroll: 1 + } + }, + { + breakpoint: 768, + settings: { + arrows: false, + dots: true, + slidesToShow: 2, + slidesToScroll: 1, + } + }, + { + breakpoint: 580, + settings: { + arrows: false, + dots: true, + slidesToShow: 1, + slidesToScroll: 1 + } + } + ] + }); + + + /* -------------------------------------------------------- + 26. Image Slide - 4 + --------------------------------------------------------- */ + $('.ltn__image-slider-4-active').slick({ + rtl: false, + arrows: true, + dots: false, + infinite: true, + speed: 300, + slidesToShow: 4, + slidesToScroll: 1, + centerMode: true, + centerPadding: '0px', + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 1200, + settings: { + slidesToShow: 3, + slidesToScroll: 1 + } + }, + { + breakpoint: 992, + settings: { + arrows: false, + dots: true, + slidesToShow: 2, + slidesToScroll: 1 + } + }, + { + breakpoint: 768, + settings: { + arrows: false, + dots: true, + slidesToShow: 2, + slidesToScroll: 1, + } + }, + { + breakpoint: 580, + settings: { + arrows: false, + dots: true, + slidesToShow: 1, + slidesToScroll: 1, + } + } + ] + }); + + + /* -------------------------------------------------------- + 27. Brand Logo + --------------------------------------------------------- */ + if($('.ltn__brand-logo-active').length){ + $('.ltn__brand-logo-active').slick({ + rtl: false, + arrows: false, + dots: false, + infinite: true, + speed: 300, + slidesToShow: 6, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 992, + settings: { + slidesToShow: 4, + slidesToScroll: 1 + } + }, + { + breakpoint: 768, + settings: { + slidesToShow: 3, + slidesToScroll: 1, + arrows: false, + } + }, + { + breakpoint: 580, + settings: { + slidesToShow: 2, + slidesToScroll: 1 + } + } + ] + }); + }; + + /* -------------------------------------------------------- + 28. Blog Gallery (Blog Page ) + --------------------------------------------------------- */ + if($('.ltn__blog-gallery-active').length){ + $('.ltn__blog-gallery-active').slick({ + rtl: false, + arrows: true, + dots: false, + infinite: true, + speed: 300, + slidesToShow: 1, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '' + }); + }; + + /* -------------------------------------------------------- + 29. Countdown + --------------------------------------------------------- */ + $('[data-countdown]').each(function () { + + var $this = $(this), + finalDate = $(this).data('countdown'); + if (!$this.hasClass('countdown-full-format')) { + $this.countdown(finalDate, function (event) { + $this.html(event.strftime('

    %D

    Days

    %H

    Hrs

    %M

    Mins

    %S

    Secs

    ')); + }); + } else { + $this.countdown(finalDate, function (event) { + $this.html(event.strftime('

    %Y

    Years

    %m

    Months

    %W

    Weeks

    %d

    Days

    %H

    Hrs

    %M

    Mins

    %S

    Secs

    ')); + }); + } + + }); + + + /* -------------------------------------------------------- + 30. Counter Up + --------------------------------------------------------- */ + // $('.ltn__counter').counterUp(); + + $('.counter').counterUp({ + delay: 10, + time: 2000 + }); + $('.counter').addClass('animated fadeInDownBig'); + $('h3').addClass('animated fadeIn'); + + + /* -------------------------------------------------------- + 31. Instagram Feed + --------------------------------------------------------- */ + if($('.ltn__instafeed').length){ + $.instagramFeed({ + 'username': 'envato', + 'container': ".ltn__instafeed", + 'display_profile': false, + 'display_biography': false, + 'display_gallery': true, + 'styling': false, + 'items': 12, + "image_size": "600", /* 320 */ + }); + $('.ltn__instafeed').on("DOMNodeInserted", function (e) { + if (e.target.className == 'instagram_gallery') { + $('.ltn__instafeed-slider-2 .' + e.target.className).slick({ + infinite: true, + slidesToShow: 3, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '', + responsive: [{ + breakpoint: 767, + settings: { + slidesToShow: 2 + } + }, { + breakpoint: 575, + settings: { + slidesToShow: 1 + } + }] + }) + $('.ltn__instafeed-slider-1 .' + e.target.className).slick({ + infinite: true, + slidesToShow: 5, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '', + responsive: [{ + breakpoint: 119, + settings: { + slidesToShow: 4 + } + }, { + breakpoint: 991, + settings: { + slidesToShow: 3 + } + }, { + breakpoint: 767, + settings: { + slidesToShow: 2 + } + }, { + breakpoint: 575, + settings: { + slidesToShow: 1 + } + }] + }); + } + }); + }; + + + /* --------------------------------------------------------- + 32. Price Slider + --------------------------------------------------------- */ + $( ".slider-range" ).slider({ + range: true, + min: 50, + max: 5000, + values: [ 50, 1500 ], + slide: function( event, ui ) { + $( ".amount" ).val( "$" + ui.values[ 0 ] + " - $" + ui.values[ 1 ] ); + } + }); + $( ".amount" ).val( "$" + $( ".slider-range" ).slider( "values", 0 ) + + " - $" + $( ".slider-range" ).slider( "values", 1 ) ); + + + /* -------------------------------------------------------- + 33. Quantity plus minus + -------------------------------------------------------- */ + $(".cart-plus-minus").prepend('
    -
    '); + $(".cart-plus-minus").append('
    +
    '); + $(".qtybutton").on("click", function() { + var $button = $(this); + var oldValue = $button.parent().find("input").val(); + if ($button.text() == "+") { + var newVal = parseFloat(oldValue) + 1; + } + else { + if (oldValue > 0) { + var newVal = parseFloat(oldValue) - 1; + } + else { + newVal = 0; + } + } + $button.parent().find("input").val(newVal); + }); + + + /* -------------------------------------------------------- + 34. scrollUp active + -------------------------------------------------------- */ + $.scrollUp({ + scrollText: '', + easingType: 'linear', + scrollSpeed: 900, + animation: 'fade' + }); + + + /* -------------------------------------------------------- + 35. Parallax active ( About Section ) + -------------------------------------------------------- */ + /* + > 1 page e 2 ta call korle 1 ta kaj kore + */ + if($('.ltn__parallax-effect-active').length){ + var scene = $('.ltn__parallax-effect-active').get(0); + var parallaxInstance = new Parallax(scene); + } + + + /* -------------------------------------------------------- + 36. Testimonial Slider 4 + -------------------------------------------------------- */ + var ltn__testimonial_quote_slider = $('.ltn__testimonial-slider-4-active'); + ltn__testimonial_quote_slider.slick({ + autoplay: true, + autoplaySpeed: 3000, + dots: false, + arrows: true, + fade: true, + speed: 1500, + slidesToShow: 1, + slidesToScroll: 1, + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 992, + settings: { + autoplay: false, + slidesToShow: 1, + slidesToScroll: 1, + dots: true, + arrows: false, + } + }, + { + breakpoint: 768, + settings: { + autoplay: false, + slidesToShow: 1, + slidesToScroll: 1, + dots: true, + arrows: false, + } + }, + { + breakpoint: 580, + settings: { + autoplay: false, + slidesToShow: 1, + slidesToScroll: 1, + dots: true, + arrows: false, + } + } + ] + }); + + /* have to write code for bind it with static images */ + ltn__testimonial_quote_slider.on('beforeChange', function (event, slick, currentSlide, nextSlide) { + var liIndex = nextSlide + 1; + var slideImageliIndex = (slick.slideCount == liIndex) ? liIndex - 1 : liIndex; + var cart = $('.ltn__testimonial-slider-4 .slick-slide[data-slick-index="' + slideImageliIndex + '"]').find('.ltn__testimonial-image'); + var imgtodrag = $('.ltn__testimonial-quote-menu li:nth-child(' + liIndex + ')').find("img").eq(0); + if (imgtodrag) { + AnimateTestimonialImage(imgtodrag, cart) + } + }); + + /* have to write code for bind static image to slider accordion to slide index of images */ + $(document).on('click', '.ltn__testimonial-quote-menu li', function (e) { + var el = $(this); + var elIndex = el.prevAll().length; + ltn__testimonial_quote_slider.slick('slickGoTo', elIndex); + var cart = $('.ltn__testimonial-slider-4 .slick-slide[data-slick-index="' + elIndex + '"]').find('.ltn__testimonial-image'); + var imgtodrag = el.find("img").eq(0); + if (imgtodrag) { + AnimateTestimonialImage(imgtodrag, cart) + } + + }); + + + + function AnimateTestimonialImage(imgtodrag, cart) { + var imgclone = imgtodrag.clone().offset({ + top: imgtodrag.offset().top, + left: imgtodrag.offset().left + }).css({ + 'opacity': '0.5', + 'position': 'absolute', + 'height': '130px', + 'width': '130px', + 'z-index': '100' + }).addClass('quote-animated-image').appendTo($('body')).animate({ + 'top': cart.offset().top + 10, + 'left': cart.offset().left + 10, + 'width': 130, + 'height': 130 + }, 300); + + + imgclone.animate({ + 'visibility': 'hidden', + 'opacity': '0' + }, function () { + $(this).remove() + }); + } + + + /*------------------------------------ + Slick Carousel + --------------------------------------*/ + + $('.ltn__testimonial-7-image-slider').slick({ + slidesToShow: 2, + asNavFor: '.ltn__testimonial-7-text-slider', + dots: false, + arrows: false, + focusOnSelect: true, + }); + + $('.ltn__testimonial-7-text-slider').slick({ + slidesToShow: 1, + slidesToScroll: 1, + arrows: true, + dots: false, + draggable: false, + fade: true, + asNavFor: '.ltn__testimonial-7-image-slider', + prevArrow: '', + nextArrow: '', + responsive: [ + { + breakpoint: 600, + settings: { + dots: true, + slidesToShow: 1, + slidesToScroll: 1, + centerPadding: '0px', + } + }, + { + breakpoint: 320, + settings: { + autoplay: false, + dots: true, + slidesToShow: 1, + slidesToScroll: 1, + centerMode: false, + focusOnSelect: false, + } + } + ] + }); + + + + + }); + + + /* -------------------------------------------------------- + 36. Header menu sticky + -------------------------------------------------------- */ + $(window).on('scroll',function() { + var scroll = $(window).scrollTop(); + if (scroll < 445) { + $(".ltn__header-sticky").removeClass("sticky-active"); + } else { + $(".ltn__header-sticky").addClass("sticky-active"); + } + }); + + + $(window).on('load',function(){ + /*----------------- + preloader + ------------------*/ + if($('#preloader').length){ + var preLoder = $("#preloader"); + preLoder.fadeOut(1000); + + }; + + + }); + + + +})(jQuery); \ No newline at end of file diff --git a/themes/nurgul/assets/js/maplace-active.js b/themes/nurgul/assets/js/maplace-active.js new file mode 100644 index 0000000..0dc8efe --- /dev/null +++ b/themes/nurgul/assets/js/maplace-active.js @@ -0,0 +1,210 @@ +$(function() { + + var LocsA = [ + { + lat: 40.740178, + lon: -74.190194, + title: 'Location 1', + html: [ '
    ', + '

    Boston, New York

    ', + '
    5816 S. Coulter Street Amarillo, TX 79119
    ', + '

    0123456789

    ', + '', + '
    ' + ].join(''), + icon: 'img/icons/map-marker-2.png', + animation: google.maps.Animation.BOUNCE + }, + { + lat: 40.733617, + lon: -74.171150, + title: 'Location 2', + html: [ '
    ', + '

    Boston, New York

    ', + '
    5816 S. Coulter Street Amarillo, TX 79119
    ', + '

    0123456789

    ', + '', + '
    ' + ].join(''), + icon: 'img/icons/map-marker-2.png', + animation: google.maps.Animation.BOUNCE + }, + { + lat: 40.743011, + lon: -74.247100, + title: 'Location 3', + html: [ '
    ', + '

    Boston, New York

    ', + '
    5816 S. Coulter Street Amarillo, TX 79119
    ', + '

    0123456789

    ', + '', + '
    ' + ].join(''), + icon: 'img/icons/map-marker-2.png', + animation: google.maps.Animation.BOUNCE + }, + { + lat: 40.711150, + lon: -74.214998, + title: 'Location 4', + html: [ '
    ', + '

    Boston, New York

    ', + '
    5816 S. Coulter Street Amarillo, TX 79119
    ', + '

    0123456789

    ', + '', + '
    ' + ].join(''), + icon: 'img/icons/map-marker-2.png', + animation: google.maps.Animation.BOUNCE + }, + { + lat: 40.690010, + lon: -74.151753, + title: 'Location 5', + html: [ '
    ', + '

    Boston, New York

    ', + '
    5816 S. Coulter Street Amarillo, TX 79119
    ', + '

    0123456789

    ', + '', + '
    ' + ].join(''), + icon: 'img/icons/map-marker-2.png', + animation: google.maps.Animation.BOUNCE + }, + { + lat: 40.697590, + lon: -74.263164, + title: 'Location 6', + html: [ '
    ', + '

    Boston, New York

    ', + '
    5816 S. Coulter Street Amarillo, TX 79119
    ', + '

    0123456789

    ', + '', + '
    ' + ].join(''), + icon: 'img/icons/map-marker-2.png', + animation: google.maps.Animation.BOUNCE + }, + { + lat: 40.729979, + lon: -74.271992, + title: 'Location 7', + html: [ '
    ', + '

    Boston, New York

    ', + '
    5816 S. Coulter Street Amarillo, TX 79119
    ', + '

    0123456789

    ', + '', + '
    ' + ].join(''), + icon: 'img/icons/map-marker-2.png', + animation: google.maps.Animation.BOUNCE + }, + { + lat: 40.749702, + lon: -74.163631, + title: 'Location 8', + html: [ '
    ', + '

    Boston, New York

    ', + '
    5816 S. Coulter Street Amarillo, TX 79119
    ', + '

    0123456789

    ', + '', + '
    ' + ].join(''), + icon: 'img/icons/map-marker-2.png', + animation: google.maps.Animation.BOUNCE + }, + { + lat: 40.718971, + lon: -74.323219, + title: 'Location 9', + html: [ '
    ', + '

    Boston, New York

    ', + '
    5816 S. Coulter Street Amarillo, TX 79119
    ', + '

    0123456789

    ', + '', + '
    ' + ].join(''), + icon: 'img/icons/map-marker-2.png', + animation: google.maps.Animation.BOUNCE + }, + { + lat: 40.748350, + lon: -74.323219, + title: 'Location 10', + html: [ '
    ', + '

    Boston, New York

    ', + '
    5816 S. Coulter Street Amarillo, TX 79119
    ', + '

    0123456789

    ', + '', + '
    ' + ].join(''), + icon: 'img/icons/map-marker-2.png', + animation: google.maps.Animation.BOUNCE + }, + { + lat: 40.740178, + lon: -74.190194, + title: 'Location 11', + html: [ '
    ', + '

    Boston, New York

    ', + '
    5816 S. Coulter Street Amarillo, TX 79119
    ', + '

    0123456789

    ', + '', + '
    ' + ].join(''), + icon: 'img/icons/map-marker-2.png', + animation: google.maps.Animation.BOUNCE + } + + ]; + new Maplace({ + locations: LocsA, + controls_on_map: true, + map_options: { + zoom: 13, + scrollwheel: false, + stopover: true + }, + stroke_options: { + strokeColor: '#f10', + strokeOpacity: 0.8, + strokeWeight: 2, + fillColor: '#f10', + fillOpacity: 0.4 + } + }).Load(); + + }); \ No newline at end of file diff --git a/themes/nurgul/assets/js/plugins.js b/themes/nurgul/assets/js/plugins.js new file mode 100644 index 0000000..a961632 --- /dev/null +++ b/themes/nurgul/assets/js/plugins.js @@ -0,0 +1,330 @@ +/* =================================================== +>>> TABLE OF CONTENTS: +====================================================== +1. Avoid `console` errors in browsers that lack a console. +2. jQuery v3.4.1 +3. Popper Bootstrap +4. Bootstrap v4.3.1 +5. Slick slider jQuery +6. Isotope jQuery +7. imagesLoaded jQuery +8. Lightcase - Popup jQuery +9. CounterUp jQuery +10. Countdown jQuery +11. Instafeed jQuery +12. Waypoints jQuery +13. Nice Select +14. jQuery UI / price range +15. scrollup jquery +16. One Page Navigation ( jQuery Easing Plugin ) +17. WOW jQuery +18. Parallax jQuery +19. Maplace.js + + +=================================================== */ + + +/*------------------------------------------------------------- + 1. Avoid `console` errors in browsers that lack a console. +---------------------------------------------------------------*/ +(function() { + var method; + var noop = function () {}; + var methods = [ + 'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error', + 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', + 'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd', + 'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn' + ]; + var length = methods.length; + var console = (window.console = window.console || {}); + + while (length--) { + method = methods[length]; + + // Only stub undefined methods. + if (!console[method]) { + console[method] = noop; + } + } +}()); + +// Place any jQuery/helper plugins in here. + +/*------------------------------------------------------------- + # Modernizr +---------------------------------------------------------------*/ +/* Modernizr 2.8.3 (Custom Build) | MIT & BSD + * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load + */ +;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b)&&c(b).matches||!1;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function l(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function m(){var a=s.elements;return typeof a=="string"?a.split(" "):a}function n(a){var b=j[a[h]];return b||(b={},i++,a[h]=i,j[i]=b),b}function o(a,c,d){c||(c=b);if(k)return c.createElement(a);d||(d=n(c));var g;return d.cache[a]?g=d.cache[a].cloneNode():f.test(a)?g=(d.cache[a]=d.createElem(a)).cloneNode():g=d.createElem(a),g.canHaveChildren&&!e.test(a)&&!g.tagUrn?d.frag.appendChild(g):g}function p(a,c){a||(a=b);if(k)return a.createDocumentFragment();c=c||n(a);var d=c.frag.cloneNode(),e=0,f=m(),g=f.length;for(;e",g="hidden"in a,k=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){g=!0,k=!0}})();var s={elements:d.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:c,shivCSS:d.shivCSS!==!1,supportsUnknownElements:k,shivMethods:d.shivMethods!==!1,type:"default",shivDocument:r,createElement:o,createDocumentFragment:p};a.html5=s,r(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=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))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(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&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(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&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(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 ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);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&&E){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=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(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(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===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]||se.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]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(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(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(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=se.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 j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.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 S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(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 je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.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)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.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),m(t)&&(t=t.call(e,n,S.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)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.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"===S.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"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(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)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(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?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.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.mouseenter(e).mouseleave(t||e)}}),S.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){S.fn[n]=function(e,t){return 0=Math.abs(t.width-n)&&(n=t.width),1>=Math.abs(t.height-o)&&(o=t.height),{x:e.offsetLeft,y:e.offsetTop,width:n,height:o}}function h(e){return"html"===s(e)?e:e.assignedSlot||e.parentNode||(r(e)?e.host:null)||f(e)}function m(e){return 0<=["html","body","#document"].indexOf(s(e))?e.ownerDocument.body:o(e)&&l(e)?e:m(h(e))}function v(e,n){var o;void 0===n&&(n=[]);var r=m(e);return e=r===(null==(o=e.ownerDocument)?void 0:o.body),o=t(r),r=e?[o].concat(o.visualViewport||[],l(r)?r:[]):r,n=n.concat(r),e?n:n.concat(v(h(r)))}function g(e){return o(e)&&"fixed"!==c(e).position?e.offsetParent:null}function y(e){for(var n=t(e),r=g(e);r&&0<=["table","td","th"].indexOf(s(r))&&"static"===c(r).position;)r=g(r);if(r&&("html"===s(r)||"body"===s(r)&&"static"===c(r).position))return n;if(!r)e:{if(r=-1!==navigator.userAgent.toLowerCase().indexOf("firefox"),-1===navigator.userAgent.indexOf("Trident")||!o(e)||"fixed"!==c(e).position)for(e=h(e);o(e)&&0>["html","body"].indexOf(s(e));){var i=c(e);if("none"!==i.transform||"none"!==i.perspective||"paint"===i.contain||-1!==["transform","perspective"].indexOf(i.willChange)||r&&"filter"===i.willChange||r&&i.filter&&"none"!==i.filter){r=e;break e}e=e.parentNode}r=null}return r||n}function b(e){function t(e){o.add(e.name),[].concat(e.requires||[],e.requiresIfExists||[]).forEach((function(e){o.has(e)||(e=n.get(e))&&t(e)})),r.push(e)}var n=new Map,o=new Set,r=[];return e.forEach((function(e){n.set(e.name,e)})),e.forEach((function(e){o.has(e.name)||t(e)})),r}function w(e){var t;return function(){return t||(t=new Promise((function(n){Promise.resolve().then((function(){t=void 0,n(e())}))}))),t}}function x(e){return e.split("-")[0]}function O(e,t){var n=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(n&&r(n))do{if(t&&e.isSameNode(t))return!0;t=t.parentNode||t.host}while(t);return!1}function j(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function E(e,n){if("viewport"===n){n=t(e);var r=f(e);n=n.visualViewport;var s=r.clientWidth;r=r.clientHeight;var l=0,u=0;n&&(s=n.width,r=n.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(l=n.offsetLeft,u=n.offsetTop)),e=j(e={width:s,height:r,x:l+p(e),y:u})}else o(n)?((e=i(n)).top+=n.clientTop,e.left+=n.clientLeft,e.bottom=e.top+n.clientHeight,e.right=e.left+n.clientWidth,e.width=n.clientWidth,e.height=n.clientHeight,e.x=e.left,e.y=e.top):(u=f(e),e=f(u),s=a(u),n=null==(r=u.ownerDocument)?void 0:r.body,r=U(e.scrollWidth,e.clientWidth,n?n.scrollWidth:0,n?n.clientWidth:0),l=U(e.scrollHeight,e.clientHeight,n?n.scrollHeight:0,n?n.clientHeight:0),u=-s.scrollLeft+p(u),s=-s.scrollTop,"rtl"===c(n||e).direction&&(u+=U(e.clientWidth,n?n.clientWidth:0)-r),e=j({width:r,height:l,x:u,y:s}));return e}function D(e,t,r){return t="clippingParents"===t?function(e){var t=v(h(e)),r=0<=["absolute","fixed"].indexOf(c(e).position)&&o(e)?y(e):e;return n(r)?t.filter((function(e){return n(e)&&O(e,r)&&"body"!==s(e)})):[]}(e):[].concat(t),(r=(r=[].concat(t,[r])).reduce((function(t,n){return n=E(e,n),t.top=U(n.top,t.top),t.right=z(n.right,t.right),t.bottom=z(n.bottom,t.bottom),t.left=U(n.left,t.left),t}),E(e,r[0]))).width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}function L(e){return 0<=["top","bottom"].indexOf(e)?"x":"y"}function M(e){var t=e.reference,n=e.element,o=(e=e.placement)?x(e):null;e=e?e.split("-")[1]:null;var r=t.x+t.width/2-n.width/2,i=t.y+t.height/2-n.height/2;switch(o){case"top":r={x:r,y:t.y-n.height};break;case"bottom":r={x:r,y:t.y+t.height};break;case"right":r={x:t.x+t.width,y:i};break;case"left":r={x:t.x-n.width,y:i};break;default:r={x:t.x,y:t.y}}if(null!=(o=o?L(o):null))switch(i="y"===o?"height":"width",e){case"start":r[o]-=t[i]/2-n[i]/2;break;case"end":r[o]+=t[i]/2-n[i]/2}return r}function P(e){return Object.assign({},{top:0,right:0,bottom:0,left:0},e)}function k(e,t){return t.reduce((function(t,n){return t[n]=e,t}),{})}function W(e,t){void 0===t&&(t={});var o=t;t=void 0===(t=o.placement)?e.placement:t;var r=o.boundary,a=void 0===r?"clippingParents":r,s=void 0===(r=o.rootBoundary)?"viewport":r;r=void 0===(r=o.elementContext)?"popper":r;var p=o.altBoundary,c=void 0!==p&&p;o=P("number"!=typeof(o=void 0===(o=o.padding)?0:o)?o:k(o,N));var l=e.elements.reference;p=e.rects.popper,a=D(n(c=e.elements[c?"popper"===r?"reference":"popper":r])?c:c.contextElement||f(e.elements.popper),a,s),c=M({reference:s=i(l),element:p,strategy:"absolute",placement:t}),p=j(Object.assign({},p,c)),s="popper"===r?p:s;var u={top:a.top-s.top+o.top,bottom:s.bottom-a.bottom+o.bottom,left:a.left-s.left+o.left,right:s.right-a.right+o.right};if(e=e.modifiersData.offset,"popper"===r&&e){var d=e[t];Object.keys(u).forEach((function(e){var t=0<=["right","bottom"].indexOf(e)?1:-1,n=0<=["top","bottom"].indexOf(e)?"y":"x";u[e]+=d[n]*t}))}return u}function A(){for(var e=arguments.length,t=Array(e),n=0;n(g.devicePixelRatio||1)?"translate("+e+"px, "+u+"px)":"translate3d("+e+"px, "+u+"px, 0)",h)):Object.assign({},o,((n={})[v]=a?u+"px":"",n[m]=d?e+"px":"",n.transform="",n))}function T(e){return e.replace(/left|right|bottom|top/g,(function(e){return ee[e]}))}function R(e){return e.replace(/start|end/g,(function(e){return te[e]}))}function S(e,t,n){return void 0===n&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function C(e){return["top","right","bottom","left"].some((function(t){return 0<=e[t]}))}var q=Math.round,N=["top","bottom","right","left"],V=N.reduce((function(e,t){return e.concat([t+"-start",t+"-end"])}),[]),I=[].concat(N,["auto"]).reduce((function(e,t){return e.concat([t,t+"-start",t+"-end"])}),[]),_="beforeRead read afterRead beforeMain main afterMain beforeWrite write afterWrite".split(" "),U=Math.max,z=Math.min,F=Math.round,X={placement:"bottom",modifiers:[],strategy:"absolute"},Y={passive:!0},G={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(e){var n=e.state,o=e.instance,r=(e=e.options).scroll,i=void 0===r||r,a=void 0===(e=e.resize)||e,s=t(n.elements.popper),f=[].concat(n.scrollParents.reference,n.scrollParents.popper);return i&&f.forEach((function(e){e.addEventListener("scroll",o.update,Y)})),a&&s.addEventListener("resize",o.update,Y),function(){i&&f.forEach((function(e){e.removeEventListener("scroll",o.update,Y)})),a&&s.removeEventListener("resize",o.update,Y)}},data:{}},J={name:"popperOffsets",enabled:!0,phase:"read",fn:function(e){var t=e.state;t.modifiersData[e.name]=M({reference:t.rects.reference,element:t.rects.popper,strategy:"absolute",placement:t.placement})},data:{}},K={top:"auto",right:"auto",bottom:"auto",left:"auto"},Q={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(e){var t=e.state,n=e.options;e=void 0===(e=n.gpuAcceleration)||e;var o=n.adaptive;o=void 0===o||o,n=void 0===(n=n.roundOffsets)||n,e={placement:x(t.placement),popper:t.elements.popper,popperRect:t.rects.popper,gpuAcceleration:e},null!=t.modifiersData.popperOffsets&&(t.styles.popper=Object.assign({},t.styles.popper,H(Object.assign({},e,{offsets:t.modifiersData.popperOffsets,position:t.options.strategy,adaptive:o,roundOffsets:n})))),null!=t.modifiersData.arrow&&(t.styles.arrow=Object.assign({},t.styles.arrow,H(Object.assign({},e,{offsets:t.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:n})))),t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-placement":t.placement})},data:{}},Z={name:"applyStyles",enabled:!0,phase:"write",fn:function(e){var t=e.state;Object.keys(t.elements).forEach((function(e){var n=t.styles[e]||{},r=t.attributes[e]||{},i=t.elements[e];o(i)&&s(i)&&(Object.assign(i.style,n),Object.keys(r).forEach((function(e){var t=r[e];!1===t?i.removeAttribute(e):i.setAttribute(e,!0===t?"":t)})))}))},effect:function(e){var t=e.state,n={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(t.elements.popper.style,n.popper),t.styles=n,t.elements.arrow&&Object.assign(t.elements.arrow.style,n.arrow),function(){Object.keys(t.elements).forEach((function(e){var r=t.elements[e],i=t.attributes[e]||{};e=Object.keys(t.styles.hasOwnProperty(e)?t.styles[e]:n[e]).reduce((function(e,t){return e[t]="",e}),{}),o(r)&&s(r)&&(Object.assign(r.style,e),Object.keys(i).forEach((function(e){r.removeAttribute(e)})))}))}},requires:["computeStyles"]},$={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(e){var t=e.state,n=e.name,o=void 0===(e=e.options.offset)?[0,0]:e,r=(e=I.reduce((function(e,n){var r=t.rects,i=x(n),a=0<=["left","top"].indexOf(i)?-1:1,s="function"==typeof o?o(Object.assign({},r,{placement:n})):o;return r=(r=s[0])||0,s=((s=s[1])||0)*a,i=0<=["left","right"].indexOf(i)?{x:s,y:r}:{x:r,y:s},e[n]=i,e}),{}))[t.placement],i=r.x;r=r.y,null!=t.modifiersData.popperOffsets&&(t.modifiersData.popperOffsets.x+=i,t.modifiersData.popperOffsets.y+=r),t.modifiersData[n]=e}},ee={left:"right",right:"left",bottom:"top",top:"bottom"},te={start:"end",end:"start"},ne={name:"flip",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options;if(e=e.name,!t.modifiersData[e]._skip){var o=n.mainAxis;o=void 0===o||o;var r=n.altAxis;r=void 0===r||r;var i=n.fallbackPlacements,a=n.padding,s=n.boundary,f=n.rootBoundary,p=n.altBoundary,c=n.flipVariations,l=void 0===c||c,u=n.allowedAutoPlacements;c=x(n=t.options.placement),i=i||(c!==n&&l?function(e){if("auto"===x(e))return[];var t=T(e);return[R(e),t,R(t)]}(n):[T(n)]);var d=[n].concat(i).reduce((function(e,n){return e.concat("auto"===x(n)?function(e,t){void 0===t&&(t={});var n=t.boundary,o=t.rootBoundary,r=t.padding,i=t.flipVariations,a=t.allowedAutoPlacements,s=void 0===a?I:a,f=t.placement.split("-")[1];0===(i=(t=f?i?V:V.filter((function(e){return e.split("-")[1]===f})):N).filter((function(e){return 0<=s.indexOf(e)}))).length&&(i=t);var p=i.reduce((function(t,i){return t[i]=W(e,{placement:i,boundary:n,rootBoundary:o,padding:r})[x(i)],t}),{});return Object.keys(p).sort((function(e,t){return p[e]-p[t]}))}(t,{placement:n,boundary:s,rootBoundary:f,padding:a,flipVariations:l,allowedAutoPlacements:u}):n)}),[]);n=t.rects.reference,i=t.rects.popper;var h=new Map;c=!0;for(var m=d[0],v=0;vi[O]&&(b=T(b)),O=T(b),w=[],o&&w.push(0>=j[y]),r&&w.push(0>=j[b],0>=j[O]),w.every((function(e){return e}))){m=g,c=!1;break}h.set(g,w)}if(c)for(o=function(e){var t=d.find((function(t){if(t=h.get(t))return t.slice(0,e).every((function(e){return e}))}));if(t)return m=t,"break"},r=l?3:1;0[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter(t=>t.matches(e)),parents(t,e){const s=[];let i=t.parentNode;for(;i&&i.nodeType===Node.ELEMENT_NODE&&3!==i.nodeType;)i.matches(e)&&s.push(i),i=i.parentNode;return s},prev(t,e){let s=t.previousElementSibling;for(;s;){if(s.matches(e))return[s];s=s.previousElementSibling}return[]},next(t,e){let s=t.nextElementSibling;for(;s;){if(s.matches(e))return[s];s=s.nextElementSibling}return[]}},n=t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t},o=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let s=t.getAttribute("href");if(!s||!s.includes("#")&&!s.startsWith("."))return null;s.includes("#")&&!s.startsWith("#")&&(s="#"+s.split("#")[1]),e=s&&"#"!==s?s.trim():null}return e},r=t=>{const e=o(t);return e&&document.querySelector(e)?e:null},a=t=>{const e=o(t);return e?document.querySelector(e):null},l=t=>{t.dispatchEvent(new Event("transitionend"))},c=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),h=t=>c(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?i.findOne(t):null,d=(t,e,s)=>{Object.keys(s).forEach(i=>{const n=s[i],o=e[i],r=o&&c(o)?"element":null==(a=o)?""+a:{}.toString.call(a).match(/\s([a-z]+)/i)[1].toLowerCase();var a;if(!new RegExp(n).test(r))throw new TypeError(`${t.toUpperCase()}: Option "${i}" provided type "${r}" but expected type "${n}".`)})},u=t=>!(!c(t)||0===t.getClientRects().length)&&"visible"===getComputedStyle(t).getPropertyValue("visibility"),g=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),p=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?p(t.parentNode):null},f=()=>{},m=t=>t.offsetHeight,_=()=>{const{jQuery:t}=window;return t&&!document.body.hasAttribute("data-bs-no-jquery")?t:null},b=[],v=()=>"rtl"===document.documentElement.dir,y=t=>{var e;e=()=>{const e=_();if(e){const s=t.NAME,i=e.fn[s];e.fn[s]=t.jQueryInterface,e.fn[s].Constructor=t,e.fn[s].noConflict=()=>(e.fn[s]=i,t.jQueryInterface)}},"loading"===document.readyState?(b.length||document.addEventListener("DOMContentLoaded",()=>{b.forEach(t=>t())}),b.push(e)):e()},w=t=>{"function"==typeof t&&t()},E=(t,e,s=!0)=>{if(!s)return void w(t);const i=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:s}=window.getComputedStyle(t);const i=Number.parseFloat(e),n=Number.parseFloat(s);return i||n?(e=e.split(",")[0],s=s.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(s))):0})(e)+5;let n=!1;const o=({target:s})=>{s===e&&(n=!0,e.removeEventListener("transitionend",o),w(t))};e.addEventListener("transitionend",o),setTimeout(()=>{n||l(e)},i)},A=(t,e,s,i)=>{let n=t.indexOf(e);if(-1===n)return t[!s&&i?t.length-1:0];const o=t.length;return n+=s?1:-1,i&&(n=(n+o)%o),t[Math.max(0,Math.min(n,o-1))]},T=/[^.]*(?=\..*)\.|.*/,C=/\..*/,k=/::\d+$/,L={};let O=1;const D={mouseenter:"mouseover",mouseleave:"mouseout"},I=/^(mouseenter|mouseleave)/i,N=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function S(t,e){return e&&`${e}::${O++}`||t.uidEvent||O++}function x(t){const e=S(t);return t.uidEvent=e,L[e]=L[e]||{},L[e]}function M(t,e,s=null){const i=Object.keys(t);for(let n=0,o=i.length;nfunction(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};i?i=t(i):s=t(s)}const[o,r,a]=P(e,s,i),l=x(t),c=l[a]||(l[a]={}),h=M(c,r,o?s:null);if(h)return void(h.oneOff=h.oneOff&&n);const d=S(r,e.replace(T,"")),u=o?function(t,e,s){return function i(n){const o=t.querySelectorAll(e);for(let{target:r}=n;r&&r!==this;r=r.parentNode)for(let a=o.length;a--;)if(o[a]===r)return n.delegateTarget=r,i.oneOff&&B.off(t,n.type,e,s),s.apply(r,[n]);return null}}(t,s,i):function(t,e){return function s(i){return i.delegateTarget=t,s.oneOff&&B.off(t,i.type,e),e.apply(t,[i])}}(t,s);u.delegationSelector=o?s:null,u.originalHandler=r,u.oneOff=n,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function H(t,e,s,i,n){const o=M(e[s],i,n);o&&(t.removeEventListener(s,o,Boolean(n)),delete e[s][o.uidEvent])}function R(t){return t=t.replace(C,""),D[t]||t}const B={on(t,e,s,i){j(t,e,s,i,!1)},one(t,e,s,i){j(t,e,s,i,!0)},off(t,e,s,i){if("string"!=typeof e||!t)return;const[n,o,r]=P(e,s,i),a=r!==e,l=x(t),c=e.startsWith(".");if(void 0!==o){if(!l||!l[r])return;return void H(t,l,r,o,n?s:null)}c&&Object.keys(l).forEach(s=>{!function(t,e,s,i){const n=e[s]||{};Object.keys(n).forEach(o=>{if(o.includes(i)){const i=n[o];H(t,e,s,i.originalHandler,i.delegationSelector)}})}(t,l,s,e.slice(1))});const h=l[r]||{};Object.keys(h).forEach(s=>{const i=s.replace(k,"");if(!a||e.includes(i)){const e=h[s];H(t,l,r,e.originalHandler,e.delegationSelector)}})},trigger(t,e,s){if("string"!=typeof e||!t)return null;const i=_(),n=R(e),o=e!==n,r=N.has(n);let a,l=!0,c=!0,h=!1,d=null;return o&&i&&(a=i.Event(e,s),i(t).trigger(a),l=!a.isPropagationStopped(),c=!a.isImmediatePropagationStopped(),h=a.isDefaultPrevented()),r?(d=document.createEvent("HTMLEvents"),d.initEvent(n,l,!0)):d=new CustomEvent(e,{bubbles:l,cancelable:!0}),void 0!==s&&Object.keys(s).forEach(t=>{Object.defineProperty(d,t,{get:()=>s[t]})}),h&&d.preventDefault(),c&&t.dispatchEvent(d),d.defaultPrevented&&void 0!==a&&a.preventDefault(),d}},$=new Map;var W={set(t,e,s){$.has(t)||$.set(t,new Map);const i=$.get(t);i.has(e)||0===i.size?i.set(e,s):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(i.keys())[0]}.`)},get:(t,e)=>$.has(t)&&$.get(t).get(e)||null,remove(t,e){if(!$.has(t))return;const s=$.get(t);s.delete(e),0===s.size&&$.delete(t)}};class q{constructor(t){(t=h(t))&&(this._element=t,W.set(this._element,this.constructor.DATA_KEY,this))}dispose(){W.remove(this._element,this.constructor.DATA_KEY),B.off(this._element,this.constructor.EVENT_KEY),Object.getOwnPropertyNames(this).forEach(t=>{this[t]=null})}_queueCallback(t,e,s=!0){E(t,e,s)}static getInstance(t){return W.get(t,this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.0.2"}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}static get DATA_KEY(){return"bs."+this.NAME}static get EVENT_KEY(){return"."+this.DATA_KEY}}class z extends q{static get NAME(){return"alert"}close(t){const e=t?this._getRootElement(t):this._element,s=this._triggerCloseEvent(e);null===s||s.defaultPrevented||this._removeElement(e)}_getRootElement(t){return a(t)||t.closest(".alert")}_triggerCloseEvent(t){return B.trigger(t,"close.bs.alert")}_removeElement(t){t.classList.remove("show");const e=t.classList.contains("fade");this._queueCallback(()=>this._destroyElement(t),t,e)}_destroyElement(t){t.remove(),B.trigger(t,"closed.bs.alert")}static jQueryInterface(t){return this.each((function(){const e=z.getOrCreateInstance(this);"close"===t&&e[t](this)}))}static handleDismiss(t){return function(e){e&&e.preventDefault(),t.close(this)}}}B.on(document,"click.bs.alert.data-api",'[data-bs-dismiss="alert"]',z.handleDismiss(new z)),y(z);class F extends q{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){const e=F.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}function U(t){return"true"===t||"false"!==t&&(t===Number(t).toString()?Number(t):""===t||"null"===t?null:t)}function K(t){return t.replace(/[A-Z]/g,t=>"-"+t.toLowerCase())}B.on(document,"click.bs.button.data-api",'[data-bs-toggle="button"]',t=>{t.preventDefault();const e=t.target.closest('[data-bs-toggle="button"]');F.getOrCreateInstance(e).toggle()}),y(F);const V={setDataAttribute(t,e,s){t.setAttribute("data-bs-"+K(e),s)},removeDataAttribute(t,e){t.removeAttribute("data-bs-"+K(e))},getDataAttributes(t){if(!t)return{};const e={};return Object.keys(t.dataset).filter(t=>t.startsWith("bs")).forEach(s=>{let i=s.replace(/^bs/,"");i=i.charAt(0).toLowerCase()+i.slice(1,i.length),e[i]=U(t.dataset[s])}),e},getDataAttribute:(t,e)=>U(t.getAttribute("data-bs-"+K(e))),offset(t){const e=t.getBoundingClientRect();return{top:e.top+document.body.scrollTop,left:e.left+document.body.scrollLeft}},position:t=>({top:t.offsetTop,left:t.offsetLeft})},Q={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},X={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},Y="next",G="prev",Z="left",J="right",tt={ArrowLeft:J,ArrowRight:Z};class et extends q{constructor(t,e){super(t),this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._indicatorsElement=i.findOne(".carousel-indicators",this._element),this._touchSupported="ontouchstart"in document.documentElement||navigator.maxTouchPoints>0,this._pointerEvent=Boolean(window.PointerEvent),this._addEventListeners()}static get Default(){return Q}static get NAME(){return"carousel"}next(){this._slide(Y)}nextWhenVisible(){!document.hidden&&u(this._element)&&this.next()}prev(){this._slide(G)}pause(t){t||(this._isPaused=!0),i.findOne(".carousel-item-next, .carousel-item-prev",this._element)&&(l(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null}cycle(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config&&this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))}to(t){this._activeElement=i.findOne(".active.carousel-item",this._element);const e=this._getItemIndex(this._activeElement);if(t>this._items.length-1||t<0)return;if(this._isSliding)return void B.one(this._element,"slid.bs.carousel",()=>this.to(t));if(e===t)return this.pause(),void this.cycle();const s=t>e?Y:G;this._slide(s,this._items[t])}_getConfig(t){return t={...Q,...V.getDataAttributes(this._element),..."object"==typeof t?t:{}},d("carousel",t,X),t}_handleSwipe(){const t=Math.abs(this.touchDeltaX);if(t<=40)return;const e=t/this.touchDeltaX;this.touchDeltaX=0,e&&this._slide(e>0?J:Z)}_addEventListeners(){this._config.keyboard&&B.on(this._element,"keydown.bs.carousel",t=>this._keydown(t)),"hover"===this._config.pause&&(B.on(this._element,"mouseenter.bs.carousel",t=>this.pause(t)),B.on(this._element,"mouseleave.bs.carousel",t=>this.cycle(t))),this._config.touch&&this._touchSupported&&this._addTouchEventListeners()}_addTouchEventListeners(){const t=t=>{!this._pointerEvent||"pen"!==t.pointerType&&"touch"!==t.pointerType?this._pointerEvent||(this.touchStartX=t.touches[0].clientX):this.touchStartX=t.clientX},e=t=>{this.touchDeltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this.touchStartX},s=t=>{!this._pointerEvent||"pen"!==t.pointerType&&"touch"!==t.pointerType||(this.touchDeltaX=t.clientX-this.touchStartX),this._handleSwipe(),"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout(t=>this.cycle(t),500+this._config.interval))};i.find(".carousel-item img",this._element).forEach(t=>{B.on(t,"dragstart.bs.carousel",t=>t.preventDefault())}),this._pointerEvent?(B.on(this._element,"pointerdown.bs.carousel",e=>t(e)),B.on(this._element,"pointerup.bs.carousel",t=>s(t)),this._element.classList.add("pointer-event")):(B.on(this._element,"touchstart.bs.carousel",e=>t(e)),B.on(this._element,"touchmove.bs.carousel",t=>e(t)),B.on(this._element,"touchend.bs.carousel",t=>s(t)))}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=tt[t.key];e&&(t.preventDefault(),this._slide(e))}_getItemIndex(t){return this._items=t&&t.parentNode?i.find(".carousel-item",t.parentNode):[],this._items.indexOf(t)}_getItemByOrder(t,e){const s=t===Y;return A(this._items,e,s,this._config.wrap)}_triggerSlideEvent(t,e){const s=this._getItemIndex(t),n=this._getItemIndex(i.findOne(".active.carousel-item",this._element));return B.trigger(this._element,"slide.bs.carousel",{relatedTarget:t,direction:e,from:n,to:s})}_setActiveIndicatorElement(t){if(this._indicatorsElement){const e=i.findOne(".active",this._indicatorsElement);e.classList.remove("active"),e.removeAttribute("aria-current");const s=i.find("[data-bs-target]",this._indicatorsElement);for(let e=0;e{B.trigger(this._element,"slid.bs.carousel",{relatedTarget:r,direction:u,from:o,to:a})};if(this._element.classList.contains("slide")){r.classList.add(d),m(r),n.classList.add(h),r.classList.add(h);const t=()=>{r.classList.remove(h,d),r.classList.add("active"),n.classList.remove("active",d,h),this._isSliding=!1,setTimeout(g,0)};this._queueCallback(t,n,!0)}else n.classList.remove("active"),r.classList.add("active"),this._isSliding=!1,g();l&&this.cycle()}_directionToOrder(t){return[J,Z].includes(t)?v()?t===Z?G:Y:t===Z?Y:G:t}_orderToDirection(t){return[Y,G].includes(t)?v()?t===G?Z:J:t===G?J:Z:t}static carouselInterface(t,e){const s=et.getOrCreateInstance(t,e);let{_config:i}=s;"object"==typeof e&&(i={...i,...e});const n="string"==typeof e?e:i.slide;if("number"==typeof e)s.to(e);else if("string"==typeof n){if(void 0===s[n])throw new TypeError(`No method named "${n}"`);s[n]()}else i.interval&&i.ride&&(s.pause(),s.cycle())}static jQueryInterface(t){return this.each((function(){et.carouselInterface(this,t)}))}static dataApiClickHandler(t){const e=a(this);if(!e||!e.classList.contains("carousel"))return;const s={...V.getDataAttributes(e),...V.getDataAttributes(this)},i=this.getAttribute("data-bs-slide-to");i&&(s.interval=!1),et.carouselInterface(e,s),i&&et.getInstance(e).to(i),t.preventDefault()}}B.on(document,"click.bs.carousel.data-api","[data-bs-slide], [data-bs-slide-to]",et.dataApiClickHandler),B.on(window,"load.bs.carousel.data-api",()=>{const t=i.find('[data-bs-ride="carousel"]');for(let e=0,s=t.length;et===this._element);null!==n&&o.length&&(this._selector=n,this._triggerArray.push(e))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}static get Default(){return st}static get NAME(){return"collapse"}toggle(){this._element.classList.contains("show")?this.hide():this.show()}show(){if(this._isTransitioning||this._element.classList.contains("show"))return;let t,e;this._parent&&(t=i.find(".show, .collapsing",this._parent).filter(t=>"string"==typeof this._config.parent?t.getAttribute("data-bs-parent")===this._config.parent:t.classList.contains("collapse")),0===t.length&&(t=null));const s=i.findOne(this._selector);if(t){const i=t.find(t=>s!==t);if(e=i?nt.getInstance(i):null,e&&e._isTransitioning)return}if(B.trigger(this._element,"show.bs.collapse").defaultPrevented)return;t&&t.forEach(t=>{s!==t&&nt.collapseInterface(t,"hide"),e||W.set(t,"bs.collapse",null)});const n=this._getDimension();this._element.classList.remove("collapse"),this._element.classList.add("collapsing"),this._element.style[n]=0,this._triggerArray.length&&this._triggerArray.forEach(t=>{t.classList.remove("collapsed"),t.setAttribute("aria-expanded",!0)}),this.setTransitioning(!0);const o="scroll"+(n[0].toUpperCase()+n.slice(1));this._queueCallback(()=>{this._element.classList.remove("collapsing"),this._element.classList.add("collapse","show"),this._element.style[n]="",this.setTransitioning(!1),B.trigger(this._element,"shown.bs.collapse")},this._element,!0),this._element.style[n]=this._element[o]+"px"}hide(){if(this._isTransitioning||!this._element.classList.contains("show"))return;if(B.trigger(this._element,"hide.bs.collapse").defaultPrevented)return;const t=this._getDimension();this._element.style[t]=this._element.getBoundingClientRect()[t]+"px",m(this._element),this._element.classList.add("collapsing"),this._element.classList.remove("collapse","show");const e=this._triggerArray.length;if(e>0)for(let t=0;t{this.setTransitioning(!1),this._element.classList.remove("collapsing"),this._element.classList.add("collapse"),B.trigger(this._element,"hidden.bs.collapse")},this._element,!0)}setTransitioning(t){this._isTransitioning=t}_getConfig(t){return(t={...st,...t}).toggle=Boolean(t.toggle),d("collapse",t,it),t}_getDimension(){return this._element.classList.contains("width")?"width":"height"}_getParent(){let{parent:t}=this._config;t=h(t);const e=`[data-bs-toggle="collapse"][data-bs-parent="${t}"]`;return i.find(e,t).forEach(t=>{const e=a(t);this._addAriaAndCollapsedClass(e,[t])}),t}_addAriaAndCollapsedClass(t,e){if(!t||!e.length)return;const s=t.classList.contains("show");e.forEach(t=>{s?t.classList.remove("collapsed"):t.classList.add("collapsed"),t.setAttribute("aria-expanded",s)})}static collapseInterface(t,e){let s=nt.getInstance(t);const i={...st,...V.getDataAttributes(t),..."object"==typeof e&&e?e:{}};if(!s&&i.toggle&&"string"==typeof e&&/show|hide/.test(e)&&(i.toggle=!1),s||(s=new nt(t,i)),"string"==typeof e){if(void 0===s[e])throw new TypeError(`No method named "${e}"`);s[e]()}}static jQueryInterface(t){return this.each((function(){nt.collapseInterface(this,t)}))}}B.on(document,"click.bs.collapse.data-api",'[data-bs-toggle="collapse"]',(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();const e=V.getDataAttributes(this),s=r(this);i.find(s).forEach(t=>{const s=nt.getInstance(t);let i;s?(null===s._parent&&"string"==typeof e.parent&&(s._config.parent=e.parent,s._parent=s._getParent()),i="toggle"):i=e,nt.collapseInterface(t,i)})})),y(nt);const ot=new RegExp("ArrowUp|ArrowDown|Escape"),rt=v()?"top-end":"top-start",at=v()?"top-start":"top-end",lt=v()?"bottom-end":"bottom-start",ct=v()?"bottom-start":"bottom-end",ht=v()?"left-start":"right-start",dt=v()?"right-start":"left-start",ut={offset:[0,2],boundary:"clippingParents",reference:"toggle",display:"dynamic",popperConfig:null,autoClose:!0},gt={offset:"(array|string|function)",boundary:"(string|element)",reference:"(string|element|object)",display:"string",popperConfig:"(null|object|function)",autoClose:"(boolean|string)"};class pt extends q{constructor(t,e){super(t),this._popper=null,this._config=this._getConfig(e),this._menu=this._getMenuElement(),this._inNavbar=this._detectNavbar(),this._addEventListeners()}static get Default(){return ut}static get DefaultType(){return gt}static get NAME(){return"dropdown"}toggle(){g(this._element)||(this._element.classList.contains("show")?this.hide():this.show())}show(){if(g(this._element)||this._menu.classList.contains("show"))return;const t=pt.getParentFromElement(this._element),e={relatedTarget:this._element};if(!B.trigger(this._element,"show.bs.dropdown",e).defaultPrevented){if(this._inNavbar)V.setDataAttribute(this._menu,"popper","none");else{if(void 0===s)throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");let e=this._element;"parent"===this._config.reference?e=t:c(this._config.reference)?e=h(this._config.reference):"object"==typeof this._config.reference&&(e=this._config.reference);const i=this._getPopperConfig(),n=i.modifiers.find(t=>"applyStyles"===t.name&&!1===t.enabled);this._popper=s.createPopper(e,this._menu,i),n&&V.setDataAttribute(this._menu,"popper","static")}"ontouchstart"in document.documentElement&&!t.closest(".navbar-nav")&&[].concat(...document.body.children).forEach(t=>B.on(t,"mouseover",f)),this._element.focus(),this._element.setAttribute("aria-expanded",!0),this._menu.classList.toggle("show"),this._element.classList.toggle("show"),B.trigger(this._element,"shown.bs.dropdown",e)}}hide(){if(g(this._element)||!this._menu.classList.contains("show"))return;const t={relatedTarget:this._element};this._completeHide(t)}dispose(){this._popper&&this._popper.destroy(),super.dispose()}update(){this._inNavbar=this._detectNavbar(),this._popper&&this._popper.update()}_addEventListeners(){B.on(this._element,"click.bs.dropdown",t=>{t.preventDefault(),this.toggle()})}_completeHide(t){B.trigger(this._element,"hide.bs.dropdown",t).defaultPrevented||("ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach(t=>B.off(t,"mouseover",f)),this._popper&&this._popper.destroy(),this._menu.classList.remove("show"),this._element.classList.remove("show"),this._element.setAttribute("aria-expanded","false"),V.removeDataAttribute(this._menu,"popper"),B.trigger(this._element,"hidden.bs.dropdown",t))}_getConfig(t){if(t={...this.constructor.Default,...V.getDataAttributes(this._element),...t},d("dropdown",t,this.constructor.DefaultType),"object"==typeof t.reference&&!c(t.reference)&&"function"!=typeof t.reference.getBoundingClientRect)throw new TypeError("dropdown".toUpperCase()+': Option "reference" provided type "object" without a required "getBoundingClientRect" method.');return t}_getMenuElement(){return i.next(this._element,".dropdown-menu")[0]}_getPlacement(){const t=this._element.parentNode;if(t.classList.contains("dropend"))return ht;if(t.classList.contains("dropstart"))return dt;const e="end"===getComputedStyle(this._menu).getPropertyValue("--bs-position").trim();return t.classList.contains("dropup")?e?at:rt:e?ct:lt}_detectNavbar(){return null!==this._element.closest(".navbar")}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map(t=>Number.parseInt(t,10)):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return"static"===this._config.display&&(t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,..."function"==typeof this._config.popperConfig?this._config.popperConfig(t):this._config.popperConfig}}_selectMenuItem({key:t,target:e}){const s=i.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter(u);s.length&&A(s,e,"ArrowDown"===t,!s.includes(e)).focus()}static dropdownInterface(t,e){const s=pt.getOrCreateInstance(t,e);if("string"==typeof e){if(void 0===s[e])throw new TypeError(`No method named "${e}"`);s[e]()}}static jQueryInterface(t){return this.each((function(){pt.dropdownInterface(this,t)}))}static clearMenus(t){if(t&&(2===t.button||"keyup"===t.type&&"Tab"!==t.key))return;const e=i.find('[data-bs-toggle="dropdown"]');for(let s=0,i=e.length;sthis.matches('[data-bs-toggle="dropdown"]')?this:i.prev(this,'[data-bs-toggle="dropdown"]')[0];return"Escape"===t.key?(s().focus(),void pt.clearMenus()):"ArrowUp"===t.key||"ArrowDown"===t.key?(e||s().click(),void pt.getInstance(s())._selectMenuItem(t)):void(e&&"Space"!==t.key||pt.clearMenus())}}B.on(document,"keydown.bs.dropdown.data-api",'[data-bs-toggle="dropdown"]',pt.dataApiKeydownHandler),B.on(document,"keydown.bs.dropdown.data-api",".dropdown-menu",pt.dataApiKeydownHandler),B.on(document,"click.bs.dropdown.data-api",pt.clearMenus),B.on(document,"keyup.bs.dropdown.data-api",pt.clearMenus),B.on(document,"click.bs.dropdown.data-api",'[data-bs-toggle="dropdown"]',(function(t){t.preventDefault(),pt.dropdownInterface(this)})),y(pt);class ft{constructor(){this._element=document.body}getWidth(){const t=document.documentElement.clientWidth;return Math.abs(window.innerWidth-t)}hide(){const t=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,"paddingRight",e=>e+t),this._setElementAttributes(".fixed-top, .fixed-bottom, .is-fixed, .sticky-top","paddingRight",e=>e+t),this._setElementAttributes(".sticky-top","marginRight",e=>e-t)}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,s){const i=this.getWidth();this._applyManipulationCallback(t,t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+i)return;this._saveInitialAttribute(t,e);const n=window.getComputedStyle(t)[e];t.style[e]=s(Number.parseFloat(n))+"px"})}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,"paddingRight"),this._resetElementAttributes(".fixed-top, .fixed-bottom, .is-fixed, .sticky-top","paddingRight"),this._resetElementAttributes(".sticky-top","marginRight")}_saveInitialAttribute(t,e){const s=t.style[e];s&&V.setDataAttribute(t,e,s)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,t=>{const s=V.getDataAttribute(t,e);void 0===s?t.style.removeProperty(e):(V.removeDataAttribute(t,e),t.style[e]=s)})}_applyManipulationCallback(t,e){c(t)?e(t):i.find(t,this._element).forEach(e)}isOverflowing(){return this.getWidth()>0}}const mt={isVisible:!0,isAnimated:!1,rootElement:"body",clickCallback:null},_t={isVisible:"boolean",isAnimated:"boolean",rootElement:"(element|string)",clickCallback:"(function|null)"};class bt{constructor(t){this._config=this._getConfig(t),this._isAppended=!1,this._element=null}show(t){this._config.isVisible?(this._append(),this._config.isAnimated&&m(this._getElement()),this._getElement().classList.add("show"),this._emulateAnimation(()=>{w(t)})):w(t)}hide(t){this._config.isVisible?(this._getElement().classList.remove("show"),this._emulateAnimation(()=>{this.dispose(),w(t)})):w(t)}_getElement(){if(!this._element){const t=document.createElement("div");t.className="modal-backdrop",this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_getConfig(t){return(t={...mt,..."object"==typeof t?t:{}}).rootElement=h(t.rootElement),d("backdrop",t,_t),t}_append(){this._isAppended||(this._config.rootElement.appendChild(this._getElement()),B.on(this._getElement(),"mousedown.bs.backdrop",()=>{w(this._config.clickCallback)}),this._isAppended=!0)}dispose(){this._isAppended&&(B.off(this._element,"mousedown.bs.backdrop"),this._element.remove(),this._isAppended=!1)}_emulateAnimation(t){E(t,this._getElement(),this._config.isAnimated)}}const vt={backdrop:!0,keyboard:!0,focus:!0},yt={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean"};class wt extends q{constructor(t,e){super(t),this._config=this._getConfig(e),this._dialog=i.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._isShown=!1,this._ignoreBackdropClick=!1,this._isTransitioning=!1,this._scrollBar=new ft}static get Default(){return vt}static get NAME(){return"modal"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||B.trigger(this._element,"show.bs.modal",{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isAnimated()&&(this._isTransitioning=!0),this._scrollBar.hide(),document.body.classList.add("modal-open"),this._adjustDialog(),this._setEscapeEvent(),this._setResizeEvent(),B.on(this._element,"click.dismiss.bs.modal",'[data-bs-dismiss="modal"]',t=>this.hide(t)),B.on(this._dialog,"mousedown.dismiss.bs.modal",()=>{B.one(this._element,"mouseup.dismiss.bs.modal",t=>{t.target===this._element&&(this._ignoreBackdropClick=!0)})}),this._showBackdrop(()=>this._showElement(t)))}hide(t){if(t&&["A","AREA"].includes(t.target.tagName)&&t.preventDefault(),!this._isShown||this._isTransitioning)return;if(B.trigger(this._element,"hide.bs.modal").defaultPrevented)return;this._isShown=!1;const e=this._isAnimated();e&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),B.off(document,"focusin.bs.modal"),this._element.classList.remove("show"),B.off(this._element,"click.dismiss.bs.modal"),B.off(this._dialog,"mousedown.dismiss.bs.modal"),this._queueCallback(()=>this._hideModal(),this._element,e)}dispose(){[window,this._dialog].forEach(t=>B.off(t,".bs.modal")),this._backdrop.dispose(),super.dispose(),B.off(document,"focusin.bs.modal")}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new bt({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_getConfig(t){return t={...vt,...V.getDataAttributes(this._element),..."object"==typeof t?t:{}},d("modal",t,yt),t}_showElement(t){const e=this._isAnimated(),s=i.findOne(".modal-body",this._dialog);this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0,s&&(s.scrollTop=0),e&&m(this._element),this._element.classList.add("show"),this._config.focus&&this._enforceFocus(),this._queueCallback(()=>{this._config.focus&&this._element.focus(),this._isTransitioning=!1,B.trigger(this._element,"shown.bs.modal",{relatedTarget:t})},this._dialog,e)}_enforceFocus(){B.off(document,"focusin.bs.modal"),B.on(document,"focusin.bs.modal",t=>{document===t.target||this._element===t.target||this._element.contains(t.target)||this._element.focus()})}_setEscapeEvent(){this._isShown?B.on(this._element,"keydown.dismiss.bs.modal",t=>{this._config.keyboard&&"Escape"===t.key?(t.preventDefault(),this.hide()):this._config.keyboard||"Escape"!==t.key||this._triggerBackdropTransition()}):B.off(this._element,"keydown.dismiss.bs.modal")}_setResizeEvent(){this._isShown?B.on(window,"resize.bs.modal",()=>this._adjustDialog()):B.off(window,"resize.bs.modal")}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide(()=>{document.body.classList.remove("modal-open"),this._resetAdjustments(),this._scrollBar.reset(),B.trigger(this._element,"hidden.bs.modal")})}_showBackdrop(t){B.on(this._element,"click.dismiss.bs.modal",t=>{this._ignoreBackdropClick?this._ignoreBackdropClick=!1:t.target===t.currentTarget&&(!0===this._config.backdrop?this.hide():"static"===this._config.backdrop&&this._triggerBackdropTransition())}),this._backdrop.show(t)}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(B.trigger(this._element,"hidePrevented.bs.modal").defaultPrevented)return;const{classList:t,scrollHeight:e,style:s}=this._element,i=e>document.documentElement.clientHeight;!i&&"hidden"===s.overflowY||t.contains("modal-static")||(i||(s.overflowY="hidden"),t.add("modal-static"),this._queueCallback(()=>{t.remove("modal-static"),i||this._queueCallback(()=>{s.overflowY=""},this._dialog)},this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),s=e>0;(!s&&t&&!v()||s&&!t&&v())&&(this._element.style.paddingLeft=e+"px"),(s&&!t&&!v()||!s&&t&&v())&&(this._element.style.paddingRight=e+"px")}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const s=wt.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===s[t])throw new TypeError(`No method named "${t}"`);s[t](e)}}))}}B.on(document,"click.bs.modal.data-api",'[data-bs-toggle="modal"]',(function(t){const e=a(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),B.one(e,"show.bs.modal",t=>{t.defaultPrevented||B.one(e,"hidden.bs.modal",()=>{u(this)&&this.focus()})}),wt.getOrCreateInstance(e).toggle(this)})),y(wt);const Et={backdrop:!0,keyboard:!0,scroll:!1},At={backdrop:"boolean",keyboard:"boolean",scroll:"boolean"};class Tt extends q{constructor(t,e){super(t),this._config=this._getConfig(e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._addEventListeners()}static get NAME(){return"offcanvas"}static get Default(){return Et}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||B.trigger(this._element,"show.bs.offcanvas",{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._element.style.visibility="visible",this._backdrop.show(),this._config.scroll||((new ft).hide(),this._enforceFocusOnElement(this._element)),this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add("show"),this._queueCallback(()=>{B.trigger(this._element,"shown.bs.offcanvas",{relatedTarget:t})},this._element,!0))}hide(){this._isShown&&(B.trigger(this._element,"hide.bs.offcanvas").defaultPrevented||(B.off(document,"focusin.bs.offcanvas"),this._element.blur(),this._isShown=!1,this._element.classList.remove("show"),this._backdrop.hide(),this._queueCallback(()=>{this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._element.style.visibility="hidden",this._config.scroll||(new ft).reset(),B.trigger(this._element,"hidden.bs.offcanvas")},this._element,!0)))}dispose(){this._backdrop.dispose(),super.dispose(),B.off(document,"focusin.bs.offcanvas")}_getConfig(t){return t={...Et,...V.getDataAttributes(this._element),..."object"==typeof t?t:{}},d("offcanvas",t,At),t}_initializeBackDrop(){return new bt({isVisible:this._config.backdrop,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:()=>this.hide()})}_enforceFocusOnElement(t){B.off(document,"focusin.bs.offcanvas"),B.on(document,"focusin.bs.offcanvas",e=>{document===e.target||t===e.target||t.contains(e.target)||t.focus()}),t.focus()}_addEventListeners(){B.on(this._element,"click.dismiss.bs.offcanvas",'[data-bs-dismiss="offcanvas"]',()=>this.hide()),B.on(this._element,"keydown.dismiss.bs.offcanvas",t=>{this._config.keyboard&&"Escape"===t.key&&this.hide()})}static jQueryInterface(t){return this.each((function(){const e=Tt.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}B.on(document,"click.bs.offcanvas.data-api",'[data-bs-toggle="offcanvas"]',(function(t){const e=a(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),g(this))return;B.one(e,"hidden.bs.offcanvas",()=>{u(this)&&this.focus()});const s=i.findOne(".offcanvas.show");s&&s!==e&&Tt.getInstance(s).hide(),Tt.getOrCreateInstance(e).toggle(this)})),B.on(window,"load.bs.offcanvas.data-api",()=>i.find(".offcanvas.show").forEach(t=>Tt.getOrCreateInstance(t).show())),y(Tt);const Ct=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),kt=/^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/i,Lt=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i,Ot=(t,e)=>{const s=t.nodeName.toLowerCase();if(e.includes(s))return!Ct.has(s)||Boolean(kt.test(t.nodeValue)||Lt.test(t.nodeValue));const i=e.filter(t=>t instanceof RegExp);for(let t=0,e=i.length;t{Ot(t,a)||s.removeAttribute(t.nodeName)})}return i.body.innerHTML}const It=new RegExp("(^|\\s)bs-tooltip\\S+","g"),Nt=new Set(["sanitize","allowList","sanitizeFn"]),St={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(array|string|function)",container:"(string|element|boolean)",fallbackPlacements:"array",boundary:"(string|element)",customClass:"(string|function)",sanitize:"boolean",sanitizeFn:"(null|function)",allowList:"object",popperConfig:"(null|object|function)"},xt={AUTO:"auto",TOP:"top",RIGHT:v()?"left":"right",BOTTOM:"bottom",LEFT:v()?"right":"left"},Mt={animation:!0,template:'',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:[0,0],container:!1,fallbackPlacements:["top","right","bottom","left"],boundary:"clippingParents",customClass:"",sanitize:!0,sanitizeFn:null,allowList:{"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},popperConfig:null},Pt={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"};class jt extends q{constructor(t,e){if(void 0===s)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t),this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this._config=this._getConfig(e),this.tip=null,this._setListeners()}static get Default(){return Mt}static get NAME(){return"tooltip"}static get Event(){return Pt}static get DefaultType(){return St}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(t){if(this._isEnabled)if(t){const e=this._initializeOnDelegatedTarget(t);e._activeTrigger.click=!e._activeTrigger.click,e._isWithActiveTrigger()?e._enter(null,e):e._leave(null,e)}else{if(this.getTipElement().classList.contains("show"))return void this._leave(null,this);this._enter(null,this)}}dispose(){clearTimeout(this._timeout),B.off(this._element.closest(".modal"),"hide.bs.modal",this._hideModalHandler),this.tip&&this.tip.remove(),this._popper&&this._popper.destroy(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this.isWithContent()||!this._isEnabled)return;const t=B.trigger(this._element,this.constructor.Event.SHOW),e=p(this._element),i=null===e?this._element.ownerDocument.documentElement.contains(this._element):e.contains(this._element);if(t.defaultPrevented||!i)return;const o=this.getTipElement(),r=n(this.constructor.NAME);o.setAttribute("id",r),this._element.setAttribute("aria-describedby",r),this.setContent(),this._config.animation&&o.classList.add("fade");const a="function"==typeof this._config.placement?this._config.placement.call(this,o,this._element):this._config.placement,l=this._getAttachment(a);this._addAttachmentClass(l);const{container:c}=this._config;W.set(o,this.constructor.DATA_KEY,this),this._element.ownerDocument.documentElement.contains(this.tip)||(c.appendChild(o),B.trigger(this._element,this.constructor.Event.INSERTED)),this._popper?this._popper.update():this._popper=s.createPopper(this._element,o,this._getPopperConfig(l)),o.classList.add("show");const h="function"==typeof this._config.customClass?this._config.customClass():this._config.customClass;h&&o.classList.add(...h.split(" ")),"ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach(t=>{B.on(t,"mouseover",f)});const d=this.tip.classList.contains("fade");this._queueCallback(()=>{const t=this._hoverState;this._hoverState=null,B.trigger(this._element,this.constructor.Event.SHOWN),"out"===t&&this._leave(null,this)},this.tip,d)}hide(){if(!this._popper)return;const t=this.getTipElement();if(B.trigger(this._element,this.constructor.Event.HIDE).defaultPrevented)return;t.classList.remove("show"),"ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach(t=>B.off(t,"mouseover",f)),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1;const e=this.tip.classList.contains("fade");this._queueCallback(()=>{this._isWithActiveTrigger()||("show"!==this._hoverState&&t.remove(),this._cleanTipClass(),this._element.removeAttribute("aria-describedby"),B.trigger(this._element,this.constructor.Event.HIDDEN),this._popper&&(this._popper.destroy(),this._popper=null))},this.tip,e),this._hoverState=""}update(){null!==this._popper&&this._popper.update()}isWithContent(){return Boolean(this.getTitle())}getTipElement(){if(this.tip)return this.tip;const t=document.createElement("div");return t.innerHTML=this._config.template,this.tip=t.children[0],this.tip}setContent(){const t=this.getTipElement();this.setElementContent(i.findOne(".tooltip-inner",t),this.getTitle()),t.classList.remove("fade","show")}setElementContent(t,e){if(null!==t)return c(e)?(e=h(e),void(this._config.html?e.parentNode!==t&&(t.innerHTML="",t.appendChild(e)):t.textContent=e.textContent)):void(this._config.html?(this._config.sanitize&&(e=Dt(e,this._config.allowList,this._config.sanitizeFn)),t.innerHTML=e):t.textContent=e)}getTitle(){let t=this._element.getAttribute("data-bs-original-title");return t||(t="function"==typeof this._config.title?this._config.title.call(this._element):this._config.title),t}updateAttachment(t){return"right"===t?"end":"left"===t?"start":t}_initializeOnDelegatedTarget(t,e){const s=this.constructor.DATA_KEY;return(e=e||W.get(t.delegateTarget,s))||(e=new this.constructor(t.delegateTarget,this._getDelegateConfig()),W.set(t.delegateTarget,s,e)),e}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map(t=>Number.parseInt(t,10)):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"onChange",enabled:!0,phase:"afterWrite",fn:t=>this._handlePopperPlacementChange(t)}],onFirstUpdate:t=>{t.options.placement!==t.placement&&this._handlePopperPlacementChange(t)}};return{...e,..."function"==typeof this._config.popperConfig?this._config.popperConfig(e):this._config.popperConfig}}_addAttachmentClass(t){this.getTipElement().classList.add("bs-tooltip-"+this.updateAttachment(t))}_getAttachment(t){return xt[t.toUpperCase()]}_setListeners(){this._config.trigger.split(" ").forEach(t=>{if("click"===t)B.on(this._element,this.constructor.Event.CLICK,this._config.selector,t=>this.toggle(t));else if("manual"!==t){const e="hover"===t?this.constructor.Event.MOUSEENTER:this.constructor.Event.FOCUSIN,s="hover"===t?this.constructor.Event.MOUSELEAVE:this.constructor.Event.FOCUSOUT;B.on(this._element,e,this._config.selector,t=>this._enter(t)),B.on(this._element,s,this._config.selector,t=>this._leave(t))}}),this._hideModalHandler=()=>{this._element&&this.hide()},B.on(this._element.closest(".modal"),"hide.bs.modal",this._hideModalHandler),this._config.selector?this._config={...this._config,trigger:"manual",selector:""}:this._fixTitle()}_fixTitle(){const t=this._element.getAttribute("title"),e=typeof this._element.getAttribute("data-bs-original-title");(t||"string"!==e)&&(this._element.setAttribute("data-bs-original-title",t||""),!t||this._element.getAttribute("aria-label")||this._element.textContent||this._element.setAttribute("aria-label",t),this._element.setAttribute("title",""))}_enter(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusin"===t.type?"focus":"hover"]=!0),e.getTipElement().classList.contains("show")||"show"===e._hoverState?e._hoverState="show":(clearTimeout(e._timeout),e._hoverState="show",e._config.delay&&e._config.delay.show?e._timeout=setTimeout(()=>{"show"===e._hoverState&&e.show()},e._config.delay.show):e.show())}_leave(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusout"===t.type?"focus":"hover"]=e._element.contains(t.relatedTarget)),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState="out",e._config.delay&&e._config.delay.hide?e._timeout=setTimeout(()=>{"out"===e._hoverState&&e.hide()},e._config.delay.hide):e.hide())}_isWithActiveTrigger(){for(const t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1}_getConfig(t){const e=V.getDataAttributes(this._element);return Object.keys(e).forEach(t=>{Nt.has(t)&&delete e[t]}),(t={...this.constructor.Default,...e,..."object"==typeof t&&t?t:{}}).container=!1===t.container?document.body:h(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),d("tooltip",t,this.constructor.DefaultType),t.sanitize&&(t.template=Dt(t.template,t.allowList,t.sanitizeFn)),t}_getDelegateConfig(){const t={};if(this._config)for(const e in this._config)this.constructor.Default[e]!==this._config[e]&&(t[e]=this._config[e]);return t}_cleanTipClass(){const t=this.getTipElement(),e=t.getAttribute("class").match(It);null!==e&&e.length>0&&e.map(t=>t.trim()).forEach(e=>t.classList.remove(e))}_handlePopperPlacementChange(t){const{state:e}=t;e&&(this.tip=e.elements.popper,this._cleanTipClass(),this._addAttachmentClass(this._getAttachment(e.placement)))}static jQueryInterface(t){return this.each((function(){const e=jt.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}y(jt);const Ht=new RegExp("(^|\\s)bs-popover\\S+","g"),Rt={...jt.Default,placement:"right",offset:[0,8],trigger:"click",content:"",template:''},Bt={...jt.DefaultType,content:"(string|element|function)"},$t={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"};class Wt extends jt{static get Default(){return Rt}static get NAME(){return"popover"}static get Event(){return $t}static get DefaultType(){return Bt}isWithContent(){return this.getTitle()||this._getContent()}getTipElement(){return this.tip||(this.tip=super.getTipElement(),this.getTitle()||i.findOne(".popover-header",this.tip).remove(),this._getContent()||i.findOne(".popover-body",this.tip).remove()),this.tip}setContent(){const t=this.getTipElement();this.setElementContent(i.findOne(".popover-header",t),this.getTitle());let e=this._getContent();"function"==typeof e&&(e=e.call(this._element)),this.setElementContent(i.findOne(".popover-body",t),e),t.classList.remove("fade","show")}_addAttachmentClass(t){this.getTipElement().classList.add("bs-popover-"+this.updateAttachment(t))}_getContent(){return this._element.getAttribute("data-bs-content")||this._config.content}_cleanTipClass(){const t=this.getTipElement(),e=t.getAttribute("class").match(Ht);null!==e&&e.length>0&&e.map(t=>t.trim()).forEach(e=>t.classList.remove(e))}static jQueryInterface(t){return this.each((function(){const e=Wt.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}y(Wt);const qt={offset:10,method:"auto",target:""},zt={offset:"number",method:"string",target:"(string|element)"};class Ft extends q{constructor(t,e){super(t),this._scrollElement="BODY"===this._element.tagName?window:this._element,this._config=this._getConfig(e),this._selector=`${this._config.target} .nav-link, ${this._config.target} .list-group-item, ${this._config.target} .dropdown-item`,this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,B.on(this._scrollElement,"scroll.bs.scrollspy",()=>this._process()),this.refresh(),this._process()}static get Default(){return qt}static get NAME(){return"scrollspy"}refresh(){const t=this._scrollElement===this._scrollElement.window?"offset":"position",e="auto"===this._config.method?t:this._config.method,s="position"===e?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),i.find(this._selector).map(t=>{const n=r(t),o=n?i.findOne(n):null;if(o){const t=o.getBoundingClientRect();if(t.width||t.height)return[V[e](o).top+s,n]}return null}).filter(t=>t).sort((t,e)=>t[0]-e[0]).forEach(t=>{this._offsets.push(t[0]),this._targets.push(t[1])})}dispose(){B.off(this._scrollElement,".bs.scrollspy"),super.dispose()}_getConfig(t){if("string"!=typeof(t={...qt,...V.getDataAttributes(this._element),..."object"==typeof t&&t?t:{}}).target&&c(t.target)){let{id:e}=t.target;e||(e=n("scrollspy"),t.target.id=e),t.target="#"+e}return d("scrollspy",t,zt),t}_getScrollTop(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop}_getScrollHeight(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)}_getOffsetHeight(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height}_process(){const t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),s=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=s){const t=this._targets[this._targets.length-1];this._activeTarget!==t&&this._activate(t)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(let e=this._offsets.length;e--;)this._activeTarget!==this._targets[e]&&t>=this._offsets[e]&&(void 0===this._offsets[e+1]||t`${e}[data-bs-target="${t}"],${e}[href="${t}"]`),s=i.findOne(e.join(","));s.classList.contains("dropdown-item")?(i.findOne(".dropdown-toggle",s.closest(".dropdown")).classList.add("active"),s.classList.add("active")):(s.classList.add("active"),i.parents(s,".nav, .list-group").forEach(t=>{i.prev(t,".nav-link, .list-group-item").forEach(t=>t.classList.add("active")),i.prev(t,".nav-item").forEach(t=>{i.children(t,".nav-link").forEach(t=>t.classList.add("active"))})})),B.trigger(this._scrollElement,"activate.bs.scrollspy",{relatedTarget:t})}_clear(){i.find(this._selector).filter(t=>t.classList.contains("active")).forEach(t=>t.classList.remove("active"))}static jQueryInterface(t){return this.each((function(){const e=Ft.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}B.on(window,"load.bs.scrollspy.data-api",()=>{i.find('[data-bs-spy="scroll"]').forEach(t=>new Ft(t))}),y(Ft);class Ut extends q{static get NAME(){return"tab"}show(){if(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&this._element.classList.contains("active"))return;let t;const e=a(this._element),s=this._element.closest(".nav, .list-group");if(s){const e="UL"===s.nodeName||"OL"===s.nodeName?":scope > li > .active":".active";t=i.find(e,s),t=t[t.length-1]}const n=t?B.trigger(t,"hide.bs.tab",{relatedTarget:this._element}):null;if(B.trigger(this._element,"show.bs.tab",{relatedTarget:t}).defaultPrevented||null!==n&&n.defaultPrevented)return;this._activate(this._element,s);const o=()=>{B.trigger(t,"hidden.bs.tab",{relatedTarget:this._element}),B.trigger(this._element,"shown.bs.tab",{relatedTarget:t})};e?this._activate(e,e.parentNode,o):o()}_activate(t,e,s){const n=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?i.children(e,".active"):i.find(":scope > li > .active",e))[0],o=s&&n&&n.classList.contains("fade"),r=()=>this._transitionComplete(t,n,s);n&&o?(n.classList.remove("show"),this._queueCallback(r,t,!0)):r()}_transitionComplete(t,e,s){if(e){e.classList.remove("active");const t=i.findOne(":scope > .dropdown-menu .active",e.parentNode);t&&t.classList.remove("active"),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}t.classList.add("active"),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),m(t),t.classList.contains("fade")&&t.classList.add("show");let n=t.parentNode;if(n&&"LI"===n.nodeName&&(n=n.parentNode),n&&n.classList.contains("dropdown-menu")){const e=t.closest(".dropdown");e&&i.find(".dropdown-toggle",e).forEach(t=>t.classList.add("active")),t.setAttribute("aria-expanded",!0)}s&&s()}static jQueryInterface(t){return this.each((function(){const e=Ut.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}B.on(document,"click.bs.tab.data-api",'[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',(function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),g(this)||Ut.getOrCreateInstance(this).show()})),y(Ut);const Kt={animation:"boolean",autohide:"boolean",delay:"number"},Vt={animation:!0,autohide:!0,delay:5e3};class Qt extends q{constructor(t,e){super(t),this._config=this._getConfig(e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get DefaultType(){return Kt}static get Default(){return Vt}static get NAME(){return"toast"}show(){B.trigger(this._element,"show.bs.toast").defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove("hide"),m(this._element),this._element.classList.add("showing"),this._queueCallback(()=>{this._element.classList.remove("showing"),this._element.classList.add("show"),B.trigger(this._element,"shown.bs.toast"),this._maybeScheduleHide()},this._element,this._config.animation))}hide(){this._element.classList.contains("show")&&(B.trigger(this._element,"hide.bs.toast").defaultPrevented||(this._element.classList.remove("show"),this._queueCallback(()=>{this._element.classList.add("hide"),B.trigger(this._element,"hidden.bs.toast")},this._element,this._config.animation)))}dispose(){this._clearTimeout(),this._element.classList.contains("show")&&this._element.classList.remove("show"),super.dispose()}_getConfig(t){return t={...Vt,...V.getDataAttributes(this._element),..."object"==typeof t&&t?t:{}},d("toast",t,this.constructor.DefaultType),t}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout(()=>{this.hide()},this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const s=t.relatedTarget;this._element===s||this._element.contains(s)||this._maybeScheduleHide()}_setListeners(){B.on(this._element,"click.dismiss.bs.toast",'[data-bs-dismiss="toast"]',()=>this.hide()),B.on(this._element,"mouseover.bs.toast",t=>this._onInteraction(t,!0)),B.on(this._element,"mouseout.bs.toast",t=>this._onInteraction(t,!1)),B.on(this._element,"focusin.bs.toast",t=>this._onInteraction(t,!0)),B.on(this._element,"focusout.bs.toast",t=>this._onInteraction(t,!1))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=Qt.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}return y(Qt),{Alert:z,Button:F,Carousel:et,Collapse:nt,Dropdown:pt,Modal:wt,Offcanvas:Tt,Popover:Wt,ScrollSpy:Ft,Tab:Ut,Toast:Qt,Tooltip:jt}})); +//# sourceMappingURL=bootstrap.min.js.map + + +/*------------------------------------------------------------- + 5. Slick slider jQuery +---------------------------------------------------------------*/ +/* + _ _ _ _ + ___| (_) ___| | __ (_)___ +/ __| | |/ __| |/ / | / __| +\__ \ | | (__| < _ | \__ \ +|___/_|_|\___|_|\_(_)/ |___/ + |__/ + + Version: 1.6.0 + Author: Ken Wheeler + Website: http://kenwheeler.github.io + Docs: http://kenwheeler.github.io/slick + Repo: http://github.com/kenwheeler/slick + Issues: http://github.com/kenwheeler/slick/issues + + */ +!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):"undefined"!=typeof exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){"use strict";var b=window.Slick||{};b=function(){function c(c,d){var f,e=this;e.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:a(c),appendDots:a(c),arrows:!0,asNavFor:null,prevArrow:'',nextArrow:'',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(b,c){return a(' + +

    + + + + + + + + + + +{% partial 'home/brand' %} diff --git a/themes/nurgul/pages/home.htm b/themes/nurgul/pages/home.htm new file mode 100755 index 0000000..d06385b --- /dev/null +++ b/themes/nurgul/pages/home.htm @@ -0,0 +1,36 @@ +url = "/" +layout = "main" +title = "Home" +== + +{% partial 'home/slider' %} + +{% partial 'home/banner' %} + +{% partial 'home/banner2' %} + +{% partial 'home/new-products' header='New Products' %} + +{% partial 'home/banner-mix' %} + +{% partial 'product/slider-item' header='Top Products' %} + + + +
    +
    +
    +
    +
    +
    + Banner Image +
    +
    +
    +
    +
    +
    + + + +{% partial 'home/brand' %} diff --git a/themes/nurgul/partials/bread.htm b/themes/nurgul/partials/bread.htm new file mode 100755 index 0000000..a6184ef --- /dev/null +++ b/themes/nurgul/partials/bread.htm @@ -0,0 +1,19 @@ + +
    +
    +
    +
    +
    +

    {{title}}

    +
    + +
    +
    +
    +
    +
    +
    + diff --git a/themes/nurgul/partials/cart.htm b/themes/nurgul/partials/cart.htm new file mode 100755 index 0000000..1892720 --- /dev/null +++ b/themes/nurgul/partials/cart.htm @@ -0,0 +1,63 @@ + +
    +
    +
    + Cart + +
    +
    +
    +
    + Image + +
    +
    +
    Premium Joyful
    + 1 x $65.00 +
    +
    +
    +
    + Image + +
    +
    +
    The White Rose
    + 1 x $85.00 +
    +
    +
    +
    + Image + +
    +
    +
    Red Rose Bouquet
    + 1 x $92.00 +
    +
    +
    +
    + Image + +
    +
    +
    Pink Flower Tree
    + 1 x $68.00 +
    +
    +
    + + +
    +
    + diff --git a/themes/nurgul/partials/contact/content.htm b/themes/nurgul/partials/contact/content.htm new file mode 100755 index 0000000..5cb0a92 --- /dev/null +++ b/themes/nurgul/partials/contact/content.htm @@ -0,0 +1,48 @@ + +
    +
    +
    +
    +
    +
    + +
    +

    {{'contact.email.title'|_}}

    +

    info@webmail.com
    + jobs@webexample.com

    +
    +
    +
    +
    +
    + +
    +

    {{'contact.phone.title'|_}}

    +

    +1234-567 890
    + +09876-543 210

    +
    +
    +
    +
    +
    + +
    +

    {{'contact.email2.title'|_}}

    +

    info@webmail.com
    + jobs@webexample.com

    +
    +
    +
    +
    +
    + +
    +

    {{'contact.open.title'|_}}

    +

    Fri to Wed: 6:00 Am to 8:00 Pm
    + Thursday - Off

    +
    +
    +
    +
    +
    + diff --git a/themes/nurgul/partials/footer.htm b/themes/nurgul/partials/footer.htm new file mode 100755 index 0000000..5050d4b --- /dev/null +++ b/themes/nurgul/partials/footer.htm @@ -0,0 +1,41 @@ + + + diff --git a/themes/nurgul/partials/header.htm b/themes/nurgul/partials/header.htm new file mode 100755 index 0000000..ac66477 --- /dev/null +++ b/themes/nurgul/partials/header.htm @@ -0,0 +1,180 @@ + +
    + +
    +
    +
    +
    + +
    +
    + +
    +
    + + +
    +
    +
    +
    + + + + + +
    + diff --git a/themes/nurgul/partials/home/banner-mix.htm b/themes/nurgul/partials/home/banner-mix.htm new file mode 100755 index 0000000..04adf78 --- /dev/null +++ b/themes/nurgul/partials/home/banner-mix.htm @@ -0,0 +1,22 @@ + +
    +
    +
    +
    +
    +
    + Banner Image +
    +
    +
    +
    +
    +
    + Banner Image +
    +
    +
    +
    +
    +
    + \ No newline at end of file diff --git a/themes/nurgul/partials/home/banner.htm b/themes/nurgul/partials/home/banner.htm new file mode 100755 index 0000000..6cf9286 --- /dev/null +++ b/themes/nurgul/partials/home/banner.htm @@ -0,0 +1,49 @@ + +
    +
    +
    +
    +
    +
    +
    + # +
    +
    +

    Free shipping

    +

    On all orders over $49.00

    +
    +
    +
    +
    + # +
    +
    +

    15 days returns

    +

    Moneyback guarantee

    +
    +
    +
    +
    + # +
    +
    +

    Secure checkout

    +

    Protected by Paypal

    +
    +
    +
    +
    + # +
    +
    +

    Offer & gift here

    +

    On all orders over

    +
    +
    +
    +
    +
    +
    +
    + diff --git a/themes/nurgul/partials/home/banner2.htm b/themes/nurgul/partials/home/banner2.htm new file mode 100755 index 0000000..77a3593 --- /dev/null +++ b/themes/nurgul/partials/home/banner2.htm @@ -0,0 +1,29 @@ + +
    +
    +
    +
    +
    +
    + Banner Image +
    +
    +
    +
    +
    +
    + Banner Image +
    +
    +
    +
    +
    +
    + Banner Image +
    +
    +
    +
    +
    +
    + diff --git a/themes/nurgul/partials/home/brand-item.htm b/themes/nurgul/partials/home/brand-item.htm new file mode 100755 index 0000000..0f98244 --- /dev/null +++ b/themes/nurgul/partials/home/brand-item.htm @@ -0,0 +1,5 @@ +
    +
    + Brand Logo +
    +
    diff --git a/themes/nurgul/partials/home/brand.htm b/themes/nurgul/partials/home/brand.htm new file mode 100755 index 0000000..c8e0590 --- /dev/null +++ b/themes/nurgul/partials/home/brand.htm @@ -0,0 +1,20 @@ + +
    +
    +
    + + {% partial "home/brand-item" %} + {% partial "home/brand-item" %} + {% partial "home/brand-item" %} + {% partial "home/brand-item" %} + {% partial "home/brand-item" %} + {% partial "home/brand-item" %} + {% partial "home/brand-item" %} + {% partial "home/brand-item" %} + {% partial "home/brand-item" %} + {% partial "home/brand-item" %} + +
    +
    +
    + diff --git a/themes/nurgul/partials/home/new-products.htm b/themes/nurgul/partials/home/new-products.htm new file mode 100755 index 0000000..881ca7c --- /dev/null +++ b/themes/nurgul/partials/home/new-products.htm @@ -0,0 +1,25 @@ + +
    +
    +
    +
    +
    +

    {{ header }}

    +
    +
    +
    +
    + + {% partial 'product/card' %} + {% partial 'product/card' %} + {% partial 'product/card' %} + {% partial 'product/card' %} + {% partial 'product/card' %} + {% partial 'product/card' %} + {% partial 'product/card' %} + {% partial 'product/card' %} + +
    +
    +
    + diff --git a/themes/nurgul/partials/home/slider.htm b/themes/nurgul/partials/home/slider.htm new file mode 100755 index 0000000..69f5dc7 --- /dev/null +++ b/themes/nurgul/partials/home/slider.htm @@ -0,0 +1,77 @@ + +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    {{'Fresh Flower'|_}}

    +
    + Natural & Beautiful Flower Here
    +
    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed + do eiusmod tempor incididunt ut labore.

    +
    +
    + Shop Now +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Fresh Flower

    +
    + Natural & Beautiful Flower Here
    +
    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed + do eiusmod tempor incididunt ut labore.

    +
    +
    + Shop Now +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + +
    +
    + \ No newline at end of file diff --git a/themes/nurgul/partials/mobile-menu.htm b/themes/nurgul/partials/mobile-menu.htm new file mode 100755 index 0000000..a9ef961 --- /dev/null +++ b/themes/nurgul/partials/mobile-menu.htm @@ -0,0 +1,108 @@ + + + diff --git a/themes/nurgul/partials/modals.htm b/themes/nurgul/partials/modals.htm new file mode 100755 index 0000000..22982c8 --- /dev/null +++ b/themes/nurgul/partials/modals.htm @@ -0,0 +1,249 @@ + +
    + +
    + + + +
    + +
    + + + +
    + +
    + diff --git a/themes/nurgul/partials/overlay.htm b/themes/nurgul/partials/overlay.htm new file mode 100755 index 0000000..0a605ad --- /dev/null +++ b/themes/nurgul/partials/overlay.htm @@ -0,0 +1 @@ +
    \ No newline at end of file diff --git a/themes/nurgul/partials/product/card.htm b/themes/nurgul/partials/product/card.htm new file mode 100755 index 0000000..f131f9d --- /dev/null +++ b/themes/nurgul/partials/product/card.htm @@ -0,0 +1,43 @@ + +
    +
    +
    + # +
    +
      +
    • 10%
    • +
    +
    +
    + +
    +
    +
    +

    Pink Flower Tree

    +
    + $18.00 + $21.00 +
    +
    +
    +
    diff --git a/themes/nurgul/partials/product/slider-item.htm b/themes/nurgul/partials/product/slider-item.htm new file mode 100755 index 0000000..ccc1c8e --- /dev/null +++ b/themes/nurgul/partials/product/slider-item.htm @@ -0,0 +1,25 @@ + +
    +
    +
    +
    +
    +

    {{header}}

    +
    +
    +
    +
    + + {% partial 'product/slider-prod-item' %} + {% partial 'product/slider-prod-item' %} + {% partial 'product/slider-prod-item' %} + {% partial 'product/slider-prod-item' %} + {% partial 'product/slider-prod-item' %} + {% partial 'product/slider-prod-item' %} + {% partial 'product/slider-prod-item' %} + + +
    +
    +
    + diff --git a/themes/nurgul/partials/product/slider-prod-item.htm b/themes/nurgul/partials/product/slider-prod-item.htm new file mode 100755 index 0000000..ecdfbdb --- /dev/null +++ b/themes/nurgul/partials/product/slider-prod-item.htm @@ -0,0 +1,43 @@ + +
    +
    +
    + # +
    +
      +
    • 10%
    • +
    +
    +
    + +
    +
    +
    +

    Pink Flower Tree

    +
    + $18.00 + $21.00 +
    +
    +
    +
    diff --git a/themes/nurgul/theme.yaml b/themes/nurgul/theme.yaml new file mode 100755 index 0000000..3450cdf --- /dev/null +++ b/themes/nurgul/theme.yaml @@ -0,0 +1,8 @@ +name: nurGul +description: '' +author: Romanah +homepage: '' +authorCode: '' +code: '' +parent: '' +database: '0' diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..76b3c20 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,17 @@ +const webpack = require('webpack'); + +module.exports = { + devtool: 'inline-source-map', + plugins: [ + new webpack.ProvidePlugin({ + $: 'jquery', + jQuery: 'jquery', + 'window.jQuery': 'jquery', + 'window.$': 'jquery', + }), + ], + externals: { + // Use external version of jQuery + jquery: 'jQuery' + }, +}; diff --git a/webpack.helpers.js b/webpack.helpers.js new file mode 100644 index 0000000..217512b --- /dev/null +++ b/webpack.helpers.js @@ -0,0 +1,45 @@ +/* + |-------------------------------------------------------------------------- + | Mix Extensions + |-------------------------------------------------------------------------- + | + | Adds custom helper functions to the mix object. + | + */ + +const { lstatSync, readdirSync } = require('fs'); +const { join } = require('path'); +const fs = require('fs'); + +const isDirectory = (source) => lstatSync(source).isDirectory(); +const getDirectories = (source) => readdirSync(source).map((name) => join(source, name)).filter(isDirectory); + +function makeComponentLessList(source) { + const componentDirs = getDirectories(source); + const result = []; + + componentDirs.forEach((dir) => { + const parts = dir.replace(/\\/g, '/').split('/'); + const componentName = parts[parts.length - 1]; + const lessFile = dir + '/assets/less/' + componentName + '.less'; + + if (fs.existsSync(lessFile)) { + result.push(componentName); + } + }); + + return result; +} + +// Attach the helpers to the mix object +module.exports = (mix) => { + + // Wildcard helper for components + mix.lessList = (path, except = []) => { + makeComponentLessList(path) + .filter(name => !except.includes(name)) + .forEach(name => mix.less(`${path}/${name}/assets/less/${name}.less`, `${path}/${name}/assets/css/`)) + ; + }; + +}; diff --git a/webpack.mix.js b/webpack.mix.js new file mode 100644 index 0000000..6cfc241 --- /dev/null +++ b/webpack.mix.js @@ -0,0 +1,67 @@ +const mix = require('laravel-mix'); +const webpackConfig = require('./webpack.config'); + +/* + |-------------------------------------------------------------------------- + | Mix Asset Management + |-------------------------------------------------------------------------- + | + | Mix provides a clean, fluent API for defining some Webpack build steps + | for your theme assets. By default, we are compiling the CSS + | file for the application as well as bundling up all the JS files. + | + */ + +mix + .webpackConfig(webpackConfig) + .options({ + processCssUrls: false, + manifest: false, + terser: { + terserOptions: { + mangle: false, + compress: true, + output: { + comments: false + } + }, + }, + }) + .setPublicPath('') +; + +// Vendor Mixes +mix + .copy('node_modules/jquery/dist/jquery.min.js', 'modules/system/assets/js/vendor/jquery.min.js') + .copy('node_modules/vue-router/dist/vue-router.min.js', 'modules/system/assets/vendor/vue-router/vue.min.js') + .copy('node_modules/bluebird/js/browser/bluebird.min.js', 'modules/system/assets/vendor/bluebird/bluebird.min.js') + .copy('node_modules/sortablejs/Sortable.min.js', 'modules/backend/assets/vendor/sortablejs/sortable.js') + .copy('node_modules/dropzone/dist/dropzone-min.js', 'modules/backend/assets/vendor/dropzone/dropzone.js') + .copy('node_modules/js-cookie/dist/js.cookie.js', 'modules/backend/assets/vendor/js-cookie/js.cookie.js') +; + +// Vue dev tools +if (!mix.inProduction()) { + mix.copy('node_modules/vue/dist/vue.js', 'modules/system/assets/vendor/vue/vue.min.js'); +} +else { + mix.copy('node_modules/vue/dist/vue.min.js', 'modules/system/assets/vendor/vue/vue.min.js'); +} + +// Boostrap Mixes +mix + .js('modules/backend/assets/vendor/bootstrap/bootstrap.js', 'modules/backend/assets/vendor/bootstrap/bootstrap.min.js') + .sass('modules/backend/assets/vendor/bootstrap/bootstrap.scss', 'modules/backend/assets/vendor/bootstrap/bootstrap.css') + .sass('modules/backend/assets/vendor/bootstrap/bootstrap-lite.scss', 'modules/backend/assets/vendor/bootstrap/bootstrap-lite.css') + .sass('modules/backend/assets/vendor/bootstrap-icons/bootstrap-icons.scss', 'modules/backend/assets/vendor/bootstrap-icons/bootstrap-icons.css') + .copy('node_modules/bootstrap-icons/font/fonts/', 'modules/backend/assets/vendor/bootstrap-icons/fonts/') +; + +// Core Mixes +require('./webpack.helpers')(mix); +require('./modules/system/system.mix')(mix); +require('./modules/backend/backend.mix')(mix); +require('./modules/editor/editor.mix')(mix); +require('./modules/media/media.mix')(mix); +require('./modules/tailor/tailor.mix')(mix); +require('./modules/cms/cms.mix')(mix);