diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 60bfc63b..00000000 --- a/.editorconfig +++ /dev/null @@ -1,11 +0,0 @@ -# https://editorconfig.org/ -# https://prettier.io/docs/en/configuration#editorconfig - -root = true - -[*] -charset = utf-8 -end_of_line = lf -indent_style = tab -insert_final_newline = true -max_line_length = 80 diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs deleted file mode 100644 index cc156834..00000000 --- a/.git-blame-ignore-revs +++ /dev/null @@ -1,9 +0,0 @@ -# https://git-scm.com/docs/git-blame -# https://github.blog/changelog/2022-03-24-ignore-commits-in-the-blame-view-beta/ -# https://docs.github.com/en/repositories/working-with-files/using-files/viewing-a-file#ignore-commits-in-the-blame-view - -# Prettier 3.0.3 -acc35fbec38d72968b735826c6807793a2054aed - -# Xcode swift indent replace spaces to tabs -962c4d81879e85362a5f878889d3aa869f4e6961 diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index b4a7b25c..00000000 --- a/.gitattributes +++ /dev/null @@ -1,7 +0,0 @@ -# https://git-scm.com/docs/gitattributes -# https://git-scm.com/book/en/Customizing-Git-Git-Attributes -* text=auto - -# https://docs.github.com/en/repositories/working-with-files/managing-files/customizing-how-changed-files-appear-on-github -# https://github.com/github-linguist/linguist/blob/master/docs/overrides.md -public linguist-generated \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index cab762b7..00000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,7 +0,0 @@ -### Please note: the project is currently temporarily suspended from receiving direct code contributions. - -Please do not submit any new pull requests, they will be close immediately. - -If you have any ideas and suggestions, please submit them to us through [`Issues`](https://github.com/quoid/userscripts/issues) or [`Discussions`](https://github.com/quoid/userscripts/discussions). - -We apologize for the inconvenience and thank you for your understanding. diff --git a/.github/workflows/deployment.yaml b/.github/workflows/deployment.yaml deleted file mode 100644 index f9b2e529..00000000 --- a/.github/workflows/deployment.yaml +++ /dev/null @@ -1,70 +0,0 @@ -# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions - -name: Userscripts deployment -on: - release: - types: [published] # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#release -jobs: - Deployment: - strategy: - matrix: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs - platform: [mac, ios] - runs-on: macos-26 # https://github.com/actions/runner-images - steps: - - uses: actions/checkout@v4 # https://github.com/actions/checkout - with: - fetch-depth: 0 - fetch-tags: true # https://github.com/actions/checkout/issues/1781 - - uses: actions/setup-node@v4 # https://github.com/actions/setup-node - with: - node-version: latest - - id: semver # Parse semver from github ref - uses: userscriptsup/actions/semver-parser@main - - name: Verify release type - run: | - if ${{ github.event.release.prerelease }}; then - ${{ steps.semver.outputs.beta }} || exit 11 - else - ${{ steps.semver.outputs.alpha }} && exit 12 - ${{ steps.semver.outputs.beta }} && exit 13 - [ -n "${{ steps.semver.outputs.prerelease }}" ] && exit 14 - exit 0 - fi - - run: npm ci - - run: npm run lint:js - - run: npm run lint:css - - run: BETA=1 npm run build:${{ matrix.platform }}-safari-15 - if: ${{ github.event.release.prerelease }} - - run: npm run build:${{ matrix.platform }}-safari-15 - if: ${{ ! github.event.release.prerelease }} - # - name: Set xcode version - # run: sudo xcode-select -s "/Applications/Xcode_26.1.1.app" # https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md#xcode - # - run: xcodebuild -downloadPlatform iOS # Temporary fix for Xcode_26_beta - # if: matrix.platform == 'ios' - - name: Run fastlane - id: fastlane - working-directory: ./fastlane - env: - FASTLANE_OPT_OUT_USAGE: "YES" - MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }} - MATCH_GIT_PRIVATE_KEY: "fastlane/${{ secrets.GIT_PRIVATE_KEY_FILE }}" - GIT_PRIVATE_KEY_FILE: ${{ secrets.GIT_PRIVATE_KEY_FILE }} - GIT_PRIVATE_KEY_BASE64: ${{ secrets.GIT_PRIVATE_KEY_BASE64 }} # https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#storing-base64-binary-blobs-as-secrets - MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - GYM_INSTALLER_CERT_NAME: ${{ secrets.GYM_INSTALLER_CERT_NAME }} # required for mac (unable to auto-detect) - APP_STORE_CONNECT_API_KEY_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }} - APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }} - APP_STORE_CONNECT_API_KEY_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY }} - MARKETING_VERSION: ${{ steps.semver.outputs.core }} - IS_PRERELEASE: ${{ github.event.release.prerelease }} - run: | - echo $GIT_PRIVATE_KEY_BASE64 | base64 --decode > $GIT_PRIVATE_KEY_FILE - chmod 600 $GIT_PRIVATE_KEY_FILE - bundle install - $IS_PRERELEASE && bundle exec fastlane ${{ matrix.platform }} beta - $IS_PRERELEASE || bundle exec fastlane ${{ matrix.platform }} release - - name: Artifact dSYM - uses: actions/upload-artifact@v4 # https://github.com/actions/upload-artifact - with: - name: Userscripts_${{ matrix.platform }}_${{ steps.fastlane.outputs.ver || github.ref_name }}.app.dSYM - path: build/*.dSYM.zip diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 45e462ed..00000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: lint -on: - - pull_request -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Install modules - run: npm install - - name: Run ESLint - run: npm run lint:js - - name: Run Stylelint - run: npm run lint:css diff --git a/.gitignore b/.gitignore index 6e9c9304..73b92ed1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,19 +1,3 @@ -# OS generated files -.DS_Store -.DS_Store? -._* -.Spotlight-V100 -.Trashes -ehthumbs.db -Thumbs.db - -# Temp/Dist/Built -temp -dist -dist-ssr -build -built - # Logs logs *.log @@ -23,11 +7,11 @@ yarn-error.log* pnpm-debug.log* lerna-debug.log* -# npm node_modules -#package-lock.json -yarn.lock -pnpm-lock.yaml +temp +dist +dist-ssr +*.local # Editor directories and files .vscode/* @@ -41,18 +25,20 @@ pnpm-lock.yaml *.sln *.sw? +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + # xcode xcuserdata/ *.xcuserstate *.dev.xcconfig XCBuildData -xcode/Ext-Safari/Resources/ - -# directories and files -local -*.local -/scripts/*.local.js - -# fastlane -/fastlane/report.xml -/fastlane/**/*.local.rb \ No newline at end of file +xcode/**/build/ +xcode/**/dist/ +# xcode/Userscripts-iOS/Base.lproj/Main.html \ No newline at end of file diff --git a/.postcssrc.json b/.postcssrc.json deleted file mode 100644 index 5c893e80..00000000 --- a/.postcssrc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "plugins": { - "autoprefixer": { "overrideBrowserslist": ["safari >= 15"] } - } -} diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 5c1a0da1..00000000 --- a/.prettierignore +++ /dev/null @@ -1,26 +0,0 @@ -# env -.env -.env.* -!.env.example -.DS_Store - -# root -/package -/public/**/vendor -/etc - -# dir -node_modules -xcode -build -built -dist -temp - -# files -*.svg - -# Ignore files for PNPM, NPM and YARN -package-lock.json -pnpm-lock.yaml -yarn.lock diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index a651d67a..00000000 --- a/.prettierrc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "plugins": ["prettier-plugin-svelte"], - "useTabs": true -} diff --git a/.stylelintrc.json b/.stylelintrc.json deleted file mode 100644 index 707413f5..00000000 --- a/.stylelintrc.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "extends": ["stylelint-config-standard", "stylelint-config-html"], - "ignoreFiles": [ - "**/etc/**", - "**/dist/**", - "**/build/**", - "**/node_modules/**", - "**/reset.css", - "public/**", - "xcode/**" - ], - "rules": { - "alpha-value-notation": "number", - "custom-property-empty-line-before": null, - "no-descending-specificity": null, - "property-no-vendor-prefix": null, - "selector-class-pattern": null, - "selector-pseudo-class-no-unknown": [ - true, - { - "ignorePseudoClasses": ["global"] - } - ] - } -} diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 02ec4445..00000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,9 +0,0 @@ -// https://code.visualstudio.com/docs/editor/extension-gallery#_workspace-recommended-extensions -{ - "recommendations": [ - "svelte.svelte-vscode", - "esbenp.prettier-vscode", - "dbaeumer.vscode-eslint", - "stylelint.vscode-stylelint" - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 892bfd4d..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,21 +0,0 @@ -// https://code.visualstudio.com/docs/getstarted/settings#_workspace-settings -{ - "files.associations": { - ".git-blame-ignore-revs": "ignore" - }, - "editor.formatOnSave": true, - "editor.defaultFormatter": "esbenp.prettier-vscode", - "[yaml]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "[jsonc]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "[css]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "[html]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "[svelte]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "[markdown]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - // https://github.com/microsoft/vscode-eslint#settings-options - "eslint.validate": ["javascript", "svelte"], - // https://github.com/stylelint/vscode-stylelint#stylelintvalidate - "stylelint.validate": ["css", "postcss", "svelte"] -} diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index c967bcab..00000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,142 +0,0 @@ -// https://code.visualstudio.com/docs/editor/tasks -{ - "version": "2.0.0", - "tasks": [ - { - "label": "npm: install", - "detail": "Install dev dependencies", - "type": "shell", - "command": "npm install", - "group": "build", - "options": { - "cwd": "./" - } - }, - { - "label": "npm: dev", - "detail": "Run dev server", - "type": "shell", - "command": "npm run dev", - "group": "build", - "options": { - "cwd": "./" - } - }, - { - "label": "npm: dev ext-safari-mac", - "detail": "Run dev server and build dev resource to xcode dist", - "type": "shell", - "command": "npm run dev:ext-safari-mac", - "group": "build", - "options": { - "cwd": "./" - } - }, - { - "label": "npm: dev ext-safari-ios", - "detail": "Run dev server and build dev resource to xcode dist", - "type": "shell", - "command": "npm run dev:ext-safari-ios", - "group": "build", - "options": { - "cwd": "./" - } - }, - { - "label": "npm: build mac", - "detail": "Build to xcode dist path", - "type": "shell", - "command": "npm run build:mac", - "group": "build", - "options": { - "cwd": "./" - } - }, - { - "label": "npm: build ios", - "detail": "Build to xcode dist path", - "type": "shell", - "command": "npm run build:ios", - "group": "build", - "options": { - "cwd": "./" - } - }, - { - "label": "xcodebuild: mac-debug", - "detail": "xcodebuild mac debug", - "type": "shell", - "command": "xcodebuild -scheme Mac -configuration Debug", - "group": "build", - "options": { - "cwd": "./xcode/" - } - }, - { - "label": "xcodebuild: mac-vite", - "detail": "xcodebuild mac vite", - "type": "shell", - "command": "xcodebuild -scheme Mac-Vite-Dev -configuration Vite", - "group": "build", - "options": { - "cwd": "./xcode/" - } - }, - { - "label": "dev: ext-safari-mac", - "detail": "npm: dev ext-safari-mac + xcodebuild: mac-vite", - "presentation": { - "reveal": "silent" - }, - "dependsOrder": "sequence", - "dependsOn": ["npm: dev ext-safari-mac", "xcodebuild: mac-vite"], - "group": { - "kind": "build", - "isDefault": true - } - }, - { - "label": "build: mac debug", - "detail": "npm: build mac + xcodebuild: mac-debug", - "presentation": { - "reveal": "silent" - }, - "dependsOrder": "sequence", - "dependsOn": ["npm: build mac", "xcodebuild: mac-debug"], - "group": { - "kind": "build", - "isDefault": true - } - }, - { - "label": "lint: js", - "detail": "lint js with eslint", - "type": "shell", - "command": "npm run lint:js", - "group": "test", - "options": { - "cwd": "./" - } - }, - { - "label": "lint: css", - "detail": "lint css with stylelint", - "type": "shell", - "command": "npm run lint:css", - "group": "test", - "options": { - "cwd": "./" - } - }, - { - "label": "prettier", - "detail": "applying prettier formatting for all supported files", - "type": "shell", - "command": "npm run prettier", - "options": { - "cwd": "./" - }, - "problemMatcher": [] - } - ] -} diff --git a/LICENSE b/LICENSE deleted file mode 100644 index f288702d..00000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/README.md b/README.md index 09cdc78a..466dad3d 100644 --- a/README.md +++ b/README.md @@ -1,391 +1,10 @@ -# Userscripts Safari +# [Userscripts GitHub Pages](https://quoid.github.io/userscripts/) -An open-source userscript editor for Safari - -![Userscripts Safari](/etc/screenshot.png) - -## Table of Contents - -- [Installation](#installation) -- [Usage](#usage) -- [UI Overview](#ui-overview) - - [Browser Page](#browser-page) - - [Settings Modal](#settings-modal) - - [Popover](#popover) -- [Metadata](#metadata) -- [API](#api) -- [Scripts Directory / Save Location](#scripts-directory) -- [Getting Help](#getting-help) -- [FAQs](#faqs) -- [Contributing](#contributing) -- [Support](#support) -- [Privacy Policy](#privacy-policy) -- [License](#license) - -## Installation - -Userscripts is available for iOS (iPadOS) and macOS. For all versions, installation is done through [Apple's App Store](https://itunes.apple.com/us/app/userscripts/id1463298887). On macOS, versions prior to `4.x` were made available to download and install directly from the repository, but due to [changes in the way Apple allows developers to distribute apps built with the WebExtension API](https://github.com/quoid/userscripts/issues/154), that is no longer an option. - -To run Userscripts on iOS you should be on iOS 15.1 or higher. - -To run Userscripts on macOS you should running macOS 12 or higher, along with Safari 14.1 or higher. - -**[App Store Link](https://itunes.apple.com/us/app/userscripts/id1463298887)** - -**[Development Progress](https://github.com/quoid/userscripts/projects/3)** - -## Usage - -It's recommend to read this documentation and, if you have time, watch the following video overviews to familiarize yourself with the app and extension. - -Once the app is downloaded and installed the following steps should be taken: - -### **iOS (iPadOS)** - -After installing the iOS App, you need two main steps to make the extension work: - -- **Open the App and set a directory** (For saving and loading userscripts) - - After Userscripts for ios v1.5.0, a local default directory will be set automatically - - In earlier versions please click the `Set Userscripts Directory` button and select the directory -- **Enable the extension in Safari** (And grant permissions) - - - Manage extensions from Settings App (Settings > Safari > Extensions) or Safari App (`AA` button on iPhone, `extension-icon` on iPad, also where you open the extension's `popup` interface) - - For optimal experience it's recommended that you `Always Allow` Userscripts for `All Websites` - -> [!NOTE] -> -> The iOS App cannot detect whether you have enabled the extension in Safari, therefore, the App prompt will not change after you enable the extension. Currently the App interface is only used to set or change the userscripts directory. -> -> You could select an iCloud folder for syncing scripts between macOS and iOS, but please note that there may be delays in synchronization, and you may encounter files be evictioned due to iCloud optimization, please refer to [#424](https://github.com/quoid/userscripts/issues/424). (**Since macOS 15 / iOS 18, please set "keep downloaded" for the folder to avoid eviction**) - -There are two main ways to install a user script from the iOS version: - -- Visit a `.user.js` URL in Safari, then open the extension `popup` and you will see an installation prompt - - The URL should end with `.user.js` in `/PATH` part, not the `?QUERY` or `#HASH` parts -- You could also save files with the extension `.user.js` directly to the Userscripts directory you set above - -> [!TIP] -> -> Both of the above work equally well in the macOS version. -> -> The iOS version does not include the script editor provided in the macOS version, but you can always edit script files in the directory you set directly on iOS. (use any third-party code editor apps, support in-place opening and editing) - -### **macOS** - -After installing Userscripts on macOS, you **do not** need to select a userscripts directory if you do not plan on syncing your userscripts between multiple devices. Instead you can choose to use the default directory, which is located at `~/User/Library/Containers/Userscripts/Data/Documents/scripts` - again, this is default (and automatic) behavior. You only need to select a new location if you want to store your userscripts elsewhere, which is especially useful if you are using an external code editor such as Sublime Text or VSCode. - -Refer to Apple's official guide page: [Use Safari extensions on your Mac](https://support.apple.com/102343) - -[**Here's a short clip showing how to easily create/add a userscript in Safari using this extension on macOS**](https://youtu.be/x1r3-L7pdYQ?t=14) - -## UI Overview - -### Browser Page: - -![Userscripts Safari Main Application Window](/etc/ui01.png) - -1. **Extension button** - click this button to open the extension interface -1. **Filter bar** - use this input to filter items in the sidebar, by _name_ -1. **Sort button** - changes the order of the items in the sidebar by name or modified time -1. **Sidebar buttons** - _described left to right_ - - The `settings` button (represented by a [cog](https://wikipedia.org/wiki/Gear)) displays the settings modal (discussed below) - - The `plus` button allows users to add new items - - `New CSS` is a "userscript" that expects [CSS](https://www.w3schools.com/css/) code - - `New Javascript` is a prototypical userscript that expects [Javascript](https://www.w3schools.com/js/DEFAULT.asp) code - - `New Remote` allows the user to add a remote hosted userscript (or style) by inputting the web address (_ex:_ `https://www.k21p.com/example.user.js`) -1. **Item toggle** - this toggle enables or disables an item -1. **Item** - this is the userscript (or style), clicking on it will load it's contents into the editor - _you can hide descriptions in the settings area!_ -1. **Editor buttons (top)** - _described left to right_ - - **Update button** - this button allows you to update userscripts that meet the following conditions - - metadata contains `@version` tag - - metadata contains `@updateURL` tag - - **Download button** - click this button to download a copy of your userscript - - _Note:_ every userscript that is displayed in the interface is already present on your local machine, at your save location - the download button offers a quick way to retrieve a copy of that file, without needing to click the settings button, and then the save location link within the settings modal - - **Trash button** - moves the currently loaded userscript to the trash bin - it will subsequently be removed from the interface and save location -1. **Editor buttons (bottom)** - - `Discard` - while editing, reverts any unsaved changes you've made to a userscript - - `Save` - while editing, saves all changes you've made to a userscript - - `Command + S` is the keyboard shortcut for the action - -### Settings Modal: - -![Userscripts Safari Settings Window](/etc/settings.png) - -- **Auto Close Brackets** - toggles on/off auto closing of brackets in the editor - - this affects the following characters: `() [] {} "" ''` -- **Auto Hint** - automatically shows completion hints while editing -- **Hide Descriptions** - hides the item descriptions in the sidebar -- **Show Invisibles** - toggles the display of invisible characters in the editor -- **Javascript Linter** - toggles basic Javascript linting within the editor -- **Tab Size** - the number of spaces a tab is equal to while editing, obviously defaults to `4` because using `2` spaces is absolute insanity -- **Enable Injection** - toggle on/off script injection for the pages you visit (this is the on/off switch) -- **Show Toolbar Count** - displays a badge on the toolbar icon with a number that represents how many enabled scripts match the url for the page you are on -- **Save Location** - where your file are currently located and being saved to (click the blue text to open location) -- **Change Save Location (cogs icon)** - this button, located directly to the right of the save location, is a shortcut for opening the host app, which will allow you to change the save location -- **Global Blacklist** - this input accepts a comma separated list of `@match` patterns ([Match pattern structure](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns#match_pattern_structure)), a page url that matches against a pattern in this list will be ignored for script injection - -### Popup: - - - - - -10. **Open Page Link** - _macOS only_, opens the extension browser page -11. **Enable Injection toggle** - turns on/off page script injection (on/off switch) -12. **Refresh View** - refreshes the popup view -13. **Available Updates View** - the extension periodically checks all userscripts in your save location for updates and when an update is found, it is shown in this view -14. **Folder Button** - on **macOS** this button opens your save location directory in Finder, on **iOS** this button displays the "all scripts view" where you can see every script that found in your save location directory, the "all scripts view" allows you to toggle individual userscript scripts on/off regardless of the current page being displayed in the browser -15. **Install Prompt** - when a userscript is displayed in the browser, this alert displays, giving the user the option to install the userscript into their save location directory, tapping the prompt will take them through the installation steps -16. **Matched Userscripts List** - this list shows the currently matched userscripts relative to the current page being displayed in the browser, all userscripts that match to the domain will be showed, whether they are active or not. Users can click/tap the userscript to the toggle them on/off. If a userscript is active for the domain through a subframe a **sub** tag will be show next the to the file type indicator - -## Metadata - -Userscripts Safari currently supports the following userscript metadata: - -- `@name` - This will be the name that displays in the sidebar and be used as the filename - you can _not_ use the same name for multiple files of the same type -- `@description`- Use this to describe what your userscript does - this will be displayed in the sidebar - there is a setting to hide descriptions -- `@icon` - This doesn't have a function with this userscript manager, but the **first value** provided in the metadata will be accessible in the `GM_/GM.info` object -- `@match` - Domain match patterns - you can use several instances of this field if you'd like multiple domain matches - please refer to: [Match pattern structure](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns#match_pattern_structure) - - **Note:** this extension only supports `http/s` -- `@exclude-match` - Domain patterns where you do _not_ want the script to run -- `@include` - Used to match against urls for injection, globs and regular expressions are allowed, [read more here](https://wiki.greasespot.net/Include_and_exclude_rules) -- `@exclude` - Functions in a similar way as `@include` but rather than injecting, a match against this key's value will prevent injection -- `@inject-into` - allows the user to choose which context to inject the script into - - allows the user to choose which context to inject the script into - - values: `auto` (default), `content`, `page` - - `GM` apis are only available when using `content` - - works like [violentmonkey](https://violentmonkey.github.io/api/metadata-block/#inject-into) -- `@run-at` - - allows the user to choose the injection timing - - document-start, document-end (default), document-idle - - works like [violentmonkey](https://violentmonkey.github.io/api/metadata-block/#run-at) - - **JS Only** -- `@weight` - - allows the user to further adjust script injection timing - - can be used to ensure one script injects before another - - ONLY accepts integers (floats, strings and everything else will be ignored) - - min value = 1, max value = 999, higher numbers (“heavier”) execute earlier -- `@require` - - allows users to include remote resources in their scripts - - the value must be a valid url, currently no local file support - - must require a resource of the same file type (JS for JS, CSS for CSS) - - when a resource is required, it is downloaded and saved locally - - the resources is downloaded once at save and never checked for updates or parsed in anyway - - if you want to update the require resources, and the url does not change, you must remove the resources, save, then re-input it - - **require remote resources at your own risk, the extension never validates remote resource code in any way and be aware that using remote resources from untrusted sources can jeopardize your personal security** -- `@version` - - used to determine the current version of a userscript - - when paired with `@updateURL`, this will allow the user to update a userscript from a remote source, if the version on their machine is `<` version at the update URL - - `@version` does nothing by itself, it needs to be paired with` @updateURL` for remote updating to function properly -- `@updateURL` - - the remote url to check version against, the url `/PATH` should end with `.meta.js` and contains the Metadata block - - if the version of the file located at the update URL is `>` the version on the local machine, the file will be updated - - `@updateURL` does nothing by itself, it needs to be paired with `@version` for remote updating to function properly - - Read this [link](https://stackoverflow.com/questions/38023717/) for more details - - _Note: The extension does not correctly implement the entire update process, tracking in issue [#248](https://github.com/quoid/userscripts/issues/248)_ -- `@downloadURL` - - the url `/PATH` should end with `.user.js`, that is, it cannot be in `?QUERY` or `#HASH` parts - - optional download location for a remotely updateable file (\*i.e. a file that has both `@version` and `@updateURL`) - - when paired with `@version` and `@updateURL`, if the local version is `<` the version of the file that `@updateURL` points to, the extension will attempt to update the file's code with the contents of the file located at the `@downloadURL` - - `@downloadURL` does nothing by itself, it needs `@version` and `@updateURL` to present in order to function properly -- `@noframes` - - this key takes no value - - prevents code from being injected into nested frames -- `@grant` - - Imperative controls which special [`APIs`](#api) (if any) your script uses, one on each `@grant` line, only those API methods will be provided. - - If no `@grant` values are provided, `none` will be assumed. - - If you specify `none` and something else, `none` takes precedence. - -**All userscripts need at least 1 `@match` or `@include` to run!** - -## API - -Userscripts currently supports the following api methods. All methods are asynchronous unless otherwise noted. Users must `@grant` these methods in order to use them in a userscript. When using API methods, it's only possible to inject into the content script scope due to security concerns. - -> [!NOTE] -> -> The following API description applies to the latest development branch, you may need to check the documentation for the corresponding version. Please switch to the version you want to check via `Branches` or `Tags` at the top. For example: -> -> For the current version of the App Store: -> https://github.com/quoid/userscripts/tree/release/4.x.x#api -> -> For the v4.5.x and earlier versions: -> https://github.com/quoid/userscripts/tree/v4.5.4#api - -For API type definitions, please refer to: [`types.d.ts`](https://github.com/userscriptsup/testscripts/blob/f2fcde4b556fa436fe806a44a89afb9eb5dccd0b/userscripts/types.d.ts) - -- `GM.addStyle(css)` - - `css: String` - - returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), resolved if succeeds, rejected with error message if fails -- `GM.setValue(key, value)` - - `key: String` - - `value: Any` - any can be JSON-serialized - - returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), resolved if succeeds, rejected with error message if fails -- `GM.getValue(key, defaultValue)` - - `key: String` - - `defaultValue: Any` - optional - - returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), resolved with the `value` that was set or `defaultValue` provided or `undefined` if succeeds, rejected with error message if fails -- `GM.deleteValue(key)` - - `key: String` - - returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), resolved if succeeds, rejected with error message if fails -- `GM.listValues()` - - returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), resolved with an array of the key names of **presently set** values if succeeds, rejected with error message if fails -- `GM.getTab()` - - returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), resolved with `Any` data that is persistent as long as this tab is open if succeeds, rejected with error message if fails -- `GM.saveTab(tabObj)` - - `tabObj: Any` - any can be JSON-serialized - - returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), resolved if succeeds, rejected with error message if fails -- `GM.openInTab(url, openInBackground)` - - `url: String` - - `openInBackground: Bool` - optional, `false` by default - - returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), resolved with [tab data](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/Tab) for the tab just opened if succeeds, rejected with error message if fails -- `GM.closeTab(tabId)` - - `tabId: Int` - optional, the `caller tab` by default - - returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), resolved if succeeds, rejected with error message if fails -- `GM.setClipboard(data, type)` - - `data: String` - - `type: String` - optional, `text/plain` by default - - [read more here](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent/clipboardData) - - returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), resolved with a `Bool` value indicating succeeds or fails, rejected with error message if fails -- `GM.info` && `GM_info` - - is available without needing to add it to `@grant` - - an object containing information about the running userscript - - `scriptHandler: String` - returns `Userscripts` - - `version: String` - the version of Userscripts app - - `scriptMetaStr: String` - the metablock for the currently running script - - `script: Object` - contains data about the currently running script - - `description: String` - - `exclude-match: [String]` - - `excludes: [String]` - - `grant: [String]` - - `includes: [String]` - - `inject-into: String` - - `matches: [String]` - - `name: String` - - `namespace: String` - - `noframes: Bool` - - `require: [String]` - - `resources: [String]` - _currently not implemented_ - - `run-at: String` - - `version: String` - _the userscript version value_ -- `GM.xmlHttpRequest(details)` - - `details: Object` - - the `details` object accepts the following properties - - `url: String` - required - - `method: String` - optional, `GET` by default - - `user: String` - optional - - `password: String` - optional - - `headers: Object` - optional - - `overrideMimeType: String` - optional - - `timeout: Int` - optional - - `binary: Bool` - optional (Deprecated, use binary data objects such as `Blob`, `ArrayBuffer`, `TypedArray`, etc. instead.) - - `data: String | Blob | ArrayBuffer | TypedArray | DataView | FormData | URLSearchParams` - optional - - `responseType: String` - optional - - refer to [`XMLHttpRequests`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) - - upload event handlers: - - `upload: Object` - optional - - `onabort: Function` - optional - - `onerror: Function` - optional - - `onload: Function` - optional - - `onloadend: Function` - optional - - `onloadstart: Function` - optional - - `onprogress: Function` - optional - - `ontimeout: Function` - optional - - the progress object passed to the event handlers has the following properties: - - `lengthComputable` - - `loaded` - - `total` - - event handlers: - - `onabort: Function` - optional - - `onerror: Function` - optional - - `onload: Function` - optional - - `onloadend: Function` - optional - - `onloadstart: Function` - optional - - `onprogress: Function` - optional - - `onreadystatechange: Function` - optional - - `ontimeout: Function` - optional - - the response object passed to the event handlers has the following properties: - - `readyState` - - `response` - - `responseHeaders` - - `responseType` - - `responseURL` - - `status` - - `statusText` - - `timeout` - - `responseText` (when `responseType` is `text`) - - returns a custom [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) contains an additional property `abort`, resolved with the response object. - - usage: - - `const xhr = GM.xmlHttpRequest({...});` - - `xhr.abort();` to abort the request - - `const response = await xhr;` - - or just: - - `const response = await GM.xmlHttpRequest({...});` -- `GM_xmlhttpRequest(details)` - - Basically the same as `GM.xmlHttpRequest(details)`, except: - - returns an object with a single property, `abort`, which is a `Function` - - usage: `const foo = GM.xmlHttpRequest({...});` ... `foo.abort();` to abort the request - -## Scripts Directory - -This is the directory where the app/extension will read from and write to. This directory is changed by opening the **containing app** and clicking the respective "change location" button. - -**Script Directory Notes** - -- Close all instances of the extension UI (browser app and/or popup) before changing the scripts directory -- After files are added, removed or edited, you will need to open the popup at least 1 time to see those changes reflected in your browsing experience -- **On macOS**, after a directory outside of the default is selected, if you rename or move that selected directory, the extension will continue to read/write to that directory - the only way to remove the “link” is by trashing the folder or selecting a new save location - -## Getting Help - -If you encounter a problem while using this app/extension or are in need of some assistance, please open an issue here in the repository. When doing so, please provide as much detail as possible. This includes listing system specs and what website and script you are trying to execute. _Please follow the issue template!_ - -## FAQs - -**"Refused to execute a script" error(s), what should I do!?** - -> You are seeing this error because of the website's [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP). Currently there is no way to allow extension content scripts to bypass CSPs in Safari. -> -> Automatically, the extension will attempt to circumvent strict CSPs, but if you are still experiencing issues, trying setting the userscript metadata key/val `// @inject-into auto` or `// @inject-into content`. -> -> You can read more about this in [this issue](https://github.com/quoid/userscripts/issues/106#issuecomment-797320450). - -**Do I need to use the extension's editor to create new userscripts or to edit existing?** - -> You can use your own editor to update and manage your files. As long as you are saving the files to the save location, and they are properly formatted, they should be injected. However, you **must open the extension popup** beforehand. That means, if you create a new or edit an existing userscript with an external editor and save it to the save location, before injection will occur properly, the extension popup must be opened and the popup must load completely. - -**What are the keyboard shortcuts?** - -> Whilst using the included editor, clicking `⌘ + s` will save the file. While working the editor, clicking `⌘ + f` will bring up the search bar and `esc` will hide it. - -**When I use `@require`, where are the required files stored?** - -> All required files are saved _as Javascript files_ in the extension container folder in macOS 11.x. That folder is located in the default save location, at: `~/Library/Containers/Userscripts/Data/Documents/require/`. -> -> If you move files from the require folder or manually edit the `manifest.json` file, you will likely break app/extension functionality. - -## Contributing - -Code level contributions please refer to [contributing.md](docs/contributing.md) - -Further, any issue marked "help wanted" is actively seeking assistance. Please respond to those issues with feedback, guidance or offers of coding assistance. - -Participating and interacting with any existing [`Issues`](https://github.com/quoid/userscripts/issues) or [`Discussions`](https://github.com/quoid/userscripts/discussions) would be a great help to the project and open source communities. Thank you for your contributions. - -## Support - -The quickest and easiest way to support the project is by [leaving a positive review on the App Store](https://apps.apple.com/us/app/userscripts/id1463298887) if you enjoy the extension and want to see future improvements. Seeing these reviews let me know I am doing something right, or wrong, and motivates me to continue working on the project. - -The second best way to help out is to sign up to beta test new versions of the app. Since this extension values your privacy, and **does not collect any data from users**, it is difficult to gauge how the extension is being used. By signing up to be a beta tester it not only allows you to test upcoming features, but also gives me the opportunity to elicit direct feedback from real users. - -**Please join and test the corresponding beta version in [releases](https://github.com/quoid/userscripts/releases) via the TestFlight public link.** - -## Privacy Policy - -Userscripts does not collect any data from its users nor monitor activities or actions you perform within the application and extension. This means everything that you do with the application and extension is private to you and is never shared with the developers or third parties. Since there is no data collection, there is no data retention of any kind. +## Userscripts Safari +https://github.com/quoid/userscripts ## License -Copyright © 2018-2025 Justin Wasack +Copyright (c) 2022 Justin Wasack -Licensed under the [GNU General Public License v3.0](/LICENSE) license for all open source applications. A commercial license is required for all other applications. +Licensed under the [GNU General Public License v3.0](/LICENSE) license for all open source applications. A commercial license is required for all other applications. \ No newline at end of file diff --git a/Userscripts.code-workspace b/Userscripts.code-workspace deleted file mode 100644 index 11c4d094..00000000 --- a/Userscripts.code-workspace +++ /dev/null @@ -1,14 +0,0 @@ -// https://code.visualstudio.com/docs/editor/workspaces -{ - "folders": [ - { - "name": "Userscripts-JS", - "path": ".", - }, - { - "name": "Userscripts-Xcode", - "path": "xcode", - }, - ], - "settings": {}, -} diff --git a/docs/contributing.md b/docs/contributing.md deleted file mode 100644 index 3cb92e9d..00000000 --- a/docs/contributing.md +++ /dev/null @@ -1,120 +0,0 @@ -# Welcome to Userscripts contributing guide - -### Please note: the project is currently temporarily suspended from receiving direct code contributions. - -Please do not submit any new pull requests, they will be close immediately. - -If you have any ideas and suggestions, please submit them to us through [`Issues`](https://github.com/quoid/userscripts/issues) or [`Discussions`](https://github.com/quoid/userscripts/discussions). - -We apologize for the inconvenience and thank you for your understanding. - -### The following is the original guide for reference only. - -Thank you for investing your time in contributing to this open source project! - -We hope this guide will helps you understand how to contribute to this project. - -For development and build environments please refer to [development guide](dev.md). - -> [!NOTE] -> Portions of this guide are outdated. Some processes are still being tweaked and optimized, we will update them in due course. - -> [!IMPORTANT] -> Please ensure your contributions align with the project's license before committing anything. -> -> Any pull requests must first go through code formatting and linters, otherwise you will fail the CI check. (Refer to the `scripts` in [`package.json`](../package.json)) - -# Branches - -### `main`: default branch - -- corresponding to development channel -- all development work around this branch -- protected branches not accept commits -- all work will be done in sub-branches -- all sub-branches will be merged via PRs - -### `beta`: latest test version - -- generated from the master branch -- corresponding to TestFlight channel -- only accept version number commits -- hotfixes and PRs are not accepted -- never merge back into master branch - -### `release`: latest public version - -- generated from the beta branch -- generate GitHub Releases and Tags -- corresponding to App Store channel -- accept hotfixes and version commits -- always merge back into master branch - -# Commits - -### Please use semantic commit messages - -Format: `(): ` - -`` is optional - -### Example - -``` -feat: add hat wobble -^--^ ^------------^ -| | -| +-> Summary in present tense. -| -+-------> Type: chore, docs, feat, fix, refactor, style, or test. -``` - -More Examples: - -- `feat`: (new feature for the user, not a new feature for build script) -- `fix`: (bug fix for the user, not a fix to a build script) -- `docs`: (changes to the documentation) -- `style`: (formatting, missing semi colons, etc; no production code change) -- `refactor`: (refactoring production code, eg. renaming a variable) -- `test`: (adding missing tests, refactoring tests; no production code change) -- `chore`: (updating grunt tasks etc; no production code change) - -[References](https://gist.github.com/joshbuchea/6f47e86d2510bce28f8e7f42ae84c716) - -# Pull requests - -Almost all features and fixes will be merged into the master branch via pull requests (PRs). - -We will improve the guidelines for creating PRs in the future, like create [`pull request template`](https://docs.github.com/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository). - -# Workflow - -If you are not a member of the project, first you need to fork the master branch of the repository. - -### General development - -- create a new branch from the master branch -- suggested branch naming format like: - - `issue/333` - - `feat/...` - - `fix/...` -- complete your commits in this new branch -- create a pull request from this new branch -- wait for other maintainers to review your changes -- pull request will be merged into master branch - -### Generate beta version - -- All completed features and fixes get into beta as soon as possible so that they get the maximum testing cycle time. -- Beta releases use build numbers incremented, version numbers always use the next major release. -- Bugs found and reported during testing are still fixed around the master branch and will be introduced in the rolling beta build. - -### Generate public version - -- When the series of betas has stabilized, we can produce a public release. -- If necessary, we can delay merging PRs of new features into the master branch, give priority to fixing bugs found in the beta version, and ensure the stability of the public version as much as possible. -- Despite various tests, we may still find bugs through user feedback in the public version, and we will fix those minor bugs through hotfixes. - -# About - -[Userscripts](https://github.com/quoid/userscripts) diff --git a/docs/dev.md b/docs/dev.md deleted file mode 100644 index 262aac05..00000000 --- a/docs/dev.md +++ /dev/null @@ -1,82 +0,0 @@ -# Environment - -The `root` directory is a typical multi-page app of Vite with Svelte JavaScript project. - -The `xcode` directory is the root of the Xcode project where the Safari extension app is built. - -For other directory structure instructions, please refer to [structure.md](structure.md). - -### Recommended code editor - -[Visual Studio Code](https://github.com/Microsoft/vscode) with extensions: [/.vscode/extensions.json](../.vscode/extensions.json) - -# Template - -The project is currently based on [`template-svelte`](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-svelte) from [`create-vite`](https://github.com/vitejs/vite/tree/main/packages/create-vite). - -Additional reference templates are from [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte). - -Reviewing the template will help you understand the composition of the project. - -# Requirement - -- [`Node.js`](https://nodejs.org/) -- [`Xcode`](https://geo.itunes.apple.com/app/id497799835) -- `Developer Team ID` (i.e. Apple Account, see [Xcode section](#xcode)) - -# Dev - -- `npm install` [^1] -- `npm run dev` [^1] - -# Build - -> [!NOTE] -> Before building the app with Xcode make sure you create the `.dev.xcconfig` files [below](#xcconfig) and fill in your `Developer Team ID`. -> Otherwise `App groups` related functions will not work properly. - -- `npm run build:mac` [^1][^2] -- `cd ./xcode` -- `xcodebuild -scheme Mac` [^1][^2][^3] or build with `Xcode` App - -[^1]: These commands can also be executed directly through the vscode tasks. Please refer to: [/.vscode/tasks.json](../.vscode/tasks.json) - -[^2]: Select the corresponding target and platform to build. Please refer to: [/package.json](../package.json) and [xcode-schemes](../xcode/Userscripts.xcodeproj/xcshareddata/xcschemes/) - -[^3]: Local setup may be required. Please refer to: [Building from the Command Line with Xcode FAQ](https://developer.apple.com/library/archive/technotes/tn2339/_index.html) - -# Xcode - -Please note that a developer account is required, which can be a free Apple Account that has agreed to the Apple Developer Agreement. This is required to obtain a `Team ID` and use the `App groups` capability. - -### Configurations - -The Xcode project contains several configurations, which have independent `xcconfig` configuration files, and can run on your local at the same time without conflicts. - -- `Vite`: for vite real-time development. - -- `Debug`: for development and debugging. - -- `Release`: for building and distributing. - -### xcconfig - -All `xcconfig` files are in the [`/xcode/xcconfig/`](../xcode/xcconfig) directory. Each `.xcconfig` file can be overridden by `.dev.xcconfig` in the same path, they will be ignored by `git`, so you can override any build settings locally. - -For example, you can create an `Userscripts-Debug.dev.xcconfig` file to override [`Userscripts-Debug.xcconfig`](../xcode/xcconfig/Userscripts-Debug.xcconfig) and fill in your own developer account `Team ID` there: - -`Userscripts-Debug.dev.xcconfig` - -``` -DEVELOPMENT_TEAM = XXXXXXXXXX -``` - -Note that all existing `.xcconfig` files already include `.dev.xcconfig` files of the same name, so they will be applied automatically once you create them. You only need to fill in the setting items that need to be overridden or added. - -# Contribute - -[Contributing guide](contributing.md) - -# About - -[Userscripts](https://github.com/quoid/userscripts) diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 00000000..5b080fdc --- /dev/null +++ b/docs/index.html @@ -0,0 +1 @@ +Userscripts Safari
Built for Safari - functionality might be broken in other browsers
diff --git a/docs/serve/download.html b/docs/serve/download.html new file mode 100644 index 00000000..124bf52e --- /dev/null +++ b/docs/serve/download.html @@ -0,0 +1,14 @@ + + + + + + +Userscripts download helper + + +

Due to Safari quirks, we need a page to assist the download functionality.

+

This page does not serve any other purpose.

+

Please refer the pull request #537 for details.

+ + \ No newline at end of file diff --git a/docs/structure.md b/docs/structure.md deleted file mode 100644 index 1a0cd320..00000000 --- a/docs/structure.md +++ /dev/null @@ -1,41 +0,0 @@ -# Project directory structure - -For development and build environments please refer to [development guide](dev.md). - -## `docs` - -Store documents and project description files, etc. - -## `etc` - -Readme references and project history assets - -## `public` - -Project Static Asset -https://vitejs.dev/guide/assets.html#the-public-directory - -### `./public/extension-page/jshint.min.js` - -CodeMirror 5 `codemirror/addon/lint/javascript-lint.js` depends on `jshint.js` -https://codemirror.net/5/doc/manual.html#addon_lint -https://github.com/jshint/jshint/blob/main/dist/jshint.js - -## `scripts` - -Custom build scripts ref in `package.json` -Used to build the source code in `src` below - -## `src` - -Project Web App/Ext Source Code -Build the project from here to xcode resources - -## `xcode` - -Project Bundled App Source Code -Build the project from here to extension bundled app - -# About - -[Userscripts](https://github.com/quoid/userscripts) diff --git a/entry-app-webview.html b/entry-app-webview.html deleted file mode 100644 index d8789222..00000000 --- a/entry-app-webview.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - Userscripts App - - -
- - - diff --git a/entry-ext-action-popup.html b/entry-ext-action-popup.html deleted file mode 100644 index 8d65c1ca..00000000 --- a/entry-ext-action-popup.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - Userscripts popup - - - -
- - - diff --git a/entry-ext-background.html b/entry-ext-background.html deleted file mode 100644 index e3ee5d4c..00000000 --- a/entry-ext-background.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - Userscripts background - - - - - diff --git a/entry-ext-extension-page.html b/entry-ext-extension-page.html deleted file mode 100644 index 24b226cb..00000000 --- a/entry-ext-extension-page.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - Userscripts page - - - -
- - - - diff --git a/eslint.config.js b/eslint.config.js deleted file mode 100644 index e89b2946..00000000 --- a/eslint.config.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file ESLint project configuration (New flat config) - * @see {@link https://eslint.org/docs/latest/use/configure/configuration-files-new} - * @see {@link https://eslint.org/docs/latest/use/configure/migration-guide} - * @see {@link https://eslint.org/docs/latest/extend/plugin-migration-flat-config} - * @see {@link https://eslint.org/blog/2022/08/new-config-system-part-1/} - * @see {@link https://eslint.org/blog/2022/08/new-config-system-part-2/} - */ - -import js from "@eslint/js"; -import globals from "globals"; -import eslintPluginSvelte from "eslint-plugin-svelte"; -import eslintConfigPrettier from "eslint-config-prettier"; - -/** @type {import("eslint").Linter.Config[]} */ -export default [ - /** - * @see {@link https://eslint.org/docs/latest/use/configure/configuration-files-new#using-predefined-configurations} - * @see {@link https://github.com/eslint/eslint/tree/main/packages/js} - */ - js.configs.recommended, - - /** - * @see {@link https://github.com/sveltejs/eslint-plugin-svelte} - */ - ...eslintPluginSvelte.configs.recommended, - ...eslintPluginSvelte.configs.prettier, - - /** - * @see {@link https://github.com/prettier/eslint-config-prettier} - * turns off the conflict rules, put it last - */ - eslintConfigPrettier, - - /** custom config objects */ - - /** @see {@link https://eslint.org/docs/latest/use/configure/configuration-files-new#globally-ignoring-files-with-ignores} */ - { - ignores: ["**/dist/", "**/build/", "etc/", "xcode/", "public/"], - }, - - /** @see {@link https://eslint.org/docs/latest/use/configure/migration-guide#configuring-language-options} */ - { - files: ["*.js", "scripts/**/*.js"], - languageOptions: { - globals: { - ...globals.node, - }, - }, - }, - { - files: ["src/{app,dev,shared}/**/*.{js,svelte}"], - languageOptions: { - globals: { - ...globals.browser, - }, - }, - }, - { - files: ["src/ext/**/*.{js,svelte}"], - languageOptions: { - globals: { - ...globals.browser, - ...globals.webextensions, - }, - }, - }, -]; diff --git a/etc/App Store Screenshot.png b/etc/App Store Screenshot.png deleted file mode 100644 index 1852ca0e..00000000 Binary files a/etc/App Store Screenshot.png and /dev/null differ diff --git a/etc/assets.sketch b/etc/assets.sketch deleted file mode 100644 index 0d440f58..00000000 Binary files a/etc/assets.sketch and /dev/null differ diff --git a/etc/popover-original.png b/etc/popover-original.png deleted file mode 100644 index 406ee145..00000000 Binary files a/etc/popover-original.png and /dev/null differ diff --git a/etc/popover.png b/etc/popover.png deleted file mode 100644 index 565b2ad1..00000000 Binary files a/etc/popover.png and /dev/null differ diff --git a/etc/screenshot.png b/etc/screenshot.png deleted file mode 100644 index 835df5aa..00000000 Binary files a/etc/screenshot.png and /dev/null differ diff --git a/etc/settings-original.png b/etc/settings-original.png deleted file mode 100644 index f31a19fd..00000000 Binary files a/etc/settings-original.png and /dev/null differ diff --git a/etc/settings.png b/etc/settings.png deleted file mode 100644 index 0a77dcc7..00000000 Binary files a/etc/settings.png and /dev/null differ diff --git a/etc/ui01-original.png b/etc/ui01-original.png deleted file mode 100644 index 133dd582..00000000 Binary files a/etc/ui01-original.png and /dev/null differ diff --git a/etc/ui01.png b/etc/ui01.png deleted file mode 100644 index 8d707f76..00000000 Binary files a/etc/ui01.png and /dev/null differ diff --git a/etc/uilayout.sketch b/etc/uilayout.sketch deleted file mode 100644 index f86be3ba..00000000 Binary files a/etc/uilayout.sketch and /dev/null differ diff --git a/fastlane/Appfile b/fastlane/Appfile deleted file mode 100644 index 86b5e78c..00000000 --- a/fastlane/Appfile +++ /dev/null @@ -1,4 +0,0 @@ -# For more information about the Appfile, see: -# https://docs.fastlane.tools/advanced/#appfile - -app_identifier("com.userscripts.macos") diff --git a/fastlane/Fastfile b/fastlane/Fastfile deleted file mode 100644 index dfbdaa49..00000000 --- a/fastlane/Fastfile +++ /dev/null @@ -1,89 +0,0 @@ -# This file contains the fastlane.tools configuration -# You can find the documentation at https://docs.fastlane.tools - -LOCAL_FASTFILE = "local/Fastfile.local.rb" -if File.file?(LOCAL_FASTFILE) - import(LOCAL_FASTFILE) -end - -PROJECT_PATH = "xcode/Userscripts.xcodeproj" - -# https://docs.fastlane.tools/actions/is_ci/ -if is_ci - setup_ci - IS_CI = true -else - IS_CI = false -end - -# https://docs.fastlane.tools/actions/app_store_connect_api_key/ -app_store_connect_api_key( - key_id: ENV['APP_STORE_CONNECT_API_KEY_KEY_ID'], - issuer_id: ENV['APP_STORE_CONNECT_API_KEY_ISSUER_ID'], - key_content: ENV['APP_STORE_CONNECT_API_KEY_KEY'], - key_filepath: ENV['APP_STORE_CONNECT_API_KEY_KEY_FILEPATH'], -) - -default_platform(:ios) - -platform :ios do - lane :beta do - match - BUILD_NUMBER = latest_testflight_build_number(platform: "ios") + 1 - File.open(ENV['GITHUB_OUTPUT'], 'a') do |file| - file.puts "ver=v#{ENV['MARKETING_VERSION']}(#{BUILD_NUMBER})" - end - build_app( - project: PROJECT_PATH, - scheme: "iOS", - xcargs: { - CURRENT_PROJECT_VERSION: BUILD_NUMBER.to_s, - MARKETING_VERSION: ENV['MARKETING_VERSION'], - }, - output_directory: "build", - output_name: "Userscripts-iOS-Beta", - silent: IS_CI, - ) - upload_to_testflight( - changelog: "#{ENV['GITHUB_REF_NAME']}", - distribute_external: true, - groups: ["QA"], - ) - end - - lane :release do - puts "ios release #{ENV['MARKETING_VERSION']}" - beta - end -end - -platform :mac do - lane :beta do - match - BUILD_NUMBER = latest_testflight_build_number(platform: "osx") + 1 - File.open(ENV['GITHUB_OUTPUT'], 'a') do |file| - file.puts "ver=v#{ENV['MARKETING_VERSION']}(#{BUILD_NUMBER})" - end - build_mac_app( - project: PROJECT_PATH, - scheme: "Mac", - xcargs: { - CURRENT_PROJECT_VERSION: BUILD_NUMBER.to_s, - MARKETING_VERSION: ENV['MARKETING_VERSION'], - }, - output_directory: "build", - output_name: "Userscripts-Mac-Beta", - silent: IS_CI, - ) - upload_to_testflight( - changelog: "#{ENV['GITHUB_REF_NAME']}", - distribute_external: true, - groups: ["QA"], - ) - end - - lane :release do - puts "mac release #{ENV['MARKETING_VERSION']}" - beta - end -end \ No newline at end of file diff --git a/fastlane/Gemfile b/fastlane/Gemfile deleted file mode 100644 index a4353219..00000000 --- a/fastlane/Gemfile +++ /dev/null @@ -1,4 +0,0 @@ -source "https://rubygems.org" - -gem "fastlane" -# gem "rubocop" diff --git a/fastlane/Gemfile.lock b/fastlane/Gemfile.lock deleted file mode 100644 index c6013a88..00000000 --- a/fastlane/Gemfile.lock +++ /dev/null @@ -1,233 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - CFPropertyList (3.0.8) - abbrev (0.1.2) - addressable (2.8.8) - public_suffix (>= 2.0.2, < 8.0) - artifactory (3.0.17) - atomos (0.1.3) - aws-eventstream (1.4.0) - aws-partitions (1.1188.0) - aws-sdk-core (3.239.2) - aws-eventstream (~> 1, >= 1.3.0) - aws-partitions (~> 1, >= 1.992.0) - aws-sigv4 (~> 1.9) - base64 - bigdecimal - jmespath (~> 1, >= 1.6.1) - logger - aws-sdk-kms (1.118.0) - aws-sdk-core (~> 3, >= 3.239.1) - aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.205.0) - aws-sdk-core (~> 3, >= 3.234.0) - aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.5) - aws-sigv4 (1.12.1) - aws-eventstream (~> 1, >= 1.0.2) - babosa (1.0.4) - base64 (0.2.0) - bigdecimal (3.3.1) - claide (1.1.0) - colored (1.2) - colored2 (3.1.2) - commander (4.6.0) - highline (~> 2.0.0) - csv (3.3.5) - declarative (0.0.20) - digest-crc (0.7.0) - rake (>= 12.0.0, < 14.0.0) - domain_name (0.6.20240107) - dotenv (2.8.1) - emoji_regex (3.2.3) - excon (0.112.0) - faraday (1.10.4) - faraday-em_http (~> 1.0) - faraday-em_synchrony (~> 1.0) - faraday-excon (~> 1.1) - faraday-httpclient (~> 1.0) - faraday-multipart (~> 1.0) - faraday-net_http (~> 1.0) - faraday-net_http_persistent (~> 1.0) - faraday-patron (~> 1.0) - faraday-rack (~> 1.0) - faraday-retry (~> 1.0) - ruby2_keywords (>= 0.0.4) - faraday-cookie_jar (0.0.8) - faraday (>= 0.8.0) - http-cookie (>= 1.0.0) - faraday-em_http (1.0.0) - faraday-em_synchrony (1.0.1) - faraday-excon (1.1.0) - faraday-httpclient (1.0.1) - faraday-multipart (1.1.1) - multipart-post (~> 2.0) - faraday-net_http (1.0.2) - faraday-net_http_persistent (1.2.0) - faraday-patron (1.0.0) - faraday-rack (1.0.0) - faraday-retry (1.0.3) - faraday_middleware (1.2.1) - faraday (~> 1.0) - fastimage (2.4.0) - fastlane (2.229.1) - CFPropertyList (>= 2.3, < 4.0.0) - abbrev (~> 0.1.2) - addressable (>= 2.8, < 3.0.0) - artifactory (~> 3.0) - aws-sdk-s3 (~> 1.0) - babosa (>= 1.0.3, < 2.0.0) - base64 (~> 0.2.0) - bundler (>= 1.12.0, < 3.0.0) - colored (~> 1.2) - commander (~> 4.6) - csv (~> 3.3) - dotenv (>= 2.1.1, < 3.0.0) - emoji_regex (>= 0.1, < 4.0) - excon (>= 0.71.0, < 1.0.0) - faraday (~> 1.0) - faraday-cookie_jar (~> 0.0.6) - faraday_middleware (~> 1.0) - fastimage (>= 2.1.0, < 3.0.0) - fastlane-sirp (>= 1.0.0) - gh_inspector (>= 1.1.2, < 2.0.0) - google-apis-androidpublisher_v3 (~> 0.3) - google-apis-playcustomapp_v1 (~> 0.1) - google-cloud-env (>= 1.6.0, < 2.0.0) - google-cloud-storage (~> 1.31) - highline (~> 2.0) - http-cookie (~> 1.0.5) - json (< 3.0.0) - jwt (>= 2.1.0, < 3) - mini_magick (>= 4.9.4, < 5.0.0) - multipart-post (>= 2.0.0, < 3.0.0) - mutex_m (~> 0.3.0) - naturally (~> 2.2) - nkf (~> 0.2.0) - optparse (>= 0.1.1, < 1.0.0) - plist (>= 3.1.0, < 4.0.0) - rubyzip (>= 2.0.0, < 3.0.0) - security (= 0.1.5) - simctl (~> 1.6.3) - terminal-notifier (>= 2.0.0, < 3.0.0) - terminal-table (~> 3) - tty-screen (>= 0.6.3, < 1.0.0) - tty-spinner (>= 0.8.0, < 1.0.0) - word_wrap (~> 1.0.0) - xcodeproj (>= 1.13.0, < 2.0.0) - xcpretty (~> 0.4.1) - xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) - fastlane-sirp (1.0.0) - sysrandom (~> 1.0) - gh_inspector (1.1.3) - google-apis-androidpublisher_v3 (0.54.0) - google-apis-core (>= 0.11.0, < 2.a) - google-apis-core (0.11.3) - addressable (~> 2.5, >= 2.5.1) - googleauth (>= 0.16.2, < 2.a) - httpclient (>= 2.8.1, < 3.a) - mini_mime (~> 1.0) - representable (~> 3.0) - retriable (>= 2.0, < 4.a) - rexml - google-apis-iamcredentials_v1 (0.17.0) - google-apis-core (>= 0.11.0, < 2.a) - google-apis-playcustomapp_v1 (0.13.0) - google-apis-core (>= 0.11.0, < 2.a) - google-apis-storage_v1 (0.31.0) - google-apis-core (>= 0.11.0, < 2.a) - google-cloud-core (1.8.0) - google-cloud-env (>= 1.0, < 3.a) - google-cloud-errors (~> 1.0) - google-cloud-env (1.6.0) - faraday (>= 0.17.3, < 3.0) - google-cloud-errors (1.5.0) - google-cloud-storage (1.47.0) - addressable (~> 2.8) - digest-crc (~> 0.4) - google-apis-iamcredentials_v1 (~> 0.1) - google-apis-storage_v1 (~> 0.31.0) - google-cloud-core (~> 1.6) - googleauth (>= 0.16.2, < 2.a) - mini_mime (~> 1.0) - googleauth (1.8.1) - faraday (>= 0.17.3, < 3.a) - jwt (>= 1.4, < 3.0) - multi_json (~> 1.11) - os (>= 0.9, < 2.0) - signet (>= 0.16, < 2.a) - highline (2.0.3) - http-cookie (1.0.8) - domain_name (~> 0.5) - httpclient (2.9.0) - mutex_m - jmespath (1.6.2) - json (2.16.0) - jwt (2.10.2) - base64 - logger (1.7.0) - mini_magick (4.13.2) - mini_mime (1.1.5) - multi_json (1.17.0) - multipart-post (2.4.1) - mutex_m (0.3.0) - nanaimo (0.4.0) - naturally (2.3.0) - nkf (0.2.0) - optparse (0.8.0) - os (1.1.4) - plist (3.7.2) - public_suffix (7.0.0) - rake (13.3.1) - representable (3.2.0) - declarative (< 0.1.0) - trailblazer-option (>= 0.1.1, < 0.2.0) - uber (< 0.2.0) - retriable (3.1.2) - rexml (3.4.4) - rouge (3.28.0) - ruby2_keywords (0.0.5) - rubyzip (2.4.1) - security (0.1.5) - signet (0.21.0) - addressable (~> 2.8) - faraday (>= 0.17.5, < 3.a) - jwt (>= 1.5, < 4.0) - multi_json (~> 1.10) - simctl (1.6.10) - CFPropertyList - naturally - sysrandom (1.0.5) - terminal-notifier (2.0.0) - terminal-table (3.0.2) - unicode-display_width (>= 1.1.1, < 3) - trailblazer-option (0.1.2) - tty-cursor (0.7.1) - tty-screen (0.8.2) - tty-spinner (0.9.3) - tty-cursor (~> 0.7) - uber (0.1.0) - unicode-display_width (2.6.0) - word_wrap (1.0.0) - xcodeproj (1.27.0) - CFPropertyList (>= 2.3.3, < 4.0) - atomos (~> 0.1.3) - claide (>= 1.0.2, < 2.0) - colored2 (~> 3.1) - nanaimo (~> 0.4.0) - rexml (>= 3.3.6, < 4.0) - xcpretty (0.4.1) - rouge (~> 3.28.0) - xcpretty-travis-formatter (1.0.1) - xcpretty (~> 0.2, >= 0.0.7) - -PLATFORMS - arm64-darwin-25 - ruby - -DEPENDENCIES - fastlane - -BUNDLED WITH - 2.7.2 diff --git a/fastlane/Matchfile b/fastlane/Matchfile deleted file mode 100644 index 3cbce194..00000000 --- a/fastlane/Matchfile +++ /dev/null @@ -1,12 +0,0 @@ -# https://docs.fastlane.tools/actions/match - -readonly(true) -type("appstore") -app_identifier([ - "com.userscripts.macos", - "com.userscripts.macos.Userscripts-Extension", -]) - -for_platform :mac do - additional_cert_types(["mac_installer_distribution"]) -end \ No newline at end of file diff --git a/index.html b/index.html deleted file mode 100644 index 215948a7..00000000 --- a/index.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - Userscripts dev - - - -
- - - - diff --git a/jsconfig.json b/jsconfig.json deleted file mode 100644 index 8f85baf3..00000000 --- a/jsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -// https://code.visualstudio.com/docs/languages/jsconfig -// https://www.typescriptlang.org/docs/handbook/tsconfig-json.html -// https://www.typescriptlang.org/tsconfig - -// https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html -// https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html - -{ - "compilerOptions": { - "target": "ESNext", - "module": "ESNext", - "moduleResolution": "bundler", - - "verbatimModuleSyntax": true, - "isolatedModules": true, - "resolveJsonModule": true, - - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "skipLibCheck": true, - "sourceMap": true - }, - "include": ["*.d.ts", "*.js"] -} diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index d4f33dbf..00000000 --- a/package-lock.json +++ /dev/null @@ -1,4194 +0,0 @@ -{ - "name": "userscripts", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "userscripts", - "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^5.0.3", - "@types/webextension-polyfill": "^0.12.3", - "autoprefixer": "^10.4.21", - "cm-show-invisibles": "^3.1.0", - "codemirror": "^5.65.19", - "eslint": "^9.27.0", - "eslint-config-prettier": "^10.1.5", - "eslint-plugin-svelte": "^3.9.0", - "globals": "^16.1.0", - "marked": "^15.0.12", - "prettier": "3.5.3", - "prettier-plugin-svelte": "3.4.0", - "stylelint": "^16.19.1", - "stylelint-config-html": "^1.1.0", - "stylelint-config-standard": "^38.0.0", - "svelte": "^5.33.0", - "vite": "^6.3.5" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/code-frame/node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", - "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.3" - } - }, - "node_modules/@csstools/css-tokenizer": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", - "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@csstools/media-query-list-parser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.2.tgz", - "integrity": "sha512-EUos465uvVvMJehckATTlNqGj4UJWkTmdWuDMjqvSUkjGpmOyFZBVwb4knxCm/k2GMTXY+c/5RkdndzFYWeX5A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" - } - }, - "node_modules/@csstools/selector-specificity": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", - "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "postcss-selector-parser": "^7.0.0" - } - }, - "node_modules/@dual-bundle/import-meta-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", - "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", - "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", - "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", - "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", - "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", - "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", - "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", - "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", - "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", - "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", - "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", - "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", - "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", - "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", - "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", - "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", - "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", - "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", - "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", - "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", - "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", - "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", - "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", - "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", - "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", - "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", - "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", - "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/core": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", - "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "9.27.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz", - "integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", - "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.14.0", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", - "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.3.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@keyv/serialize": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.3.tgz", - "integrity": "sha512-qnEovoOp5Np2JDGonIDL6Ayihw0RhnRh6vxPuHo4RDn1UOzwEo4AeIfpL6UGIrsceWrCMiVPgwRjbHu4vYFc3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.0.tgz", - "integrity": "sha512-KxN+zCjOYHGwCl4UCtSfZ6jrq/qi88JDUtiEFk8LELEHq2Egfc/FgW+jItZiOLRuQfb/3xJSgFuNPC9jzggX+A==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.0.tgz", - "integrity": "sha512-yDvqx3lWlcugozax3DItKJI5j05B0d4Kvnjx+5mwiUpWramVvmAByYigMplaoAQ3pvdprGCTCE03eduqE/8mPQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.0.tgz", - "integrity": "sha512-2KOU574vD3gzcPSjxO0eyR5iWlnxxtmW1F5CkNOHmMlueKNCQkxR6+ekgWyVnz6zaZihpUNkGxjsYrkTJKhkaw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.0.tgz", - "integrity": "sha512-gE5ACNSxHcEZyP2BA9TuTakfZvULEW4YAOtxl/A/YDbIir/wPKukde0BNPlnBiP88ecaN4BJI2TtAd+HKuZPQQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.0.tgz", - "integrity": "sha512-GSxU6r5HnWij7FoSo7cZg3l5GPg4HFLkzsFFh0N/b16q5buW1NAWuCJ+HMtIdUEi6XF0qH+hN0TEd78laRp7Dg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.0.tgz", - "integrity": "sha512-KGiGKGDg8qLRyOWmk6IeiHJzsN/OYxO6nSbT0Vj4MwjS2XQy/5emsmtoqLAabqrohbgLWJ5GV3s/ljdrIr8Qjg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.0.tgz", - "integrity": "sha512-46OzWeqEVQyX3N2/QdiU/CMXYDH/lSHpgfBkuhl3igpZiaB3ZIfSjKuOnybFVBQzjsLwkus2mjaESy8H41SzvA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.0.tgz", - "integrity": "sha512-lfgW3KtQP4YauqdPpcUZHPcqQXmTmH4nYU0cplNeW583CMkAGjtImw4PKli09NFi2iQgChk4e9erkwlfYem6Lg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.0.tgz", - "integrity": "sha512-nn8mEyzMbdEJzT7cwxgObuwviMx6kPRxzYiOl6o/o+ChQq23gfdlZcUNnt89lPhhz3BYsZ72rp0rxNqBSfqlqw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.0.tgz", - "integrity": "sha512-l+QK99je2zUKGd31Gh+45c4pGDAqZSuWQiuRFCdHYC2CSiO47qUWsCcenrI6p22hvHZrDje9QjwSMAFL3iwXwQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.0.tgz", - "integrity": "sha512-WbnJaxPv1gPIm6S8O/Wg+wfE/OzGSXlBMbOe4ie+zMyykMOeqmgD1BhPxZQuDqwUN+0T/xOFtL2RUWBspnZj3w==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.0.tgz", - "integrity": "sha512-eRDWR5t67/b2g8Q/S8XPi0YdbKcCs4WQ8vklNnUYLaSWF+Cbv2axZsp4jni6/j7eKvMLYCYdcsv8dcU+a6QNFg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.0.tgz", - "integrity": "sha512-TWrZb6GF5jsEKG7T1IHwlLMDRy2f3DPqYldmIhnA2DVqvvhY2Ai184vZGgahRrg8k9UBWoSlHv+suRfTN7Ua4A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.0.tgz", - "integrity": "sha512-ieQljaZKuJpmWvd8gW87ZmSFwid6AxMDk5bhONJ57U8zT77zpZ/TPKkU9HpnnFrM4zsgr4kiGuzbIbZTGi7u9A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.0.tgz", - "integrity": "sha512-/L3pW48SxrWAlVsKCN0dGLB2bi8Nv8pr5S5ocSM+S0XCn5RCVCXqi8GVtHFsOBBCSeR+u9brV2zno5+mg3S4Aw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.0.tgz", - "integrity": "sha512-XMLeKjyH8NsEDCRptf6LO8lJk23o9wvB+dJwcXMaH6ZQbbkHu2dbGIUindbMtRN6ux1xKi16iXWu6q9mu7gDhQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.0.tgz", - "integrity": "sha512-m/P7LycHZTvSQeXhFmgmdqEiTqSV80zn6xHaQ1JSqwCtD1YGtwEK515Qmy9DcB2HK4dOUVypQxvhVSy06cJPEg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.0.tgz", - "integrity": "sha512-4yodtcOrFHpbomJGVEqZ8fzD4kfBeCbpsUy5Pqk4RluXOdsWdjLnjhiKy2w3qzcASWd04fp52Xz7JKarVJ5BTg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.0.tgz", - "integrity": "sha512-tmazCrAsKzdkXssEc65zIE1oC6xPHwfy9d5Ta25SRCDOZS+I6RypVVShWALNuU9bxIfGA0aqrmzlzoM5wO5SPQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.0.tgz", - "integrity": "sha512-h1J+Yzjo/X+0EAvR2kIXJDuTuyT7drc+t2ALY0nIcGPbTatNOf0VWdhEA2Z4AAjv6X1NJV7SYo5oCTYRJhSlVA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@sveltejs/acorn-typescript": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz", - "integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^8.9.0" - } - }, - "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-5.0.3.tgz", - "integrity": "sha512-MCFS6CrQDu1yGwspm4qtli0e63vaPCehf6V7pIMP15AsWgMKrqDGCPFF/0kn4SP0ii4aySu4Pa62+fIRGFMjgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1", - "debug": "^4.4.0", - "deepmerge": "^4.3.1", - "kleur": "^4.1.5", - "magic-string": "^0.30.15", - "vitefu": "^1.0.4" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22" - }, - "peerDependencies": { - "svelte": "^5.0.0", - "vite": "^6.0.0" - } - }, - "node_modules/@sveltejs/vite-plugin-svelte-inspector": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-4.0.1.tgz", - "integrity": "sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.7" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22" - }, - "peerDependencies": { - "@sveltejs/vite-plugin-svelte": "^5.0.0", - "svelte": "^5.0.0", - "vite": "^6.0.0" - } - }, - "node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/webextension-polyfill": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/@types/webextension-polyfill/-/webextension-polyfill-0.12.3.tgz", - "integrity": "sha512-F58aDVSeN/MjUGazXo/cPsmR76EvqQhQ1v4x23hFjUX0cfAJYE+JBWwiOGW36/VJGGxoH74sVlRIF3z7SJCKyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/autoprefixer": { - "version": "10.4.21", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", - "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "browserslist": "^4.24.4", - "caniuse-lite": "^1.0.30001702", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.1.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/axobject-query": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", - "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.24.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", - "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001716", - "electron-to-chromium": "^1.5.149", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/cacheable": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.9.0.tgz", - "integrity": "sha512-8D5htMCxPDUULux9gFzv30f04Xo3wCnik0oOxKoRTPIBoqA7HtOcJ87uBhQTs3jCfZZTrUBGsYIZOgE0ZRgMAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "hookified": "^1.8.2", - "keyv": "^5.3.3" - } - }, - "node_modules/cacheable/node_modules/keyv": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.3.tgz", - "integrity": "sha512-Rwu4+nXI9fqcxiEHtbkvoes2X+QfkTRo1TMkPfwzipGsJlJO/z69vqB4FNl9xJ3xCpAcbkvmEabZfPzrwN3+gQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@keyv/serialize": "^1.0.3" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001718", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz", - "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cm-show-invisibles": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cm-show-invisibles/-/cm-show-invisibles-3.1.0.tgz", - "integrity": "sha512-dfWd4QmuSMoSgONkCv4+REfPrxp3R3OE8jnxR3u2IjkLPolHArGOhMetBLo6gTeiL8tA4ff5v+VBZ1u1AZx+4A==", - "dev": true, - "license": "MIT" - }, - "node_modules/codemirror": { - "version": "5.65.19", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.19.tgz", - "integrity": "sha512-+aFkvqhaAVr1gferNMuN8vkTSrWIFvzlMV9I2KBLCWS2WpZ2+UAkZjlMZmEuT+gcXTi6RrGQCkWq1/bDtGqhIA==", - "dev": true, - "license": "MIT" - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-functions-list": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.3.tgz", - "integrity": "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12 || >=16" - } - }, - "node_modules/css-tree": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", - "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "mdn-data": "2.12.2", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause", - "peer": true - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.155", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz", - "integrity": "sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng==", - "dev": true, - "license": "ISC" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/esbuild": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", - "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.4", - "@esbuild/android-arm": "0.25.4", - "@esbuild/android-arm64": "0.25.4", - "@esbuild/android-x64": "0.25.4", - "@esbuild/darwin-arm64": "0.25.4", - "@esbuild/darwin-x64": "0.25.4", - "@esbuild/freebsd-arm64": "0.25.4", - "@esbuild/freebsd-x64": "0.25.4", - "@esbuild/linux-arm": "0.25.4", - "@esbuild/linux-arm64": "0.25.4", - "@esbuild/linux-ia32": "0.25.4", - "@esbuild/linux-loong64": "0.25.4", - "@esbuild/linux-mips64el": "0.25.4", - "@esbuild/linux-ppc64": "0.25.4", - "@esbuild/linux-riscv64": "0.25.4", - "@esbuild/linux-s390x": "0.25.4", - "@esbuild/linux-x64": "0.25.4", - "@esbuild/netbsd-arm64": "0.25.4", - "@esbuild/netbsd-x64": "0.25.4", - "@esbuild/openbsd-arm64": "0.25.4", - "@esbuild/openbsd-x64": "0.25.4", - "@esbuild/sunos-x64": "0.25.4", - "@esbuild/win32-arm64": "0.25.4", - "@esbuild/win32-ia32": "0.25.4", - "@esbuild/win32-x64": "0.25.4" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "9.27.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz", - "integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.20.0", - "@eslint/config-helpers": "^0.2.1", - "@eslint/core": "^0.14.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.27.0", - "@eslint/plugin-kit": "^0.3.1", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-config-prettier": { - "version": "10.1.5", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz", - "integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==", - "dev": true, - "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "funding": { - "url": "https://opencollective.com/eslint-config-prettier" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-svelte": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-3.9.0.tgz", - "integrity": "sha512-nvIUNyyPGbr5922Kd1p/jXe+FfNdVPXsxLyrrXpwfSbZZEFdAYva9O/gm2lObC/wXkQo/AUmQkAihfmNJYeCjA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.6.1", - "@jridgewell/sourcemap-codec": "^1.5.0", - "esutils": "^2.0.3", - "globals": "^16.0.0", - "known-css-properties": "^0.36.0", - "postcss": "^8.4.49", - "postcss-load-config": "^3.1.4", - "postcss-safe-parser": "^7.0.0", - "semver": "^7.6.3", - "svelte-eslint-parser": "^1.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://github.com/sponsors/ota-meshi" - }, - "peerDependencies": { - "eslint": "^8.57.1 || ^9.0.0", - "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "svelte": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", - "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esm-env": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", - "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.14.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrap": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.6.tgz", - "integrity": "sha512-F/D2mADJ9SHY3IwksD4DAXjTt7qt7GWUf3/8RhCNWmC/67tyb55dpimHmy7EplakFaflV0R/PC+fdSPqrRHAQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, - "license": "ISC" - }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/globals": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz", - "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globjoin": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", - "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", - "dev": true, - "license": "MIT" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/hookified": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.9.0.tgz", - "integrity": "sha512-2yEEGqphImtKIe1NXWEhu6yD3hlFR4Mxk4Mtp3XEyScpSt4pQ4ymmXA1zzxZpj99QkFK+nN0nzjeb2+RUi/6CQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/html-tags": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", - "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "license": "ISC" - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-reference": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", - "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.6" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/js-tokens": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", - "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/known-css-properties": { - "version": "0.36.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.36.0.tgz", - "integrity": "sha512-A+9jP+IUmuQsNdsLdcg6Yt7voiMF/D4K83ew0OpJtpu+l34ef7LaohWV0Rc6KNvzw6ZDizkqfyB5JznZnzuKQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/locate-character": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", - "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", - "dev": true, - "license": "MIT" - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true, - "license": "MIT" - }, - "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/marked": { - "version": "15.0.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz", - "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==", - "dev": true, - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/mathml-tag-names": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", - "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdn-data": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", - "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/meow": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", - "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, - "license": "MIT" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.8", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-html": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-1.8.0.tgz", - "integrity": "sha512-5mMeb1TgLWoRKxZ0Xh9RZDfwUUIqRrcxO2uXO+Ezl1N5lqpCiSU5Gk6+1kZediBfBHFtPCdopr2UZ2SgUsKcgQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "htmlparser2": "^8.0.0", - "js-tokens": "^9.0.0", - "postcss": "^8.5.0", - "postcss-safe-parser": "^6.0.0" - }, - "engines": { - "node": "^12 || >=14" - } - }, - "node_modules/postcss-html/node_modules/postcss-safe-parser": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", - "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.3.3" - } - }, - "node_modules/postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "dev": true, - "license": "MIT", - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-load-config/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, - "node_modules/postcss-resolve-nested-selector": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", - "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", - "dev": true, - "license": "MIT" - }, - "node_modules/postcss-safe-parser": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", - "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-scss": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", - "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss-scss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.4.29" - } - }, - "node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-plugin-svelte": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.4.0.tgz", - "integrity": "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "prettier": "^3.0.0", - "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.0.tgz", - "integrity": "sha512-HqMFpUbWlf/tvcxBFNKnJyzc7Lk+XO3FGc3pbNBLqEbOz0gPLRgcrlS3UF4MfUrVlstOaP/q0kM6GVvi+LrLRg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.7" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.41.0", - "@rollup/rollup-android-arm64": "4.41.0", - "@rollup/rollup-darwin-arm64": "4.41.0", - "@rollup/rollup-darwin-x64": "4.41.0", - "@rollup/rollup-freebsd-arm64": "4.41.0", - "@rollup/rollup-freebsd-x64": "4.41.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.41.0", - "@rollup/rollup-linux-arm-musleabihf": "4.41.0", - "@rollup/rollup-linux-arm64-gnu": "4.41.0", - "@rollup/rollup-linux-arm64-musl": "4.41.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.41.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.41.0", - "@rollup/rollup-linux-riscv64-gnu": "4.41.0", - "@rollup/rollup-linux-riscv64-musl": "4.41.0", - "@rollup/rollup-linux-s390x-gnu": "4.41.0", - "@rollup/rollup-linux-x64-gnu": "4.41.0", - "@rollup/rollup-linux-x64-musl": "4.41.0", - "@rollup/rollup-win32-arm64-msvc": "4.41.0", - "@rollup/rollup-win32-ia32-msvc": "4.41.0", - "@rollup/rollup-win32-x64-msvc": "4.41.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stylelint": { - "version": "16.19.1", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.19.1.tgz", - "integrity": "sha512-C1SlPZNMKl+d/C867ZdCRthrS+6KuZ3AoGW113RZCOL0M8xOGpgx7G70wq7lFvqvm4dcfdGFVLB/mNaLFChRKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" - }, - { - "type": "github", - "url": "https://github.com/sponsors/stylelint" - } - ], - "license": "MIT", - "dependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/media-query-list-parser": "^4.0.2", - "@csstools/selector-specificity": "^5.0.0", - "@dual-bundle/import-meta-resolve": "^4.1.0", - "balanced-match": "^2.0.0", - "colord": "^2.9.3", - "cosmiconfig": "^9.0.0", - "css-functions-list": "^3.2.3", - "css-tree": "^3.1.0", - "debug": "^4.3.7", - "fast-glob": "^3.3.3", - "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^10.0.8", - "global-modules": "^2.0.0", - "globby": "^11.1.0", - "globjoin": "^0.1.4", - "html-tags": "^3.3.1", - "ignore": "^7.0.3", - "imurmurhash": "^0.1.4", - "is-plain-object": "^5.0.0", - "known-css-properties": "^0.36.0", - "mathml-tag-names": "^2.1.3", - "meow": "^13.2.0", - "micromatch": "^4.0.8", - "normalize-path": "^3.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.5.3", - "postcss-resolve-nested-selector": "^0.1.6", - "postcss-safe-parser": "^7.0.1", - "postcss-selector-parser": "^7.1.0", - "postcss-value-parser": "^4.2.0", - "resolve-from": "^5.0.0", - "string-width": "^4.2.3", - "supports-hyperlinks": "^3.2.0", - "svg-tags": "^1.0.0", - "table": "^6.9.0", - "write-file-atomic": "^5.0.1" - }, - "bin": { - "stylelint": "bin/stylelint.mjs" - }, - "engines": { - "node": ">=18.12.0" - } - }, - "node_modules/stylelint-config-html": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stylelint-config-html/-/stylelint-config-html-1.1.0.tgz", - "integrity": "sha512-IZv4IVESjKLumUGi+HWeb7skgO6/g4VMuAYrJdlqQFndgbj6WJAXPhaysvBiXefX79upBdQVumgYcdd17gCpjQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12 || >=14" - }, - "funding": { - "url": "https://github.com/sponsors/ota-meshi" - }, - "peerDependencies": { - "postcss-html": "^1.0.0", - "stylelint": ">=14.0.0" - } - }, - "node_modules/stylelint-config-recommended": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-16.0.0.tgz", - "integrity": "sha512-4RSmPjQegF34wNcK1e1O3Uz91HN8P1aFdFzio90wNK9mjgAI19u5vsU868cVZboKzCaa5XbpvtTzAAGQAxpcXA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" - }, - { - "type": "github", - "url": "https://github.com/sponsors/stylelint" - } - ], - "license": "MIT", - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "stylelint": "^16.16.0" - } - }, - "node_modules/stylelint-config-standard": { - "version": "38.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-38.0.0.tgz", - "integrity": "sha512-uj3JIX+dpFseqd/DJx8Gy3PcRAJhlEZ2IrlFOc4LUxBX/PNMEQ198x7LCOE2Q5oT9Vw8nyc4CIL78xSqPr6iag==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" - }, - { - "type": "github", - "url": "https://github.com/sponsors/stylelint" - } - ], - "license": "MIT", - "dependencies": { - "stylelint-config-recommended": "^16.0.0" - }, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "stylelint": "^16.18.0" - } - }, - "node_modules/stylelint/node_modules/balanced-match": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", - "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", - "dev": true, - "license": "MIT" - }, - "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.1.0.tgz", - "integrity": "sha512-Et/ex6smi3wOOB+n5mek+Grf7P2AxZR5ueqRUvAAn4qkyatXi3cUC1cuQXVkX0VlzBVsN4BkWJFmY/fYiRTdww==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^6.1.9" - } - }, - "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.9.tgz", - "integrity": "sha512-DUqiKkTlAfhtl7g78IuwqYM+YqvT+as0mY+EVk6mfimy19U79pJCzDZQsnqk3Ou/T6hFXWLGbwbADzD/c8Tydg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cacheable": "^1.9.0", - "flatted": "^3.3.3", - "hookified": "^1.8.2" - } - }, - "node_modules/stylelint/node_modules/ignore": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", - "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/stylelint/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", - "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=14.18" - }, - "funding": { - "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" - } - }, - "node_modules/svelte": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.33.0.tgz", - "integrity": "sha512-COPJa+cxefgDShgTr3vcLKXdyBfuE96Z65D/EsuxDcU3fwqBxAN6bVjZ0LoVYyAYAShu4K96/k9BxxlAVO6fpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.3.0", - "@jridgewell/sourcemap-codec": "^1.5.0", - "@sveltejs/acorn-typescript": "^1.0.5", - "@types/estree": "^1.0.5", - "acorn": "^8.12.1", - "aria-query": "^5.3.1", - "axobject-query": "^4.1.0", - "clsx": "^2.1.1", - "esm-env": "^1.2.1", - "esrap": "^1.4.6", - "is-reference": "^3.0.3", - "locate-character": "^3.0.0", - "magic-string": "^0.30.11", - "zimmerframe": "^1.1.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/svelte-eslint-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.2.0.tgz", - "integrity": "sha512-mbPtajIeuiyU80BEyGvwAktBeTX7KCr5/0l+uRGLq1dafwRNrjfM5kHGJScEBlPG3ipu6dJqfW/k0/fujvIEVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-scope": "^8.2.0", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.0.0", - "postcss": "^8.4.49", - "postcss-scss": "^4.0.9", - "postcss-selector-parser": "^7.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://github.com/sponsors/ota-meshi" - }, - "peerDependencies": { - "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "svelte": { - "optional": true - } - } - }, - "node_modules/svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", - "dev": true - }, - "node_modules/table": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", - "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyglobby": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", - "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/vite": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", - "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/fdir": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/vitefu": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.6.tgz", - "integrity": "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==", - "dev": true, - "license": "MIT", - "workspaces": [ - "tests/deps/*", - "tests/projects/*" - ], - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/yaml": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", - "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zimmerframe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.2.tgz", - "integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==", - "dev": true, - "license": "MIT" - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index 6f9ef87f..00000000 --- a/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "userscripts", - "private": true, - "type": "module", - "sideEffects": false, - "scripts": { - "dev": "vite", - "dev:mac-safari": "SAFARI_PLATFORM=mac node scripts/dev-safari.js", - "dev:ios-safari": "SAFARI_PLATFORM=ios node scripts/dev-safari.js", - "build:mac-safari-15": "SAFARI_PLATFORM=mac node scripts/build-safari-15.js", - "build:ios-safari-15": "SAFARI_PLATFORM=ios node scripts/build-safari-15.js", - "build:mac-safari-16.4": "SAFARI_PLATFORM=mac node scripts/build-safari-16.4.js", - "build:ios-safari-16.4": "SAFARI_PLATFORM=ios node scripts/build-safari-16.4.js", - "lint:js": "eslint . && prettier --check . --plugin prettier-plugin-svelte", - "lint:css": "stylelint '**/*.{css,html,svelte}'", - "prettier": "prettier --write . --plugin prettier-plugin-svelte" - }, - "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^5.0.3", - "@types/webextension-polyfill": "^0.12.3", - "autoprefixer": "^10.4.21", - "cm-show-invisibles": "^3.1.0", - "codemirror": "^5.65.19", - "eslint": "^9.27.0", - "eslint-config-prettier": "^10.1.5", - "eslint-plugin-svelte": "^3.9.0", - "globals": "^16.1.0", - "marked": "^15.0.12", - "prettier": "3.5.3", - "prettier-plugin-svelte": "3.4.0", - "stylelint": "^16.19.1", - "stylelint-config-html": "^1.1.0", - "stylelint-config-standard": "^38.0.0", - "svelte": "^5.33.0", - "vite": "^6.3.5" - } -} diff --git a/public/ext/safari-15/images/icon-128.png b/public/ext/safari-15/images/icon-128.png deleted file mode 100644 index f0030ddd..00000000 Binary files a/public/ext/safari-15/images/icon-128.png and /dev/null differ diff --git a/public/ext/safari-15/images/icon-256.png b/public/ext/safari-15/images/icon-256.png deleted file mode 100644 index dea9320e..00000000 Binary files a/public/ext/safari-15/images/icon-256.png and /dev/null differ diff --git a/public/ext/safari-15/images/icon-48.png b/public/ext/safari-15/images/icon-48.png deleted file mode 100644 index 3955fd6b..00000000 Binary files a/public/ext/safari-15/images/icon-48.png and /dev/null differ diff --git a/public/ext/safari-15/images/icon-512.png b/public/ext/safari-15/images/icon-512.png deleted file mode 100644 index 3d0c5854..00000000 Binary files a/public/ext/safari-15/images/icon-512.png and /dev/null differ diff --git a/public/ext/safari-15/images/icon-64.png b/public/ext/safari-15/images/icon-64.png deleted file mode 100644 index d1ffa334..00000000 Binary files a/public/ext/safari-15/images/icon-64.png and /dev/null differ diff --git a/public/ext/safari-15/images/icon-96.png b/public/ext/safari-15/images/icon-96.png deleted file mode 100644 index 411a520a..00000000 Binary files a/public/ext/safari-15/images/icon-96.png and /dev/null differ diff --git a/public/ext/safari-15/images/toolbar-icon-16.png b/public/ext/safari-15/images/toolbar-icon-16.png deleted file mode 100644 index cee9abb0..00000000 Binary files a/public/ext/safari-15/images/toolbar-icon-16.png and /dev/null differ diff --git a/public/ext/safari-15/images/toolbar-icon-32.png b/public/ext/safari-15/images/toolbar-icon-32.png deleted file mode 100644 index 1de18ba5..00000000 Binary files a/public/ext/safari-15/images/toolbar-icon-32.png and /dev/null differ diff --git a/public/ext/safari-15/images/toolbar-icon-48.png b/public/ext/safari-15/images/toolbar-icon-48.png deleted file mode 100644 index e1367b2b..00000000 Binary files a/public/ext/safari-15/images/toolbar-icon-48.png and /dev/null differ diff --git a/public/ext/safari-15/manifest.json b/public/ext/safari-15/manifest.json deleted file mode 100644 index 1f64988a..00000000 --- a/public/ext/safari-15/manifest.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "manifest_version": 2, - "default_locale": "en", - "name": "__MSG_extension_name__", - "description": "__MSG_extension_description__", - "version": "_VERSION_", - "icons": { - "48": "images/icon-48.png", - "64": "images/icon-64.png", - "96": "images/icon-96.png", - "128": "images/icon-128.png", - "256": "images/icon-256.png", - "512": "images/icon-512.png" - }, - "background": { - "scripts": ["dist/background.js"], - "persistent": false - }, - "browser_action": { - "default_popup": "dist/entry-ext-action-popup.html", - "default_icon": { - "16": "images/toolbar-icon-16.png", - "32": "images/toolbar-icon-32.png", - "48": "images/toolbar-icon-48.png" - } - }, - "options_ui": { - "page": "dist/entry-ext-extension-page.html#state=settings" - }, - "content_scripts": [ - { - "js": ["dist/content-scripts/userscripts.js"], - "matches": [""], - "run_at": "document_start", - "all_frames": true - }, - { - "js": ["dist/content-scripts/dot-user-js.js"], - "matches": ["*://*/*.user.js", "*://*/*.user.js?*"], - "run_at": "document_start" - }, - { - "js": ["dist/content-scripts/script-market.js"], - "matches": ["*://*.greasyfork.org/*"], - "exclude_matches": ["*://*/*.user.js", "*://*/*.user.js?*"], - "run_at": "document_end" - } - ], - "permissions": [ - "", - "clipboardWrite", - "contextMenus", - "declarativeNetRequest", - "declarativeNetRequestWithHostAccess", - "menus", - "nativeMessaging", - "storage", - "tabs", - "unlimitedStorage", - "webNavigation" - ] -} diff --git a/public/ext/safari-16.4/images/128.svg b/public/ext/safari-16.4/images/128.svg deleted file mode 100644 index c6ec62ad..00000000 --- a/public/ext/safari-16.4/images/128.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/ext/safari-16.4/images/action.svg b/public/ext/safari-16.4/images/action.svg deleted file mode 100644 index ad16f09d..00000000 --- a/public/ext/safari-16.4/images/action.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/ext/safari-16.4/manifest.json b/public/ext/safari-16.4/manifest.json deleted file mode 100644 index ab445895..00000000 --- a/public/ext/safari-16.4/manifest.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "manifest_version": 2, - "default_locale": "en", - "name": "__MSG_extension_name__", - "description": "__MSG_extension_description__", - "version": "_VERSION_", - "icons": { - "48": "images/128.svg", - "96": "images/128.svg", - "128": "images/128.svg", - "256": "images/128.svg", - "512": "images/128.svg" - }, - "background": { - "scripts": ["dist/background.js"], - "persistent": false - }, - "browser_action": { - "default_popup": "dist/entry-ext-action-popup.html", - "default_icon": "images/action.svg" - }, - "options_ui": { - "page": "dist/entry-ext-extension-page.html#state=settings" - }, - "content_scripts": [ - { - "js": ["dist/content-scripts/userscripts.js"], - "matches": [""], - "run_at": "document_start", - "all_frames": true - } - ], - "permissions": [ - "", - "clipboardWrite", - "contextMenus", - "declarativeNetRequestWithHostAccess", - "menus", - "nativeMessaging", - "scripting", - "storage", - "tabs", - "unlimitedStorage", - "webNavigation" - ], - "browser_specific_settings": { - "safari": { - "strict_min_version": "16.4" - } - } -} diff --git a/public/ext/safari-dev/manifest-ios.json b/public/ext/safari-dev/manifest-ios.json deleted file mode 100644 index e1cac050..00000000 --- a/public/ext/safari-dev/manifest-ios.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "manifest_version": 2, - "default_locale": "en", - "name": "__MSG_extension_name__", - "description": "__MSG_extension_description__", - "version": "_VERSION_", - "icons": { - "48": "images/128.svg", - "96": "images/128.svg", - "128": "images/128.svg", - "256": "images/128.svg", - "512": "images/128.svg" - }, - "background": { - "page": "dist/entry-ext-background.html", - "persistent": false - }, - "browser_action": { - "default_popup": "dist/entry-ext-action-popup.html", - "default_icon": "images/action.svg" - }, - "options_ui": { - "page": "dist/entry-ext-extension-page.html#state=settings" - }, - "content_scripts": [ - { - "js": ["dist/content-scripts/userscripts.js"], - "matches": [""], - "run_at": "document_start", - "all_frames": true - } - ], - "permissions": [ - "", - "clipboardWrite", - "contextMenus", - "declarativeNetRequestWithHostAccess", - "menus", - "nativeMessaging", - "scripting", - "storage", - "tabs", - "unlimitedStorage", - "webNavigation" - ], - "browser_specific_settings": { - "safari": { - "strict_min_version": "16.4" - } - }, - "content_security_policy": "script-src 'self' https://localhost:55173 https://userscripts.test:55173" -} diff --git a/public/ext/safari-dev/manifest-mac.json b/public/ext/safari-dev/manifest-mac.json deleted file mode 100644 index e469aa66..00000000 --- a/public/ext/safari-dev/manifest-mac.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "manifest_version": 2, - "default_locale": "en", - "name": "__MSG_extension_name__", - "description": "__MSG_extension_description__", - "version": "_VERSION_", - "icons": { - "48": "images/128.svg", - "96": "images/128.svg", - "128": "images/128.svg", - "256": "images/128.svg", - "512": "images/128.svg" - }, - "background": { - "page": "dist/entry-ext-background.html", - "persistent": true - }, - "browser_action": { - "default_popup": "dist/entry-ext-action-popup.html", - "default_icon": "images/action.svg" - }, - "options_ui": { - "page": "dist/entry-ext-extension-page.html#state=settings" - }, - "content_scripts": [ - { - "js": ["dist/content-scripts/userscripts.js"], - "matches": [""], - "run_at": "document_start", - "all_frames": true - } - ], - "permissions": [ - "", - "clipboardWrite", - "contextMenus", - "declarativeNetRequestWithHostAccess", - "menus", - "nativeMessaging", - "scripting", - "storage", - "tabs", - "unlimitedStorage", - "webNavigation" - ], - "browser_specific_settings": { - "safari": { - "strict_min_version": "16.4" - } - }, - "content_security_policy": "script-src 'self' https://localhost:55173 https://userscripts.test:55173" -} diff --git a/public/ext/shared-dev/images/128.svg b/public/ext/shared-dev/images/128.svg deleted file mode 100644 index 76189438..00000000 --- a/public/ext/shared-dev/images/128.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/ext/shared-dev/images/action.svg b/public/ext/shared-dev/images/action.svg deleted file mode 100644 index 3789dd89..00000000 --- a/public/ext/shared-dev/images/action.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/ext/shared/_locales/en/messages.json b/public/ext/shared/_locales/en/messages.json deleted file mode 100644 index a39bfc24..00000000 --- a/public/ext/shared/_locales/en/messages.json +++ /dev/null @@ -1,250 +0,0 @@ -{ - "extension_name": { - "message": "_NAME_", - "description": "The display name for the extension." - }, - "extension_description": { - "message": "Save and run javascript for the web pages you visit", - "description": "Description of what the extension does." - }, - "settings": { - "message": "Settings" - }, - "settings_section_editor": { - "message": "Editor Settings" - }, - "settings_section_general": { - "message": "General Settings" - }, - "settings_section_native": { - "message": "Native Settings" - }, - "settings_section_tools": { - "message": "Tools" - }, - "settings_section_about": { - "message": "About" - }, - "settings_editor_auto_hint": { - "message": "Auto Hint" - }, - "settings_editor_auto_hint_desc": { - "message": "Automatically shows completion hints while editing" - }, - "settings_editor_close_brackets": { - "message": "Auto Close Brackets" - }, - "settings_editor_close_brackets_desc": { - "message": "Toggles on/off auto closing of brackets in the editor, this affects the following characters: () [] {} \"\" ''" - }, - "settings_editor_javascript_lint": { - "message": "JavaScript Linter" - }, - "settings_editor_javascript_lint_desc": { - "message": "Toggles the basic javascript linting within the editor" - }, - "settings_editor_list_descriptions": { - "message": "Sidebar Item Descriptions" - }, - "settings_editor_list_descriptions_desc": { - "message": "Show or hides the item descriptions in the sidebar" - }, - "settings_editor_list_sort": { - "message": "Sidebar Item Sort Order" - }, - "settings_editor_list_sort_desc": { - "message": "Display order of items in the sidebar" - }, - "settings_editor_list_sort_nameAsc": { - "message": "Scripts Name: Asc" - }, - "settings_editor_list_sort_nameDesc": { - "message": "Scripts Name: Desc" - }, - "settings_editor_list_sort_lastModifiedAsc": { - "message": "Last Modified: Asc" - }, - "settings_editor_list_sort_lastModifiedDesc": { - "message": "Last Modified: Desc" - }, - "settings_editor_show_whitespace": { - "message": "Show Whitespace Characters" - }, - "settings_editor_show_whitespace_desc": { - "message": "Toggles the display of invisible characters in the editor" - }, - "settings_editor_tab_size": { - "message": "Tab Size" - }, - "settings_editor_tab_size_desc": { - "message": "Choose the number of spaces a tab is equal to when rendering code" - }, - "settings_global_active": { - "message": "Enable Injection" - }, - "settings_global_active_desc": { - "message": "Toggle on/off script injection for the pages you visit" - }, - "settings_global_exclude_match": { - "message": "Global Exclude Match patterns" - }, - "settings_global_exclude_match_desc": { - "message": "This input accepts a whitespace (spaces, newlines etc.) separated list of @match patterns, a page url that matches against a pattern in this list will be ignored for script injection" - }, - "settings_global_exclude_match_done": { - "message": "Done" - }, - "settings_global_exclude_match_saving": { - "message": "Saving..." - }, - "settings_global_exclude_match_placeholder": { - "message": "list of @match patterns, for example: \n*://*/*foo.bar\n*://*/*foo.bar?*\n*://*.example.net/*\nhttps://example.net/*/foo/*/\nhttps://*.example.net/a/b/c/?foo=/" - }, - "settings_global_exclude_match_refer": { - "message": "Please refer to:" - }, - "settings_scripts_update_automation": { - "message": "Scripts Updates Automatically" - }, - "settings_scripts_update_automation_desc": { - "message": "Script silently auto-updates in the background, which is dangerous and may introduce unconfirmed malicious code" - }, - "settings_scripts_update_check_interval": { - "message": "Scripts Update Check Interval" - }, - "settings_scripts_update_check_interval_desc": { - "message": "Disable or set user scripts update check interval (days)" - }, - "settings_scripts_update_check_interval_0": { - "message": "Never" - }, - "settings_scripts_update_check_lasttime": { - "message": "Scripts Update Check Lasttime" - }, - "settings_scripts_update_check_lasttime_desc": { - "message": "The lasttime for script update check in background" - }, - "settings_settings_sync": { - "message": "Sync Settings" - }, - "settings_settings_sync_desc": { - "message": "Sync settings across devices" - }, - "settings_augmented_userjs_install": { - "message": "Enhanced installation prompts" - }, - "settings_augmented_userjs_install_desc": { - "message": "Automatically pop up the installation interface when opening a user script URL (.user.js), and takes over the install button of the user scripts market" - }, - "settings_toolbar_badge_count": { - "message": "Show Toolbar Count Badge" - }, - "settings_toolbar_badge_count_desc": { - "message": "Displays a badge on the toolbar icon with a number that represents how many enabled scripts match the url for the page you are on" - }, - "settings_scripts_directory": { - "message": "Save Location" - }, - "settings_scripts_directory_desc": { - "message": "Path to the folder where user scripts are stored" - }, - "settings_set_scripts_directory": { - "message": "Change save location" - }, - "settings_section_tools_import": { - "message": "Import" - }, - "settings_section_tools_export": { - "message": "Export" - }, - "settings_section_tools_reset": { - "message": "Reset" - }, - "settings_section_tools_goback": { - "message": "Go Back" - }, - "settings_section_tools_reset_all": { - "message": "Reset All Settings" - }, - "settings_section_tools_reset_single": { - "message": "Reset" - }, - "settings_section_tools_reset_section": { - "message": "Reset Section" - }, - "settings_scripts_tools_desc": { - "message": "These tools can help you import and export \"settings data\". Reset single, section or all settings." - }, - "settings_about_text1": { - "message": "Get more information about this extension by visiting the open source project:" - }, - "settings_about_text2": { - "message": "If you enjoy using this extension, please consider leaving a review on the App Store or sign up to beta test new versions:" - }, - "settings_about_button_repo": { - "message": "Code repository" - }, - "settings_about_button_docs": { - "message": "Documentation" - }, - "settings_about_button_issues": { - "message": "Report bugs" - }, - "settings_about_button_store": { - "message": "Open in the App Store" - }, - "settings_about_button_beta": { - "message": "Sign up for beta testing" - }, - "utils_check_match_patterns_0": { - "message": "The match pattern will match all URLs" - }, - "utils_check_match_patterns_1": { - "message": "The scheme component should one of *, https, http" - }, - "utils_check_match_patterns_2": { - "message": "The scheme and host should separated by `://`" - }, - "utils_check_match_patterns_3": { - "message": "The match pattern has no path component" - }, - "utils_check_match_patterns_4": { - "message": "The `*.` should followed by part of the hostname" - }, - "utils_check_match_patterns_5": { - "message": "The host component length should be 1-255" - }, - "utils_check_match_patterns_6": { - "message": "The `*` in host component should be independent or `*.` at the start" - }, - "utils_check_match_patterns_7": { - "message": "The host component contains empty label(s)" - }, - "utils_check_match_patterns_8": { - "message": "The hostname label cannot start or end with `-` character" - }, - "utils_check_match_patterns_9": { - "message": "The maximum length of the hostname label cannot exceed 63" - }, - "utils_check_match_patterns_10": { - "message": "The host component contains invalid character(s): $1" - }, - "utils_check_match_patterns_11": { - "message": "The path component contains invalid character(s): $1" - }, - "msg_invalid_match_pattern": { - "message": "Invalid match pattern" - }, - "msg_invalid_backup_file": { - "message": "Not a valid backup file" - }, - "msg_backup_import_finish": { - "message": "Import completed! ✅" - }, - "msg_backup_import_failed": { - "message": "Import failed, please check the error log in the console" - }, - "msg_settings_reset_finish": { - "message": "Reset all settings completed! ✅" - } -} diff --git a/public/ext/shared/_locales/zh/messages.json b/public/ext/shared/_locales/zh/messages.json deleted file mode 100644 index 7338f30a..00000000 --- a/public/ext/shared/_locales/zh/messages.json +++ /dev/null @@ -1,246 +0,0 @@ -{ - "extension_description": { - "message": "用户脚本和样式管理器", - "description": "Description of what the extension does." - }, - "settings": { - "message": "设置" - }, - "settings_section_editor": { - "message": "编辑器设置" - }, - "settings_section_general": { - "message": "通用设置" - }, - "settings_section_native": { - "message": "本地设置" - }, - "settings_section_tools": { - "message": "工具" - }, - "settings_section_about": { - "message": "关于" - }, - "settings_editor_auto_hint": { - "message": "自动提示(Hint)" - }, - "settings_editor_auto_hint_desc": { - "message": "编辑时自动显示完成提示" - }, - "settings_editor_close_brackets": { - "message": "自动关闭括号" - }, - "settings_editor_close_brackets_desc": { - "message": "在编辑器中启用自动关闭括号,这会影响以下字符:() [] {} \"\" ''" - }, - "settings_editor_javascript_lint": { - "message": "JavaScript Linter" - }, - "settings_editor_javascript_lint_desc": { - "message": "在编辑器中启用基本的 JavaScript Linting(代码检查)" - }, - "settings_editor_list_descriptions": { - "message": "侧栏项目描述" - }, - "settings_editor_list_descriptions_desc": { - "message": "显示或隐藏侧边栏中项目的描述" - }, - "settings_editor_list_sort": { - "message": "侧栏项目排序" - }, - "settings_editor_list_sort_desc": { - "message": "侧边栏中项目的显示顺序" - }, - "settings_editor_list_sort_nameAsc": { - "message": "项目名称: 升序" - }, - "settings_editor_list_sort_nameDesc": { - "message": "项目名称: 降序" - }, - "settings_editor_list_sort_lastModifiedAsc": { - "message": "最后修改: 升序" - }, - "settings_editor_list_sort_lastModifiedDesc": { - "message": "最后修改: 降序" - }, - "settings_editor_show_whitespace": { - "message": "显示空白字符" - }, - "settings_editor_show_whitespace_desc": { - "message": "切换编辑器中不可见字符的显示" - }, - "settings_editor_tab_size": { - "message": "制表符大小" - }, - "settings_editor_tab_size_desc": { - "message": "选择渲染代码时制表符等于的空格数" - }, - "settings_global_active": { - "message": "启用注入" - }, - "settings_global_active_desc": { - "message": "全局脚本注入的开启或关闭" - }, - "settings_global_exclude_match": { - "message": "全局排除匹配模式列表" - }, - "settings_global_exclude_match_desc": { - "message": "此输入接受以空白符(空格、换行等)分隔的 @match 模式列表,与此列表中的模式匹配的页面 URL 将在脚本注入时被忽略" - }, - "settings_global_exclude_match_done": { - "message": "完成" - }, - "settings_global_exclude_match_saving": { - "message": "保存中..." - }, - "settings_global_exclude_match_placeholder": { - "message": "@match 模式列表,例如:\n*://*/*foo.bar\n*://*/*foo.bar?*\n*://*.example.net/*\nhttps://example.net/*/foo/*/\nhttps://*.example.net/a/b/c/?foo=/" - }, - "settings_global_exclude_match_refer": { - "message": "匹配模式结构请参考:" - }, - "settings_scripts_update_automation": { - "message": "自动更新脚本" - }, - "settings_scripts_update_automation_desc": { - "message": "脚本在后台静默自动更新,这是危险的,可能引入未经确认的恶意代码" - }, - "settings_scripts_update_check_interval": { - "message": "脚本更新检查间隔" - }, - "settings_scripts_update_check_interval_desc": { - "message": "禁用或设置用户脚本更新检查间隔(天)" - }, - "settings_scripts_update_check_interval_0": { - "message": "从不" - }, - "settings_scripts_update_check_lasttime": { - "message": "脚本更新上次检查时间" - }, - "settings_scripts_update_check_lasttime_desc": { - "message": "后台脚本更新检查上次时间" - }, - "settings_settings_sync": { - "message": "同步设置" - }, - "settings_settings_sync_desc": { - "message": "跨设备同步设置" - }, - "settings_augmented_userjs_install": { - "message": "增强的脚本安装提示" - }, - "settings_augmented_userjs_install_desc": { - "message": "当打开一个用户脚本 URL(.user.js)时自动弹出安装界面,并接管用户脚本市场的安装按钮" - }, - "settings_toolbar_badge_count": { - "message": "工具栏图标显示计数徽章" - }, - "settings_toolbar_badge_count_desc": { - "message": "在工具栏图标上显示一个徽章,其中的数字代表有多少个已启用的脚本与您所在页面的 URL 匹配" - }, - "settings_scripts_directory": { - "message": "保存位置" - }, - "settings_scripts_directory_desc": { - "message": "存储用户脚本的文件夹路径" - }, - "settings_set_scripts_directory": { - "message": "更改保存位置" - }, - "settings_section_tools_import": { - "message": "导入" - }, - "settings_section_tools_export": { - "message": "导出" - }, - "settings_section_tools_reset": { - "message": "还原" - }, - "settings_section_tools_goback": { - "message": "返回" - }, - "settings_section_tools_reset_all": { - "message": "还原所有设置" - }, - "settings_section_tools_reset_single": { - "message": "还原" - }, - "settings_section_tools_reset_section": { - "message": "还原该组" - }, - "settings_scripts_tools_desc": { - "message": "这些工具可以帮助您导入和导出“设置数据”。重置单个、一组或所有设置。" - }, - "settings_about_text1": { - "message": "获取有关此扩展的更多信息,请访问本开源项目:" - }, - "settings_about_text2": { - "message": "如果您喜欢使用此扩展,请考虑在 App Store 上留下您的评论或注册 Beta 测试新版本:" - }, - "settings_about_button_repo": { - "message": "代码库" - }, - "settings_about_button_docs": { - "message": "文档" - }, - "settings_about_button_issues": { - "message": "报告错误" - }, - "settings_about_button_store": { - "message": "在 App Store 中打开" - }, - "settings_about_button_beta": { - "message": "注册 Beta 测试版" - }, - "utils_check_match_patterns_0": { - "message": "此匹配模式将匹配所有 URL" - }, - "utils_check_match_patterns_1": { - "message": "这 scheme 部分应当为 *、https、http 之一" - }, - "utils_check_match_patterns_2": { - "message": "这 scheme 和 host 部分应当用 `://` 分隔" - }, - "utils_check_match_patterns_3": { - "message": "匹配模式缺少 path 部分(至少应当有`/`)" - }, - "utils_check_match_patterns_4": { - "message": "这 `*.` 后面应当跟随主机名的一部分" - }, - "utils_check_match_patterns_5": { - "message": "这 host 部分长度应当为 1-255" - }, - "utils_check_match_patterns_6": { - "message": "这 host 部分中的 `*` 应该是独立的或为 `*.` 在开头" - }, - "utils_check_match_patterns_7": { - "message": "这 host 部分包含一个或多个空标签" - }, - "utils_check_match_patterns_8": { - "message": "主机名标签不能以 `-` 字符开头或结尾" - }, - "utils_check_match_patterns_9": { - "message": "主机名标签最大长度不能超过 63" - }, - "utils_check_match_patterns_10": { - "message": "这 host 部分包含无效字符:$1" - }, - "utils_check_match_patterns_11": { - "message": "这 path 部分包含无效字符:$1" - }, - "msg_invalid_match_pattern": { - "message": "无效的匹配模式" - }, - "msg_invalid_backup_file": { - "message": "无效的备份文件" - }, - "msg_backup_import_finish": { - "message": "导入完成!✅" - }, - "msg_backup_import_failed": { - "message": "导入失败,请在控制台中检查错误日志" - }, - "msg_settings_reset_finish": { - "message": "还原所有设置完成!✅" - } -} diff --git a/public/ext/shared/_locales/zh_HK b/public/ext/shared/_locales/zh_HK deleted file mode 120000 index dec9132e..00000000 --- a/public/ext/shared/_locales/zh_HK +++ /dev/null @@ -1 +0,0 @@ -zh_TW \ No newline at end of file diff --git a/public/ext/shared/_locales/zh_MO b/public/ext/shared/_locales/zh_MO deleted file mode 120000 index dec9132e..00000000 --- a/public/ext/shared/_locales/zh_MO +++ /dev/null @@ -1 +0,0 @@ -zh_TW \ No newline at end of file diff --git a/public/ext/shared/_locales/zh_TW/messages.json b/public/ext/shared/_locales/zh_TW/messages.json deleted file mode 100644 index 07853cb3..00000000 --- a/public/ext/shared/_locales/zh_TW/messages.json +++ /dev/null @@ -1,246 +0,0 @@ -{ - "extension_description": { - "message": "使用者腳本和樣式管理器", - "description": "Description of what the extension does." - }, - "settings": { - "message": "設定" - }, - "settings_section_editor": { - "message": "編輯器設定" - }, - "settings_section_general": { - "message": "一般設定" - }, - "settings_section_native": { - "message": "本地設定" - }, - "settings_section_tools": { - "message": "工具" - }, - "settings_section_about": { - "message": "關於" - }, - "settings_editor_auto_hint": { - "message": "自動提示(Hint)" - }, - "settings_editor_auto_hint_desc": { - "message": "編輯時自動顯示完成提示" - }, - "settings_editor_close_brackets": { - "message": "自動關閉括號" - }, - "settings_editor_close_brackets_desc": { - "message": "在編輯器中啟用自動關閉括號,這會影響以下字元:() [] {} \"\" ''" - }, - "settings_editor_javascript_lint": { - "message": "JavaScript Linter" - }, - "settings_editor_javascript_lint_desc": { - "message": "在編輯器中啟用基本的 JavaScript Linting(程式碼檢查)" - }, - "settings_editor_list_descriptions": { - "message": "側欄項目描述" - }, - "settings_editor_list_descriptions_desc": { - "message": "顯示或隱藏側邊欄中項目的描述" - }, - "settings_editor_list_sort": { - "message": "側欄項目排序" - }, - "settings_editor_list_sort_desc": { - "message": "側邊欄中項目的顯示順序" - }, - "settings_editor_list_sort_nameAsc": { - "message": "項目名稱: 升序" - }, - "settings_editor_list_sort_nameDesc": { - "message": "項目名稱: 降序" - }, - "settings_editor_list_sort_lastModifiedAsc": { - "message": "最後修改: 升序" - }, - "settings_editor_list_sort_lastModifiedDesc": { - "message": "最後修改: 降序" - }, - "settings_editor_show_whitespace": { - "message": "顯示空白字元" - }, - "settings_editor_show_whitespace_desc": { - "message": "切換編輯器中不可見字元的顯示" - }, - "settings_editor_tab_size": { - "message": "製表符大小" - }, - "settings_editor_tab_size_desc": { - "message": "選擇渲染程式碼時製表符等於的空格數" - }, - "settings_global_active": { - "message": "啟用注入" - }, - "settings_global_active_desc": { - "message": "全域性腳本注入的開啟或關閉" - }, - "settings_global_exclude_match": { - "message": "全域性排除匹配模式列表" - }, - "settings_global_exclude_match_desc": { - "message": "此輸入接受以空白符(空格、換行等)分隔的 @match 模式列表,與此列表中的模式匹配的頁面 URL 將在腳本注入時被忽略" - }, - "settings_global_exclude_match_done": { - "message": "完成" - }, - "settings_global_exclude_match_saving": { - "message": "儲存中..." - }, - "settings_global_exclude_match_placeholder": { - "message": "@match 模式列表,例如:\n*://*/*foo.bar\n*://*/*foo.bar?*\n*://*.example.net/*\nhttps://example.net/*/foo/*/\nhttps://*.example.net/a/b/c/?foo=/" - }, - "settings_global_exclude_match_refer": { - "message": "匹配模式結構請參考:" - }, - "settings_scripts_update_automation": { - "message": "自動更新腳本" - }, - "settings_scripts_update_automation_desc": { - "message": "腳本在後臺靜默自動更新,這是危險的,可能引入未經確認的惡意程式碼" - }, - "settings_scripts_update_check_interval": { - "message": "腳本更新檢查間隔" - }, - "settings_scripts_update_check_interval_desc": { - "message": "禁用或設定使用者腳本更新檢查間隔(天)" - }, - "settings_scripts_update_check_interval_0": { - "message": "從不" - }, - "settings_scripts_update_check_lasttime": { - "message": "腳本更新上次檢查時間" - }, - "settings_scripts_update_check_lasttime_desc": { - "message": "後臺腳本更新檢查上次時間" - }, - "settings_settings_sync": { - "message": "同步設定" - }, - "settings_settings_sync_desc": { - "message": "跨裝置同步設定" - }, - "settings_augmented_userjs_install": { - "message": "增強的腳本安裝提示" - }, - "settings_augmented_userjs_install_desc": { - "message": "當開啟一個使用者腳本 URL(.user.js)時自動彈出安裝介面,並接管使用者腳本市場的安裝按鈕" - }, - "settings_toolbar_badge_count": { - "message": "工具欄圖示顯示計數徽章" - }, - "settings_toolbar_badge_count_desc": { - "message": "在工具欄圖示上顯示一個徽章,其中的數字代表有多少個已啟用的腳本與您所在頁面的 URL 匹配" - }, - "settings_scripts_directory": { - "message": "儲存位置" - }, - "settings_scripts_directory_desc": { - "message": "儲存使用者腳本的資料夾路徑" - }, - "settings_set_scripts_directory": { - "message": "更改儲存位置" - }, - "settings_section_tools_import": { - "message": "匯入" - }, - "settings_section_tools_export": { - "message": "匯出" - }, - "settings_section_tools_reset": { - "message": "還原" - }, - "settings_section_tools_goback": { - "message": "返回" - }, - "settings_section_tools_reset_all": { - "message": "還原所有設定" - }, - "settings_section_tools_reset_single": { - "message": "還原" - }, - "settings_section_tools_reset_section": { - "message": "還原該組" - }, - "settings_scripts_tools_desc": { - "message": "這些工具可以幫助您匯入和匯出“設定資料”。重置單個、一組或所有設定。" - }, - "settings_about_text1": { - "message": "獲取有關此延伸功能的更多資訊,請訪問本開源項目:" - }, - "settings_about_text2": { - "message": "如果您喜歡使用此延伸功能,請考慮在 App Store 上留下您的評論或註冊 Beta 測試新版本:" - }, - "settings_about_button_repo": { - "message": "代碼庫" - }, - "settings_about_button_docs": { - "message": "文件" - }, - "settings_about_button_issues": { - "message": "報告錯誤" - }, - "settings_about_button_store": { - "message": "在 App Store 中開啟" - }, - "settings_about_button_beta": { - "message": "註冊 Beta 測試版" - }, - "utils_check_match_patterns_0": { - "message": "此匹配模式將匹配所有 URL" - }, - "utils_check_match_patterns_1": { - "message": "這 scheme 部分應當為 *、https、http 之一" - }, - "utils_check_match_patterns_2": { - "message": "這 scheme 和 host 部分應當用 `://` 分隔" - }, - "utils_check_match_patterns_3": { - "message": "匹配模式缺少 path 部分(至少應當有`/`)" - }, - "utils_check_match_patterns_4": { - "message": "這 `*.` 後面應當跟隨主機名的一部分" - }, - "utils_check_match_patterns_5": { - "message": "這 host 部分長度應當為 1-255" - }, - "utils_check_match_patterns_6": { - "message": "這 host 部分中的 `*` 應該是獨立的或為 `*.` 在開頭" - }, - "utils_check_match_patterns_7": { - "message": "這 host 部分包含一個或多個空標籤" - }, - "utils_check_match_patterns_8": { - "message": "主機名標籤不能以 `-` 字元開頭或結尾" - }, - "utils_check_match_patterns_9": { - "message": "主機名標籤最大長度不能超過 63" - }, - "utils_check_match_patterns_10": { - "message": "這 host 部分包含無效字元:$1" - }, - "utils_check_match_patterns_11": { - "message": "這 path 部分包含無效字元:$1" - }, - "msg_invalid_match_pattern": { - "message": "無效的匹配模式" - }, - "msg_invalid_backup_file": { - "message": "無效的備份檔案" - }, - "msg_backup_import_finish": { - "message": "匯入完成!✅" - }, - "msg_backup_import_failed": { - "message": "匯入失敗,請在控制檯中檢查錯誤日誌" - }, - "msg_settings_reset_finish": { - "message": "還原所有設定完成!✅" - } -} diff --git a/public/ext/vendor/jshint.min.js b/public/ext/vendor/jshint.min.js deleted file mode 100644 index 4819821b..00000000 --- a/public/ext/vendor/jshint.min.js +++ /dev/null @@ -1,28 +0,0 @@ -/*! 2.13.6 */ var JSHINT;"undefined"==typeof window&&(window={}),function(){var _;JSHINT=(_=function $(e,t,n){function r(u,o){if(!t[u]){if(!e[u]){var a="function"==typeof _&&_;if(!o&&a)return a(u,!0);if(i)return i(u,!0);var s=Error("Cannot find module '"+u+"'");throw s.code="MODULE_NOT_FOUND",s}var c=t[u]={exports:{}};e[u][0].call(c.exports,function(_){var $;return r(e[u][1][_]||_)},c,c.exports,$,e,t,n)}return t[u].exports}for(var i="function"==typeof _&&_,u=0;u=65&&n<=90||95===n||n>=97&&n<=122;for(var r=[],n=0;n<128;n++)r[n]=t[n]||n>=48&&n<=57;$.exports={asciiIdentifierStartTable:t,asciiIdentifierPartTable:r}},{}],2:[function(_,$,e){$.exports=/^(?:[\$A-Z_a-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0525\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0621-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971\u0972\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D3D\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC\u0EDD\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8B\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10D0-\u10FA\u10FC\u1100-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u2094\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2D00-\u2D25\u2D30-\u2D65\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31B7\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCB\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA65F\uA662-\uA66E\uA67F-\uA697\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B\uA78C\uA7FB-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA2D\uFA30-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC])(?:[\$0-9A-Z_a-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u0525\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0621-\u065E\u0660-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0900-\u0939\u093C-\u094E\u0950-\u0955\u0958-\u0963\u0966-\u096F\u0971\u0972\u0979-\u097F\u0981-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C01-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C82\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0D02\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC\u0EDD\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F8B\u0F90-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10D0-\u10FA\u10FC\u1100-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17B3\u17B6-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191C\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BAA\u1BAE-\u1BB9\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF2\u1D00-\u1DE6\u1DFD-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u2094\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF1\u2D00-\u2D25\u2D30-\u2D65\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31B7\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCB\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA65F\uA662-\uA66F\uA67C\uA67D\uA67F-\uA697\uA6A0-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B\uA78C\uA7FB-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7B\uAA80-\uAAC2\uAADB-\uAADD\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA2D\uFA30-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE26\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC])*$/},{}],3:[function(_,$,e){var t="183,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,903,1155,1156,1157,1158,1159,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1471,1473,1474,1476,1477,1479,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1648,1750,1751,1752,1753,1754,1755,1756,1759,1760,1761,1762,1763,1764,1767,1768,1770,1771,1772,1773,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1809,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,2027,2028,2029,2030,2031,2032,2033,2034,2035,2045,2070,2071,2072,2073,2075,2076,2077,2078,2079,2080,2081,2082,2083,2085,2086,2087,2089,2090,2091,2092,2093,2137,2138,2139,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,2305,2306,2307,2362,2363,2364,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,2381,2382,2383,2385,2386,2387,2388,2389,2390,2391,2402,2403,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2433,2434,2435,2492,2494,2495,2496,2497,2498,2499,2500,2503,2504,2507,2508,2509,2519,2530,2531,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2558,2561,2562,2563,2620,2622,2623,2624,2625,2626,2631,2632,2635,2636,2637,2641,2662,2663,2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2677,2689,2690,2691,2748,2750,2751,2752,2753,2754,2755,2756,2757,2759,2760,2761,2763,2764,2765,2786,2787,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,2810,2811,2812,2813,2814,2815,2817,2818,2819,2876,2878,2879,2880,2881,2882,2883,2884,2887,2888,2891,2892,2893,2902,2903,2914,2915,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2946,3006,3007,3008,3009,3010,3014,3015,3016,3018,3019,3020,3021,3031,3046,3047,3048,3049,3050,3051,3052,3053,3054,3055,3072,3073,3074,3075,3076,3134,3135,3136,3137,3138,3139,3140,3142,3143,3144,3146,3147,3148,3149,3157,3158,3170,3171,3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3201,3202,3203,3260,3262,3263,3264,3265,3266,3267,3268,3270,3271,3272,3274,3275,3276,3277,3285,3286,3298,3299,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3328,3329,3330,3331,3387,3388,3390,3391,3392,3393,3394,3395,3396,3398,3399,3400,3402,3403,3404,3405,3415,3426,3427,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3458,3459,3530,3535,3536,3537,3538,3539,3540,3542,3544,3545,3546,3547,3548,3549,3550,3551,3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3570,3571,3633,3636,3637,3638,3639,3640,3641,3642,3655,3656,3657,3658,3659,3660,3661,3662,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3761,3764,3765,3766,3767,3768,3769,3771,3772,3784,3785,3786,3787,3788,3789,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3864,3865,3872,3873,3874,3875,3876,3877,3878,3879,3880,3881,3893,3895,3897,3902,3903,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3974,3975,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990,3991,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4038,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4160,4161,4162,4163,4164,4165,4166,4167,4168,4169,4182,4183,4184,4185,4190,4191,4192,4194,4195,4196,4199,4200,4201,4202,4203,4204,4205,4209,4210,4211,4212,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4239,4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4957,4958,4959,4969,4970,4971,4972,4973,4974,4975,4976,4977,5906,5907,5908,5938,5939,5940,5970,5971,6002,6003,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6109,6112,6113,6114,6115,6116,6117,6118,6119,6120,6121,6155,6156,6157,6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6313,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,6470,6471,6472,6473,6474,6475,6476,6477,6478,6479,6608,6609,6610,6611,6612,6613,6614,6615,6616,6617,6618,6679,6680,6681,6682,6683,6741,6742,6743,6744,6745,6746,6747,6748,6749,6750,6752,6753,6754,6755,6756,6757,6758,6759,6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777,6778,6779,6780,6783,6784,6785,6786,6787,6788,6789,6790,6791,6792,6793,6800,6801,6802,6803,6804,6805,6806,6807,6808,6809,6832,6833,6834,6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6912,6913,6914,6915,6916,6964,6965,6966,6967,6968,6969,6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6992,6993,6994,6995,6996,6997,6998,6999,7000,7001,7019,7020,7021,7022,7023,7024,7025,7026,7027,7040,7041,7042,7073,7074,7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7088,7089,7090,7091,7092,7093,7094,7095,7096,7097,7142,7143,7144,7145,7146,7147,7148,7149,7150,7151,7152,7153,7154,7155,7204,7205,7206,7207,7208,7209,7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7232,7233,7234,7235,7236,7237,7238,7239,7240,7241,7248,7249,7250,7251,7252,7253,7254,7255,7256,7257,7376,7377,7378,7380,7381,7382,7383,7384,7385,7386,7387,7388,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7405,7410,7411,7412,7415,7416,7417,7616,7617,7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,7670,7671,7672,7673,7675,7676,7677,7678,7679,8204,8205,8255,8256,8276,8400,8401,8402,8403,8404,8405,8406,8407,8408,8409,8410,8411,8412,8417,8421,8422,8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,11503,11504,11505,11647,11744,11745,11746,11747,11748,11749,11750,11751,11752,11753,11754,11755,11756,11757,11758,11759,11760,11761,11762,11763,11764,11765,11766,11767,11768,11769,11770,11771,11772,11773,11774,11775,12330,12331,12332,12333,12334,12335,12441,12442,42528,42529,42530,42531,42532,42533,42534,42535,42536,42537,42607,42612,42613,42614,42615,42616,42617,42618,42619,42620,42621,42654,42655,42736,42737,43010,43014,43019,43043,43044,43045,43046,43047,43136,43137,43188,43189,43190,43191,43192,43193,43194,43195,43196,43197,43198,43199,43200,43201,43202,43203,43204,43205,43216,43217,43218,43219,43220,43221,43222,43223,43224,43225,43232,43233,43234,43235,43236,43237,43238,43239,43240,43241,43242,43243,43244,43245,43246,43247,43248,43249,43263,43264,43265,43266,43267,43268,43269,43270,43271,43272,43273,43302,43303,43304,43305,43306,43307,43308,43309,43335,43336,43337,43338,43339,43340,43341,43342,43343,43344,43345,43346,43347,43392,43393,43394,43395,43443,43444,43445,43446,43447,43448,43449,43450,43451,43452,43453,43454,43455,43456,43472,43473,43474,43475,43476,43477,43478,43479,43480,43481,43493,43504,43505,43506,43507,43508,43509,43510,43511,43512,43513,43561,43562,43563,43564,43565,43566,43567,43568,43569,43570,43571,43572,43573,43574,43587,43596,43597,43600,43601,43602,43603,43604,43605,43606,43607,43608,43609,43643,43644,43645,43696,43698,43699,43700,43703,43704,43710,43711,43713,43755,43756,43757,43758,43759,43765,43766,44003,44004,44005,44006,44007,44008,44009,44010,44012,44013,44016,44017,44018,44019,44020,44021,44022,44023,44024,44025,64286,65024,65025,65026,65027,65028,65029,65030,65031,65032,65033,65034,65035,65036,65037,65038,65039,65056,65057,65058,65059,65060,65061,65062,65063,65064,65065,65066,65067,65068,65069,65070,65071,65075,65076,65101,65102,65103,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,65343".split(",").map(function(_){return parseInt(_,10)});$.exports=t},{}],4:[function(_,$,e){var t="170,181,186,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,710,711,712,713,714,715,716,717,718,719,720,721,736,737,738,739,740,748,750,880,881,882,883,884,886,887,890,891,892,893,895,902,904,905,906,908,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1369,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1519,1520,1521,1522,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1646,1647,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1749,1765,1766,1774,1775,1786,1787,1788,1791,1808,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1969,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2036,2037,2042,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2074,2084,2088,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2230,2231,2232,2233,2234,2235,2236,2237,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2365,2384,2392,2393,2394,2395,2396,2397,2398,2399,2400,2401,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2431,2432,2437,2438,2439,2440,2441,2442,2443,2444,2447,2448,2451,2452,2453,2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2474,2475,2476,2477,2478,2479,2480,2482,2486,2487,2488,2489,2493,2510,2524,2525,2527,2528,2529,2544,2545,2556,2565,2566,2567,2568,2569,2570,2575,2576,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2602,2603,2604,2605,2606,2607,2608,2610,2611,2613,2614,2616,2617,2649,2650,2651,2652,2654,2674,2675,2676,2693,2694,2695,2696,2697,2698,2699,2700,2701,2703,2704,2705,2707,2708,2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,2730,2731,2732,2733,2734,2735,2736,2738,2739,2741,2742,2743,2744,2745,2749,2768,2784,2785,2809,2821,2822,2823,2824,2825,2826,2827,2828,2831,2832,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2858,2859,2860,2861,2862,2863,2864,2866,2867,2869,2870,2871,2872,2873,2877,2908,2909,2911,2912,2913,2929,2947,2949,2950,2951,2952,2953,2954,2958,2959,2960,2962,2963,2964,2965,2969,2970,2972,2974,2975,2979,2980,2984,2985,2986,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3024,3077,3078,3079,3080,3081,3082,3083,3084,3086,3087,3088,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3114,3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,3133,3160,3161,3162,3168,3169,3200,3205,3206,3207,3208,3209,3210,3211,3212,3214,3215,3216,3218,3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3253,3254,3255,3256,3257,3261,3294,3296,3297,3313,3314,3333,3334,3335,3336,3337,3338,3339,3340,3342,3343,3344,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3389,3406,3412,3413,3414,3423,3424,3425,3450,3451,3452,3453,3454,3455,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,3482,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,3507,3508,3509,3510,3511,3512,3513,3514,3515,3517,3520,3521,3522,3523,3524,3525,3526,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3634,3635,3648,3649,3650,3651,3652,3653,3654,3713,3714,3716,3719,3720,3722,3725,3732,3733,3734,3735,3737,3738,3739,3740,3741,3742,3743,3745,3746,3747,3749,3751,3754,3755,3757,3758,3759,3760,3762,3763,3773,3776,3777,3778,3779,3780,3782,3804,3805,3806,3807,3840,3904,3905,3906,3907,3908,3909,3910,3911,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3976,3977,3978,3979,3980,4096,4097,4098,4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,4138,4159,4176,4177,4178,4179,4180,4181,4186,4187,4188,4189,4193,4197,4198,4206,4207,4208,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,4224,4225,4238,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,4295,4301,4304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,4330,4331,4332,4333,4334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,4345,4346,4348,4349,4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,4404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,4419,4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,4614,4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,4674,4675,4676,4677,4678,4679,4680,4682,4683,4684,4685,4688,4689,4690,4691,4692,4693,4694,4696,4698,4699,4700,4701,4704,4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4746,4747,4748,4749,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,4780,4781,4782,4783,4784,4786,4787,4788,4789,4792,4793,4794,4795,4796,4797,4798,4800,4802,4803,4804,4805,4808,4809,4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4824,4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4882,4883,4884,4885,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,5005,5006,5007,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,5112,5113,5114,5115,5116,5117,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,5184,5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664,5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,5759,5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5792,5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,5860,5861,5862,5863,5864,5865,5866,5870,5871,5872,5873,5874,5875,5876,5877,5878,5879,5880,5888,5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5902,5903,5904,5905,5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936,5937,5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968,5969,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5998,5999,6000,6016,6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6103,6108,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,6189,6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,6219,6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,6234,6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,6249,6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,6264,6272,6273,6274,6275,6276,6277,6278,6279,6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,6294,6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,6309,6310,6311,6312,6314,6320,6321,6322,6323,6324,6325,6326,6327,6328,6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,6339,6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,6354,6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,6384,6385,6386,6387,6388,6389,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,6414,6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,6429,6430,6480,6481,6482,6483,6484,6485,6486,6487,6488,6489,6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,6504,6505,6506,6507,6508,6509,6512,6513,6514,6515,6516,6528,6529,6530,6531,6532,6533,6534,6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,6565,6566,6567,6568,6569,6570,6571,6576,6577,6578,6579,6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,6594,6595,6596,6597,6598,6599,6600,6601,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,6669,6670,6671,6672,6673,6674,6675,6676,6677,6678,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,6715,6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6823,6917,6918,6919,6920,6921,6922,6923,6924,6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,6939,6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6981,6982,6983,6984,6985,6986,6987,7043,7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059,7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7086,7087,7098,7099,7100,7101,7102,7103,7104,7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,7135,7136,7137,7138,7139,7140,7141,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,7194,7195,7196,7197,7198,7199,7200,7201,7202,7203,7245,7246,7247,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,7269,7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,7284,7285,7286,7287,7288,7289,7290,7291,7292,7293,7296,7297,7298,7299,7300,7301,7302,7303,7304,7312,7313,7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,7343,7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7357,7358,7359,7401,7402,7403,7404,7406,7407,7408,7409,7413,7414,7424,7425,7426,7427,7428,7429,7430,7431,7432,7433,7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,7448,7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,7463,7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,7478,7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491,7492,7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,7538,7539,7540,7541,7542,7543,7544,7545,7546,7547,7548,7549,7550,7551,7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567,7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582,7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,7613,7614,7615,7680,7681,7682,7683,7684,7685,7686,7687,7688,7689,7690,7691,7692,7693,7694,7695,7696,7697,7698,7699,7700,7701,7702,7703,7704,7705,7706,7707,7708,7709,7710,7711,7712,7713,7714,7715,7716,7717,7718,7719,7720,7721,7722,7723,7724,7725,7726,7727,7728,7729,7730,7731,7732,7733,7734,7735,7736,7737,7738,7739,7740,7741,7742,7743,7744,7745,7746,7747,7748,7749,7750,7751,7752,7753,7754,7755,7756,7757,7758,7759,7760,7761,7762,7763,7764,7765,7766,7767,7768,7769,7770,7771,7772,7773,7774,7775,7776,7777,7778,7779,7780,7781,7782,7783,7784,7785,7786,7787,7788,7789,7790,7791,7792,7793,7794,7795,7796,7797,7798,7799,7800,7801,7802,7803,7804,7805,7806,7807,7808,7809,7810,7811,7812,7813,7814,7815,7816,7817,7818,7819,7820,7821,7822,7823,7824,7825,7826,7827,7828,7829,7830,7831,7832,7833,7834,7835,7836,7837,7838,7839,7840,7841,7842,7843,7844,7845,7846,7847,7848,7849,7850,7851,7852,7853,7854,7855,7856,7857,7858,7859,7860,7861,7862,7863,7864,7865,7866,7867,7868,7869,7870,7871,7872,7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886,7887,7888,7889,7890,7891,7892,7893,7894,7895,7896,7897,7898,7899,7900,7901,7902,7903,7904,7905,7906,7907,7908,7909,7910,7911,7912,7913,7914,7915,7916,7917,7918,7919,7920,7921,7922,7923,7924,7925,7926,7927,7928,7929,7930,7931,7932,7933,7934,7935,7936,7937,7938,7939,7940,7941,7942,7943,7944,7945,7946,7947,7948,7949,7950,7951,7952,7953,7954,7955,7956,7957,7960,7961,7962,7963,7964,7965,7968,7969,7970,7971,7972,7973,7974,7975,7976,7977,7978,7979,7980,7981,7982,7983,7984,7985,7986,7987,7988,7989,7990,7991,7992,7993,7994,7995,7996,7997,7998,7999,8000,8001,8002,8003,8004,8005,8008,8009,8010,8011,8012,8013,8016,8017,8018,8019,8020,8021,8022,8023,8025,8027,8029,8031,8032,8033,8034,8035,8036,8037,8038,8039,8040,8041,8042,8043,8044,8045,8046,8047,8048,8049,8050,8051,8052,8053,8054,8055,8056,8057,8058,8059,8060,8061,8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095,8096,8097,8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110,8111,8112,8113,8114,8115,8116,8118,8119,8120,8121,8122,8123,8124,8126,8130,8131,8132,8134,8135,8136,8137,8138,8139,8140,8144,8145,8146,8147,8150,8151,8152,8153,8154,8155,8160,8161,8162,8163,8164,8165,8166,8167,8168,8169,8170,8171,8172,8178,8179,8180,8182,8183,8184,8185,8186,8187,8188,8305,8319,8336,8337,8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,8348,8450,8455,8458,8459,8460,8461,8462,8463,8464,8465,8466,8467,8469,8472,8473,8474,8475,8476,8477,8484,8486,8488,8490,8491,8492,8493,8494,8495,8496,8497,8498,8499,8500,8501,8502,8503,8504,8505,8508,8509,8510,8511,8517,8518,8519,8520,8521,8526,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,8570,8571,8572,8573,8574,8575,8576,8577,8578,8579,8580,8581,8582,8583,8584,11264,11265,11266,11267,11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,11306,11307,11308,11309,11310,11312,11313,11314,11315,11316,11317,11318,11319,11320,11321,11322,11323,11324,11325,11326,11327,11328,11329,11330,11331,11332,11333,11334,11335,11336,11337,11338,11339,11340,11341,11342,11343,11344,11345,11346,11347,11348,11349,11350,11351,11352,11353,11354,11355,11356,11357,11358,11360,11361,11362,11363,11364,11365,11366,11367,11368,11369,11370,11371,11372,11373,11374,11375,11376,11377,11378,11379,11380,11381,11382,11383,11384,11385,11386,11387,11388,11389,11390,11391,11392,11393,11394,11395,11396,11397,11398,11399,11400,11401,11402,11403,11404,11405,11406,11407,11408,11409,11410,11411,11412,11413,11414,11415,11416,11417,11418,11419,11420,11421,11422,11423,11424,11425,11426,11427,11428,11429,11430,11431,11432,11433,11434,11435,11436,11437,11438,11439,11440,11441,11442,11443,11444,11445,11446,11447,11448,11449,11450,11451,11452,11453,11454,11455,11456,11457,11458,11459,11460,11461,11462,11463,11464,11465,11466,11467,11468,11469,11470,11471,11472,11473,11474,11475,11476,11477,11478,11479,11480,11481,11482,11483,11484,11485,11486,11487,11488,11489,11490,11491,11492,11499,11500,11501,11502,11506,11507,11520,11521,11522,11523,11524,11525,11526,11527,11528,11529,11530,11531,11532,11533,11534,11535,11536,11537,11538,11539,11540,11541,11542,11543,11544,11545,11546,11547,11548,11549,11550,11551,11552,11553,11554,11555,11556,11557,11559,11565,11568,11569,11570,11571,11572,11573,11574,11575,11576,11577,11578,11579,11580,11581,11582,11583,11584,11585,11586,11587,11588,11589,11590,11591,11592,11593,11594,11595,11596,11597,11598,11599,11600,11601,11602,11603,11604,11605,11606,11607,11608,11609,11610,11611,11612,11613,11614,11615,11616,11617,11618,11619,11620,11621,11622,11623,11631,11648,11649,11650,11651,11652,11653,11654,11655,11656,11657,11658,11659,11660,11661,11662,11663,11664,11665,11666,11667,11668,11669,11670,11680,11681,11682,11683,11684,11685,11686,11688,11689,11690,11691,11692,11693,11694,11696,11697,11698,11699,11700,11701,11702,11704,11705,11706,11707,11708,11709,11710,11712,11713,11714,11715,11716,11717,11718,11720,11721,11722,11723,11724,11725,11726,11728,11729,11730,11731,11732,11733,11734,11736,11737,11738,11739,11740,11741,11742,12293,12294,12295,12321,12322,12323,12324,12325,12326,12327,12328,12329,12337,12338,12339,12340,12341,12344,12345,12346,12347,12348,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,12436,12437,12438,12443,12444,12445,12446,12447,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,12535,12536,12537,12538,12540,12541,12542,12543,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,12586,12587,12588,12589,12590,12591,12593,12594,12595,12596,12597,12598,12599,12600,12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,12611,12612,12613,12614,12615,12616,12617,12618,12619,12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,12632,12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,12662,12663,12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679,12680,12681,12682,12683,12684,12685,12686,12704,12705,12706,12707,12708,12709,12710,12711,12712,12713,12714,12715,12716,12717,12718,12719,12720,12721,12722,12723,12724,12725,12726,12727,12728,12729,12730,12784,12785,12786,12787,12788,12789,12790,12791,12792,12793,12794,12795,12796,12797,12798,12799,13312,13313,13314,13315,13316,13317,13318,13319,13320,13321,13322,13323,13324,13325,13326,13327,13328,13329,13330,13331,13332,13333,13334,13335,13336,13337,13338,13339,13340,13341,13342,13343,13344,13345,13346,13347,13348,13349,13350,13351,13352,13353,13354,13355,13356,13357,13358,13359,13360,13361,13362,13363,13364,13365,13366,13367,13368,13369,13370,13371,13372,13373,13374,13375,13376,13377,13378,13379,13380,13381,13382,13383,13384,13385,13386,13387,13388,13389,13390,13391,13392,13393,13394,13395,13396,13397,13398,13399,13400,13401,13402,13403,13404,13405,13406,13407,13408,13409,13410,13411,13412,13413,13414,13415,13416,13417,13418,13419,13420,13421,13422,13423,13424,13425,13426,13427,13428,13429,13430,13431,13432,13433,13434,13435,13436,13437,13438,13439,13440,13441,13442,13443,13444,13445,13446,13447,13448,13449,13450,13451,13452,13453,13454,13455,13456,13457,13458,13459,13460,13461,13462,13463,13464,13465,13466,13467,13468,13469,13470,13471,13472,13473,13474,13475,13476,13477,13478,13479,13480,13481,13482,13483,13484,13485,13486,13487,13488,13489,13490,13491,13492,13493,13494,13495,13496,13497,13498,13499,13500,13501,13502,13503,13504,13505,13506,13507,13508,13509,13510,13511,13512,13513,13514,13515,13516,13517,13518,13519,13520,13521,13522,13523,13524,13525,13526,13527,13528,13529,13530,13531,13532,13533,13534,13535,13536,13537,13538,13539,13540,13541,13542,13543,13544,13545,13546,13547,13548,13549,13550,13551,13552,13553,13554,13555,13556,13557,13558,13559,13560,13561,13562,13563,13564,13565,13566,13567,13568,13569,13570,13571,13572,13573,13574,13575,13576,13577,13578,13579,13580,13581,13582,13583,13584,13585,13586,13587,13588,13589,13590,13591,13592,13593,13594,13595,13596,13597,13598,13599,13600,13601,13602,13603,13604,13605,13606,13607,13608,13609,13610,13611,13612,13613,13614,13615,13616,13617,13618,13619,13620,13621,13622,13623,13624,13625,13626,13627,13628,13629,13630,13631,13632,13633,13634,13635,13636,13637,13638,13639,13640,13641,13642,13643,13644,13645,13646,13647,13648,13649,13650,13651,13652,13653,13654,13655,13656,13657,13658,13659,13660,13661,13662,13663,13664,13665,13666,13667,13668,13669,13670,13671,13672,13673,13674,13675,13676,13677,13678,13679,13680,13681,13682,13683,13684,13685,13686,13687,13688,13689,13690,13691,13692,13693,13694,13695,13696,13697,13698,13699,13700,13701,13702,13703,13704,13705,13706,13707,13708,13709,13710,13711,13712,13713,13714,13715,13716,13717,13718,13719,13720,13721,13722,13723,13724,13725,13726,13727,13728,13729,13730,13731,13732,13733,13734,13735,13736,13737,13738,13739,13740,13741,13742,13743,13744,13745,13746,13747,13748,13749,13750,13751,13752,13753,13754,13755,13756,13757,13758,13759,13760,13761,13762,13763,13764,13765,13766,13767,13768,13769,13770,13771,13772,13773,13774,13775,13776,13777,13778,13779,13780,13781,13782,13783,13784,13785,13786,13787,13788,13789,13790,13791,13792,13793,13794,13795,13796,13797,13798,13799,13800,13801,13802,13803,13804,13805,13806,13807,13808,13809,13810,13811,13812,13813,13814,13815,13816,13817,13818,13819,13820,13821,13822,13823,13824,13825,13826,13827,13828,13829,13830,13831,13832,13833,13834,13835,13836,13837,13838,13839,13840,13841,13842,13843,13844,13845,13846,13847,13848,13849,13850,13851,13852,13853,13854,13855,13856,13857,13858,13859,13860,13861,13862,13863,13864,13865,13866,13867,13868,13869,13870,13871,13872,13873,13874,13875,13876,13877,13878,13879,13880,13881,13882,13883,13884,13885,13886,13887,13888,13889,13890,13891,13892,13893,13894,13895,13896,13897,13898,13899,13900,13901,13902,13903,13904,13905,13906,13907,13908,13909,13910,13911,13912,13913,13914,13915,13916,13917,13918,13919,13920,13921,13922,13923,13924,13925,13926,13927,13928,13929,13930,13931,13932,13933,13934,13935,13936,13937,13938,13939,13940,13941,13942,13943,13944,13945,13946,13947,13948,13949,13950,13951,13952,13953,13954,13955,13956,13957,13958,13959,13960,13961,13962,13963,13964,13965,13966,13967,13968,13969,13970,13971,13972,13973,13974,13975,13976,13977,13978,13979,13980,13981,13982,13983,13984,13985,13986,13987,13988,13989,13990,13991,13992,13993,13994,13995,13996,13997,13998,13999,14000,14001,14002,14003,14004,14005,14006,14007,14008,14009,14010,14011,14012,14013,14014,14015,14016,14017,14018,14019,14020,14021,14022,14023,14024,14025,14026,14027,14028,14029,14030,14031,14032,14033,14034,14035,14036,14037,14038,14039,14040,14041,14042,14043,14044,14045,14046,14047,14048,14049,14050,14051,14052,14053,14054,14055,14056,14057,14058,14059,14060,14061,14062,14063,14064,14065,14066,14067,14068,14069,14070,14071,14072,14073,14074,14075,14076,14077,14078,14079,14080,14081,14082,14083,14084,14085,14086,14087,14088,14089,14090,14091,14092,14093,14094,14095,14096,14097,14098,14099,14100,14101,14102,14103,14104,14105,14106,14107,14108,14109,14110,14111,14112,14113,14114,14115,14116,14117,14118,14119,14120,14121,14122,14123,14124,14125,14126,14127,14128,14129,14130,14131,14132,14133,14134,14135,14136,14137,14138,14139,14140,14141,14142,14143,14144,14145,14146,14147,14148,14149,14150,14151,14152,14153,14154,14155,14156,14157,14158,14159,14160,14161,14162,14163,14164,14165,14166,14167,14168,14169,14170,14171,14172,14173,14174,14175,14176,14177,14178,14179,14180,14181,14182,14183,14184,14185,14186,14187,14188,14189,14190,14191,14192,14193,14194,14195,14196,14197,14198,14199,14200,14201,14202,14203,14204,14205,14206,14207,14208,14209,14210,14211,14212,14213,14214,14215,14216,14217,14218,14219,14220,14221,14222,14223,14224,14225,14226,14227,14228,14229,14230,14231,14232,14233,14234,14235,14236,14237,14238,14239,14240,14241,14242,14243,14244,14245,14246,14247,14248,14249,14250,14251,14252,14253,14254,14255,14256,14257,14258,14259,14260,14261,14262,14263,14264,14265,14266,14267,14268,14269,14270,14271,14272,14273,14274,14275,14276,14277,14278,14279,14280,14281,14282,14283,14284,14285,14286,14287,14288,14289,14290,14291,14292,14293,14294,14295,14296,14297,14298,14299,14300,14301,14302,14303,14304,14305,14306,14307,14308,14309,14310,14311,14312,14313,14314,14315,14316,14317,14318,14319,14320,14321,14322,14323,14324,14325,14326,14327,14328,14329,14330,14331,14332,14333,14334,14335,14336,14337,14338,14339,14340,14341,14342,14343,14344,14345,14346,14347,14348,14349,14350,14351,14352,14353,14354,14355,14356,14357,14358,14359,14360,14361,14362,14363,14364,14365,14366,14367,14368,14369,14370,14371,14372,14373,14374,14375,14376,14377,14378,14379,14380,14381,14382,14383,14384,14385,14386,14387,14388,14389,14390,14391,14392,14393,14394,14395,14396,14397,14398,14399,14400,14401,14402,14403,14404,14405,14406,14407,14408,14409,14410,14411,14412,14413,14414,14415,14416,14417,14418,14419,14420,14421,14422,14423,14424,14425,14426,14427,14428,14429,14430,14431,14432,14433,14434,14435,14436,14437,14438,14439,14440,14441,14442,14443,14444,14445,14446,14447,14448,14449,14450,14451,14452,14453,14454,14455,14456,14457,14458,14459,14460,14461,14462,14463,14464,14465,14466,14467,14468,14469,14470,14471,14472,14473,14474,14475,14476,14477,14478,14479,14480,14481,14482,14483,14484,14485,14486,14487,14488,14489,14490,14491,14492,14493,14494,14495,14496,14497,14498,14499,14500,14501,14502,14503,14504,14505,14506,14507,14508,14509,14510,14511,14512,14513,14514,14515,14516,14517,14518,14519,14520,14521,14522,14523,14524,14525,14526,14527,14528,14529,14530,14531,14532,14533,14534,14535,14536,14537,14538,14539,14540,14541,14542,14543,14544,14545,14546,14547,14548,14549,14550,14551,14552,14553,14554,14555,14556,14557,14558,14559,14560,14561,14562,14563,14564,14565,14566,14567,14568,14569,14570,14571,14572,14573,14574,14575,14576,14577,14578,14579,14580,14581,14582,14583,14584,14585,14586,14587,14588,14589,14590,14591,14592,14593,14594,14595,14596,14597,14598,14599,14600,14601,14602,14603,14604,14605,14606,14607,14608,14609,14610,14611,14612,14613,14614,14615,14616,14617,14618,14619,14620,14621,14622,14623,14624,14625,14626,14627,14628,14629,14630,14631,14632,14633,14634,14635,14636,14637,14638,14639,14640,14641,14642,14643,14644,14645,14646,14647,14648,14649,14650,14651,14652,14653,14654,14655,14656,14657,14658,14659,14660,14661,14662,14663,14664,14665,14666,14667,14668,14669,14670,14671,14672,14673,14674,14675,14676,14677,14678,14679,14680,14681,14682,14683,14684,14685,14686,14687,14688,14689,14690,14691,14692,14693,14694,14695,14696,14697,14698,14699,14700,14701,14702,14703,14704,14705,14706,14707,14708,14709,14710,14711,14712,14713,14714,14715,14716,14717,14718,14719,14720,14721,14722,14723,14724,14725,14726,14727,14728,14729,14730,14731,14732,14733,14734,14735,14736,14737,14738,14739,14740,14741,14742,14743,14744,14745,14746,14747,14748,14749,14750,14751,14752,14753,14754,14755,14756,14757,14758,14759,14760,14761,14762,14763,14764,14765,14766,14767,14768,14769,14770,14771,14772,14773,14774,14775,14776,14777,14778,14779,14780,14781,14782,14783,14784,14785,14786,14787,14788,14789,14790,14791,14792,14793,14794,14795,14796,14797,14798,14799,14800,14801,14802,14803,14804,14805,14806,14807,14808,14809,14810,14811,14812,14813,14814,14815,14816,14817,14818,14819,14820,14821,14822,14823,14824,14825,14826,14827,14828,14829,14830,14831,14832,14833,14834,14835,14836,14837,14838,14839,14840,14841,14842,14843,14844,14845,14846,14847,14848,14849,14850,14851,14852,14853,14854,14855,14856,14857,14858,14859,14860,14861,14862,14863,14864,14865,14866,14867,14868,14869,14870,14871,14872,14873,14874,14875,14876,14877,14878,14879,14880,14881,14882,14883,14884,14885,14886,14887,14888,14889,14890,14891,14892,14893,14894,14895,14896,14897,14898,14899,14900,14901,14902,14903,14904,14905,14906,14907,14908,14909,14910,14911,14912,14913,14914,14915,14916,14917,14918,14919,14920,14921,14922,14923,14924,14925,14926,14927,14928,14929,14930,14931,14932,14933,14934,14935,14936,14937,14938,14939,14940,14941,14942,14943,14944,14945,14946,14947,14948,14949,14950,14951,14952,14953,14954,14955,14956,14957,14958,14959,14960,14961,14962,14963,14964,14965,14966,14967,14968,14969,14970,14971,14972,14973,14974,14975,14976,14977,14978,14979,14980,14981,14982,14983,14984,14985,14986,14987,14988,14989,14990,14991,14992,14993,14994,14995,14996,14997,14998,14999,15000,15001,15002,15003,15004,15005,15006,15007,15008,15009,15010,15011,15012,15013,15014,15015,15016,15017,15018,15019,15020,15021,15022,15023,15024,15025,15026,15027,15028,15029,15030,15031,15032,15033,15034,15035,15036,15037,15038,15039,15040,15041,15042,15043,15044,15045,15046,15047,15048,15049,15050,15051,15052,15053,15054,15055,15056,15057,15058,15059,15060,15061,15062,15063,15064,15065,15066,15067,15068,15069,15070,15071,15072,15073,15074,15075,15076,15077,15078,15079,15080,15081,15082,15083,15084,15085,15086,15087,15088,15089,15090,15091,15092,15093,15094,15095,15096,15097,15098,15099,15100,15101,15102,15103,15104,15105,15106,15107,15108,15109,15110,15111,15112,15113,15114,15115,15116,15117,15118,15119,15120,15121,15122,15123,15124,15125,15126,15127,15128,15129,15130,15131,15132,15133,15134,15135,15136,15137,15138,15139,15140,15141,15142,15143,15144,15145,15146,15147,15148,15149,15150,15151,15152,15153,15154,15155,15156,15157,15158,15159,15160,15161,15162,15163,15164,15165,15166,15167,15168,15169,15170,15171,15172,15173,15174,15175,15176,15177,15178,15179,15180,15181,15182,15183,15184,15185,15186,15187,15188,15189,15190,15191,15192,15193,15194,15195,15196,15197,15198,15199,15200,15201,15202,15203,15204,15205,15206,15207,15208,15209,15210,15211,15212,15213,15214,15215,15216,15217,15218,15219,15220,15221,15222,15223,15224,15225,15226,15227,15228,15229,15230,15231,15232,15233,15234,15235,15236,15237,15238,15239,15240,15241,15242,15243,15244,15245,15246,15247,15248,15249,15250,15251,15252,15253,15254,15255,15256,15257,15258,15259,15260,15261,15262,15263,15264,15265,15266,15267,15268,15269,15270,15271,15272,15273,15274,15275,15276,15277,15278,15279,15280,15281,15282,15283,15284,15285,15286,15287,15288,15289,15290,15291,15292,15293,15294,15295,15296,15297,15298,15299,15300,15301,15302,15303,15304,15305,15306,15307,15308,15309,15310,15311,15312,15313,15314,15315,15316,15317,15318,15319,15320,15321,15322,15323,15324,15325,15326,15327,15328,15329,15330,15331,15332,15333,15334,15335,15336,15337,15338,15339,15340,15341,15342,15343,15344,15345,15346,15347,15348,15349,15350,15351,15352,15353,15354,15355,15356,15357,15358,15359,15360,15361,15362,15363,15364,15365,15366,15367,15368,15369,15370,15371,15372,15373,15374,15375,15376,15377,15378,15379,15380,15381,15382,15383,15384,15385,15386,15387,15388,15389,15390,15391,15392,15393,15394,15395,15396,15397,15398,15399,15400,15401,15402,15403,15404,15405,15406,15407,15408,15409,15410,15411,15412,15413,15414,15415,15416,15417,15418,15419,15420,15421,15422,15423,15424,15425,15426,15427,15428,15429,15430,15431,15432,15433,15434,15435,15436,15437,15438,15439,15440,15441,15442,15443,15444,15445,15446,15447,15448,15449,15450,15451,15452,15453,15454,15455,15456,15457,15458,15459,15460,15461,15462,15463,15464,15465,15466,15467,15468,15469,15470,15471,15472,15473,15474,15475,15476,15477,15478,15479,15480,15481,15482,15483,15484,15485,15486,15487,15488,15489,15490,15491,15492,15493,15494,15495,15496,15497,15498,15499,15500,15501,15502,15503,15504,15505,15506,15507,15508,15509,15510,15511,15512,15513,15514,15515,15516,15517,15518,15519,15520,15521,15522,15523,15524,15525,15526,15527,15528,15529,15530,15531,15532,15533,15534,15535,15536,15537,15538,15539,15540,15541,15542,15543,15544,15545,15546,15547,15548,15549,15550,15551,15552,15553,15554,15555,15556,15557,15558,15559,15560,15561,15562,15563,15564,15565,15566,15567,15568,15569,15570,15571,15572,15573,15574,15575,15576,15577,15578,15579,15580,15581,15582,15583,15584,15585,15586,15587,15588,15589,15590,15591,15592,15593,15594,15595,15596,15597,15598,15599,15600,15601,15602,15603,15604,15605,15606,15607,15608,15609,15610,15611,15612,15613,15614,15615,15616,15617,15618,15619,15620,15621,15622,15623,15624,15625,15626,15627,15628,15629,15630,15631,15632,15633,15634,15635,15636,15637,15638,15639,15640,15641,15642,15643,15644,15645,15646,15647,15648,15649,15650,15651,15652,15653,15654,15655,15656,15657,15658,15659,15660,15661,15662,15663,15664,15665,15666,15667,15668,15669,15670,15671,15672,15673,15674,15675,15676,15677,15678,15679,15680,15681,15682,15683,15684,15685,15686,15687,15688,15689,15690,15691,15692,15693,15694,15695,15696,15697,15698,15699,15700,15701,15702,15703,15704,15705,15706,15707,15708,15709,15710,15711,15712,15713,15714,15715,15716,15717,15718,15719,15720,15721,15722,15723,15724,15725,15726,15727,15728,15729,15730,15731,15732,15733,15734,15735,15736,15737,15738,15739,15740,15741,15742,15743,15744,15745,15746,15747,15748,15749,15750,15751,15752,15753,15754,15755,15756,15757,15758,15759,15760,15761,15762,15763,15764,15765,15766,15767,15768,15769,15770,15771,15772,15773,15774,15775,15776,15777,15778,15779,15780,15781,15782,15783,15784,15785,15786,15787,15788,15789,15790,15791,15792,15793,15794,15795,15796,15797,15798,15799,15800,15801,15802,15803,15804,15805,15806,15807,15808,15809,15810,15811,15812,15813,15814,15815,15816,15817,15818,15819,15820,15821,15822,15823,15824,15825,15826,15827,15828,15829,15830,15831,15832,15833,15834,15835,15836,15837,15838,15839,15840,15841,15842,15843,15844,15845,15846,15847,15848,15849,15850,15851,15852,15853,15854,15855,15856,15857,15858,15859,15860,15861,15862,15863,15864,15865,15866,15867,15868,15869,15870,15871,15872,15873,15874,15875,15876,15877,15878,15879,15880,15881,15882,15883,15884,15885,15886,15887,15888,15889,15890,15891,15892,15893,15894,15895,15896,15897,15898,15899,15900,15901,15902,15903,15904,15905,15906,15907,15908,15909,15910,15911,15912,15913,15914,15915,15916,15917,15918,15919,15920,15921,15922,15923,15924,15925,15926,15927,15928,15929,15930,15931,15932,15933,15934,15935,15936,15937,15938,15939,15940,15941,15942,15943,15944,15945,15946,15947,15948,15949,15950,15951,15952,15953,15954,15955,15956,15957,15958,15959,15960,15961,15962,15963,15964,15965,15966,15967,15968,15969,15970,15971,15972,15973,15974,15975,15976,15977,15978,15979,15980,15981,15982,15983,15984,15985,15986,15987,15988,15989,15990,15991,15992,15993,15994,15995,15996,15997,15998,15999,16000,16001,16002,16003,16004,16005,16006,16007,16008,16009,16010,16011,16012,16013,16014,16015,16016,16017,16018,16019,16020,16021,16022,16023,16024,16025,16026,16027,16028,16029,16030,16031,16032,16033,16034,16035,16036,16037,16038,16039,16040,16041,16042,16043,16044,16045,16046,16047,16048,16049,16050,16051,16052,16053,16054,16055,16056,16057,16058,16059,16060,16061,16062,16063,16064,16065,16066,16067,16068,16069,16070,16071,16072,16073,16074,16075,16076,16077,16078,16079,16080,16081,16082,16083,16084,16085,16086,16087,16088,16089,16090,16091,16092,16093,16094,16095,16096,16097,16098,16099,16100,16101,16102,16103,16104,16105,16106,16107,16108,16109,16110,16111,16112,16113,16114,16115,16116,16117,16118,16119,16120,16121,16122,16123,16124,16125,16126,16127,16128,16129,16130,16131,16132,16133,16134,16135,16136,16137,16138,16139,16140,16141,16142,16143,16144,16145,16146,16147,16148,16149,16150,16151,16152,16153,16154,16155,16156,16157,16158,16159,16160,16161,16162,16163,16164,16165,16166,16167,16168,16169,16170,16171,16172,16173,16174,16175,16176,16177,16178,16179,16180,16181,16182,16183,16184,16185,16186,16187,16188,16189,16190,16191,16192,16193,16194,16195,16196,16197,16198,16199,16200,16201,16202,16203,16204,16205,16206,16207,16208,16209,16210,16211,16212,16213,16214,16215,16216,16217,16218,16219,16220,16221,16222,16223,16224,16225,16226,16227,16228,16229,16230,16231,16232,16233,16234,16235,16236,16237,16238,16239,16240,16241,16242,16243,16244,16245,16246,16247,16248,16249,16250,16251,16252,16253,16254,16255,16256,16257,16258,16259,16260,16261,16262,16263,16264,16265,16266,16267,16268,16269,16270,16271,16272,16273,16274,16275,16276,16277,16278,16279,16280,16281,16282,16283,16284,16285,16286,16287,16288,16289,16290,16291,16292,16293,16294,16295,16296,16297,16298,16299,16300,16301,16302,16303,16304,16305,16306,16307,16308,16309,16310,16311,16312,16313,16314,16315,16316,16317,16318,16319,16320,16321,16322,16323,16324,16325,16326,16327,16328,16329,16330,16331,16332,16333,16334,16335,16336,16337,16338,16339,16340,16341,16342,16343,16344,16345,16346,16347,16348,16349,16350,16351,16352,16353,16354,16355,16356,16357,16358,16359,16360,16361,16362,16363,16364,16365,16366,16367,16368,16369,16370,16371,16372,16373,16374,16375,16376,16377,16378,16379,16380,16381,16382,16383,16384,16385,16386,16387,16388,16389,16390,16391,16392,16393,16394,16395,16396,16397,16398,16399,16400,16401,16402,16403,16404,16405,16406,16407,16408,16409,16410,16411,16412,16413,16414,16415,16416,16417,16418,16419,16420,16421,16422,16423,16424,16425,16426,16427,16428,16429,16430,16431,16432,16433,16434,16435,16436,16437,16438,16439,16440,16441,16442,16443,16444,16445,16446,16447,16448,16449,16450,16451,16452,16453,16454,16455,16456,16457,16458,16459,16460,16461,16462,16463,16464,16465,16466,16467,16468,16469,16470,16471,16472,16473,16474,16475,16476,16477,16478,16479,16480,16481,16482,16483,16484,16485,16486,16487,16488,16489,16490,16491,16492,16493,16494,16495,16496,16497,16498,16499,16500,16501,16502,16503,16504,16505,16506,16507,16508,16509,16510,16511,16512,16513,16514,16515,16516,16517,16518,16519,16520,16521,16522,16523,16524,16525,16526,16527,16528,16529,16530,16531,16532,16533,16534,16535,16536,16537,16538,16539,16540,16541,16542,16543,16544,16545,16546,16547,16548,16549,16550,16551,16552,16553,16554,16555,16556,16557,16558,16559,16560,16561,16562,16563,16564,16565,16566,16567,16568,16569,16570,16571,16572,16573,16574,16575,16576,16577,16578,16579,16580,16581,16582,16583,16584,16585,16586,16587,16588,16589,16590,16591,16592,16593,16594,16595,16596,16597,16598,16599,16600,16601,16602,16603,16604,16605,16606,16607,16608,16609,16610,16611,16612,16613,16614,16615,16616,16617,16618,16619,16620,16621,16622,16623,16624,16625,16626,16627,16628,16629,16630,16631,16632,16633,16634,16635,16636,16637,16638,16639,16640,16641,16642,16643,16644,16645,16646,16647,16648,16649,16650,16651,16652,16653,16654,16655,16656,16657,16658,16659,16660,16661,16662,16663,16664,16665,16666,16667,16668,16669,16670,16671,16672,16673,16674,16675,16676,16677,16678,16679,16680,16681,16682,16683,16684,16685,16686,16687,16688,16689,16690,16691,16692,16693,16694,16695,16696,16697,16698,16699,16700,16701,16702,16703,16704,16705,16706,16707,16708,16709,16710,16711,16712,16713,16714,16715,16716,16717,16718,16719,16720,16721,16722,16723,16724,16725,16726,16727,16728,16729,16730,16731,16732,16733,16734,16735,16736,16737,16738,16739,16740,16741,16742,16743,16744,16745,16746,16747,16748,16749,16750,16751,16752,16753,16754,16755,16756,16757,16758,16759,16760,16761,16762,16763,16764,16765,16766,16767,16768,16769,16770,16771,16772,16773,16774,16775,16776,16777,16778,16779,16780,16781,16782,16783,16784,16785,16786,16787,16788,16789,16790,16791,16792,16793,16794,16795,16796,16797,16798,16799,16800,16801,16802,16803,16804,16805,16806,16807,16808,16809,16810,16811,16812,16813,16814,16815,16816,16817,16818,16819,16820,16821,16822,16823,16824,16825,16826,16827,16828,16829,16830,16831,16832,16833,16834,16835,16836,16837,16838,16839,16840,16841,16842,16843,16844,16845,16846,16847,16848,16849,16850,16851,16852,16853,16854,16855,16856,16857,16858,16859,16860,16861,16862,16863,16864,16865,16866,16867,16868,16869,16870,16871,16872,16873,16874,16875,16876,16877,16878,16879,16880,16881,16882,16883,16884,16885,16886,16887,16888,16889,16890,16891,16892,16893,16894,16895,16896,16897,16898,16899,16900,16901,16902,16903,16904,16905,16906,16907,16908,16909,16910,16911,16912,16913,16914,16915,16916,16917,16918,16919,16920,16921,16922,16923,16924,16925,16926,16927,16928,16929,16930,16931,16932,16933,16934,16935,16936,16937,16938,16939,16940,16941,16942,16943,16944,16945,16946,16947,16948,16949,16950,16951,16952,16953,16954,16955,16956,16957,16958,16959,16960,16961,16962,16963,16964,16965,16966,16967,16968,16969,16970,16971,16972,16973,16974,16975,16976,16977,16978,16979,16980,16981,16982,16983,16984,16985,16986,16987,16988,16989,16990,16991,16992,16993,16994,16995,16996,16997,16998,16999,17000,17001,17002,17003,17004,17005,17006,17007,17008,17009,17010,17011,17012,17013,17014,17015,17016,17017,17018,17019,17020,17021,17022,17023,17024,17025,17026,17027,17028,17029,17030,17031,17032,17033,17034,17035,17036,17037,17038,17039,17040,17041,17042,17043,17044,17045,17046,17047,17048,17049,17050,17051,17052,17053,17054,17055,17056,17057,17058,17059,17060,17061,17062,17063,17064,17065,17066,17067,17068,17069,17070,17071,17072,17073,17074,17075,17076,17077,17078,17079,17080,17081,17082,17083,17084,17085,17086,17087,17088,17089,17090,17091,17092,17093,17094,17095,17096,17097,17098,17099,17100,17101,17102,17103,17104,17105,17106,17107,17108,17109,17110,17111,17112,17113,17114,17115,17116,17117,17118,17119,17120,17121,17122,17123,17124,17125,17126,17127,17128,17129,17130,17131,17132,17133,17134,17135,17136,17137,17138,17139,17140,17141,17142,17143,17144,17145,17146,17147,17148,17149,17150,17151,17152,17153,17154,17155,17156,17157,17158,17159,17160,17161,17162,17163,17164,17165,17166,17167,17168,17169,17170,17171,17172,17173,17174,17175,17176,17177,17178,17179,17180,17181,17182,17183,17184,17185,17186,17187,17188,17189,17190,17191,17192,17193,17194,17195,17196,17197,17198,17199,17200,17201,17202,17203,17204,17205,17206,17207,17208,17209,17210,17211,17212,17213,17214,17215,17216,17217,17218,17219,17220,17221,17222,17223,17224,17225,17226,17227,17228,17229,17230,17231,17232,17233,17234,17235,17236,17237,17238,17239,17240,17241,17242,17243,17244,17245,17246,17247,17248,17249,17250,17251,17252,17253,17254,17255,17256,17257,17258,17259,17260,17261,17262,17263,17264,17265,17266,17267,17268,17269,17270,17271,17272,17273,17274,17275,17276,17277,17278,17279,17280,17281,17282,17283,17284,17285,17286,17287,17288,17289,17290,17291,17292,17293,17294,17295,17296,17297,17298,17299,17300,17301,17302,17303,17304,17305,17306,17307,17308,17309,17310,17311,17312,17313,17314,17315,17316,17317,17318,17319,17320,17321,17322,17323,17324,17325,17326,17327,17328,17329,17330,17331,17332,17333,17334,17335,17336,17337,17338,17339,17340,17341,17342,17343,17344,17345,17346,17347,17348,17349,17350,17351,17352,17353,17354,17355,17356,17357,17358,17359,17360,17361,17362,17363,17364,17365,17366,17367,17368,17369,17370,17371,17372,17373,17374,17375,17376,17377,17378,17379,17380,17381,17382,17383,17384,17385,17386,17387,17388,17389,17390,17391,17392,17393,17394,17395,17396,17397,17398,17399,17400,17401,17402,17403,17404,17405,17406,17407,17408,17409,17410,17411,17412,17413,17414,17415,17416,17417,17418,17419,17420,17421,17422,17423,17424,17425,17426,17427,17428,17429,17430,17431,17432,17433,17434,17435,17436,17437,17438,17439,17440,17441,17442,17443,17444,17445,17446,17447,17448,17449,17450,17451,17452,17453,17454,17455,17456,17457,17458,17459,17460,17461,17462,17463,17464,17465,17466,17467,17468,17469,17470,17471,17472,17473,17474,17475,17476,17477,17478,17479,17480,17481,17482,17483,17484,17485,17486,17487,17488,17489,17490,17491,17492,17493,17494,17495,17496,17497,17498,17499,17500,17501,17502,17503,17504,17505,17506,17507,17508,17509,17510,17511,17512,17513,17514,17515,17516,17517,17518,17519,17520,17521,17522,17523,17524,17525,17526,17527,17528,17529,17530,17531,17532,17533,17534,17535,17536,17537,17538,17539,17540,17541,17542,17543,17544,17545,17546,17547,17548,17549,17550,17551,17552,17553,17554,17555,17556,17557,17558,17559,17560,17561,17562,17563,17564,17565,17566,17567,17568,17569,17570,17571,17572,17573,17574,17575,17576,17577,17578,17579,17580,17581,17582,17583,17584,17585,17586,17587,17588,17589,17590,17591,17592,17593,17594,17595,17596,17597,17598,17599,17600,17601,17602,17603,17604,17605,17606,17607,17608,17609,17610,17611,17612,17613,17614,17615,17616,17617,17618,17619,17620,17621,17622,17623,17624,17625,17626,17627,17628,17629,17630,17631,17632,17633,17634,17635,17636,17637,17638,17639,17640,17641,17642,17643,17644,17645,17646,17647,17648,17649,17650,17651,17652,17653,17654,17655,17656,17657,17658,17659,17660,17661,17662,17663,17664,17665,17666,17667,17668,17669,17670,17671,17672,17673,17674,17675,17676,17677,17678,17679,17680,17681,17682,17683,17684,17685,17686,17687,17688,17689,17690,17691,17692,17693,17694,17695,17696,17697,17698,17699,17700,17701,17702,17703,17704,17705,17706,17707,17708,17709,17710,17711,17712,17713,17714,17715,17716,17717,17718,17719,17720,17721,17722,17723,17724,17725,17726,17727,17728,17729,17730,17731,17732,17733,17734,17735,17736,17737,17738,17739,17740,17741,17742,17743,17744,17745,17746,17747,17748,17749,17750,17751,17752,17753,17754,17755,17756,17757,17758,17759,17760,17761,17762,17763,17764,17765,17766,17767,17768,17769,17770,17771,17772,17773,17774,17775,17776,17777,17778,17779,17780,17781,17782,17783,17784,17785,17786,17787,17788,17789,17790,17791,17792,17793,17794,17795,17796,17797,17798,17799,17800,17801,17802,17803,17804,17805,17806,17807,17808,17809,17810,17811,17812,17813,17814,17815,17816,17817,17818,17819,17820,17821,17822,17823,17824,17825,17826,17827,17828,17829,17830,17831,17832,17833,17834,17835,17836,17837,17838,17839,17840,17841,17842,17843,17844,17845,17846,17847,17848,17849,17850,17851,17852,17853,17854,17855,17856,17857,17858,17859,17860,17861,17862,17863,17864,17865,17866,17867,17868,17869,17870,17871,17872,17873,17874,17875,17876,17877,17878,17879,17880,17881,17882,17883,17884,17885,17886,17887,17888,17889,17890,17891,17892,17893,17894,17895,17896,17897,17898,17899,17900,17901,17902,17903,17904,17905,17906,17907,17908,17909,17910,17911,17912,17913,17914,17915,17916,17917,17918,17919,17920,17921,17922,17923,17924,17925,17926,17927,17928,17929,17930,17931,17932,17933,17934,17935,17936,17937,17938,17939,17940,17941,17942,17943,17944,17945,17946,17947,17948,17949,17950,17951,17952,17953,17954,17955,17956,17957,17958,17959,17960,17961,17962,17963,17964,17965,17966,17967,17968,17969,17970,17971,17972,17973,17974,17975,17976,17977,17978,17979,17980,17981,17982,17983,17984,17985,17986,17987,17988,17989,17990,17991,17992,17993,17994,17995,17996,17997,17998,17999,18000,18001,18002,18003,18004,18005,18006,18007,18008,18009,18010,18011,18012,18013,18014,18015,18016,18017,18018,18019,18020,18021,18022,18023,18024,18025,18026,18027,18028,18029,18030,18031,18032,18033,18034,18035,18036,18037,18038,18039,18040,18041,18042,18043,18044,18045,18046,18047,18048,18049,18050,18051,18052,18053,18054,18055,18056,18057,18058,18059,18060,18061,18062,18063,18064,18065,18066,18067,18068,18069,18070,18071,18072,18073,18074,18075,18076,18077,18078,18079,18080,18081,18082,18083,18084,18085,18086,18087,18088,18089,18090,18091,18092,18093,18094,18095,18096,18097,18098,18099,18100,18101,18102,18103,18104,18105,18106,18107,18108,18109,18110,18111,18112,18113,18114,18115,18116,18117,18118,18119,18120,18121,18122,18123,18124,18125,18126,18127,18128,18129,18130,18131,18132,18133,18134,18135,18136,18137,18138,18139,18140,18141,18142,18143,18144,18145,18146,18147,18148,18149,18150,18151,18152,18153,18154,18155,18156,18157,18158,18159,18160,18161,18162,18163,18164,18165,18166,18167,18168,18169,18170,18171,18172,18173,18174,18175,18176,18177,18178,18179,18180,18181,18182,18183,18184,18185,18186,18187,18188,18189,18190,18191,18192,18193,18194,18195,18196,18197,18198,18199,18200,18201,18202,18203,18204,18205,18206,18207,18208,18209,18210,18211,18212,18213,18214,18215,18216,18217,18218,18219,18220,18221,18222,18223,18224,18225,18226,18227,18228,18229,18230,18231,18232,18233,18234,18235,18236,18237,18238,18239,18240,18241,18242,18243,18244,18245,18246,18247,18248,18249,18250,18251,18252,18253,18254,18255,18256,18257,18258,18259,18260,18261,18262,18263,18264,18265,18266,18267,18268,18269,18270,18271,18272,18273,18274,18275,18276,18277,18278,18279,18280,18281,18282,18283,18284,18285,18286,18287,18288,18289,18290,18291,18292,18293,18294,18295,18296,18297,18298,18299,18300,18301,18302,18303,18304,18305,18306,18307,18308,18309,18310,18311,18312,18313,18314,18315,18316,18317,18318,18319,18320,18321,18322,18323,18324,18325,18326,18327,18328,18329,18330,18331,18332,18333,18334,18335,18336,18337,18338,18339,18340,18341,18342,18343,18344,18345,18346,18347,18348,18349,18350,18351,18352,18353,18354,18355,18356,18357,18358,18359,18360,18361,18362,18363,18364,18365,18366,18367,18368,18369,18370,18371,18372,18373,18374,18375,18376,18377,18378,18379,18380,18381,18382,18383,18384,18385,18386,18387,18388,18389,18390,18391,18392,18393,18394,18395,18396,18397,18398,18399,18400,18401,18402,18403,18404,18405,18406,18407,18408,18409,18410,18411,18412,18413,18414,18415,18416,18417,18418,18419,18420,18421,18422,18423,18424,18425,18426,18427,18428,18429,18430,18431,18432,18433,18434,18435,18436,18437,18438,18439,18440,18441,18442,18443,18444,18445,18446,18447,18448,18449,18450,18451,18452,18453,18454,18455,18456,18457,18458,18459,18460,18461,18462,18463,18464,18465,18466,18467,18468,18469,18470,18471,18472,18473,18474,18475,18476,18477,18478,18479,18480,18481,18482,18483,18484,18485,18486,18487,18488,18489,18490,18491,18492,18493,18494,18495,18496,18497,18498,18499,18500,18501,18502,18503,18504,18505,18506,18507,18508,18509,18510,18511,18512,18513,18514,18515,18516,18517,18518,18519,18520,18521,18522,18523,18524,18525,18526,18527,18528,18529,18530,18531,18532,18533,18534,18535,18536,18537,18538,18539,18540,18541,18542,18543,18544,18545,18546,18547,18548,18549,18550,18551,18552,18553,18554,18555,18556,18557,18558,18559,18560,18561,18562,18563,18564,18565,18566,18567,18568,18569,18570,18571,18572,18573,18574,18575,18576,18577,18578,18579,18580,18581,18582,18583,18584,18585,18586,18587,18588,18589,18590,18591,18592,18593,18594,18595,18596,18597,18598,18599,18600,18601,18602,18603,18604,18605,18606,18607,18608,18609,18610,18611,18612,18613,18614,18615,18616,18617,18618,18619,18620,18621,18622,18623,18624,18625,18626,18627,18628,18629,18630,18631,18632,18633,18634,18635,18636,18637,18638,18639,18640,18641,18642,18643,18644,18645,18646,18647,18648,18649,18650,18651,18652,18653,18654,18655,18656,18657,18658,18659,18660,18661,18662,18663,18664,18665,18666,18667,18668,18669,18670,18671,18672,18673,18674,18675,18676,18677,18678,18679,18680,18681,18682,18683,18684,18685,18686,18687,18688,18689,18690,18691,18692,18693,18694,18695,18696,18697,18698,18699,18700,18701,18702,18703,18704,18705,18706,18707,18708,18709,18710,18711,18712,18713,18714,18715,18716,18717,18718,18719,18720,18721,18722,18723,18724,18725,18726,18727,18728,18729,18730,18731,18732,18733,18734,18735,18736,18737,18738,18739,18740,18741,18742,18743,18744,18745,18746,18747,18748,18749,18750,18751,18752,18753,18754,18755,18756,18757,18758,18759,18760,18761,18762,18763,18764,18765,18766,18767,18768,18769,18770,18771,18772,18773,18774,18775,18776,18777,18778,18779,18780,18781,18782,18783,18784,18785,18786,18787,18788,18789,18790,18791,18792,18793,18794,18795,18796,18797,18798,18799,18800,18801,18802,18803,18804,18805,18806,18807,18808,18809,18810,18811,18812,18813,18814,18815,18816,18817,18818,18819,18820,18821,18822,18823,18824,18825,18826,18827,18828,18829,18830,18831,18832,18833,18834,18835,18836,18837,18838,18839,18840,18841,18842,18843,18844,18845,18846,18847,18848,18849,18850,18851,18852,18853,18854,18855,18856,18857,18858,18859,18860,18861,18862,18863,18864,18865,18866,18867,18868,18869,18870,18871,18872,18873,18874,18875,18876,18877,18878,18879,18880,18881,18882,18883,18884,18885,18886,18887,18888,18889,18890,18891,18892,18893,18894,18895,18896,18897,18898,18899,18900,18901,18902,18903,18904,18905,18906,18907,18908,18909,18910,18911,18912,18913,18914,18915,18916,18917,18918,18919,18920,18921,18922,18923,18924,18925,18926,18927,18928,18929,18930,18931,18932,18933,18934,18935,18936,18937,18938,18939,18940,18941,18942,18943,18944,18945,18946,18947,18948,18949,18950,18951,18952,18953,18954,18955,18956,18957,18958,18959,18960,18961,18962,18963,18964,18965,18966,18967,18968,18969,18970,18971,18972,18973,18974,18975,18976,18977,18978,18979,18980,18981,18982,18983,18984,18985,18986,18987,18988,18989,18990,18991,18992,18993,18994,18995,18996,18997,18998,18999,19000,19001,19002,19003,19004,19005,19006,19007,19008,19009,19010,19011,19012,19013,19014,19015,19016,19017,19018,19019,19020,19021,19022,19023,19024,19025,19026,19027,19028,19029,19030,19031,19032,19033,19034,19035,19036,19037,19038,19039,19040,19041,19042,19043,19044,19045,19046,19047,19048,19049,19050,19051,19052,19053,19054,19055,19056,19057,19058,19059,19060,19061,19062,19063,19064,19065,19066,19067,19068,19069,19070,19071,19072,19073,19074,19075,19076,19077,19078,19079,19080,19081,19082,19083,19084,19085,19086,19087,19088,19089,19090,19091,19092,19093,19094,19095,19096,19097,19098,19099,19100,19101,19102,19103,19104,19105,19106,19107,19108,19109,19110,19111,19112,19113,19114,19115,19116,19117,19118,19119,19120,19121,19122,19123,19124,19125,19126,19127,19128,19129,19130,19131,19132,19133,19134,19135,19136,19137,19138,19139,19140,19141,19142,19143,19144,19145,19146,19147,19148,19149,19150,19151,19152,19153,19154,19155,19156,19157,19158,19159,19160,19161,19162,19163,19164,19165,19166,19167,19168,19169,19170,19171,19172,19173,19174,19175,19176,19177,19178,19179,19180,19181,19182,19183,19184,19185,19186,19187,19188,19189,19190,19191,19192,19193,19194,19195,19196,19197,19198,19199,19200,19201,19202,19203,19204,19205,19206,19207,19208,19209,19210,19211,19212,19213,19214,19215,19216,19217,19218,19219,19220,19221,19222,19223,19224,19225,19226,19227,19228,19229,19230,19231,19232,19233,19234,19235,19236,19237,19238,19239,19240,19241,19242,19243,19244,19245,19246,19247,19248,19249,19250,19251,19252,19253,19254,19255,19256,19257,19258,19259,19260,19261,19262,19263,19264,19265,19266,19267,19268,19269,19270,19271,19272,19273,19274,19275,19276,19277,19278,19279,19280,19281,19282,19283,19284,19285,19286,19287,19288,19289,19290,19291,19292,19293,19294,19295,19296,19297,19298,19299,19300,19301,19302,19303,19304,19305,19306,19307,19308,19309,19310,19311,19312,19313,19314,19315,19316,19317,19318,19319,19320,19321,19322,19323,19324,19325,19326,19327,19328,19329,19330,19331,19332,19333,19334,19335,19336,19337,19338,19339,19340,19341,19342,19343,19344,19345,19346,19347,19348,19349,19350,19351,19352,19353,19354,19355,19356,19357,19358,19359,19360,19361,19362,19363,19364,19365,19366,19367,19368,19369,19370,19371,19372,19373,19374,19375,19376,19377,19378,19379,19380,19381,19382,19383,19384,19385,19386,19387,19388,19389,19390,19391,19392,19393,19394,19395,19396,19397,19398,19399,19400,19401,19402,19403,19404,19405,19406,19407,19408,19409,19410,19411,19412,19413,19414,19415,19416,19417,19418,19419,19420,19421,19422,19423,19424,19425,19426,19427,19428,19429,19430,19431,19432,19433,19434,19435,19436,19437,19438,19439,19440,19441,19442,19443,19444,19445,19446,19447,19448,19449,19450,19451,19452,19453,19454,19455,19456,19457,19458,19459,19460,19461,19462,19463,19464,19465,19466,19467,19468,19469,19470,19471,19472,19473,19474,19475,19476,19477,19478,19479,19480,19481,19482,19483,19484,19485,19486,19487,19488,19489,19490,19491,19492,19493,19494,19495,19496,19497,19498,19499,19500,19501,19502,19503,19504,19505,19506,19507,19508,19509,19510,19511,19512,19513,19514,19515,19516,19517,19518,19519,19520,19521,19522,19523,19524,19525,19526,19527,19528,19529,19530,19531,19532,19533,19534,19535,19536,19537,19538,19539,19540,19541,19542,19543,19544,19545,19546,19547,19548,19549,19550,19551,19552,19553,19554,19555,19556,19557,19558,19559,19560,19561,19562,19563,19564,19565,19566,19567,19568,19569,19570,19571,19572,19573,19574,19575,19576,19577,19578,19579,19580,19581,19582,19583,19584,19585,19586,19587,19588,19589,19590,19591,19592,19593,19594,19595,19596,19597,19598,19599,19600,19601,19602,19603,19604,19605,19606,19607,19608,19609,19610,19611,19612,19613,19614,19615,19616,19617,19618,19619,19620,19621,19622,19623,19624,19625,19626,19627,19628,19629,19630,19631,19632,19633,19634,19635,19636,19637,19638,19639,19640,19641,19642,19643,19644,19645,19646,19647,19648,19649,19650,19651,19652,19653,19654,19655,19656,19657,19658,19659,19660,19661,19662,19663,19664,19665,19666,19667,19668,19669,19670,19671,19672,19673,19674,19675,19676,19677,19678,19679,19680,19681,19682,19683,19684,19685,19686,19687,19688,19689,19690,19691,19692,19693,19694,19695,19696,19697,19698,19699,19700,19701,19702,19703,19704,19705,19706,19707,19708,19709,19710,19711,19712,19713,19714,19715,19716,19717,19718,19719,19720,19721,19722,19723,19724,19725,19726,19727,19728,19729,19730,19731,19732,19733,19734,19735,19736,19737,19738,19739,19740,19741,19742,19743,19744,19745,19746,19747,19748,19749,19750,19751,19752,19753,19754,19755,19756,19757,19758,19759,19760,19761,19762,19763,19764,19765,19766,19767,19768,19769,19770,19771,19772,19773,19774,19775,19776,19777,19778,19779,19780,19781,19782,19783,19784,19785,19786,19787,19788,19789,19790,19791,19792,19793,19794,19795,19796,19797,19798,19799,19800,19801,19802,19803,19804,19805,19806,19807,19808,19809,19810,19811,19812,19813,19814,19815,19816,19817,19818,19819,19820,19821,19822,19823,19824,19825,19826,19827,19828,19829,19830,19831,19832,19833,19834,19835,19836,19837,19838,19839,19840,19841,19842,19843,19844,19845,19846,19847,19848,19849,19850,19851,19852,19853,19854,19855,19856,19857,19858,19859,19860,19861,19862,19863,19864,19865,19866,19867,19868,19869,19870,19871,19872,19873,19874,19875,19876,19877,19878,19879,19880,19881,19882,19883,19884,19885,19886,19887,19888,19889,19890,19891,19892,19893,19968,19969,19970,19971,19972,19973,19974,19975,19976,19977,19978,19979,19980,19981,19982,19983,19984,19985,19986,19987,19988,19989,19990,19991,19992,19993,19994,19995,19996,19997,19998,19999,20000,20001,20002,20003,20004,20005,20006,20007,20008,20009,20010,20011,20012,20013,20014,20015,20016,20017,20018,20019,20020,20021,20022,20023,20024,20025,20026,20027,20028,20029,20030,20031,20032,20033,20034,20035,20036,20037,20038,20039,20040,20041,20042,20043,20044,20045,20046,20047,20048,20049,20050,20051,20052,20053,20054,20055,20056,20057,20058,20059,20060,20061,20062,20063,20064,20065,20066,20067,20068,20069,20070,20071,20072,20073,20074,20075,20076,20077,20078,20079,20080,20081,20082,20083,20084,20085,20086,20087,20088,20089,20090,20091,20092,20093,20094,20095,20096,20097,20098,20099,20100,20101,20102,20103,20104,20105,20106,20107,20108,20109,20110,20111,20112,20113,20114,20115,20116,20117,20118,20119,20120,20121,20122,20123,20124,20125,20126,20127,20128,20129,20130,20131,20132,20133,20134,20135,20136,20137,20138,20139,20140,20141,20142,20143,20144,20145,20146,20147,20148,20149,20150,20151,20152,20153,20154,20155,20156,20157,20158,20159,20160,20161,20162,20163,20164,20165,20166,20167,20168,20169,20170,20171,20172,20173,20174,20175,20176,20177,20178,20179,20180,20181,20182,20183,20184,20185,20186,20187,20188,20189,20190,20191,20192,20193,20194,20195,20196,20197,20198,20199,20200,20201,20202,20203,20204,20205,20206,20207,20208,20209,20210,20211,20212,20213,20214,20215,20216,20217,20218,20219,20220,20221,20222,20223,20224,20225,20226,20227,20228,20229,20230,20231,20232,20233,20234,20235,20236,20237,20238,20239,20240,20241,20242,20243,20244,20245,20246,20247,20248,20249,20250,20251,20252,20253,20254,20255,20256,20257,20258,20259,20260,20261,20262,20263,20264,20265,20266,20267,20268,20269,20270,20271,20272,20273,20274,20275,20276,20277,20278,20279,20280,20281,20282,20283,20284,20285,20286,20287,20288,20289,20290,20291,20292,20293,20294,20295,20296,20297,20298,20299,20300,20301,20302,20303,20304,20305,20306,20307,20308,20309,20310,20311,20312,20313,20314,20315,20316,20317,20318,20319,20320,20321,20322,20323,20324,20325,20326,20327,20328,20329,20330,20331,20332,20333,20334,20335,20336,20337,20338,20339,20340,20341,20342,20343,20344,20345,20346,20347,20348,20349,20350,20351,20352,20353,20354,20355,20356,20357,20358,20359,20360,20361,20362,20363,20364,20365,20366,20367,20368,20369,20370,20371,20372,20373,20374,20375,20376,20377,20378,20379,20380,20381,20382,20383,20384,20385,20386,20387,20388,20389,20390,20391,20392,20393,20394,20395,20396,20397,20398,20399,20400,20401,20402,20403,20404,20405,20406,20407,20408,20409,20410,20411,20412,20413,20414,20415,20416,20417,20418,20419,20420,20421,20422,20423,20424,20425,20426,20427,20428,20429,20430,20431,20432,20433,20434,20435,20436,20437,20438,20439,20440,20441,20442,20443,20444,20445,20446,20447,20448,20449,20450,20451,20452,20453,20454,20455,20456,20457,20458,20459,20460,20461,20462,20463,20464,20465,20466,20467,20468,20469,20470,20471,20472,20473,20474,20475,20476,20477,20478,20479,20480,20481,20482,20483,20484,20485,20486,20487,20488,20489,20490,20491,20492,20493,20494,20495,20496,20497,20498,20499,20500,20501,20502,20503,20504,20505,20506,20507,20508,20509,20510,20511,20512,20513,20514,20515,20516,20517,20518,20519,20520,20521,20522,20523,20524,20525,20526,20527,20528,20529,20530,20531,20532,20533,20534,20535,20536,20537,20538,20539,20540,20541,20542,20543,20544,20545,20546,20547,20548,20549,20550,20551,20552,20553,20554,20555,20556,20557,20558,20559,20560,20561,20562,20563,20564,20565,20566,20567,20568,20569,20570,20571,20572,20573,20574,20575,20576,20577,20578,20579,20580,20581,20582,20583,20584,20585,20586,20587,20588,20589,20590,20591,20592,20593,20594,20595,20596,20597,20598,20599,20600,20601,20602,20603,20604,20605,20606,20607,20608,20609,20610,20611,20612,20613,20614,20615,20616,20617,20618,20619,20620,20621,20622,20623,20624,20625,20626,20627,20628,20629,20630,20631,20632,20633,20634,20635,20636,20637,20638,20639,20640,20641,20642,20643,20644,20645,20646,20647,20648,20649,20650,20651,20652,20653,20654,20655,20656,20657,20658,20659,20660,20661,20662,20663,20664,20665,20666,20667,20668,20669,20670,20671,20672,20673,20674,20675,20676,20677,20678,20679,20680,20681,20682,20683,20684,20685,20686,20687,20688,20689,20690,20691,20692,20693,20694,20695,20696,20697,20698,20699,20700,20701,20702,20703,20704,20705,20706,20707,20708,20709,20710,20711,20712,20713,20714,20715,20716,20717,20718,20719,20720,20721,20722,20723,20724,20725,20726,20727,20728,20729,20730,20731,20732,20733,20734,20735,20736,20737,20738,20739,20740,20741,20742,20743,20744,20745,20746,20747,20748,20749,20750,20751,20752,20753,20754,20755,20756,20757,20758,20759,20760,20761,20762,20763,20764,20765,20766,20767,20768,20769,20770,20771,20772,20773,20774,20775,20776,20777,20778,20779,20780,20781,20782,20783,20784,20785,20786,20787,20788,20789,20790,20791,20792,20793,20794,20795,20796,20797,20798,20799,20800,20801,20802,20803,20804,20805,20806,20807,20808,20809,20810,20811,20812,20813,20814,20815,20816,20817,20818,20819,20820,20821,20822,20823,20824,20825,20826,20827,20828,20829,20830,20831,20832,20833,20834,20835,20836,20837,20838,20839,20840,20841,20842,20843,20844,20845,20846,20847,20848,20849,20850,20851,20852,20853,20854,20855,20856,20857,20858,20859,20860,20861,20862,20863,20864,20865,20866,20867,20868,20869,20870,20871,20872,20873,20874,20875,20876,20877,20878,20879,20880,20881,20882,20883,20884,20885,20886,20887,20888,20889,20890,20891,20892,20893,20894,20895,20896,20897,20898,20899,20900,20901,20902,20903,20904,20905,20906,20907,20908,20909,20910,20911,20912,20913,20914,20915,20916,20917,20918,20919,20920,20921,20922,20923,20924,20925,20926,20927,20928,20929,20930,20931,20932,20933,20934,20935,20936,20937,20938,20939,20940,20941,20942,20943,20944,20945,20946,20947,20948,20949,20950,20951,20952,20953,20954,20955,20956,20957,20958,20959,20960,20961,20962,20963,20964,20965,20966,20967,20968,20969,20970,20971,20972,20973,20974,20975,20976,20977,20978,20979,20980,20981,20982,20983,20984,20985,20986,20987,20988,20989,20990,20991,20992,20993,20994,20995,20996,20997,20998,20999,21000,21001,21002,21003,21004,21005,21006,21007,21008,21009,21010,21011,21012,21013,21014,21015,21016,21017,21018,21019,21020,21021,21022,21023,21024,21025,21026,21027,21028,21029,21030,21031,21032,21033,21034,21035,21036,21037,21038,21039,21040,21041,21042,21043,21044,21045,21046,21047,21048,21049,21050,21051,21052,21053,21054,21055,21056,21057,21058,21059,21060,21061,21062,21063,21064,21065,21066,21067,21068,21069,21070,21071,21072,21073,21074,21075,21076,21077,21078,21079,21080,21081,21082,21083,21084,21085,21086,21087,21088,21089,21090,21091,21092,21093,21094,21095,21096,21097,21098,21099,21100,21101,21102,21103,21104,21105,21106,21107,21108,21109,21110,21111,21112,21113,21114,21115,21116,21117,21118,21119,21120,21121,21122,21123,21124,21125,21126,21127,21128,21129,21130,21131,21132,21133,21134,21135,21136,21137,21138,21139,21140,21141,21142,21143,21144,21145,21146,21147,21148,21149,21150,21151,21152,21153,21154,21155,21156,21157,21158,21159,21160,21161,21162,21163,21164,21165,21166,21167,21168,21169,21170,21171,21172,21173,21174,21175,21176,21177,21178,21179,21180,21181,21182,21183,21184,21185,21186,21187,21188,21189,21190,21191,21192,21193,21194,21195,21196,21197,21198,21199,21200,21201,21202,21203,21204,21205,21206,21207,21208,21209,21210,21211,21212,21213,21214,21215,21216,21217,21218,21219,21220,21221,21222,21223,21224,21225,21226,21227,21228,21229,21230,21231,21232,21233,21234,21235,21236,21237,21238,21239,21240,21241,21242,21243,21244,21245,21246,21247,21248,21249,21250,21251,21252,21253,21254,21255,21256,21257,21258,21259,21260,21261,21262,21263,21264,21265,21266,21267,21268,21269,21270,21271,21272,21273,21274,21275,21276,21277,21278,21279,21280,21281,21282,21283,21284,21285,21286,21287,21288,21289,21290,21291,21292,21293,21294,21295,21296,21297,21298,21299,21300,21301,21302,21303,21304,21305,21306,21307,21308,21309,21310,21311,21312,21313,21314,21315,21316,21317,21318,21319,21320,21321,21322,21323,21324,21325,21326,21327,21328,21329,21330,21331,21332,21333,21334,21335,21336,21337,21338,21339,21340,21341,21342,21343,21344,21345,21346,21347,21348,21349,21350,21351,21352,21353,21354,21355,21356,21357,21358,21359,21360,21361,21362,21363,21364,21365,21366,21367,21368,21369,21370,21371,21372,21373,21374,21375,21376,21377,21378,21379,21380,21381,21382,21383,21384,21385,21386,21387,21388,21389,21390,21391,21392,21393,21394,21395,21396,21397,21398,21399,21400,21401,21402,21403,21404,21405,21406,21407,21408,21409,21410,21411,21412,21413,21414,21415,21416,21417,21418,21419,21420,21421,21422,21423,21424,21425,21426,21427,21428,21429,21430,21431,21432,21433,21434,21435,21436,21437,21438,21439,21440,21441,21442,21443,21444,21445,21446,21447,21448,21449,21450,21451,21452,21453,21454,21455,21456,21457,21458,21459,21460,21461,21462,21463,21464,21465,21466,21467,21468,21469,21470,21471,21472,21473,21474,21475,21476,21477,21478,21479,21480,21481,21482,21483,21484,21485,21486,21487,21488,21489,21490,21491,21492,21493,21494,21495,21496,21497,21498,21499,21500,21501,21502,21503,21504,21505,21506,21507,21508,21509,21510,21511,21512,21513,21514,21515,21516,21517,21518,21519,21520,21521,21522,21523,21524,21525,21526,21527,21528,21529,21530,21531,21532,21533,21534,21535,21536,21537,21538,21539,21540,21541,21542,21543,21544,21545,21546,21547,21548,21549,21550,21551,21552,21553,21554,21555,21556,21557,21558,21559,21560,21561,21562,21563,21564,21565,21566,21567,21568,21569,21570,21571,21572,21573,21574,21575,21576,21577,21578,21579,21580,21581,21582,21583,21584,21585,21586,21587,21588,21589,21590,21591,21592,21593,21594,21595,21596,21597,21598,21599,21600,21601,21602,21603,21604,21605,21606,21607,21608,21609,21610,21611,21612,21613,21614,21615,21616,21617,21618,21619,21620,21621,21622,21623,21624,21625,21626,21627,21628,21629,21630,21631,21632,21633,21634,21635,21636,21637,21638,21639,21640,21641,21642,21643,21644,21645,21646,21647,21648,21649,21650,21651,21652,21653,21654,21655,21656,21657,21658,21659,21660,21661,21662,21663,21664,21665,21666,21667,21668,21669,21670,21671,21672,21673,21674,21675,21676,21677,21678,21679,21680,21681,21682,21683,21684,21685,21686,21687,21688,21689,21690,21691,21692,21693,21694,21695,21696,21697,21698,21699,21700,21701,21702,21703,21704,21705,21706,21707,21708,21709,21710,21711,21712,21713,21714,21715,21716,21717,21718,21719,21720,21721,21722,21723,21724,21725,21726,21727,21728,21729,21730,21731,21732,21733,21734,21735,21736,21737,21738,21739,21740,21741,21742,21743,21744,21745,21746,21747,21748,21749,21750,21751,21752,21753,21754,21755,21756,21757,21758,21759,21760,21761,21762,21763,21764,21765,21766,21767,21768,21769,21770,21771,21772,21773,21774,21775,21776,21777,21778,21779,21780,21781,21782,21783,21784,21785,21786,21787,21788,21789,21790,21791,21792,21793,21794,21795,21796,21797,21798,21799,21800,21801,21802,21803,21804,21805,21806,21807,21808,21809,21810,21811,21812,21813,21814,21815,21816,21817,21818,21819,21820,21821,21822,21823,21824,21825,21826,21827,21828,21829,21830,21831,21832,21833,21834,21835,21836,21837,21838,21839,21840,21841,21842,21843,21844,21845,21846,21847,21848,21849,21850,21851,21852,21853,21854,21855,21856,21857,21858,21859,21860,21861,21862,21863,21864,21865,21866,21867,21868,21869,21870,21871,21872,21873,21874,21875,21876,21877,21878,21879,21880,21881,21882,21883,21884,21885,21886,21887,21888,21889,21890,21891,21892,21893,21894,21895,21896,21897,21898,21899,21900,21901,21902,21903,21904,21905,21906,21907,21908,21909,21910,21911,21912,21913,21914,21915,21916,21917,21918,21919,21920,21921,21922,21923,21924,21925,21926,21927,21928,21929,21930,21931,21932,21933,21934,21935,21936,21937,21938,21939,21940,21941,21942,21943,21944,21945,21946,21947,21948,21949,21950,21951,21952,21953,21954,21955,21956,21957,21958,21959,21960,21961,21962,21963,21964,21965,21966,21967,21968,21969,21970,21971,21972,21973,21974,21975,21976,21977,21978,21979,21980,21981,21982,21983,21984,21985,21986,21987,21988,21989,21990,21991,21992,21993,21994,21995,21996,21997,21998,21999,22000,22001,22002,22003,22004,22005,22006,22007,22008,22009,22010,22011,22012,22013,22014,22015,22016,22017,22018,22019,22020,22021,22022,22023,22024,22025,22026,22027,22028,22029,22030,22031,22032,22033,22034,22035,22036,22037,22038,22039,22040,22041,22042,22043,22044,22045,22046,22047,22048,22049,22050,22051,22052,22053,22054,22055,22056,22057,22058,22059,22060,22061,22062,22063,22064,22065,22066,22067,22068,22069,22070,22071,22072,22073,22074,22075,22076,22077,22078,22079,22080,22081,22082,22083,22084,22085,22086,22087,22088,22089,22090,22091,22092,22093,22094,22095,22096,22097,22098,22099,22100,22101,22102,22103,22104,22105,22106,22107,22108,22109,22110,22111,22112,22113,22114,22115,22116,22117,22118,22119,22120,22121,22122,22123,22124,22125,22126,22127,22128,22129,22130,22131,22132,22133,22134,22135,22136,22137,22138,22139,22140,22141,22142,22143,22144,22145,22146,22147,22148,22149,22150,22151,22152,22153,22154,22155,22156,22157,22158,22159,22160,22161,22162,22163,22164,22165,22166,22167,22168,22169,22170,22171,22172,22173,22174,22175,22176,22177,22178,22179,22180,22181,22182,22183,22184,22185,22186,22187,22188,22189,22190,22191,22192,22193,22194,22195,22196,22197,22198,22199,22200,22201,22202,22203,22204,22205,22206,22207,22208,22209,22210,22211,22212,22213,22214,22215,22216,22217,22218,22219,22220,22221,22222,22223,22224,22225,22226,22227,22228,22229,22230,22231,22232,22233,22234,22235,22236,22237,22238,22239,22240,22241,22242,22243,22244,22245,22246,22247,22248,22249,22250,22251,22252,22253,22254,22255,22256,22257,22258,22259,22260,22261,22262,22263,22264,22265,22266,22267,22268,22269,22270,22271,22272,22273,22274,22275,22276,22277,22278,22279,22280,22281,22282,22283,22284,22285,22286,22287,22288,22289,22290,22291,22292,22293,22294,22295,22296,22297,22298,22299,22300,22301,22302,22303,22304,22305,22306,22307,22308,22309,22310,22311,22312,22313,22314,22315,22316,22317,22318,22319,22320,22321,22322,22323,22324,22325,22326,22327,22328,22329,22330,22331,22332,22333,22334,22335,22336,22337,22338,22339,22340,22341,22342,22343,22344,22345,22346,22347,22348,22349,22350,22351,22352,22353,22354,22355,22356,22357,22358,22359,22360,22361,22362,22363,22364,22365,22366,22367,22368,22369,22370,22371,22372,22373,22374,22375,22376,22377,22378,22379,22380,22381,22382,22383,22384,22385,22386,22387,22388,22389,22390,22391,22392,22393,22394,22395,22396,22397,22398,22399,22400,22401,22402,22403,22404,22405,22406,22407,22408,22409,22410,22411,22412,22413,22414,22415,22416,22417,22418,22419,22420,22421,22422,22423,22424,22425,22426,22427,22428,22429,22430,22431,22432,22433,22434,22435,22436,22437,22438,22439,22440,22441,22442,22443,22444,22445,22446,22447,22448,22449,22450,22451,22452,22453,22454,22455,22456,22457,22458,22459,22460,22461,22462,22463,22464,22465,22466,22467,22468,22469,22470,22471,22472,22473,22474,22475,22476,22477,22478,22479,22480,22481,22482,22483,22484,22485,22486,22487,22488,22489,22490,22491,22492,22493,22494,22495,22496,22497,22498,22499,22500,22501,22502,22503,22504,22505,22506,22507,22508,22509,22510,22511,22512,22513,22514,22515,22516,22517,22518,22519,22520,22521,22522,22523,22524,22525,22526,22527,22528,22529,22530,22531,22532,22533,22534,22535,22536,22537,22538,22539,22540,22541,22542,22543,22544,22545,22546,22547,22548,22549,22550,22551,22552,22553,22554,22555,22556,22557,22558,22559,22560,22561,22562,22563,22564,22565,22566,22567,22568,22569,22570,22571,22572,22573,22574,22575,22576,22577,22578,22579,22580,22581,22582,22583,22584,22585,22586,22587,22588,22589,22590,22591,22592,22593,22594,22595,22596,22597,22598,22599,22600,22601,22602,22603,22604,22605,22606,22607,22608,22609,22610,22611,22612,22613,22614,22615,22616,22617,22618,22619,22620,22621,22622,22623,22624,22625,22626,22627,22628,22629,22630,22631,22632,22633,22634,22635,22636,22637,22638,22639,22640,22641,22642,22643,22644,22645,22646,22647,22648,22649,22650,22651,22652,22653,22654,22655,22656,22657,22658,22659,22660,22661,22662,22663,22664,22665,22666,22667,22668,22669,22670,22671,22672,22673,22674,22675,22676,22677,22678,22679,22680,22681,22682,22683,22684,22685,22686,22687,22688,22689,22690,22691,22692,22693,22694,22695,22696,22697,22698,22699,22700,22701,22702,22703,22704,22705,22706,22707,22708,22709,22710,22711,22712,22713,22714,22715,22716,22717,22718,22719,22720,22721,22722,22723,22724,22725,22726,22727,22728,22729,22730,22731,22732,22733,22734,22735,22736,22737,22738,22739,22740,22741,22742,22743,22744,22745,22746,22747,22748,22749,22750,22751,22752,22753,22754,22755,22756,22757,22758,22759,22760,22761,22762,22763,22764,22765,22766,22767,22768,22769,22770,22771,22772,22773,22774,22775,22776,22777,22778,22779,22780,22781,22782,22783,22784,22785,22786,22787,22788,22789,22790,22791,22792,22793,22794,22795,22796,22797,22798,22799,22800,22801,22802,22803,22804,22805,22806,22807,22808,22809,22810,22811,22812,22813,22814,22815,22816,22817,22818,22819,22820,22821,22822,22823,22824,22825,22826,22827,22828,22829,22830,22831,22832,22833,22834,22835,22836,22837,22838,22839,22840,22841,22842,22843,22844,22845,22846,22847,22848,22849,22850,22851,22852,22853,22854,22855,22856,22857,22858,22859,22860,22861,22862,22863,22864,22865,22866,22867,22868,22869,22870,22871,22872,22873,22874,22875,22876,22877,22878,22879,22880,22881,22882,22883,22884,22885,22886,22887,22888,22889,22890,22891,22892,22893,22894,22895,22896,22897,22898,22899,22900,22901,22902,22903,22904,22905,22906,22907,22908,22909,22910,22911,22912,22913,22914,22915,22916,22917,22918,22919,22920,22921,22922,22923,22924,22925,22926,22927,22928,22929,22930,22931,22932,22933,22934,22935,22936,22937,22938,22939,22940,22941,22942,22943,22944,22945,22946,22947,22948,22949,22950,22951,22952,22953,22954,22955,22956,22957,22958,22959,22960,22961,22962,22963,22964,22965,22966,22967,22968,22969,22970,22971,22972,22973,22974,22975,22976,22977,22978,22979,22980,22981,22982,22983,22984,22985,22986,22987,22988,22989,22990,22991,22992,22993,22994,22995,22996,22997,22998,22999,23000,23001,23002,23003,23004,23005,23006,23007,23008,23009,23010,23011,23012,23013,23014,23015,23016,23017,23018,23019,23020,23021,23022,23023,23024,23025,23026,23027,23028,23029,23030,23031,23032,23033,23034,23035,23036,23037,23038,23039,23040,23041,23042,23043,23044,23045,23046,23047,23048,23049,23050,23051,23052,23053,23054,23055,23056,23057,23058,23059,23060,23061,23062,23063,23064,23065,23066,23067,23068,23069,23070,23071,23072,23073,23074,23075,23076,23077,23078,23079,23080,23081,23082,23083,23084,23085,23086,23087,23088,23089,23090,23091,23092,23093,23094,23095,23096,23097,23098,23099,23100,23101,23102,23103,23104,23105,23106,23107,23108,23109,23110,23111,23112,23113,23114,23115,23116,23117,23118,23119,23120,23121,23122,23123,23124,23125,23126,23127,23128,23129,23130,23131,23132,23133,23134,23135,23136,23137,23138,23139,23140,23141,23142,23143,23144,23145,23146,23147,23148,23149,23150,23151,23152,23153,23154,23155,23156,23157,23158,23159,23160,23161,23162,23163,23164,23165,23166,23167,23168,23169,23170,23171,23172,23173,23174,23175,23176,23177,23178,23179,23180,23181,23182,23183,23184,23185,23186,23187,23188,23189,23190,23191,23192,23193,23194,23195,23196,23197,23198,23199,23200,23201,23202,23203,23204,23205,23206,23207,23208,23209,23210,23211,23212,23213,23214,23215,23216,23217,23218,23219,23220,23221,23222,23223,23224,23225,23226,23227,23228,23229,23230,23231,23232,23233,23234,23235,23236,23237,23238,23239,23240,23241,23242,23243,23244,23245,23246,23247,23248,23249,23250,23251,23252,23253,23254,23255,23256,23257,23258,23259,23260,23261,23262,23263,23264,23265,23266,23267,23268,23269,23270,23271,23272,23273,23274,23275,23276,23277,23278,23279,23280,23281,23282,23283,23284,23285,23286,23287,23288,23289,23290,23291,23292,23293,23294,23295,23296,23297,23298,23299,23300,23301,23302,23303,23304,23305,23306,23307,23308,23309,23310,23311,23312,23313,23314,23315,23316,23317,23318,23319,23320,23321,23322,23323,23324,23325,23326,23327,23328,23329,23330,23331,23332,23333,23334,23335,23336,23337,23338,23339,23340,23341,23342,23343,23344,23345,23346,23347,23348,23349,23350,23351,23352,23353,23354,23355,23356,23357,23358,23359,23360,23361,23362,23363,23364,23365,23366,23367,23368,23369,23370,23371,23372,23373,23374,23375,23376,23377,23378,23379,23380,23381,23382,23383,23384,23385,23386,23387,23388,23389,23390,23391,23392,23393,23394,23395,23396,23397,23398,23399,23400,23401,23402,23403,23404,23405,23406,23407,23408,23409,23410,23411,23412,23413,23414,23415,23416,23417,23418,23419,23420,23421,23422,23423,23424,23425,23426,23427,23428,23429,23430,23431,23432,23433,23434,23435,23436,23437,23438,23439,23440,23441,23442,23443,23444,23445,23446,23447,23448,23449,23450,23451,23452,23453,23454,23455,23456,23457,23458,23459,23460,23461,23462,23463,23464,23465,23466,23467,23468,23469,23470,23471,23472,23473,23474,23475,23476,23477,23478,23479,23480,23481,23482,23483,23484,23485,23486,23487,23488,23489,23490,23491,23492,23493,23494,23495,23496,23497,23498,23499,23500,23501,23502,23503,23504,23505,23506,23507,23508,23509,23510,23511,23512,23513,23514,23515,23516,23517,23518,23519,23520,23521,23522,23523,23524,23525,23526,23527,23528,23529,23530,23531,23532,23533,23534,23535,23536,23537,23538,23539,23540,23541,23542,23543,23544,23545,23546,23547,23548,23549,23550,23551,23552,23553,23554,23555,23556,23557,23558,23559,23560,23561,23562,23563,23564,23565,23566,23567,23568,23569,23570,23571,23572,23573,23574,23575,23576,23577,23578,23579,23580,23581,23582,23583,23584,23585,23586,23587,23588,23589,23590,23591,23592,23593,23594,23595,23596,23597,23598,23599,23600,23601,23602,23603,23604,23605,23606,23607,23608,23609,23610,23611,23612,23613,23614,23615,23616,23617,23618,23619,23620,23621,23622,23623,23624,23625,23626,23627,23628,23629,23630,23631,23632,23633,23634,23635,23636,23637,23638,23639,23640,23641,23642,23643,23644,23645,23646,23647,23648,23649,23650,23651,23652,23653,23654,23655,23656,23657,23658,23659,23660,23661,23662,23663,23664,23665,23666,23667,23668,23669,23670,23671,23672,23673,23674,23675,23676,23677,23678,23679,23680,23681,23682,23683,23684,23685,23686,23687,23688,23689,23690,23691,23692,23693,23694,23695,23696,23697,23698,23699,23700,23701,23702,23703,23704,23705,23706,23707,23708,23709,23710,23711,23712,23713,23714,23715,23716,23717,23718,23719,23720,23721,23722,23723,23724,23725,23726,23727,23728,23729,23730,23731,23732,23733,23734,23735,23736,23737,23738,23739,23740,23741,23742,23743,23744,23745,23746,23747,23748,23749,23750,23751,23752,23753,23754,23755,23756,23757,23758,23759,23760,23761,23762,23763,23764,23765,23766,23767,23768,23769,23770,23771,23772,23773,23774,23775,23776,23777,23778,23779,23780,23781,23782,23783,23784,23785,23786,23787,23788,23789,23790,23791,23792,23793,23794,23795,23796,23797,23798,23799,23800,23801,23802,23803,23804,23805,23806,23807,23808,23809,23810,23811,23812,23813,23814,23815,23816,23817,23818,23819,23820,23821,23822,23823,23824,23825,23826,23827,23828,23829,23830,23831,23832,23833,23834,23835,23836,23837,23838,23839,23840,23841,23842,23843,23844,23845,23846,23847,23848,23849,23850,23851,23852,23853,23854,23855,23856,23857,23858,23859,23860,23861,23862,23863,23864,23865,23866,23867,23868,23869,23870,23871,23872,23873,23874,23875,23876,23877,23878,23879,23880,23881,23882,23883,23884,23885,23886,23887,23888,23889,23890,23891,23892,23893,23894,23895,23896,23897,23898,23899,23900,23901,23902,23903,23904,23905,23906,23907,23908,23909,23910,23911,23912,23913,23914,23915,23916,23917,23918,23919,23920,23921,23922,23923,23924,23925,23926,23927,23928,23929,23930,23931,23932,23933,23934,23935,23936,23937,23938,23939,23940,23941,23942,23943,23944,23945,23946,23947,23948,23949,23950,23951,23952,23953,23954,23955,23956,23957,23958,23959,23960,23961,23962,23963,23964,23965,23966,23967,23968,23969,23970,23971,23972,23973,23974,23975,23976,23977,23978,23979,23980,23981,23982,23983,23984,23985,23986,23987,23988,23989,23990,23991,23992,23993,23994,23995,23996,23997,23998,23999,24000,24001,24002,24003,24004,24005,24006,24007,24008,24009,24010,24011,24012,24013,24014,24015,24016,24017,24018,24019,24020,24021,24022,24023,24024,24025,24026,24027,24028,24029,24030,24031,24032,24033,24034,24035,24036,24037,24038,24039,24040,24041,24042,24043,24044,24045,24046,24047,24048,24049,24050,24051,24052,24053,24054,24055,24056,24057,24058,24059,24060,24061,24062,24063,24064,24065,24066,24067,24068,24069,24070,24071,24072,24073,24074,24075,24076,24077,24078,24079,24080,24081,24082,24083,24084,24085,24086,24087,24088,24089,24090,24091,24092,24093,24094,24095,24096,24097,24098,24099,24100,24101,24102,24103,24104,24105,24106,24107,24108,24109,24110,24111,24112,24113,24114,24115,24116,24117,24118,24119,24120,24121,24122,24123,24124,24125,24126,24127,24128,24129,24130,24131,24132,24133,24134,24135,24136,24137,24138,24139,24140,24141,24142,24143,24144,24145,24146,24147,24148,24149,24150,24151,24152,24153,24154,24155,24156,24157,24158,24159,24160,24161,24162,24163,24164,24165,24166,24167,24168,24169,24170,24171,24172,24173,24174,24175,24176,24177,24178,24179,24180,24181,24182,24183,24184,24185,24186,24187,24188,24189,24190,24191,24192,24193,24194,24195,24196,24197,24198,24199,24200,24201,24202,24203,24204,24205,24206,24207,24208,24209,24210,24211,24212,24213,24214,24215,24216,24217,24218,24219,24220,24221,24222,24223,24224,24225,24226,24227,24228,24229,24230,24231,24232,24233,24234,24235,24236,24237,24238,24239,24240,24241,24242,24243,24244,24245,24246,24247,24248,24249,24250,24251,24252,24253,24254,24255,24256,24257,24258,24259,24260,24261,24262,24263,24264,24265,24266,24267,24268,24269,24270,24271,24272,24273,24274,24275,24276,24277,24278,24279,24280,24281,24282,24283,24284,24285,24286,24287,24288,24289,24290,24291,24292,24293,24294,24295,24296,24297,24298,24299,24300,24301,24302,24303,24304,24305,24306,24307,24308,24309,24310,24311,24312,24313,24314,24315,24316,24317,24318,24319,24320,24321,24322,24323,24324,24325,24326,24327,24328,24329,24330,24331,24332,24333,24334,24335,24336,24337,24338,24339,24340,24341,24342,24343,24344,24345,24346,24347,24348,24349,24350,24351,24352,24353,24354,24355,24356,24357,24358,24359,24360,24361,24362,24363,24364,24365,24366,24367,24368,24369,24370,24371,24372,24373,24374,24375,24376,24377,24378,24379,24380,24381,24382,24383,24384,24385,24386,24387,24388,24389,24390,24391,24392,24393,24394,24395,24396,24397,24398,24399,24400,24401,24402,24403,24404,24405,24406,24407,24408,24409,24410,24411,24412,24413,24414,24415,24416,24417,24418,24419,24420,24421,24422,24423,24424,24425,24426,24427,24428,24429,24430,24431,24432,24433,24434,24435,24436,24437,24438,24439,24440,24441,24442,24443,24444,24445,24446,24447,24448,24449,24450,24451,24452,24453,24454,24455,24456,24457,24458,24459,24460,24461,24462,24463,24464,24465,24466,24467,24468,24469,24470,24471,24472,24473,24474,24475,24476,24477,24478,24479,24480,24481,24482,24483,24484,24485,24486,24487,24488,24489,24490,24491,24492,24493,24494,24495,24496,24497,24498,24499,24500,24501,24502,24503,24504,24505,24506,24507,24508,24509,24510,24511,24512,24513,24514,24515,24516,24517,24518,24519,24520,24521,24522,24523,24524,24525,24526,24527,24528,24529,24530,24531,24532,24533,24534,24535,24536,24537,24538,24539,24540,24541,24542,24543,24544,24545,24546,24547,24548,24549,24550,24551,24552,24553,24554,24555,24556,24557,24558,24559,24560,24561,24562,24563,24564,24565,24566,24567,24568,24569,24570,24571,24572,24573,24574,24575,24576,24577,24578,24579,24580,24581,24582,24583,24584,24585,24586,24587,24588,24589,24590,24591,24592,24593,24594,24595,24596,24597,24598,24599,24600,24601,24602,24603,24604,24605,24606,24607,24608,24609,24610,24611,24612,24613,24614,24615,24616,24617,24618,24619,24620,24621,24622,24623,24624,24625,24626,24627,24628,24629,24630,24631,24632,24633,24634,24635,24636,24637,24638,24639,24640,24641,24642,24643,24644,24645,24646,24647,24648,24649,24650,24651,24652,24653,24654,24655,24656,24657,24658,24659,24660,24661,24662,24663,24664,24665,24666,24667,24668,24669,24670,24671,24672,24673,24674,24675,24676,24677,24678,24679,24680,24681,24682,24683,24684,24685,24686,24687,24688,24689,24690,24691,24692,24693,24694,24695,24696,24697,24698,24699,24700,24701,24702,24703,24704,24705,24706,24707,24708,24709,24710,24711,24712,24713,24714,24715,24716,24717,24718,24719,24720,24721,24722,24723,24724,24725,24726,24727,24728,24729,24730,24731,24732,24733,24734,24735,24736,24737,24738,24739,24740,24741,24742,24743,24744,24745,24746,24747,24748,24749,24750,24751,24752,24753,24754,24755,24756,24757,24758,24759,24760,24761,24762,24763,24764,24765,24766,24767,24768,24769,24770,24771,24772,24773,24774,24775,24776,24777,24778,24779,24780,24781,24782,24783,24784,24785,24786,24787,24788,24789,24790,24791,24792,24793,24794,24795,24796,24797,24798,24799,24800,24801,24802,24803,24804,24805,24806,24807,24808,24809,24810,24811,24812,24813,24814,24815,24816,24817,24818,24819,24820,24821,24822,24823,24824,24825,24826,24827,24828,24829,24830,24831,24832,24833,24834,24835,24836,24837,24838,24839,24840,24841,24842,24843,24844,24845,24846,24847,24848,24849,24850,24851,24852,24853,24854,24855,24856,24857,24858,24859,24860,24861,24862,24863,24864,24865,24866,24867,24868,24869,24870,24871,24872,24873,24874,24875,24876,24877,24878,24879,24880,24881,24882,24883,24884,24885,24886,24887,24888,24889,24890,24891,24892,24893,24894,24895,24896,24897,24898,24899,24900,24901,24902,24903,24904,24905,24906,24907,24908,24909,24910,24911,24912,24913,24914,24915,24916,24917,24918,24919,24920,24921,24922,24923,24924,24925,24926,24927,24928,24929,24930,24931,24932,24933,24934,24935,24936,24937,24938,24939,24940,24941,24942,24943,24944,24945,24946,24947,24948,24949,24950,24951,24952,24953,24954,24955,24956,24957,24958,24959,24960,24961,24962,24963,24964,24965,24966,24967,24968,24969,24970,24971,24972,24973,24974,24975,24976,24977,24978,24979,24980,24981,24982,24983,24984,24985,24986,24987,24988,24989,24990,24991,24992,24993,24994,24995,24996,24997,24998,24999,25000,25001,25002,25003,25004,25005,25006,25007,25008,25009,25010,25011,25012,25013,25014,25015,25016,25017,25018,25019,25020,25021,25022,25023,25024,25025,25026,25027,25028,25029,25030,25031,25032,25033,25034,25035,25036,25037,25038,25039,25040,25041,25042,25043,25044,25045,25046,25047,25048,25049,25050,25051,25052,25053,25054,25055,25056,25057,25058,25059,25060,25061,25062,25063,25064,25065,25066,25067,25068,25069,25070,25071,25072,25073,25074,25075,25076,25077,25078,25079,25080,25081,25082,25083,25084,25085,25086,25087,25088,25089,25090,25091,25092,25093,25094,25095,25096,25097,25098,25099,25100,25101,25102,25103,25104,25105,25106,25107,25108,25109,25110,25111,25112,25113,25114,25115,25116,25117,25118,25119,25120,25121,25122,25123,25124,25125,25126,25127,25128,25129,25130,25131,25132,25133,25134,25135,25136,25137,25138,25139,25140,25141,25142,25143,25144,25145,25146,25147,25148,25149,25150,25151,25152,25153,25154,25155,25156,25157,25158,25159,25160,25161,25162,25163,25164,25165,25166,25167,25168,25169,25170,25171,25172,25173,25174,25175,25176,25177,25178,25179,25180,25181,25182,25183,25184,25185,25186,25187,25188,25189,25190,25191,25192,25193,25194,25195,25196,25197,25198,25199,25200,25201,25202,25203,25204,25205,25206,25207,25208,25209,25210,25211,25212,25213,25214,25215,25216,25217,25218,25219,25220,25221,25222,25223,25224,25225,25226,25227,25228,25229,25230,25231,25232,25233,25234,25235,25236,25237,25238,25239,25240,25241,25242,25243,25244,25245,25246,25247,25248,25249,25250,25251,25252,25253,25254,25255,25256,25257,25258,25259,25260,25261,25262,25263,25264,25265,25266,25267,25268,25269,25270,25271,25272,25273,25274,25275,25276,25277,25278,25279,25280,25281,25282,25283,25284,25285,25286,25287,25288,25289,25290,25291,25292,25293,25294,25295,25296,25297,25298,25299,25300,25301,25302,25303,25304,25305,25306,25307,25308,25309,25310,25311,25312,25313,25314,25315,25316,25317,25318,25319,25320,25321,25322,25323,25324,25325,25326,25327,25328,25329,25330,25331,25332,25333,25334,25335,25336,25337,25338,25339,25340,25341,25342,25343,25344,25345,25346,25347,25348,25349,25350,25351,25352,25353,25354,25355,25356,25357,25358,25359,25360,25361,25362,25363,25364,25365,25366,25367,25368,25369,25370,25371,25372,25373,25374,25375,25376,25377,25378,25379,25380,25381,25382,25383,25384,25385,25386,25387,25388,25389,25390,25391,25392,25393,25394,25395,25396,25397,25398,25399,25400,25401,25402,25403,25404,25405,25406,25407,25408,25409,25410,25411,25412,25413,25414,25415,25416,25417,25418,25419,25420,25421,25422,25423,25424,25425,25426,25427,25428,25429,25430,25431,25432,25433,25434,25435,25436,25437,25438,25439,25440,25441,25442,25443,25444,25445,25446,25447,25448,25449,25450,25451,25452,25453,25454,25455,25456,25457,25458,25459,25460,25461,25462,25463,25464,25465,25466,25467,25468,25469,25470,25471,25472,25473,25474,25475,25476,25477,25478,25479,25480,25481,25482,25483,25484,25485,25486,25487,25488,25489,25490,25491,25492,25493,25494,25495,25496,25497,25498,25499,25500,25501,25502,25503,25504,25505,25506,25507,25508,25509,25510,25511,25512,25513,25514,25515,25516,25517,25518,25519,25520,25521,25522,25523,25524,25525,25526,25527,25528,25529,25530,25531,25532,25533,25534,25535,25536,25537,25538,25539,25540,25541,25542,25543,25544,25545,25546,25547,25548,25549,25550,25551,25552,25553,25554,25555,25556,25557,25558,25559,25560,25561,25562,25563,25564,25565,25566,25567,25568,25569,25570,25571,25572,25573,25574,25575,25576,25577,25578,25579,25580,25581,25582,25583,25584,25585,25586,25587,25588,25589,25590,25591,25592,25593,25594,25595,25596,25597,25598,25599,25600,25601,25602,25603,25604,25605,25606,25607,25608,25609,25610,25611,25612,25613,25614,25615,25616,25617,25618,25619,25620,25621,25622,25623,25624,25625,25626,25627,25628,25629,25630,25631,25632,25633,25634,25635,25636,25637,25638,25639,25640,25641,25642,25643,25644,25645,25646,25647,25648,25649,25650,25651,25652,25653,25654,25655,25656,25657,25658,25659,25660,25661,25662,25663,25664,25665,25666,25667,25668,25669,25670,25671,25672,25673,25674,25675,25676,25677,25678,25679,25680,25681,25682,25683,25684,25685,25686,25687,25688,25689,25690,25691,25692,25693,25694,25695,25696,25697,25698,25699,25700,25701,25702,25703,25704,25705,25706,25707,25708,25709,25710,25711,25712,25713,25714,25715,25716,25717,25718,25719,25720,25721,25722,25723,25724,25725,25726,25727,25728,25729,25730,25731,25732,25733,25734,25735,25736,25737,25738,25739,25740,25741,25742,25743,25744,25745,25746,25747,25748,25749,25750,25751,25752,25753,25754,25755,25756,25757,25758,25759,25760,25761,25762,25763,25764,25765,25766,25767,25768,25769,25770,25771,25772,25773,25774,25775,25776,25777,25778,25779,25780,25781,25782,25783,25784,25785,25786,25787,25788,25789,25790,25791,25792,25793,25794,25795,25796,25797,25798,25799,25800,25801,25802,25803,25804,25805,25806,25807,25808,25809,25810,25811,25812,25813,25814,25815,25816,25817,25818,25819,25820,25821,25822,25823,25824,25825,25826,25827,25828,25829,25830,25831,25832,25833,25834,25835,25836,25837,25838,25839,25840,25841,25842,25843,25844,25845,25846,25847,25848,25849,25850,25851,25852,25853,25854,25855,25856,25857,25858,25859,25860,25861,25862,25863,25864,25865,25866,25867,25868,25869,25870,25871,25872,25873,25874,25875,25876,25877,25878,25879,25880,25881,25882,25883,25884,25885,25886,25887,25888,25889,25890,25891,25892,25893,25894,25895,25896,25897,25898,25899,25900,25901,25902,25903,25904,25905,25906,25907,25908,25909,25910,25911,25912,25913,25914,25915,25916,25917,25918,25919,25920,25921,25922,25923,25924,25925,25926,25927,25928,25929,25930,25931,25932,25933,25934,25935,25936,25937,25938,25939,25940,25941,25942,25943,25944,25945,25946,25947,25948,25949,25950,25951,25952,25953,25954,25955,25956,25957,25958,25959,25960,25961,25962,25963,25964,25965,25966,25967,25968,25969,25970,25971,25972,25973,25974,25975,25976,25977,25978,25979,25980,25981,25982,25983,25984,25985,25986,25987,25988,25989,25990,25991,25992,25993,25994,25995,25996,25997,25998,25999,26000,26001,26002,26003,26004,26005,26006,26007,26008,26009,26010,26011,26012,26013,26014,26015,26016,26017,26018,26019,26020,26021,26022,26023,26024,26025,26026,26027,26028,26029,26030,26031,26032,26033,26034,26035,26036,26037,26038,26039,26040,26041,26042,26043,26044,26045,26046,26047,26048,26049,26050,26051,26052,26053,26054,26055,26056,26057,26058,26059,26060,26061,26062,26063,26064,26065,26066,26067,26068,26069,26070,26071,26072,26073,26074,26075,26076,26077,26078,26079,26080,26081,26082,26083,26084,26085,26086,26087,26088,26089,26090,26091,26092,26093,26094,26095,26096,26097,26098,26099,26100,26101,26102,26103,26104,26105,26106,26107,26108,26109,26110,26111,26112,26113,26114,26115,26116,26117,26118,26119,26120,26121,26122,26123,26124,26125,26126,26127,26128,26129,26130,26131,26132,26133,26134,26135,26136,26137,26138,26139,26140,26141,26142,26143,26144,26145,26146,26147,26148,26149,26150,26151,26152,26153,26154,26155,26156,26157,26158,26159,26160,26161,26162,26163,26164,26165,26166,26167,26168,26169,26170,26171,26172,26173,26174,26175,26176,26177,26178,26179,26180,26181,26182,26183,26184,26185,26186,26187,26188,26189,26190,26191,26192,26193,26194,26195,26196,26197,26198,26199,26200,26201,26202,26203,26204,26205,26206,26207,26208,26209,26210,26211,26212,26213,26214,26215,26216,26217,26218,26219,26220,26221,26222,26223,26224,26225,26226,26227,26228,26229,26230,26231,26232,26233,26234,26235,26236,26237,26238,26239,26240,26241,26242,26243,26244,26245,26246,26247,26248,26249,26250,26251,26252,26253,26254,26255,26256,26257,26258,26259,26260,26261,26262,26263,26264,26265,26266,26267,26268,26269,26270,26271,26272,26273,26274,26275,26276,26277,26278,26279,26280,26281,26282,26283,26284,26285,26286,26287,26288,26289,26290,26291,26292,26293,26294,26295,26296,26297,26298,26299,26300,26301,26302,26303,26304,26305,26306,26307,26308,26309,26310,26311,26312,26313,26314,26315,26316,26317,26318,26319,26320,26321,26322,26323,26324,26325,26326,26327,26328,26329,26330,26331,26332,26333,26334,26335,26336,26337,26338,26339,26340,26341,26342,26343,26344,26345,26346,26347,26348,26349,26350,26351,26352,26353,26354,26355,26356,26357,26358,26359,26360,26361,26362,26363,26364,26365,26366,26367,26368,26369,26370,26371,26372,26373,26374,26375,26376,26377,26378,26379,26380,26381,26382,26383,26384,26385,26386,26387,26388,26389,26390,26391,26392,26393,26394,26395,26396,26397,26398,26399,26400,26401,26402,26403,26404,26405,26406,26407,26408,26409,26410,26411,26412,26413,26414,26415,26416,26417,26418,26419,26420,26421,26422,26423,26424,26425,26426,26427,26428,26429,26430,26431,26432,26433,26434,26435,26436,26437,26438,26439,26440,26441,26442,26443,26444,26445,26446,26447,26448,26449,26450,26451,26452,26453,26454,26455,26456,26457,26458,26459,26460,26461,26462,26463,26464,26465,26466,26467,26468,26469,26470,26471,26472,26473,26474,26475,26476,26477,26478,26479,26480,26481,26482,26483,26484,26485,26486,26487,26488,26489,26490,26491,26492,26493,26494,26495,26496,26497,26498,26499,26500,26501,26502,26503,26504,26505,26506,26507,26508,26509,26510,26511,26512,26513,26514,26515,26516,26517,26518,26519,26520,26521,26522,26523,26524,26525,26526,26527,26528,26529,26530,26531,26532,26533,26534,26535,26536,26537,26538,26539,26540,26541,26542,26543,26544,26545,26546,26547,26548,26549,26550,26551,26552,26553,26554,26555,26556,26557,26558,26559,26560,26561,26562,26563,26564,26565,26566,26567,26568,26569,26570,26571,26572,26573,26574,26575,26576,26577,26578,26579,26580,26581,26582,26583,26584,26585,26586,26587,26588,26589,26590,26591,26592,26593,26594,26595,26596,26597,26598,26599,26600,26601,26602,26603,26604,26605,26606,26607,26608,26609,26610,26611,26612,26613,26614,26615,26616,26617,26618,26619,26620,26621,26622,26623,26624,26625,26626,26627,26628,26629,26630,26631,26632,26633,26634,26635,26636,26637,26638,26639,26640,26641,26642,26643,26644,26645,26646,26647,26648,26649,26650,26651,26652,26653,26654,26655,26656,26657,26658,26659,26660,26661,26662,26663,26664,26665,26666,26667,26668,26669,26670,26671,26672,26673,26674,26675,26676,26677,26678,26679,26680,26681,26682,26683,26684,26685,26686,26687,26688,26689,26690,26691,26692,26693,26694,26695,26696,26697,26698,26699,26700,26701,26702,26703,26704,26705,26706,26707,26708,26709,26710,26711,26712,26713,26714,26715,26716,26717,26718,26719,26720,26721,26722,26723,26724,26725,26726,26727,26728,26729,26730,26731,26732,26733,26734,26735,26736,26737,26738,26739,26740,26741,26742,26743,26744,26745,26746,26747,26748,26749,26750,26751,26752,26753,26754,26755,26756,26757,26758,26759,26760,26761,26762,26763,26764,26765,26766,26767,26768,26769,26770,26771,26772,26773,26774,26775,26776,26777,26778,26779,26780,26781,26782,26783,26784,26785,26786,26787,26788,26789,26790,26791,26792,26793,26794,26795,26796,26797,26798,26799,26800,26801,26802,26803,26804,26805,26806,26807,26808,26809,26810,26811,26812,26813,26814,26815,26816,26817,26818,26819,26820,26821,26822,26823,26824,26825,26826,26827,26828,26829,26830,26831,26832,26833,26834,26835,26836,26837,26838,26839,26840,26841,26842,26843,26844,26845,26846,26847,26848,26849,26850,26851,26852,26853,26854,26855,26856,26857,26858,26859,26860,26861,26862,26863,26864,26865,26866,26867,26868,26869,26870,26871,26872,26873,26874,26875,26876,26877,26878,26879,26880,26881,26882,26883,26884,26885,26886,26887,26888,26889,26890,26891,26892,26893,26894,26895,26896,26897,26898,26899,26900,26901,26902,26903,26904,26905,26906,26907,26908,26909,26910,26911,26912,26913,26914,26915,26916,26917,26918,26919,26920,26921,26922,26923,26924,26925,26926,26927,26928,26929,26930,26931,26932,26933,26934,26935,26936,26937,26938,26939,26940,26941,26942,26943,26944,26945,26946,26947,26948,26949,26950,26951,26952,26953,26954,26955,26956,26957,26958,26959,26960,26961,26962,26963,26964,26965,26966,26967,26968,26969,26970,26971,26972,26973,26974,26975,26976,26977,26978,26979,26980,26981,26982,26983,26984,26985,26986,26987,26988,26989,26990,26991,26992,26993,26994,26995,26996,26997,26998,26999,27000,27001,27002,27003,27004,27005,27006,27007,27008,27009,27010,27011,27012,27013,27014,27015,27016,27017,27018,27019,27020,27021,27022,27023,27024,27025,27026,27027,27028,27029,27030,27031,27032,27033,27034,27035,27036,27037,27038,27039,27040,27041,27042,27043,27044,27045,27046,27047,27048,27049,27050,27051,27052,27053,27054,27055,27056,27057,27058,27059,27060,27061,27062,27063,27064,27065,27066,27067,27068,27069,27070,27071,27072,27073,27074,27075,27076,27077,27078,27079,27080,27081,27082,27083,27084,27085,27086,27087,27088,27089,27090,27091,27092,27093,27094,27095,27096,27097,27098,27099,27100,27101,27102,27103,27104,27105,27106,27107,27108,27109,27110,27111,27112,27113,27114,27115,27116,27117,27118,27119,27120,27121,27122,27123,27124,27125,27126,27127,27128,27129,27130,27131,27132,27133,27134,27135,27136,27137,27138,27139,27140,27141,27142,27143,27144,27145,27146,27147,27148,27149,27150,27151,27152,27153,27154,27155,27156,27157,27158,27159,27160,27161,27162,27163,27164,27165,27166,27167,27168,27169,27170,27171,27172,27173,27174,27175,27176,27177,27178,27179,27180,27181,27182,27183,27184,27185,27186,27187,27188,27189,27190,27191,27192,27193,27194,27195,27196,27197,27198,27199,27200,27201,27202,27203,27204,27205,27206,27207,27208,27209,27210,27211,27212,27213,27214,27215,27216,27217,27218,27219,27220,27221,27222,27223,27224,27225,27226,27227,27228,27229,27230,27231,27232,27233,27234,27235,27236,27237,27238,27239,27240,27241,27242,27243,27244,27245,27246,27247,27248,27249,27250,27251,27252,27253,27254,27255,27256,27257,27258,27259,27260,27261,27262,27263,27264,27265,27266,27267,27268,27269,27270,27271,27272,27273,27274,27275,27276,27277,27278,27279,27280,27281,27282,27283,27284,27285,27286,27287,27288,27289,27290,27291,27292,27293,27294,27295,27296,27297,27298,27299,27300,27301,27302,27303,27304,27305,27306,27307,27308,27309,27310,27311,27312,27313,27314,27315,27316,27317,27318,27319,27320,27321,27322,27323,27324,27325,27326,27327,27328,27329,27330,27331,27332,27333,27334,27335,27336,27337,27338,27339,27340,27341,27342,27343,27344,27345,27346,27347,27348,27349,27350,27351,27352,27353,27354,27355,27356,27357,27358,27359,27360,27361,27362,27363,27364,27365,27366,27367,27368,27369,27370,27371,27372,27373,27374,27375,27376,27377,27378,27379,27380,27381,27382,27383,27384,27385,27386,27387,27388,27389,27390,27391,27392,27393,27394,27395,27396,27397,27398,27399,27400,27401,27402,27403,27404,27405,27406,27407,27408,27409,27410,27411,27412,27413,27414,27415,27416,27417,27418,27419,27420,27421,27422,27423,27424,27425,27426,27427,27428,27429,27430,27431,27432,27433,27434,27435,27436,27437,27438,27439,27440,27441,27442,27443,27444,27445,27446,27447,27448,27449,27450,27451,27452,27453,27454,27455,27456,27457,27458,27459,27460,27461,27462,27463,27464,27465,27466,27467,27468,27469,27470,27471,27472,27473,27474,27475,27476,27477,27478,27479,27480,27481,27482,27483,27484,27485,27486,27487,27488,27489,27490,27491,27492,27493,27494,27495,27496,27497,27498,27499,27500,27501,27502,27503,27504,27505,27506,27507,27508,27509,27510,27511,27512,27513,27514,27515,27516,27517,27518,27519,27520,27521,27522,27523,27524,27525,27526,27527,27528,27529,27530,27531,27532,27533,27534,27535,27536,27537,27538,27539,27540,27541,27542,27543,27544,27545,27546,27547,27548,27549,27550,27551,27552,27553,27554,27555,27556,27557,27558,27559,27560,27561,27562,27563,27564,27565,27566,27567,27568,27569,27570,27571,27572,27573,27574,27575,27576,27577,27578,27579,27580,27581,27582,27583,27584,27585,27586,27587,27588,27589,27590,27591,27592,27593,27594,27595,27596,27597,27598,27599,27600,27601,27602,27603,27604,27605,27606,27607,27608,27609,27610,27611,27612,27613,27614,27615,27616,27617,27618,27619,27620,27621,27622,27623,27624,27625,27626,27627,27628,27629,27630,27631,27632,27633,27634,27635,27636,27637,27638,27639,27640,27641,27642,27643,27644,27645,27646,27647,27648,27649,27650,27651,27652,27653,27654,27655,27656,27657,27658,27659,27660,27661,27662,27663,27664,27665,27666,27667,27668,27669,27670,27671,27672,27673,27674,27675,27676,27677,27678,27679,27680,27681,27682,27683,27684,27685,27686,27687,27688,27689,27690,27691,27692,27693,27694,27695,27696,27697,27698,27699,27700,27701,27702,27703,27704,27705,27706,27707,27708,27709,27710,27711,27712,27713,27714,27715,27716,27717,27718,27719,27720,27721,27722,27723,27724,27725,27726,27727,27728,27729,27730,27731,27732,27733,27734,27735,27736,27737,27738,27739,27740,27741,27742,27743,27744,27745,27746,27747,27748,27749,27750,27751,27752,27753,27754,27755,27756,27757,27758,27759,27760,27761,27762,27763,27764,27765,27766,27767,27768,27769,27770,27771,27772,27773,27774,27775,27776,27777,27778,27779,27780,27781,27782,27783,27784,27785,27786,27787,27788,27789,27790,27791,27792,27793,27794,27795,27796,27797,27798,27799,27800,27801,27802,27803,27804,27805,27806,27807,27808,27809,27810,27811,27812,27813,27814,27815,27816,27817,27818,27819,27820,27821,27822,27823,27824,27825,27826,27827,27828,27829,27830,27831,27832,27833,27834,27835,27836,27837,27838,27839,27840,27841,27842,27843,27844,27845,27846,27847,27848,27849,27850,27851,27852,27853,27854,27855,27856,27857,27858,27859,27860,27861,27862,27863,27864,27865,27866,27867,27868,27869,27870,27871,27872,27873,27874,27875,27876,27877,27878,27879,27880,27881,27882,27883,27884,27885,27886,27887,27888,27889,27890,27891,27892,27893,27894,27895,27896,27897,27898,27899,27900,27901,27902,27903,27904,27905,27906,27907,27908,27909,27910,27911,27912,27913,27914,27915,27916,27917,27918,27919,27920,27921,27922,27923,27924,27925,27926,27927,27928,27929,27930,27931,27932,27933,27934,27935,27936,27937,27938,27939,27940,27941,27942,27943,27944,27945,27946,27947,27948,27949,27950,27951,27952,27953,27954,27955,27956,27957,27958,27959,27960,27961,27962,27963,27964,27965,27966,27967,27968,27969,27970,27971,27972,27973,27974,27975,27976,27977,27978,27979,27980,27981,27982,27983,27984,27985,27986,27987,27988,27989,27990,27991,27992,27993,27994,27995,27996,27997,27998,27999,28000,28001,28002,28003,28004,28005,28006,28007,28008,28009,28010,28011,28012,28013,28014,28015,28016,28017,28018,28019,28020,28021,28022,28023,28024,28025,28026,28027,28028,28029,28030,28031,28032,28033,28034,28035,28036,28037,28038,28039,28040,28041,28042,28043,28044,28045,28046,28047,28048,28049,28050,28051,28052,28053,28054,28055,28056,28057,28058,28059,28060,28061,28062,28063,28064,28065,28066,28067,28068,28069,28070,28071,28072,28073,28074,28075,28076,28077,28078,28079,28080,28081,28082,28083,28084,28085,28086,28087,28088,28089,28090,28091,28092,28093,28094,28095,28096,28097,28098,28099,28100,28101,28102,28103,28104,28105,28106,28107,28108,28109,28110,28111,28112,28113,28114,28115,28116,28117,28118,28119,28120,28121,28122,28123,28124,28125,28126,28127,28128,28129,28130,28131,28132,28133,28134,28135,28136,28137,28138,28139,28140,28141,28142,28143,28144,28145,28146,28147,28148,28149,28150,28151,28152,28153,28154,28155,28156,28157,28158,28159,28160,28161,28162,28163,28164,28165,28166,28167,28168,28169,28170,28171,28172,28173,28174,28175,28176,28177,28178,28179,28180,28181,28182,28183,28184,28185,28186,28187,28188,28189,28190,28191,28192,28193,28194,28195,28196,28197,28198,28199,28200,28201,28202,28203,28204,28205,28206,28207,28208,28209,28210,28211,28212,28213,28214,28215,28216,28217,28218,28219,28220,28221,28222,28223,28224,28225,28226,28227,28228,28229,28230,28231,28232,28233,28234,28235,28236,28237,28238,28239,28240,28241,28242,28243,28244,28245,28246,28247,28248,28249,28250,28251,28252,28253,28254,28255,28256,28257,28258,28259,28260,28261,28262,28263,28264,28265,28266,28267,28268,28269,28270,28271,28272,28273,28274,28275,28276,28277,28278,28279,28280,28281,28282,28283,28284,28285,28286,28287,28288,28289,28290,28291,28292,28293,28294,28295,28296,28297,28298,28299,28300,28301,28302,28303,28304,28305,28306,28307,28308,28309,28310,28311,28312,28313,28314,28315,28316,28317,28318,28319,28320,28321,28322,28323,28324,28325,28326,28327,28328,28329,28330,28331,28332,28333,28334,28335,28336,28337,28338,28339,28340,28341,28342,28343,28344,28345,28346,28347,28348,28349,28350,28351,28352,28353,28354,28355,28356,28357,28358,28359,28360,28361,28362,28363,28364,28365,28366,28367,28368,28369,28370,28371,28372,28373,28374,28375,28376,28377,28378,28379,28380,28381,28382,28383,28384,28385,28386,28387,28388,28389,28390,28391,28392,28393,28394,28395,28396,28397,28398,28399,28400,28401,28402,28403,28404,28405,28406,28407,28408,28409,28410,28411,28412,28413,28414,28415,28416,28417,28418,28419,28420,28421,28422,28423,28424,28425,28426,28427,28428,28429,28430,28431,28432,28433,28434,28435,28436,28437,28438,28439,28440,28441,28442,28443,28444,28445,28446,28447,28448,28449,28450,28451,28452,28453,28454,28455,28456,28457,28458,28459,28460,28461,28462,28463,28464,28465,28466,28467,28468,28469,28470,28471,28472,28473,28474,28475,28476,28477,28478,28479,28480,28481,28482,28483,28484,28485,28486,28487,28488,28489,28490,28491,28492,28493,28494,28495,28496,28497,28498,28499,28500,28501,28502,28503,28504,28505,28506,28507,28508,28509,28510,28511,28512,28513,28514,28515,28516,28517,28518,28519,28520,28521,28522,28523,28524,28525,28526,28527,28528,28529,28530,28531,28532,28533,28534,28535,28536,28537,28538,28539,28540,28541,28542,28543,28544,28545,28546,28547,28548,28549,28550,28551,28552,28553,28554,28555,28556,28557,28558,28559,28560,28561,28562,28563,28564,28565,28566,28567,28568,28569,28570,28571,28572,28573,28574,28575,28576,28577,28578,28579,28580,28581,28582,28583,28584,28585,28586,28587,28588,28589,28590,28591,28592,28593,28594,28595,28596,28597,28598,28599,28600,28601,28602,28603,28604,28605,28606,28607,28608,28609,28610,28611,28612,28613,28614,28615,28616,28617,28618,28619,28620,28621,28622,28623,28624,28625,28626,28627,28628,28629,28630,28631,28632,28633,28634,28635,28636,28637,28638,28639,28640,28641,28642,28643,28644,28645,28646,28647,28648,28649,28650,28651,28652,28653,28654,28655,28656,28657,28658,28659,28660,28661,28662,28663,28664,28665,28666,28667,28668,28669,28670,28671,28672,28673,28674,28675,28676,28677,28678,28679,28680,28681,28682,28683,28684,28685,28686,28687,28688,28689,28690,28691,28692,28693,28694,28695,28696,28697,28698,28699,28700,28701,28702,28703,28704,28705,28706,28707,28708,28709,28710,28711,28712,28713,28714,28715,28716,28717,28718,28719,28720,28721,28722,28723,28724,28725,28726,28727,28728,28729,28730,28731,28732,28733,28734,28735,28736,28737,28738,28739,28740,28741,28742,28743,28744,28745,28746,28747,28748,28749,28750,28751,28752,28753,28754,28755,28756,28757,28758,28759,28760,28761,28762,28763,28764,28765,28766,28767,28768,28769,28770,28771,28772,28773,28774,28775,28776,28777,28778,28779,28780,28781,28782,28783,28784,28785,28786,28787,28788,28789,28790,28791,28792,28793,28794,28795,28796,28797,28798,28799,28800,28801,28802,28803,28804,28805,28806,28807,28808,28809,28810,28811,28812,28813,28814,28815,28816,28817,28818,28819,28820,28821,28822,28823,28824,28825,28826,28827,28828,28829,28830,28831,28832,28833,28834,28835,28836,28837,28838,28839,28840,28841,28842,28843,28844,28845,28846,28847,28848,28849,28850,28851,28852,28853,28854,28855,28856,28857,28858,28859,28860,28861,28862,28863,28864,28865,28866,28867,28868,28869,28870,28871,28872,28873,28874,28875,28876,28877,28878,28879,28880,28881,28882,28883,28884,28885,28886,28887,28888,28889,28890,28891,28892,28893,28894,28895,28896,28897,28898,28899,28900,28901,28902,28903,28904,28905,28906,28907,28908,28909,28910,28911,28912,28913,28914,28915,28916,28917,28918,28919,28920,28921,28922,28923,28924,28925,28926,28927,28928,28929,28930,28931,28932,28933,28934,28935,28936,28937,28938,28939,28940,28941,28942,28943,28944,28945,28946,28947,28948,28949,28950,28951,28952,28953,28954,28955,28956,28957,28958,28959,28960,28961,28962,28963,28964,28965,28966,28967,28968,28969,28970,28971,28972,28973,28974,28975,28976,28977,28978,28979,28980,28981,28982,28983,28984,28985,28986,28987,28988,28989,28990,28991,28992,28993,28994,28995,28996,28997,28998,28999,29000,29001,29002,29003,29004,29005,29006,29007,29008,29009,29010,29011,29012,29013,29014,29015,29016,29017,29018,29019,29020,29021,29022,29023,29024,29025,29026,29027,29028,29029,29030,29031,29032,29033,29034,29035,29036,29037,29038,29039,29040,29041,29042,29043,29044,29045,29046,29047,29048,29049,29050,29051,29052,29053,29054,29055,29056,29057,29058,29059,29060,29061,29062,29063,29064,29065,29066,29067,29068,29069,29070,29071,29072,29073,29074,29075,29076,29077,29078,29079,29080,29081,29082,29083,29084,29085,29086,29087,29088,29089,29090,29091,29092,29093,29094,29095,29096,29097,29098,29099,29100,29101,29102,29103,29104,29105,29106,29107,29108,29109,29110,29111,29112,29113,29114,29115,29116,29117,29118,29119,29120,29121,29122,29123,29124,29125,29126,29127,29128,29129,29130,29131,29132,29133,29134,29135,29136,29137,29138,29139,29140,29141,29142,29143,29144,29145,29146,29147,29148,29149,29150,29151,29152,29153,29154,29155,29156,29157,29158,29159,29160,29161,29162,29163,29164,29165,29166,29167,29168,29169,29170,29171,29172,29173,29174,29175,29176,29177,29178,29179,29180,29181,29182,29183,29184,29185,29186,29187,29188,29189,29190,29191,29192,29193,29194,29195,29196,29197,29198,29199,29200,29201,29202,29203,29204,29205,29206,29207,29208,29209,29210,29211,29212,29213,29214,29215,29216,29217,29218,29219,29220,29221,29222,29223,29224,29225,29226,29227,29228,29229,29230,29231,29232,29233,29234,29235,29236,29237,29238,29239,29240,29241,29242,29243,29244,29245,29246,29247,29248,29249,29250,29251,29252,29253,29254,29255,29256,29257,29258,29259,29260,29261,29262,29263,29264,29265,29266,29267,29268,29269,29270,29271,29272,29273,29274,29275,29276,29277,29278,29279,29280,29281,29282,29283,29284,29285,29286,29287,29288,29289,29290,29291,29292,29293,29294,29295,29296,29297,29298,29299,29300,29301,29302,29303,29304,29305,29306,29307,29308,29309,29310,29311,29312,29313,29314,29315,29316,29317,29318,29319,29320,29321,29322,29323,29324,29325,29326,29327,29328,29329,29330,29331,29332,29333,29334,29335,29336,29337,29338,29339,29340,29341,29342,29343,29344,29345,29346,29347,29348,29349,29350,29351,29352,29353,29354,29355,29356,29357,29358,29359,29360,29361,29362,29363,29364,29365,29366,29367,29368,29369,29370,29371,29372,29373,29374,29375,29376,29377,29378,29379,29380,29381,29382,29383,29384,29385,29386,29387,29388,29389,29390,29391,29392,29393,29394,29395,29396,29397,29398,29399,29400,29401,29402,29403,29404,29405,29406,29407,29408,29409,29410,29411,29412,29413,29414,29415,29416,29417,29418,29419,29420,29421,29422,29423,29424,29425,29426,29427,29428,29429,29430,29431,29432,29433,29434,29435,29436,29437,29438,29439,29440,29441,29442,29443,29444,29445,29446,29447,29448,29449,29450,29451,29452,29453,29454,29455,29456,29457,29458,29459,29460,29461,29462,29463,29464,29465,29466,29467,29468,29469,29470,29471,29472,29473,29474,29475,29476,29477,29478,29479,29480,29481,29482,29483,29484,29485,29486,29487,29488,29489,29490,29491,29492,29493,29494,29495,29496,29497,29498,29499,29500,29501,29502,29503,29504,29505,29506,29507,29508,29509,29510,29511,29512,29513,29514,29515,29516,29517,29518,29519,29520,29521,29522,29523,29524,29525,29526,29527,29528,29529,29530,29531,29532,29533,29534,29535,29536,29537,29538,29539,29540,29541,29542,29543,29544,29545,29546,29547,29548,29549,29550,29551,29552,29553,29554,29555,29556,29557,29558,29559,29560,29561,29562,29563,29564,29565,29566,29567,29568,29569,29570,29571,29572,29573,29574,29575,29576,29577,29578,29579,29580,29581,29582,29583,29584,29585,29586,29587,29588,29589,29590,29591,29592,29593,29594,29595,29596,29597,29598,29599,29600,29601,29602,29603,29604,29605,29606,29607,29608,29609,29610,29611,29612,29613,29614,29615,29616,29617,29618,29619,29620,29621,29622,29623,29624,29625,29626,29627,29628,29629,29630,29631,29632,29633,29634,29635,29636,29637,29638,29639,29640,29641,29642,29643,29644,29645,29646,29647,29648,29649,29650,29651,29652,29653,29654,29655,29656,29657,29658,29659,29660,29661,29662,29663,29664,29665,29666,29667,29668,29669,29670,29671,29672,29673,29674,29675,29676,29677,29678,29679,29680,29681,29682,29683,29684,29685,29686,29687,29688,29689,29690,29691,29692,29693,29694,29695,29696,29697,29698,29699,29700,29701,29702,29703,29704,29705,29706,29707,29708,29709,29710,29711,29712,29713,29714,29715,29716,29717,29718,29719,29720,29721,29722,29723,29724,29725,29726,29727,29728,29729,29730,29731,29732,29733,29734,29735,29736,29737,29738,29739,29740,29741,29742,29743,29744,29745,29746,29747,29748,29749,29750,29751,29752,29753,29754,29755,29756,29757,29758,29759,29760,29761,29762,29763,29764,29765,29766,29767,29768,29769,29770,29771,29772,29773,29774,29775,29776,29777,29778,29779,29780,29781,29782,29783,29784,29785,29786,29787,29788,29789,29790,29791,29792,29793,29794,29795,29796,29797,29798,29799,29800,29801,29802,29803,29804,29805,29806,29807,29808,29809,29810,29811,29812,29813,29814,29815,29816,29817,29818,29819,29820,29821,29822,29823,29824,29825,29826,29827,29828,29829,29830,29831,29832,29833,29834,29835,29836,29837,29838,29839,29840,29841,29842,29843,29844,29845,29846,29847,29848,29849,29850,29851,29852,29853,29854,29855,29856,29857,29858,29859,29860,29861,29862,29863,29864,29865,29866,29867,29868,29869,29870,29871,29872,29873,29874,29875,29876,29877,29878,29879,29880,29881,29882,29883,29884,29885,29886,29887,29888,29889,29890,29891,29892,29893,29894,29895,29896,29897,29898,29899,29900,29901,29902,29903,29904,29905,29906,29907,29908,29909,29910,29911,29912,29913,29914,29915,29916,29917,29918,29919,29920,29921,29922,29923,29924,29925,29926,29927,29928,29929,29930,29931,29932,29933,29934,29935,29936,29937,29938,29939,29940,29941,29942,29943,29944,29945,29946,29947,29948,29949,29950,29951,29952,29953,29954,29955,29956,29957,29958,29959,29960,29961,29962,29963,29964,29965,29966,29967,29968,29969,29970,29971,29972,29973,29974,29975,29976,29977,29978,29979,29980,29981,29982,29983,29984,29985,29986,29987,29988,29989,29990,29991,29992,29993,29994,29995,29996,29997,29998,29999,30000,30001,30002,30003,30004,30005,30006,30007,30008,30009,30010,30011,30012,30013,30014,30015,30016,30017,30018,30019,30020,30021,30022,30023,30024,30025,30026,30027,30028,30029,30030,30031,30032,30033,30034,30035,30036,30037,30038,30039,30040,30041,30042,30043,30044,30045,30046,30047,30048,30049,30050,30051,30052,30053,30054,30055,30056,30057,30058,30059,30060,30061,30062,30063,30064,30065,30066,30067,30068,30069,30070,30071,30072,30073,30074,30075,30076,30077,30078,30079,30080,30081,30082,30083,30084,30085,30086,30087,30088,30089,30090,30091,30092,30093,30094,30095,30096,30097,30098,30099,30100,30101,30102,30103,30104,30105,30106,30107,30108,30109,30110,30111,30112,30113,30114,30115,30116,30117,30118,30119,30120,30121,30122,30123,30124,30125,30126,30127,30128,30129,30130,30131,30132,30133,30134,30135,30136,30137,30138,30139,30140,30141,30142,30143,30144,30145,30146,30147,30148,30149,30150,30151,30152,30153,30154,30155,30156,30157,30158,30159,30160,30161,30162,30163,30164,30165,30166,30167,30168,30169,30170,30171,30172,30173,30174,30175,30176,30177,30178,30179,30180,30181,30182,30183,30184,30185,30186,30187,30188,30189,30190,30191,30192,30193,30194,30195,30196,30197,30198,30199,30200,30201,30202,30203,30204,30205,30206,30207,30208,30209,30210,30211,30212,30213,30214,30215,30216,30217,30218,30219,30220,30221,30222,30223,30224,30225,30226,30227,30228,30229,30230,30231,30232,30233,30234,30235,30236,30237,30238,30239,30240,30241,30242,30243,30244,30245,30246,30247,30248,30249,30250,30251,30252,30253,30254,30255,30256,30257,30258,30259,30260,30261,30262,30263,30264,30265,30266,30267,30268,30269,30270,30271,30272,30273,30274,30275,30276,30277,30278,30279,30280,30281,30282,30283,30284,30285,30286,30287,30288,30289,30290,30291,30292,30293,30294,30295,30296,30297,30298,30299,30300,30301,30302,30303,30304,30305,30306,30307,30308,30309,30310,30311,30312,30313,30314,30315,30316,30317,30318,30319,30320,30321,30322,30323,30324,30325,30326,30327,30328,30329,30330,30331,30332,30333,30334,30335,30336,30337,30338,30339,30340,30341,30342,30343,30344,30345,30346,30347,30348,30349,30350,30351,30352,30353,30354,30355,30356,30357,30358,30359,30360,30361,30362,30363,30364,30365,30366,30367,30368,30369,30370,30371,30372,30373,30374,30375,30376,30377,30378,30379,30380,30381,30382,30383,30384,30385,30386,30387,30388,30389,30390,30391,30392,30393,30394,30395,30396,30397,30398,30399,30400,30401,30402,30403,30404,30405,30406,30407,30408,30409,30410,30411,30412,30413,30414,30415,30416,30417,30418,30419,30420,30421,30422,30423,30424,30425,30426,30427,30428,30429,30430,30431,30432,30433,30434,30435,30436,30437,30438,30439,30440,30441,30442,30443,30444,30445,30446,30447,30448,30449,30450,30451,30452,30453,30454,30455,30456,30457,30458,30459,30460,30461,30462,30463,30464,30465,30466,30467,30468,30469,30470,30471,30472,30473,30474,30475,30476,30477,30478,30479,30480,30481,30482,30483,30484,30485,30486,30487,30488,30489,30490,30491,30492,30493,30494,30495,30496,30497,30498,30499,30500,30501,30502,30503,30504,30505,30506,30507,30508,30509,30510,30511,30512,30513,30514,30515,30516,30517,30518,30519,30520,30521,30522,30523,30524,30525,30526,30527,30528,30529,30530,30531,30532,30533,30534,30535,30536,30537,30538,30539,30540,30541,30542,30543,30544,30545,30546,30547,30548,30549,30550,30551,30552,30553,30554,30555,30556,30557,30558,30559,30560,30561,30562,30563,30564,30565,30566,30567,30568,30569,30570,30571,30572,30573,30574,30575,30576,30577,30578,30579,30580,30581,30582,30583,30584,30585,30586,30587,30588,30589,30590,30591,30592,30593,30594,30595,30596,30597,30598,30599,30600,30601,30602,30603,30604,30605,30606,30607,30608,30609,30610,30611,30612,30613,30614,30615,30616,30617,30618,30619,30620,30621,30622,30623,30624,30625,30626,30627,30628,30629,30630,30631,30632,30633,30634,30635,30636,30637,30638,30639,30640,30641,30642,30643,30644,30645,30646,30647,30648,30649,30650,30651,30652,30653,30654,30655,30656,30657,30658,30659,30660,30661,30662,30663,30664,30665,30666,30667,30668,30669,30670,30671,30672,30673,30674,30675,30676,30677,30678,30679,30680,30681,30682,30683,30684,30685,30686,30687,30688,30689,30690,30691,30692,30693,30694,30695,30696,30697,30698,30699,30700,30701,30702,30703,30704,30705,30706,30707,30708,30709,30710,30711,30712,30713,30714,30715,30716,30717,30718,30719,30720,30721,30722,30723,30724,30725,30726,30727,30728,30729,30730,30731,30732,30733,30734,30735,30736,30737,30738,30739,30740,30741,30742,30743,30744,30745,30746,30747,30748,30749,30750,30751,30752,30753,30754,30755,30756,30757,30758,30759,30760,30761,30762,30763,30764,30765,30766,30767,30768,30769,30770,30771,30772,30773,30774,30775,30776,30777,30778,30779,30780,30781,30782,30783,30784,30785,30786,30787,30788,30789,30790,30791,30792,30793,30794,30795,30796,30797,30798,30799,30800,30801,30802,30803,30804,30805,30806,30807,30808,30809,30810,30811,30812,30813,30814,30815,30816,30817,30818,30819,30820,30821,30822,30823,30824,30825,30826,30827,30828,30829,30830,30831,30832,30833,30834,30835,30836,30837,30838,30839,30840,30841,30842,30843,30844,30845,30846,30847,30848,30849,30850,30851,30852,30853,30854,30855,30856,30857,30858,30859,30860,30861,30862,30863,30864,30865,30866,30867,30868,30869,30870,30871,30872,30873,30874,30875,30876,30877,30878,30879,30880,30881,30882,30883,30884,30885,30886,30887,30888,30889,30890,30891,30892,30893,30894,30895,30896,30897,30898,30899,30900,30901,30902,30903,30904,30905,30906,30907,30908,30909,30910,30911,30912,30913,30914,30915,30916,30917,30918,30919,30920,30921,30922,30923,30924,30925,30926,30927,30928,30929,30930,30931,30932,30933,30934,30935,30936,30937,30938,30939,30940,30941,30942,30943,30944,30945,30946,30947,30948,30949,30950,30951,30952,30953,30954,30955,30956,30957,30958,30959,30960,30961,30962,30963,30964,30965,30966,30967,30968,30969,30970,30971,30972,30973,30974,30975,30976,30977,30978,30979,30980,30981,30982,30983,30984,30985,30986,30987,30988,30989,30990,30991,30992,30993,30994,30995,30996,30997,30998,30999,31000,31001,31002,31003,31004,31005,31006,31007,31008,31009,31010,31011,31012,31013,31014,31015,31016,31017,31018,31019,31020,31021,31022,31023,31024,31025,31026,31027,31028,31029,31030,31031,31032,31033,31034,31035,31036,31037,31038,31039,31040,31041,31042,31043,31044,31045,31046,31047,31048,31049,31050,31051,31052,31053,31054,31055,31056,31057,31058,31059,31060,31061,31062,31063,31064,31065,31066,31067,31068,31069,31070,31071,31072,31073,31074,31075,31076,31077,31078,31079,31080,31081,31082,31083,31084,31085,31086,31087,31088,31089,31090,31091,31092,31093,31094,31095,31096,31097,31098,31099,31100,31101,31102,31103,31104,31105,31106,31107,31108,31109,31110,31111,31112,31113,31114,31115,31116,31117,31118,31119,31120,31121,31122,31123,31124,31125,31126,31127,31128,31129,31130,31131,31132,31133,31134,31135,31136,31137,31138,31139,31140,31141,31142,31143,31144,31145,31146,31147,31148,31149,31150,31151,31152,31153,31154,31155,31156,31157,31158,31159,31160,31161,31162,31163,31164,31165,31166,31167,31168,31169,31170,31171,31172,31173,31174,31175,31176,31177,31178,31179,31180,31181,31182,31183,31184,31185,31186,31187,31188,31189,31190,31191,31192,31193,31194,31195,31196,31197,31198,31199,31200,31201,31202,31203,31204,31205,31206,31207,31208,31209,31210,31211,31212,31213,31214,31215,31216,31217,31218,31219,31220,31221,31222,31223,31224,31225,31226,31227,31228,31229,31230,31231,31232,31233,31234,31235,31236,31237,31238,31239,31240,31241,31242,31243,31244,31245,31246,31247,31248,31249,31250,31251,31252,31253,31254,31255,31256,31257,31258,31259,31260,31261,31262,31263,31264,31265,31266,31267,31268,31269,31270,31271,31272,31273,31274,31275,31276,31277,31278,31279,31280,31281,31282,31283,31284,31285,31286,31287,31288,31289,31290,31291,31292,31293,31294,31295,31296,31297,31298,31299,31300,31301,31302,31303,31304,31305,31306,31307,31308,31309,31310,31311,31312,31313,31314,31315,31316,31317,31318,31319,31320,31321,31322,31323,31324,31325,31326,31327,31328,31329,31330,31331,31332,31333,31334,31335,31336,31337,31338,31339,31340,31341,31342,31343,31344,31345,31346,31347,31348,31349,31350,31351,31352,31353,31354,31355,31356,31357,31358,31359,31360,31361,31362,31363,31364,31365,31366,31367,31368,31369,31370,31371,31372,31373,31374,31375,31376,31377,31378,31379,31380,31381,31382,31383,31384,31385,31386,31387,31388,31389,31390,31391,31392,31393,31394,31395,31396,31397,31398,31399,31400,31401,31402,31403,31404,31405,31406,31407,31408,31409,31410,31411,31412,31413,31414,31415,31416,31417,31418,31419,31420,31421,31422,31423,31424,31425,31426,31427,31428,31429,31430,31431,31432,31433,31434,31435,31436,31437,31438,31439,31440,31441,31442,31443,31444,31445,31446,31447,31448,31449,31450,31451,31452,31453,31454,31455,31456,31457,31458,31459,31460,31461,31462,31463,31464,31465,31466,31467,31468,31469,31470,31471,31472,31473,31474,31475,31476,31477,31478,31479,31480,31481,31482,31483,31484,31485,31486,31487,31488,31489,31490,31491,31492,31493,31494,31495,31496,31497,31498,31499,31500,31501,31502,31503,31504,31505,31506,31507,31508,31509,31510,31511,31512,31513,31514,31515,31516,31517,31518,31519,31520,31521,31522,31523,31524,31525,31526,31527,31528,31529,31530,31531,31532,31533,31534,31535,31536,31537,31538,31539,31540,31541,31542,31543,31544,31545,31546,31547,31548,31549,31550,31551,31552,31553,31554,31555,31556,31557,31558,31559,31560,31561,31562,31563,31564,31565,31566,31567,31568,31569,31570,31571,31572,31573,31574,31575,31576,31577,31578,31579,31580,31581,31582,31583,31584,31585,31586,31587,31588,31589,31590,31591,31592,31593,31594,31595,31596,31597,31598,31599,31600,31601,31602,31603,31604,31605,31606,31607,31608,31609,31610,31611,31612,31613,31614,31615,31616,31617,31618,31619,31620,31621,31622,31623,31624,31625,31626,31627,31628,31629,31630,31631,31632,31633,31634,31635,31636,31637,31638,31639,31640,31641,31642,31643,31644,31645,31646,31647,31648,31649,31650,31651,31652,31653,31654,31655,31656,31657,31658,31659,31660,31661,31662,31663,31664,31665,31666,31667,31668,31669,31670,31671,31672,31673,31674,31675,31676,31677,31678,31679,31680,31681,31682,31683,31684,31685,31686,31687,31688,31689,31690,31691,31692,31693,31694,31695,31696,31697,31698,31699,31700,31701,31702,31703,31704,31705,31706,31707,31708,31709,31710,31711,31712,31713,31714,31715,31716,31717,31718,31719,31720,31721,31722,31723,31724,31725,31726,31727,31728,31729,31730,31731,31732,31733,31734,31735,31736,31737,31738,31739,31740,31741,31742,31743,31744,31745,31746,31747,31748,31749,31750,31751,31752,31753,31754,31755,31756,31757,31758,31759,31760,31761,31762,31763,31764,31765,31766,31767,31768,31769,31770,31771,31772,31773,31774,31775,31776,31777,31778,31779,31780,31781,31782,31783,31784,31785,31786,31787,31788,31789,31790,31791,31792,31793,31794,31795,31796,31797,31798,31799,31800,31801,31802,31803,31804,31805,31806,31807,31808,31809,31810,31811,31812,31813,31814,31815,31816,31817,31818,31819,31820,31821,31822,31823,31824,31825,31826,31827,31828,31829,31830,31831,31832,31833,31834,31835,31836,31837,31838,31839,31840,31841,31842,31843,31844,31845,31846,31847,31848,31849,31850,31851,31852,31853,31854,31855,31856,31857,31858,31859,31860,31861,31862,31863,31864,31865,31866,31867,31868,31869,31870,31871,31872,31873,31874,31875,31876,31877,31878,31879,31880,31881,31882,31883,31884,31885,31886,31887,31888,31889,31890,31891,31892,31893,31894,31895,31896,31897,31898,31899,31900,31901,31902,31903,31904,31905,31906,31907,31908,31909,31910,31911,31912,31913,31914,31915,31916,31917,31918,31919,31920,31921,31922,31923,31924,31925,31926,31927,31928,31929,31930,31931,31932,31933,31934,31935,31936,31937,31938,31939,31940,31941,31942,31943,31944,31945,31946,31947,31948,31949,31950,31951,31952,31953,31954,31955,31956,31957,31958,31959,31960,31961,31962,31963,31964,31965,31966,31967,31968,31969,31970,31971,31972,31973,31974,31975,31976,31977,31978,31979,31980,31981,31982,31983,31984,31985,31986,31987,31988,31989,31990,31991,31992,31993,31994,31995,31996,31997,31998,31999,32000,32001,32002,32003,32004,32005,32006,32007,32008,32009,32010,32011,32012,32013,32014,32015,32016,32017,32018,32019,32020,32021,32022,32023,32024,32025,32026,32027,32028,32029,32030,32031,32032,32033,32034,32035,32036,32037,32038,32039,32040,32041,32042,32043,32044,32045,32046,32047,32048,32049,32050,32051,32052,32053,32054,32055,32056,32057,32058,32059,32060,32061,32062,32063,32064,32065,32066,32067,32068,32069,32070,32071,32072,32073,32074,32075,32076,32077,32078,32079,32080,32081,32082,32083,32084,32085,32086,32087,32088,32089,32090,32091,32092,32093,32094,32095,32096,32097,32098,32099,32100,32101,32102,32103,32104,32105,32106,32107,32108,32109,32110,32111,32112,32113,32114,32115,32116,32117,32118,32119,32120,32121,32122,32123,32124,32125,32126,32127,32128,32129,32130,32131,32132,32133,32134,32135,32136,32137,32138,32139,32140,32141,32142,32143,32144,32145,32146,32147,32148,32149,32150,32151,32152,32153,32154,32155,32156,32157,32158,32159,32160,32161,32162,32163,32164,32165,32166,32167,32168,32169,32170,32171,32172,32173,32174,32175,32176,32177,32178,32179,32180,32181,32182,32183,32184,32185,32186,32187,32188,32189,32190,32191,32192,32193,32194,32195,32196,32197,32198,32199,32200,32201,32202,32203,32204,32205,32206,32207,32208,32209,32210,32211,32212,32213,32214,32215,32216,32217,32218,32219,32220,32221,32222,32223,32224,32225,32226,32227,32228,32229,32230,32231,32232,32233,32234,32235,32236,32237,32238,32239,32240,32241,32242,32243,32244,32245,32246,32247,32248,32249,32250,32251,32252,32253,32254,32255,32256,32257,32258,32259,32260,32261,32262,32263,32264,32265,32266,32267,32268,32269,32270,32271,32272,32273,32274,32275,32276,32277,32278,32279,32280,32281,32282,32283,32284,32285,32286,32287,32288,32289,32290,32291,32292,32293,32294,32295,32296,32297,32298,32299,32300,32301,32302,32303,32304,32305,32306,32307,32308,32309,32310,32311,32312,32313,32314,32315,32316,32317,32318,32319,32320,32321,32322,32323,32324,32325,32326,32327,32328,32329,32330,32331,32332,32333,32334,32335,32336,32337,32338,32339,32340,32341,32342,32343,32344,32345,32346,32347,32348,32349,32350,32351,32352,32353,32354,32355,32356,32357,32358,32359,32360,32361,32362,32363,32364,32365,32366,32367,32368,32369,32370,32371,32372,32373,32374,32375,32376,32377,32378,32379,32380,32381,32382,32383,32384,32385,32386,32387,32388,32389,32390,32391,32392,32393,32394,32395,32396,32397,32398,32399,32400,32401,32402,32403,32404,32405,32406,32407,32408,32409,32410,32411,32412,32413,32414,32415,32416,32417,32418,32419,32420,32421,32422,32423,32424,32425,32426,32427,32428,32429,32430,32431,32432,32433,32434,32435,32436,32437,32438,32439,32440,32441,32442,32443,32444,32445,32446,32447,32448,32449,32450,32451,32452,32453,32454,32455,32456,32457,32458,32459,32460,32461,32462,32463,32464,32465,32466,32467,32468,32469,32470,32471,32472,32473,32474,32475,32476,32477,32478,32479,32480,32481,32482,32483,32484,32485,32486,32487,32488,32489,32490,32491,32492,32493,32494,32495,32496,32497,32498,32499,32500,32501,32502,32503,32504,32505,32506,32507,32508,32509,32510,32511,32512,32513,32514,32515,32516,32517,32518,32519,32520,32521,32522,32523,32524,32525,32526,32527,32528,32529,32530,32531,32532,32533,32534,32535,32536,32537,32538,32539,32540,32541,32542,32543,32544,32545,32546,32547,32548,32549,32550,32551,32552,32553,32554,32555,32556,32557,32558,32559,32560,32561,32562,32563,32564,32565,32566,32567,32568,32569,32570,32571,32572,32573,32574,32575,32576,32577,32578,32579,32580,32581,32582,32583,32584,32585,32586,32587,32588,32589,32590,32591,32592,32593,32594,32595,32596,32597,32598,32599,32600,32601,32602,32603,32604,32605,32606,32607,32608,32609,32610,32611,32612,32613,32614,32615,32616,32617,32618,32619,32620,32621,32622,32623,32624,32625,32626,32627,32628,32629,32630,32631,32632,32633,32634,32635,32636,32637,32638,32639,32640,32641,32642,32643,32644,32645,32646,32647,32648,32649,32650,32651,32652,32653,32654,32655,32656,32657,32658,32659,32660,32661,32662,32663,32664,32665,32666,32667,32668,32669,32670,32671,32672,32673,32674,32675,32676,32677,32678,32679,32680,32681,32682,32683,32684,32685,32686,32687,32688,32689,32690,32691,32692,32693,32694,32695,32696,32697,32698,32699,32700,32701,32702,32703,32704,32705,32706,32707,32708,32709,32710,32711,32712,32713,32714,32715,32716,32717,32718,32719,32720,32721,32722,32723,32724,32725,32726,32727,32728,32729,32730,32731,32732,32733,32734,32735,32736,32737,32738,32739,32740,32741,32742,32743,32744,32745,32746,32747,32748,32749,32750,32751,32752,32753,32754,32755,32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768,32769,32770,32771,32772,32773,32774,32775,32776,32777,32778,32779,32780,32781,32782,32783,32784,32785,32786,32787,32788,32789,32790,32791,32792,32793,32794,32795,32796,32797,32798,32799,32800,32801,32802,32803,32804,32805,32806,32807,32808,32809,32810,32811,32812,32813,32814,32815,32816,32817,32818,32819,32820,32821,32822,32823,32824,32825,32826,32827,32828,32829,32830,32831,32832,32833,32834,32835,32836,32837,32838,32839,32840,32841,32842,32843,32844,32845,32846,32847,32848,32849,32850,32851,32852,32853,32854,32855,32856,32857,32858,32859,32860,32861,32862,32863,32864,32865,32866,32867,32868,32869,32870,32871,32872,32873,32874,32875,32876,32877,32878,32879,32880,32881,32882,32883,32884,32885,32886,32887,32888,32889,32890,32891,32892,32893,32894,32895,32896,32897,32898,32899,32900,32901,32902,32903,32904,32905,32906,32907,32908,32909,32910,32911,32912,32913,32914,32915,32916,32917,32918,32919,32920,32921,32922,32923,32924,32925,32926,32927,32928,32929,32930,32931,32932,32933,32934,32935,32936,32937,32938,32939,32940,32941,32942,32943,32944,32945,32946,32947,32948,32949,32950,32951,32952,32953,32954,32955,32956,32957,32958,32959,32960,32961,32962,32963,32964,32965,32966,32967,32968,32969,32970,32971,32972,32973,32974,32975,32976,32977,32978,32979,32980,32981,32982,32983,32984,32985,32986,32987,32988,32989,32990,32991,32992,32993,32994,32995,32996,32997,32998,32999,33000,33001,33002,33003,33004,33005,33006,33007,33008,33009,33010,33011,33012,33013,33014,33015,33016,33017,33018,33019,33020,33021,33022,33023,33024,33025,33026,33027,33028,33029,33030,33031,33032,33033,33034,33035,33036,33037,33038,33039,33040,33041,33042,33043,33044,33045,33046,33047,33048,33049,33050,33051,33052,33053,33054,33055,33056,33057,33058,33059,33060,33061,33062,33063,33064,33065,33066,33067,33068,33069,33070,33071,33072,33073,33074,33075,33076,33077,33078,33079,33080,33081,33082,33083,33084,33085,33086,33087,33088,33089,33090,33091,33092,33093,33094,33095,33096,33097,33098,33099,33100,33101,33102,33103,33104,33105,33106,33107,33108,33109,33110,33111,33112,33113,33114,33115,33116,33117,33118,33119,33120,33121,33122,33123,33124,33125,33126,33127,33128,33129,33130,33131,33132,33133,33134,33135,33136,33137,33138,33139,33140,33141,33142,33143,33144,33145,33146,33147,33148,33149,33150,33151,33152,33153,33154,33155,33156,33157,33158,33159,33160,33161,33162,33163,33164,33165,33166,33167,33168,33169,33170,33171,33172,33173,33174,33175,33176,33177,33178,33179,33180,33181,33182,33183,33184,33185,33186,33187,33188,33189,33190,33191,33192,33193,33194,33195,33196,33197,33198,33199,33200,33201,33202,33203,33204,33205,33206,33207,33208,33209,33210,33211,33212,33213,33214,33215,33216,33217,33218,33219,33220,33221,33222,33223,33224,33225,33226,33227,33228,33229,33230,33231,33232,33233,33234,33235,33236,33237,33238,33239,33240,33241,33242,33243,33244,33245,33246,33247,33248,33249,33250,33251,33252,33253,33254,33255,33256,33257,33258,33259,33260,33261,33262,33263,33264,33265,33266,33267,33268,33269,33270,33271,33272,33273,33274,33275,33276,33277,33278,33279,33280,33281,33282,33283,33284,33285,33286,33287,33288,33289,33290,33291,33292,33293,33294,33295,33296,33297,33298,33299,33300,33301,33302,33303,33304,33305,33306,33307,33308,33309,33310,33311,33312,33313,33314,33315,33316,33317,33318,33319,33320,33321,33322,33323,33324,33325,33326,33327,33328,33329,33330,33331,33332,33333,33334,33335,33336,33337,33338,33339,33340,33341,33342,33343,33344,33345,33346,33347,33348,33349,33350,33351,33352,33353,33354,33355,33356,33357,33358,33359,33360,33361,33362,33363,33364,33365,33366,33367,33368,33369,33370,33371,33372,33373,33374,33375,33376,33377,33378,33379,33380,33381,33382,33383,33384,33385,33386,33387,33388,33389,33390,33391,33392,33393,33394,33395,33396,33397,33398,33399,33400,33401,33402,33403,33404,33405,33406,33407,33408,33409,33410,33411,33412,33413,33414,33415,33416,33417,33418,33419,33420,33421,33422,33423,33424,33425,33426,33427,33428,33429,33430,33431,33432,33433,33434,33435,33436,33437,33438,33439,33440,33441,33442,33443,33444,33445,33446,33447,33448,33449,33450,33451,33452,33453,33454,33455,33456,33457,33458,33459,33460,33461,33462,33463,33464,33465,33466,33467,33468,33469,33470,33471,33472,33473,33474,33475,33476,33477,33478,33479,33480,33481,33482,33483,33484,33485,33486,33487,33488,33489,33490,33491,33492,33493,33494,33495,33496,33497,33498,33499,33500,33501,33502,33503,33504,33505,33506,33507,33508,33509,33510,33511,33512,33513,33514,33515,33516,33517,33518,33519,33520,33521,33522,33523,33524,33525,33526,33527,33528,33529,33530,33531,33532,33533,33534,33535,33536,33537,33538,33539,33540,33541,33542,33543,33544,33545,33546,33547,33548,33549,33550,33551,33552,33553,33554,33555,33556,33557,33558,33559,33560,33561,33562,33563,33564,33565,33566,33567,33568,33569,33570,33571,33572,33573,33574,33575,33576,33577,33578,33579,33580,33581,33582,33583,33584,33585,33586,33587,33588,33589,33590,33591,33592,33593,33594,33595,33596,33597,33598,33599,33600,33601,33602,33603,33604,33605,33606,33607,33608,33609,33610,33611,33612,33613,33614,33615,33616,33617,33618,33619,33620,33621,33622,33623,33624,33625,33626,33627,33628,33629,33630,33631,33632,33633,33634,33635,33636,33637,33638,33639,33640,33641,33642,33643,33644,33645,33646,33647,33648,33649,33650,33651,33652,33653,33654,33655,33656,33657,33658,33659,33660,33661,33662,33663,33664,33665,33666,33667,33668,33669,33670,33671,33672,33673,33674,33675,33676,33677,33678,33679,33680,33681,33682,33683,33684,33685,33686,33687,33688,33689,33690,33691,33692,33693,33694,33695,33696,33697,33698,33699,33700,33701,33702,33703,33704,33705,33706,33707,33708,33709,33710,33711,33712,33713,33714,33715,33716,33717,33718,33719,33720,33721,33722,33723,33724,33725,33726,33727,33728,33729,33730,33731,33732,33733,33734,33735,33736,33737,33738,33739,33740,33741,33742,33743,33744,33745,33746,33747,33748,33749,33750,33751,33752,33753,33754,33755,33756,33757,33758,33759,33760,33761,33762,33763,33764,33765,33766,33767,33768,33769,33770,33771,33772,33773,33774,33775,33776,33777,33778,33779,33780,33781,33782,33783,33784,33785,33786,33787,33788,33789,33790,33791,33792,33793,33794,33795,33796,33797,33798,33799,33800,33801,33802,33803,33804,33805,33806,33807,33808,33809,33810,33811,33812,33813,33814,33815,33816,33817,33818,33819,33820,33821,33822,33823,33824,33825,33826,33827,33828,33829,33830,33831,33832,33833,33834,33835,33836,33837,33838,33839,33840,33841,33842,33843,33844,33845,33846,33847,33848,33849,33850,33851,33852,33853,33854,33855,33856,33857,33858,33859,33860,33861,33862,33863,33864,33865,33866,33867,33868,33869,33870,33871,33872,33873,33874,33875,33876,33877,33878,33879,33880,33881,33882,33883,33884,33885,33886,33887,33888,33889,33890,33891,33892,33893,33894,33895,33896,33897,33898,33899,33900,33901,33902,33903,33904,33905,33906,33907,33908,33909,33910,33911,33912,33913,33914,33915,33916,33917,33918,33919,33920,33921,33922,33923,33924,33925,33926,33927,33928,33929,33930,33931,33932,33933,33934,33935,33936,33937,33938,33939,33940,33941,33942,33943,33944,33945,33946,33947,33948,33949,33950,33951,33952,33953,33954,33955,33956,33957,33958,33959,33960,33961,33962,33963,33964,33965,33966,33967,33968,33969,33970,33971,33972,33973,33974,33975,33976,33977,33978,33979,33980,33981,33982,33983,33984,33985,33986,33987,33988,33989,33990,33991,33992,33993,33994,33995,33996,33997,33998,33999,34000,34001,34002,34003,34004,34005,34006,34007,34008,34009,34010,34011,34012,34013,34014,34015,34016,34017,34018,34019,34020,34021,34022,34023,34024,34025,34026,34027,34028,34029,34030,34031,34032,34033,34034,34035,34036,34037,34038,34039,34040,34041,34042,34043,34044,34045,34046,34047,34048,34049,34050,34051,34052,34053,34054,34055,34056,34057,34058,34059,34060,34061,34062,34063,34064,34065,34066,34067,34068,34069,34070,34071,34072,34073,34074,34075,34076,34077,34078,34079,34080,34081,34082,34083,34084,34085,34086,34087,34088,34089,34090,34091,34092,34093,34094,34095,34096,34097,34098,34099,34100,34101,34102,34103,34104,34105,34106,34107,34108,34109,34110,34111,34112,34113,34114,34115,34116,34117,34118,34119,34120,34121,34122,34123,34124,34125,34126,34127,34128,34129,34130,34131,34132,34133,34134,34135,34136,34137,34138,34139,34140,34141,34142,34143,34144,34145,34146,34147,34148,34149,34150,34151,34152,34153,34154,34155,34156,34157,34158,34159,34160,34161,34162,34163,34164,34165,34166,34167,34168,34169,34170,34171,34172,34173,34174,34175,34176,34177,34178,34179,34180,34181,34182,34183,34184,34185,34186,34187,34188,34189,34190,34191,34192,34193,34194,34195,34196,34197,34198,34199,34200,34201,34202,34203,34204,34205,34206,34207,34208,34209,34210,34211,34212,34213,34214,34215,34216,34217,34218,34219,34220,34221,34222,34223,34224,34225,34226,34227,34228,34229,34230,34231,34232,34233,34234,34235,34236,34237,34238,34239,34240,34241,34242,34243,34244,34245,34246,34247,34248,34249,34250,34251,34252,34253,34254,34255,34256,34257,34258,34259,34260,34261,34262,34263,34264,34265,34266,34267,34268,34269,34270,34271,34272,34273,34274,34275,34276,34277,34278,34279,34280,34281,34282,34283,34284,34285,34286,34287,34288,34289,34290,34291,34292,34293,34294,34295,34296,34297,34298,34299,34300,34301,34302,34303,34304,34305,34306,34307,34308,34309,34310,34311,34312,34313,34314,34315,34316,34317,34318,34319,34320,34321,34322,34323,34324,34325,34326,34327,34328,34329,34330,34331,34332,34333,34334,34335,34336,34337,34338,34339,34340,34341,34342,34343,34344,34345,34346,34347,34348,34349,34350,34351,34352,34353,34354,34355,34356,34357,34358,34359,34360,34361,34362,34363,34364,34365,34366,34367,34368,34369,34370,34371,34372,34373,34374,34375,34376,34377,34378,34379,34380,34381,34382,34383,34384,34385,34386,34387,34388,34389,34390,34391,34392,34393,34394,34395,34396,34397,34398,34399,34400,34401,34402,34403,34404,34405,34406,34407,34408,34409,34410,34411,34412,34413,34414,34415,34416,34417,34418,34419,34420,34421,34422,34423,34424,34425,34426,34427,34428,34429,34430,34431,34432,34433,34434,34435,34436,34437,34438,34439,34440,34441,34442,34443,34444,34445,34446,34447,34448,34449,34450,34451,34452,34453,34454,34455,34456,34457,34458,34459,34460,34461,34462,34463,34464,34465,34466,34467,34468,34469,34470,34471,34472,34473,34474,34475,34476,34477,34478,34479,34480,34481,34482,34483,34484,34485,34486,34487,34488,34489,34490,34491,34492,34493,34494,34495,34496,34497,34498,34499,34500,34501,34502,34503,34504,34505,34506,34507,34508,34509,34510,34511,34512,34513,34514,34515,34516,34517,34518,34519,34520,34521,34522,34523,34524,34525,34526,34527,34528,34529,34530,34531,34532,34533,34534,34535,34536,34537,34538,34539,34540,34541,34542,34543,34544,34545,34546,34547,34548,34549,34550,34551,34552,34553,34554,34555,34556,34557,34558,34559,34560,34561,34562,34563,34564,34565,34566,34567,34568,34569,34570,34571,34572,34573,34574,34575,34576,34577,34578,34579,34580,34581,34582,34583,34584,34585,34586,34587,34588,34589,34590,34591,34592,34593,34594,34595,34596,34597,34598,34599,34600,34601,34602,34603,34604,34605,34606,34607,34608,34609,34610,34611,34612,34613,34614,34615,34616,34617,34618,34619,34620,34621,34622,34623,34624,34625,34626,34627,34628,34629,34630,34631,34632,34633,34634,34635,34636,34637,34638,34639,34640,34641,34642,34643,34644,34645,34646,34647,34648,34649,34650,34651,34652,34653,34654,34655,34656,34657,34658,34659,34660,34661,34662,34663,34664,34665,34666,34667,34668,34669,34670,34671,34672,34673,34674,34675,34676,34677,34678,34679,34680,34681,34682,34683,34684,34685,34686,34687,34688,34689,34690,34691,34692,34693,34694,34695,34696,34697,34698,34699,34700,34701,34702,34703,34704,34705,34706,34707,34708,34709,34710,34711,34712,34713,34714,34715,34716,34717,34718,34719,34720,34721,34722,34723,34724,34725,34726,34727,34728,34729,34730,34731,34732,34733,34734,34735,34736,34737,34738,34739,34740,34741,34742,34743,34744,34745,34746,34747,34748,34749,34750,34751,34752,34753,34754,34755,34756,34757,34758,34759,34760,34761,34762,34763,34764,34765,34766,34767,34768,34769,34770,34771,34772,34773,34774,34775,34776,34777,34778,34779,34780,34781,34782,34783,34784,34785,34786,34787,34788,34789,34790,34791,34792,34793,34794,34795,34796,34797,34798,34799,34800,34801,34802,34803,34804,34805,34806,34807,34808,34809,34810,34811,34812,34813,34814,34815,34816,34817,34818,34819,34820,34821,34822,34823,34824,34825,34826,34827,34828,34829,34830,34831,34832,34833,34834,34835,34836,34837,34838,34839,34840,34841,34842,34843,34844,34845,34846,34847,34848,34849,34850,34851,34852,34853,34854,34855,34856,34857,34858,34859,34860,34861,34862,34863,34864,34865,34866,34867,34868,34869,34870,34871,34872,34873,34874,34875,34876,34877,34878,34879,34880,34881,34882,34883,34884,34885,34886,34887,34888,34889,34890,34891,34892,34893,34894,34895,34896,34897,34898,34899,34900,34901,34902,34903,34904,34905,34906,34907,34908,34909,34910,34911,34912,34913,34914,34915,34916,34917,34918,34919,34920,34921,34922,34923,34924,34925,34926,34927,34928,34929,34930,34931,34932,34933,34934,34935,34936,34937,34938,34939,34940,34941,34942,34943,34944,34945,34946,34947,34948,34949,34950,34951,34952,34953,34954,34955,34956,34957,34958,34959,34960,34961,34962,34963,34964,34965,34966,34967,34968,34969,34970,34971,34972,34973,34974,34975,34976,34977,34978,34979,34980,34981,34982,34983,34984,34985,34986,34987,34988,34989,34990,34991,34992,34993,34994,34995,34996,34997,34998,34999,35000,35001,35002,35003,35004,35005,35006,35007,35008,35009,35010,35011,35012,35013,35014,35015,35016,35017,35018,35019,35020,35021,35022,35023,35024,35025,35026,35027,35028,35029,35030,35031,35032,35033,35034,35035,35036,35037,35038,35039,35040,35041,35042,35043,35044,35045,35046,35047,35048,35049,35050,35051,35052,35053,35054,35055,35056,35057,35058,35059,35060,35061,35062,35063,35064,35065,35066,35067,35068,35069,35070,35071,35072,35073,35074,35075,35076,35077,35078,35079,35080,35081,35082,35083,35084,35085,35086,35087,35088,35089,35090,35091,35092,35093,35094,35095,35096,35097,35098,35099,35100,35101,35102,35103,35104,35105,35106,35107,35108,35109,35110,35111,35112,35113,35114,35115,35116,35117,35118,35119,35120,35121,35122,35123,35124,35125,35126,35127,35128,35129,35130,35131,35132,35133,35134,35135,35136,35137,35138,35139,35140,35141,35142,35143,35144,35145,35146,35147,35148,35149,35150,35151,35152,35153,35154,35155,35156,35157,35158,35159,35160,35161,35162,35163,35164,35165,35166,35167,35168,35169,35170,35171,35172,35173,35174,35175,35176,35177,35178,35179,35180,35181,35182,35183,35184,35185,35186,35187,35188,35189,35190,35191,35192,35193,35194,35195,35196,35197,35198,35199,35200,35201,35202,35203,35204,35205,35206,35207,35208,35209,35210,35211,35212,35213,35214,35215,35216,35217,35218,35219,35220,35221,35222,35223,35224,35225,35226,35227,35228,35229,35230,35231,35232,35233,35234,35235,35236,35237,35238,35239,35240,35241,35242,35243,35244,35245,35246,35247,35248,35249,35250,35251,35252,35253,35254,35255,35256,35257,35258,35259,35260,35261,35262,35263,35264,35265,35266,35267,35268,35269,35270,35271,35272,35273,35274,35275,35276,35277,35278,35279,35280,35281,35282,35283,35284,35285,35286,35287,35288,35289,35290,35291,35292,35293,35294,35295,35296,35297,35298,35299,35300,35301,35302,35303,35304,35305,35306,35307,35308,35309,35310,35311,35312,35313,35314,35315,35316,35317,35318,35319,35320,35321,35322,35323,35324,35325,35326,35327,35328,35329,35330,35331,35332,35333,35334,35335,35336,35337,35338,35339,35340,35341,35342,35343,35344,35345,35346,35347,35348,35349,35350,35351,35352,35353,35354,35355,35356,35357,35358,35359,35360,35361,35362,35363,35364,35365,35366,35367,35368,35369,35370,35371,35372,35373,35374,35375,35376,35377,35378,35379,35380,35381,35382,35383,35384,35385,35386,35387,35388,35389,35390,35391,35392,35393,35394,35395,35396,35397,35398,35399,35400,35401,35402,35403,35404,35405,35406,35407,35408,35409,35410,35411,35412,35413,35414,35415,35416,35417,35418,35419,35420,35421,35422,35423,35424,35425,35426,35427,35428,35429,35430,35431,35432,35433,35434,35435,35436,35437,35438,35439,35440,35441,35442,35443,35444,35445,35446,35447,35448,35449,35450,35451,35452,35453,35454,35455,35456,35457,35458,35459,35460,35461,35462,35463,35464,35465,35466,35467,35468,35469,35470,35471,35472,35473,35474,35475,35476,35477,35478,35479,35480,35481,35482,35483,35484,35485,35486,35487,35488,35489,35490,35491,35492,35493,35494,35495,35496,35497,35498,35499,35500,35501,35502,35503,35504,35505,35506,35507,35508,35509,35510,35511,35512,35513,35514,35515,35516,35517,35518,35519,35520,35521,35522,35523,35524,35525,35526,35527,35528,35529,35530,35531,35532,35533,35534,35535,35536,35537,35538,35539,35540,35541,35542,35543,35544,35545,35546,35547,35548,35549,35550,35551,35552,35553,35554,35555,35556,35557,35558,35559,35560,35561,35562,35563,35564,35565,35566,35567,35568,35569,35570,35571,35572,35573,35574,35575,35576,35577,35578,35579,35580,35581,35582,35583,35584,35585,35586,35587,35588,35589,35590,35591,35592,35593,35594,35595,35596,35597,35598,35599,35600,35601,35602,35603,35604,35605,35606,35607,35608,35609,35610,35611,35612,35613,35614,35615,35616,35617,35618,35619,35620,35621,35622,35623,35624,35625,35626,35627,35628,35629,35630,35631,35632,35633,35634,35635,35636,35637,35638,35639,35640,35641,35642,35643,35644,35645,35646,35647,35648,35649,35650,35651,35652,35653,35654,35655,35656,35657,35658,35659,35660,35661,35662,35663,35664,35665,35666,35667,35668,35669,35670,35671,35672,35673,35674,35675,35676,35677,35678,35679,35680,35681,35682,35683,35684,35685,35686,35687,35688,35689,35690,35691,35692,35693,35694,35695,35696,35697,35698,35699,35700,35701,35702,35703,35704,35705,35706,35707,35708,35709,35710,35711,35712,35713,35714,35715,35716,35717,35718,35719,35720,35721,35722,35723,35724,35725,35726,35727,35728,35729,35730,35731,35732,35733,35734,35735,35736,35737,35738,35739,35740,35741,35742,35743,35744,35745,35746,35747,35748,35749,35750,35751,35752,35753,35754,35755,35756,35757,35758,35759,35760,35761,35762,35763,35764,35765,35766,35767,35768,35769,35770,35771,35772,35773,35774,35775,35776,35777,35778,35779,35780,35781,35782,35783,35784,35785,35786,35787,35788,35789,35790,35791,35792,35793,35794,35795,35796,35797,35798,35799,35800,35801,35802,35803,35804,35805,35806,35807,35808,35809,35810,35811,35812,35813,35814,35815,35816,35817,35818,35819,35820,35821,35822,35823,35824,35825,35826,35827,35828,35829,35830,35831,35832,35833,35834,35835,35836,35837,35838,35839,35840,35841,35842,35843,35844,35845,35846,35847,35848,35849,35850,35851,35852,35853,35854,35855,35856,35857,35858,35859,35860,35861,35862,35863,35864,35865,35866,35867,35868,35869,35870,35871,35872,35873,35874,35875,35876,35877,35878,35879,35880,35881,35882,35883,35884,35885,35886,35887,35888,35889,35890,35891,35892,35893,35894,35895,35896,35897,35898,35899,35900,35901,35902,35903,35904,35905,35906,35907,35908,35909,35910,35911,35912,35913,35914,35915,35916,35917,35918,35919,35920,35921,35922,35923,35924,35925,35926,35927,35928,35929,35930,35931,35932,35933,35934,35935,35936,35937,35938,35939,35940,35941,35942,35943,35944,35945,35946,35947,35948,35949,35950,35951,35952,35953,35954,35955,35956,35957,35958,35959,35960,35961,35962,35963,35964,35965,35966,35967,35968,35969,35970,35971,35972,35973,35974,35975,35976,35977,35978,35979,35980,35981,35982,35983,35984,35985,35986,35987,35988,35989,35990,35991,35992,35993,35994,35995,35996,35997,35998,35999,36000,36001,36002,36003,36004,36005,36006,36007,36008,36009,36010,36011,36012,36013,36014,36015,36016,36017,36018,36019,36020,36021,36022,36023,36024,36025,36026,36027,36028,36029,36030,36031,36032,36033,36034,36035,36036,36037,36038,36039,36040,36041,36042,36043,36044,36045,36046,36047,36048,36049,36050,36051,36052,36053,36054,36055,36056,36057,36058,36059,36060,36061,36062,36063,36064,36065,36066,36067,36068,36069,36070,36071,36072,36073,36074,36075,36076,36077,36078,36079,36080,36081,36082,36083,36084,36085,36086,36087,36088,36089,36090,36091,36092,36093,36094,36095,36096,36097,36098,36099,36100,36101,36102,36103,36104,36105,36106,36107,36108,36109,36110,36111,36112,36113,36114,36115,36116,36117,36118,36119,36120,36121,36122,36123,36124,36125,36126,36127,36128,36129,36130,36131,36132,36133,36134,36135,36136,36137,36138,36139,36140,36141,36142,36143,36144,36145,36146,36147,36148,36149,36150,36151,36152,36153,36154,36155,36156,36157,36158,36159,36160,36161,36162,36163,36164,36165,36166,36167,36168,36169,36170,36171,36172,36173,36174,36175,36176,36177,36178,36179,36180,36181,36182,36183,36184,36185,36186,36187,36188,36189,36190,36191,36192,36193,36194,36195,36196,36197,36198,36199,36200,36201,36202,36203,36204,36205,36206,36207,36208,36209,36210,36211,36212,36213,36214,36215,36216,36217,36218,36219,36220,36221,36222,36223,36224,36225,36226,36227,36228,36229,36230,36231,36232,36233,36234,36235,36236,36237,36238,36239,36240,36241,36242,36243,36244,36245,36246,36247,36248,36249,36250,36251,36252,36253,36254,36255,36256,36257,36258,36259,36260,36261,36262,36263,36264,36265,36266,36267,36268,36269,36270,36271,36272,36273,36274,36275,36276,36277,36278,36279,36280,36281,36282,36283,36284,36285,36286,36287,36288,36289,36290,36291,36292,36293,36294,36295,36296,36297,36298,36299,36300,36301,36302,36303,36304,36305,36306,36307,36308,36309,36310,36311,36312,36313,36314,36315,36316,36317,36318,36319,36320,36321,36322,36323,36324,36325,36326,36327,36328,36329,36330,36331,36332,36333,36334,36335,36336,36337,36338,36339,36340,36341,36342,36343,36344,36345,36346,36347,36348,36349,36350,36351,36352,36353,36354,36355,36356,36357,36358,36359,36360,36361,36362,36363,36364,36365,36366,36367,36368,36369,36370,36371,36372,36373,36374,36375,36376,36377,36378,36379,36380,36381,36382,36383,36384,36385,36386,36387,36388,36389,36390,36391,36392,36393,36394,36395,36396,36397,36398,36399,36400,36401,36402,36403,36404,36405,36406,36407,36408,36409,36410,36411,36412,36413,36414,36415,36416,36417,36418,36419,36420,36421,36422,36423,36424,36425,36426,36427,36428,36429,36430,36431,36432,36433,36434,36435,36436,36437,36438,36439,36440,36441,36442,36443,36444,36445,36446,36447,36448,36449,36450,36451,36452,36453,36454,36455,36456,36457,36458,36459,36460,36461,36462,36463,36464,36465,36466,36467,36468,36469,36470,36471,36472,36473,36474,36475,36476,36477,36478,36479,36480,36481,36482,36483,36484,36485,36486,36487,36488,36489,36490,36491,36492,36493,36494,36495,36496,36497,36498,36499,36500,36501,36502,36503,36504,36505,36506,36507,36508,36509,36510,36511,36512,36513,36514,36515,36516,36517,36518,36519,36520,36521,36522,36523,36524,36525,36526,36527,36528,36529,36530,36531,36532,36533,36534,36535,36536,36537,36538,36539,36540,36541,36542,36543,36544,36545,36546,36547,36548,36549,36550,36551,36552,36553,36554,36555,36556,36557,36558,36559,36560,36561,36562,36563,36564,36565,36566,36567,36568,36569,36570,36571,36572,36573,36574,36575,36576,36577,36578,36579,36580,36581,36582,36583,36584,36585,36586,36587,36588,36589,36590,36591,36592,36593,36594,36595,36596,36597,36598,36599,36600,36601,36602,36603,36604,36605,36606,36607,36608,36609,36610,36611,36612,36613,36614,36615,36616,36617,36618,36619,36620,36621,36622,36623,36624,36625,36626,36627,36628,36629,36630,36631,36632,36633,36634,36635,36636,36637,36638,36639,36640,36641,36642,36643,36644,36645,36646,36647,36648,36649,36650,36651,36652,36653,36654,36655,36656,36657,36658,36659,36660,36661,36662,36663,36664,36665,36666,36667,36668,36669,36670,36671,36672,36673,36674,36675,36676,36677,36678,36679,36680,36681,36682,36683,36684,36685,36686,36687,36688,36689,36690,36691,36692,36693,36694,36695,36696,36697,36698,36699,36700,36701,36702,36703,36704,36705,36706,36707,36708,36709,36710,36711,36712,36713,36714,36715,36716,36717,36718,36719,36720,36721,36722,36723,36724,36725,36726,36727,36728,36729,36730,36731,36732,36733,36734,36735,36736,36737,36738,36739,36740,36741,36742,36743,36744,36745,36746,36747,36748,36749,36750,36751,36752,36753,36754,36755,36756,36757,36758,36759,36760,36761,36762,36763,36764,36765,36766,36767,36768,36769,36770,36771,36772,36773,36774,36775,36776,36777,36778,36779,36780,36781,36782,36783,36784,36785,36786,36787,36788,36789,36790,36791,36792,36793,36794,36795,36796,36797,36798,36799,36800,36801,36802,36803,36804,36805,36806,36807,36808,36809,36810,36811,36812,36813,36814,36815,36816,36817,36818,36819,36820,36821,36822,36823,36824,36825,36826,36827,36828,36829,36830,36831,36832,36833,36834,36835,36836,36837,36838,36839,36840,36841,36842,36843,36844,36845,36846,36847,36848,36849,36850,36851,36852,36853,36854,36855,36856,36857,36858,36859,36860,36861,36862,36863,36864,36865,36866,36867,36868,36869,36870,36871,36872,36873,36874,36875,36876,36877,36878,36879,36880,36881,36882,36883,36884,36885,36886,36887,36888,36889,36890,36891,36892,36893,36894,36895,36896,36897,36898,36899,36900,36901,36902,36903,36904,36905,36906,36907,36908,36909,36910,36911,36912,36913,36914,36915,36916,36917,36918,36919,36920,36921,36922,36923,36924,36925,36926,36927,36928,36929,36930,36931,36932,36933,36934,36935,36936,36937,36938,36939,36940,36941,36942,36943,36944,36945,36946,36947,36948,36949,36950,36951,36952,36953,36954,36955,36956,36957,36958,36959,36960,36961,36962,36963,36964,36965,36966,36967,36968,36969,36970,36971,36972,36973,36974,36975,36976,36977,36978,36979,36980,36981,36982,36983,36984,36985,36986,36987,36988,36989,36990,36991,36992,36993,36994,36995,36996,36997,36998,36999,37000,37001,37002,37003,37004,37005,37006,37007,37008,37009,37010,37011,37012,37013,37014,37015,37016,37017,37018,37019,37020,37021,37022,37023,37024,37025,37026,37027,37028,37029,37030,37031,37032,37033,37034,37035,37036,37037,37038,37039,37040,37041,37042,37043,37044,37045,37046,37047,37048,37049,37050,37051,37052,37053,37054,37055,37056,37057,37058,37059,37060,37061,37062,37063,37064,37065,37066,37067,37068,37069,37070,37071,37072,37073,37074,37075,37076,37077,37078,37079,37080,37081,37082,37083,37084,37085,37086,37087,37088,37089,37090,37091,37092,37093,37094,37095,37096,37097,37098,37099,37100,37101,37102,37103,37104,37105,37106,37107,37108,37109,37110,37111,37112,37113,37114,37115,37116,37117,37118,37119,37120,37121,37122,37123,37124,37125,37126,37127,37128,37129,37130,37131,37132,37133,37134,37135,37136,37137,37138,37139,37140,37141,37142,37143,37144,37145,37146,37147,37148,37149,37150,37151,37152,37153,37154,37155,37156,37157,37158,37159,37160,37161,37162,37163,37164,37165,37166,37167,37168,37169,37170,37171,37172,37173,37174,37175,37176,37177,37178,37179,37180,37181,37182,37183,37184,37185,37186,37187,37188,37189,37190,37191,37192,37193,37194,37195,37196,37197,37198,37199,37200,37201,37202,37203,37204,37205,37206,37207,37208,37209,37210,37211,37212,37213,37214,37215,37216,37217,37218,37219,37220,37221,37222,37223,37224,37225,37226,37227,37228,37229,37230,37231,37232,37233,37234,37235,37236,37237,37238,37239,37240,37241,37242,37243,37244,37245,37246,37247,37248,37249,37250,37251,37252,37253,37254,37255,37256,37257,37258,37259,37260,37261,37262,37263,37264,37265,37266,37267,37268,37269,37270,37271,37272,37273,37274,37275,37276,37277,37278,37279,37280,37281,37282,37283,37284,37285,37286,37287,37288,37289,37290,37291,37292,37293,37294,37295,37296,37297,37298,37299,37300,37301,37302,37303,37304,37305,37306,37307,37308,37309,37310,37311,37312,37313,37314,37315,37316,37317,37318,37319,37320,37321,37322,37323,37324,37325,37326,37327,37328,37329,37330,37331,37332,37333,37334,37335,37336,37337,37338,37339,37340,37341,37342,37343,37344,37345,37346,37347,37348,37349,37350,37351,37352,37353,37354,37355,37356,37357,37358,37359,37360,37361,37362,37363,37364,37365,37366,37367,37368,37369,37370,37371,37372,37373,37374,37375,37376,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37387,37388,37389,37390,37391,37392,37393,37394,37395,37396,37397,37398,37399,37400,37401,37402,37403,37404,37405,37406,37407,37408,37409,37410,37411,37412,37413,37414,37415,37416,37417,37418,37419,37420,37421,37422,37423,37424,37425,37426,37427,37428,37429,37430,37431,37432,37433,37434,37435,37436,37437,37438,37439,37440,37441,37442,37443,37444,37445,37446,37447,37448,37449,37450,37451,37452,37453,37454,37455,37456,37457,37458,37459,37460,37461,37462,37463,37464,37465,37466,37467,37468,37469,37470,37471,37472,37473,37474,37475,37476,37477,37478,37479,37480,37481,37482,37483,37484,37485,37486,37487,37488,37489,37490,37491,37492,37493,37494,37495,37496,37497,37498,37499,37500,37501,37502,37503,37504,37505,37506,37507,37508,37509,37510,37511,37512,37513,37514,37515,37516,37517,37518,37519,37520,37521,37522,37523,37524,37525,37526,37527,37528,37529,37530,37531,37532,37533,37534,37535,37536,37537,37538,37539,37540,37541,37542,37543,37544,37545,37546,37547,37548,37549,37550,37551,37552,37553,37554,37555,37556,37557,37558,37559,37560,37561,37562,37563,37564,37565,37566,37567,37568,37569,37570,37571,37572,37573,37574,37575,37576,37577,37578,37579,37580,37581,37582,37583,37584,37585,37586,37587,37588,37589,37590,37591,37592,37593,37594,37595,37596,37597,37598,37599,37600,37601,37602,37603,37604,37605,37606,37607,37608,37609,37610,37611,37612,37613,37614,37615,37616,37617,37618,37619,37620,37621,37622,37623,37624,37625,37626,37627,37628,37629,37630,37631,37632,37633,37634,37635,37636,37637,37638,37639,37640,37641,37642,37643,37644,37645,37646,37647,37648,37649,37650,37651,37652,37653,37654,37655,37656,37657,37658,37659,37660,37661,37662,37663,37664,37665,37666,37667,37668,37669,37670,37671,37672,37673,37674,37675,37676,37677,37678,37679,37680,37681,37682,37683,37684,37685,37686,37687,37688,37689,37690,37691,37692,37693,37694,37695,37696,37697,37698,37699,37700,37701,37702,37703,37704,37705,37706,37707,37708,37709,37710,37711,37712,37713,37714,37715,37716,37717,37718,37719,37720,37721,37722,37723,37724,37725,37726,37727,37728,37729,37730,37731,37732,37733,37734,37735,37736,37737,37738,37739,37740,37741,37742,37743,37744,37745,37746,37747,37748,37749,37750,37751,37752,37753,37754,37755,37756,37757,37758,37759,37760,37761,37762,37763,37764,37765,37766,37767,37768,37769,37770,37771,37772,37773,37774,37775,37776,37777,37778,37779,37780,37781,37782,37783,37784,37785,37786,37787,37788,37789,37790,37791,37792,37793,37794,37795,37796,37797,37798,37799,37800,37801,37802,37803,37804,37805,37806,37807,37808,37809,37810,37811,37812,37813,37814,37815,37816,37817,37818,37819,37820,37821,37822,37823,37824,37825,37826,37827,37828,37829,37830,37831,37832,37833,37834,37835,37836,37837,37838,37839,37840,37841,37842,37843,37844,37845,37846,37847,37848,37849,37850,37851,37852,37853,37854,37855,37856,37857,37858,37859,37860,37861,37862,37863,37864,37865,37866,37867,37868,37869,37870,37871,37872,37873,37874,37875,37876,37877,37878,37879,37880,37881,37882,37883,37884,37885,37886,37887,37888,37889,37890,37891,37892,37893,37894,37895,37896,37897,37898,37899,37900,37901,37902,37903,37904,37905,37906,37907,37908,37909,37910,37911,37912,37913,37914,37915,37916,37917,37918,37919,37920,37921,37922,37923,37924,37925,37926,37927,37928,37929,37930,37931,37932,37933,37934,37935,37936,37937,37938,37939,37940,37941,37942,37943,37944,37945,37946,37947,37948,37949,37950,37951,37952,37953,37954,37955,37956,37957,37958,37959,37960,37961,37962,37963,37964,37965,37966,37967,37968,37969,37970,37971,37972,37973,37974,37975,37976,37977,37978,37979,37980,37981,37982,37983,37984,37985,37986,37987,37988,37989,37990,37991,37992,37993,37994,37995,37996,37997,37998,37999,38000,38001,38002,38003,38004,38005,38006,38007,38008,38009,38010,38011,38012,38013,38014,38015,38016,38017,38018,38019,38020,38021,38022,38023,38024,38025,38026,38027,38028,38029,38030,38031,38032,38033,38034,38035,38036,38037,38038,38039,38040,38041,38042,38043,38044,38045,38046,38047,38048,38049,38050,38051,38052,38053,38054,38055,38056,38057,38058,38059,38060,38061,38062,38063,38064,38065,38066,38067,38068,38069,38070,38071,38072,38073,38074,38075,38076,38077,38078,38079,38080,38081,38082,38083,38084,38085,38086,38087,38088,38089,38090,38091,38092,38093,38094,38095,38096,38097,38098,38099,38100,38101,38102,38103,38104,38105,38106,38107,38108,38109,38110,38111,38112,38113,38114,38115,38116,38117,38118,38119,38120,38121,38122,38123,38124,38125,38126,38127,38128,38129,38130,38131,38132,38133,38134,38135,38136,38137,38138,38139,38140,38141,38142,38143,38144,38145,38146,38147,38148,38149,38150,38151,38152,38153,38154,38155,38156,38157,38158,38159,38160,38161,38162,38163,38164,38165,38166,38167,38168,38169,38170,38171,38172,38173,38174,38175,38176,38177,38178,38179,38180,38181,38182,38183,38184,38185,38186,38187,38188,38189,38190,38191,38192,38193,38194,38195,38196,38197,38198,38199,38200,38201,38202,38203,38204,38205,38206,38207,38208,38209,38210,38211,38212,38213,38214,38215,38216,38217,38218,38219,38220,38221,38222,38223,38224,38225,38226,38227,38228,38229,38230,38231,38232,38233,38234,38235,38236,38237,38238,38239,38240,38241,38242,38243,38244,38245,38246,38247,38248,38249,38250,38251,38252,38253,38254,38255,38256,38257,38258,38259,38260,38261,38262,38263,38264,38265,38266,38267,38268,38269,38270,38271,38272,38273,38274,38275,38276,38277,38278,38279,38280,38281,38282,38283,38284,38285,38286,38287,38288,38289,38290,38291,38292,38293,38294,38295,38296,38297,38298,38299,38300,38301,38302,38303,38304,38305,38306,38307,38308,38309,38310,38311,38312,38313,38314,38315,38316,38317,38318,38319,38320,38321,38322,38323,38324,38325,38326,38327,38328,38329,38330,38331,38332,38333,38334,38335,38336,38337,38338,38339,38340,38341,38342,38343,38344,38345,38346,38347,38348,38349,38350,38351,38352,38353,38354,38355,38356,38357,38358,38359,38360,38361,38362,38363,38364,38365,38366,38367,38368,38369,38370,38371,38372,38373,38374,38375,38376,38377,38378,38379,38380,38381,38382,38383,38384,38385,38386,38387,38388,38389,38390,38391,38392,38393,38394,38395,38396,38397,38398,38399,38400,38401,38402,38403,38404,38405,38406,38407,38408,38409,38410,38411,38412,38413,38414,38415,38416,38417,38418,38419,38420,38421,38422,38423,38424,38425,38426,38427,38428,38429,38430,38431,38432,38433,38434,38435,38436,38437,38438,38439,38440,38441,38442,38443,38444,38445,38446,38447,38448,38449,38450,38451,38452,38453,38454,38455,38456,38457,38458,38459,38460,38461,38462,38463,38464,38465,38466,38467,38468,38469,38470,38471,38472,38473,38474,38475,38476,38477,38478,38479,38480,38481,38482,38483,38484,38485,38486,38487,38488,38489,38490,38491,38492,38493,38494,38495,38496,38497,38498,38499,38500,38501,38502,38503,38504,38505,38506,38507,38508,38509,38510,38511,38512,38513,38514,38515,38516,38517,38518,38519,38520,38521,38522,38523,38524,38525,38526,38527,38528,38529,38530,38531,38532,38533,38534,38535,38536,38537,38538,38539,38540,38541,38542,38543,38544,38545,38546,38547,38548,38549,38550,38551,38552,38553,38554,38555,38556,38557,38558,38559,38560,38561,38562,38563,38564,38565,38566,38567,38568,38569,38570,38571,38572,38573,38574,38575,38576,38577,38578,38579,38580,38581,38582,38583,38584,38585,38586,38587,38588,38589,38590,38591,38592,38593,38594,38595,38596,38597,38598,38599,38600,38601,38602,38603,38604,38605,38606,38607,38608,38609,38610,38611,38612,38613,38614,38615,38616,38617,38618,38619,38620,38621,38622,38623,38624,38625,38626,38627,38628,38629,38630,38631,38632,38633,38634,38635,38636,38637,38638,38639,38640,38641,38642,38643,38644,38645,38646,38647,38648,38649,38650,38651,38652,38653,38654,38655,38656,38657,38658,38659,38660,38661,38662,38663,38664,38665,38666,38667,38668,38669,38670,38671,38672,38673,38674,38675,38676,38677,38678,38679,38680,38681,38682,38683,38684,38685,38686,38687,38688,38689,38690,38691,38692,38693,38694,38695,38696,38697,38698,38699,38700,38701,38702,38703,38704,38705,38706,38707,38708,38709,38710,38711,38712,38713,38714,38715,38716,38717,38718,38719,38720,38721,38722,38723,38724,38725,38726,38727,38728,38729,38730,38731,38732,38733,38734,38735,38736,38737,38738,38739,38740,38741,38742,38743,38744,38745,38746,38747,38748,38749,38750,38751,38752,38753,38754,38755,38756,38757,38758,38759,38760,38761,38762,38763,38764,38765,38766,38767,38768,38769,38770,38771,38772,38773,38774,38775,38776,38777,38778,38779,38780,38781,38782,38783,38784,38785,38786,38787,38788,38789,38790,38791,38792,38793,38794,38795,38796,38797,38798,38799,38800,38801,38802,38803,38804,38805,38806,38807,38808,38809,38810,38811,38812,38813,38814,38815,38816,38817,38818,38819,38820,38821,38822,38823,38824,38825,38826,38827,38828,38829,38830,38831,38832,38833,38834,38835,38836,38837,38838,38839,38840,38841,38842,38843,38844,38845,38846,38847,38848,38849,38850,38851,38852,38853,38854,38855,38856,38857,38858,38859,38860,38861,38862,38863,38864,38865,38866,38867,38868,38869,38870,38871,38872,38873,38874,38875,38876,38877,38878,38879,38880,38881,38882,38883,38884,38885,38886,38887,38888,38889,38890,38891,38892,38893,38894,38895,38896,38897,38898,38899,38900,38901,38902,38903,38904,38905,38906,38907,38908,38909,38910,38911,38912,38913,38914,38915,38916,38917,38918,38919,38920,38921,38922,38923,38924,38925,38926,38927,38928,38929,38930,38931,38932,38933,38934,38935,38936,38937,38938,38939,38940,38941,38942,38943,38944,38945,38946,38947,38948,38949,38950,38951,38952,38953,38954,38955,38956,38957,38958,38959,38960,38961,38962,38963,38964,38965,38966,38967,38968,38969,38970,38971,38972,38973,38974,38975,38976,38977,38978,38979,38980,38981,38982,38983,38984,38985,38986,38987,38988,38989,38990,38991,38992,38993,38994,38995,38996,38997,38998,38999,39000,39001,39002,39003,39004,39005,39006,39007,39008,39009,39010,39011,39012,39013,39014,39015,39016,39017,39018,39019,39020,39021,39022,39023,39024,39025,39026,39027,39028,39029,39030,39031,39032,39033,39034,39035,39036,39037,39038,39039,39040,39041,39042,39043,39044,39045,39046,39047,39048,39049,39050,39051,39052,39053,39054,39055,39056,39057,39058,39059,39060,39061,39062,39063,39064,39065,39066,39067,39068,39069,39070,39071,39072,39073,39074,39075,39076,39077,39078,39079,39080,39081,39082,39083,39084,39085,39086,39087,39088,39089,39090,39091,39092,39093,39094,39095,39096,39097,39098,39099,39100,39101,39102,39103,39104,39105,39106,39107,39108,39109,39110,39111,39112,39113,39114,39115,39116,39117,39118,39119,39120,39121,39122,39123,39124,39125,39126,39127,39128,39129,39130,39131,39132,39133,39134,39135,39136,39137,39138,39139,39140,39141,39142,39143,39144,39145,39146,39147,39148,39149,39150,39151,39152,39153,39154,39155,39156,39157,39158,39159,39160,39161,39162,39163,39164,39165,39166,39167,39168,39169,39170,39171,39172,39173,39174,39175,39176,39177,39178,39179,39180,39181,39182,39183,39184,39185,39186,39187,39188,39189,39190,39191,39192,39193,39194,39195,39196,39197,39198,39199,39200,39201,39202,39203,39204,39205,39206,39207,39208,39209,39210,39211,39212,39213,39214,39215,39216,39217,39218,39219,39220,39221,39222,39223,39224,39225,39226,39227,39228,39229,39230,39231,39232,39233,39234,39235,39236,39237,39238,39239,39240,39241,39242,39243,39244,39245,39246,39247,39248,39249,39250,39251,39252,39253,39254,39255,39256,39257,39258,39259,39260,39261,39262,39263,39264,39265,39266,39267,39268,39269,39270,39271,39272,39273,39274,39275,39276,39277,39278,39279,39280,39281,39282,39283,39284,39285,39286,39287,39288,39289,39290,39291,39292,39293,39294,39295,39296,39297,39298,39299,39300,39301,39302,39303,39304,39305,39306,39307,39308,39309,39310,39311,39312,39313,39314,39315,39316,39317,39318,39319,39320,39321,39322,39323,39324,39325,39326,39327,39328,39329,39330,39331,39332,39333,39334,39335,39336,39337,39338,39339,39340,39341,39342,39343,39344,39345,39346,39347,39348,39349,39350,39351,39352,39353,39354,39355,39356,39357,39358,39359,39360,39361,39362,39363,39364,39365,39366,39367,39368,39369,39370,39371,39372,39373,39374,39375,39376,39377,39378,39379,39380,39381,39382,39383,39384,39385,39386,39387,39388,39389,39390,39391,39392,39393,39394,39395,39396,39397,39398,39399,39400,39401,39402,39403,39404,39405,39406,39407,39408,39409,39410,39411,39412,39413,39414,39415,39416,39417,39418,39419,39420,39421,39422,39423,39424,39425,39426,39427,39428,39429,39430,39431,39432,39433,39434,39435,39436,39437,39438,39439,39440,39441,39442,39443,39444,39445,39446,39447,39448,39449,39450,39451,39452,39453,39454,39455,39456,39457,39458,39459,39460,39461,39462,39463,39464,39465,39466,39467,39468,39469,39470,39471,39472,39473,39474,39475,39476,39477,39478,39479,39480,39481,39482,39483,39484,39485,39486,39487,39488,39489,39490,39491,39492,39493,39494,39495,39496,39497,39498,39499,39500,39501,39502,39503,39504,39505,39506,39507,39508,39509,39510,39511,39512,39513,39514,39515,39516,39517,39518,39519,39520,39521,39522,39523,39524,39525,39526,39527,39528,39529,39530,39531,39532,39533,39534,39535,39536,39537,39538,39539,39540,39541,39542,39543,39544,39545,39546,39547,39548,39549,39550,39551,39552,39553,39554,39555,39556,39557,39558,39559,39560,39561,39562,39563,39564,39565,39566,39567,39568,39569,39570,39571,39572,39573,39574,39575,39576,39577,39578,39579,39580,39581,39582,39583,39584,39585,39586,39587,39588,39589,39590,39591,39592,39593,39594,39595,39596,39597,39598,39599,39600,39601,39602,39603,39604,39605,39606,39607,39608,39609,39610,39611,39612,39613,39614,39615,39616,39617,39618,39619,39620,39621,39622,39623,39624,39625,39626,39627,39628,39629,39630,39631,39632,39633,39634,39635,39636,39637,39638,39639,39640,39641,39642,39643,39644,39645,39646,39647,39648,39649,39650,39651,39652,39653,39654,39655,39656,39657,39658,39659,39660,39661,39662,39663,39664,39665,39666,39667,39668,39669,39670,39671,39672,39673,39674,39675,39676,39677,39678,39679,39680,39681,39682,39683,39684,39685,39686,39687,39688,39689,39690,39691,39692,39693,39694,39695,39696,39697,39698,39699,39700,39701,39702,39703,39704,39705,39706,39707,39708,39709,39710,39711,39712,39713,39714,39715,39716,39717,39718,39719,39720,39721,39722,39723,39724,39725,39726,39727,39728,39729,39730,39731,39732,39733,39734,39735,39736,39737,39738,39739,39740,39741,39742,39743,39744,39745,39746,39747,39748,39749,39750,39751,39752,39753,39754,39755,39756,39757,39758,39759,39760,39761,39762,39763,39764,39765,39766,39767,39768,39769,39770,39771,39772,39773,39774,39775,39776,39777,39778,39779,39780,39781,39782,39783,39784,39785,39786,39787,39788,39789,39790,39791,39792,39793,39794,39795,39796,39797,39798,39799,39800,39801,39802,39803,39804,39805,39806,39807,39808,39809,39810,39811,39812,39813,39814,39815,39816,39817,39818,39819,39820,39821,39822,39823,39824,39825,39826,39827,39828,39829,39830,39831,39832,39833,39834,39835,39836,39837,39838,39839,39840,39841,39842,39843,39844,39845,39846,39847,39848,39849,39850,39851,39852,39853,39854,39855,39856,39857,39858,39859,39860,39861,39862,39863,39864,39865,39866,39867,39868,39869,39870,39871,39872,39873,39874,39875,39876,39877,39878,39879,39880,39881,39882,39883,39884,39885,39886,39887,39888,39889,39890,39891,39892,39893,39894,39895,39896,39897,39898,39899,39900,39901,39902,39903,39904,39905,39906,39907,39908,39909,39910,39911,39912,39913,39914,39915,39916,39917,39918,39919,39920,39921,39922,39923,39924,39925,39926,39927,39928,39929,39930,39931,39932,39933,39934,39935,39936,39937,39938,39939,39940,39941,39942,39943,39944,39945,39946,39947,39948,39949,39950,39951,39952,39953,39954,39955,39956,39957,39958,39959,39960,39961,39962,39963,39964,39965,39966,39967,39968,39969,39970,39971,39972,39973,39974,39975,39976,39977,39978,39979,39980,39981,39982,39983,39984,39985,39986,39987,39988,39989,39990,39991,39992,39993,39994,39995,39996,39997,39998,39999,40000,40001,40002,40003,40004,40005,40006,40007,40008,40009,40010,40011,40012,40013,40014,40015,40016,40017,40018,40019,40020,40021,40022,40023,40024,40025,40026,40027,40028,40029,40030,40031,40032,40033,40034,40035,40036,40037,40038,40039,40040,40041,40042,40043,40044,40045,40046,40047,40048,40049,40050,40051,40052,40053,40054,40055,40056,40057,40058,40059,40060,40061,40062,40063,40064,40065,40066,40067,40068,40069,40070,40071,40072,40073,40074,40075,40076,40077,40078,40079,40080,40081,40082,40083,40084,40085,40086,40087,40088,40089,40090,40091,40092,40093,40094,40095,40096,40097,40098,40099,40100,40101,40102,40103,40104,40105,40106,40107,40108,40109,40110,40111,40112,40113,40114,40115,40116,40117,40118,40119,40120,40121,40122,40123,40124,40125,40126,40127,40128,40129,40130,40131,40132,40133,40134,40135,40136,40137,40138,40139,40140,40141,40142,40143,40144,40145,40146,40147,40148,40149,40150,40151,40152,40153,40154,40155,40156,40157,40158,40159,40160,40161,40162,40163,40164,40165,40166,40167,40168,40169,40170,40171,40172,40173,40174,40175,40176,40177,40178,40179,40180,40181,40182,40183,40184,40185,40186,40187,40188,40189,40190,40191,40192,40193,40194,40195,40196,40197,40198,40199,40200,40201,40202,40203,40204,40205,40206,40207,40208,40209,40210,40211,40212,40213,40214,40215,40216,40217,40218,40219,40220,40221,40222,40223,40224,40225,40226,40227,40228,40229,40230,40231,40232,40233,40234,40235,40236,40237,40238,40239,40240,40241,40242,40243,40244,40245,40246,40247,40248,40249,40250,40251,40252,40253,40254,40255,40256,40257,40258,40259,40260,40261,40262,40263,40264,40265,40266,40267,40268,40269,40270,40271,40272,40273,40274,40275,40276,40277,40278,40279,40280,40281,40282,40283,40284,40285,40286,40287,40288,40289,40290,40291,40292,40293,40294,40295,40296,40297,40298,40299,40300,40301,40302,40303,40304,40305,40306,40307,40308,40309,40310,40311,40312,40313,40314,40315,40316,40317,40318,40319,40320,40321,40322,40323,40324,40325,40326,40327,40328,40329,40330,40331,40332,40333,40334,40335,40336,40337,40338,40339,40340,40341,40342,40343,40344,40345,40346,40347,40348,40349,40350,40351,40352,40353,40354,40355,40356,40357,40358,40359,40360,40361,40362,40363,40364,40365,40366,40367,40368,40369,40370,40371,40372,40373,40374,40375,40376,40377,40378,40379,40380,40381,40382,40383,40384,40385,40386,40387,40388,40389,40390,40391,40392,40393,40394,40395,40396,40397,40398,40399,40400,40401,40402,40403,40404,40405,40406,40407,40408,40409,40410,40411,40412,40413,40414,40415,40416,40417,40418,40419,40420,40421,40422,40423,40424,40425,40426,40427,40428,40429,40430,40431,40432,40433,40434,40435,40436,40437,40438,40439,40440,40441,40442,40443,40444,40445,40446,40447,40448,40449,40450,40451,40452,40453,40454,40455,40456,40457,40458,40459,40460,40461,40462,40463,40464,40465,40466,40467,40468,40469,40470,40471,40472,40473,40474,40475,40476,40477,40478,40479,40480,40481,40482,40483,40484,40485,40486,40487,40488,40489,40490,40491,40492,40493,40494,40495,40496,40497,40498,40499,40500,40501,40502,40503,40504,40505,40506,40507,40508,40509,40510,40511,40512,40513,40514,40515,40516,40517,40518,40519,40520,40521,40522,40523,40524,40525,40526,40527,40528,40529,40530,40531,40532,40533,40534,40535,40536,40537,40538,40539,40540,40541,40542,40543,40544,40545,40546,40547,40548,40549,40550,40551,40552,40553,40554,40555,40556,40557,40558,40559,40560,40561,40562,40563,40564,40565,40566,40567,40568,40569,40570,40571,40572,40573,40574,40575,40576,40577,40578,40579,40580,40581,40582,40583,40584,40585,40586,40587,40588,40589,40590,40591,40592,40593,40594,40595,40596,40597,40598,40599,40600,40601,40602,40603,40604,40605,40606,40607,40608,40609,40610,40611,40612,40613,40614,40615,40616,40617,40618,40619,40620,40621,40622,40623,40624,40625,40626,40627,40628,40629,40630,40631,40632,40633,40634,40635,40636,40637,40638,40639,40640,40641,40642,40643,40644,40645,40646,40647,40648,40649,40650,40651,40652,40653,40654,40655,40656,40657,40658,40659,40660,40661,40662,40663,40664,40665,40666,40667,40668,40669,40670,40671,40672,40673,40674,40675,40676,40677,40678,40679,40680,40681,40682,40683,40684,40685,40686,40687,40688,40689,40690,40691,40692,40693,40694,40695,40696,40697,40698,40699,40700,40701,40702,40703,40704,40705,40706,40707,40708,40709,40710,40711,40712,40713,40714,40715,40716,40717,40718,40719,40720,40721,40722,40723,40724,40725,40726,40727,40728,40729,40730,40731,40732,40733,40734,40735,40736,40737,40738,40739,40740,40741,40742,40743,40744,40745,40746,40747,40748,40749,40750,40751,40752,40753,40754,40755,40756,40757,40758,40759,40760,40761,40762,40763,40764,40765,40766,40767,40768,40769,40770,40771,40772,40773,40774,40775,40776,40777,40778,40779,40780,40781,40782,40783,40784,40785,40786,40787,40788,40789,40790,40791,40792,40793,40794,40795,40796,40797,40798,40799,40800,40801,40802,40803,40804,40805,40806,40807,40808,40809,40810,40811,40812,40813,40814,40815,40816,40817,40818,40819,40820,40821,40822,40823,40824,40825,40826,40827,40828,40829,40830,40831,40832,40833,40834,40835,40836,40837,40838,40839,40840,40841,40842,40843,40844,40845,40846,40847,40848,40849,40850,40851,40852,40853,40854,40855,40856,40857,40858,40859,40860,40861,40862,40863,40864,40865,40866,40867,40868,40869,40870,40871,40872,40873,40874,40875,40876,40877,40878,40879,40880,40881,40882,40883,40884,40885,40886,40887,40888,40889,40890,40891,40892,40893,40894,40895,40896,40897,40898,40899,40900,40901,40902,40903,40904,40905,40906,40907,40908,40909,40910,40911,40912,40913,40914,40915,40916,40917,40918,40919,40920,40921,40922,40923,40924,40925,40926,40927,40928,40929,40930,40931,40932,40933,40934,40935,40936,40937,40938,40939,40940,40941,40942,40943,40960,40961,40962,40963,40964,40965,40966,40967,40968,40969,40970,40971,40972,40973,40974,40975,40976,40977,40978,40979,40980,40981,40982,40983,40984,40985,40986,40987,40988,40989,40990,40991,40992,40993,40994,40995,40996,40997,40998,40999,41000,41001,41002,41003,41004,41005,41006,41007,41008,41009,41010,41011,41012,41013,41014,41015,41016,41017,41018,41019,41020,41021,41022,41023,41024,41025,41026,41027,41028,41029,41030,41031,41032,41033,41034,41035,41036,41037,41038,41039,41040,41041,41042,41043,41044,41045,41046,41047,41048,41049,41050,41051,41052,41053,41054,41055,41056,41057,41058,41059,41060,41061,41062,41063,41064,41065,41066,41067,41068,41069,41070,41071,41072,41073,41074,41075,41076,41077,41078,41079,41080,41081,41082,41083,41084,41085,41086,41087,41088,41089,41090,41091,41092,41093,41094,41095,41096,41097,41098,41099,41100,41101,41102,41103,41104,41105,41106,41107,41108,41109,41110,41111,41112,41113,41114,41115,41116,41117,41118,41119,41120,41121,41122,41123,41124,41125,41126,41127,41128,41129,41130,41131,41132,41133,41134,41135,41136,41137,41138,41139,41140,41141,41142,41143,41144,41145,41146,41147,41148,41149,41150,41151,41152,41153,41154,41155,41156,41157,41158,41159,41160,41161,41162,41163,41164,41165,41166,41167,41168,41169,41170,41171,41172,41173,41174,41175,41176,41177,41178,41179,41180,41181,41182,41183,41184,41185,41186,41187,41188,41189,41190,41191,41192,41193,41194,41195,41196,41197,41198,41199,41200,41201,41202,41203,41204,41205,41206,41207,41208,41209,41210,41211,41212,41213,41214,41215,41216,41217,41218,41219,41220,41221,41222,41223,41224,41225,41226,41227,41228,41229,41230,41231,41232,41233,41234,41235,41236,41237,41238,41239,41240,41241,41242,41243,41244,41245,41246,41247,41248,41249,41250,41251,41252,41253,41254,41255,41256,41257,41258,41259,41260,41261,41262,41263,41264,41265,41266,41267,41268,41269,41270,41271,41272,41273,41274,41275,41276,41277,41278,41279,41280,41281,41282,41283,41284,41285,41286,41287,41288,41289,41290,41291,41292,41293,41294,41295,41296,41297,41298,41299,41300,41301,41302,41303,41304,41305,41306,41307,41308,41309,41310,41311,41312,41313,41314,41315,41316,41317,41318,41319,41320,41321,41322,41323,41324,41325,41326,41327,41328,41329,41330,41331,41332,41333,41334,41335,41336,41337,41338,41339,41340,41341,41342,41343,41344,41345,41346,41347,41348,41349,41350,41351,41352,41353,41354,41355,41356,41357,41358,41359,41360,41361,41362,41363,41364,41365,41366,41367,41368,41369,41370,41371,41372,41373,41374,41375,41376,41377,41378,41379,41380,41381,41382,41383,41384,41385,41386,41387,41388,41389,41390,41391,41392,41393,41394,41395,41396,41397,41398,41399,41400,41401,41402,41403,41404,41405,41406,41407,41408,41409,41410,41411,41412,41413,41414,41415,41416,41417,41418,41419,41420,41421,41422,41423,41424,41425,41426,41427,41428,41429,41430,41431,41432,41433,41434,41435,41436,41437,41438,41439,41440,41441,41442,41443,41444,41445,41446,41447,41448,41449,41450,41451,41452,41453,41454,41455,41456,41457,41458,41459,41460,41461,41462,41463,41464,41465,41466,41467,41468,41469,41470,41471,41472,41473,41474,41475,41476,41477,41478,41479,41480,41481,41482,41483,41484,41485,41486,41487,41488,41489,41490,41491,41492,41493,41494,41495,41496,41497,41498,41499,41500,41501,41502,41503,41504,41505,41506,41507,41508,41509,41510,41511,41512,41513,41514,41515,41516,41517,41518,41519,41520,41521,41522,41523,41524,41525,41526,41527,41528,41529,41530,41531,41532,41533,41534,41535,41536,41537,41538,41539,41540,41541,41542,41543,41544,41545,41546,41547,41548,41549,41550,41551,41552,41553,41554,41555,41556,41557,41558,41559,41560,41561,41562,41563,41564,41565,41566,41567,41568,41569,41570,41571,41572,41573,41574,41575,41576,41577,41578,41579,41580,41581,41582,41583,41584,41585,41586,41587,41588,41589,41590,41591,41592,41593,41594,41595,41596,41597,41598,41599,41600,41601,41602,41603,41604,41605,41606,41607,41608,41609,41610,41611,41612,41613,41614,41615,41616,41617,41618,41619,41620,41621,41622,41623,41624,41625,41626,41627,41628,41629,41630,41631,41632,41633,41634,41635,41636,41637,41638,41639,41640,41641,41642,41643,41644,41645,41646,41647,41648,41649,41650,41651,41652,41653,41654,41655,41656,41657,41658,41659,41660,41661,41662,41663,41664,41665,41666,41667,41668,41669,41670,41671,41672,41673,41674,41675,41676,41677,41678,41679,41680,41681,41682,41683,41684,41685,41686,41687,41688,41689,41690,41691,41692,41693,41694,41695,41696,41697,41698,41699,41700,41701,41702,41703,41704,41705,41706,41707,41708,41709,41710,41711,41712,41713,41714,41715,41716,41717,41718,41719,41720,41721,41722,41723,41724,41725,41726,41727,41728,41729,41730,41731,41732,41733,41734,41735,41736,41737,41738,41739,41740,41741,41742,41743,41744,41745,41746,41747,41748,41749,41750,41751,41752,41753,41754,41755,41756,41757,41758,41759,41760,41761,41762,41763,41764,41765,41766,41767,41768,41769,41770,41771,41772,41773,41774,41775,41776,41777,41778,41779,41780,41781,41782,41783,41784,41785,41786,41787,41788,41789,41790,41791,41792,41793,41794,41795,41796,41797,41798,41799,41800,41801,41802,41803,41804,41805,41806,41807,41808,41809,41810,41811,41812,41813,41814,41815,41816,41817,41818,41819,41820,41821,41822,41823,41824,41825,41826,41827,41828,41829,41830,41831,41832,41833,41834,41835,41836,41837,41838,41839,41840,41841,41842,41843,41844,41845,41846,41847,41848,41849,41850,41851,41852,41853,41854,41855,41856,41857,41858,41859,41860,41861,41862,41863,41864,41865,41866,41867,41868,41869,41870,41871,41872,41873,41874,41875,41876,41877,41878,41879,41880,41881,41882,41883,41884,41885,41886,41887,41888,41889,41890,41891,41892,41893,41894,41895,41896,41897,41898,41899,41900,41901,41902,41903,41904,41905,41906,41907,41908,41909,41910,41911,41912,41913,41914,41915,41916,41917,41918,41919,41920,41921,41922,41923,41924,41925,41926,41927,41928,41929,41930,41931,41932,41933,41934,41935,41936,41937,41938,41939,41940,41941,41942,41943,41944,41945,41946,41947,41948,41949,41950,41951,41952,41953,41954,41955,41956,41957,41958,41959,41960,41961,41962,41963,41964,41965,41966,41967,41968,41969,41970,41971,41972,41973,41974,41975,41976,41977,41978,41979,41980,41981,41982,41983,41984,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,41997,41998,41999,42000,42001,42002,42003,42004,42005,42006,42007,42008,42009,42010,42011,42012,42013,42014,42015,42016,42017,42018,42019,42020,42021,42022,42023,42024,42025,42026,42027,42028,42029,42030,42031,42032,42033,42034,42035,42036,42037,42038,42039,42040,42041,42042,42043,42044,42045,42046,42047,42048,42049,42050,42051,42052,42053,42054,42055,42056,42057,42058,42059,42060,42061,42062,42063,42064,42065,42066,42067,42068,42069,42070,42071,42072,42073,42074,42075,42076,42077,42078,42079,42080,42081,42082,42083,42084,42085,42086,42087,42088,42089,42090,42091,42092,42093,42094,42095,42096,42097,42098,42099,42100,42101,42102,42103,42104,42105,42106,42107,42108,42109,42110,42111,42112,42113,42114,42115,42116,42117,42118,42119,42120,42121,42122,42123,42124,42192,42193,42194,42195,42196,42197,42198,42199,42200,42201,42202,42203,42204,42205,42206,42207,42208,42209,42210,42211,42212,42213,42214,42215,42216,42217,42218,42219,42220,42221,42222,42223,42224,42225,42226,42227,42228,42229,42230,42231,42232,42233,42234,42235,42236,42237,42240,42241,42242,42243,42244,42245,42246,42247,42248,42249,42250,42251,42252,42253,42254,42255,42256,42257,42258,42259,42260,42261,42262,42263,42264,42265,42266,42267,42268,42269,42270,42271,42272,42273,42274,42275,42276,42277,42278,42279,42280,42281,42282,42283,42284,42285,42286,42287,42288,42289,42290,42291,42292,42293,42294,42295,42296,42297,42298,42299,42300,42301,42302,42303,42304,42305,42306,42307,42308,42309,42310,42311,42312,42313,42314,42315,42316,42317,42318,42319,42320,42321,42322,42323,42324,42325,42326,42327,42328,42329,42330,42331,42332,42333,42334,42335,42336,42337,42338,42339,42340,42341,42342,42343,42344,42345,42346,42347,42348,42349,42350,42351,42352,42353,42354,42355,42356,42357,42358,42359,42360,42361,42362,42363,42364,42365,42366,42367,42368,42369,42370,42371,42372,42373,42374,42375,42376,42377,42378,42379,42380,42381,42382,42383,42384,42385,42386,42387,42388,42389,42390,42391,42392,42393,42394,42395,42396,42397,42398,42399,42400,42401,42402,42403,42404,42405,42406,42407,42408,42409,42410,42411,42412,42413,42414,42415,42416,42417,42418,42419,42420,42421,42422,42423,42424,42425,42426,42427,42428,42429,42430,42431,42432,42433,42434,42435,42436,42437,42438,42439,42440,42441,42442,42443,42444,42445,42446,42447,42448,42449,42450,42451,42452,42453,42454,42455,42456,42457,42458,42459,42460,42461,42462,42463,42464,42465,42466,42467,42468,42469,42470,42471,42472,42473,42474,42475,42476,42477,42478,42479,42480,42481,42482,42483,42484,42485,42486,42487,42488,42489,42490,42491,42492,42493,42494,42495,42496,42497,42498,42499,42500,42501,42502,42503,42504,42505,42506,42507,42508,42512,42513,42514,42515,42516,42517,42518,42519,42520,42521,42522,42523,42524,42525,42526,42527,42538,42539,42560,42561,42562,42563,42564,42565,42566,42567,42568,42569,42570,42571,42572,42573,42574,42575,42576,42577,42578,42579,42580,42581,42582,42583,42584,42585,42586,42587,42588,42589,42590,42591,42592,42593,42594,42595,42596,42597,42598,42599,42600,42601,42602,42603,42604,42605,42606,42623,42624,42625,42626,42627,42628,42629,42630,42631,42632,42633,42634,42635,42636,42637,42638,42639,42640,42641,42642,42643,42644,42645,42646,42647,42648,42649,42650,42651,42652,42653,42656,42657,42658,42659,42660,42661,42662,42663,42664,42665,42666,42667,42668,42669,42670,42671,42672,42673,42674,42675,42676,42677,42678,42679,42680,42681,42682,42683,42684,42685,42686,42687,42688,42689,42690,42691,42692,42693,42694,42695,42696,42697,42698,42699,42700,42701,42702,42703,42704,42705,42706,42707,42708,42709,42710,42711,42712,42713,42714,42715,42716,42717,42718,42719,42720,42721,42722,42723,42724,42725,42726,42727,42728,42729,42730,42731,42732,42733,42734,42735,42775,42776,42777,42778,42779,42780,42781,42782,42783,42786,42787,42788,42789,42790,42791,42792,42793,42794,42795,42796,42797,42798,42799,42800,42801,42802,42803,42804,42805,42806,42807,42808,42809,42810,42811,42812,42813,42814,42815,42816,42817,42818,42819,42820,42821,42822,42823,42824,42825,42826,42827,42828,42829,42830,42831,42832,42833,42834,42835,42836,42837,42838,42839,42840,42841,42842,42843,42844,42845,42846,42847,42848,42849,42850,42851,42852,42853,42854,42855,42856,42857,42858,42859,42860,42861,42862,42863,42864,42865,42866,42867,42868,42869,42870,42871,42872,42873,42874,42875,42876,42877,42878,42879,42880,42881,42882,42883,42884,42885,42886,42887,42888,42891,42892,42893,42894,42895,42896,42897,42898,42899,42900,42901,42902,42903,42904,42905,42906,42907,42908,42909,42910,42911,42912,42913,42914,42915,42916,42917,42918,42919,42920,42921,42922,42923,42924,42925,42926,42927,42928,42929,42930,42931,42932,42933,42934,42935,42936,42937,42999,43000,43001,43002,43003,43004,43005,43006,43007,43008,43009,43011,43012,43013,43015,43016,43017,43018,43020,43021,43022,43023,43024,43025,43026,43027,43028,43029,43030,43031,43032,43033,43034,43035,43036,43037,43038,43039,43040,43041,43042,43072,43073,43074,43075,43076,43077,43078,43079,43080,43081,43082,43083,43084,43085,43086,43087,43088,43089,43090,43091,43092,43093,43094,43095,43096,43097,43098,43099,43100,43101,43102,43103,43104,43105,43106,43107,43108,43109,43110,43111,43112,43113,43114,43115,43116,43117,43118,43119,43120,43121,43122,43123,43138,43139,43140,43141,43142,43143,43144,43145,43146,43147,43148,43149,43150,43151,43152,43153,43154,43155,43156,43157,43158,43159,43160,43161,43162,43163,43164,43165,43166,43167,43168,43169,43170,43171,43172,43173,43174,43175,43176,43177,43178,43179,43180,43181,43182,43183,43184,43185,43186,43187,43250,43251,43252,43253,43254,43255,43259,43261,43262,43274,43275,43276,43277,43278,43279,43280,43281,43282,43283,43284,43285,43286,43287,43288,43289,43290,43291,43292,43293,43294,43295,43296,43297,43298,43299,43300,43301,43312,43313,43314,43315,43316,43317,43318,43319,43320,43321,43322,43323,43324,43325,43326,43327,43328,43329,43330,43331,43332,43333,43334,43360,43361,43362,43363,43364,43365,43366,43367,43368,43369,43370,43371,43372,43373,43374,43375,43376,43377,43378,43379,43380,43381,43382,43383,43384,43385,43386,43387,43388,43396,43397,43398,43399,43400,43401,43402,43403,43404,43405,43406,43407,43408,43409,43410,43411,43412,43413,43414,43415,43416,43417,43418,43419,43420,43421,43422,43423,43424,43425,43426,43427,43428,43429,43430,43431,43432,43433,43434,43435,43436,43437,43438,43439,43440,43441,43442,43471,43488,43489,43490,43491,43492,43494,43495,43496,43497,43498,43499,43500,43501,43502,43503,43514,43515,43516,43517,43518,43520,43521,43522,43523,43524,43525,43526,43527,43528,43529,43530,43531,43532,43533,43534,43535,43536,43537,43538,43539,43540,43541,43542,43543,43544,43545,43546,43547,43548,43549,43550,43551,43552,43553,43554,43555,43556,43557,43558,43559,43560,43584,43585,43586,43588,43589,43590,43591,43592,43593,43594,43595,43616,43617,43618,43619,43620,43621,43622,43623,43624,43625,43626,43627,43628,43629,43630,43631,43632,43633,43634,43635,43636,43637,43638,43642,43646,43647,43648,43649,43650,43651,43652,43653,43654,43655,43656,43657,43658,43659,43660,43661,43662,43663,43664,43665,43666,43667,43668,43669,43670,43671,43672,43673,43674,43675,43676,43677,43678,43679,43680,43681,43682,43683,43684,43685,43686,43687,43688,43689,43690,43691,43692,43693,43694,43695,43697,43701,43702,43705,43706,43707,43708,43709,43712,43714,43739,43740,43741,43744,43745,43746,43747,43748,43749,43750,43751,43752,43753,43754,43762,43763,43764,43777,43778,43779,43780,43781,43782,43785,43786,43787,43788,43789,43790,43793,43794,43795,43796,43797,43798,43808,43809,43810,43811,43812,43813,43814,43816,43817,43818,43819,43820,43821,43822,43824,43825,43826,43827,43828,43829,43830,43831,43832,43833,43834,43835,43836,43837,43838,43839,43840,43841,43842,43843,43844,43845,43846,43847,43848,43849,43850,43851,43852,43853,43854,43855,43856,43857,43858,43859,43860,43861,43862,43863,43864,43865,43866,43868,43869,43870,43871,43872,43873,43874,43875,43876,43877,43888,43889,43890,43891,43892,43893,43894,43895,43896,43897,43898,43899,43900,43901,43902,43903,43904,43905,43906,43907,43908,43909,43910,43911,43912,43913,43914,43915,43916,43917,43918,43919,43920,43921,43922,43923,43924,43925,43926,43927,43928,43929,43930,43931,43932,43933,43934,43935,43936,43937,43938,43939,43940,43941,43942,43943,43944,43945,43946,43947,43948,43949,43950,43951,43952,43953,43954,43955,43956,43957,43958,43959,43960,43961,43962,43963,43964,43965,43966,43967,43968,43969,43970,43971,43972,43973,43974,43975,43976,43977,43978,43979,43980,43981,43982,43983,43984,43985,43986,43987,43988,43989,43990,43991,43992,43993,43994,43995,43996,43997,43998,43999,44000,44001,44002,44032,44033,44034,44035,44036,44037,44038,44039,44040,44041,44042,44043,44044,44045,44046,44047,44048,44049,44050,44051,44052,44053,44054,44055,44056,44057,44058,44059,44060,44061,44062,44063,44064,44065,44066,44067,44068,44069,44070,44071,44072,44073,44074,44075,44076,44077,44078,44079,44080,44081,44082,44083,44084,44085,44086,44087,44088,44089,44090,44091,44092,44093,44094,44095,44096,44097,44098,44099,44100,44101,44102,44103,44104,44105,44106,44107,44108,44109,44110,44111,44112,44113,44114,44115,44116,44117,44118,44119,44120,44121,44122,44123,44124,44125,44126,44127,44128,44129,44130,44131,44132,44133,44134,44135,44136,44137,44138,44139,44140,44141,44142,44143,44144,44145,44146,44147,44148,44149,44150,44151,44152,44153,44154,44155,44156,44157,44158,44159,44160,44161,44162,44163,44164,44165,44166,44167,44168,44169,44170,44171,44172,44173,44174,44175,44176,44177,44178,44179,44180,44181,44182,44183,44184,44185,44186,44187,44188,44189,44190,44191,44192,44193,44194,44195,44196,44197,44198,44199,44200,44201,44202,44203,44204,44205,44206,44207,44208,44209,44210,44211,44212,44213,44214,44215,44216,44217,44218,44219,44220,44221,44222,44223,44224,44225,44226,44227,44228,44229,44230,44231,44232,44233,44234,44235,44236,44237,44238,44239,44240,44241,44242,44243,44244,44245,44246,44247,44248,44249,44250,44251,44252,44253,44254,44255,44256,44257,44258,44259,44260,44261,44262,44263,44264,44265,44266,44267,44268,44269,44270,44271,44272,44273,44274,44275,44276,44277,44278,44279,44280,44281,44282,44283,44284,44285,44286,44287,44288,44289,44290,44291,44292,44293,44294,44295,44296,44297,44298,44299,44300,44301,44302,44303,44304,44305,44306,44307,44308,44309,44310,44311,44312,44313,44314,44315,44316,44317,44318,44319,44320,44321,44322,44323,44324,44325,44326,44327,44328,44329,44330,44331,44332,44333,44334,44335,44336,44337,44338,44339,44340,44341,44342,44343,44344,44345,44346,44347,44348,44349,44350,44351,44352,44353,44354,44355,44356,44357,44358,44359,44360,44361,44362,44363,44364,44365,44366,44367,44368,44369,44370,44371,44372,44373,44374,44375,44376,44377,44378,44379,44380,44381,44382,44383,44384,44385,44386,44387,44388,44389,44390,44391,44392,44393,44394,44395,44396,44397,44398,44399,44400,44401,44402,44403,44404,44405,44406,44407,44408,44409,44410,44411,44412,44413,44414,44415,44416,44417,44418,44419,44420,44421,44422,44423,44424,44425,44426,44427,44428,44429,44430,44431,44432,44433,44434,44435,44436,44437,44438,44439,44440,44441,44442,44443,44444,44445,44446,44447,44448,44449,44450,44451,44452,44453,44454,44455,44456,44457,44458,44459,44460,44461,44462,44463,44464,44465,44466,44467,44468,44469,44470,44471,44472,44473,44474,44475,44476,44477,44478,44479,44480,44481,44482,44483,44484,44485,44486,44487,44488,44489,44490,44491,44492,44493,44494,44495,44496,44497,44498,44499,44500,44501,44502,44503,44504,44505,44506,44507,44508,44509,44510,44511,44512,44513,44514,44515,44516,44517,44518,44519,44520,44521,44522,44523,44524,44525,44526,44527,44528,44529,44530,44531,44532,44533,44534,44535,44536,44537,44538,44539,44540,44541,44542,44543,44544,44545,44546,44547,44548,44549,44550,44551,44552,44553,44554,44555,44556,44557,44558,44559,44560,44561,44562,44563,44564,44565,44566,44567,44568,44569,44570,44571,44572,44573,44574,44575,44576,44577,44578,44579,44580,44581,44582,44583,44584,44585,44586,44587,44588,44589,44590,44591,44592,44593,44594,44595,44596,44597,44598,44599,44600,44601,44602,44603,44604,44605,44606,44607,44608,44609,44610,44611,44612,44613,44614,44615,44616,44617,44618,44619,44620,44621,44622,44623,44624,44625,44626,44627,44628,44629,44630,44631,44632,44633,44634,44635,44636,44637,44638,44639,44640,44641,44642,44643,44644,44645,44646,44647,44648,44649,44650,44651,44652,44653,44654,44655,44656,44657,44658,44659,44660,44661,44662,44663,44664,44665,44666,44667,44668,44669,44670,44671,44672,44673,44674,44675,44676,44677,44678,44679,44680,44681,44682,44683,44684,44685,44686,44687,44688,44689,44690,44691,44692,44693,44694,44695,44696,44697,44698,44699,44700,44701,44702,44703,44704,44705,44706,44707,44708,44709,44710,44711,44712,44713,44714,44715,44716,44717,44718,44719,44720,44721,44722,44723,44724,44725,44726,44727,44728,44729,44730,44731,44732,44733,44734,44735,44736,44737,44738,44739,44740,44741,44742,44743,44744,44745,44746,44747,44748,44749,44750,44751,44752,44753,44754,44755,44756,44757,44758,44759,44760,44761,44762,44763,44764,44765,44766,44767,44768,44769,44770,44771,44772,44773,44774,44775,44776,44777,44778,44779,44780,44781,44782,44783,44784,44785,44786,44787,44788,44789,44790,44791,44792,44793,44794,44795,44796,44797,44798,44799,44800,44801,44802,44803,44804,44805,44806,44807,44808,44809,44810,44811,44812,44813,44814,44815,44816,44817,44818,44819,44820,44821,44822,44823,44824,44825,44826,44827,44828,44829,44830,44831,44832,44833,44834,44835,44836,44837,44838,44839,44840,44841,44842,44843,44844,44845,44846,44847,44848,44849,44850,44851,44852,44853,44854,44855,44856,44857,44858,44859,44860,44861,44862,44863,44864,44865,44866,44867,44868,44869,44870,44871,44872,44873,44874,44875,44876,44877,44878,44879,44880,44881,44882,44883,44884,44885,44886,44887,44888,44889,44890,44891,44892,44893,44894,44895,44896,44897,44898,44899,44900,44901,44902,44903,44904,44905,44906,44907,44908,44909,44910,44911,44912,44913,44914,44915,44916,44917,44918,44919,44920,44921,44922,44923,44924,44925,44926,44927,44928,44929,44930,44931,44932,44933,44934,44935,44936,44937,44938,44939,44940,44941,44942,44943,44944,44945,44946,44947,44948,44949,44950,44951,44952,44953,44954,44955,44956,44957,44958,44959,44960,44961,44962,44963,44964,44965,44966,44967,44968,44969,44970,44971,44972,44973,44974,44975,44976,44977,44978,44979,44980,44981,44982,44983,44984,44985,44986,44987,44988,44989,44990,44991,44992,44993,44994,44995,44996,44997,44998,44999,45000,45001,45002,45003,45004,45005,45006,45007,45008,45009,45010,45011,45012,45013,45014,45015,45016,45017,45018,45019,45020,45021,45022,45023,45024,45025,45026,45027,45028,45029,45030,45031,45032,45033,45034,45035,45036,45037,45038,45039,45040,45041,45042,45043,45044,45045,45046,45047,45048,45049,45050,45051,45052,45053,45054,45055,45056,45057,45058,45059,45060,45061,45062,45063,45064,45065,45066,45067,45068,45069,45070,45071,45072,45073,45074,45075,45076,45077,45078,45079,45080,45081,45082,45083,45084,45085,45086,45087,45088,45089,45090,45091,45092,45093,45094,45095,45096,45097,45098,45099,45100,45101,45102,45103,45104,45105,45106,45107,45108,45109,45110,45111,45112,45113,45114,45115,45116,45117,45118,45119,45120,45121,45122,45123,45124,45125,45126,45127,45128,45129,45130,45131,45132,45133,45134,45135,45136,45137,45138,45139,45140,45141,45142,45143,45144,45145,45146,45147,45148,45149,45150,45151,45152,45153,45154,45155,45156,45157,45158,45159,45160,45161,45162,45163,45164,45165,45166,45167,45168,45169,45170,45171,45172,45173,45174,45175,45176,45177,45178,45179,45180,45181,45182,45183,45184,45185,45186,45187,45188,45189,45190,45191,45192,45193,45194,45195,45196,45197,45198,45199,45200,45201,45202,45203,45204,45205,45206,45207,45208,45209,45210,45211,45212,45213,45214,45215,45216,45217,45218,45219,45220,45221,45222,45223,45224,45225,45226,45227,45228,45229,45230,45231,45232,45233,45234,45235,45236,45237,45238,45239,45240,45241,45242,45243,45244,45245,45246,45247,45248,45249,45250,45251,45252,45253,45254,45255,45256,45257,45258,45259,45260,45261,45262,45263,45264,45265,45266,45267,45268,45269,45270,45271,45272,45273,45274,45275,45276,45277,45278,45279,45280,45281,45282,45283,45284,45285,45286,45287,45288,45289,45290,45291,45292,45293,45294,45295,45296,45297,45298,45299,45300,45301,45302,45303,45304,45305,45306,45307,45308,45309,45310,45311,45312,45313,45314,45315,45316,45317,45318,45319,45320,45321,45322,45323,45324,45325,45326,45327,45328,45329,45330,45331,45332,45333,45334,45335,45336,45337,45338,45339,45340,45341,45342,45343,45344,45345,45346,45347,45348,45349,45350,45351,45352,45353,45354,45355,45356,45357,45358,45359,45360,45361,45362,45363,45364,45365,45366,45367,45368,45369,45370,45371,45372,45373,45374,45375,45376,45377,45378,45379,45380,45381,45382,45383,45384,45385,45386,45387,45388,45389,45390,45391,45392,45393,45394,45395,45396,45397,45398,45399,45400,45401,45402,45403,45404,45405,45406,45407,45408,45409,45410,45411,45412,45413,45414,45415,45416,45417,45418,45419,45420,45421,45422,45423,45424,45425,45426,45427,45428,45429,45430,45431,45432,45433,45434,45435,45436,45437,45438,45439,45440,45441,45442,45443,45444,45445,45446,45447,45448,45449,45450,45451,45452,45453,45454,45455,45456,45457,45458,45459,45460,45461,45462,45463,45464,45465,45466,45467,45468,45469,45470,45471,45472,45473,45474,45475,45476,45477,45478,45479,45480,45481,45482,45483,45484,45485,45486,45487,45488,45489,45490,45491,45492,45493,45494,45495,45496,45497,45498,45499,45500,45501,45502,45503,45504,45505,45506,45507,45508,45509,45510,45511,45512,45513,45514,45515,45516,45517,45518,45519,45520,45521,45522,45523,45524,45525,45526,45527,45528,45529,45530,45531,45532,45533,45534,45535,45536,45537,45538,45539,45540,45541,45542,45543,45544,45545,45546,45547,45548,45549,45550,45551,45552,45553,45554,45555,45556,45557,45558,45559,45560,45561,45562,45563,45564,45565,45566,45567,45568,45569,45570,45571,45572,45573,45574,45575,45576,45577,45578,45579,45580,45581,45582,45583,45584,45585,45586,45587,45588,45589,45590,45591,45592,45593,45594,45595,45596,45597,45598,45599,45600,45601,45602,45603,45604,45605,45606,45607,45608,45609,45610,45611,45612,45613,45614,45615,45616,45617,45618,45619,45620,45621,45622,45623,45624,45625,45626,45627,45628,45629,45630,45631,45632,45633,45634,45635,45636,45637,45638,45639,45640,45641,45642,45643,45644,45645,45646,45647,45648,45649,45650,45651,45652,45653,45654,45655,45656,45657,45658,45659,45660,45661,45662,45663,45664,45665,45666,45667,45668,45669,45670,45671,45672,45673,45674,45675,45676,45677,45678,45679,45680,45681,45682,45683,45684,45685,45686,45687,45688,45689,45690,45691,45692,45693,45694,45695,45696,45697,45698,45699,45700,45701,45702,45703,45704,45705,45706,45707,45708,45709,45710,45711,45712,45713,45714,45715,45716,45717,45718,45719,45720,45721,45722,45723,45724,45725,45726,45727,45728,45729,45730,45731,45732,45733,45734,45735,45736,45737,45738,45739,45740,45741,45742,45743,45744,45745,45746,45747,45748,45749,45750,45751,45752,45753,45754,45755,45756,45757,45758,45759,45760,45761,45762,45763,45764,45765,45766,45767,45768,45769,45770,45771,45772,45773,45774,45775,45776,45777,45778,45779,45780,45781,45782,45783,45784,45785,45786,45787,45788,45789,45790,45791,45792,45793,45794,45795,45796,45797,45798,45799,45800,45801,45802,45803,45804,45805,45806,45807,45808,45809,45810,45811,45812,45813,45814,45815,45816,45817,45818,45819,45820,45821,45822,45823,45824,45825,45826,45827,45828,45829,45830,45831,45832,45833,45834,45835,45836,45837,45838,45839,45840,45841,45842,45843,45844,45845,45846,45847,45848,45849,45850,45851,45852,45853,45854,45855,45856,45857,45858,45859,45860,45861,45862,45863,45864,45865,45866,45867,45868,45869,45870,45871,45872,45873,45874,45875,45876,45877,45878,45879,45880,45881,45882,45883,45884,45885,45886,45887,45888,45889,45890,45891,45892,45893,45894,45895,45896,45897,45898,45899,45900,45901,45902,45903,45904,45905,45906,45907,45908,45909,45910,45911,45912,45913,45914,45915,45916,45917,45918,45919,45920,45921,45922,45923,45924,45925,45926,45927,45928,45929,45930,45931,45932,45933,45934,45935,45936,45937,45938,45939,45940,45941,45942,45943,45944,45945,45946,45947,45948,45949,45950,45951,45952,45953,45954,45955,45956,45957,45958,45959,45960,45961,45962,45963,45964,45965,45966,45967,45968,45969,45970,45971,45972,45973,45974,45975,45976,45977,45978,45979,45980,45981,45982,45983,45984,45985,45986,45987,45988,45989,45990,45991,45992,45993,45994,45995,45996,45997,45998,45999,46000,46001,46002,46003,46004,46005,46006,46007,46008,46009,46010,46011,46012,46013,46014,46015,46016,46017,46018,46019,46020,46021,46022,46023,46024,46025,46026,46027,46028,46029,46030,46031,46032,46033,46034,46035,46036,46037,46038,46039,46040,46041,46042,46043,46044,46045,46046,46047,46048,46049,46050,46051,46052,46053,46054,46055,46056,46057,46058,46059,46060,46061,46062,46063,46064,46065,46066,46067,46068,46069,46070,46071,46072,46073,46074,46075,46076,46077,46078,46079,46080,46081,46082,46083,46084,46085,46086,46087,46088,46089,46090,46091,46092,46093,46094,46095,46096,46097,46098,46099,46100,46101,46102,46103,46104,46105,46106,46107,46108,46109,46110,46111,46112,46113,46114,46115,46116,46117,46118,46119,46120,46121,46122,46123,46124,46125,46126,46127,46128,46129,46130,46131,46132,46133,46134,46135,46136,46137,46138,46139,46140,46141,46142,46143,46144,46145,46146,46147,46148,46149,46150,46151,46152,46153,46154,46155,46156,46157,46158,46159,46160,46161,46162,46163,46164,46165,46166,46167,46168,46169,46170,46171,46172,46173,46174,46175,46176,46177,46178,46179,46180,46181,46182,46183,46184,46185,46186,46187,46188,46189,46190,46191,46192,46193,46194,46195,46196,46197,46198,46199,46200,46201,46202,46203,46204,46205,46206,46207,46208,46209,46210,46211,46212,46213,46214,46215,46216,46217,46218,46219,46220,46221,46222,46223,46224,46225,46226,46227,46228,46229,46230,46231,46232,46233,46234,46235,46236,46237,46238,46239,46240,46241,46242,46243,46244,46245,46246,46247,46248,46249,46250,46251,46252,46253,46254,46255,46256,46257,46258,46259,46260,46261,46262,46263,46264,46265,46266,46267,46268,46269,46270,46271,46272,46273,46274,46275,46276,46277,46278,46279,46280,46281,46282,46283,46284,46285,46286,46287,46288,46289,46290,46291,46292,46293,46294,46295,46296,46297,46298,46299,46300,46301,46302,46303,46304,46305,46306,46307,46308,46309,46310,46311,46312,46313,46314,46315,46316,46317,46318,46319,46320,46321,46322,46323,46324,46325,46326,46327,46328,46329,46330,46331,46332,46333,46334,46335,46336,46337,46338,46339,46340,46341,46342,46343,46344,46345,46346,46347,46348,46349,46350,46351,46352,46353,46354,46355,46356,46357,46358,46359,46360,46361,46362,46363,46364,46365,46366,46367,46368,46369,46370,46371,46372,46373,46374,46375,46376,46377,46378,46379,46380,46381,46382,46383,46384,46385,46386,46387,46388,46389,46390,46391,46392,46393,46394,46395,46396,46397,46398,46399,46400,46401,46402,46403,46404,46405,46406,46407,46408,46409,46410,46411,46412,46413,46414,46415,46416,46417,46418,46419,46420,46421,46422,46423,46424,46425,46426,46427,46428,46429,46430,46431,46432,46433,46434,46435,46436,46437,46438,46439,46440,46441,46442,46443,46444,46445,46446,46447,46448,46449,46450,46451,46452,46453,46454,46455,46456,46457,46458,46459,46460,46461,46462,46463,46464,46465,46466,46467,46468,46469,46470,46471,46472,46473,46474,46475,46476,46477,46478,46479,46480,46481,46482,46483,46484,46485,46486,46487,46488,46489,46490,46491,46492,46493,46494,46495,46496,46497,46498,46499,46500,46501,46502,46503,46504,46505,46506,46507,46508,46509,46510,46511,46512,46513,46514,46515,46516,46517,46518,46519,46520,46521,46522,46523,46524,46525,46526,46527,46528,46529,46530,46531,46532,46533,46534,46535,46536,46537,46538,46539,46540,46541,46542,46543,46544,46545,46546,46547,46548,46549,46550,46551,46552,46553,46554,46555,46556,46557,46558,46559,46560,46561,46562,46563,46564,46565,46566,46567,46568,46569,46570,46571,46572,46573,46574,46575,46576,46577,46578,46579,46580,46581,46582,46583,46584,46585,46586,46587,46588,46589,46590,46591,46592,46593,46594,46595,46596,46597,46598,46599,46600,46601,46602,46603,46604,46605,46606,46607,46608,46609,46610,46611,46612,46613,46614,46615,46616,46617,46618,46619,46620,46621,46622,46623,46624,46625,46626,46627,46628,46629,46630,46631,46632,46633,46634,46635,46636,46637,46638,46639,46640,46641,46642,46643,46644,46645,46646,46647,46648,46649,46650,46651,46652,46653,46654,46655,46656,46657,46658,46659,46660,46661,46662,46663,46664,46665,46666,46667,46668,46669,46670,46671,46672,46673,46674,46675,46676,46677,46678,46679,46680,46681,46682,46683,46684,46685,46686,46687,46688,46689,46690,46691,46692,46693,46694,46695,46696,46697,46698,46699,46700,46701,46702,46703,46704,46705,46706,46707,46708,46709,46710,46711,46712,46713,46714,46715,46716,46717,46718,46719,46720,46721,46722,46723,46724,46725,46726,46727,46728,46729,46730,46731,46732,46733,46734,46735,46736,46737,46738,46739,46740,46741,46742,46743,46744,46745,46746,46747,46748,46749,46750,46751,46752,46753,46754,46755,46756,46757,46758,46759,46760,46761,46762,46763,46764,46765,46766,46767,46768,46769,46770,46771,46772,46773,46774,46775,46776,46777,46778,46779,46780,46781,46782,46783,46784,46785,46786,46787,46788,46789,46790,46791,46792,46793,46794,46795,46796,46797,46798,46799,46800,46801,46802,46803,46804,46805,46806,46807,46808,46809,46810,46811,46812,46813,46814,46815,46816,46817,46818,46819,46820,46821,46822,46823,46824,46825,46826,46827,46828,46829,46830,46831,46832,46833,46834,46835,46836,46837,46838,46839,46840,46841,46842,46843,46844,46845,46846,46847,46848,46849,46850,46851,46852,46853,46854,46855,46856,46857,46858,46859,46860,46861,46862,46863,46864,46865,46866,46867,46868,46869,46870,46871,46872,46873,46874,46875,46876,46877,46878,46879,46880,46881,46882,46883,46884,46885,46886,46887,46888,46889,46890,46891,46892,46893,46894,46895,46896,46897,46898,46899,46900,46901,46902,46903,46904,46905,46906,46907,46908,46909,46910,46911,46912,46913,46914,46915,46916,46917,46918,46919,46920,46921,46922,46923,46924,46925,46926,46927,46928,46929,46930,46931,46932,46933,46934,46935,46936,46937,46938,46939,46940,46941,46942,46943,46944,46945,46946,46947,46948,46949,46950,46951,46952,46953,46954,46955,46956,46957,46958,46959,46960,46961,46962,46963,46964,46965,46966,46967,46968,46969,46970,46971,46972,46973,46974,46975,46976,46977,46978,46979,46980,46981,46982,46983,46984,46985,46986,46987,46988,46989,46990,46991,46992,46993,46994,46995,46996,46997,46998,46999,47000,47001,47002,47003,47004,47005,47006,47007,47008,47009,47010,47011,47012,47013,47014,47015,47016,47017,47018,47019,47020,47021,47022,47023,47024,47025,47026,47027,47028,47029,47030,47031,47032,47033,47034,47035,47036,47037,47038,47039,47040,47041,47042,47043,47044,47045,47046,47047,47048,47049,47050,47051,47052,47053,47054,47055,47056,47057,47058,47059,47060,47061,47062,47063,47064,47065,47066,47067,47068,47069,47070,47071,47072,47073,47074,47075,47076,47077,47078,47079,47080,47081,47082,47083,47084,47085,47086,47087,47088,47089,47090,47091,47092,47093,47094,47095,47096,47097,47098,47099,47100,47101,47102,47103,47104,47105,47106,47107,47108,47109,47110,47111,47112,47113,47114,47115,47116,47117,47118,47119,47120,47121,47122,47123,47124,47125,47126,47127,47128,47129,47130,47131,47132,47133,47134,47135,47136,47137,47138,47139,47140,47141,47142,47143,47144,47145,47146,47147,47148,47149,47150,47151,47152,47153,47154,47155,47156,47157,47158,47159,47160,47161,47162,47163,47164,47165,47166,47167,47168,47169,47170,47171,47172,47173,47174,47175,47176,47177,47178,47179,47180,47181,47182,47183,47184,47185,47186,47187,47188,47189,47190,47191,47192,47193,47194,47195,47196,47197,47198,47199,47200,47201,47202,47203,47204,47205,47206,47207,47208,47209,47210,47211,47212,47213,47214,47215,47216,47217,47218,47219,47220,47221,47222,47223,47224,47225,47226,47227,47228,47229,47230,47231,47232,47233,47234,47235,47236,47237,47238,47239,47240,47241,47242,47243,47244,47245,47246,47247,47248,47249,47250,47251,47252,47253,47254,47255,47256,47257,47258,47259,47260,47261,47262,47263,47264,47265,47266,47267,47268,47269,47270,47271,47272,47273,47274,47275,47276,47277,47278,47279,47280,47281,47282,47283,47284,47285,47286,47287,47288,47289,47290,47291,47292,47293,47294,47295,47296,47297,47298,47299,47300,47301,47302,47303,47304,47305,47306,47307,47308,47309,47310,47311,47312,47313,47314,47315,47316,47317,47318,47319,47320,47321,47322,47323,47324,47325,47326,47327,47328,47329,47330,47331,47332,47333,47334,47335,47336,47337,47338,47339,47340,47341,47342,47343,47344,47345,47346,47347,47348,47349,47350,47351,47352,47353,47354,47355,47356,47357,47358,47359,47360,47361,47362,47363,47364,47365,47366,47367,47368,47369,47370,47371,47372,47373,47374,47375,47376,47377,47378,47379,47380,47381,47382,47383,47384,47385,47386,47387,47388,47389,47390,47391,47392,47393,47394,47395,47396,47397,47398,47399,47400,47401,47402,47403,47404,47405,47406,47407,47408,47409,47410,47411,47412,47413,47414,47415,47416,47417,47418,47419,47420,47421,47422,47423,47424,47425,47426,47427,47428,47429,47430,47431,47432,47433,47434,47435,47436,47437,47438,47439,47440,47441,47442,47443,47444,47445,47446,47447,47448,47449,47450,47451,47452,47453,47454,47455,47456,47457,47458,47459,47460,47461,47462,47463,47464,47465,47466,47467,47468,47469,47470,47471,47472,47473,47474,47475,47476,47477,47478,47479,47480,47481,47482,47483,47484,47485,47486,47487,47488,47489,47490,47491,47492,47493,47494,47495,47496,47497,47498,47499,47500,47501,47502,47503,47504,47505,47506,47507,47508,47509,47510,47511,47512,47513,47514,47515,47516,47517,47518,47519,47520,47521,47522,47523,47524,47525,47526,47527,47528,47529,47530,47531,47532,47533,47534,47535,47536,47537,47538,47539,47540,47541,47542,47543,47544,47545,47546,47547,47548,47549,47550,47551,47552,47553,47554,47555,47556,47557,47558,47559,47560,47561,47562,47563,47564,47565,47566,47567,47568,47569,47570,47571,47572,47573,47574,47575,47576,47577,47578,47579,47580,47581,47582,47583,47584,47585,47586,47587,47588,47589,47590,47591,47592,47593,47594,47595,47596,47597,47598,47599,47600,47601,47602,47603,47604,47605,47606,47607,47608,47609,47610,47611,47612,47613,47614,47615,47616,47617,47618,47619,47620,47621,47622,47623,47624,47625,47626,47627,47628,47629,47630,47631,47632,47633,47634,47635,47636,47637,47638,47639,47640,47641,47642,47643,47644,47645,47646,47647,47648,47649,47650,47651,47652,47653,47654,47655,47656,47657,47658,47659,47660,47661,47662,47663,47664,47665,47666,47667,47668,47669,47670,47671,47672,47673,47674,47675,47676,47677,47678,47679,47680,47681,47682,47683,47684,47685,47686,47687,47688,47689,47690,47691,47692,47693,47694,47695,47696,47697,47698,47699,47700,47701,47702,47703,47704,47705,47706,47707,47708,47709,47710,47711,47712,47713,47714,47715,47716,47717,47718,47719,47720,47721,47722,47723,47724,47725,47726,47727,47728,47729,47730,47731,47732,47733,47734,47735,47736,47737,47738,47739,47740,47741,47742,47743,47744,47745,47746,47747,47748,47749,47750,47751,47752,47753,47754,47755,47756,47757,47758,47759,47760,47761,47762,47763,47764,47765,47766,47767,47768,47769,47770,47771,47772,47773,47774,47775,47776,47777,47778,47779,47780,47781,47782,47783,47784,47785,47786,47787,47788,47789,47790,47791,47792,47793,47794,47795,47796,47797,47798,47799,47800,47801,47802,47803,47804,47805,47806,47807,47808,47809,47810,47811,47812,47813,47814,47815,47816,47817,47818,47819,47820,47821,47822,47823,47824,47825,47826,47827,47828,47829,47830,47831,47832,47833,47834,47835,47836,47837,47838,47839,47840,47841,47842,47843,47844,47845,47846,47847,47848,47849,47850,47851,47852,47853,47854,47855,47856,47857,47858,47859,47860,47861,47862,47863,47864,47865,47866,47867,47868,47869,47870,47871,47872,47873,47874,47875,47876,47877,47878,47879,47880,47881,47882,47883,47884,47885,47886,47887,47888,47889,47890,47891,47892,47893,47894,47895,47896,47897,47898,47899,47900,47901,47902,47903,47904,47905,47906,47907,47908,47909,47910,47911,47912,47913,47914,47915,47916,47917,47918,47919,47920,47921,47922,47923,47924,47925,47926,47927,47928,47929,47930,47931,47932,47933,47934,47935,47936,47937,47938,47939,47940,47941,47942,47943,47944,47945,47946,47947,47948,47949,47950,47951,47952,47953,47954,47955,47956,47957,47958,47959,47960,47961,47962,47963,47964,47965,47966,47967,47968,47969,47970,47971,47972,47973,47974,47975,47976,47977,47978,47979,47980,47981,47982,47983,47984,47985,47986,47987,47988,47989,47990,47991,47992,47993,47994,47995,47996,47997,47998,47999,48000,48001,48002,48003,48004,48005,48006,48007,48008,48009,48010,48011,48012,48013,48014,48015,48016,48017,48018,48019,48020,48021,48022,48023,48024,48025,48026,48027,48028,48029,48030,48031,48032,48033,48034,48035,48036,48037,48038,48039,48040,48041,48042,48043,48044,48045,48046,48047,48048,48049,48050,48051,48052,48053,48054,48055,48056,48057,48058,48059,48060,48061,48062,48063,48064,48065,48066,48067,48068,48069,48070,48071,48072,48073,48074,48075,48076,48077,48078,48079,48080,48081,48082,48083,48084,48085,48086,48087,48088,48089,48090,48091,48092,48093,48094,48095,48096,48097,48098,48099,48100,48101,48102,48103,48104,48105,48106,48107,48108,48109,48110,48111,48112,48113,48114,48115,48116,48117,48118,48119,48120,48121,48122,48123,48124,48125,48126,48127,48128,48129,48130,48131,48132,48133,48134,48135,48136,48137,48138,48139,48140,48141,48142,48143,48144,48145,48146,48147,48148,48149,48150,48151,48152,48153,48154,48155,48156,48157,48158,48159,48160,48161,48162,48163,48164,48165,48166,48167,48168,48169,48170,48171,48172,48173,48174,48175,48176,48177,48178,48179,48180,48181,48182,48183,48184,48185,48186,48187,48188,48189,48190,48191,48192,48193,48194,48195,48196,48197,48198,48199,48200,48201,48202,48203,48204,48205,48206,48207,48208,48209,48210,48211,48212,48213,48214,48215,48216,48217,48218,48219,48220,48221,48222,48223,48224,48225,48226,48227,48228,48229,48230,48231,48232,48233,48234,48235,48236,48237,48238,48239,48240,48241,48242,48243,48244,48245,48246,48247,48248,48249,48250,48251,48252,48253,48254,48255,48256,48257,48258,48259,48260,48261,48262,48263,48264,48265,48266,48267,48268,48269,48270,48271,48272,48273,48274,48275,48276,48277,48278,48279,48280,48281,48282,48283,48284,48285,48286,48287,48288,48289,48290,48291,48292,48293,48294,48295,48296,48297,48298,48299,48300,48301,48302,48303,48304,48305,48306,48307,48308,48309,48310,48311,48312,48313,48314,48315,48316,48317,48318,48319,48320,48321,48322,48323,48324,48325,48326,48327,48328,48329,48330,48331,48332,48333,48334,48335,48336,48337,48338,48339,48340,48341,48342,48343,48344,48345,48346,48347,48348,48349,48350,48351,48352,48353,48354,48355,48356,48357,48358,48359,48360,48361,48362,48363,48364,48365,48366,48367,48368,48369,48370,48371,48372,48373,48374,48375,48376,48377,48378,48379,48380,48381,48382,48383,48384,48385,48386,48387,48388,48389,48390,48391,48392,48393,48394,48395,48396,48397,48398,48399,48400,48401,48402,48403,48404,48405,48406,48407,48408,48409,48410,48411,48412,48413,48414,48415,48416,48417,48418,48419,48420,48421,48422,48423,48424,48425,48426,48427,48428,48429,48430,48431,48432,48433,48434,48435,48436,48437,48438,48439,48440,48441,48442,48443,48444,48445,48446,48447,48448,48449,48450,48451,48452,48453,48454,48455,48456,48457,48458,48459,48460,48461,48462,48463,48464,48465,48466,48467,48468,48469,48470,48471,48472,48473,48474,48475,48476,48477,48478,48479,48480,48481,48482,48483,48484,48485,48486,48487,48488,48489,48490,48491,48492,48493,48494,48495,48496,48497,48498,48499,48500,48501,48502,48503,48504,48505,48506,48507,48508,48509,48510,48511,48512,48513,48514,48515,48516,48517,48518,48519,48520,48521,48522,48523,48524,48525,48526,48527,48528,48529,48530,48531,48532,48533,48534,48535,48536,48537,48538,48539,48540,48541,48542,48543,48544,48545,48546,48547,48548,48549,48550,48551,48552,48553,48554,48555,48556,48557,48558,48559,48560,48561,48562,48563,48564,48565,48566,48567,48568,48569,48570,48571,48572,48573,48574,48575,48576,48577,48578,48579,48580,48581,48582,48583,48584,48585,48586,48587,48588,48589,48590,48591,48592,48593,48594,48595,48596,48597,48598,48599,48600,48601,48602,48603,48604,48605,48606,48607,48608,48609,48610,48611,48612,48613,48614,48615,48616,48617,48618,48619,48620,48621,48622,48623,48624,48625,48626,48627,48628,48629,48630,48631,48632,48633,48634,48635,48636,48637,48638,48639,48640,48641,48642,48643,48644,48645,48646,48647,48648,48649,48650,48651,48652,48653,48654,48655,48656,48657,48658,48659,48660,48661,48662,48663,48664,48665,48666,48667,48668,48669,48670,48671,48672,48673,48674,48675,48676,48677,48678,48679,48680,48681,48682,48683,48684,48685,48686,48687,48688,48689,48690,48691,48692,48693,48694,48695,48696,48697,48698,48699,48700,48701,48702,48703,48704,48705,48706,48707,48708,48709,48710,48711,48712,48713,48714,48715,48716,48717,48718,48719,48720,48721,48722,48723,48724,48725,48726,48727,48728,48729,48730,48731,48732,48733,48734,48735,48736,48737,48738,48739,48740,48741,48742,48743,48744,48745,48746,48747,48748,48749,48750,48751,48752,48753,48754,48755,48756,48757,48758,48759,48760,48761,48762,48763,48764,48765,48766,48767,48768,48769,48770,48771,48772,48773,48774,48775,48776,48777,48778,48779,48780,48781,48782,48783,48784,48785,48786,48787,48788,48789,48790,48791,48792,48793,48794,48795,48796,48797,48798,48799,48800,48801,48802,48803,48804,48805,48806,48807,48808,48809,48810,48811,48812,48813,48814,48815,48816,48817,48818,48819,48820,48821,48822,48823,48824,48825,48826,48827,48828,48829,48830,48831,48832,48833,48834,48835,48836,48837,48838,48839,48840,48841,48842,48843,48844,48845,48846,48847,48848,48849,48850,48851,48852,48853,48854,48855,48856,48857,48858,48859,48860,48861,48862,48863,48864,48865,48866,48867,48868,48869,48870,48871,48872,48873,48874,48875,48876,48877,48878,48879,48880,48881,48882,48883,48884,48885,48886,48887,48888,48889,48890,48891,48892,48893,48894,48895,48896,48897,48898,48899,48900,48901,48902,48903,48904,48905,48906,48907,48908,48909,48910,48911,48912,48913,48914,48915,48916,48917,48918,48919,48920,48921,48922,48923,48924,48925,48926,48927,48928,48929,48930,48931,48932,48933,48934,48935,48936,48937,48938,48939,48940,48941,48942,48943,48944,48945,48946,48947,48948,48949,48950,48951,48952,48953,48954,48955,48956,48957,48958,48959,48960,48961,48962,48963,48964,48965,48966,48967,48968,48969,48970,48971,48972,48973,48974,48975,48976,48977,48978,48979,48980,48981,48982,48983,48984,48985,48986,48987,48988,48989,48990,48991,48992,48993,48994,48995,48996,48997,48998,48999,49000,49001,49002,49003,49004,49005,49006,49007,49008,49009,49010,49011,49012,49013,49014,49015,49016,49017,49018,49019,49020,49021,49022,49023,49024,49025,49026,49027,49028,49029,49030,49031,49032,49033,49034,49035,49036,49037,49038,49039,49040,49041,49042,49043,49044,49045,49046,49047,49048,49049,49050,49051,49052,49053,49054,49055,49056,49057,49058,49059,49060,49061,49062,49063,49064,49065,49066,49067,49068,49069,49070,49071,49072,49073,49074,49075,49076,49077,49078,49079,49080,49081,49082,49083,49084,49085,49086,49087,49088,49089,49090,49091,49092,49093,49094,49095,49096,49097,49098,49099,49100,49101,49102,49103,49104,49105,49106,49107,49108,49109,49110,49111,49112,49113,49114,49115,49116,49117,49118,49119,49120,49121,49122,49123,49124,49125,49126,49127,49128,49129,49130,49131,49132,49133,49134,49135,49136,49137,49138,49139,49140,49141,49142,49143,49144,49145,49146,49147,49148,49149,49150,49151,49152,49153,49154,49155,49156,49157,49158,49159,49160,49161,49162,49163,49164,49165,49166,49167,49168,49169,49170,49171,49172,49173,49174,49175,49176,49177,49178,49179,49180,49181,49182,49183,49184,49185,49186,49187,49188,49189,49190,49191,49192,49193,49194,49195,49196,49197,49198,49199,49200,49201,49202,49203,49204,49205,49206,49207,49208,49209,49210,49211,49212,49213,49214,49215,49216,49217,49218,49219,49220,49221,49222,49223,49224,49225,49226,49227,49228,49229,49230,49231,49232,49233,49234,49235,49236,49237,49238,49239,49240,49241,49242,49243,49244,49245,49246,49247,49248,49249,49250,49251,49252,49253,49254,49255,49256,49257,49258,49259,49260,49261,49262,49263,49264,49265,49266,49267,49268,49269,49270,49271,49272,49273,49274,49275,49276,49277,49278,49279,49280,49281,49282,49283,49284,49285,49286,49287,49288,49289,49290,49291,49292,49293,49294,49295,49296,49297,49298,49299,49300,49301,49302,49303,49304,49305,49306,49307,49308,49309,49310,49311,49312,49313,49314,49315,49316,49317,49318,49319,49320,49321,49322,49323,49324,49325,49326,49327,49328,49329,49330,49331,49332,49333,49334,49335,49336,49337,49338,49339,49340,49341,49342,49343,49344,49345,49346,49347,49348,49349,49350,49351,49352,49353,49354,49355,49356,49357,49358,49359,49360,49361,49362,49363,49364,49365,49366,49367,49368,49369,49370,49371,49372,49373,49374,49375,49376,49377,49378,49379,49380,49381,49382,49383,49384,49385,49386,49387,49388,49389,49390,49391,49392,49393,49394,49395,49396,49397,49398,49399,49400,49401,49402,49403,49404,49405,49406,49407,49408,49409,49410,49411,49412,49413,49414,49415,49416,49417,49418,49419,49420,49421,49422,49423,49424,49425,49426,49427,49428,49429,49430,49431,49432,49433,49434,49435,49436,49437,49438,49439,49440,49441,49442,49443,49444,49445,49446,49447,49448,49449,49450,49451,49452,49453,49454,49455,49456,49457,49458,49459,49460,49461,49462,49463,49464,49465,49466,49467,49468,49469,49470,49471,49472,49473,49474,49475,49476,49477,49478,49479,49480,49481,49482,49483,49484,49485,49486,49487,49488,49489,49490,49491,49492,49493,49494,49495,49496,49497,49498,49499,49500,49501,49502,49503,49504,49505,49506,49507,49508,49509,49510,49511,49512,49513,49514,49515,49516,49517,49518,49519,49520,49521,49522,49523,49524,49525,49526,49527,49528,49529,49530,49531,49532,49533,49534,49535,49536,49537,49538,49539,49540,49541,49542,49543,49544,49545,49546,49547,49548,49549,49550,49551,49552,49553,49554,49555,49556,49557,49558,49559,49560,49561,49562,49563,49564,49565,49566,49567,49568,49569,49570,49571,49572,49573,49574,49575,49576,49577,49578,49579,49580,49581,49582,49583,49584,49585,49586,49587,49588,49589,49590,49591,49592,49593,49594,49595,49596,49597,49598,49599,49600,49601,49602,49603,49604,49605,49606,49607,49608,49609,49610,49611,49612,49613,49614,49615,49616,49617,49618,49619,49620,49621,49622,49623,49624,49625,49626,49627,49628,49629,49630,49631,49632,49633,49634,49635,49636,49637,49638,49639,49640,49641,49642,49643,49644,49645,49646,49647,49648,49649,49650,49651,49652,49653,49654,49655,49656,49657,49658,49659,49660,49661,49662,49663,49664,49665,49666,49667,49668,49669,49670,49671,49672,49673,49674,49675,49676,49677,49678,49679,49680,49681,49682,49683,49684,49685,49686,49687,49688,49689,49690,49691,49692,49693,49694,49695,49696,49697,49698,49699,49700,49701,49702,49703,49704,49705,49706,49707,49708,49709,49710,49711,49712,49713,49714,49715,49716,49717,49718,49719,49720,49721,49722,49723,49724,49725,49726,49727,49728,49729,49730,49731,49732,49733,49734,49735,49736,49737,49738,49739,49740,49741,49742,49743,49744,49745,49746,49747,49748,49749,49750,49751,49752,49753,49754,49755,49756,49757,49758,49759,49760,49761,49762,49763,49764,49765,49766,49767,49768,49769,49770,49771,49772,49773,49774,49775,49776,49777,49778,49779,49780,49781,49782,49783,49784,49785,49786,49787,49788,49789,49790,49791,49792,49793,49794,49795,49796,49797,49798,49799,49800,49801,49802,49803,49804,49805,49806,49807,49808,49809,49810,49811,49812,49813,49814,49815,49816,49817,49818,49819,49820,49821,49822,49823,49824,49825,49826,49827,49828,49829,49830,49831,49832,49833,49834,49835,49836,49837,49838,49839,49840,49841,49842,49843,49844,49845,49846,49847,49848,49849,49850,49851,49852,49853,49854,49855,49856,49857,49858,49859,49860,49861,49862,49863,49864,49865,49866,49867,49868,49869,49870,49871,49872,49873,49874,49875,49876,49877,49878,49879,49880,49881,49882,49883,49884,49885,49886,49887,49888,49889,49890,49891,49892,49893,49894,49895,49896,49897,49898,49899,49900,49901,49902,49903,49904,49905,49906,49907,49908,49909,49910,49911,49912,49913,49914,49915,49916,49917,49918,49919,49920,49921,49922,49923,49924,49925,49926,49927,49928,49929,49930,49931,49932,49933,49934,49935,49936,49937,49938,49939,49940,49941,49942,49943,49944,49945,49946,49947,49948,49949,49950,49951,49952,49953,49954,49955,49956,49957,49958,49959,49960,49961,49962,49963,49964,49965,49966,49967,49968,49969,49970,49971,49972,49973,49974,49975,49976,49977,49978,49979,49980,49981,49982,49983,49984,49985,49986,49987,49988,49989,49990,49991,49992,49993,49994,49995,49996,49997,49998,49999,50000,50001,50002,50003,50004,50005,50006,50007,50008,50009,50010,50011,50012,50013,50014,50015,50016,50017,50018,50019,50020,50021,50022,50023,50024,50025,50026,50027,50028,50029,50030,50031,50032,50033,50034,50035,50036,50037,50038,50039,50040,50041,50042,50043,50044,50045,50046,50047,50048,50049,50050,50051,50052,50053,50054,50055,50056,50057,50058,50059,50060,50061,50062,50063,50064,50065,50066,50067,50068,50069,50070,50071,50072,50073,50074,50075,50076,50077,50078,50079,50080,50081,50082,50083,50084,50085,50086,50087,50088,50089,50090,50091,50092,50093,50094,50095,50096,50097,50098,50099,50100,50101,50102,50103,50104,50105,50106,50107,50108,50109,50110,50111,50112,50113,50114,50115,50116,50117,50118,50119,50120,50121,50122,50123,50124,50125,50126,50127,50128,50129,50130,50131,50132,50133,50134,50135,50136,50137,50138,50139,50140,50141,50142,50143,50144,50145,50146,50147,50148,50149,50150,50151,50152,50153,50154,50155,50156,50157,50158,50159,50160,50161,50162,50163,50164,50165,50166,50167,50168,50169,50170,50171,50172,50173,50174,50175,50176,50177,50178,50179,50180,50181,50182,50183,50184,50185,50186,50187,50188,50189,50190,50191,50192,50193,50194,50195,50196,50197,50198,50199,50200,50201,50202,50203,50204,50205,50206,50207,50208,50209,50210,50211,50212,50213,50214,50215,50216,50217,50218,50219,50220,50221,50222,50223,50224,50225,50226,50227,50228,50229,50230,50231,50232,50233,50234,50235,50236,50237,50238,50239,50240,50241,50242,50243,50244,50245,50246,50247,50248,50249,50250,50251,50252,50253,50254,50255,50256,50257,50258,50259,50260,50261,50262,50263,50264,50265,50266,50267,50268,50269,50270,50271,50272,50273,50274,50275,50276,50277,50278,50279,50280,50281,50282,50283,50284,50285,50286,50287,50288,50289,50290,50291,50292,50293,50294,50295,50296,50297,50298,50299,50300,50301,50302,50303,50304,50305,50306,50307,50308,50309,50310,50311,50312,50313,50314,50315,50316,50317,50318,50319,50320,50321,50322,50323,50324,50325,50326,50327,50328,50329,50330,50331,50332,50333,50334,50335,50336,50337,50338,50339,50340,50341,50342,50343,50344,50345,50346,50347,50348,50349,50350,50351,50352,50353,50354,50355,50356,50357,50358,50359,50360,50361,50362,50363,50364,50365,50366,50367,50368,50369,50370,50371,50372,50373,50374,50375,50376,50377,50378,50379,50380,50381,50382,50383,50384,50385,50386,50387,50388,50389,50390,50391,50392,50393,50394,50395,50396,50397,50398,50399,50400,50401,50402,50403,50404,50405,50406,50407,50408,50409,50410,50411,50412,50413,50414,50415,50416,50417,50418,50419,50420,50421,50422,50423,50424,50425,50426,50427,50428,50429,50430,50431,50432,50433,50434,50435,50436,50437,50438,50439,50440,50441,50442,50443,50444,50445,50446,50447,50448,50449,50450,50451,50452,50453,50454,50455,50456,50457,50458,50459,50460,50461,50462,50463,50464,50465,50466,50467,50468,50469,50470,50471,50472,50473,50474,50475,50476,50477,50478,50479,50480,50481,50482,50483,50484,50485,50486,50487,50488,50489,50490,50491,50492,50493,50494,50495,50496,50497,50498,50499,50500,50501,50502,50503,50504,50505,50506,50507,50508,50509,50510,50511,50512,50513,50514,50515,50516,50517,50518,50519,50520,50521,50522,50523,50524,50525,50526,50527,50528,50529,50530,50531,50532,50533,50534,50535,50536,50537,50538,50539,50540,50541,50542,50543,50544,50545,50546,50547,50548,50549,50550,50551,50552,50553,50554,50555,50556,50557,50558,50559,50560,50561,50562,50563,50564,50565,50566,50567,50568,50569,50570,50571,50572,50573,50574,50575,50576,50577,50578,50579,50580,50581,50582,50583,50584,50585,50586,50587,50588,50589,50590,50591,50592,50593,50594,50595,50596,50597,50598,50599,50600,50601,50602,50603,50604,50605,50606,50607,50608,50609,50610,50611,50612,50613,50614,50615,50616,50617,50618,50619,50620,50621,50622,50623,50624,50625,50626,50627,50628,50629,50630,50631,50632,50633,50634,50635,50636,50637,50638,50639,50640,50641,50642,50643,50644,50645,50646,50647,50648,50649,50650,50651,50652,50653,50654,50655,50656,50657,50658,50659,50660,50661,50662,50663,50664,50665,50666,50667,50668,50669,50670,50671,50672,50673,50674,50675,50676,50677,50678,50679,50680,50681,50682,50683,50684,50685,50686,50687,50688,50689,50690,50691,50692,50693,50694,50695,50696,50697,50698,50699,50700,50701,50702,50703,50704,50705,50706,50707,50708,50709,50710,50711,50712,50713,50714,50715,50716,50717,50718,50719,50720,50721,50722,50723,50724,50725,50726,50727,50728,50729,50730,50731,50732,50733,50734,50735,50736,50737,50738,50739,50740,50741,50742,50743,50744,50745,50746,50747,50748,50749,50750,50751,50752,50753,50754,50755,50756,50757,50758,50759,50760,50761,50762,50763,50764,50765,50766,50767,50768,50769,50770,50771,50772,50773,50774,50775,50776,50777,50778,50779,50780,50781,50782,50783,50784,50785,50786,50787,50788,50789,50790,50791,50792,50793,50794,50795,50796,50797,50798,50799,50800,50801,50802,50803,50804,50805,50806,50807,50808,50809,50810,50811,50812,50813,50814,50815,50816,50817,50818,50819,50820,50821,50822,50823,50824,50825,50826,50827,50828,50829,50830,50831,50832,50833,50834,50835,50836,50837,50838,50839,50840,50841,50842,50843,50844,50845,50846,50847,50848,50849,50850,50851,50852,50853,50854,50855,50856,50857,50858,50859,50860,50861,50862,50863,50864,50865,50866,50867,50868,50869,50870,50871,50872,50873,50874,50875,50876,50877,50878,50879,50880,50881,50882,50883,50884,50885,50886,50887,50888,50889,50890,50891,50892,50893,50894,50895,50896,50897,50898,50899,50900,50901,50902,50903,50904,50905,50906,50907,50908,50909,50910,50911,50912,50913,50914,50915,50916,50917,50918,50919,50920,50921,50922,50923,50924,50925,50926,50927,50928,50929,50930,50931,50932,50933,50934,50935,50936,50937,50938,50939,50940,50941,50942,50943,50944,50945,50946,50947,50948,50949,50950,50951,50952,50953,50954,50955,50956,50957,50958,50959,50960,50961,50962,50963,50964,50965,50966,50967,50968,50969,50970,50971,50972,50973,50974,50975,50976,50977,50978,50979,50980,50981,50982,50983,50984,50985,50986,50987,50988,50989,50990,50991,50992,50993,50994,50995,50996,50997,50998,50999,51000,51001,51002,51003,51004,51005,51006,51007,51008,51009,51010,51011,51012,51013,51014,51015,51016,51017,51018,51019,51020,51021,51022,51023,51024,51025,51026,51027,51028,51029,51030,51031,51032,51033,51034,51035,51036,51037,51038,51039,51040,51041,51042,51043,51044,51045,51046,51047,51048,51049,51050,51051,51052,51053,51054,51055,51056,51057,51058,51059,51060,51061,51062,51063,51064,51065,51066,51067,51068,51069,51070,51071,51072,51073,51074,51075,51076,51077,51078,51079,51080,51081,51082,51083,51084,51085,51086,51087,51088,51089,51090,51091,51092,51093,51094,51095,51096,51097,51098,51099,51100,51101,51102,51103,51104,51105,51106,51107,51108,51109,51110,51111,51112,51113,51114,51115,51116,51117,51118,51119,51120,51121,51122,51123,51124,51125,51126,51127,51128,51129,51130,51131,51132,51133,51134,51135,51136,51137,51138,51139,51140,51141,51142,51143,51144,51145,51146,51147,51148,51149,51150,51151,51152,51153,51154,51155,51156,51157,51158,51159,51160,51161,51162,51163,51164,51165,51166,51167,51168,51169,51170,51171,51172,51173,51174,51175,51176,51177,51178,51179,51180,51181,51182,51183,51184,51185,51186,51187,51188,51189,51190,51191,51192,51193,51194,51195,51196,51197,51198,51199,51200,51201,51202,51203,51204,51205,51206,51207,51208,51209,51210,51211,51212,51213,51214,51215,51216,51217,51218,51219,51220,51221,51222,51223,51224,51225,51226,51227,51228,51229,51230,51231,51232,51233,51234,51235,51236,51237,51238,51239,51240,51241,51242,51243,51244,51245,51246,51247,51248,51249,51250,51251,51252,51253,51254,51255,51256,51257,51258,51259,51260,51261,51262,51263,51264,51265,51266,51267,51268,51269,51270,51271,51272,51273,51274,51275,51276,51277,51278,51279,51280,51281,51282,51283,51284,51285,51286,51287,51288,51289,51290,51291,51292,51293,51294,51295,51296,51297,51298,51299,51300,51301,51302,51303,51304,51305,51306,51307,51308,51309,51310,51311,51312,51313,51314,51315,51316,51317,51318,51319,51320,51321,51322,51323,51324,51325,51326,51327,51328,51329,51330,51331,51332,51333,51334,51335,51336,51337,51338,51339,51340,51341,51342,51343,51344,51345,51346,51347,51348,51349,51350,51351,51352,51353,51354,51355,51356,51357,51358,51359,51360,51361,51362,51363,51364,51365,51366,51367,51368,51369,51370,51371,51372,51373,51374,51375,51376,51377,51378,51379,51380,51381,51382,51383,51384,51385,51386,51387,51388,51389,51390,51391,51392,51393,51394,51395,51396,51397,51398,51399,51400,51401,51402,51403,51404,51405,51406,51407,51408,51409,51410,51411,51412,51413,51414,51415,51416,51417,51418,51419,51420,51421,51422,51423,51424,51425,51426,51427,51428,51429,51430,51431,51432,51433,51434,51435,51436,51437,51438,51439,51440,51441,51442,51443,51444,51445,51446,51447,51448,51449,51450,51451,51452,51453,51454,51455,51456,51457,51458,51459,51460,51461,51462,51463,51464,51465,51466,51467,51468,51469,51470,51471,51472,51473,51474,51475,51476,51477,51478,51479,51480,51481,51482,51483,51484,51485,51486,51487,51488,51489,51490,51491,51492,51493,51494,51495,51496,51497,51498,51499,51500,51501,51502,51503,51504,51505,51506,51507,51508,51509,51510,51511,51512,51513,51514,51515,51516,51517,51518,51519,51520,51521,51522,51523,51524,51525,51526,51527,51528,51529,51530,51531,51532,51533,51534,51535,51536,51537,51538,51539,51540,51541,51542,51543,51544,51545,51546,51547,51548,51549,51550,51551,51552,51553,51554,51555,51556,51557,51558,51559,51560,51561,51562,51563,51564,51565,51566,51567,51568,51569,51570,51571,51572,51573,51574,51575,51576,51577,51578,51579,51580,51581,51582,51583,51584,51585,51586,51587,51588,51589,51590,51591,51592,51593,51594,51595,51596,51597,51598,51599,51600,51601,51602,51603,51604,51605,51606,51607,51608,51609,51610,51611,51612,51613,51614,51615,51616,51617,51618,51619,51620,51621,51622,51623,51624,51625,51626,51627,51628,51629,51630,51631,51632,51633,51634,51635,51636,51637,51638,51639,51640,51641,51642,51643,51644,51645,51646,51647,51648,51649,51650,51651,51652,51653,51654,51655,51656,51657,51658,51659,51660,51661,51662,51663,51664,51665,51666,51667,51668,51669,51670,51671,51672,51673,51674,51675,51676,51677,51678,51679,51680,51681,51682,51683,51684,51685,51686,51687,51688,51689,51690,51691,51692,51693,51694,51695,51696,51697,51698,51699,51700,51701,51702,51703,51704,51705,51706,51707,51708,51709,51710,51711,51712,51713,51714,51715,51716,51717,51718,51719,51720,51721,51722,51723,51724,51725,51726,51727,51728,51729,51730,51731,51732,51733,51734,51735,51736,51737,51738,51739,51740,51741,51742,51743,51744,51745,51746,51747,51748,51749,51750,51751,51752,51753,51754,51755,51756,51757,51758,51759,51760,51761,51762,51763,51764,51765,51766,51767,51768,51769,51770,51771,51772,51773,51774,51775,51776,51777,51778,51779,51780,51781,51782,51783,51784,51785,51786,51787,51788,51789,51790,51791,51792,51793,51794,51795,51796,51797,51798,51799,51800,51801,51802,51803,51804,51805,51806,51807,51808,51809,51810,51811,51812,51813,51814,51815,51816,51817,51818,51819,51820,51821,51822,51823,51824,51825,51826,51827,51828,51829,51830,51831,51832,51833,51834,51835,51836,51837,51838,51839,51840,51841,51842,51843,51844,51845,51846,51847,51848,51849,51850,51851,51852,51853,51854,51855,51856,51857,51858,51859,51860,51861,51862,51863,51864,51865,51866,51867,51868,51869,51870,51871,51872,51873,51874,51875,51876,51877,51878,51879,51880,51881,51882,51883,51884,51885,51886,51887,51888,51889,51890,51891,51892,51893,51894,51895,51896,51897,51898,51899,51900,51901,51902,51903,51904,51905,51906,51907,51908,51909,51910,51911,51912,51913,51914,51915,51916,51917,51918,51919,51920,51921,51922,51923,51924,51925,51926,51927,51928,51929,51930,51931,51932,51933,51934,51935,51936,51937,51938,51939,51940,51941,51942,51943,51944,51945,51946,51947,51948,51949,51950,51951,51952,51953,51954,51955,51956,51957,51958,51959,51960,51961,51962,51963,51964,51965,51966,51967,51968,51969,51970,51971,51972,51973,51974,51975,51976,51977,51978,51979,51980,51981,51982,51983,51984,51985,51986,51987,51988,51989,51990,51991,51992,51993,51994,51995,51996,51997,51998,51999,52000,52001,52002,52003,52004,52005,52006,52007,52008,52009,52010,52011,52012,52013,52014,52015,52016,52017,52018,52019,52020,52021,52022,52023,52024,52025,52026,52027,52028,52029,52030,52031,52032,52033,52034,52035,52036,52037,52038,52039,52040,52041,52042,52043,52044,52045,52046,52047,52048,52049,52050,52051,52052,52053,52054,52055,52056,52057,52058,52059,52060,52061,52062,52063,52064,52065,52066,52067,52068,52069,52070,52071,52072,52073,52074,52075,52076,52077,52078,52079,52080,52081,52082,52083,52084,52085,52086,52087,52088,52089,52090,52091,52092,52093,52094,52095,52096,52097,52098,52099,52100,52101,52102,52103,52104,52105,52106,52107,52108,52109,52110,52111,52112,52113,52114,52115,52116,52117,52118,52119,52120,52121,52122,52123,52124,52125,52126,52127,52128,52129,52130,52131,52132,52133,52134,52135,52136,52137,52138,52139,52140,52141,52142,52143,52144,52145,52146,52147,52148,52149,52150,52151,52152,52153,52154,52155,52156,52157,52158,52159,52160,52161,52162,52163,52164,52165,52166,52167,52168,52169,52170,52171,52172,52173,52174,52175,52176,52177,52178,52179,52180,52181,52182,52183,52184,52185,52186,52187,52188,52189,52190,52191,52192,52193,52194,52195,52196,52197,52198,52199,52200,52201,52202,52203,52204,52205,52206,52207,52208,52209,52210,52211,52212,52213,52214,52215,52216,52217,52218,52219,52220,52221,52222,52223,52224,52225,52226,52227,52228,52229,52230,52231,52232,52233,52234,52235,52236,52237,52238,52239,52240,52241,52242,52243,52244,52245,52246,52247,52248,52249,52250,52251,52252,52253,52254,52255,52256,52257,52258,52259,52260,52261,52262,52263,52264,52265,52266,52267,52268,52269,52270,52271,52272,52273,52274,52275,52276,52277,52278,52279,52280,52281,52282,52283,52284,52285,52286,52287,52288,52289,52290,52291,52292,52293,52294,52295,52296,52297,52298,52299,52300,52301,52302,52303,52304,52305,52306,52307,52308,52309,52310,52311,52312,52313,52314,52315,52316,52317,52318,52319,52320,52321,52322,52323,52324,52325,52326,52327,52328,52329,52330,52331,52332,52333,52334,52335,52336,52337,52338,52339,52340,52341,52342,52343,52344,52345,52346,52347,52348,52349,52350,52351,52352,52353,52354,52355,52356,52357,52358,52359,52360,52361,52362,52363,52364,52365,52366,52367,52368,52369,52370,52371,52372,52373,52374,52375,52376,52377,52378,52379,52380,52381,52382,52383,52384,52385,52386,52387,52388,52389,52390,52391,52392,52393,52394,52395,52396,52397,52398,52399,52400,52401,52402,52403,52404,52405,52406,52407,52408,52409,52410,52411,52412,52413,52414,52415,52416,52417,52418,52419,52420,52421,52422,52423,52424,52425,52426,52427,52428,52429,52430,52431,52432,52433,52434,52435,52436,52437,52438,52439,52440,52441,52442,52443,52444,52445,52446,52447,52448,52449,52450,52451,52452,52453,52454,52455,52456,52457,52458,52459,52460,52461,52462,52463,52464,52465,52466,52467,52468,52469,52470,52471,52472,52473,52474,52475,52476,52477,52478,52479,52480,52481,52482,52483,52484,52485,52486,52487,52488,52489,52490,52491,52492,52493,52494,52495,52496,52497,52498,52499,52500,52501,52502,52503,52504,52505,52506,52507,52508,52509,52510,52511,52512,52513,52514,52515,52516,52517,52518,52519,52520,52521,52522,52523,52524,52525,52526,52527,52528,52529,52530,52531,52532,52533,52534,52535,52536,52537,52538,52539,52540,52541,52542,52543,52544,52545,52546,52547,52548,52549,52550,52551,52552,52553,52554,52555,52556,52557,52558,52559,52560,52561,52562,52563,52564,52565,52566,52567,52568,52569,52570,52571,52572,52573,52574,52575,52576,52577,52578,52579,52580,52581,52582,52583,52584,52585,52586,52587,52588,52589,52590,52591,52592,52593,52594,52595,52596,52597,52598,52599,52600,52601,52602,52603,52604,52605,52606,52607,52608,52609,52610,52611,52612,52613,52614,52615,52616,52617,52618,52619,52620,52621,52622,52623,52624,52625,52626,52627,52628,52629,52630,52631,52632,52633,52634,52635,52636,52637,52638,52639,52640,52641,52642,52643,52644,52645,52646,52647,52648,52649,52650,52651,52652,52653,52654,52655,52656,52657,52658,52659,52660,52661,52662,52663,52664,52665,52666,52667,52668,52669,52670,52671,52672,52673,52674,52675,52676,52677,52678,52679,52680,52681,52682,52683,52684,52685,52686,52687,52688,52689,52690,52691,52692,52693,52694,52695,52696,52697,52698,52699,52700,52701,52702,52703,52704,52705,52706,52707,52708,52709,52710,52711,52712,52713,52714,52715,52716,52717,52718,52719,52720,52721,52722,52723,52724,52725,52726,52727,52728,52729,52730,52731,52732,52733,52734,52735,52736,52737,52738,52739,52740,52741,52742,52743,52744,52745,52746,52747,52748,52749,52750,52751,52752,52753,52754,52755,52756,52757,52758,52759,52760,52761,52762,52763,52764,52765,52766,52767,52768,52769,52770,52771,52772,52773,52774,52775,52776,52777,52778,52779,52780,52781,52782,52783,52784,52785,52786,52787,52788,52789,52790,52791,52792,52793,52794,52795,52796,52797,52798,52799,52800,52801,52802,52803,52804,52805,52806,52807,52808,52809,52810,52811,52812,52813,52814,52815,52816,52817,52818,52819,52820,52821,52822,52823,52824,52825,52826,52827,52828,52829,52830,52831,52832,52833,52834,52835,52836,52837,52838,52839,52840,52841,52842,52843,52844,52845,52846,52847,52848,52849,52850,52851,52852,52853,52854,52855,52856,52857,52858,52859,52860,52861,52862,52863,52864,52865,52866,52867,52868,52869,52870,52871,52872,52873,52874,52875,52876,52877,52878,52879,52880,52881,52882,52883,52884,52885,52886,52887,52888,52889,52890,52891,52892,52893,52894,52895,52896,52897,52898,52899,52900,52901,52902,52903,52904,52905,52906,52907,52908,52909,52910,52911,52912,52913,52914,52915,52916,52917,52918,52919,52920,52921,52922,52923,52924,52925,52926,52927,52928,52929,52930,52931,52932,52933,52934,52935,52936,52937,52938,52939,52940,52941,52942,52943,52944,52945,52946,52947,52948,52949,52950,52951,52952,52953,52954,52955,52956,52957,52958,52959,52960,52961,52962,52963,52964,52965,52966,52967,52968,52969,52970,52971,52972,52973,52974,52975,52976,52977,52978,52979,52980,52981,52982,52983,52984,52985,52986,52987,52988,52989,52990,52991,52992,52993,52994,52995,52996,52997,52998,52999,53000,53001,53002,53003,53004,53005,53006,53007,53008,53009,53010,53011,53012,53013,53014,53015,53016,53017,53018,53019,53020,53021,53022,53023,53024,53025,53026,53027,53028,53029,53030,53031,53032,53033,53034,53035,53036,53037,53038,53039,53040,53041,53042,53043,53044,53045,53046,53047,53048,53049,53050,53051,53052,53053,53054,53055,53056,53057,53058,53059,53060,53061,53062,53063,53064,53065,53066,53067,53068,53069,53070,53071,53072,53073,53074,53075,53076,53077,53078,53079,53080,53081,53082,53083,53084,53085,53086,53087,53088,53089,53090,53091,53092,53093,53094,53095,53096,53097,53098,53099,53100,53101,53102,53103,53104,53105,53106,53107,53108,53109,53110,53111,53112,53113,53114,53115,53116,53117,53118,53119,53120,53121,53122,53123,53124,53125,53126,53127,53128,53129,53130,53131,53132,53133,53134,53135,53136,53137,53138,53139,53140,53141,53142,53143,53144,53145,53146,53147,53148,53149,53150,53151,53152,53153,53154,53155,53156,53157,53158,53159,53160,53161,53162,53163,53164,53165,53166,53167,53168,53169,53170,53171,53172,53173,53174,53175,53176,53177,53178,53179,53180,53181,53182,53183,53184,53185,53186,53187,53188,53189,53190,53191,53192,53193,53194,53195,53196,53197,53198,53199,53200,53201,53202,53203,53204,53205,53206,53207,53208,53209,53210,53211,53212,53213,53214,53215,53216,53217,53218,53219,53220,53221,53222,53223,53224,53225,53226,53227,53228,53229,53230,53231,53232,53233,53234,53235,53236,53237,53238,53239,53240,53241,53242,53243,53244,53245,53246,53247,53248,53249,53250,53251,53252,53253,53254,53255,53256,53257,53258,53259,53260,53261,53262,53263,53264,53265,53266,53267,53268,53269,53270,53271,53272,53273,53274,53275,53276,53277,53278,53279,53280,53281,53282,53283,53284,53285,53286,53287,53288,53289,53290,53291,53292,53293,53294,53295,53296,53297,53298,53299,53300,53301,53302,53303,53304,53305,53306,53307,53308,53309,53310,53311,53312,53313,53314,53315,53316,53317,53318,53319,53320,53321,53322,53323,53324,53325,53326,53327,53328,53329,53330,53331,53332,53333,53334,53335,53336,53337,53338,53339,53340,53341,53342,53343,53344,53345,53346,53347,53348,53349,53350,53351,53352,53353,53354,53355,53356,53357,53358,53359,53360,53361,53362,53363,53364,53365,53366,53367,53368,53369,53370,53371,53372,53373,53374,53375,53376,53377,53378,53379,53380,53381,53382,53383,53384,53385,53386,53387,53388,53389,53390,53391,53392,53393,53394,53395,53396,53397,53398,53399,53400,53401,53402,53403,53404,53405,53406,53407,53408,53409,53410,53411,53412,53413,53414,53415,53416,53417,53418,53419,53420,53421,53422,53423,53424,53425,53426,53427,53428,53429,53430,53431,53432,53433,53434,53435,53436,53437,53438,53439,53440,53441,53442,53443,53444,53445,53446,53447,53448,53449,53450,53451,53452,53453,53454,53455,53456,53457,53458,53459,53460,53461,53462,53463,53464,53465,53466,53467,53468,53469,53470,53471,53472,53473,53474,53475,53476,53477,53478,53479,53480,53481,53482,53483,53484,53485,53486,53487,53488,53489,53490,53491,53492,53493,53494,53495,53496,53497,53498,53499,53500,53501,53502,53503,53504,53505,53506,53507,53508,53509,53510,53511,53512,53513,53514,53515,53516,53517,53518,53519,53520,53521,53522,53523,53524,53525,53526,53527,53528,53529,53530,53531,53532,53533,53534,53535,53536,53537,53538,53539,53540,53541,53542,53543,53544,53545,53546,53547,53548,53549,53550,53551,53552,53553,53554,53555,53556,53557,53558,53559,53560,53561,53562,53563,53564,53565,53566,53567,53568,53569,53570,53571,53572,53573,53574,53575,53576,53577,53578,53579,53580,53581,53582,53583,53584,53585,53586,53587,53588,53589,53590,53591,53592,53593,53594,53595,53596,53597,53598,53599,53600,53601,53602,53603,53604,53605,53606,53607,53608,53609,53610,53611,53612,53613,53614,53615,53616,53617,53618,53619,53620,53621,53622,53623,53624,53625,53626,53627,53628,53629,53630,53631,53632,53633,53634,53635,53636,53637,53638,53639,53640,53641,53642,53643,53644,53645,53646,53647,53648,53649,53650,53651,53652,53653,53654,53655,53656,53657,53658,53659,53660,53661,53662,53663,53664,53665,53666,53667,53668,53669,53670,53671,53672,53673,53674,53675,53676,53677,53678,53679,53680,53681,53682,53683,53684,53685,53686,53687,53688,53689,53690,53691,53692,53693,53694,53695,53696,53697,53698,53699,53700,53701,53702,53703,53704,53705,53706,53707,53708,53709,53710,53711,53712,53713,53714,53715,53716,53717,53718,53719,53720,53721,53722,53723,53724,53725,53726,53727,53728,53729,53730,53731,53732,53733,53734,53735,53736,53737,53738,53739,53740,53741,53742,53743,53744,53745,53746,53747,53748,53749,53750,53751,53752,53753,53754,53755,53756,53757,53758,53759,53760,53761,53762,53763,53764,53765,53766,53767,53768,53769,53770,53771,53772,53773,53774,53775,53776,53777,53778,53779,53780,53781,53782,53783,53784,53785,53786,53787,53788,53789,53790,53791,53792,53793,53794,53795,53796,53797,53798,53799,53800,53801,53802,53803,53804,53805,53806,53807,53808,53809,53810,53811,53812,53813,53814,53815,53816,53817,53818,53819,53820,53821,53822,53823,53824,53825,53826,53827,53828,53829,53830,53831,53832,53833,53834,53835,53836,53837,53838,53839,53840,53841,53842,53843,53844,53845,53846,53847,53848,53849,53850,53851,53852,53853,53854,53855,53856,53857,53858,53859,53860,53861,53862,53863,53864,53865,53866,53867,53868,53869,53870,53871,53872,53873,53874,53875,53876,53877,53878,53879,53880,53881,53882,53883,53884,53885,53886,53887,53888,53889,53890,53891,53892,53893,53894,53895,53896,53897,53898,53899,53900,53901,53902,53903,53904,53905,53906,53907,53908,53909,53910,53911,53912,53913,53914,53915,53916,53917,53918,53919,53920,53921,53922,53923,53924,53925,53926,53927,53928,53929,53930,53931,53932,53933,53934,53935,53936,53937,53938,53939,53940,53941,53942,53943,53944,53945,53946,53947,53948,53949,53950,53951,53952,53953,53954,53955,53956,53957,53958,53959,53960,53961,53962,53963,53964,53965,53966,53967,53968,53969,53970,53971,53972,53973,53974,53975,53976,53977,53978,53979,53980,53981,53982,53983,53984,53985,53986,53987,53988,53989,53990,53991,53992,53993,53994,53995,53996,53997,53998,53999,54000,54001,54002,54003,54004,54005,54006,54007,54008,54009,54010,54011,54012,54013,54014,54015,54016,54017,54018,54019,54020,54021,54022,54023,54024,54025,54026,54027,54028,54029,54030,54031,54032,54033,54034,54035,54036,54037,54038,54039,54040,54041,54042,54043,54044,54045,54046,54047,54048,54049,54050,54051,54052,54053,54054,54055,54056,54057,54058,54059,54060,54061,54062,54063,54064,54065,54066,54067,54068,54069,54070,54071,54072,54073,54074,54075,54076,54077,54078,54079,54080,54081,54082,54083,54084,54085,54086,54087,54088,54089,54090,54091,54092,54093,54094,54095,54096,54097,54098,54099,54100,54101,54102,54103,54104,54105,54106,54107,54108,54109,54110,54111,54112,54113,54114,54115,54116,54117,54118,54119,54120,54121,54122,54123,54124,54125,54126,54127,54128,54129,54130,54131,54132,54133,54134,54135,54136,54137,54138,54139,54140,54141,54142,54143,54144,54145,54146,54147,54148,54149,54150,54151,54152,54153,54154,54155,54156,54157,54158,54159,54160,54161,54162,54163,54164,54165,54166,54167,54168,54169,54170,54171,54172,54173,54174,54175,54176,54177,54178,54179,54180,54181,54182,54183,54184,54185,54186,54187,54188,54189,54190,54191,54192,54193,54194,54195,54196,54197,54198,54199,54200,54201,54202,54203,54204,54205,54206,54207,54208,54209,54210,54211,54212,54213,54214,54215,54216,54217,54218,54219,54220,54221,54222,54223,54224,54225,54226,54227,54228,54229,54230,54231,54232,54233,54234,54235,54236,54237,54238,54239,54240,54241,54242,54243,54244,54245,54246,54247,54248,54249,54250,54251,54252,54253,54254,54255,54256,54257,54258,54259,54260,54261,54262,54263,54264,54265,54266,54267,54268,54269,54270,54271,54272,54273,54274,54275,54276,54277,54278,54279,54280,54281,54282,54283,54284,54285,54286,54287,54288,54289,54290,54291,54292,54293,54294,54295,54296,54297,54298,54299,54300,54301,54302,54303,54304,54305,54306,54307,54308,54309,54310,54311,54312,54313,54314,54315,54316,54317,54318,54319,54320,54321,54322,54323,54324,54325,54326,54327,54328,54329,54330,54331,54332,54333,54334,54335,54336,54337,54338,54339,54340,54341,54342,54343,54344,54345,54346,54347,54348,54349,54350,54351,54352,54353,54354,54355,54356,54357,54358,54359,54360,54361,54362,54363,54364,54365,54366,54367,54368,54369,54370,54371,54372,54373,54374,54375,54376,54377,54378,54379,54380,54381,54382,54383,54384,54385,54386,54387,54388,54389,54390,54391,54392,54393,54394,54395,54396,54397,54398,54399,54400,54401,54402,54403,54404,54405,54406,54407,54408,54409,54410,54411,54412,54413,54414,54415,54416,54417,54418,54419,54420,54421,54422,54423,54424,54425,54426,54427,54428,54429,54430,54431,54432,54433,54434,54435,54436,54437,54438,54439,54440,54441,54442,54443,54444,54445,54446,54447,54448,54449,54450,54451,54452,54453,54454,54455,54456,54457,54458,54459,54460,54461,54462,54463,54464,54465,54466,54467,54468,54469,54470,54471,54472,54473,54474,54475,54476,54477,54478,54479,54480,54481,54482,54483,54484,54485,54486,54487,54488,54489,54490,54491,54492,54493,54494,54495,54496,54497,54498,54499,54500,54501,54502,54503,54504,54505,54506,54507,54508,54509,54510,54511,54512,54513,54514,54515,54516,54517,54518,54519,54520,54521,54522,54523,54524,54525,54526,54527,54528,54529,54530,54531,54532,54533,54534,54535,54536,54537,54538,54539,54540,54541,54542,54543,54544,54545,54546,54547,54548,54549,54550,54551,54552,54553,54554,54555,54556,54557,54558,54559,54560,54561,54562,54563,54564,54565,54566,54567,54568,54569,54570,54571,54572,54573,54574,54575,54576,54577,54578,54579,54580,54581,54582,54583,54584,54585,54586,54587,54588,54589,54590,54591,54592,54593,54594,54595,54596,54597,54598,54599,54600,54601,54602,54603,54604,54605,54606,54607,54608,54609,54610,54611,54612,54613,54614,54615,54616,54617,54618,54619,54620,54621,54622,54623,54624,54625,54626,54627,54628,54629,54630,54631,54632,54633,54634,54635,54636,54637,54638,54639,54640,54641,54642,54643,54644,54645,54646,54647,54648,54649,54650,54651,54652,54653,54654,54655,54656,54657,54658,54659,54660,54661,54662,54663,54664,54665,54666,54667,54668,54669,54670,54671,54672,54673,54674,54675,54676,54677,54678,54679,54680,54681,54682,54683,54684,54685,54686,54687,54688,54689,54690,54691,54692,54693,54694,54695,54696,54697,54698,54699,54700,54701,54702,54703,54704,54705,54706,54707,54708,54709,54710,54711,54712,54713,54714,54715,54716,54717,54718,54719,54720,54721,54722,54723,54724,54725,54726,54727,54728,54729,54730,54731,54732,54733,54734,54735,54736,54737,54738,54739,54740,54741,54742,54743,54744,54745,54746,54747,54748,54749,54750,54751,54752,54753,54754,54755,54756,54757,54758,54759,54760,54761,54762,54763,54764,54765,54766,54767,54768,54769,54770,54771,54772,54773,54774,54775,54776,54777,54778,54779,54780,54781,54782,54783,54784,54785,54786,54787,54788,54789,54790,54791,54792,54793,54794,54795,54796,54797,54798,54799,54800,54801,54802,54803,54804,54805,54806,54807,54808,54809,54810,54811,54812,54813,54814,54815,54816,54817,54818,54819,54820,54821,54822,54823,54824,54825,54826,54827,54828,54829,54830,54831,54832,54833,54834,54835,54836,54837,54838,54839,54840,54841,54842,54843,54844,54845,54846,54847,54848,54849,54850,54851,54852,54853,54854,54855,54856,54857,54858,54859,54860,54861,54862,54863,54864,54865,54866,54867,54868,54869,54870,54871,54872,54873,54874,54875,54876,54877,54878,54879,54880,54881,54882,54883,54884,54885,54886,54887,54888,54889,54890,54891,54892,54893,54894,54895,54896,54897,54898,54899,54900,54901,54902,54903,54904,54905,54906,54907,54908,54909,54910,54911,54912,54913,54914,54915,54916,54917,54918,54919,54920,54921,54922,54923,54924,54925,54926,54927,54928,54929,54930,54931,54932,54933,54934,54935,54936,54937,54938,54939,54940,54941,54942,54943,54944,54945,54946,54947,54948,54949,54950,54951,54952,54953,54954,54955,54956,54957,54958,54959,54960,54961,54962,54963,54964,54965,54966,54967,54968,54969,54970,54971,54972,54973,54974,54975,54976,54977,54978,54979,54980,54981,54982,54983,54984,54985,54986,54987,54988,54989,54990,54991,54992,54993,54994,54995,54996,54997,54998,54999,55000,55001,55002,55003,55004,55005,55006,55007,55008,55009,55010,55011,55012,55013,55014,55015,55016,55017,55018,55019,55020,55021,55022,55023,55024,55025,55026,55027,55028,55029,55030,55031,55032,55033,55034,55035,55036,55037,55038,55039,55040,55041,55042,55043,55044,55045,55046,55047,55048,55049,55050,55051,55052,55053,55054,55055,55056,55057,55058,55059,55060,55061,55062,55063,55064,55065,55066,55067,55068,55069,55070,55071,55072,55073,55074,55075,55076,55077,55078,55079,55080,55081,55082,55083,55084,55085,55086,55087,55088,55089,55090,55091,55092,55093,55094,55095,55096,55097,55098,55099,55100,55101,55102,55103,55104,55105,55106,55107,55108,55109,55110,55111,55112,55113,55114,55115,55116,55117,55118,55119,55120,55121,55122,55123,55124,55125,55126,55127,55128,55129,55130,55131,55132,55133,55134,55135,55136,55137,55138,55139,55140,55141,55142,55143,55144,55145,55146,55147,55148,55149,55150,55151,55152,55153,55154,55155,55156,55157,55158,55159,55160,55161,55162,55163,55164,55165,55166,55167,55168,55169,55170,55171,55172,55173,55174,55175,55176,55177,55178,55179,55180,55181,55182,55183,55184,55185,55186,55187,55188,55189,55190,55191,55192,55193,55194,55195,55196,55197,55198,55199,55200,55201,55202,55203,55216,55217,55218,55219,55220,55221,55222,55223,55224,55225,55226,55227,55228,55229,55230,55231,55232,55233,55234,55235,55236,55237,55238,55243,55244,55245,55246,55247,55248,55249,55250,55251,55252,55253,55254,55255,55256,55257,55258,55259,55260,55261,55262,55263,55264,55265,55266,55267,55268,55269,55270,55271,55272,55273,55274,55275,55276,55277,55278,55279,55280,55281,55282,55283,55284,55285,55286,55287,55288,55289,55290,55291,63744,63745,63746,63747,63748,63749,63750,63751,63752,63753,63754,63755,63756,63757,63758,63759,63760,63761,63762,63763,63764,63765,63766,63767,63768,63769,63770,63771,63772,63773,63774,63775,63776,63777,63778,63779,63780,63781,63782,63783,63784,63785,63786,63787,63788,63789,63790,63791,63792,63793,63794,63795,63796,63797,63798,63799,63800,63801,63802,63803,63804,63805,63806,63807,63808,63809,63810,63811,63812,63813,63814,63815,63816,63817,63818,63819,63820,63821,63822,63823,63824,63825,63826,63827,63828,63829,63830,63831,63832,63833,63834,63835,63836,63837,63838,63839,63840,63841,63842,63843,63844,63845,63846,63847,63848,63849,63850,63851,63852,63853,63854,63855,63856,63857,63858,63859,63860,63861,63862,63863,63864,63865,63866,63867,63868,63869,63870,63871,63872,63873,63874,63875,63876,63877,63878,63879,63880,63881,63882,63883,63884,63885,63886,63887,63888,63889,63890,63891,63892,63893,63894,63895,63896,63897,63898,63899,63900,63901,63902,63903,63904,63905,63906,63907,63908,63909,63910,63911,63912,63913,63914,63915,63916,63917,63918,63919,63920,63921,63922,63923,63924,63925,63926,63927,63928,63929,63930,63931,63932,63933,63934,63935,63936,63937,63938,63939,63940,63941,63942,63943,63944,63945,63946,63947,63948,63949,63950,63951,63952,63953,63954,63955,63956,63957,63958,63959,63960,63961,63962,63963,63964,63965,63966,63967,63968,63969,63970,63971,63972,63973,63974,63975,63976,63977,63978,63979,63980,63981,63982,63983,63984,63985,63986,63987,63988,63989,63990,63991,63992,63993,63994,63995,63996,63997,63998,63999,64000,64001,64002,64003,64004,64005,64006,64007,64008,64009,64010,64011,64012,64013,64014,64015,64016,64017,64018,64019,64020,64021,64022,64023,64024,64025,64026,64027,64028,64029,64030,64031,64032,64033,64034,64035,64036,64037,64038,64039,64040,64041,64042,64043,64044,64045,64046,64047,64048,64049,64050,64051,64052,64053,64054,64055,64056,64057,64058,64059,64060,64061,64062,64063,64064,64065,64066,64067,64068,64069,64070,64071,64072,64073,64074,64075,64076,64077,64078,64079,64080,64081,64082,64083,64084,64085,64086,64087,64088,64089,64090,64091,64092,64093,64094,64095,64096,64097,64098,64099,64100,64101,64102,64103,64104,64105,64106,64107,64108,64109,64112,64113,64114,64115,64116,64117,64118,64119,64120,64121,64122,64123,64124,64125,64126,64127,64128,64129,64130,64131,64132,64133,64134,64135,64136,64137,64138,64139,64140,64141,64142,64143,64144,64145,64146,64147,64148,64149,64150,64151,64152,64153,64154,64155,64156,64157,64158,64159,64160,64161,64162,64163,64164,64165,64166,64167,64168,64169,64170,64171,64172,64173,64174,64175,64176,64177,64178,64179,64180,64181,64182,64183,64184,64185,64186,64187,64188,64189,64190,64191,64192,64193,64194,64195,64196,64197,64198,64199,64200,64201,64202,64203,64204,64205,64206,64207,64208,64209,64210,64211,64212,64213,64214,64215,64216,64217,64256,64257,64258,64259,64260,64261,64262,64275,64276,64277,64278,64279,64285,64287,64288,64289,64290,64291,64292,64293,64294,64295,64296,64298,64299,64300,64301,64302,64303,64304,64305,64306,64307,64308,64309,64310,64312,64313,64314,64315,64316,64318,64320,64321,64323,64324,64326,64327,64328,64329,64330,64331,64332,64333,64334,64335,64336,64337,64338,64339,64340,64341,64342,64343,64344,64345,64346,64347,64348,64349,64350,64351,64352,64353,64354,64355,64356,64357,64358,64359,64360,64361,64362,64363,64364,64365,64366,64367,64368,64369,64370,64371,64372,64373,64374,64375,64376,64377,64378,64379,64380,64381,64382,64383,64384,64385,64386,64387,64388,64389,64390,64391,64392,64393,64394,64395,64396,64397,64398,64399,64400,64401,64402,64403,64404,64405,64406,64407,64408,64409,64410,64411,64412,64413,64414,64415,64416,64417,64418,64419,64420,64421,64422,64423,64424,64425,64426,64427,64428,64429,64430,64431,64432,64433,64467,64468,64469,64470,64471,64472,64473,64474,64475,64476,64477,64478,64479,64480,64481,64482,64483,64484,64485,64486,64487,64488,64489,64490,64491,64492,64493,64494,64495,64496,64497,64498,64499,64500,64501,64502,64503,64504,64505,64506,64507,64508,64509,64510,64511,64512,64513,64514,64515,64516,64517,64518,64519,64520,64521,64522,64523,64524,64525,64526,64527,64528,64529,64530,64531,64532,64533,64534,64535,64536,64537,64538,64539,64540,64541,64542,64543,64544,64545,64546,64547,64548,64549,64550,64551,64552,64553,64554,64555,64556,64557,64558,64559,64560,64561,64562,64563,64564,64565,64566,64567,64568,64569,64570,64571,64572,64573,64574,64575,64576,64577,64578,64579,64580,64581,64582,64583,64584,64585,64586,64587,64588,64589,64590,64591,64592,64593,64594,64595,64596,64597,64598,64599,64600,64601,64602,64603,64604,64605,64606,64607,64608,64609,64610,64611,64612,64613,64614,64615,64616,64617,64618,64619,64620,64621,64622,64623,64624,64625,64626,64627,64628,64629,64630,64631,64632,64633,64634,64635,64636,64637,64638,64639,64640,64641,64642,64643,64644,64645,64646,64647,64648,64649,64650,64651,64652,64653,64654,64655,64656,64657,64658,64659,64660,64661,64662,64663,64664,64665,64666,64667,64668,64669,64670,64671,64672,64673,64674,64675,64676,64677,64678,64679,64680,64681,64682,64683,64684,64685,64686,64687,64688,64689,64690,64691,64692,64693,64694,64695,64696,64697,64698,64699,64700,64701,64702,64703,64704,64705,64706,64707,64708,64709,64710,64711,64712,64713,64714,64715,64716,64717,64718,64719,64720,64721,64722,64723,64724,64725,64726,64727,64728,64729,64730,64731,64732,64733,64734,64735,64736,64737,64738,64739,64740,64741,64742,64743,64744,64745,64746,64747,64748,64749,64750,64751,64752,64753,64754,64755,64756,64757,64758,64759,64760,64761,64762,64763,64764,64765,64766,64767,64768,64769,64770,64771,64772,64773,64774,64775,64776,64777,64778,64779,64780,64781,64782,64783,64784,64785,64786,64787,64788,64789,64790,64791,64792,64793,64794,64795,64796,64797,64798,64799,64800,64801,64802,64803,64804,64805,64806,64807,64808,64809,64810,64811,64812,64813,64814,64815,64816,64817,64818,64819,64820,64821,64822,64823,64824,64825,64826,64827,64828,64829,64848,64849,64850,64851,64852,64853,64854,64855,64856,64857,64858,64859,64860,64861,64862,64863,64864,64865,64866,64867,64868,64869,64870,64871,64872,64873,64874,64875,64876,64877,64878,64879,64880,64881,64882,64883,64884,64885,64886,64887,64888,64889,64890,64891,64892,64893,64894,64895,64896,64897,64898,64899,64900,64901,64902,64903,64904,64905,64906,64907,64908,64909,64910,64911,64914,64915,64916,64917,64918,64919,64920,64921,64922,64923,64924,64925,64926,64927,64928,64929,64930,64931,64932,64933,64934,64935,64936,64937,64938,64939,64940,64941,64942,64943,64944,64945,64946,64947,64948,64949,64950,64951,64952,64953,64954,64955,64956,64957,64958,64959,64960,64961,64962,64963,64964,64965,64966,64967,65008,65009,65010,65011,65012,65013,65014,65015,65016,65017,65018,65019,65136,65137,65138,65139,65140,65142,65143,65144,65145,65146,65147,65148,65149,65150,65151,65152,65153,65154,65155,65156,65157,65158,65159,65160,65161,65162,65163,65164,65165,65166,65167,65168,65169,65170,65171,65172,65173,65174,65175,65176,65177,65178,65179,65180,65181,65182,65183,65184,65185,65186,65187,65188,65189,65190,65191,65192,65193,65194,65195,65196,65197,65198,65199,65200,65201,65202,65203,65204,65205,65206,65207,65208,65209,65210,65211,65212,65213,65214,65215,65216,65217,65218,65219,65220,65221,65222,65223,65224,65225,65226,65227,65228,65229,65230,65231,65232,65233,65234,65235,65236,65237,65238,65239,65240,65241,65242,65243,65244,65245,65246,65247,65248,65249,65250,65251,65252,65253,65254,65255,65256,65257,65258,65259,65260,65261,65262,65263,65264,65265,65266,65267,65268,65269,65270,65271,65272,65273,65274,65275,65276,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,65382,65383,65384,65385,65386,65387,65388,65389,65390,65391,65392,65393,65394,65395,65396,65397,65398,65399,65400,65401,65402,65403,65404,65405,65406,65407,65408,65409,65410,65411,65412,65413,65414,65415,65416,65417,65418,65419,65420,65421,65422,65423,65424,65425,65426,65427,65428,65429,65430,65431,65432,65433,65434,65435,65436,65437,65438,65439,65440,65441,65442,65443,65444,65445,65446,65447,65448,65449,65450,65451,65452,65453,65454,65455,65456,65457,65458,65459,65460,65461,65462,65463,65464,65465,65466,65467,65468,65469,65470,65474,65475,65476,65477,65478,65479,65482,65483,65484,65485,65486,65487,65490,65491,65492,65493,65494,65495,65498,65499,65500".split(",").map(function(_){return parseInt(_,10)});$.exports=t},{}],5:[function(_,$,e){var t=_("util/"),n=Array.prototype.slice,r=Object.prototype.hasOwnProperty,i=$.exports=s;function u(_,$){return t.isUndefined($)?""+$:t.isNumber($)&&!isFinite($)||t.isFunction($)||t.isRegExp($)?$.toString():$}function o(_,$){return t.isString(_)?_.length<$?_:_.slice(0,$):_}function a(_,$,e,t,n){throw new i.AssertionError({message:e,actual:_,expected:$,operator:t,stackStartFunction:n})}function s(_,$){_||a(_,!0,$,"==",i.ok)}function c(_,$){if(_===$)return!0;if(t.isBuffer(_)&&t.isBuffer($)){if(_.length!=$.length)return!1;for(var e=0;e<_.length;e++)if(_[e]!==$[e])return!1;return!0}if(t.isDate(_)&&t.isDate($))return _.getTime()===$.getTime();if(t.isRegExp(_)&&t.isRegExp($))return _.source===$.source&&_.global===$.global&&_.multiline===$.multiline&&_.lastIndex===$.lastIndex&&_.ignoreCase===$.ignoreCase;if(!t.isObject(_)&&!t.isObject($))return _==$;else return function _($,e){if(t.isNullOrUndefined($)||t.isNullOrUndefined(e)||$.prototype!==e.prototype)return!1;if(t.isPrimitive($)||t.isPrimitive(e))return $===e;var r=l($),i=l(e);if(r&&!i||!r&&i)return!1;if(r)return $=n.call($),e=n.call(e),c($,e);var u,o,a=p($),s=p(e);if(a.length!=s.length)return!1;for(a.sort(),s.sort(),o=a.length-1;o>=0;o--)if(a[o]!=s[o])return!1;for(o=a.length-1;o>=0;o--)if(!c($[u=a[o]],e[u]))return!1;return!0}(_,$)}function l(_){return"[object Arguments]"==Object.prototype.toString.call(_)}function f(_,$){return!!_&&!!$&&("[object RegExp]"==Object.prototype.toString.call($)?$.test(_):_ instanceof $||!0===$.call({},_))}function d(_,$,e,n){var r;t.isString(e)&&(n=e,e=null);try{$()}catch(i){r=i}if(n=(e&&e.name?" ("+e.name+").":".")+(n?" "+n:"."),_&&!r&&a(r,e,"Missing expected exception"+n),!_&&f(r,e)&&a(r,e,"Got unwanted exception"+n),_&&r&&e&&!f(r,e)||!_&&r)throw r}i.AssertionError=function _($){this.name="AssertionError",this.actual=$.actual,this.expected=$.expected,this.operator=$.operator,$.message?(this.message=$.message,this.generatedMessage=!1):(this.message=(e=this,o(JSON.stringify(e.actual,u),128)+" "+e.operator+" "+o(JSON.stringify(e.expected,u),128)),this.generatedMessage=!0);var e,t=$.stackStartFunction||a;if(Error.captureStackTrace)Error.captureStackTrace(this,t);else{var n=Error();if(n.stack){var r=n.stack,i=t.name,s=r.indexOf("\n"+i);if(s>=0){var c=r.indexOf("\n",s+1);r=r.substring(c+1)}this.stack=r}}},t.inherits(i.AssertionError,Error),i.fail=a,i.ok=s,i.equal=function _($,e,t){$!=e&&a($,e,t,"==",i.equal)},i.notEqual=function _($,e,t){$==e&&a($,e,t,"!=",i.notEqual)},i.deepEqual=function _($,e,t){c($,e)||a($,e,t,"deepEqual",i.deepEqual)},i.notDeepEqual=function _($,e,t){c($,e)&&a($,e,t,"notDeepEqual",i.notDeepEqual)},i.strictEqual=function _($,e,t){$!==e&&a($,e,t,"===",i.strictEqual)},i.notStrictEqual=function _($,e,t){$===e&&a($,e,t,"!==",i.notStrictEqual)},i.throws=function(_,$,e){d.apply(this,[!0].concat(n.call(arguments)))},i.doesNotThrow=function(_,$){d.apply(this,[!1].concat(n.call(arguments)))},i.ifError=function(_){if(_)throw _};var p=Object.keys||function(_){var $=[];for(var e in _)r.call(_,e)&&$.push(e);return $}},{"util/":8}],6:[function(_,$,e){"function"==typeof Object.create?$.exports=function _($,e){$.super_=e,$.prototype=Object.create(e.prototype,{constructor:{value:$,enumerable:!1,writable:!0,configurable:!0}})}:$.exports=function _($,e){$.super_=e;var t=function(){};t.prototype=e.prototype,$.prototype=new t,$.prototype.constructor=$}},{}],7:[function(_,$,e){$.exports=function _($){return $&&"object"==typeof $&&"function"==typeof $.copy&&"function"==typeof $.fill&&"function"==typeof $.readUInt8}},{}],8:[function(_,$,e){(function($,t){var n,r=/%[sdj%]/g;e.format=function(_){if(!v(_)){for(var $=[],e=0;e=n)return _;switch(_){case"%s":return String(t[e++]);case"%d":return Number(t[e++]);case"%j":try{return JSON.stringify(t[e++])}catch($){return"[Circular]"}default:return _}}),o=t[e];e=3&&(t.depth=arguments[2]),arguments.length>=4&&(t.colors=arguments[3]),d($)?t.showHidden=$:$&&e._extend(t,$),g(t.showHidden)&&(t.showHidden=!1),g(t.depth)&&(t.depth=2),g(t.colors)&&(t.colors=!1),g(t.customInspect)&&(t.customInspect=!0),t.colors&&(t.stylize=o),s(t,_,t.depth)}function o(_,$){var e=u.styles[$];return e?"\x1b["+u.colors[e][0]+"m"+_+"\x1b["+u.colors[e][1]+"m":_}function a(_,$){return _}function s(_,$,t){if(_.customInspect&&$&&b($.inspect)&&$.inspect!==e.inspect&&!($.constructor&&$.constructor.prototype===$)){var n,r,i,u,o,a=$.inspect(t,_);return v(a)||(a=s(_,a,t)),a}var y=function _($,e){if(g(e))return $.stylize("undefined","undefined");if(v(e)){var t="'"+JSON.stringify(e).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return $.stylize(t,"string")}return h(e)?$.stylize(""+e,"number"):d(e)?$.stylize(""+e,"boolean"):p(e)?$.stylize("null","null"):void 0}(_,$);if(y)return y;var E,A,S=Object.keys($),F=(E=S,A={},E.forEach(function(_,$){A[_]=!0}),A);if(_.showHidden&&(S=Object.getOwnPropertyNames($)),x($)&&(S.indexOf("message")>=0||S.indexOf("description")>=0))return c($);if(0===S.length){if(b($)){var w=$.name?": "+$.name:"";return _.stylize("[Function"+w+"]","special")}if(m($))return _.stylize(RegExp.prototype.toString.call($),"regexp");if(k($))return _.stylize(Date.prototype.toString.call($),"date");if(x($))return c($)}var W="",D=!1,B=["{","}"];if(f($)&&(D=!0,B=["[","]"]),b($)&&(W=" [Function"+($.name?": "+$.name:"")+"]"),m($)&&(W=" "+RegExp.prototype.toString.call($)),k($)&&(W=" "+Date.prototype.toUTCString.call($)),x($)&&(W=" "+c($)),0===S.length&&(!D||0==$.length))return B[0]+W+B[1];if(t<0)return m($)?_.stylize(RegExp.prototype.toString.call($),"regexp"):_.stylize("[Object]","special");return _.seen.push($),o=D?function _($,e,t,n,r){for(var i=[],u=0,o=e.length;u=0&&u++,_+$.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60?i[0]+(""===r?"":r+"\n ")+" "+n.join(",\n ")+" "+i[1]:i[0]+r+" "+n.join(", ")+" "+i[1]}function c(_){return"["+Error.prototype.toString.call(_)+"]"}function l(_,$,e,t,n,r){var i,u,o;if((o=Object.getOwnPropertyDescriptor($,n)||{value:$[n]}).get?u=o.set?_.stylize("[Getter/Setter]","special"):_.stylize("[Getter]","special"):o.set&&(u=_.stylize("[Setter]","special")),C(t,n)||(i="["+n+"]"),!u&&(0>_.seen.indexOf(o.value)?(u=p(e)?s(_,o.value,null):s(_,o.value,e-1)).indexOf("\n")>-1&&(u=r?u.split("\n").map(function(_){return" "+_}).join("\n").substr(2):"\n"+u.split("\n").map(function(_){return" "+_}).join("\n")):u=_.stylize("[Circular]","special")),g(i)){if(r&&n.match(/^\d+$/))return u;(i=JSON.stringify(""+n)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(i=i.substr(1,i.length-2),i=_.stylize(i,"name")):(i=i.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),i=_.stylize(i,"string"))}return i+": "+u}function f(_){return Array.isArray(_)}function d(_){return"boolean"==typeof _}function p(_){return null===_}function h(_){return"number"==typeof _}function v(_){return"string"==typeof _}function g(_){return void 0===_}function m(_){return y(_)&&"[object RegExp]"===E(_)}function y(_){return"object"==typeof _&&null!==_}function k(_){return y(_)&&"[object Date]"===E(_)}function x(_){return y(_)&&("[object Error]"===E(_)||_ instanceof Error)}function b(_){return"function"==typeof _}function E(_){return Object.prototype.toString.call(_)}function A(_){return _<10?"0"+_.toString(10):_.toString(10)}e.debuglog=function(_){if(g(n)&&(n=$.env.NODE_DEBUG||""),!i[_=_.toUpperCase()]){if(RegExp("\\b"+_+"\\b","i").test(n)){var t=$.pid;i[_]=function(){var $=e.format.apply(e,arguments);console.error("%s %d: %s",_,t,$)}}else i[_]=function(){}}return i[_]},e.inspect=u,u.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},u.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},e.isArray=f,e.isBoolean=d,e.isNull=p,e.isNullOrUndefined=function _($){return null==$},e.isNumber=h,e.isString=v,e.isSymbol=function _($){return"symbol"==typeof $},e.isUndefined=g,e.isRegExp=m,e.isObject=y,e.isDate=k,e.isError=x,e.isFunction=b,e.isPrimitive=function _($){return null===$||"boolean"==typeof $||"number"==typeof $||"string"==typeof $||"symbol"==typeof $||void 0===$},e.isBuffer=_("./support/isBuffer");var S=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function C(_,$){return Object.prototype.hasOwnProperty.call(_,$)}e.log=function(){var _,$;console.log("%s - %s",($=[A((_=new Date).getHours()),A(_.getMinutes()),A(_.getSeconds())].join(":"),[_.getDate(),S[_.getMonth()],$].join(" ")),e.format.apply(e,arguments))},e.inherits=_("inherits"),e._extend=function(_,$){if(!$||!y($))return _;for(var e=Object.keys($),t=e.length;t--;)_[e[t]]=$[e[t]];return _}}).call(this,_("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./support/isBuffer":7,_process:13,inherits:6}],9:[function(_,$,e){(function(e){var t,n=_("util"),r=_("assert"),i=_("date-now"),u=Array.prototype.slice,o={};t=void 0!==e&&e.console?e.console:"undefined"!=typeof window&&window.console?window.console:{};for(var a=[[function _(){},"log"],[function _(){t.log.apply(t,arguments)},"info"],[function _(){t.log.apply(t,arguments)},"warn"],[function _(){t.warn.apply(t,arguments)},"error"],[function _($){o[$]=i()},"time"],[function _($){var e=o[$];if(!e)throw Error("No such label: "+$);var n=i()-e;t.log($+": "+n+"ms")},"timeEnd"],[function _(){var $=Error();$.name="Trace",$.message=n.format.apply(null,arguments),t.error($.stack)},"trace"],[function _($){t.log(n.inspect($)+"\n")},"dir"],[function _($){if(!$){var e=u.call(arguments,1);r.ok(!1,n.format.apply(null,e))}},"assert"]],s=0;s0&&this._events[_].length>e&&(this._events[_].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[_].length),"function"==typeof console.trace&&console.trace()),this},t.prototype.on=t.prototype.addListener,t.prototype.once=function(_,$){if(!n($))throw TypeError("listener must be a function");var e=!1;function t(){this.removeListener(_,t),e||(e=!0,$.apply(this,arguments))}return t.listener=$,this.on(_,t),this},t.prototype.removeListener=function(_,$){var e,t,i,u;if(!n($))throw TypeError("listener must be a function");if(!this._events||!this._events[_])return this;if(i=(e=this._events[_]).length,t=-1,e===$||n(e.listener)&&e.listener===$)delete this._events[_],this._events.removeListener&&this.emit("removeListener",_,$);else if(r(e)){for(u=i;u-- >0;)if(e[u]===$||e[u].listener&&e[u].listener===$){t=u;break}if(t<0)return this;1===e.length?(e.length=0,delete this._events[_]):e.splice(t,1),this._events.removeListener&&this.emit("removeListener",_,$)}return this},t.prototype.removeAllListeners=function(_){var $,e;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[_]&&delete this._events[_],this;if(0===arguments.length){for($ in this._events)"removeListener"!==$&&this.removeAllListeners($);return this.removeAllListeners("removeListener"),this._events={},this}if(n(e=this._events[_]))this.removeListener(_,e);else for(;e.length;)this.removeListener(_,e[e.length-1]);return delete this._events[_],this},t.prototype.listeners=function(_){var $;return this._events&&this._events[_]?n(this._events[_])?[this._events[_]]:this._events[_].slice():[]},t.listenerCount=function(_,$){var e;return _._events&&_._events[$]?n(_._events[$])?1:_._events[$].length:0}},{}],12:[function(_,$,e){(function(_){(function(){var t,n="Expected a function",r="__lodash_hash_undefined__",i="__lodash_placeholder__",u=1/0,o=0/0,a=4294967295,s=a-1,c=a>>>1,l=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],f="[object Arguments]",d="[object Array]",p="[object Boolean]",h="[object Date]",v="[object Error]",g="[object Function]",m="[object GeneratorFunction]",y="[object Map]",k="[object Number]",x="[object Object]",b="[object Promise]",E="[object RegExp]",A="[object Set]",S="[object String]",C="[object Symbol]",F="[object WeakMap]",w="[object ArrayBuffer]",W="[object DataView]",D="[object Float32Array]",B="[object Float64Array]",L="[object Int8Array]",M="[object Int16Array]",T="[object Int32Array]",j="[object Uint8Array]",G="[object Uint8ClampedArray]",I="[object Uint16Array]",P="[object Uint32Array]",O=/\b__p \+= '';/g,V=/\b(__p \+=) '' \+/g,R=/(__e\(.*?\)|\b__t\)) \+\n'';/g,U=/&(?:amp|lt|gt|quot|#39);/g,z=/[&<>"']/g,H=RegExp(U.source),N=RegExp(z.source),q=/<%-([\s\S]+?)%>/g,K=/<%([\s\S]+?)%>/g,Z=/<%=([\s\S]+?)%>/g,J=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,X=/^\w*$/,Q=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Y=/[\\^$.*+?()[\]{}|]/g,_2=RegExp(Y.source),_1=/^\s+/,_0=/\s/,__=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,_3=/\{\n\/\* \[wrapped with (.+)\] \*/,_$=/,? & /,_4=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,_5=/[()=,{}\[\]\/\s]/,_6=/\\(\\)?/g,_7=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,_e=/\w*$/,_t=/^[-+]0x[0-9a-f]+$/i,_n=/^0b[01]+$/i,_r=/^\[object .+?Constructor\]$/,_i=/^0o[0-7]+$/i,_u=/^(?:0|[1-9]\d*)$/,_o=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,_a=/($^)/,_s=/['\n\r\u2028\u2029\\]/g,_c="\ud800-\udfff",_l="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",_f="\\u2700-\\u27bf",_d="a-z\\xdf-\\xf6\\xf8-\\xff",_p="A-Z\\xc0-\\xd6\\xd8-\\xde",_h="\\ufe0e\\ufe0f",_v="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",_g="['’]",_m="["+_v+"]",_y="["+_l+"]",_k="["+_d+"]",_x="[^"+_c+_v+"\\d+"+_f+_d+_p+"]",_b="\ud83c[\udffb-\udfff]",_E="[^"+_c+"]",_8="(?:\ud83c[\udde6-\uddff]){2}",_A="[\ud800-\udbff][\udc00-\udfff]",_S="["+_p+"]",_C="\\u200d",_F="(?:"+_k+"|"+_x+")",_w="(?:"+_g+"(?:d|ll|m|re|s|t|ve))?",_W="(?:"+_g+"(?:D|LL|M|RE|S|T|VE))?",_D="(?:"+_y+"|"+_b+")?",_B="["+_h+"]?",_L="(?:"+_C+"(?:"+[_E,_8,_A].join("|")+")"+_B+_D+")*",_M=_B+_D+_L,_T="(?:"+["["+_f+"]",_8,_A].join("|")+")"+_M,_j="(?:"+[_E+_y+"?",_y,_8,_A,"["+_c+"]"].join("|")+")",_G=RegExp(_g,"g"),_I=RegExp(_y,"g"),_P=RegExp(_b+"(?="+_b+")|"+_j+_M,"g"),_O=RegExp([_S+"?"+_k+"+"+_w+"(?="+[_m,_S,"$"].join("|")+")","(?:"+_S+"|"+_x+")+"+_W+"(?="+[_m,_S+_F,"$"].join("|")+")",_S+"?"+_F+"+"+_w,_S+"+"+_W,"\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])","\\d+",_T].join("|"),"g"),_V=RegExp("["+_C+_c+_l+_h+"]"),_R=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,_U=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],_z=-1,_H={};_H[D]=_H[B]=_H[L]=_H[M]=_H[T]=_H[j]=_H[G]=_H[I]=_H[P]=!0,_H[f]=_H[d]=_H[w]=_H[p]=_H[W]=_H[h]=_H[v]=_H[g]=_H[y]=_H[k]=_H[x]=_H[E]=_H[A]=_H[S]=_H[F]=!1;var _N={};_N[f]=_N[d]=_N[w]=_N[W]=_N[p]=_N[h]=_N[D]=_N[B]=_N[L]=_N[M]=_N[T]=_N[y]=_N[k]=_N[x]=_N[E]=_N[A]=_N[S]=_N[C]=_N[j]=_N[G]=_N[I]=_N[P]=!0,_N[v]=_N[g]=_N[F]=!1;var _q={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},_9=parseFloat,_K=parseInt,_Z="object"==typeof _&&_&&_.Object===Object&&_,_J="object"==typeof self&&self&&self.Object===Object&&self,_X=_Z||_J||Function("return this")(),_Q="object"==typeof e&&e&&!e.nodeType&&e,_Y=_Q&&"object"==typeof $&&$&&!$.nodeType&&$,$2=_Y&&_Y.exports===_Q,$1=$2&&_Z.process,$0=function(){try{var _=_Y&&_Y.require&&_Y.require("util").types;if(_)return _;return $1&&$1.binding&&$1.binding("util")}catch($){}}(),$_=$0&&$0.isArrayBuffer,$3=$0&&$0.isDate,$$=$0&&$0.isMap,$4=$0&&$0.isRegExp,$5=$0&&$0.isSet,$6=$0&&$0.isTypedArray;function $7(_,$,e){switch(e.length){case 0:return _.call($);case 1:return _.call($,e[0]);case 2:return _.call($,e[0],e[1]);case 3:return _.call($,e[0],e[1],e[2])}return _.apply($,e)}function $e(_,$,e,t){for(var n=-1,r=null==_?0:_.length;++n-1}function $o(_,$,e){for(var t=-1,n=null==_?0:_.length;++t-1;);return e}function $W(_,$){for(var e=_.length;e--&&$v($,_[e],0)>-1;);return e}var $D=$x({À:"A",Á:"A",Â:"A",Ã:"A",Ä:"A",Å:"A",à:"a",á:"a",â:"a",ã:"a",ä:"a",å:"a",Ç:"C",ç:"c",Ð:"D",ð:"d",È:"E",É:"E",Ê:"E",Ë:"E",è:"e",é:"e",ê:"e",ë:"e",Ì:"I",Í:"I",Î:"I",Ï:"I",ì:"i",í:"i",î:"i",ï:"i",Ñ:"N",ñ:"n",Ò:"O",Ó:"O",Ô:"O",Õ:"O",Ö:"O",Ø:"O",ò:"o",ó:"o",ô:"o",õ:"o",ö:"o",ø:"o",Ù:"U",Ú:"U",Û:"U",Ü:"U",ù:"u",ú:"u",û:"u",ü:"u",Ý:"Y",ý:"y",ÿ:"y",Æ:"Ae",æ:"ae",Þ:"Th",þ:"th",ß:"ss",Ā:"A",Ă:"A",Ą:"A",ā:"a",ă:"a",ą:"a",Ć:"C",Ĉ:"C",Ċ:"C",Č:"C",ć:"c",ĉ:"c",ċ:"c",č:"c",Ď:"D",Đ:"D",ď:"d",đ:"d",Ē:"E",Ĕ:"E",Ė:"E",Ę:"E",Ě:"E",ē:"e",ĕ:"e",ė:"e",ę:"e",ě:"e",Ĝ:"G",Ğ:"G",Ġ:"G",Ģ:"G",ĝ:"g",ğ:"g",ġ:"g",ģ:"g",Ĥ:"H",Ħ:"H",ĥ:"h",ħ:"h",Ĩ:"I",Ī:"I",Ĭ:"I",Į:"I",İ:"I",ĩ:"i",ī:"i",ĭ:"i",į:"i",ı:"i",Ĵ:"J",ĵ:"j",Ķ:"K",ķ:"k",ĸ:"k",Ĺ:"L",Ļ:"L",Ľ:"L",Ŀ:"L",Ł:"L",ĺ:"l",ļ:"l",ľ:"l",ŀ:"l",ł:"l",Ń:"N",Ņ:"N",Ň:"N",Ŋ:"N",ń:"n",ņ:"n",ň:"n",ŋ:"n",Ō:"O",Ŏ:"O",Ő:"O",ō:"o",ŏ:"o",ő:"o",Ŕ:"R",Ŗ:"R",Ř:"R",ŕ:"r",ŗ:"r",ř:"r",Ś:"S",Ŝ:"S",Ş:"S",Š:"S",ś:"s",ŝ:"s",ş:"s",š:"s",Ţ:"T",Ť:"T",Ŧ:"T",ţ:"t",ť:"t",ŧ:"t",Ũ:"U",Ū:"U",Ŭ:"U",Ů:"U",Ű:"U",Ų:"U",ũ:"u",ū:"u",ŭ:"u",ů:"u",ű:"u",ų:"u",Ŵ:"W",ŵ:"w",Ŷ:"Y",ŷ:"y",Ÿ:"Y",Ź:"Z",Ż:"Z",Ž:"Z",ź:"z",ż:"z",ž:"z",IJ:"IJ",ij:"ij",Œ:"Oe",œ:"oe",ʼn:"'n",ſ:"s"}),$B=$x({"&":"&","<":"<",">":">",'"':""","'":"'"});function $L(_){return"\\"+_q[_]}function $M(_){return _V.test(_)}function $T(_){var $=-1,e=Array(_.size);return _.forEach(function(_,t){e[++$]=[t,_]}),e}function $j(_,$){return function(e){return _($(e))}}function $G(_,$){for(var e=-1,t=_.length,n=0,r=[];++e",""":'"',"'":"'"}),$U=function _($){var e,_0=($=null==$?_X:$U.defaults(_X.Object(),$,$U.pick(_X,_U))).Array,_c=$.Date,_l=$.Error,_f=$.Function,_d=$.Math,_p=$.Object,_h=$.RegExp,_v=$.String,_g=$.TypeError,_m=_0.prototype,_y=_f.prototype,_k=_p.prototype,_x=$["__core-js_shared__"],_b=_y.toString,_E=_k.hasOwnProperty,_8=0,_A=(e=/[^.]+$/.exec(_x&&_x.keys&&_x.keys.IE_PROTO||""))?"Symbol(src)_1."+e:"",_S=_k.toString,_C=_b.call(_p),_F=_X._,_w=_h("^"+_b.call(_E).replace(Y,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),_W=$2?$.Buffer:t,_D=$.Symbol,_B=$.Uint8Array,_L=_W?_W.allocUnsafe:t,_M=$j(_p.getPrototypeOf,_p),_T=_p.create,_j=_k.propertyIsEnumerable,_P=_m.splice,_V=_D?_D.isConcatSpreadable:t,_q=_D?_D.iterator:t,_Z=_D?_D.toStringTag:t,_J=function(){try{var _=na(_p,"defineProperty");return _({},"",{}),_}catch($){}}(),_Q=$.clearTimeout!==_X.clearTimeout&&$.clearTimeout,_Y=_c&&_c.now!==_X.Date.now&&_c.now,$1=$.setTimeout!==_X.setTimeout&&$.setTimeout,$0=_d.ceil,$d=_d.floor,$x=_p.getOwnPropertySymbols,$z=_W?_W.isBuffer:t,$H=$.isFinite,$N=_m.join,$q=$j(_p.keys,_p),$9=_d.max,$K=_d.min,$Z=_c.now,$J=$.parseInt,$X=_d.random,$Q=_m.reverse,$Y=na($,"DataView"),e2=na($,"Map"),e1=na($,"Promise"),e0=na($,"Set"),e_=na($,"WeakMap"),e3=na(_p,"create"),e$=e_&&new e_,e4={},e5=nG($Y),e6=nG(e2),e7=nG(e1),ee=nG(e0),et=nG(e_),en=_D?_D.prototype:t,er=en?en.valueOf:t,ei=en?en.toString:t;function eu(_){if(rK(_)&&!rG(_)&&!(_ instanceof ec)){if(_ instanceof es)return _;if(_E.call(_,"__wrapped__"))return nI(_)}return new es(_)}var eo=function(){function _(){}return function($){if(!r9($))return{};if(_T)return _T($);_.prototype=$;var e=new _;return _.prototype=t,e}}();function ea(){}function es(_,$){this.__wrapped__=_,this.__actions__=[],this.__chain__=!!$,this.__index__=0,this.__values__=t}function ec(_){this.__wrapped__=_,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=a,this.__views__=[]}function el(_){var $=-1,e=null==_?0:_.length;for(this.clear();++$=$?_:$)),_}function eF(_,$,e,n,r,i){var u,o=1&$,a=2&$;if(e&&(u=r?e(_,n,r,i):e(_)),u!==t)return u;if(!r9(_))return _;var s=rG(_);if(s){if(u=(c=_,l=c.length,d=new c.constructor(l),l&&"string"==typeof c[0]&&_E.call(c,"index")&&(d.index=c.index,d.input=c.input),d),!o)return tj(_,u)}else{var c,l,d,v,b,F,O,V,R,U=nl(_),z=U==g||U==m;if(rV(_))return tW(_,o);if(U==x||U==f||z&&!r){if(u=a||z?{}:nd(_),!o){return a?(v=_,b=(V=u,R=_,V&&tG(R,im(R),V)),tG(v,nc(v),b)):(F=_,O=e8(u,_),tG(F,ns(F),O))}}else{if(!_N[U])return r?_:{};u=function _($,e,t){var n,r,i,u,o,a,s=$.constructor;switch(e){case w:return tD($);case p:case h:return new s(+$);case W:return n=$,i=(r=t)?tD(n.buffer):n.buffer,new n.constructor(i,n.byteOffset,n.byteLength);case D:case B:case L:case M:case T:case j:case G:case I:case P:return tB($,t);case y:return new s;case k:case S:return new s($);case E:return(o=new(u=$).constructor(u.source,_e.exec(u))).lastIndex=u.lastIndex,o;case A:return new s;case C:return a=$,er?_p(er.call(a)):{}}}(_,U,o)}}i||(i=new eh);var H=i.get(_);if(H)return H;i.set(_,u),rY(_)?_.forEach(function(t){u.add(eF(t,$,e,t,_,i))}):rZ(_)&&_.forEach(function(t,n){u.set(n,eF(t,$,e,n,_,i))});var N=s?t:(4&$?a?ne:n7:a?im:ig)(_);return $t(N||_,function(t,n){N&&(t=_[n=t]),ex(u,n,eF(t,$,e,n,_,i))}),u}function ew(_,$,e){var n=e.length;if(null==_)return!n;for(_=_p(_);n--;){var r=e[n],i=$[r],u=_[r];if(u===t&&!(r in _)||!i(u))return!1}return!0}function eW(_,$,e){if("function"!=typeof _)throw new _g(n);return nC(function(){_.apply(t,e)},$)}function eD(_,$,e,t){var n=-1,r=$u,i=!0,u=_.length,o=[],a=$.length;if(!u)return o;e&&($=$a($,$S(e))),t?(r=$o,i=!1):$.length>=200&&(r=$F,i=!1,$=new ep($));outer:for(;++n-1},ef.prototype.set=function _($,e){var t=this.__data__,n=eb(t,$);return n<0?(++this.size,t.push([$,e])):t[n][1]=e,this},ed.prototype.clear=function _(){this.size=0,this.__data__={hash:new el,map:new(e2||ef),string:new el}},ed.prototype.delete=function _($){var e=nu(this,$).delete($);return this.size-=e?1:0,e},ed.prototype.get=function _($){return nu(this,$).get($)},ed.prototype.has=function _($){return nu(this,$).has($)},ed.prototype.set=function _($,e){var t=nu(this,$),n=t.size;return t.set($,e),this.size+=t.size==n?0:1,this},ep.prototype.add=ep.prototype.push=function _($){return this.__data__.set($,r),this},ep.prototype.has=function _($){return this.__data__.has($)},eh.prototype.clear=function _(){this.__data__=new ef,this.size=0},eh.prototype.delete=function _($){var e=this.__data__,t=e.delete($);return this.size=e.size,t},eh.prototype.get=function _($){return this.__data__.get($)},eh.prototype.has=function _($){return this.__data__.has($)},eh.prototype.set=function _($,e){var t=this.__data__;if(t instanceof ef){var n=t.__data__;if(!e2||n.length<199)return n.push([$,e]),this.size=++t.size,this;t=this.__data__=new ed(n)}return t.set($,e),this.size=t.size,this};var eB=tO(eO),eL=tO(eV,!0);function eM(_,$){var e=!0;return eB(_,function(_,t,n){return e=!!$(_,t,n)}),e}function eT(_,$,e){for(var n=-1,r=_.length;++n0&&e(u)?$>1?eG(u,$-1,e,t,n):$s(n,u):t||(n[n.length]=u)}return n}var eI=tV(),eP=tV(!0);function eO(_,$){return _&&eI(_,$,ig)}function eV(_,$){return _&&eP(_,$,ig)}function eR(_,$){return $i($,function($){return rH(_[$])})}function eU(_,$){$=tC($,_);for(var e=0,n=$.length;null!=_&&e$}function eq(_,$){return null!=_&&_E.call(_,$)}function e9(_,$){return null!=_&&$ in _p(_)}function eK(_,$,e){for(var n=e?$o:$u,r=_[0].length,i=_.length,u=i,o=_0(i),a=1/0,s=[];u--;){var c=_[u];u&&$&&(c=$a(c,$S($))),a=$K(c.length,a),o[u]=!e&&($||r>=120&&c.length>=120)?new ep(u&&c):t}c=_[0];var l=-1,f=o[0];outer:for(;++l=o)return a;return a*("desc"==t[n]?-1:1)}}return $.index-e.index}(_,$,e)})}function t7(_,$,e){for(var t=-1,n=$.length,r={};++t-1;)u!==_&&_P.call(u,o,1),_P.call(_,o,1);return _}function tt(_,$){for(var e=_?$.length:0,t=e-1;e--;){var n=$[e];if(e==t||n!==r){var r=n;nh(n)?_P.call(_,n,1):ty(_,n)}}return _}function tn(_,$){return _+$d($X()*($-_+1))}function tr(_,$){var e="";if(!_||$<1||$>9007199254740991)return e;do $%2&&(e+=_),($=$d($/2))&&(_+=_);while($);return e}function ti(_,$){return nF(nE(_,$,iU),_+"")}function tu(_){return eg(iS(_))}function to(_,$){var e=iS(_);return nD(e,eC($,0,e.length))}function ta(_,$,e,n){if(!r9(_))return _;$=tC($,_);for(var r=-1,i=$.length,u=i-1,o=_;null!=o&&++rn?0:n+$),(e=e>n?n:e)<0&&(e+=n),n=$>e?0:e-$>>>0,$>>>=0;for(var r=_0(n);++t>>1,i=_[r];null!==i&&!i1(i)&&(e?i<=$:i<$)?t=r+1:n=r}return n}return tp(_,$,iU,e)}function tp(_,$,e,n){var r=0,i=null==_?0:_.length;if(0===i)return 0;for(var u=($=e($))!=$,o=null===$,a=i1($),c=$===t;r=200){var a=$?null:n1(_);if(a)return $I(a);i=!1,n=$F,o=new ep}else o=$?[]:u;outer:for(;++t=n?_:tl(_,$,e)}var tw=_Q||function(_){return _X.clearTimeout(_)};function tW(_,$){if($)return _.slice();var e=_.length,t=_L?_L(e):new _.constructor(e);return _.copy(t),t}function tD(_){var $=new _.constructor(_.byteLength);return new _B($).set(new _B(_)),$}function tB(_,$){var e=$?tD(_.buffer):_.buffer;return new _.constructor(e,_.byteOffset,_.length)}function tL(_,$){if(_!==$){var e=_!==t,n=null===_,r=_==_,i=i1(_),u=$!==t,o=null===$,a=$==$,s=i1($);if(!o&&!s&&!i&&_>$||i&&u&&a&&!o&&!s||n&&u&&a||!e&&a||!r)return 1;if(!n&&!i&&!s&&_<$||s&&e&&r&&!n&&!i||o&&e&&r||!u&&r||!a)return -1}return 0}function tM(_,$,e,t){for(var n=-1,r=_.length,i=e.length,u=-1,o=$.length,a=$9(r-i,0),s=_0(o+a),c=!t;++u1?e[r-1]:t,u=r>2?e[2]:t;for(i=_.length>3&&"function"==typeof i?(r--,i):t,u&&nv(e[0],e[1],u)&&(i=r<3?t:i,r=1),$=_p($);++n-1?r[i?$[u]:u]:t}}function tN(_){return n6(function($){var e=$.length,r=e,i=es.prototype.thru;for(_&&$.reverse();r--;){var u=$[r];if("function"!=typeof u)throw new _g(n);if(i&&!o&&"wrapper"==nn(u))var o=new es([],!0)}for(r=o?r:e;++r1&&m.reverse(),c&&ao))return!1;var s=i.get(_),c=i.get($);if(s&&c)return s==$&&c==_;var l=-1,f=!0,d=2&e?new ep:t;for(i.set(_,$),i.set($,_);++l-1&&_%1==0&&_<$}function nv(_,$,e){if(!r9(e))return!1;var t=typeof $;return("number"==t?!!(rP(e)&&nh($,e.length)):"string"==t&&$ in e)&&rL(e[$],_)}function ng(_,$){if(rG(_))return!1;var e=typeof _;return!!("number"==e||"symbol"==e||"boolean"==e||null==_||i1(_))||X.test(_)||!J.test(_)||null!=$&&_ in _p($)}function nm(_){var $=nn(_),e=eu[$];if("function"!=typeof e||!($ in ec.prototype))return!1;if(_===e)return!0;var t=nt(e);return!!t&&_===t[0]}($Y&&nl(new $Y(new ArrayBuffer(1)))!=W||e2&&nl(new e2)!=y||e1&&nl(e1.resolve())!=b||e0&&nl(new e0)!=A||e_&&nl(new e_)!=F)&&(nl=function(_){var $=eH(_),e=$==x?_.constructor:t,n=e?nG(e):"";if(n)switch(n){case e5:return W;case e6:return y;case e7:return b;case ee:return A;case et:return F}return $});var ny=_x?rH:u1;function nk(_){var $=_&&_.constructor;return _===("function"==typeof $&&$.prototype||_k)}function nx(_){return _==_&&!r9(_)}function nb(_,$){return function(e){return null!=e&&e[_]===$&&($!==t||_ in _p(e))}}function nE(_,$,e){return $=$9($===t?_.length-1:$,0),function(){for(var t=arguments,n=-1,r=$9(t.length-$,0),i=_0(r);++n1?"& ":"")+e[n],e=e.join(t>2?", ":" "),$.replace(__,"{\n/* [wrapped with "+e+"] */\n")}(u,(r=(n=(t=u).match(_3))?n[1].split(_$):[],i=e,$t(l,function(_){var $="_."+_[0];i&_[1]&&!$u(r,$)&&r.push($)}),r.sort())))}function nW(_){var $=0,e=0;return function(){var n=$Z(),r=16-(n-e);if(e=n,r>0){if(++$>=800)return arguments[0]}else $=0;return _.apply(t,arguments)}}function nD(_,$){var e=-1,n=_.length,r=n-1;for($=$===t?n:$;++e<$;){var i=tn(e,r),u=_[i];_[i]=_[e],_[e]=u}return _.length=$,_}var nB,nL,nM,nT=(nM=(nL=rC(nB=function(_){var $=[];return 46===_.charCodeAt(0)&&$.push(""),_.replace(Q,function(_,e,t,n){$.push(t?n.replace(_6,"$1"):e||_)}),$},function(_){return 500===nM.size&&nM.clear(),_})).cache,nL);function nj(_){if("string"==typeof _||i1(_))return _;var $=_+"";return"0"==$&&1/_==-u?"-0":$}function nG(_){if(null!=_){try{return _b.call(_)}catch($){}try{return _+""}catch(e){}}return""}function nI(_){if(_ instanceof ec)return _.clone();var $=new es(_.__wrapped__,_.__chain__);return $.__actions__=tj(_.__actions__),$.__index__=_.__index__,$.__values__=_.__values__,$}var nP=ti(function(_,$){return rO(_)?eD(_,eG($,1,rO,!0)):[]}),nO=ti(function(_,$){var e=nK($);return rO(e)&&(e=t),rO(_)?eD(_,eG($,1,rO,!0),ni(e,2)):[]}),nV=ti(function(_,$){var e=nK($);return rO(e)&&(e=t),rO(_)?eD(_,eG($,1,rO,!0),t,e):[]});function nR(_,$,e){var t=null==_?0:_.length;if(!t)return -1;var n=null==e?0:i5(e);return n<0&&(n=$9(t+n,0)),$h(_,ni($,3),n)}function nU(_,$,e){var n=null==_?0:_.length;if(!n)return -1;var r=n-1;return e!==t&&(r=i5(e),r=e<0?$9(n+r,0):$K(r,n-1)),$h(_,ni($,3),r,!0)}function nz(_){return(null==_?0:_.length)?eG(_,1):[]}function nH(_){return _&&_.length?_[0]:t}var nN=ti(function(_){var $=$a(_,tA);return $.length&&$[0]===_[0]?eK($):[]}),nq=ti(function(_){var $=nK(_),e=$a(_,tA);return $===nK(e)?$=t:e.pop(),e.length&&e[0]===_[0]?eK(e,ni($,2)):[]}),n9=ti(function(_){var $=nK(_),e=$a(_,tA);return($="function"==typeof $?$:t)&&e.pop(),e.length&&e[0]===_[0]?eK(e,t,$):[]});function nK(_){var $=null==_?0:_.length;return $?_[$-1]:t}var nZ=ti(nJ);function nJ(_,$){return _&&_.length&&$&&$.length?te(_,$):_}var nX=n6(function(_,$){var e=null==_?0:_.length,t=eS(_,$);return tt(_,$a($,function(_){return nh(_,e)?+_:_}).sort(tL)),t});function nQ(_){return null==_?_:$Q.call(_)}function nY(_,$){return td(_,$)}var r2=ti(function(_){return tm(eG(_,1,rO,!0))}),r1=ti(function(_){var $=nK(_);return rO($)&&($=t),tm(eG(_,1,rO,!0),ni($,2))}),r0=ti(function(_){var $=nK(_);return $="function"==typeof $?$:t,tm(eG(_,1,rO,!0),t,$)});function r_(_){if(!(_&&_.length))return[];var $=0;return _=$i(_,function(_){if(rO(_))return $=$9(_.length,$),!0}),$8($,function($){return $a(_,$k($))})}function r3(_,$){if(!(_&&_.length))return[];var e=r_(_);return null==$?e:$a(e,function(_){return $7($,t,_)})}var r$=ti(function(_,$){return rO(_)?eD(_,$):[]}),r4=ti(function(_){return tE($i(_,rO))}),r5=ti(function(_){var $=nK(_);return rO($)&&($=t),tE($i(_,rO),ni($,2))}),r6=ti(function(_){var $=nK(_);return $="function"==typeof $?$:t,tE($i(_,rO),t,$)}),r7=ti(r_),re=ti(function(_){var $=_.length,e=$>1?_[$-1]:t;return e="function"==typeof e?(_.pop(),e):t,r3(_,e)});function rt(_){var $=eu(_);return $.__chain__=!0,$}function rn(_,$){return $(_),_}function rr(_,$){return $(_)}var ri=n6(function(_){var $=_.length,e=$?_[0]:0,n=this.__wrapped__,r=function($){return eS($,_)};return!($>1)&&!this.__actions__.length&&n instanceof ec&&nh(e)?((n=n.slice(e,+e+($?1:0))).__actions__.push({func:rr,args:[r],thisArg:t}),new es(n,this.__chain__).thru(function(_){return $&&!_.length&&_.push(t),_})):this.thru(r)}),ru=tI(function(_,$,e){_E.call(_,e)?++_[e]:eA(_,e,1)}),ro=tH(nR),ra=tH(nU);function rs(_,$){return(rG(_)?$t:eB)(_,ni($,3))}function rc(_,$){return(rG(_)?$n:eL)(_,ni($,3))}var rl=tI(function(_,$,e){_E.call(_,e)?_[e].push($):eA(_,e,[$])}),rf=ti(function(_,$,e){var t=-1,n="function"==typeof $,r=rP(_)?_0(_.length):[];return eB(_,function(_){r[++t]=n?$7($,_,e):eZ(_,$,e)}),r}),rd=tI(function(_,$,e){eA(_,e,$)});function rp(_,$){return(rG(_)?$a:t_)(_,ni($,3))}var rh=tI(function(_,$,e){_[e?0:1].push($)},function(){return[[],[]]}),rv=ti(function(_,$){if(null==_)return[];var e=$.length;return e>1&&nv(_,$[0],$[1])?$=[]:e>2&&nv($[0],$[1],$[2])&&($=[$[0]]),t6(_,eG($,1),[])}),rg=_Y||function(){return _X.Date.now()};function rm(_,$,e){return $=e?t:$,$=_&&null==$?_.length:$,n_(_,128,t,t,t,t,$)}function ry(_,$){var e;if("function"!=typeof $)throw new _g(n);return _=i5(_),function(){return--_>0&&(e=$.apply(this,arguments)),_<=1&&($=t),e}}var rk=ti(function(_,$,e){var t=1;if(e.length){var n=$G(e,nr(rk));t|=32}return n_(_,t,$,e,n)}),rx=ti(function(_,$,e){var t=3;if(e.length){var n=$G(e,nr(rx));t|=32}return n_($,t,_,e,n)});function rb(_,$,e){$=e?t:$;var n=n_(_,8,t,t,t,t,t,$);return n.placeholder=rb.placeholder,n}function rE(_,$,e){$=e?t:$;var n=n_(_,16,t,t,t,t,t,$);return n.placeholder=rE.placeholder,n}function r8(_,$,e){var r,i,u,o,a,s,c=0,l=!1,f=!1,d=!0;if("function"!=typeof _)throw new _g(n);function p($){var e=r,n=i;return r=i=t,c=$,o=_.apply(n,e)}function h(_){var e=_-s,n=_-c;return s===t||e>=$||e<0||f&&n>=u}function v(){var _,e,t,n,r=rg();if(h(r))return g(r);a=nC(v,(e=(_=r)-s,t=_-c,n=$-e,f?$K(n,u-t):n))}function g(_){return(a=t,d&&r)?p(_):(r=i=t,o)}function m(){var _,e=rg(),n=h(e);if(r=arguments,i=this,s=e,n){if(a===t)return c=_=s,a=nC(v,$),l?p(_):o;if(f)return tw(a),a=nC(v,$),p(s)}return a===t&&(a=nC(v,$)),o}return $=i7($)||0,r9(e)&&(l=!!e.leading,u=(f="maxWait"in e)?$9(i7(e.maxWait)||0,$):u,d="trailing"in e?!!e.trailing:d),m.cancel=function _(){a!==t&&tw(a),c=0,r=s=i=a=t},m.flush=function _(){return a===t?o:g(rg())},m}var rA=ti(function(_,$){return eW(_,1,$)}),rS=ti(function(_,$,e){return eW(_,i7($)||0,e)});function rC(_,$){if("function"!=typeof _||null!=$&&"function"!=typeof $)throw new _g(n);var e=function(){var t=arguments,n=$?$.apply(this,t):t[0],r=e.cache;if(r.has(n))return r.get(n);var i=_.apply(this,t);return e.cache=r.set(n,i)||r,i};return e.cache=new(rC.Cache||ed),e}function rF(_){if("function"!=typeof _)throw new _g(n);return function(){var $=arguments;switch($.length){case 0:return!_.call(this);case 1:return!_.call(this,$[0]);case 2:return!_.call(this,$[0],$[1]);case 3:return!_.call(this,$[0],$[1],$[2])}return!_.apply(this,$)}}rC.Cache=ed;var rw=ti(function(_,$){var e=($=1==$.length&&rG($[0])?$a($[0],$S(ni())):$a(eG($,1),$S(ni()))).length;return ti(function(t){for(var n=-1,r=$K(t.length,e);++n=$}),rj=eJ(function(){return arguments}())?eJ:function(_){return rK(_)&&_E.call(_,"callee")&&!_j.call(_,"callee")},rG=_0.isArray,rI=$_?$S($_):function _($){return rK($)&&eH($)==w};function rP(_){return null!=_&&rq(_.length)&&!rH(_)}function rO(_){return rK(_)&&rP(_)}var rV=$z||u1,rR=$3?$S($3):function _($){return rK($)&&eH($)==h};function rU(_,$){return eX(_,$)}function rz(_){if(!rK(_))return!1;var $=eH(_);return $==v||"[object DOMException]"==$||"string"==typeof _.message&&"string"==typeof _.name&&!rX(_)}function rH(_){if(!r9(_))return!1;var $=eH(_);return $==g||$==m||"[object AsyncFunction]"==$||"[object Proxy]"==$}function rN(_){return"number"==typeof _&&_==i5(_)}function rq(_){return"number"==typeof _&&_>-1&&_%1==0&&_<=9007199254740991}function r9(_){var $=typeof _;return null!=_&&("object"==$||"function"==$)}function rK(_){return null!=_&&"object"==typeof _}var rZ=$$?$S($$):function _($){return rK($)&&nl($)==y};function rJ(_){return"number"==typeof _||rK(_)&&eH(_)==k}function rX(_){if(!rK(_)||eH(_)!=x)return!1;var $=_M(_);if(null===$)return!0;var e=_E.call($,"constructor")&&$.constructor;return"function"==typeof e&&e instanceof e&&_b.call(e)==_C}var rQ=$4?$S($4):function _($){return rK($)&&eH($)==E},rY=$5?$S($5):function _($){return rK($)&&nl($)==A};function i2(_){return"string"==typeof _||!rG(_)&&rK(_)&&eH(_)==S}function i1(_){return"symbol"==typeof _||rK(_)&&eH(_)==C}var i0=$6?$S($6):function _($){return rK($)&&rq($.length)&&!!_H[eH($)]},i_=tQ(t0),i3=tQ(function(_,$){return _<=$});function i$(_){if(!_)return[];if(rP(_))return i2(_)?$O(_):tj(_);if(_q&&_[_q])return function _($){for(var e,t=[];!(e=$.next()).done;)t.push(e.value);return t}(_[_q]());var $=nl(_);return($==y?$T:$==A?$I:iS)(_)}function i4(_){return _?(_=i7(_))===u||_===-u?(_<0?-1:1)*17976931348623157e292:_==_?_:0:0===_?_:0}function i5(_){var $=i4(_),e=$%1;return $==$?e?$-e:$:0}function i6(_){return _?eC(i5(_),0,a):0}function i7(_){if("number"==typeof _)return _;if(i1(_))return o;if(r9(_)){var $="function"==typeof _.valueOf?_.valueOf():_;_=r9($)?$+"":$}if("string"!=typeof _)return 0===_?_:+_;_=$A(_);var e=_n.test(_);return e||_i.test(_)?_K(_.slice(2),e?2:8):_t.test(_)?o:+_}function ie(_){return tG(_,im(_))}function it(_){return null==_?"":tg(_)}var ir=tP(function(_,$){if(nk($)||rP($)){tG($,ig($),_);return}for(var e in $)_E.call($,e)&&ex(_,e,$[e])}),ii=tP(function(_,$){tG($,im($),_)}),iu=tP(function(_,$,e,t){tG($,im($),_,t)}),io=tP(function(_,$,e,t){tG($,ig($),_,t)}),ia=n6(eS),is=ti(function(_,$){_=_p(_);var e=-1,n=$.length,r=n>2?$[2]:t;for(r&&nv($[0],$[1],r)&&(n=1);++e1),$}),tG(_,ne(_),e),t&&(e=eF(e,7,n4));for(var n=$.length;n--;)ty(e,$[n]);return e}),ib=n6(function(_,$){var e,t;return null==_?{}:(e=_,t7(e,t=$,function(_,$){return id(e,$)}))});function iE(_,$){if(null==_)return{};var e=$a(ne(_),function(_){return[_]});return $=ni($),t7(_,e,function(_,e){return $(_,e[0])})}var i8=n0(ig),iA=n0(im);function iS(_){return null==_?[]:$C(_,ig(_))}var iC=tU(function(_,$,e){return $=$.toLowerCase(),_+(e?iF($):$)});function iF(_){return ij(it(_).toLowerCase())}function iw(_){return(_=it(_))&&_.replace(_o,$D).replace(_I,"")}var iW=tU(function(_,$,e){return _+(e?"-":"")+$.toLowerCase()}),iD=tU(function(_,$,e){return _+(e?" ":"")+$.toLowerCase()}),iB=tR("toLowerCase"),iL=tU(function(_,$,e){return _+(e?"_":"")+$.toLowerCase()}),iM=tU(function(_,$,e){return _+(e?" ":"")+ij($)}),iT=tU(function(_,$,e){return _+(e?" ":"")+$.toUpperCase()}),ij=tR("toUpperCase");function iG(_,$,e){if(_=it(_),t===($=e?t:$)){var n,r,i;return(n=_,_R.test(n))?(r=_).match(_O)||[]:(i=_).match(_4)||[]}return _.match($)||[]}var iI=ti(function(_,$){try{return $7(_,t,$)}catch(e){return rz(e)?e:new _l(e)}}),iP=n6(function(_,$){return $t($,function($){$=nj($),eA(_,$,rk(_[$],_))}),_});function iO(_){return function(){return _}}var iV=tN(),iR=tN(!0);function iU(_){return _}function iz(_){return t2("function"==typeof _?_:eF(_,1))}var iH=ti(function(_,$){return function(e){return eZ(e,_,$)}}),iN=ti(function(_,$){return function(e){return eZ(_,e,$)}});function iq(_,$,e){var t=ig($),n=eR($,t);null!=e||r9($)&&(n.length||!t.length)||(e=$,$=_,_=this,n=eR($,ig($)));var r=!(r9(e)&&"chain"in e)||!!e.chain,i=rH(_);return $t(n,function(e){var t=$[e];_[e]=t,i&&(_.prototype[e]=function(){var $=this.__chain__;if(r||$){var e=_(this.__wrapped__);return(e.__actions__=tj(this.__actions__)).push({func:t,args:arguments,thisArg:_}),e.__chain__=$,e}return t.apply(_,$s([this.value()],arguments))})}),_}function i9(){}var iK=tZ($a),iZ=tZ($r),iJ=tZ($f);function iX(_){var $;return ng(_)?$k(nj(_)):($=_,function(_){return eU(_,$)})}var iQ=tX(),iY=tX(!0);function u2(){return[]}function u1(){return!1}function u0(){return{}}function u_(){return""}function u3(){return!0}var u$,u4=tK(function(_,$){return _+$},0),u5=n2("ceil"),u6=tK(function(_,$){return _/$},1),u7=n2("floor"),ue=tK(function(_,$){return _*$},1),ut=n2("round"),un=tK(function(_,$){return _-$},0);return eu.after=function _($,e){if("function"!=typeof e)throw new _g(n);return $=i5($),function(){if(--$<1)return e.apply(this,arguments)}},eu.ary=rm,eu.assign=ir,eu.assignIn=ii,eu.assignInWith=iu,eu.assignWith=io,eu.at=ia,eu.before=ry,eu.bind=rk,eu.bindAll=iP,eu.bindKey=rx,eu.castArray=function _(){if(!arguments.length)return[];var $=arguments[0];return rG($)?$:[$]},eu.chain=rt,eu.chunk=function _($,e,n){e=(n?nv($,e,n):e===t)?1:$9(i5(e),0);var r=null==$?0:$.length;if(!r||e<1)return[];for(var i=0,u=0,o=_0($0(r/e));ii?0:i+n),(r=r===t||r>i?i:i5(r))<0&&(r+=i),r=n>r?0:i6(r);n>>0)?($=it($))&&("string"==typeof e||null!=e&&!rQ(e))&&!(e=tg(e))&&$M($)?tF($O($),0,n):$.split(e,n):[]},eu.spread=function _($,e){if("function"!=typeof $)throw new _g(n);return e=null==e?0:$9(i5(e),0),ti(function(_){var t=_[e],n=tF(_,0,e);return t&&$s(n,t),$7($,this,n)})},eu.tail=function _($){var e=null==$?0:$.length;return e?tl($,1,e):[]},eu.take=function _($,e,n){return $&&$.length?(e=n||e===t?1:i5(e),tl($,0,e<0?0:e)):[]},eu.takeRight=function _($,e,n){var r=null==$?0:$.length;return r?(e=n||e===t?1:i5(e),tl($,(e=r-e)<0?0:e,r)):[]},eu.takeRightWhile=function _($,e){return $&&$.length?tx($,ni(e,3),!1,!0):[]},eu.takeWhile=function _($,e){return $&&$.length?tx($,ni(e,3)):[]},eu.tap=rn,eu.throttle=function _($,e,t){var r=!0,i=!0;if("function"!=typeof $)throw new _g(n);return r9(t)&&(r="leading"in t?!!t.leading:r,i="trailing"in t?!!t.trailing:i),r8($,e,{leading:r,maxWait:e,trailing:i})},eu.thru=rr,eu.toArray=i$,eu.toPairs=i8,eu.toPairsIn=iA,eu.toPath=function _($){return rG($)?$a($,nj):i1($)?[$]:tj(nT(it($)))},eu.toPlainObject=ie,eu.transform=function _($,e,t){var n=rG($),r=n||rV($)||i0($);if(e=ni(e,4),null==t){var i=$&&$.constructor;t=r?n?new i:[]:r9($)&&rH(i)?eo(_M($)):{}}return(r?$t:eO)($,function(_,$,n){return e(t,_,$,n)}),t},eu.unary=function _($){return rm($,1)},eu.union=r2,eu.unionBy=r1,eu.unionWith=r0,eu.uniq=function _($){return $&&$.length?tm($):[]},eu.uniqBy=function _($,e){return $&&$.length?tm($,ni(e,2)):[]},eu.uniqWith=function _($,e){return e="function"==typeof e?e:t,$&&$.length?tm($,t,e):[]},eu.unset=function _($,e){return null==$||ty($,e)},eu.unzip=r_,eu.unzipWith=r3,eu.update=function _($,e,t){return null==$?$:tk($,e,tS(t))},eu.updateWith=function _($,e,n,r){return r="function"==typeof r?r:t,null==$?$:tk($,e,tS(n),r)},eu.values=iS,eu.valuesIn=function _($){return null==$?[]:$C($,im($))},eu.without=r$,eu.words=iG,eu.wrap=function _($,e){return rW(tS(e),$)},eu.xor=r4,eu.xorBy=r5,eu.xorWith=r6,eu.zip=r7,eu.zipObject=function _($,e){return t8($||[],e||[],ex)},eu.zipObjectDeep=function _($,e){return t8($||[],e||[],ta)},eu.zipWith=re,eu.entries=i8,eu.entriesIn=iA,eu.extend=ii,eu.extendWith=iu,iq(eu,eu),eu.add=u4,eu.attempt=iI,eu.camelCase=iC,eu.capitalize=iF,eu.ceil=u5,eu.clamp=function _($,e,n){return n===t&&(n=e,e=t),n!==t&&(n=(n=i7(n))==n?n:0),e!==t&&(e=(e=i7(e))==e?e:0),eC(i7($),e,n)},eu.clone=function _($){return eF($,4)},eu.cloneDeep=function _($){return eF($,5)},eu.cloneDeepWith=function _($,e){return e="function"==typeof e?e:t,eF($,5,e)},eu.cloneWith=function _($,e){return e="function"==typeof e?e:t,eF($,4,e)},eu.conformsTo=function _($,e){return null==e||ew($,e,ig(e))},eu.deburr=iw,eu.defaultTo=function _($,e){return null==$||$!=$?e:$},eu.divide=u6,eu.endsWith=function _($,e,n){$=it($),e=tg(e);var r=$.length,i=n=n===t?r:eC(i5(n),0,r);return(n-=e.length)>=0&&$.slice(n,i)==e},eu.eq=rL,eu.escape=function _($){return($=it($))&&N.test($)?$.replace(z,$B):$},eu.escapeRegExp=function _($){return($=it($))&&_2.test($)?$.replace(Y,"\\$&"):$},eu.every=function _($,e,n){var r=rG($)?$r:eM;return n&&nv($,e,n)&&(e=t),r($,ni(e,3))},eu.find=ro,eu.findIndex=nR,eu.findKey=function _($,e){return $p($,ni(e,3),eO)},eu.findLast=ra,eu.findLastIndex=nU,eu.findLastKey=function _($,e){return $p($,ni(e,3),eV)},eu.floor=u7,eu.forEach=rs,eu.forEachRight=rc,eu.forIn=function _($,e){return null==$?$:eI($,ni(e,3),im)},eu.forInRight=function _($,e){return null==$?$:eP($,ni(e,3),im)},eu.forOwn=function _($,e){return $&&eO($,ni(e,3))},eu.forOwnRight=function _($,e){return $&&eV($,ni(e,3))},eu.get=il,eu.gt=rM,eu.gte=rT,eu.has=function _($,e){return null!=$&&nf($,e,eq)},eu.hasIn=id,eu.head=nH,eu.identity=iU,eu.includes=function _($,e,t,n){$=rP($)?$:iS($),t=t&&!n?i5(t):0;var r=$.length;return t<0&&(t=$9(r+t,0)),i2($)?t<=r&&$.indexOf(e,t)>-1:!!r&&$v($,e,t)>-1},eu.indexOf=function _($,e,t){var n=null==$?0:$.length;if(!n)return -1;var r=null==t?0:i5(t);return r<0&&(r=$9(n+r,0)),$v($,e,r)},eu.inRange=function _($,e,n){var r,i,u;return e=i4(e),n===t?(n=e,e=0):n=i4(n),r=$=i7($),i=e,r>=$K(i,u=n)&&r<$9(i,u)},eu.invoke=iv,eu.isArguments=rj,eu.isArray=rG,eu.isArrayBuffer=rI,eu.isArrayLike=rP,eu.isArrayLikeObject=rO,eu.isBoolean=function _($){return!0===$||!1===$||rK($)&&eH($)==p},eu.isBuffer=rV,eu.isDate=rR,eu.isElement=function _($){return rK($)&&1===$.nodeType&&!rX($)},eu.isEmpty=function _($){if(null==$)return!0;if(rP($)&&(rG($)||"string"==typeof $||"function"==typeof $.splice||rV($)||i0($)||rj($)))return!$.length;var e=nl($);if(e==y||e==A)return!$.size;if(nk($))return!t1($).length;for(var t in $)if(_E.call($,t))return!1;return!0},eu.isEqual=rU,eu.isEqualWith=function _($,e,n){var r=(n="function"==typeof n?n:t)?n($,e):t;return r===t?eX($,e,t,n):!!r},eu.isError=rz,eu.isFinite=function _($){return"number"==typeof $&&$H($)},eu.isFunction=rH,eu.isInteger=rN,eu.isLength=rq,eu.isMap=rZ,eu.isMatch=function _($,e){return $===e||eQ($,e,no(e))},eu.isMatchWith=function _($,e,n){return n="function"==typeof n?n:t,eQ($,e,no(e),n)},eu.isNaN=function _($){return rJ($)&&$!=+$},eu.isNative=function _($){if(ny($))throw new _l("Unsupported core-js use. Try https://npms.io/search?q=ponyfill.");return eY($)},eu.isNil=function _($){return null==$},eu.isNull=function _($){return null===$},eu.isNumber=rJ,eu.isObject=r9,eu.isObjectLike=rK,eu.isPlainObject=rX,eu.isRegExp=rQ,eu.isSafeInteger=function _($){return rN($)&&$>=-9007199254740991&&$<=9007199254740991},eu.isSet=rY,eu.isString=i2,eu.isSymbol=i1,eu.isTypedArray=i0,eu.isUndefined=function _($){return $===t},eu.isWeakMap=function _($){return rK($)&&nl($)==F},eu.isWeakSet=function _($){return rK($)&&"[object WeakSet]"==eH($)},eu.join=function _($,e){return null==$?"":$N.call($,e)},eu.kebabCase=iW,eu.last=nK,eu.lastIndexOf=function _($,e,n){var r=null==$?0:$.length;if(!r)return -1;var i=r;return n!==t&&(i=(i=i5(n))<0?$9(r+i,0):$K(i,r-1)),e==e?function _($,e,t){for(var n=t+1;n--&&$[n]!==e;);return n}($,e,i):$h($,$m,i,!0)},eu.lowerCase=iD,eu.lowerFirst=iB,eu.lt=i_,eu.lte=i3,eu.max=function _($){return $&&$.length?eT($,iU,eN):t},eu.maxBy=function _($,e){return $&&$.length?eT($,ni(e,2),eN):t},eu.mean=function _($){return $y($,iU)},eu.meanBy=function _($,e){return $y($,ni(e,2))},eu.min=function _($){return $&&$.length?eT($,iU,t0):t},eu.minBy=function _($,e){return $&&$.length?eT($,ni(e,2),t0):t},eu.stubArray=u2,eu.stubFalse=u1,eu.stubObject=u0,eu.stubString=u_,eu.stubTrue=u3,eu.multiply=ue,eu.nth=function _($,e){return $&&$.length?t5($,i5(e)):t},eu.noConflict=function _(){return _X._===this&&(_X._=_F),this},eu.noop=i9,eu.now=rg,eu.pad=function _($,e,t){$=it($);var n=(e=i5(e))?$P($):0;if(!e||n>=e)return $;var r=(e-n)/2;return tJ($d(r),t)+$+tJ($0(r),t)},eu.padEnd=function _($,e,t){$=it($);var n=(e=i5(e))?$P($):0;return e&&ne){var r=$;$=e,e=r}if(n||$%1||e%1){var i=$X();return $K($+i*(e-$+_9("1e-"+((i+"").length-1))),e)}return tn($,e)},eu.reduce=function _($,e,t){var n=rG($)?$c:$b,r=arguments.length<3;return n($,ni(e,4),t,r,eB)},eu.reduceRight=function _($,e,t){var n=rG($)?$l:$b,r=arguments.length<3;return n($,ni(e,4),t,r,eL)},eu.repeat=function _($,e,n){return e=(n?nv($,e,n):e===t)?1:i5(e),tr(it($),e)},eu.replace=function _(){var $=arguments,e=it($[0]);return $.length<3?e:e.replace($[1],$[2])},eu.result=function _($,e,n){e=tC(e,$);var r=-1,i=e.length;for(i||(i=1,$=t);++r9007199254740991)return[];var t=a,n=$K($,a);e=ni(e),$-=a;for(var r=$8(n,e);++t<$;)e(t);return r},eu.toFinite=i4,eu.toInteger=i5,eu.toLength=i6,eu.toLower=function _($){return it($).toLowerCase()},eu.toNumber=i7,eu.toSafeInteger=function _($){return $?eC(i5($),-9007199254740991,9007199254740991):0===$?$:0},eu.toString=it,eu.toUpper=function _($){return it($).toUpperCase()},eu.trim=function _($,e,n){if(($=it($))&&(n||e===t))return $A($);if(!$||!(e=tg(e)))return $;var r=$O($),i=$O(e),u=$w(r,i),o=$W(r,i)+1;return tF(r,u,o).join("")},eu.trimEnd=function _($,e,n){if(($=it($))&&(n||e===t))return $.slice(0,$V($)+1);if(!$||!(e=tg(e)))return $;var r=$O($),i=$W(r,$O(e))+1;return tF(r,0,i).join("")},eu.trimStart=function _($,e,n){if(($=it($))&&(n||e===t))return $.replace(_1,"");if(!$||!(e=tg(e)))return $;var r=$O($),i=$w(r,$O(e));return tF(r,i).join("")},eu.truncate=function _($,e){var n=30,r="...";if(r9(e)){var i="separator"in e?e.separator:i;n="length"in e?i5(e.length):n,r="omission"in e?tg(e.omission):r}var u=($=it($)).length;if($M($)){var o=$O($);u=o.length}if(n>=u)return $;var a=n-$P(r);if(a<1)return r;var s=o?tF(o,0,a).join(""):$.slice(0,a);if(i===t)return s+r;if(o&&(a+=s.length-a),rQ(i)){if($.slice(a).search(i)){var c,l=s;for(i.global||(i=_h(i.source,it(_e.exec(i))+"g")),i.lastIndex=0;c=i.exec(l);)var f=c.index;s=s.slice(0,f===t?a:f)}}else if($.indexOf(tg(i),a)!=a){var d=s.lastIndexOf(i);d>-1&&(s=s.slice(0,d))}return s+r},eu.unescape=function _($){return($=it($))&&H.test($)?$.replace(U,$R):$},eu.uniqueId=function _($){var e=++_8;return it($)+e},eu.upperCase=iT,eu.upperFirst=ij,eu.each=rs,eu.eachRight=rc,eu.first=nH,iq(eu,(u$={},eO(eu,function(_,$){_E.call(eu.prototype,$)||(u$[$]=_)}),u$),{chain:!1}),eu.VERSION="4.17.21",$t(["bind","bindKey","curry","curryRight","partial","partialRight"],function(_){eu[_].placeholder=eu}),$t(["drop","take"],function(_,$){ec.prototype[_]=function(e){e=e===t?1:$9(i5(e),0);var n=this.__filtered__&&!$?new ec(this):this.clone();return n.__filtered__?n.__takeCount__=$K(e,n.__takeCount__):n.__views__.push({size:$K(e,a),type:_+(n.__dir__<0?"Right":"")}),n},ec.prototype[_+"Right"]=function($){return this.reverse()[_]($).reverse()}}),$t(["filter","map","takeWhile"],function(_,$){var e=$+1,t=1==e||3==e;ec.prototype[_]=function(_){var $=this.clone();return $.__iteratees__.push({iteratee:ni(_,3),type:e}),$.__filtered__=$.__filtered__||t,$}}),$t(["head","last"],function(_,$){var e="take"+($?"Right":"");ec.prototype[_]=function(){return this[e](1).value()[0]}}),$t(["initial","tail"],function(_,$){var e="drop"+($?"":"Right");ec.prototype[_]=function(){return this.__filtered__?new ec(this):this[e](1)}}),ec.prototype.compact=function(){return this.filter(iU)},ec.prototype.find=function(_){return this.filter(_).head()},ec.prototype.findLast=function(_){return this.reverse().find(_)},ec.prototype.invokeMap=ti(function(_,$){return"function"==typeof _?new ec(this):this.map(function(e){return eZ(e,_,$)})}),ec.prototype.reject=function(_){return this.filter(rF(ni(_)))},ec.prototype.slice=function(_,$){_=i5(_);var e=this;return e.__filtered__&&(_>0||$<0)?new ec(e):(_<0?e=e.takeRight(-_):_&&(e=e.drop(_)),$!==t&&(e=($=i5($))<0?e.dropRight(-$):e.take($-_)),e)},ec.prototype.takeRightWhile=function(_){return this.reverse().takeWhile(_).reverse()},ec.prototype.toArray=function(){return this.take(a)},eO(ec.prototype,function(_,$){var e=/^(?:filter|find|map|reject)|While$/.test($),n=/^(?:head|last)$/.test($),r=eu[n?"take"+("last"==$?"Right":""):$],i=n||/^find/.test($);r&&(eu.prototype[$]=function(){var $=this.__wrapped__,u=n?[1]:arguments,o=$ instanceof ec,a=u[0],s=o||rG($),c=function(_){var $=r.apply(eu,$s([_],u));return n&&l?$[0]:$};s&&e&&"function"==typeof a&&1!=a.length&&(o=s=!1);var l=this.__chain__,f=!!this.__actions__.length,d=i&&!l,p=o&&!f;if(!i&&s){$=p?$:new ec(this);var h=_.apply($,u);return h.__actions__.push({func:rr,args:[c],thisArg:t}),new es(h,l)}return d&&p?_.apply(this,u):(h=this.thru(c),d?n?h.value()[0]:h.value():h)})}),$t(["pop","push","shift","sort","splice","unshift"],function(_){var $=_m[_],e=/^(?:push|sort|unshift)$/.test(_)?"tap":"thru",t=/^(?:pop|shift)$/.test(_);eu.prototype[_]=function(){var _=arguments;if(t&&!this.__chain__){var n=this.value();return $.apply(rG(n)?n:[],_)}return this[e](function(e){return $.apply(rG(e)?e:[],_)})}}),eO(ec.prototype,function(_,$){var e=eu[$];if(e){var t=e.name+"";_E.call(e4,t)||(e4[t]=[]),e4[t].push({name:$,func:e})}}),e4[tq(t,2).name]=[{name:"wrapper",func:t}],ec.prototype.clone=function _(){var $=new ec(this.__wrapped__);return $.__actions__=tj(this.__actions__),$.__dir__=this.__dir__,$.__filtered__=this.__filtered__,$.__iteratees__=tj(this.__iteratees__),$.__takeCount__=this.__takeCount__,$.__views__=tj(this.__views__),$},ec.prototype.reverse=function _(){if(this.__filtered__){var $=new ec(this);$.__dir__=-1,$.__filtered__=!0}else $=this.clone(),$.__dir__*=-1;return $},ec.prototype.value=function _(){var $=this.__wrapped__.value(),e=this.__dir__,t=rG($),n=e<0,r=t?$.length:0,i=function _($,e,t){for(var n=-1,r=t.length;++n=this.__values__.length,e=$?t:this.__values__[this.__index__++];return{done:$,value:e}},eu.prototype.plant=function _($){for(var e,n=this;n instanceof ea;){var r=nI(n);r.__index__=0,r.__values__=t,e?i.__wrapped__=r:e=r;var i=r;n=n.__wrapped__}return i.__wrapped__=$,e},eu.prototype.reverse=function _(){var $=this.__wrapped__;if($ instanceof ec){var e=$;return this.__actions__.length&&(e=new ec(this)),(e=e.reverse()).__actions__.push({func:rr,args:[nQ],thisArg:t}),new es(e,this.__chain__)}return this.thru(nQ)},eu.prototype.toJSON=eu.prototype.valueOf=eu.prototype.value=function _(){return tb(this.__wrapped__,this.__actions__)},eu.prototype.first=eu.prototype.head,_q&&(eu.prototype[_q]=function _(){return this}),eu}();"function"==typeof define&&"object"==typeof define.amd&&define.amd?(_X._=$U,define(function(){return $U})):_Y?((_Y.exports=$U)._=$U,_Q._=$U):_X._=$U}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],13:[function(_,$,e){var t=$.exports={},n=[],r=!1;function i(){if(!r){r=!0;for(var _,$=n.length;$;){_=n,n=[];for(var e=-1;++e<$;)_[e]();$=n.length}r=!1}}function u(){}t.nextTick=function(_){n.push(_),r||setTimeout(i,0)},t.title="browser",t.browser=!0,t.env={},t.argv=[],t.version="",t.versions={},t.on=u,t.addListener=u,t.once=u,t.off=u,t.removeListener=u,t.removeAllListeners=u,t.emit=u,t.binding=function(_){throw Error("process.binding is not supported")},t.cwd=function(){return"/"},t.chdir=function(_){throw Error("process.chdir is not supported")},t.umask=function(){return 0}},{}],14:[function(_,$,e){arguments[4][6][0].apply(e,arguments)},{dup:6}],15:[function(_,$,e){arguments[4][7][0].apply(e,arguments)},{dup:7}],16:[function(_,$,e){arguments[4][8][0].apply(e,arguments)},{"./support/isBuffer":15,_process:13,dup:8,inherits:14}],17:[function(_,$,e){"use strict";var t,n=_("lodash"),r=_("events"),i=_("./reg.js"),u=_("./state.js").state,o=_("../data/ascii-identifier-data.js"),a=o.asciiIdentifierStartTable,s=o.asciiIdentifierPartTable,c=_("../data/non-ascii-identifier-start.js"),l=_("../data/non-ascii-identifier-part-only.js"),f={Identifier:1,Punctuator:2,NumericLiteral:3,StringLiteral:4,Comment:5,Keyword:6,RegExp:9,TemplateHead:10,TemplateMiddle:11,TemplateTail:12,NoSubstTemplate:13},d={Block:1,Template:2};function p(_){return/^[0-9a-fA-F]+$/.test(_)}function h(_){return 1===_.length&&p(_)}function v(_){var $=_;"string"==typeof $&&($=$.replace(/\r\n/g,"\n").replace(/\r/g,"\n").split("\n")),$[0]&&"#!"===$[0].substr(0,2)&&(-1!==$[0].indexOf("node")&&(u.option.node=!0),$[0]=""),this.emitter=new r.EventEmitter,this.source=_,this.setLines($),this.prereg=!0,this.line=0,this.char=1,this.from=1,this.input="",this.inComment=!1,this.context=[],this.templateStarts=[];for(var e=0;e0&&this.context[this.context.length-1].type===_},pushContext:function(_){this.context.push({type:_})},popContext:function(){return this.context.pop()},currentContext:function(){return this.context.length>0&&this.context[this.context.length-1]},getLines:function(){return this._lines=u.lines,this._lines},setLines:function(_){this._lines=_,u.lines=this._lines},peek:function(_){return this.input.charAt(_||0)},skip:function(_){_=_||1,this.char+=_,this.input=this.input.slice(_)},on:function(_,$){_.split(" ").forEach((function(_){this.emitter.on(_,$)}).bind(this))},trigger:function(){this.emitter.emit.apply(this.emitter,Array.prototype.slice.call(arguments))},triggerAsync:function(_,$,e,t){e.push((function(){t()&&this.trigger(_,$)}).bind(this))},scanPunctuator:function(){var _,$,e,t=this.peek();switch(t){case".":if(/^[0-9]$/.test(this.peek(1)))return null;if("."===this.peek(1)&&"."===this.peek(2))return{type:f.Punctuator,value:"..."};case"(":case")":case";":case",":case"[":case"]":case":":case"~":case"#":return{type:f.Punctuator,value:t};case"{":return this.pushContext(d.Block),{type:f.Punctuator,value:t};case"}":return this.inContext(d.Block)&&this.popContext(),{type:f.Punctuator,value:t};case"":return null}return(_=this.peek(1),$=this.peek(2),"?"===t)?"."!==_||i.decimalDigit.test($)?{type:f.Punctuator,value:"?"===_?"??":"?"}:{type:f.Punctuator,value:"?."}:(e=this.peek(3),">"===t&&">"===_&&">"===$&&"="===e)?{type:f.Punctuator,value:">>>="}:"="===t&&"="===_&&"="===$?{type:f.Punctuator,value:"==="}:"!"===t&&"="===_&&"="===$?{type:f.Punctuator,value:"!=="}:">"===t&&">"===_&&">"===$?{type:f.Punctuator,value:">>>"}:"<"===t&&"<"===_&&"="===$?{type:f.Punctuator,value:"<<="}:">"===t&&">"===_&&"="===$?{type:f.Punctuator,value:">>="}:"="===t&&">"===_?{type:f.Punctuator,value:t+_}:t===_&&"+-<>&|*".indexOf(t)>=0?"*"===t&&"="===$?{type:f.Punctuator,value:t+_+$}:{type:f.Punctuator,value:t+_}:"<>=!+-*%&|^/".indexOf(t)>=0?"="===_?{type:f.Punctuator,value:t+_}:{type:f.Punctuator,value:t}:null},scanComments:function(_){var $=this.peek(),e=this.peek(1),t=this.input.substr(2),n=this.line,r=this.char,u=this;function o(_,$,e){var t=!1,n=_+$,r="plain";return(e=e||{}).isMultiline&&(n+="*/"),$=$.replace(/\n/g," "),"/*"===_&&i.fallsThrough.test($)&&(t=!0,r="falls through"),["jshint","jshint.unstable","jslint","members","member","globals","global","exported"].forEach(function(e){if(!t&&("//"!==_||"jshint"===e||"jshint.unstable"===e)){" "===$.charAt(e.length)&&$.substr(0,e.length)===e&&(t=!0,_+=e,$=$.substr(e.length)),t||" "!==$.charAt(0)||" "!==$.charAt(e.length+1)||$.substr(1,e.length)!==e||(t=!0,_=_+" "+e,$=$.substr(e.length+1));var n=$.indexOf(e);if(!t&&n>=0&&" "===$.charAt(n+e.length)&&0===$.substr(0,n).trim().length&&(t=!0,$=$.substr(e.length+n)),t)switch(e){case"member":r="members";break;case"global":r="globals";break;default:var i=$.split(":").map(function(_){return _.replace(/^\s+/,"").replace(/\s+$/,"")});if(2===i.length&&"ignore"===i[0])switch(i[1]){case"start":u.ignoringLinterErrors=!0,t=!1;break;case"end":u.ignoringLinterErrors=!1,t=!1}r=e}}}),{type:f.Comment,commentType:r,value:n,body:$,isSpecial:t,isMalformed:e.isMalformed||!1}}if("*"===$&&"/"===e)return this.trigger("error",{code:"E018",line:n,character:r}),this.skip(2),null;if("/"!==$||"*"!==e&&"/"!==e)return null;if("/"===e)return this.skip(this.input.length),o("//",t);var a="";if("*"===e){for(this.inComment=!0,this.skip(2);"*"!==this.peek()||"/"!==this.peek(1);)if(""===this.peek()){if(a+="\n",!this.nextLine(_))return this.trigger("error",{code:"E017",line:n,character:r}),this.inComment=!1,o("/*",a,{isMultiline:!0,isMalformed:!0})}else a+=this.peek(),this.skip();return this.skip(2),this.inComment=!1,o("/*",a,{isMultiline:!0})}},scanKeyword:function(){var _=/^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input);return _&&["if","in","do","var","for","new","try","let","this","else","case","void","with","enum","while","break","catch","throw","const","yield","class","super","return","typeof","delete","switch","export","import","default","finally","extends","function","continue","debugger","instanceof","true","false","null","async","await"].indexOf(_[0])>=0?{type:f.Keyword,value:_[0]}:null},scanIdentifier:function($){var e,n,r,i="",o=0;function d(_){return c.indexOf(_)>-1}function h(_){return d(_)||l.indexOf(_)>-1}var v=(function(){if(o+=1,"u"!==this.peek(o))return null;var _,$=this.peek(o+1)+this.peek(o+2)+this.peek(o+3)+this.peek(o+4);return p($)&&(s[_=parseInt($,16)]||h(_))?(o+=5,"\\u"+$):null}).bind(this),g=(function(){var _=this.peek(o),$=_.charCodeAt(0);return 92===$?v():$<128?a[$]?(o+=1,_):null:d($)?(o+=1,_):null}).bind(this),m=(function(){var _=this.peek(o),$=_.charCodeAt(0);return 92===$?v():$<128?s[$]?(o+=1,_):null:h($)?(o+=1,_):null}).bind(this);if(null===(n=g()))return null;for(i=n;null!==(n=m());)i+=n;return r=(e=i).replace(/\\u([0-9a-fA-F]{4})/g,function(_,$){return String.fromCharCode(parseInt($,16))}),u.inES6(!0)||(t=_("../data/es5-identifier-names.js")).test(r)||this.triggerAsync("warning",{code:"W119",line:this.line,character:this.char,data:["unicode 8","6"]},$,function(){return!0}),{type:f.Identifier,value:r,text:i,tokenLength:i.length}},scanNumericLiteral:function(_){var $=0,e="",t=this.input.length,n=this.peek($),r=s,i=10,o=!1,a=!1;function s(_){return/^[0-9]$/.test(_)}function c(_){return/^[0-7]$/.test(_)}function l(_){return"8"===_||"9"===_}function d(_){return"$"===_||"_"===_||"\\"===_||_>="a"&&_<="z"||_>="A"&&_<="Z"}if("."!==n&&!s(n))return null;if("."!==n){for(e=this.peek($),$+=1,n=this.peek($),"0"===e&&(("x"===n||"X"===n)&&(r=h,i=16,$+=1,e+=n),("o"===n||"O"===n)&&(r=c,i=8,u.inES6(!0)||this.triggerAsync("warning",{code:"W119",line:this.line,character:this.char,data:["Octal integer literal","6"]},_,function(){return!0}),$+=1,e+=n),("b"===n||"B"===n)&&(r=function _($){return/^[01]$/.test($)},i=2,u.inES6(!0)||this.triggerAsync("warning",{code:"W119",line:this.line,character:this.char,data:["Binary integer literal","6"]},_,function(){return!0}),$+=1,e+=n),c(n)?(r=c,i=8,o=!0):s(n)&&(a=!0));$=0&&n<=7&&u.isStrict()});break;case"1":case"2":case"3":case"4":case"5":case"6":case"7":t="\\"+t,this.triggerAsync("warning",{code:"W115",line:this.line,character:this.char},_,function(){return u.isStrict()});break;case"u":var r=this.input.substr(1,4),i=parseInt(r,16);p(r)||this.trigger("warning",{code:"W052",line:this.line,character:this.char,data:["u"+r]}),t=String.fromCharCode(i),e=5;break;case"v":this.triggerAsync("warning",{code:"W114",line:this.line,character:this.char,data:["\\v"]},_,function(){return u.jsonMode}),t="\v";break;case"x":var o=parseInt(this.input.substr(1,2),16);this.triggerAsync("warning",{code:"W114",line:this.line,character:this.char,data:["\\x-"]},_,function(){return u.jsonMode}),t=String.fromCharCode(o),e=3;break;case"\\":t="\\\\";break;case"/":break;case"":$=!0,t=""}return{char:t,jump:e,allowNewLine:$}},scanTemplateLiteral:function(_){var $,e,t="",n=this.line,r=this.char,i=this.templateStarts.length;if("`"===this.peek())u.inES6(!0)||this.triggerAsync("warning",{code:"W119",line:this.line,character:this.char,data:["template literal syntax","6"]},_,function(){return!0}),$=f.TemplateHead,this.templateStarts.push({line:this.line,char:this.char}),i=this.templateStarts.length,this.skip(1),this.pushContext(d.Template);else{if(!this.inContext(d.Template)||"}"!==this.peek())return null;$=f.TemplateMiddle}for(;"`"!==this.peek();){for(;""===(e=this.peek());)if(t+="\n",!this.nextLine(_)){var o=this.templateStarts.pop();return this.trigger("error",{code:"E052",line:o.line,character:o.char}),{type:$,value:t,startLine:n,startChar:r,isUnclosed:!0,depth:i,context:this.popContext()}}if("$"===e&&"{"===this.peek(1))return t+="${",this.skip(2),{type:$,value:t,startLine:n,startChar:r,isUnclosed:!1,depth:i,context:this.currentContext()};if("\\"===e){var a=this.scanEscapeSequence(_);t+=a.char,this.skip(a.jump)}else"`"!==e&&(t+=e,this.skip(1))}return $=$===f.TemplateHead?f.NoSubstTemplate:f.TemplateTail,this.skip(1),this.templateStarts.pop(),{type:$,value:t,startLine:n,startChar:r,isUnclosed:!1,depth:i,context:this.popContext()}},scanStringLiteral:function(_){var $=this.peek();if('"'!==$&&"'"!==$)return null;this.triggerAsync("warning",{code:"W108",line:this.line,character:this.char},_,function(){return u.jsonMode&&'"'!==$});var e="",t=this.line,n=this.char,r=!1;for(this.skip();this.peek()!==$;)if(""===this.peek()){if(r?(r=!1,this.triggerAsync("warning",{code:"W043",line:this.line,character:this.char},_,function(){return!u.option.multistr}),this.triggerAsync("warning",{code:"W042",line:this.line,character:this.char},_,function(){return u.jsonMode&&u.option.multistr})):this.trigger("warning",{code:"W112",line:this.line,character:this.char}),!this.nextLine(_))return{type:f.StringLiteral,value:e,startLine:t,startChar:n,isUnclosed:!0,quote:$}}else{r=!1;var i=this.peek(),o=1;if(i<" "&&this.triggerAsync("warning",{code:"W113",line:this.line,character:this.char,data:[""]},_,function(){return!0}),"\\"===i){var a=this.scanEscapeSequence(_);i=a.char,o=a.jump,r=a.allowNewLine}""!==i&&(e+=i,this.skip(o))}return this.skip(),{type:f.StringLiteral,value:e,startLine:t,startChar:n,isUnclosed:!1,quote:$}},scanRegExp:function($){var e,t,n,r=0,o=this.input.length,a=this.peek(),s=a,c="",l=[],d="",h="",v=!1,g=!1,m=!1,y=!1,k=!1,x=!1,b="",E=function(){return d.indexOf("u")>-1},A=0,S=(function(){var e,t;if(r+=1,a=this.peek(r),i.nonzeroDigit.test(a)){for(t=a,e=this.peek(r+1);i.nonzeroDigit.test(e)||"0"===e;)r+=1,t+=a=e,c+=a,s+=a,e=this.peek(r+1);return l.push(Number(t)),t}if(b+=a,"u"===a&&"{"===this.peek(r+1)){var n=r+2;for(t="u{",e=this.peek(n);p(e);)t+=e,n+=1,e=this.peek(n);if("}"!==e)this.triggerAsync("error",{code:"E016",line:this.line,character:this.char,data:["Invalid Unicode escape sequence"]},$,E);else if(t.length>2)return t+="}",c+=t,s+=t,r=n+1,t}if("p"===a||"P"===a){var o=r+2;if(t="",e="","{"===this.peek(r+1))for(e=this.peek(o);e&&"}"!==e;)t+=e,o+=1,e=this.peek(o);if(t&&_("./validate-unicode-escape-sequence")(t)||this.triggerAsync("error",{code:"E016",line:this.line,character:this.char,data:["Invalid Unicode property escape sequence"]},$,E),t)return c+=t=a+"{"+t+"}",s+=t,r=o+1,u.inES9()||this.triggerAsync("warning",{code:"W119",line:this.line,character:this.char,data:["Unicode property escape","9"]},$,E),t}return a<" "&&(v=!0,this.triggerAsync("warning",{code:"W048",line:this.line,character:this.char},$,function(){return!0})),"<"===a?(v=!0,this.triggerAsync("warning",{code:"W049",line:this.line,character:this.char,data:[a]},$,function(){return!0})):"0"===a&&i.decimalDigit.test(this.peek(r+1))&&this.triggerAsync("error",{code:"E016",line:this.line,character:this.char,data:["Invalid decimal escape sequence"]},$,E),r+=1,c+=a,s+=a,a}).bind(this),C=(function(){var _,$=r,e="",t="";for(_=this.peek($+1);i.decimalDigit.test(_);)$+=1,e+=_,_=this.peek($+1);if(!e)return!1;if("}"===_)return!0;if(","!==_)return!1;for($+=1,_=this.peek($+1);i.decimalDigit.test(_);)$+=1,t+=_,_=this.peek($+1);return"}"===_&&(!t||Number(e)<=Number(t))}).bind(this),F=(function(_){return _.replace(/\\u\{([0-9a-fA-F]+)\}|\\u([a-fA-F0-9]{4})/g,(function(_,$,e){var t,n=parseInt($||e,16);if(n>1114111){v=!0,this.trigger("error",{code:"E016",line:this.line,character:this.char,data:[a]});return}return(t=String.fromCharCode(n),i.regexpSyntaxChars.test(t))?_:n<=65535?String.fromCharCode(n):"￿"}).bind(this)).replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,"￿")}).bind(this);if(!this.prereg||"/"!==a)return null;for(r+=1,t=!1;r$)return!0})||!e.split("").every(function(_){return"u"===_||"/"===_||"0"===_||t.regexpControlEscapes.test(_)||t.regexpCharClasses.test(_)||t.regexpSyntaxChars.test(_)})}(l,A,b,i)?n="Invalid escape":x&&(n="Invalid quantifier"),c=F(c)):"s"===a?(u.inES9()||this.triggerAsync("warning",{code:"W119",line:this.line,character:this.char,data:["DotAll RegExp flag","9"]},$,function(){return!0}),s.indexOf("s")>-1&&(n="Duplicate RegExp flag")):h+=a,d.indexOf(a)>-1&&(n="Duplicate RegExp flag"),d+=a,s+=a,d+=a,r+=1;-1===d.indexOf("u")&&this.triggerAsync("warning",{code:"W147",line:this.line,character:this.char},$,function(){return u.option.regexpu});try{RegExp(c,h)}catch(w){n=w.message}return n?(v=!0,this.trigger("error",{code:"E016",line:this.line,character:this.char,data:[n]})):d.indexOf("s")>-1&&!i.regexpDot.test(c)&&this.trigger("warning",{code:"W148",line:this.line,character:this.char}),{type:f.RegExp,value:s,isMalformed:v}},scanNonBreakingSpaces:function(){return u.option.nonbsp?this.input.search(/(\u00A0)/):-1},next:function(_){for(this.from=this.char;i.whitespace.test(this.peek());)this.from+=1,this.skip();var $=this.scanComments(_)||this.scanStringLiteral(_)||this.scanTemplateLiteral(_);return $||(($=this.scanRegExp(_)||this.scanPunctuator()||this.scanKeyword()||this.scanIdentifier(_)||this.scanNumericLiteral(_))?(this.skip($.tokenLength||$.value.length),$):null)},nextLine:function(_){if(this.line>=this.getLines().length)return!1;this.input=this.getLines()[this.line],this.line+=1,this.char=1,this.from=1;var $,e=this.input.trim(),t=function(){return n.some(arguments,function(_){return 0===e.indexOf(_)})};return!0!==this.ignoringLinterErrors||t("/*","//")||this.inComment&&function(){return n.some(arguments,function(_){return -1!==e.indexOf(_,e.length-_.length)})}("*/")||(this.input=""),($=this.scanNonBreakingSpaces())>=0&&this.triggerAsync("warning",{code:"W125",line:this.line,character:$+1},_,function(){return!0}),this.input=this.input.replace(/\t/g,u.tab),!this.ignoringLinterErrors&&u.option.maxlen&&u.option.maxlen=0;--$){var e=o[$]["(bindings)"];if(e[_])return e}}function x($,e){if("outer"===_.option.shadow)for(var t="global"===s["(type)"],n="functionparams"===u["(type)"],r=!t,i=0;i1?o[o.length-2]:null,d=u===s,p="functionparams"===u["(type)"],g="functionouter"===u["(type)"],k=u["(usages)"],x=u["(bindings)"],b=Object.keys(k);for(k.__proto__&&-1===b.indexOf("__proto__")&&b.push("__proto__"),$=0;$-1&&v("E069",$,$.value),d.push($.value)),_&&this.block.use(_.value,_)},initialize:function(_){u["(bindings)"][_]&&(u["(bindings)"][_]["(initialized)"]=!0)},addbinding:function($,n){var i=n.type,a=n.token,l="let"===i||"const"===i||"class"===i||"import"===i||"generator function"===i||"async function"===i||"async generator function"===i,f="function"===i||"generator function"===i||"async function"===i||"import"===i,d="global"===(l?u:s)["(type)"]&&t.has(e,$);if(x($,a),_.isStrict()&&("arguments"===$||"eval"===$)&&h("E008",a),l){var p=u["(bindings)"][$];p||u!==s||"global"===u["(type)"]||(p=!!s["(parent)"]["(bindings)"][$]),!p&&u["(usages)"][$]&&(u["(usages)"][$]["(onlyUsedSubFunction)"]||f?b(i,$,a):f||h("E056",a,$,i)),p&&(!f||"global"!==u["(type)"]||"import"===i)?h("E011",a,$):"outer"===_.option.shadow&&E.funct.has($)&&h("W004",a,$),E.block.add($,i,a,!d,n.initialized)}else{var v=E.funct.has($);!v&&function _($){for(var e=o.length-1;e>=0;e--){var t=o[e];if(t["(usages)"][$])return t["(usages)"][$];if(t===s)break}return!1}($)&&b(i,$,a),E.funct.has($,{onlyBlockscoped:!0})?h("E011",a,$):!0!==_.option.shadow&&v&&"__proto__"!==$&&"global"!==s["(type)"]&&h("W004",a,$),E.funct.add($,i,a,!d),"global"!==s["(type)"]||_.impliedClosure()||(c[$]=r)}},funct:{bindingtype:function(_,$){for(var e=$&&$.onlyBlockscoped,t=$&&$.excludeParams,n=o.length-($&&$.excludeCurrent?2:1),r=n;r>=0;r--){var i=o[r];if(i["(bindings)"][_]&&(!e||i["(bindings)"][_]["(blockscoped)"]))return i["(bindings)"][_]["(type)"];var u=t?o[r-1]:i;if(u&&"functionparams"===u["(type)"])break}return null},hasLabel:function(_){for(var $=o.length-1;$>=0;$--){var e=o[$];if(e["(labels)"][_])return!0;if("functionparams"===e["(type)"])break}return!1},has:function(_,$){return Boolean(this.bindingtype(_,$))},add:function(_,$,e,t){u["(bindings)"][_]={"(type)":$,"(token)":e,"(blockscoped)":!1,"(function)":s,"(unused)":t}}},block:{isGlobal:function(){return"global"===u["(type)"]},use:function($,e){var t=s["(parent)"];t&&t["(bindings)"][$]&&"param"===t["(bindings)"][$]["(type)"]&&!E.funct.has($,{excludeParams:!0,onlyBlockscoped:!0})&&(t["(bindings)"][$]["(unused)"]=!1),e&&(_.ignored.W117||!1===_.option.undef)&&(e.ignoreUndef=!0),g($),u["(usages)"][$]["(onlyUsedSubFunction)"]=!1,e&&(e["(function)"]=s,u["(usages)"][$]["(tokens)"].push(e));var n=u["(bindings)"][$];n&&n["(blockscoped)"]&&!n["(initialized)"]&&v("E056",e,$,n["(type)"])},reassign:function($,e){e.ignoreW020=_.ignored.W020,e.ignoreW021=_.ignored.W021,this.modify($,e),u["(usages)"][$]["(reassigned)"].push(e)},modify:function(_,$){g(_),u["(usages)"][_]["(onlyUsedSubFunction)"]=!1,u["(usages)"][_]["(modified)"].push($)},add:function(_,$,e,t,n){u["(bindings)"][_]={"(type)":$,"(token)":e,"(initialized)":!!n,"(blockscoped)":!0,"(unused)":t}},addLabel:function($,e){var t=e.token;E.funct.hasLabel($)?h("E011",t,$):"outer"===_.option.shadow&&(E.funct.has($)?h("W004",t,$):x($,t)),u["(labels)"][$]=t}}};return E};$.exports=i},{events:11,lodash:12}],24:[function(_,$,e){"use strict";var t=_("./name-stack.js");e.state={syntax:{},isStrict:function(){return!!this.directive["use strict"]||this.inClassBody||this.option.module||"implied"===this.option.strict},stmtMissingStrict:function(){return"global"===this.option.strict||!1!==this.option.strict&&!!this.option.globalstrict},allowsGlobalUsd:function(){return"global"===this.option.strict||this.option.globalstrict||this.option.module||this.impliedClosure()},impliedClosure:function(){return this.option.node||this.option.phantom||this.option.browserify},inMoz:function(){return this.option.moz},inES11:function(){return this.esVersion>=11},inES10:function(){return this.esVersion>=10},inES9:function(){return this.esVersion>=9},inES8:function(){return this.esVersion>=8},inES7:function(){return this.esVersion>=7},inES6:function(_){return!_&&!!this.option.moz||this.esVersion>=6},inES5:function(){return!this.esVersion||this.esVersion>=5||this.option.moz},inferEsVersion:function(){var _=null;if(this.option.esversion){if(this.option.es3?_="es3":this.option.es5?_="es5":this.option.esnext&&(_="esnext"),_)return _;2015===this.option.esversion?this.esVersion=6:this.esVersion=this.option.esversion}else this.option.es3?this.esVersion=3:this.option.esnext&&(this.esVersion=6);return null},reset:function(){this.tokens={prev:null,next:null,curr:null},this.option={unstable:{}},this.esVersion=5,this.funct=null,this.ignored={},this.directive=Object.create(null),this.jsonMode=!1,this.lines=[],this.tab="",this.cache={},this.ignoredLines={},this.forinifcheckneeded=!1,this.nameStack=new t,this.inClassBody=!1}}},{"./name-stack.js":19}],25:[function(_,$,e){"use strict";e.register=function(_){_.on("Identifier",function $(e){!_.getOption("proto")&&"__proto__"===e.name&&_.warn("W103",{line:e.line,char:e.char,data:[e.name,"6"]})}),_.on("Identifier",function $(e){!_.getOption("iterator")&&"__iterator__"===e.name&&_.warn("W103",{line:e.line,char:e.char,data:[e.name]})}),_.on("Identifier",function $(e){_.getOption("camelcase")&&e.name.replace(/^_+|_+$/g,"").indexOf("_")>-1&&!e.name.match(/^[A-Z0-9_]*$/)&&_.warn("W106",{line:e.line,char:e.char,data:[e.name]})}),_.on("String",function $(e){var t,n=_.getOption("quotmark");n&&("single"===n&&"'"!==e.quote&&(t="W109"),"double"===n&&'"'!==e.quote&&(t="W108"),!0===n&&(_.getCache("quotmark")||_.setCache("quotmark",e.quote),_.getCache("quotmark")!==e.quote&&(t="W110")),t&&_.warn(t,{line:e.line,char:e.char}))}),_.on("Number",function $(e){"."===e.value.charAt(0)&&_.warn("W008",{line:e.line,char:e.char,data:[e.value]}),"."===e.value.substr(e.value.length-1)&&_.warn("W047",{line:e.line,char:e.char,data:[e.value]}),/^00+/.test(e.value)&&_.warn("W046",{line:e.line,char:e.char,data:[e.value]})}),_.on("String",function $(e){!_.getOption("scripturl")&&/^(?:javascript|jscript|ecmascript|vbscript|livescript)\s*:/i.test(e.value)&&_.warn("W107",{line:e.line,char:e.char})})}},{}],26:[function(_,$,e){"use strict";$.exports=function _($){var e=$.indexOf("=");if(-1===e)return $ in t.binary||$ in n.general;var r=$.substr(0,e),i=$.substr(e+1);return"General_Category"===r||"gc"===r?i in n.general:("Script"===r||"sc"===r||"Script_Extensions"===r||"scx"===r)&&i in n.script};var t={nonBinary:Object.create(null),binary:Object.create(null)},n={general:Object.create(null),script:Object.create(null)},r=t.nonBinary;r.General_Category=!0,r.gc=!0,r.Script=!0,r.sc=!0,r.Script_Extensions=!0,r.scx=!0;var i=t.binary;i.ASCII=!0,i.ASCII_Hex_Digit=!0,i.AHex=!0,i.Alphabetic=!0,i.Alpha=!0,i.Any=!0,i.Assigned=!0,i.Bidi_Control=!0,i.Bidi_C=!0,i.Bidi_Mirrored=!0,i.Bidi_M=!0,i.Case_Ignorable=!0,i.CI=!0,i.Cased=!0,i.Changes_When_Casefolded=!0,i.CWCF=!0,i.Changes_When_Casemapped=!0,i.CWCM=!0,i.Changes_When_Lowercased=!0,i.CWL=!0,i.Changes_When_NFKC_Casefolded=!0,i.CWKCF=!0,i.Changes_When_Titlecased=!0,i.CWT=!0,i.Changes_When_Uppercased=!0,i.CWU=!0,i.Dash=!0,i.Default_Ignorable_Code_Point=!0,i.DI=!0,i.Deprecated=!0,i.Dep=!0,i.Diacritic=!0,i.Dia=!0,i.Emoji=!0,i.Emoji_Component=!0,i.EComp=!0,i.Emoji_Modifier=!0,i.EMod=!0,i.Emoji_Modifier_Base=!0,i.EBase=!0,i.Emoji_Presentation=!0,i.EPres=!0,i.Extended_Pictographic=!0,i.ExtPict=!0,i.Extender=!0,i.Ext=!0,i.Grapheme_Base=!0,i.Gr_Base=!0,i.Grapheme_Extend=!0,i.Gr_Ext=!0,i.Hex_Digit=!0,i.Hex=!0,i.IDS_Binary_Operator=!0,i.IDSB=!0,i.IDS_Trinary_Operator=!0,i.IDST=!0,i.ID_Continue=!0,i.IDC=!0,i.ID_Start=!0,i.IDS=!0,i.Ideographic=!0,i.Ideo=!0,i.Join_Control=!0,i.Join_C=!0,i.Logical_Order_Exception=!0,i.LOE=!0,i.Lowercase=!0,i.Lower=!0,i.Math=!0,i.Noncharacter_Code_Point=!0,i.NChar=!0,i.Pattern_Syntax=!0,i.Pat_Syn=!0,i.Pattern_White_Space=!0,i.Pat_WS=!0,i.Quotation_Mark=!0,i.QMark=!0,i.Radical=!0,i.Regional_Indicator=!0,i.RI=!0,i.Sentence_Terminal=!0,i.STerm=!0,i.Soft_Dotted=!0,i.SD=!0,i.Terminal_Punctuation=!0,i.Term=!0,i.Unified_Ideograph=!0,i.UIdeo=!0,i.Uppercase=!0,i.Upper=!0,i.Variation_Selector=!0,i.VS=!0,i.White_Space=!0,i.space=!0,i.XID_Continue=!0,i.XIDC=!0,i.XID_Start=!0,i.XIDS=!0;var u=n.general;u.Cased_Letter=!0,u.LC=!0,u.Close_Punctuation=!0,u.Pe=!0,u.Connector_Punctuation=!0,u.Pc=!0,u.Control=!0,u.Cc=!0,u.cntrl=!0,u.Currency_Symbol=!0,u.Sc=!0,u.Dash_Punctuation=!0,u.Pd=!0,u.Decimal_Number=!0,u.Nd=!0,u.digit=!0,u.Enclosing_Mark=!0,u.Me=!0,u.Final_Punctuation=!0,u.Pf=!0,u.Format=!0,u.Cf=!0,u.Initial_Punctuation=!0,u.Pi=!0,u.Letter=!0,u.L=!0,u.Letter_Number=!0,u.Nl=!0,u.Line_Separator=!0,u.Zl=!0,u.Lowercase_Letter=!0,u.Ll=!0,u.Mark=!0,u.M=!0,u.Combining_Mark=!0,u.Math_Symbol=!0,u.Sm=!0,u.Modifier_Letter=!0,u.Lm=!0,u.Modifier_Symbol=!0,u.Sk=!0,u.Nonspacing_Mark=!0,u.Mn=!0,u.Number=!0,u.N=!0,u.Open_Punctuation=!0,u.Ps=!0,u.Other=!0,u.C=!0,u.Other_Letter=!0,u.Lo=!0,u.Other_Number=!0,u.No=!0,u.Other_Punctuation=!0,u.Po=!0,u.Other_Symbol=!0,u.So=!0,u.Paragraph_Separator=!0,u.Zp=!0,u.Private_Use=!0,u.Co=!0,u.Punctuation=!0,u.P=!0,u.punct=!0,u.Separator=!0,u.Z=!0,u.Space_Separator=!0,u.Zs=!0,u.Spacing_Mark=!0,u.Mc=!0,u.Surrogate=!0,u.Cs=!0,u.Symbol=!0,u.S=!0,u.Titlecase_Letter=!0,u.Lt=!0,u.Unassigned=!0,u.Cn=!0,u.Uppercase_Letter=!0,u.Lu=!0;var o=n.script;o.Adlam=!0,o.Adlm=!0,o.Ahom=!0,o.Anatolian_Hieroglyphs=!0,o.Hluw=!0,o.Arabic=!0,o.Arab=!0,o.Armenian=!0,o.Armn=!0,o.Avestan=!0,o.Avst=!0,o.Balinese=!0,o.Bali=!0,o.Bamum=!0,o.Bamu=!0,o.Bassa_Vah=!0,o.Bass=!0,o.Batak=!0,o.Batk=!0,o.Bengali=!0,o.Beng=!0,o.Bhaiksuki=!0,o.Bhks=!0,o.Bopomofo=!0,o.Bopo=!0,o.Brahmi=!0,o.Brah=!0,o.Braille=!0,o.Brai=!0,o.Buginese=!0,o.Bugi=!0,o.Buhid=!0,o.Buhd=!0,o.Canadian_Aboriginal=!0,o.Cans=!0,o.Carian=!0,o.Cari=!0,o.Caucasian_Albanian=!0,o.Aghb=!0,o.Chakma=!0,o.Cakm=!0,o.Cham=!0,o.Chorasmian=!0,o.Chrs=!0,o.Cherokee=!0,o.Cher=!0,o.Common=!0,o.Zyyy=!0,o.Coptic=!0,o.Copt=!0,o.Qaac=!0,o.Cuneiform=!0,o.Xsux=!0,o.Cypriot=!0,o.Cprt=!0,o.Cyrillic=!0,o.Cyrl=!0,o.Deseret=!0,o.Dsrt=!0,o.Devanagari=!0,o.Deva=!0,o.Dives_Akuru=!0,o.Diak=!0,o.Dogra=!0,o.Dogr=!0,o.Duployan=!0,o.Dupl=!0,o.Egyptian_Hieroglyphs=!0,o.Egyp=!0,o.Elbasan=!0,o.Elba=!0,o.Elymaic=!0,o.Elym=!0,o.Ethiopic=!0,o.Ethi=!0,o.Georgian=!0,o.Geor=!0,o.Glagolitic=!0,o.Glag=!0,o.Gothic=!0,o.Goth=!0,o.Grantha=!0,o.Gran=!0,o.Greek=!0,o.Grek=!0,o.Gujarati=!0,o.Gujr=!0,o.Gunjala_Gondi=!0,o.Gong=!0,o.Gurmukhi=!0,o.Guru=!0,o.Han=!0,o.Hani=!0,o.Hangul=!0,o.Hang=!0,o.Hanifi_Rohingya=!0,o.Rohg=!0,o.Hanunoo=!0,o.Hano=!0,o.Hatran=!0,o.Hatr=!0,o.Hebrew=!0,o.Hebr=!0,o.Hiragana=!0,o.Hira=!0,o.Imperial_Aramaic=!0,o.Armi=!0,o.Inherited=!0,o.Zinh=!0,o.Qaai=!0,o.Inscriptional_Pahlavi=!0,o.Phli=!0,o.Inscriptional_Parthian=!0,o.Prti=!0,o.Javanese=!0,o.Java=!0,o.Kaithi=!0,o.Kthi=!0,o.Kannada=!0,o.Knda=!0,o.Katakana=!0,o.Kana=!0,o.Kayah_Li=!0,o.Kali=!0,o.Kharoshthi=!0,o.Khar=!0,o.Khitan_Small_Script=!0,o.Kits=!0,o.Khmer=!0,o.Khmr=!0,o.Khojki=!0,o.Khoj=!0,o.Khudawadi=!0,o.Sind=!0,o.Lao=!0,o.Laoo=!0,o.Latin=!0,o.Latn=!0,o.Lepcha=!0,o.Lepc=!0,o.Limbu=!0,o.Limb=!0,o.Linear_A=!0,o.Lina=!0,o.Linear_B=!0,o.Linb=!0,o.Lisu=!0,o.Lycian=!0,o.Lyci=!0,o.Lydian=!0,o.Lydi=!0,o.Mahajani=!0,o.Mahj=!0,o.Makasar=!0,o.Maka=!0,o.Malayalam=!0,o.Mlym=!0,o.Mandaic=!0,o.Mand=!0,o.Manichaean=!0,o.Mani=!0,o.Marchen=!0,o.Marc=!0,o.Medefaidrin=!0,o.Medf=!0,o.Masaram_Gondi=!0,o.Gonm=!0,o.Meetei_Mayek=!0,o.Mtei=!0,o.Mende_Kikakui=!0,o.Mend=!0,o.Meroitic_Cursive=!0,o.Merc=!0,o.Meroitic_Hieroglyphs=!0,o.Mero=!0,o.Miao=!0,o.Plrd=!0,o.Modi=!0,o.Mongolian=!0,o.Mong=!0,o.Mro=!0,o.Mroo=!0,o.Multani=!0,o.Mult=!0,o.Myanmar=!0,o.Mymr=!0,o.Nabataean=!0,o.Nbat=!0,o.Nandinagari=!0,o.Nand=!0,o.New_Tai_Lue=!0,o.Talu=!0,o.Newa=!0,o.Nko=!0,o.Nkoo=!0,o.Nushu=!0,o.Nshu=!0,o.Nyiakeng_Puachue_Hmong=!0,o.Hmnp=!0,o.Ogham=!0,o.Ogam=!0,o.Ol_Chiki=!0,o.Olck=!0,o.Old_Hungarian=!0,o.Hung=!0,o.Old_Italic=!0,o.Ital=!0,o.Old_North_Arabian=!0,o.Narb=!0,o.Old_Permic=!0,o.Perm=!0,o.Old_Persian=!0,o.Xpeo=!0,o.Old_Sogdian=!0,o.Sogo=!0,o.Old_South_Arabian=!0,o.Sarb=!0,o.Old_Turkic=!0,o.Orkh=!0,o.Oriya=!0,o.Orya=!0,o.Osage=!0,o.Osge=!0,o.Osmanya=!0,o.Osma=!0,o.Pahawh_Hmong=!0,o.Hmng=!0,o.Palmyrene=!0,o.Palm=!0,o.Pau_Cin_Hau=!0,o.Pauc=!0,o.Phags_Pa=!0,o.Phag=!0,o.Phoenician=!0,o.Phnx=!0,o.Psalter_Pahlavi=!0,o.Phlp=!0,o.Rejang=!0,o.Rjng=!0,o.Runic=!0,o.Runr=!0,o.Samaritan=!0,o.Samr=!0,o.Saurashtra=!0,o.Saur=!0,o.Sharada=!0,o.Shrd=!0,o.Shavian=!0,o.Shaw=!0,o.Siddham=!0,o.Sidd=!0,o.SignWriting=!0,o.Sgnw=!0,o.Sinhala=!0,o.Sinh=!0,o.Sogdian=!0,o.Sogd=!0,o.Sora_Sompeng=!0,o.Sora=!0,o.Soyombo=!0,o.Soyo=!0,o.Sundanese=!0,o.Sund=!0,o.Syloti_Nagri=!0,o.Sylo=!0,o.Syriac=!0,o.Syrc=!0,o.Tagalog=!0,o.Tglg=!0,o.Tagbanwa=!0,o.Tagb=!0,o.Tai_Le=!0,o.Tale=!0,o.Tai_Tham=!0,o.Lana=!0,o.Tai_Viet=!0,o.Tavt=!0,o.Takri=!0,o.Takr=!0,o.Tamil=!0,o.Taml=!0,o.Tangut=!0,o.Tang=!0,o.Telugu=!0,o.Telu=!0,o.Thaana=!0,o.Thaa=!0,o.Thai=!0,o.Tibetan=!0,o.Tibt=!0,o.Tifinagh=!0,o.Tfng=!0,o.Tirhuta=!0,o.Tirh=!0,o.Ugaritic=!0,o.Ugar=!0,o.Vai=!0,o.Vaii=!0,o.Wancho=!0,o.Wcho=!0,o.Warang_Citi=!0,o.Wara=!0,o.Yezidi=!0,o.Yezi=!0,o.Yi=!0,o.Yiii=!0,o.Zanabazar_Square=!0,o.Zanb=!0},{}],27:[function(_,$,e){"use strict";e.reservedVars={NaN:!1,undefined:!1},e.ecmaIdentifiers={3:{Array:!1,Boolean:!1,Date:!1,decodeURI:!1,decodeURIComponent:!1,encodeURI:!1,encodeURIComponent:!1,Error:!1,eval:!1,EvalError:!1,Function:!1,hasOwnProperty:!1,Infinity:!1,isFinite:!1,isNaN:!1,Math:!1,Number:!1,Object:!1,parseInt:!1,parseFloat:!1,RangeError:!1,ReferenceError:!1,RegExp:!1,String:!1,SyntaxError:!1,TypeError:!1,URIError:!1},5:{JSON:!1},6:{ArrayBuffer:!1,DataView:!1,Float32Array:!1,Float64Array:!1,Int8Array:!1,Int16Array:!1,Int32Array:!1,Map:!1,Promise:!1,Proxy:!1,Reflect:!1,Set:!1,Symbol:!1,Uint8Array:!1,Uint16Array:!1,Uint32Array:!1,Uint8ClampedArray:!1,WeakMap:!1,WeakSet:!1},8:{Atomics:!1,SharedArrayBuffer:!1},11:{BigInt:!1,globalThis:!1}},e.browser={Audio:!1,Blob:!1,addEventListener:!1,applicationCache:!1,atob:!1,blur:!1,btoa:!1,cancelAnimationFrame:!1,CanvasGradient:!1,CanvasPattern:!1,CanvasRenderingContext2D:!1,CSS:!1,CSSImportRule:!1,CSSGroupingRule:!1,CSSMarginRule:!1,CSSMediaRule:!1,CSSNamespaceRule:!1,CSSPageRule:!1,CSSRule:!1,CSSRuleList:!1,CSSStyleDeclaration:!1,CSSStyleRule:!1,CSSStyleSheet:!1,clearInterval:!1,clearTimeout:!1,close:!1,closed:!1,Comment:!1,CompositionEvent:!1,createImageBitmap:!1,CustomEvent:!1,DOMParser:!1,defaultStatus:!1,dispatchEvent:!1,Document:!1,document:!1,DocumentFragment:!1,Element:!1,ElementTimeControl:!1,Event:!1,event:!1,fetch:!1,File:!1,FileList:!1,FileReader:!1,FormData:!1,focus:!1,frames:!1,getComputedStyle:!1,Headers:!1,HTMLAnchorElement:!1,HTMLAreaElement:!1,HTMLAudioElement:!1,HTMLBaseElement:!1,HTMLBlockquoteElement:!1,HTMLBodyElement:!1,HTMLBRElement:!1,HTMLButtonElement:!1,HTMLCanvasElement:!1,HTMLCollection:!1,HTMLDataElement:!1,HTMLDataListElement:!1,HTMLDetailsElement:!1,HTMLDialogElement:!1,HTMLDirectoryElement:!1,HTMLDivElement:!1,HTMLDListElement:!1,HTMLElement:!1,HTMLEmbedElement:!1,HTMLFieldSetElement:!1,HTMLFontElement:!1,HTMLFormElement:!1,HTMLFrameElement:!1,HTMLFrameSetElement:!1,HTMLHeadElement:!1,HTMLHeadingElement:!1,HTMLHRElement:!1,HTMLHtmlElement:!1,HTMLIFrameElement:!1,HTMLImageElement:!1,HTMLInputElement:!1,HTMLIsIndexElement:!1,HTMLLabelElement:!1,HTMLLayerElement:!1,HTMLLegendElement:!1,HTMLLIElement:!1,HTMLLinkElement:!1,HTMLMapElement:!1,HTMLMarqueeElement:!1,HTMLMediaElement:!1,HTMLMenuElement:!1,HTMLMetaElement:!1,HTMLMeterElement:!1,HTMLModElement:!1,HTMLObjectElement:!1,HTMLOListElement:!1,HTMLOptGroupElement:!1,HTMLOptionElement:!1,HTMLParagraphElement:!1,HTMLParamElement:!1,HTMLPictureElement:!1,HTMLPreElement:!1,HTMLProgressElement:!1,HTMLQuoteElement:!1,HTMLScriptElement:!1,HTMLSelectElement:!1,HTMLSlotElement:!1,HTMLSourceElement:!1,HTMLStyleElement:!1,HTMLTableCaptionElement:!1,HTMLTableCellElement:!1,HTMLTableColElement:!1,HTMLTableElement:!1,HTMLTableRowElement:!1,HTMLTableSectionElement:!1,HTMLTemplateElement:!1,HTMLTextAreaElement:!1,HTMLTimeElement:!1,HTMLTitleElement:!1,HTMLTrackElement:!1,HTMLUListElement:!1,HTMLVideoElement:!1,history:!1,Image:!1,IntersectionObserver:!1,Intl:!1,length:!1,localStorage:!1,location:!1,matchMedia:!1,MediaList:!1,MediaRecorder:!1,MessageChannel:!1,MessageEvent:!1,MessagePort:!1,MouseEvent:!1,moveBy:!1,moveTo:!1,MutationObserver:!1,name:!1,Node:!1,NodeFilter:!1,NodeList:!1,Notification:!1,navigator:!1,onbeforeunload:!0,onblur:!0,onerror:!0,onfocus:!0,onload:!0,onresize:!0,onunload:!0,open:!1,openDatabase:!1,opener:!1,Option:!1,origin:!1,parent:!1,performance:!1,print:!1,queueMicrotask:!1,Range:!1,requestAnimationFrame:!1,removeEventListener:!1,Request:!1,resizeBy:!1,resizeTo:!1,Response:!1,screen:!1,scroll:!1,scrollBy:!1,scrollTo:!1,sessionStorage:!1,setInterval:!1,setTimeout:!1,SharedWorker:!1,status:!1,Storage:!1,StyleSheet:!1,SVGAElement:!1,SVGAltGlyphDefElement:!1,SVGAltGlyphElement:!1,SVGAltGlyphItemElement:!1,SVGAngle:!1,SVGAnimateColorElement:!1,SVGAnimateElement:!1,SVGAnimateMotionElement:!1,SVGAnimateTransformElement:!1,SVGAnimatedAngle:!1,SVGAnimatedBoolean:!1,SVGAnimatedEnumeration:!1,SVGAnimatedInteger:!1,SVGAnimatedLength:!1,SVGAnimatedLengthList:!1,SVGAnimatedNumber:!1,SVGAnimatedNumberList:!1,SVGAnimatedPathData:!1,SVGAnimatedPoints:!1,SVGAnimatedPreserveAspectRatio:!1,SVGAnimatedRect:!1,SVGAnimatedString:!1,SVGAnimatedTransformList:!1,SVGAnimationElement:!1,SVGCSSRule:!1,SVGCircleElement:!1,SVGClipPathElement:!1,SVGColor:!1,SVGColorProfileElement:!1,SVGColorProfileRule:!1,SVGComponentTransferFunctionElement:!1,SVGCursorElement:!1,SVGDefsElement:!1,SVGDescElement:!1,SVGDocument:!1,SVGElement:!1,SVGElementInstance:!1,SVGElementInstanceList:!1,SVGEllipseElement:!1,SVGExternalResourcesRequired:!1,SVGFEBlendElement:!1,SVGFEColorMatrixElement:!1,SVGFEComponentTransferElement:!1,SVGFECompositeElement:!1,SVGFEConvolveMatrixElement:!1,SVGFEDiffuseLightingElement:!1,SVGFEDisplacementMapElement:!1,SVGFEDistantLightElement:!1,SVGFEFloodElement:!1,SVGFEFuncAElement:!1,SVGFEFuncBElement:!1,SVGFEFuncGElement:!1,SVGFEFuncRElement:!1,SVGFEGaussianBlurElement:!1,SVGFEImageElement:!1,SVGFEMergeElement:!1,SVGFEMergeNodeElement:!1,SVGFEMorphologyElement:!1,SVGFEOffsetElement:!1,SVGFEPointLightElement:!1,SVGFESpecularLightingElement:!1,SVGFESpotLightElement:!1,SVGFETileElement:!1,SVGFETurbulenceElement:!1,SVGFilterElement:!1,SVGFilterPrimitiveStandardAttributes:!1,SVGFitToViewBox:!1,SVGFontElement:!1,SVGFontFaceElement:!1,SVGFontFaceFormatElement:!1,SVGFontFaceNameElement:!1,SVGFontFaceSrcElement:!1,SVGFontFaceUriElement:!1,SVGForeignObjectElement:!1,SVGGElement:!1,SVGGlyphElement:!1,SVGGlyphRefElement:!1,SVGGradientElement:!1,SVGHKernElement:!1,SVGICCColor:!1,SVGImageElement:!1,SVGLangSpace:!1,SVGLength:!1,SVGLengthList:!1,SVGLineElement:!1,SVGLinearGradientElement:!1,SVGLocatable:!1,SVGMPathElement:!1,SVGMarkerElement:!1,SVGMaskElement:!1,SVGMatrix:!1,SVGMetadataElement:!1,SVGMissingGlyphElement:!1,SVGNumber:!1,SVGNumberList:!1,SVGPaint:!1,SVGPathElement:!1,SVGPathSeg:!1,SVGPathSegArcAbs:!1,SVGPathSegArcRel:!1,SVGPathSegClosePath:!1,SVGPathSegCurvetoCubicAbs:!1,SVGPathSegCurvetoCubicRel:!1,SVGPathSegCurvetoCubicSmoothAbs:!1,SVGPathSegCurvetoCubicSmoothRel:!1,SVGPathSegCurvetoQuadraticAbs:!1,SVGPathSegCurvetoQuadraticRel:!1,SVGPathSegCurvetoQuadraticSmoothAbs:!1,SVGPathSegCurvetoQuadraticSmoothRel:!1,SVGPathSegLinetoAbs:!1,SVGPathSegLinetoHorizontalAbs:!1,SVGPathSegLinetoHorizontalRel:!1,SVGPathSegLinetoRel:!1,SVGPathSegLinetoVerticalAbs:!1,SVGPathSegLinetoVerticalRel:!1,SVGPathSegList:!1,SVGPathSegMovetoAbs:!1,SVGPathSegMovetoRel:!1,SVGPatternElement:!1,SVGPoint:!1,SVGPointList:!1,SVGPolygonElement:!1,SVGPolylineElement:!1,SVGPreserveAspectRatio:!1,SVGRadialGradientElement:!1,SVGRect:!1,SVGRectElement:!1,SVGRenderingIntent:!1,SVGSVGElement:!1,SVGScriptElement:!1,SVGSetElement:!1,SVGStopElement:!1,SVGStringList:!1,SVGStylable:!1,SVGStyleElement:!1,SVGSwitchElement:!1,SVGSymbolElement:!1,SVGTRefElement:!1,SVGTSpanElement:!1,SVGTests:!1,SVGTextContentElement:!1,SVGTextElement:!1,SVGTextPathElement:!1,SVGTextPositioningElement:!1,SVGTitleElement:!1,SVGTransform:!1,SVGTransformList:!1,SVGTransformable:!1,SVGURIReference:!1,SVGUnitTypes:!1,SVGUseElement:!1,SVGVKernElement:!1,SVGViewElement:!1,SVGViewSpec:!1,SVGZoomAndPan:!1,Text:!1,TextDecoder:!1,TextEncoder:!1,TimeEvent:!1,top:!1,URL:!1,URLSearchParams:!1,WebGLActiveInfo:!1,WebGLBuffer:!1,WebGLContextEvent:!1,WebGLFramebuffer:!1,WebGLProgram:!1,WebGLRenderbuffer:!1,WebGLRenderingContext:!1,WebGLShader:!1,WebGLShaderPrecisionFormat:!1,WebGLTexture:!1,WebGLUniformLocation:!1,WebSocket:!1,window:!1,Window:!1,Worker:!1,XDomainRequest:!1,XMLDocument:!1,XMLHttpRequest:!1,XMLSerializer:!1,XPathEvaluator:!1,XPathException:!1,XPathExpression:!1,XPathNamespace:!1,XPathNSResolver:!1,XPathResult:!1},e.devel={alert:!1,confirm:!1,console:!1,Debug:!1,opera:!1,prompt:!1},e.worker={addEventListener:!0,atob:!0,btoa:!0,clearInterval:!0,clearTimeout:!0,createImageBitmap:!0,dispatchEvent:!0,importScripts:!0,onmessage:!0,origin:!0,postMessage:!0,queueMicrotask:!0,removeEventListener:!0,self:!0,setInterval:!0,setTimeout:!0,FileReaderSync:!0},e.nonstandard={escape:!1,unescape:!1},e.couch={require:!1,respond:!1,getRow:!1,emit:!1,send:!1,start:!1,sum:!1,log:!1,exports:!1,module:!1,provides:!1},e.node={__filename:!1,__dirname:!1,arguments:!1,GLOBAL:!1,global:!1,module:!1,require:!1,Intl:!1,Buffer:!0,console:!0,exports:!0,process:!0,setTimeout:!0,clearTimeout:!0,setInterval:!0,clearInterval:!0,setImmediate:!0,clearImmediate:!0,URL:!0,URLSearchParams:!0},e.browserify={__filename:!1,__dirname:!1,global:!1,module:!1,require:!1,Buffer:!0,exports:!0,process:!0},e.phantom={phantom:!0,require:!0,WebPage:!0,console:!0,exports:!0},e.qunit={asyncTest:!1,deepEqual:!1,equal:!1,expect:!1,module:!1,notDeepEqual:!1,notEqual:!1,notOk:!1,notPropEqual:!1,notStrictEqual:!1,ok:!1,propEqual:!1,QUnit:!1,raises:!1,start:!1,stop:!1,strictEqual:!1,test:!1,throws:!1},e.rhino={arguments:!1,defineClass:!1,deserialize:!1,gc:!1,help:!1,importClass:!1,importPackage:!1,java:!1,load:!1,loadClass:!1,Packages:!1,print:!1,quit:!1,readFile:!1,readUrl:!1,runCommand:!1,seal:!1,serialize:!1,spawn:!1,sync:!1,toint32:!1,version:!1},e.shelljs={target:!1,echo:!1,exit:!1,cd:!1,pwd:!1,ls:!1,find:!1,cp:!1,rm:!1,mv:!1,mkdir:!1,test:!1,cat:!1,sed:!1,grep:!1,which:!1,dirs:!1,pushd:!1,popd:!1,env:!1,exec:!1,chmod:!1,config:!1,error:!1,tempdir:!1},e.typed={ArrayBuffer:!1,ArrayBufferView:!1,DataView:!1,Float32Array:!1,Float64Array:!1,Int16Array:!1,Int32Array:!1,Int8Array:!1,Uint16Array:!1,Uint32Array:!1,Uint8Array:!1,Uint8ClampedArray:!1},e.wsh={ActiveXObject:!0,Enumerator:!0,GetObject:!0,ScriptEngine:!0,ScriptEngineBuildVersion:!0,ScriptEngineMajorVersion:!0,ScriptEngineMinorVersion:!0,VBArray:!0,WSH:!0,WScript:!0,XDomainRequest:!0},e.dojo={dojo:!1,dijit:!1,dojox:!1,define:!1,require:!1},e.jquery={$:!1,jQuery:!1},e.mootools={$:!1,$$:!1,Asset:!1,Browser:!1,Chain:!1,Class:!1,Color:!1,Cookie:!1,Core:!1,Document:!1,DomReady:!1,DOMEvent:!1,DOMReady:!1,Drag:!1,Element:!1,Elements:!1,Event:!1,Events:!1,Fx:!1,Group:!1,Hash:!1,HtmlTable:!1,IFrame:!1,IframeShim:!1,InputValidator:!1,instanceOf:!1,Keyboard:!1,Locale:!1,Mask:!1,MooTools:!1,Native:!1,Options:!1,OverText:!1,Request:!1,Scroller:!1,Slick:!1,Slider:!1,Sortables:!1,Spinner:!1,Swiff:!1,Tips:!1,Type:!1,typeOf:!1,URI:!1,Window:!1},e.prototypejs={$:!1,$$:!1,$A:!1,$F:!1,$H:!1,$R:!1,$break:!1,$continue:!1,$w:!1,Abstract:!1,Ajax:!1,Class:!1,Enumerable:!1,Element:!1,Event:!1,Field:!1,Form:!1,Hash:!1,Insertion:!1,ObjectRange:!1,PeriodicalExecuter:!1,Position:!1,Prototype:!1,Selector:!1,Template:!1,Toggle:!1,Try:!1,Autocompleter:!1,Builder:!1,Control:!1,Draggable:!1,Draggables:!1,Droppables:!1,Effect:!1,Sortable:!1,SortableObserver:!1,Sound:!1,Scriptaculous:!1},e.yui={YUI:!1,Y:!1,YUI_config:!1},e.mocha={mocha:!1,describe:!1,xdescribe:!1,context:!1,xcontext:!1,it:!1,xit:!1,specify:!1,xspecify:!1,before:!1,after:!1,beforeEach:!1,afterEach:!1,suite:!1,test:!1,setup:!1,teardown:!1,suiteSetup:!1,suiteTeardown:!1},e.jasmine={jasmine:!1,describe:!1,xdescribe:!1,it:!1,xit:!1,beforeEach:!1,afterEach:!1,setFixtures:!1,loadFixtures:!1,spyOn:!1,expect:!1,runs:!1,waitsFor:!1,waits:!1,beforeAll:!1,afterAll:!1,fail:!1,fdescribe:!1,fit:!1,pending:!1,spyOnProperty:!1}},{}],jshint:[function(_,$,e){/*! - * JSHint, by JSHint Community. - * - * Licensed under the MIT license. - * - * JSHint is a derivative work of JSLint: - * - * Copyright (c) 2002 Douglas Crockford (www.JSLint.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. - * - */ var t=_("lodash"),n=_("events"),r=_("./vars.js"),i=_("./messages.js"),u=_("./lex.js").Lexer,o=_("./reg.js"),a=_("./state.js").state,s=_("./style.js"),c=_("./options.js"),l=_("./scope-manager.js"),f=_("./prod-params.js");_("console-browserify");var d=function(){"use strict";var _,$,e,p,h,v,g,m,y,k,x={"<":!0,"<=":!0,"==":!0,"===":!0,"!==":!0,"!=":!0,">":!0,">=":!0,"+":!0,"-":!0,"*":!0,"/":!0,"%":!0},b=[],E=new n.EventEmitter;function A(_,$,e){var n,r,i,u,o,a,s,l="E001";return $?(n="",r=c.validNames):(n="unstable ",r=c.unstableNames),_=_.trim(),!!/^[+-]W\d{3}$/g.test(_)||!!(-1!==r.indexOf(_)||"jslint"===e.type||t.has(c.removed,_))||(i=e,u=n,L(l,i,u,o=_,a,s),!1)}function S(_,$){return!!_&&!!_.identifier&&_.value===$}function C(_,$){if(!$.reserved)return!1;var e=$.meta;if(e&&e.isFutureReservedWord){if(a.inES5()&&(!e.es5||$.isProperty))return!1}else if(e&&e.es5&&!a.inES5())return!1;return(!(e&&e.strictOnly&&a.inES5())||!!a.option.strict||!!a.isStrict())&&("await"!==$.id||!!(_&f.async)||!!a.option.module)&&("yield"!==$.id||!!(_&f.yield)||a.isStrict())}function F(_,$){return _.replace(/\{([^{}]*)\}/g,function(_,e){var t=$[e];return"string"==typeof t||"number"==typeof t?t:_})}function w(_,$){Object.keys($).forEach(function(e){t.has(d.blacklist,e)||(_[e]=$[e])})}function W(){var _=null;(function _(){if(a.option.enforceall){for(var $ in c.bool.enforcing)void 0!==a.option[$]||c.noenforceall[$]||(a.option[$]=!0);for(var e in c.bool.relaxing)void 0===a.option[e]&&(a.option[e]=!1)}})(),(_=a.inferEsVersion())&&D("E059",a.tokens.next,"esversion",_),a.inES5()&&w(k,r.ecmaIdentifiers[5]),a.inES6()&&w(k,r.ecmaIdentifiers[6]),a.inES8()&&w(k,r.ecmaIdentifiers[8]),a.inES11()&&w(k,r.ecmaIdentifiers[11]),"global"===a.option.strict&&"globalstrict"in a.option&&D("E059",a.tokens.next,"strict","globalstrict"),a.option.module&&!a.inES6()&&L("W134",a.tokens.next,"module",6),a.option.regexpu&&!a.inES6()&&L("W134",a.tokens.next,"regexpu",6),a.option.couch&&w(k,r.couch),a.option.qunit&&w(k,r.qunit),a.option.rhino&&w(k,r.rhino),a.option.shelljs&&(w(k,r.shelljs),w(k,r.node)),a.option.typed&&w(k,r.typed),a.option.phantom&&w(k,r.phantom),a.option.prototypejs&&w(k,r.prototypejs),a.option.node&&(w(k,r.node),w(k,r.typed)),a.option.devel&&w(k,r.devel),a.option.dojo&&w(k,r.dojo),a.option.browser&&(w(k,r.browser),w(k,r.typed)),a.option.browserify&&(w(k,r.browser),w(k,r.typed),w(k,r.browserify)),a.option.nonstandard&&w(k,r.nonstandard),a.option.jasmine&&w(k,r.jasmine),a.option.jquery&&w(k,r.jquery),a.option.mootools&&w(k,r.mootools),a.option.worker&&w(k,r.worker),a.option.wsh&&w(k,r.wsh),a.option.yui&&w(k,r.yui),a.option.mocha&&w(k,r.mocha)}function D(_,$,e,t){var n=Math.floor($.line/a.lines.length*100),r=i.errors[_].desc,u={name:"JSHintError",line:$.line,character:$.from,message:r+" ("+n+"% scanned).",raw:r,code:_,a:e,b:t};throw u.reason=F(r,u)+" ("+n+"% scanned).",u}function B(){var _=a.ignoredLines;t.isEmpty(_)||(d.errors=t.reject(d.errors,function($){return _[$.line]}))}function L(_,$,e,t,n,r){var u,o,s,c;if(/^W\d{3}$/.test(_)){if(a.ignored[_])return;c=i.warnings[_]}else/E\d{3}/.test(_)?c=i.errors[_]:/I\d{3}/.test(_)&&(c=i.info[_]);return"(end)"===($=$||a.tokens.next||{}).id&&($=a.tokens.curr),o=$.line,u=$.from,(s={id:"(error)",raw:c.desc,code:c.code,evidence:a.lines[o-1]||"",line:o,character:u,scope:d.scope,a:e,b:t,c:n,d:r}).reason=F(c.desc,s),d.errors.push(s),B(),d.errors.filter(function(_){return/E\d{3}/.test(_.code)}).length>=a.option.maxerr&&D("E043",$),s}function M(_,$,e,t,n,r,i){return L(_,{line:$,from:e},t,n,r,i)}function T(_,$,e,t,n,r){L(_,$,e,t,n,r)}function j(_,$,e,t,n,r,i){var u,o,a,s,c,l;return u=_,o={line:$,from:e},a=t,s=n,c=r,void L(u,o,a,s,c,l=i)}function G(_,$){d.internals.push({id:"(internal)",elem:_,token:$,code:$.value.replace(/([^\\])(\\*)\2\\n/g,"$1\n")})}function I(_,e){var n=_.body.split(",").map(function(_){return _.trim()}),r={};if("falls through"===_.type){e.caseFallsThrough=!0;return}if("globals"===_.type)for(var i in n.forEach(function($,e){var t=$.split(":"),i=t[0].trim();if("-"===i||!i.length){if(e>0&&e===n.length-1)return;var u,o="E002";L(o,u=_,void 0,void 0,void 0,void 0);return}"-"===i.charAt(0)?(i=i.slice(1),d.blacklist[i]=i,delete k[i]):r[i]=t.length>1&&"true"===t[1].trim()}),w(k,r),r)t.has(r,i)&&($[i]=_);"exported"===_.type&&n.forEach(function($,e){if(!$.length){var t;if(e>0&&e===n.length-1)return;L("E002",t=_,void 0,void 0,void 0,void 0);return}a.funct["(scope)"].addExported($)}),"members"===_.type&&(y=y||{},n.forEach(function(_){var $=_.charAt(0);$===_.charAt(_.length-1)&&('"'===$||"'"===$)&&(_=_.substr(1,_.length-2).replace('\\"','"')),y[_]=!1}));var u=["maxstatements","maxparams","maxdepth","maxcomplexity","maxerr","maxlen","indent"];("jshint"===_.type||"jslint"===_.type||"jshint.unstable"===_.type)&&(n.forEach(function($){var e,t,n=$.split(":"),r=n[0].trim(),i=n.length>1?n[1].trim():"";if(A(r,"jshint.unstable"!==_.type,_)){if(u.indexOf(r)>=0){if("false"!==i){if("number"!=typeof(e=+i)||!isFinite(e)||e<=0||Math.floor(e)!==e){o=_,L("E032",o,s=i,void 0,void 0,void 0);return}a.option[r]=e}else a.option[r]="indent"===r&&4;return}if("validthis"===r){if(a.funct["(global)"])return void void L("E009",void 0,void 0,void 0,void 0,void 0);if("true"!==i&&"false"!==i){return void void L("E002",l=_,void 0,void 0,void 0,void 0)}return void(a.option.validthis="true"===i)}if("quotmark"===r){switch(i){case"true":case"false":a.option.quotmark="true"===i;break;case"double":case"single":a.option.quotmark=i;break;default:L("E002",f=_,void 0,void 0,void 0,void 0)}return}if("shadow"===r){switch(i){case"true":a.option.shadow=!0;break;case"outer":a.option.shadow="outer";break;case"false":case"inner":a.option.shadow="inner";break;default:L("E002",d=_,void 0,void 0,void 0,void 0)}return}if("unused"===r){switch(i){case"true":a.option.unused=!0;break;case"false":a.option.unused=!1;break;case"vars":case"strict":a.option.unused=i;break;default:L("E002",p=_,void 0,void 0,void 0,void 0)}return}if("latedef"===r){switch(i){case"true":a.option.latedef=!0;break;case"false":a.option.latedef=!1;break;case"nofunc":a.option.latedef="nofunc";break;default:L("E002",h=_,void 0,void 0,void 0,void 0)}return}if("ignore"===r){if("line"===i)a.ignoredLines[_.line]=!0,B();else{L("E002",v=_,void 0,void 0,void 0,void 0)}return}if("strict"===r){switch(i){case"true":a.option.strict=!0;break;case"false":a.option.strict=!1;break;case"global":case"implied":a.option.strict=i;break;default:L("E002",g=_,void 0,void 0,void 0,void 0)}return}if("module"===r&&!_8(a.funct)){L("E055",m=_,"module",void 0,void 0,void 0)}if("esversion"===r){switch(i){case"3":case"5":case"6":case"7":case"8":case"9":case"10":case"11":a.option.moz=!1,a.option.esversion=+i;break;case"2015":case"2016":case"2017":case"2018":case"2019":case"2020":a.option.moz=!1,a.option.esversion=+i-2009;break;default:L("E002",y=_,void 0,void 0,void 0,void 0)}if(!_8(a.funct)){L("E055",k=_,"esversion",void 0,void 0,void 0)}return}var o,s,l,f,d,p,h,v,g,m,y,k,x,b=/^([+-])(W\d{3})$/g.exec(r);if(b){a.ignored[b[2]]="-"===b[1];return}if("true"===i||"false"===i){"jslint"===_.type?(t=c.renamed[r]||r,a.option[t]="true"===i,void 0!==c.inverted[t]&&(a.option[t]=!a.option[t])):"jshint.unstable"===_.type?a.option.unstable[r]="true"===i:a.option[r]="true"===i;return}L("E002",x=_,void 0,void 0,void 0,void 0)}}),W())}function P(_){var $,e=_||0,t=v.length;if(e="a"&&$<="z"||$>="A"&&$<="Z")&&(_.identifier=_.reserved=!0),_}function Y(_,$){var e=K(_,150);return Q(e),e.nud="function"==typeof $?$:function(_){return this.arity="unary",this.right=U(_,150),("++"===this.id||"--"===this.id)&&(a.option.plusplus&&L("W016",this,this.id),this.right&&_7(_,this.right,this)),this},e}function _2(_,$){var e=K(_,0);return e.type=_,e.nud=$,e}function _1(_,$){var e=_2(_,$);return e.identifier=!0,e.reserved=!0,e}function _0(_,$){var e=_2(_,a.syntax["(identifier)"].nud);return($=$||{}).isFutureReservedWord=!0,e.value=_,e.identifier=!0,e.reserved=!0,e.meta=$,e}function __(_,$,e,t){var n=K(_,e);return Q(n),n.infix=!0,n.led=function(n,r){return(t||H(a.tokens.prev,a.tokens.curr),("in"===_||"instanceof"===_)&&"!"===r.id&&L("W018",r,"!"),"function"==typeof $)?$(n,r,this):(this.left=r,this.right=U(n,e),this)},n}function _3(_,$){var e=K(_,100);return e.infix=!0,e.led=function(_,e){H(a.tokens.prev,a.tokens.curr),this.left=e;var t=this.right=U(_,100);return S(e,"NaN")||S(t,"NaN")?L("W019",this):$&&$.apply(this,[_,e,t]),e&&t||D("E041",a.tokens.curr),"!"===e.id&&L("W018",e,"!"),"!"===t.id&&L("W018",t,"!"),this},e}function _$(_){return"unary"===_.arity&&"++"!==_.id&&"--"!==_.id}var _4={};function _5(_,$,e){var n;return!e.option.notypeof&&!!_&&!!$&&(n=e.inES6()?_4.es6:_4.es3,"(identifier)"===$.type&&"typeof"===$.value&&"(string)"===_.type&&("bigint"===_.value?(e.inES11()||L("W119",_,"BigInt","11"),!1):!t.includes(n,_.value)))}function _6(_,$){var e=!1;return"this"===_.type&&null===$.funct["(context)"]?e=!0:"(identifier)"===_.type&&($.option.node&&"global"===_.value?e=!0:$.option.browser&&("window"===_.value||"document"===_.value)&&(e=!0)),e}function _7(_,$,e,t){var n,r,i,u=t&&t.allowDestructuring;if(e=e||$,a.option.freeze){var o=function _($){var e=["Array","ArrayBuffer","Boolean","Collator","DataView","Date","DateTimeFormat","Error","EvalError","Float32Array","Float64Array","Function","Infinity","Intl","Int16Array","Int32Array","Int8Array","Iterator","Number","NumberFormat","Object","RangeError","ReferenceError","RegExp","StopIteration","String","SyntaxError","TypeError","Uint16Array","Uint32Array","Uint8Array","Uint8ClampedArray","URIError"],t=function _($){if("object"==typeof $)return"prototype"===$.right?$:_($.left)}($);if(t)return function _($){for(;!$.identifier&&"object"==typeof $.left;)$=$.left;if($.identifier&&e.indexOf($.value)>=0&&a.funct["(scope)"].isPredefined($.value))return $.value}(t)}($);o&&L("W121",$,o)}if($.identifier&&!$.isMetaProperty&&a.funct["(scope)"].block.reassign($.value,$),"."===$.id)return $.left&&("arguments"!==$.left.value||a.isStrict())||L("W143",e),a.nameStack.set(a.tokens.prev),!0;if("{"===$.id||"["===$.id)return u&&$.destructAssign||("{"!==$.id&&$.left?"arguments"!==$.left.value||a.isStrict()||L("W143",e):L("E031",e)),"["===$.id&&a.nameStack.set($.right),!0;if($.identifier&&!C(_,$)&&!$.isMetaProperty){if("exception"===a.funct["(scope)"].bindingtype($.value)&&L("W022",$),"eval"===$.value&&a.isStrict()){return L("E031",n=e,void 0,void 0,void 0,void 0),!1}if("arguments"===$.value){if(a.isStrict()){return L("E031",r=e,void 0,void 0,void 0,void 0),!1}L("W143",e)}return a.nameStack.set($),!0}return L("E031",i=e,void 0,void 0,void 0,void 0),!1}function _e(_,$){var e=__(_,"function"==typeof $?$:function(_,$,e){return e.left=$,_7(_,$,e,{allowDestructuring:!0}),e.right=U(_,10),e},20);return e.exps=!0,e.assign=!0,e}function _t(_,$,e){var t=K(_,e);return Q(t),t.infix=!0,t.led="function"==typeof $?$:function(_,$){return a.option.bitwise&&L("W016",this,this.id),this.left=$,this.right=U(_,e),this},t}function _n(_){return K(_,20).exps=!0,__(_,function(_,$,e){return a.option.bitwise&&L("W016",e,e.id),_7(_,$,e),e.right=U(_,10),e},20)}function _r(_){var $=K(_,150);return $.led=function(_,$){return a.option.plusplus&&L("W016",this,this.id),_7(_,$,this),this.left=$,this},$}function _i(_,$,e){if(a.tokens.next.identifier){e||V();var t=a.tokens.curr;return C(_,t)&&!($&&a.inES5())&&L("W024",a.tokens.curr,a.tokens.curr.id),t.value}}function _u(_){if(!_X(a.tokens.next,"..."))return!1;if(a.inES6(!0)||L("W119",a.tokens.next,_+" operator","6"),V(),_X(a.tokens.next,"..."))for(L("E024",a.tokens.next,"...");_X(a.tokens.next,"...");)V();return!0}function _o(_,$){var e,t,n=_i(_,$,!1);if(n)return n;e=a.tokens.next,L("E030",e,t=a.tokens.next.value,void 0,void 0,void 0),";"!==a.tokens.next.id&&V()}function _a(_){var $,e=0;if(";"===a.tokens.next.id&&!_.inBracelessBlock)for(;;){do $=P(e),e+=1;while("(end)"!==$.id&&"(comment)"===$.id);if($.reach)return;if("(endline)"!==$.id){if(t($,e)){!0===a.option.latedef&&L("W026",$);break}L("W027",$,$.value,_.value);break}}function t(_,$){return"function"===_.id||("async"===_.id?"function"===(_=P($)).id:void 0)}}function _s(_){if(";"!==a.tokens.next.id){if(a.tokens.next.isUnclosed)return V();var $=z(a.tokens.curr,a.tokens.next)&&"(end)"!==a.tokens.next.id,e=_X(a.tokens.next,"}");!$||e||"do"===_.id&&a.inES6(!0)?a.option.asi||e&&$&&a.option.lastsemic||M("W033",a.tokens.curr.line,a.tokens.curr.character):j("E058",a.tokens.curr.line,a.tokens.curr.character)}else V(";")}function _c(_){var $,e=h,t=a.tokens.next,n=!1;if(_|=f.initial,";"===t.id){V(";");return}var r=C(_,t);if(r&&t.meta&&t.meta.isFutureReservedWord&&!t.fud&&(L("W024",t,t.id),r=!1),t.identifier&&!r&&":"===P().id&&(V(),V(":"),n=!0,a.funct["(scope)"].stack(),a.funct["(scope)"].block.addLabel(t.value,{token:a.tokens.curr}),a.tokens.next.labelled||"{"===a.tokens.next.value||L("W028",a.tokens.next,t.value,a.tokens.next.value),t=a.tokens.next),"{"===t.id){_d(_,!0,!0,!1,!1,"case"===a.funct["(verb)"]&&":"===a.tokens.curr.value),n&&a.funct["(scope)"].unstack();return}return($=U(_,0))&&!($.identifier&&"function"===$.value)&&!("(punctuator)"===$.type&&$.left&&$.left.identifier&&"function"===$.left.value)&&!a.isStrict()&&a.stmtMissingStrict()&&L("E007"),t.block||(a.option.expr||$&&$.exps?a.option.nonew&&$&&$.left&&"("===$.id&&"new"===$.left.id&&L("W031",t):L("W030",a.tokens.curr),_s(t)),h=e,n&&a.funct["(scope)"].unstack(),$}function _l(_){for(var $,e=[];!a.tokens.next.reach&&"(end)"!==a.tokens.next.id;)";"===a.tokens.next.id?(($=P())&&("("===$.id||"["===$.id)||L("W032"),V(";")):e.push(_c(_));return e}function _f(){for(var _=a.tokens.next;"(string)"===a.tokens.next.id;){var $,e=O();if(!R(0,_,e))break;_=e,V();var t=a.tokens.curr.value;if((a.directive[t]||"use strict"===t&&"implied"===a.option.strict)&&L("W034",a.tokens.curr,t),"use strict"===t&&a.inES7()&&!a.funct["(global)"]&&!1===a.funct["(hasSimpleParams)"]){L("E065",$=a.tokens.curr,void 0,void 0,void 0,void 0)}a.directive[t]=a.tokens.curr,_s(_)}a.isStrict()&&(a.option.undef=!0)}function _d(_,$,e,t,n,r){var i,u,o,s,c,l,d,v=p,g=h;p=$,l=a.tokens.next;var m=a.funct["(metrics)"];if(m.nestedBlockDepth+=1,m.verifyMaxNestedBlockDepthPerFunction(),"{"===a.tokens.next.id){if(V("{"),a.funct["(scope)"].stack(),"}"!==a.tokens.next.id){for(h+=a.option.indent;!$&&a.tokens.next.from>h;)h+=a.option.indent;if(t){for(d in c={},a.directive)c[d]=a.directive[d];_f(),a.funct["(isStrict)"]=a.isStrict(),a.option.strict&&a.funct["(context)"]["(global)"]&&!c["use strict"]&&!a.isStrict()&&L("E007")}s=_l(_),m.statementCount+=s.length,h-=a.option.indent}else t&&(a.funct["(isStrict)"]=a.isStrict());V("}",l),t&&(a.funct["(scope)"].validateParams(n),c&&(a.directive=c)),a.funct["(scope)"].unstack(),h=g}else if($){a.funct["(scope)"].stack(),(!e||a.option.curly)&&L("W116",a.tokens.next,"{",a.tokens.next.value);var y,k,x="if"===a.funct["(verb)"]||"else"===a.tokens.curr.id;if(a.tokens.next.inBracelessBlock=!0,h+=a.option.indent,s=[_c(_)],h-=a.option.indent,s[0]&&s[0].declaration&&!(x&&"function"===s[0].id)){y=s[0],L("E048",y,k=s[0].id[0].toUpperCase()+s[0].id.slice(1),void 0,void 0,void 0)}a.funct["(scope)"].unstack()}else if(t){if(a.funct["(scope)"].stack(),e&&!n&&!a.inMoz()){L("W118",i=a.tokens.curr,"function closure expressions",void 0,void 0,void 0)}n&&a.funct["(scope)"].validateParams(!0);var b=U(_,10);a.option.noreturnawait&&_&f.async&&b.identifier&&"await"===b.value&&L("W146",b),a.option.strict&&a.funct["(context)"]["(global)"]&&!a.isStrict()&&L("E007"),a.funct["(scope)"].unstack()}else{u=a.tokens.next,L("E021",u,"{",o=a.tokens.next.value,void 0,void 0)}switch(a.funct["(verb)"]){case"break":case"continue":case"return":case"throw":if(r)break;default:a.funct["(verb)"]=null}return p=v,$&&a.option.noempty&&(!s||0===s.length)&&L("W035",a.tokens.prev),m.nestedBlockDepth-=1,s}function _p(_){y&&"boolean"!=typeof y[_]&&L("W036",a.tokens.curr,_),"number"==typeof m[_]?m[_]+=1:m[_]=1}_4.legacy=["xml","unknown"],_4.es3=["undefined","boolean","number","string","function","object",],_4.es3=_4.es3.concat(_4.legacy),_4.es6=_4.es3.concat("symbol","bigint"),_2("(number)",function(){return"."===a.tokens.next.id&&L("W005",this),this}),_2("(string)",function(){return this}),a.syntax["(identifier)"]={type:"(identifier)",lbp:0,identifier:!0,nud:function(_){var $=this.value,e="=>"===a.tokens.next.id;return C(_,this)?L("W024",this,$):e||a.funct["(comparray)"].check($)||a.funct["(scope)"].block.use($,a.tokens.curr),this},led:function(){var _,$;_=a.tokens.next,L("E033",_,$=a.tokens.next.value,void 0,void 0,void 0)}};var _h,_v,_g={identifier:!1,template:!0};a.syntax["(template)"]=t.extend({lbp:155,type:"(template)",nud:_A,led:_A,noSubst:!1},_g),a.syntax["(template middle)"]=t.extend({lbp:0,type:"(template middle)",noSubst:!1},_g),a.syntax["(template tail)"]=t.extend({lbp:0,type:"(template tail)",tail:!0,noSubst:!1},_g),a.syntax["(no subst template)"]=t.extend({lbp:155,type:"(template)",nud:_A,led:_A,noSubst:!0,tail:!0},_g),_2("(regexp)",function(){return this}),Z("(endline)"),(_h=Z("(begin)")).line=_h.from=0,Z("(end)").reach=!0,Z("(error)").reach=!0,Z("}").reach=!0,Z(")"),Z("]"),Z('"').reach=!0,Z("'").reach=!0,Z(";"),Z(":").reach=!0,Z("#"),_1("else"),_1("case").reach=!0,_1("catch"),_1("default").reach=!0,_1("finally"),_1("true",function(){return this}),_1("false",function(){return this}),_1("null",function(){return this}),_1("this",function(){return a.isStrict()&&!a.funct["(method)"]&&!a.option.validthis&&(a.funct["(statement)"]&&a.funct["(name)"].charAt(0)>"Z"||a.funct["(global)"])&&L("W040",this),this}),(_v=_1("super",function(){return _N.call(a.tokens.curr,this),this})).rbp=161,_e("=","assign"),_e("+=","assignadd"),_e("-=","assignsub"),_e("*=","assignmult"),_e("/=","assigndiv").nud=function(){L("E014",void 0,void 0,void 0,void 0,void 0)},_e("%=","assignmod"),_e("**=",function(_,$,e){return a.inES7()||L("W119",e,"Exponentiation operator","7"),e.left=$,_7(_,$,e),e.right=U(_,10),e}),_n("&="),_n("|="),_n("^="),_n("<<="),_n(">>="),_n(">>>="),__(",",function(_,$,e){return a.option.nocomma&&L("W127",e),e.left=$,q()?e.right=U(_,10):e.right=null,e},10,!0),__("?",function(_,$,e){return _F(),e.left=$,e.right=U(_&~f.noin,10),V(":"),U(_,10),e},30),__("||",function(_,$,e){return _F(),e.left=$,e.right=U(_,40),e},40),__("&&",function(_,$,e){return _F(),e.left=$,e.right=U(_,50),e},50),__("??",function(_,$,e){if(!$.paren&&("||"===$.id||"&&"===$.id)){L("E024",t=e,"??",void 0,void 0,void 0)}a.inES11()||L("W119",e,"nullish coalescing","11"),_F(),e.left=$;var t,n,r,i,u,o=e.right=U(_,39);if(o){if(!o.paren&&("||"===o.id||"&&"===o.id)){n=e.right,L("E024",n,r=e.right.id,void 0,void 0,void 0)}}else{i=a.tokens.next,L("E024",i,u=a.tokens.next.id,void 0,void 0,void 0)}return e},39),__("**",function(_,$,e){if(a.inES7()||L("W119",e,"Exponentiation operator","7"),!$.paren&&_$($)){var t;L("E024",t=e,"**",void 0,void 0,void 0)}return e.left=$,e.right=U(_,e.rbp),e},150),a.syntax["**"].rbp=140,_t("|","bitor",70),_t("^","bitxor",80),_t("&","bitand",90),_3("==",function(_,$,e){var t=a.option.eqnull&&("null"===($&&$.value)||"null"===(e&&e.value));switch(!0){case!t&&a.option.eqeqeq:this.from=this.character,L("W116",this,"===","==");break;case _5(e,$,a):L("W122",this,e.value);break;case _5($,e,a):L("W122",this,$.value)}return this}),_3("===",function(_,$,e){return _5(e,$,a)?L("W122",this,e.value):_5($,e,a)&&L("W122",this,$.value),this}),_3("!=",function(_,$,e){return!(a.option.eqnull&&("null"===($&&$.value)||"null"===(e&&e.value)))&&a.option.eqeqeq?(this.from=this.character,L("W116",this,"!==","!=")):_5(e,$,a)?L("W122",this,e.value):_5($,e,a)&&L("W122",this,$.value),this}),_3("!==",function(_,$,e){return _5(e,$,a)?L("W122",this,e.value):_5($,e,a)&&L("W122",this,$.value),this}),_3("<"),_3(">"),_3("<="),_3(">="),_t("<<","shiftleft",120),_t(">>","shiftright",120),_t(">>>","shiftrightunsigned",120),__("in","in",120),__("instanceof",function(_,$,e){var t,n=a.funct["(scope)"];return(e.left=$,e.right=t=U(_,120),t)?(("(number)"===t.id||"(string)"===t.id||"null"===t.value||"undefined"===t.value&&!n.has("undefined")||"unary"===t.arity||"{"===t.id||"["===t.id&&!t.right||"(regexp)"===t.id||"(template)"===t.id&&!t.tag)&&L("E060",void 0,void 0,void 0,void 0,void 0),"function"===t.id&&L("W139"),e):e},120),__("+",function(_,$,e){var t,n=a.tokens.next;return(e.left=$,e.right=t=U(_,130),$&&t&&"(string)"===$.id&&"(string)"===t.id)?($.value+=t.value,$.character=t.character,!a.option.scripturl&&o.javascriptURL.test($.value)&&L("W050",$),$):(("+"===n.id||"++"===n.id)&&L("W007",e.right),e)},130),Y("+",function(_){var $=a.tokens.next;return this.arity="unary",this.right=U(_,150),("+"===$.id||"++"===$.id)&&L("W007",this.right),this}),__("-",function(_,$,e){var t=a.tokens.next;return e.left=$,e.right=U(_,130),("-"===t.id||"--"===t.id)&&L("W006",e.right),e},130),Y("-",function(_){var $=a.tokens.next;return this.arity="unary",this.right=U(_,150),("-"===$.id||"--"===$.id)&&L("W006",this.right),this}),__("*","mult",140),__("/","div",140),__("%","mod",140),_r("++"),Y("++","preinc"),a.syntax["++"].exps=!0,_r("--"),Y("--","predec"),a.syntax["--"].exps=!0,Y("delete",function(_){this.arity="unary";var $=U(_,150);return $&&("."!==$.id&&"["!==$.id&&L("W051"),this.first=$,$.identifier&&!a.isStrict()&&($.forgiveUndef=!0)),this}).exps=!0,Y("~",function(_){return a.option.bitwise&&L("W016",this,"~"),this.arity="unary",this.right=U(_,150),this}),__("..."),Y("!",function(_){return this.arity="unary",this.right=U(_,150),this.right||D("E041",this),!0===x[this.right.id]&&L("W018",this,"!"),this}),Y("typeof",function(_){this.arity="unary";var $=U(_,150);return this.first=this.right=$,$||D("E041",this),$.identifier&&($.forgiveUndef=!0),this}),Y("new",function(_){var $,e,t,n=_D(_,"target",function(){a.inES6(!0)||L("W119",a.tokens.prev,"new.target","6");for(var _,$=a.funct;$&&(_=!$["(global)"],$["(arrow)"]);)$=$["(context)"];_||L("W136",a.tokens.prev,"new.target")});if(n)return n;var r,i=a.tokens.next,u=U(_,155);if(!u)return this;if(!u.paren&&u.rbp>160){$=i,L("E024",$,e=i.value,void 0,void 0,void 0)}if("function"!==u.id){if(u.identifier)switch(u.value){case"Number":case"String":case"Boolean":case"Math":case"JSON":L("W053",a.tokens.prev,u.value);break;case"Symbol":a.inES6()&&L("W053",a.tokens.prev,u.value);break;case"Function":a.option.evil||L("W054");break;case"Date":case"RegExp":case"this":break;default:r=u.value.substr(0,1),a.option.newcap&&(r<"A"||r>"Z")&&!a.funct["(scope)"].isPredefined(u.value)&&L("W055",a.tokens.curr)}else if("?."!==u.id||u.paren)"."!==u.id&&"["!==u.id&&"("!==u.id&&L("W056",a.tokens.curr);else{t=u,L("E024",t,"?.",void 0,void 0,void 0)}}else a.option.supernew||L("W057",this);return"("===a.tokens.next.id||a.option.supernew||L("W058",a.tokens.curr,a.tokens.curr.value),this.first=this.right=u,this}),a.syntax.new.exps=!0;var _m=X("class",function(_){var $,e;return a.inES6()||L("W104",a.tokens.curr,"class","6"),a.inClassBody=!0,a.tokens.next.identifier&&"extends"!==a.tokens.next.value&&($=(e=a.tokens.next).value,_o(_),a.funct["(scope)"].addbinding($,{type:"class",initialized:!1,token:e})),"extends"===a.tokens.next.value&&(V("extends"),U(_,0)),e?(this.name=e,a.funct["(scope)"].initialize($)):this.name=null,a.funct["(scope)"].stack(),_y(this,_),this});function _y(_,$){var e,t,n,r,i,u,o,s,c,l,d,p,h,v,g,m,y,k,x,b,E,A,S=Object.create(null);for("{"===a.tokens.next.value?V("{"):(L("W116",a.tokens.curr,"identifier",a.tokens.next.type),V());"}"!==a.tokens.next.value;){if(b=!1,E=!1,$&=~f.preAsync,"static"!==a.tokens.next.value||_X(P(),"(")||(b=!0,V()),"async"!==a.tokens.next.value||_X(P(),"(")||($|=f.preAsync,V(),N(a.tokens.curr),_X(a.tokens.next,"*")&&(E=!0,V("*"),a.inES9()||L("W119",a.tokens.next,"async generators","9")),a.inES8()||L("W119",a.tokens.curr,"async functions","8")),"*"===a.tokens.next.value&&(E=!0,V()),"set"!==(x=a.tokens.next).value&&"get"!==x.value||_X(P(),"("))k=null;else{if(E){e=x,L("E024",e,t=x.value,void 0,void 0,void 0)}if(k=x.value,V(),x=a.tokens.next,b||"constructor"!==x.value){if(b&&"prototype"===x.value){n=x,r="static class "+k+"ter method",L("E049",n,r,i=x.value,void 0,void 0)}}else{u=x,o="class "+k+"ter method",L("E049",u,o,s=x.value,void 0,void 0)}}switch(x.value){case";":L("W032",x),V();break;case"constructor":if(b)y=_b($),_9(S,y,x,!0,b),_k(_,$,y,E);else{if(E||$&f.preAsync){c=x,L("E024",c,l=x.value,void 0,void 0,void 0)}else if(A){d=x,L("E024",d,p=x.value,void 0,void 0,void 0)}else A=!k&&!b;V(),_k(_,$,a.nameStack.infer())}break;case"[":y=_Z($),_k(_,$,y,E);break;default:if(void 0===(y=_b($))){h=x,L("E024",h,v=x.value,void 0,void 0,void 0),V();break}if(k)_K(k,S,y,x,!0,b),y=a.nameStack.infer();else{if(b&&"prototype"===y){g=x,L("E049",g,"static class method",m=y,void 0,void 0)}_9(S,y,x,!0,b)}_k(_,$,y,E)}}V("}"),_W(S),a.inClassBody=!1,a.funct["(scope)"].unstack()}function _k(_,$,e,t){if(t&&!a.inES6()&&L("W119",a.tokens.curr,"function*","6"),"("!==a.tokens.next.value){var n,r;if(n=a.tokens.next,L("E054",n,r=a.tokens.next.value,void 0,void 0,void 0),V(),"{"===a.tokens.next.value){V(),"}"===a.tokens.next.value&&(L("W116",a.tokens.next,"(",a.tokens.next.value),V(),_o($),V());return}for(;"("!==a.tokens.next.value;)V()}_S($,{name:e,type:t?"generator":null,isMethod:!0,statement:_})}function _x(_){var $,e=a.tokens.next,t=-1;do"("===e.value?_+=1:")"===e.value&&(_-=1),t+=1,$=e,e=P(t);while(!(0===_&&")"===$.value)&&"(end)"!==e.type);return e}function _b(_){var $=_i(_,!0);return $||("(string)"===a.tokens.next.id?($=a.tokens.next.value,V()):"(number)"===a.tokens.next.id&&($=a.tokens.next.value.toString(),V())),"hasOwnProperty"===$&&L("W001"),$}function _E(_,$,e){var n={"(name)":_,"(breakage)":0,"(loopage)":0,"(isStrict)":"unknown","(global)":!1,"(line)":null,"(character)":null,"(metrics)":null,"(statement)":null,"(context)":null,"(scope)":null,"(comparray)":null,"(yielded)":null,"(arrow)":null,"(async)":null,"(params)":null};return $&&t.extend(n,{"(line)":$.line,"(character)":$.character,"(metrics)":_C($)}),t.extend(n,e),n["(context)"]&&(n["(scope)"]=n["(context)"]["(scope)"],n["(comparray)"]=n["(context)"]["(comparray)"]),n}function _8(_){return _["(global)"]&&!_["(verb)"]}function _A(_,$){var e=this.context,t=this.noSubst,n=this.depth;if(!t)for(;!r();)!a.tokens.next.template||a.tokens.next.depth>n?U(_,0):V();return{id:"(template)",type:"(template)",tag:"number"==typeof $?null:$};function r(){if(a.tokens.curr.template&&a.tokens.curr.tail&&a.tokens.curr.context===e)return!0;var _=a.tokens.next.template&&a.tokens.next.tail&&a.tokens.next.context===e;return _&&V(),_||a.tokens.next.isUnclosed}}function _S(_,$){var n,r,i,u,o,s,c,l,d,p=a.option,h=a.ignored,v=_&f.preAsync;$&&(i=$.name,u=$.statement,o=$.classExprBinding,s="generator"===$.type,c="arrow"===$.type,l=$.isMethod,d=$.ignoreLoopFunc),_&=~f.noin,_&=~f.tryClause,v?_|=f.async:_&=~f.async,s?_|=f.yield:c||(_&=~f.yield),_&=~f.preAsync,a.option=Object.create(a.option),a.ignored=Object.create(a.ignored),a.funct=_E(i||a.nameStack.infer(),a.tokens.next,{"(statement)":u,"(context)":a.funct,"(arrow)":c,"(method)":l,"(async)":v}),n=a.funct,r=a.tokens.curr,e.push(a.funct),a.funct["(scope)"].stack("functionouter");var g=!l&&(i||o);g&&a.funct["(scope)"].block.add(g,o?"class":"function",a.tokens.curr,!1),c||a.funct["(scope)"].funct.add("arguments","var",r,!1),a.funct["(scope)"].stack("functionparams");var m=function _($,e){var n,r,i,u=[],o=[],s=!1,c=!1,l=0,f=e&&e.loneArg,d=!1;if(f&&!0===f.identifier)return a.funct["(scope)"].addParam(f.value,f),{arity:1,params:[f.value],isSimple:!0};if(n=a.tokens.next,e&&e.parsedOpening||V("("),")"===a.tokens.next.id){V(")");return}function p(_){a.funct["(scope)"].addParam.apply(a.funct["(scope)"],_)}for(;;){l++;var h,v,g=[];if(c=_u("rest"),t.includes(["{","["],a.tokens.next.id))for(i in d=!0,o=_B($))(i=o[i]).id&&(u.push(i.id),g.push([i.id,i.token]));else if(r=_o($))u.push(r),g.push([r,a.tokens.curr]);else for(;!_J(a.tokens.next,[",",")"]);)V();if(s&&"="!==a.tokens.next.id){L("W138",h=a.tokens.curr,void 0,void 0,void 0,void 0)}if("="===a.tokens.next.id){if(a.inES6()||L("W119",a.tokens.next,"default parameters","6"),c){L("E062",v=a.tokens.next,void 0,void 0,void 0,void 0)}V("="),s=!0,U($,10)}if(g.forEach(p),","===a.tokens.next.id&&(c&&L("W131",a.tokens.next),V(","),q({allowTrailing:!0})),")"===a.tokens.next.id)return","!==a.tokens.curr.id||a.inES8()||L("W119",a.tokens.curr,"Trailing comma in function parameters","8"),V(")",n),{arity:l,params:u,isSimple:!d&&!c&&!s}}}(_,$);return m?(a.funct["(params)"]=m.params,a.funct["(hasSimpleParams)"]=m.isSimple,a.funct["(metrics)"].arity=m.arity,a.funct["(metrics)"].verifyMaxParametersPerFunction()):(a.funct["(params)"]=[],a.funct["(metrics)"].arity=0,a.funct["(hasSimpleParams)"]=!0),c&&(_&=~f.yield,a.inES6(!0)||L("W119",a.tokens.curr,"arrow function syntax (=>)","6"),$.loneArg||V("=>")),_d(_,!1,!0,!0,c),a.option.noyield||!s||a.funct["(yielded)"]||L("W124",a.tokens.curr),a.funct["(metrics)"].verifyMaxStatementsPerFunction(),a.funct["(metrics)"].verifyMaxComplexityPerFunction(),a.funct["(unusedOption)"]=a.option.unused,a.option=p,a.ignored=h,a.funct["(last)"]=a.tokens.curr.line,a.funct["(lastcharacter)"]=a.tokens.curr.character,a.funct["(scope)"].unstack(),a.funct["(scope)"].unstack(),a.funct=a.funct["(context)"],!d&&!a.option.loopfunc&&a.funct["(loopage)"]&&n["(outerMutables)"]&&L("W083",r,n["(outerMutables)"].join(", ")),n}function _C(_){return{statementCount:0,nestedBlockDepth:-1,ComplexityCount:1,arity:0,verifyMaxStatementsPerFunction:function(){a.option.maxstatements&&this.statementCount>a.option.maxstatements&&L("W071",_,this.statementCount)},verifyMaxParametersPerFunction:function(){t.isNumber(a.option.maxparams)&&this.arity>a.option.maxparams&&L("W072",_,this.arity)},verifyMaxNestedBlockDepthPerFunction:function(){a.option.maxdepth&&this.nestedBlockDepth>0&&this.nestedBlockDepth===a.option.maxdepth+1&&L("W073",null,this.nestedBlockDepth)},verifyMaxComplexityPerFunction:function(){var $=a.option.maxcomplexity,e=this.ComplexityCount;$&&e>$&&L("W074",_,e)}}}function _F(){a.funct["(metrics)"].ComplexityCount+=1}function _w(_){if(_&&!_.paren){if(","===_.id){_w(_.right);return}switch(_.id){case"=":case"+=":case"-=":case"*=":case"%=":case"&=":case"|=":case"^=":case"/=":a.option.boss||L("W084",_)}}}function _W(_){if(a.inES5())for(var $ in _)_[$]&&_[$].setterToken&&!_[$].getterToken&&!_[$].static&&L("W078",_[$].setterToken)}function _D(_,$,e){if(_X(a.tokens.next,".")){var t,n,r,i=a.tokens.curr.id;V(".");var u=_o(_);if(a.tokens.curr.isMetaProperty=!0,$!==u){t=a.tokens.prev,n=i,r=u,L("E057",t,n,r,void 0,void 0)}else e();return a.tokens.curr}}function _B(_,$){var e=$&&$.assignment;return _&=~f.noin,a.inES6()||L("W104",a.tokens.curr,e?"destructuring assignment":"destructuring binding","6"),function _($,e){var t,n,r,i,u=[],o=e&&e.openingParsed,s=e&&e.assignment,c=s?{assignment:s}:null,l=o?a.tokens.curr:a.tokens.next,f=function(){var e;if(_J(a.tokens.next,["[","{"]))for(n=0,t=_($,c);n"===t.id||"("===t.id||"&&"===t.id||"||"===t.id||"?"===t.id||"async"===t.id||"?."===t.id||a.inES6()&&t["(name)"])&&L("W067",e)),e.left=$,e},155,!0).exps=!0,Y("(",function(_,$){var e,t,n,r,i,u=a.tokens.curr,o=a.tokens.prev,s=!a.option.singleGroups,c=_x(1);if("function"===a.tokens.next.id&&(n=a.tokens.next.immed=!0),"=>"===c.value)return c.funct=_S(_,{type:"arrow",parsedOpening:!0}),c;if(")"===a.tokens.next.id){V(")");return}if(t=U(_,0),V(")",this),t){if(t.paren=!0,a.option.immed&&t&&"function"===t.id&&"("!==a.tokens.next.id&&"."!==a.tokens.next.id&&"["!==a.tokens.next.id&&L("W068",this),","===t.id){for(r=t.left;","===r.id;)r=r.left;i=t.right}else r=i=t,s||(n||(n="async"===t.id),s=u.beginsStmt&&("{"===t.id||n)||n&&(!R()||"}"!==a.tokens.prev.id)||"=>"===t.id&&!R()||"{"===t.id&&"=>"===o.id||_$(t)&&"**"===a.tokens.next.id||"??"===o.id&&("&&"===t.id||"||"===t.id)||"(number)"===t.type&&_X(c,".")&&/^\d+$/.test(t.value)||u.beginsStmt&&"="===t.id&&"{"===t.left.id||"?."===t.id&&("new"===o.id||"(template)"===a.tokens.next.type));return!s&&((e=r).first||e.right||e.left||"yield"===e.id||"await"===e.id||r!==i)&&(s=$>r.lbp||$>0&&$===r.lbp||!R()&&i.rbp",42)).infix=!0,_G.led=function(_,$){return H(a.tokens.prev,a.tokens.curr),this.left=$,this.right=_S(_,{type:"arrow",loneArg:$}),this},_G).rbp=161,__("[",function(_,$,e){var t,n,r;return a.option.asi&&_J(a.tokens.prev,[")","]"])&&!z(a.tokens.prev,a.tokens.curr)&&L("W014",a.tokens.curr,a.tokens.curr.id),(t=U(_&~f.noin,0))&&"(string)"===t.type&&(!a.option.evil&&("eval"===t.value||"execScript"===t.value)&&_6($,a)&&L("W061"),_p(t.value),!a.option.sub&&o.identifier.test(t.value)&&(r=(n=a.syntax[t.value])?!C(_,n):"eval"!==t.value&&"arguments"!==t.value)&&L("W069",a.tokens.prev,t.value)),V("]",e),t&&"hasOwnProperty"===t.value&&"="===a.tokens.next.value&&L("W001"),e.left=$,e.right=t,e},160,!0),Y("[",function(_){var $=_q();if($.isCompArray)return a.option.esnext||a.inMoz()||L("W118",a.tokens.curr,"array comprehension"),function _($){var e,n={};n.exps=!0,a.funct["(comparray)"].stack();var r=!1;if("for"!==a.tokens.next.value&&(r=!0,a.inMoz()||L("W116",a.tokens.next,"for",a.tokens.next.value),a.funct["(comparray)"].setState("use"),n.right=U($,10)),V("for"),"each"!==a.tokens.next.value||(V("each"),a.inMoz()||L("W118",a.tokens.curr,"for each")),V("("),a.funct["(comparray)"].setState("define"),n.left=U($,130),t.includes(["in","of"],a.tokens.next.value))V();else{L("E045",e=a.tokens.curr,void 0,void 0,void 0,void 0)}return a.funct["(comparray)"].setState("generate"),U($,10),V(")"),"if"===a.tokens.next.value&&(V("if"),V("("),a.funct["(comparray)"].setState("filter"),U($,10),V(")")),r||(a.funct["(comparray)"].setState("use"),n.right=U($,10)),V("]"),a.funct["(comparray)"].unstack(),n}(_);if($.isDestAssign)return this.destructAssign=_B(_,{openingParsed:!0,assignment:!0}),this;var e=!z(a.tokens.curr,a.tokens.next);for(this.first=[],e&&(h+=a.option.indent,a.tokens.next.from===h+a.option.indent&&(h+=a.option.indent));"(end)"!==a.tokens.next.id;){for(;","===a.tokens.next.id;){if(!a.option.elision){if(a.inES5()){L("W128");do V(",");while(","===a.tokens.next.id);continue}L("W070")}V(",")}if("]"===a.tokens.next.id)break;if(_u("spread"),this.first.push(U(_,10)),","===a.tokens.next.id){if(V(","),q({allowTrailing:!0}),"]"===a.tokens.next.id&&!a.inES5()){L("W070",a.tokens.curr);break}}else{a.option.trailingcomma&&a.inES5()&&M("W140",a.tokens.curr.line,a.tokens.curr.character);break}}return e&&(h-=a.option.indent),V("]",this),this}),(_I=Z("{")).nud=function(_){var $,e,t,n,r,i,u=!1,o=Object.create(null),s=!1;if(($=!z(a.tokens.curr,a.tokens.next))&&(h+=a.option.indent,a.tokens.next.from===h+a.option.indent&&(h+=a.option.indent)),_q().isDestAssign)return this.destructAssign=_B(_,{openingParsed:!0,assignment:!0}),this;for(a.inObjectBody=!0;"}"!==a.tokens.next.id;){if(i=a.tokens.next.value,a.tokens.next.identifier&&(","===O().id||"}"===O().id))a.inES6()||L("W104",a.tokens.next,"object short notation","6"),t=(r=U(_,10))&&r.value,r&&_9(o,t,r);else if(":"!==P().id&&("get"===i||"set"===i))V(i),!a.inES5()&&L("E034",void 0,void 0,void 0,void 0,void 0),"["===a.tokens.next.id?t=_Z(_):!(t=_b(_))&&!a.inES6()&&L("E035",void 0,void 0,void 0,void 0,void 0),t&&_K(i,o,t,a.tokens.curr),r=a.tokens.next,n=(e=_S(_,{isMethod:!0}))["(params)"],"get"===i&&t&&n.length?L("W076",r,n[0],t):"set"===i&&t&&1!==e["(metrics)"].arity&&L("W077",r,t);else if(_u("spread"))a.inES9()||L("W119",a.tokens.next,"object spread property","9"),U(_,10);else{if("async"!==a.tokens.next.id||_J(P(),["(",":"])?s=!1:(a.inES8()||L("W119",a.tokens.next,"async functions","8"),s=!0,V(),N(a.tokens.curr)),"*"===a.tokens.next.value&&"(punctuator)"===a.tokens.next.type?(s&&!a.inES9()?L("W119",a.tokens.next,"async generators","9"):a.inES6()||L("W104",a.tokens.next,"generator functions","6"),V("*"),u=!0):u=!1,"["===a.tokens.next.id)t=_Z(_),a.nameStack.set(t);else if(a.nameStack.set(a.tokens.next),t=_b(_),_9(o,t,a.tokens.next),"string"!=typeof t)break;"("===a.tokens.next.value?(a.inES6()||L("W104",a.tokens.curr,"concise methods","6"),_S(s?_|f.preAsync:_,{isMethod:!0,type:u?"generator":null})):(V(":"),U(_,10))}if(_p(t),","===a.tokens.next.id)V(","),q({allowTrailing:!0,property:!0}),","===a.tokens.next.id?L("W070",a.tokens.curr):"}"!==a.tokens.next.id||a.inES5()||L("W070",a.tokens.curr);else{a.option.trailingcomma&&a.inES5()&&M("W140",a.tokens.curr.line,a.tokens.curr.character);break}}return $&&(h-=a.option.indent),V("}",this),_W(o),a.inObjectBody=!1,this},_I.fud=function(){var _;L("E036",_=a.tokens.curr,void 0,void 0,void 0,void 0)};var _T=J("const",function(_){return _M("const",this,_)});function _j(){return"("===a.tokens.next.id&&a.inMoz()}_T.exps=!0,_T.declaration=!0;var _G,_I,_P,_O,_V,_R=J("let",function(_){return _M("let",this,_)});_R.nud=function(_,$){if(!_j())return this.exps=!1,a.syntax["(identifier)"].nud.apply(this,arguments);a.funct["(scope)"].stack(),V("("),a.tokens.prev.fud(_),V(")"),U(_,$),a.funct["(scope)"].unstack()},_R.meta={es5:!0,isFutureReservedWord:!1,strictOnly:!0},_R.exps=!0,_R.declaration=!0,_R.useFud=function(_){var $,e=a.tokens.next;return!!(this.line===e.line||a.inES6())&&(($=e.identifier&&(!C(_,e)||"let"===e.id))||_J(e,["{","["])||_j())},J("var",function(_){var $,e,n,i,u=_&f.noin;for(this.first=[];;){var o=[];for(var s in t.includes(["{","["],a.tokens.next.value)?($=_B(_),e=!1):($=[],(i=_o(_))&&$.push({id:i,token:a.tokens.curr}),e=!0),a.option.varstmt&&L("W132",this),$)$.hasOwnProperty(s)&&(s=$[s],!a.funct["(global)"]||a.impliedClosure()||(!1===k[s.id]?L("W079",s.token,s.id):!1!==a.option.futurehostile||(a.inES5()||!1!==r.ecmaIdentifiers[5][s.id])&&(a.inES6()||!1!==r.ecmaIdentifiers[6][s.id])||L("W129",s.token,s.id)),s.id&&(a.funct["(scope)"].addbinding(s.id,{type:"var",token:s.token}),o.push(s.token)));if("="===a.tokens.next.id&&(this.hasInitializer=!0,a.nameStack.set(a.tokens.curr),V("="),"="!==P(0).id||!a.tokens.next.identifier||(u||a.funct["(params)"])&&-1!==a.funct["(params)"].indexOf(a.tokens.next.value)||L("W120",a.tokens.next,a.tokens.next.value),i=a.tokens.prev,(n=U(_,10))&&(!a.funct["(loopage)"]&&n.identifier&&"undefined"===n.value&&L("W080",i,i.value),e||_L(o,n))),this.first=this.first.concat(o),","!==a.tokens.next.id)break;this.hasComma=!0,V(","),q()}return this}).exps=!0,X("function",function(_){var $,e=_&f.export,t=!1,n=_&f.preAsync,r="";n&&(r="async "),"*"===a.tokens.next.value&&(n&&!a.inES9()?L("W119",a.tokens.prev,"async generators","9"):n||a.inES6(!0)||L("W119",a.tokens.next,"function*","6"),V("*"),r+="generator ",t=!0),r+="function",p&&L("W082",a.tokens.curr),this.name=_i(_)?a.tokens.curr:null,this.name?a.funct["(scope)"].addbinding(this.name.value,{type:r,token:a.tokens.curr,initialized:!0}):e||L("W025");var i=_S(_,{name:this.name&&this.name.value,statement:this,type:t?"generator":null,ignoreLoopFunc:p}),u=i["(isStrict)"]&&!a.isStrict();if(this.name&&("arguments"===i["(name)"]||"eval"===i["(name)"])&&u){L("E008",$=this.name,void 0,void 0,void 0,void 0)}return"("===a.tokens.next.id&&")"===P().id&&"=>"!==P(1).id&&a.tokens.next.line===a.tokens.curr.line&&L("E039",void 0,void 0,void 0,void 0,void 0),this}).declaration=!0,Y("function",function(_){var $,e,t=!1,n=_&f.preAsync;"*"===a.tokens.next.value&&(n&&!a.inES9()?L("W119",a.tokens.prev,"async generators","9"):n||a.inES6(!0)||L("W119",a.tokens.curr,"function*","6"),V("*"),t=!0),this.name=_i(n?_|f.async:_)?a.tokens.curr:null;var r=_S(_,{name:this.name&&this.name.value,type:t?"generator":null});if(t&&this.name&&"yield"===this.name.value){L("E024",$=this.name,"yield",void 0,void 0,void 0)}if(this.name&&("arguments"===r["(name)"]||"eval"===r["(name)"])&&r["(isStrict)"]){L("E008",e=this.name,void 0,void 0,void 0,void 0)}return this}),X("if",function(_){var $=a.tokens.next;_F(),V("(");var e=U(_,0);e||D("E041",this),_w(e);var t=null;a.option.forin&&a.forinifcheckneeded&&(a.forinifcheckneeded=!1,t=a.forinifchecks[a.forinifchecks.length-1],"(punctuator)"===e.type&&"!"===e.value?t.type="(negative)":t.type="(positive)"),V(")",$);var n=_d(_,!0,!0);return t&&"(negative)"===t.type&&n&&n[0]&&"(identifier)"===n[0].type&&"continue"===n[0].value&&(t.type="(negative-with-continue)"),"else"===a.tokens.next.id&&(V("else"),"if"===a.tokens.next.id||"switch"===a.tokens.next.id?_c(_):_d(_,!0,!0)),this}),X("try",function(_){var $,e,n,r=!1;function i(){if(V("("),_J(a.tokens.next,["[","{"])){var $=_B(_);t.each($,function(_){_.id&&a.funct["(scope)"].addParam(_.id,_.token,"exception")})}else"(identifier)"!==a.tokens.next.type?L("E030",a.tokens.next,a.tokens.next.value):a.funct["(scope)"].addParam(_o(_),a.tokens.curr,"exception");"if"===a.tokens.next.value&&(a.inMoz()||L("W118",a.tokens.curr,"catch filter"),V("if"),U(_,0)),V(")")}for(_d(_|f.tryClause,!0);"catch"===a.tokens.next.id;)_F(),n&&!a.inMoz()&&L("W118",a.tokens.next,"multiple catch blocks"),V("catch"),"{"!==a.tokens.next.id?(a.funct["(scope)"].stack("catchparams"),r=!0,i()):a.inES10()||L("W119",a.tokens.curr,"optional catch binding","10"),_d(_,!1),r&&(a.funct["(scope)"].unstack(),r=!1),n=!0;if("finally"===a.tokens.next.id){V("finally"),_d(_,!0);return}if(!n){$=a.tokens.next,L("E021",$,"catch",e=a.tokens.next.value,void 0,void 0)}return this}),X("while",function(_){var $=a.tokens.next;return a.funct["(breakage)"]+=1,a.funct["(loopage)"]+=1,_F(),V("("),_w(U(_,0)),V(")",$),_d(_,!0,!0),a.funct["(breakage)"]-=1,a.funct["(loopage)"]-=1,this}).labelled=!0,X("with",function(_){var $,e=a.tokens.next;if(a.isStrict()){L("E010",$=a.tokens.curr,void 0,void 0,void 0,void 0)}else a.option.withstmt||L("W085",a.tokens.curr);return V("("),U(_,0),V(")",e),_d(_,!0,!0),this}),X("switch",function(_){var $,e,t,n,r,i=a.tokens.next,u=!1,o=!1,s=!1;for(a.funct["(breakage)"]+=1,V("("),_w(U(_,0)),V(")",i),i=a.tokens.next,V("{"),a.funct["(scope)"].stack(),a.tokens.next.from===h&&(o=!0),o||(h+=a.option.indent);;)switch(a.tokens.next.id){case"case":switch(a.funct["(verb)"]){case"yield":case"break":case"case":case"continue":case"return":case"switch":case"throw":break;case"default":a.option.leanswitch&&L("W145",a.tokens.next);break;default:a.tokens.curr.caseFallsThrough||L("W086",a.tokens.curr,"case")}V("case"),U(_,0),s=!0,_F(),u=!0,V(":"),a.funct["(verb)"]="case";break;case"default":switch(a.funct["(verb)"]){case"yield":case"break":case"continue":case"return":case"throw":break;case"case":a.option.leanswitch&&L("W145",a.tokens.curr);break;default:s&&!a.tokens.curr.caseFallsThrough&&L("W086",a.tokens.curr,"default")}V("default"),u=!0,V(":"),a.funct["(verb)"]="default";break;case"}":o||(h-=a.option.indent),V("}",i),a.funct["(scope)"].unstack(),a.funct["(breakage)"]-=1,a.funct["(verb)"]=void 0;return;case"(end)":L("E023",$=a.tokens.next,"}",void 0,void 0,void 0);return;default:if(h+=a.option.indent,u)switch(a.tokens.curr.id){case",":L("E040",void 0,void 0,void 0,void 0,void 0);return;case":":u=!1,_l(_);break;default:L("E025",e=a.tokens.curr,void 0,void 0,void 0,void 0);return}else if(":"===a.tokens.curr.id){V(":"),L("E024",t=a.tokens.curr,":",void 0,void 0,void 0),_l(_)}else{n=a.tokens.next,L("E021",n,"case",r=a.tokens.next.value,void 0,void 0);return}h-=a.option.indent}}).labelled=!0,J("debugger",function(){return a.option.debug||L("W087",this),this}).exps=!0,(_P=J("do",function(_){a.funct["(breakage)"]+=1,a.funct["(loopage)"]+=1,_F(),this.first=_d(_,!0,!0),V("while");var $=a.tokens.next;return V("("),_w(U(_,0)),V(")",$),a.funct["(breakage)"]-=1,a.funct["(loopage)"]-=1,this})).labelled=!0,_P.exps=!0,X("for",function(_){var $,e,n,r,i,u,o,s,c,l,d=a.tokens.next,p=!1,h=!1,v=null;if("each"!==d.value||(v=d,V("each"),a.inMoz()||L("W118",a.tokens.curr,"for each")),a.tokens.next.identifier&&"await"===a.tokens.next.value){if(V("await"),h=!0,_&f.async)a.inES9()||L("W119",a.tokens.curr,"asynchronous iteration","9");else{L("E024",y=a.tokens.curr,"await",void 0,void 0,void 0)}}_F(),V("(");var g=P(),m=_|f.noin;if("var"===a.tokens.next.id)V("var"),r=(c=a.tokens.curr.fud(m)).hasComma?c:null,i=c.hasInitializer?c:null;else if("const"===a.tokens.next.id||"let"===a.tokens.next.id&&(g.identifier&&"in"!==g.id||_J(g,["{","["])))V(a.tokens.next.id),p=!0,a.funct["(scope)"].stack(),r=(c=a.tokens.curr.fud(m)).hasComma?c:null,i=c.hasInitializer?c:null;else if(!_X(a.tokens.next,";")){for(o=[];"in"!==a.tokens.next.value&&"of"!==a.tokens.next.value&&!_X(a.tokens.next,";");)_J(a.tokens.next,["{","["])?(_B(m,{assignment:!0}).forEach(function(_){this.push(_.token)},o),_X(a.tokens.next,"=")&&(V("="),i=a.tokens.curr,U(m,10))):(s=U(m,10))&&("(identifier)"===s.type?o.push(s):_X(s,"=")&&(i=s,o.push(s))),_X(a.tokens.next,",")&&(V(","),r||(r=a.tokens.curr));i||r||o.forEach(function(_){a.funct["(scope)"].has(_.value)||L("W088",_,_.value)})}if(n=a.tokens.next,h&&"of"!==n.value){L("E066",k=n,void 0,void 0,void 0,void 0)}if(t.includes(["in","of"],n.value)){if("of"===n.value?(u=20,a.inES6()||L("W104",n,"for of","6")):u=0,r){x=r,L("W133",x,b=n.value,"more than one ForBinding",void 0,void 0)}if(i){E=i,L("W133",E,A=n.value,"initializer is forbidden",void 0,void 0)}if(!s||r||i||_7(_,s,n),V(n.value),U(_,u),V(")",d),"in"===n.value&&a.option.forin&&(a.forinifcheckneeded=!0,void 0===a.forinifchecks&&(a.forinifchecks=[]),a.forinifchecks.push({type:"(none)"})),a.funct["(breakage)"]+=1,a.funct["(loopage)"]+=1,l=_d(_,!0,!0),"in"===n.value&&a.option.forin){if(a.forinifchecks&&a.forinifchecks.length>0){var y,k,x,b,E,A,S=a.forinifchecks.pop();(l&&l.length>0&&("object"!=typeof l[0]||"if"!==l[0].value)||"(positive)"===S.type&&l.length>1||"(negative)"===S.type)&&L("W089",this)}a.forinifcheckneeded=!1}a.funct["(breakage)"]-=1,a.funct["(loopage)"]-=1}else{if(v){L("E045",$=v,void 0,void 0,void 0,void 0)}if(V(";"),c&&c.first&&c.first[0]&&("const"!==c.value||c.hasInitializer||L("E012",c,c.first[0].value),c.first.forEach(function(_){a.funct["(scope)"].initialize(_.value)})),a.funct["(loopage)"]+=1,";"!==a.tokens.next.id&&_w(U(_,0)),V(";"),";"===a.tokens.next.id){L("E021",e=a.tokens.next,")",";",void 0,void 0)}if(")"!==a.tokens.next.id)for(;U(_,0),","===a.tokens.next.id;)V(","),q();V(")",d),a.funct["(breakage)"]+=1,_d(_,!0,!0),a.funct["(breakage)"]-=1,a.funct["(loopage)"]-=1}return p&&a.funct["(scope)"].unstack(),this}).labelled=!0,J("break",function(){var _=a.tokens.next.value;return a.tokens.next.identifier&&z(a.tokens.curr,a.tokens.next)?(a.funct["(scope)"].funct.hasLabel(_)||L("W090",a.tokens.next,_),this.first=a.tokens.next,V()):0===a.funct["(breakage)"]&&L("W052",a.tokens.next,this.value),_a(this),this}).exps=!0,J("continue",function(){var _=a.tokens.next.value;return 0!==a.funct["(breakage)"]&&a.funct["(loopage)"]||L("W052",a.tokens.next,this.value),a.tokens.next.identifier&&z(a.tokens.curr,a.tokens.next)&&(a.funct["(scope)"].funct.hasLabel(_)||L("W090",a.tokens.next,_),this.first=a.tokens.next,V()),_a(this),this}).exps=!0,J("return",function(_){return z(this,a.tokens.next)?";"!==a.tokens.next.id&&!a.tokens.next.reach&&(this.first=U(_,0),!this.first||"(punctuator)"!==this.first.type||"="!==this.first.value||this.first.paren||a.option.boss||L("W093",this.first),a.option.noreturnawait&&_&f.async&&!(_&f.tryClause)&&this.first.identifier&&"await"===this.first.value&&L("W146",this.first)):"(punctuator)"===a.tokens.next.type&&["[","{","+","-"].indexOf(a.tokens.next.value)>-1&&N(this),_a(this),this}).exps=!0,Y("await",function(_){if(!(_&f.async))return this.exps=!1,a.syntax["(identifier)"].nud.apply(this,arguments);if(!a.funct["(params)"]){var $;$=this,L("E024",$,"await",void 0,void 0,void 0)}return U(_,10),this}).exps=!0,(_O=Y("async",function(_,$){return this.isFunc(_)?(a.inES8()||L("W119",this,"async functions","8"),_|=f.preAsync,this.func=U(_,$),this.identifier=!1,this):(this.exps=!1,a.syntax["(identifier)"].nud.apply(this,arguments))})).meta={es5:!0,isFutureReservedWord:!0,strictOnly:!0},_O.isFunc=function(){var _,$=a.tokens.next;return this.line===$.line&&("function"===$.id||("("===$.id?"=>"===(_=_x(0)).id:!!$.identifier&&"=>"===P().id))},_O.useFud=_O.isFunc,_O.fud=function(_){return a.inES8()||L("W119",this,"async functions","8"),_|=f.preAsync,_|=f.initial,this.func=U(_,0),this.block=this.func.block,this.exps=this.func.exps,this},_O.exps=!0,delete _O.reserved,(_V=Y("yield",function(_){if(a.inMoz())return _U.call(this,_);if(!(_&f.yield))return this.exps=!1,a.syntax["(identifier)"].nud.apply(this,arguments);var $,e,t,n=a.tokens.prev;if(!a.funct["(params)"]){$=this,L("E024",$,"yield",void 0,void 0,void 0)}if(!this.beginsStmt&&n.lbp>30&&!_J(n,["("])){e=this,L("E061",e,void 0,void 0,void 0,void 0)}if(a.inES6()||L("W104",a.tokens.curr,"yield","6"),a.funct["(yielded)"]=!0,"*"===a.tokens.next.value&&V("*"),"*"===a.tokens.curr.value||z(a.tokens.curr,a.tokens.next)){if(a.tokens.next.nud)H(a.tokens.curr,a.tokens.next),this.first=U(_,10),"(punctuator)"!==this.first.type||"="!==this.first.value||this.first.paren||a.option.boss||L("W093",this.first);else if(a.tokens.next.led&&","!==a.tokens.next.id){L("W017",t=a.tokens.next,void 0,void 0,void 0,void 0)}}return this})).rbp=_V.lbp=25,_V.exps=!0;var _U=function(_){var $,e,t=a.tokens.prev;if(a.inES6(!0)&&!(_&f.yield)){L("E046",$=a.tokens.curr,"yield",void 0,void 0,void 0)}a.funct["(yielded)"]=!0;var n=!1;if("*"===a.tokens.next.value&&(n=!0,V("*")),z(this,a.tokens.next)){if(!n&&(";"===a.tokens.next.id||a.option.asi||a.tokens.next.reach||!a.tokens.next.nud)||(H(a.tokens.curr,a.tokens.next),this.first=U(_,10),"(punctuator)"!==this.first.type||"="!==this.first.value||this.first.paren||a.option.boss||L("W093",this.first)),")"!==a.tokens.next.id&&(t.lbp>30||!t.assign&&!R())){e=this,L("E050",e,void 0,void 0,void 0,void 0)}}else a.option.asi||N(this);return this};J("throw",function(_){return N(this),this.first=U(_,20),_a(this),this}).exps=!0,Y("import",function(_){var $=_D(_,"meta",function(){if(a.inES11(!0)||L("W119",a.tokens.prev,"import.meta","11"),!a.option.module){var _;L("E070",_=a.tokens.prev,void 0,void 0,void 0,void 0)}});return $||(_X(a.tokens.next,"(")?(a.inES11()||L("W119",a.tokens.curr,"dynamic import","11"),V("("),U(_,10),V(")"),this):a.syntax["(identifier)"].nud.call(this,_))});var _z=J("import",function(_){var $,e,t,n;if(!a.funct["(scope)"].block.isGlobal()){L("E053",$=a.tokens.curr,"Import",void 0,void 0,void 0)}if(a.inES6()||L("W119",a.tokens.curr,"import","6"),"(string)"===a.tokens.next.type)return V("(string)"),this;if(a.tokens.next.identifier){if(this.name=_o(_),a.funct["(scope)"].addbinding(this.name,{type:"import",initialized:!0,token:a.tokens.curr}),","!==a.tokens.next.value)return V("from"),V("(string)"),this;V(",")}if("*"===a.tokens.next.id)V("*"),V("as"),a.tokens.next.identifier&&(this.name=_o(_),a.funct["(scope)"].addbinding(this.name,{type:"import",initialized:!0,token:a.tokens.curr}));else for(V("{");;){if("}"===a.tokens.next.value){V("}");break}if("as"===P().value&&(_o(_,!0),V("as")),e=_o(_),a.funct["(scope)"].addbinding(e,{type:"import",initialized:!0,token:a.tokens.curr}),","===a.tokens.next.value)V(",");else if("}"===a.tokens.next.value){V("}");break}else{t=a.tokens.next,L("E024",t,n=a.tokens.next.value,void 0,void 0,void 0);break}}return V("from"),V("(string)"),this});function _H(_,$){return("call"!==_||!$["(async)"])&&("property"===_&&!!$["(method)"]||"call"===_&&!!$["(statement)"]&&"class"===$["(statement)"].id||!!$["(arrow)"]&&_H(_,$["(context)"]))}_z.exps=!0,_z.reserved=!0,_z.meta={isFutureReservedWord:!0,es5:!0},_z.useFud=function(){return!_J(a.tokens.next,[".","("])},_z.rbp=161,J("export",function(_){var $,e,t,n,r=!0;if(_|=f.export,a.inES6()||(L("W119",a.tokens.curr,"export","6"),r=!1),!a.funct["(scope)"].block.isGlobal()){L("E053",o=a.tokens.curr,"Export",void 0,void 0,void 0),r=!1}if("*"===a.tokens.next.value)return V("*"),"as"===a.tokens.next.value&&(a.inES11()||L("W119",a.tokens.curr,"export * as ns from","11"),V("as"),_o(_,!0),a.funct["(scope)"].setExported(null,a.tokens.curr)),V("from"),V("(string)"),this;if("default"===a.tokens.next.type){a.nameStack.set(a.tokens.next),V("default");var i=a.tokens.curr,u=a.tokens.next.id;return"function"===u?(this.block=!0,V("function"),t=a.syntax.function.fud(_),a.funct["(scope)"].setExported(t.name,i)):"async"===u&&"function"===P().id?(this.block=!0,V("async"),V("function"),t=a.syntax.function.fud(_|f.preAsync),a.funct["(scope)"].setExported(t.name,i)):"class"===u?(this.block=!0,V("class"),t=a.syntax.class.fud(_),a.funct["(scope)"].setExported(t.name,i)):(U(_,10),a.funct["(scope)"].setExported(null,i)),this}if("{"===a.tokens.next.value){V("{");for(var o,s,c,l,d,p=[];!_X(a.tokens.next,"}");){if(!a.tokens.next.identifier){s=a.tokens.next,L("E030",s,c=a.tokens.next.value,void 0,void 0,void 0)}if(V(),"as"===a.tokens.next.value){if(V("as"),!a.tokens.next.identifier){l=a.tokens.next,L("E030",l,d=a.tokens.next.value,void 0,void 0,void 0)}p.push({local:a.tokens.prev,export:a.tokens.next}),V()}else p.push({local:a.tokens.curr,export:a.tokens.curr});_X(a.tokens.next,"}")||V(",")}V("}"),"from"===a.tokens.next.value?(V("from"),n=a.tokens.next,V("(string)")):r&&p.forEach(function(_){a.funct["(scope)"].setExported(_.local,_.export)}),0===p.length&&(n?L("W142",this,"export",n.value):L("W141",this,"export"))}else if("var"===a.tokens.next.id)V("var"),(t=a.tokens.curr.fud(_)).first.forEach(function(_){a.funct["(scope)"].setExported(_,_)});else if("let"===a.tokens.next.id)V("let"),(t=a.tokens.curr.fud(_)).first.forEach(function(_){a.funct["(scope)"].setExported(_,_)});else if("const"===a.tokens.next.id)V("const"),(t=a.tokens.curr.fud(_)).first.forEach(function(_){a.funct["(scope)"].setExported(_,_)});else if("function"===a.tokens.next.id)this.block=!0,V("function"),t=a.syntax.function.fud(_),a.funct["(scope)"].setExported(t.name,t.name);else if("async"===a.tokens.next.id&&"function"===P().id)this.block=!0,V("async"),V("function"),t=a.syntax.function.fud(_|f.preAsync),a.funct["(scope)"].setExported(t.name,t.name);else if("class"===a.tokens.next.id)this.block=!0,V("class"),t=a.syntax.class.fud(_),a.funct["(scope)"].setExported(t.name,t.name);else{$=a.tokens.next,L("E024",$,e=a.tokens.next.value,void 0,void 0,void 0)}return this}).exps=!0;var _N=function(){var _,$,e,t,n=a.tokens.next;if(_J(n,["[","."])){if(!_H("property",a.funct)){_=this,L("E063",_,void 0,void 0,void 0,void 0)}}else if(_X(n,"(")){if(!_H("call",a.funct)){$=this,L("E064",$,void 0,void 0,void 0,void 0)}}else{e=n,L("E024",e,t=n.value||n.id,void 0,void 0,void 0)}return this};_0("abstract"),_0("boolean"),_0("byte"),_0("char"),_0("double"),_0("enum",{es5:!0}),_0("export",{es5:!0}),_0("extends",{es5:!0}),_0("final"),_0("float"),_0("goto"),_0("implements",{es5:!0,strictOnly:!0}),_0("int"),_0("interface",{es5:!0,strictOnly:!0}),_0("long"),_0("native"),_0("package",{es5:!0,strictOnly:!0}),_0("private",{es5:!0,strictOnly:!0}),_0("protected",{es5:!0,strictOnly:!0}),_0("public",{es5:!0,strictOnly:!0}),_0("short"),_0("static",{es5:!0,strictOnly:!0}),_0("synchronized"),_0("transient"),_0("volatile");var _q=function(){var _,$,e,t=-1,n=0,r={};_J(a.tokens.curr,["[","{"])&&(n+=1);do{if(e=-1===t?a.tokens.curr:_,_=-1===t?a.tokens.next:P(t),$=P(t+1),t+=1,_J(_,["[","{"])?n+=1:_J(_,["]","}"])&&(n-=1),1===n&&_.identifier&&"for"===_.value&&!_X(e,".")){r.isCompArray=!0,r.notJson=!0;break}if(0===n&&_J(_,["}","]"])){if("="===$.value){r.isDestAssign=!0,r.notJson=!0;break}if("."===$.value){r.notJson=!0;break}}_X(_,";")&&(r.notJson=!0)}while(n>0&&"(end)"!==_.id);return r};function _9(_,$,e,t,n,r){e.identifier&&($=e.value);var i=$;if(t&&n&&(i="static "+$),_[i]&&"__proto__"!==$&&!r){var u=["key","class method","static class method"];u=u[(t||!1)+(n||!1)],L("W075",a.tokens.next,u,$)}else _[i]=Object.create(null);_[i].basic=!0,_[i].basictkn=e}function _K(_,$,e,t,n,r){var i="get"===_?"getterToken":"setterToken",u=e;if(a.tokens.curr.accessorType=_,a.nameStack.set(t),n&&r&&(u="static "+e),$[u]){if(($[u].basic||$[u][i])&&"__proto__"!==e){var o="";n?(r&&(o+="static "),o+=_+"ter method"):o="key",L("W075",a.tokens.next,o,e)}}else $[u]=Object.create(null);$[u][i]=t,r&&($[u].static=!0)}function _Z(_){V("["),a.tokens.curr.delim=!0,a.tokens.curr.lbp=0,a.inES6()||L("W119",a.tokens.curr,"computed property names","6");var $=U(_&~f.noin,10);return V("]"),$}function _J(_,$){return"(punctuator)"===_.type&&t.includes($,_.value)}function _X(_,$){return"(punctuator)"===_.type&&_.value===$}var _Q=function(){var _,$=function(){this.mode="use",this.variables=[]},e=[];function n($){return 0===_.variables.filter(function(_){if(_.value===$&&!_.undef)return!0===_.unused&&(_.unused=!1),$}).length}return{stack:function(){_=new $,e.push(_)},unstack:function(){_.variables.filter(function(_){_.unused&&L("W098",_.token,_.token.raw_text||_.value),_.undef&&a.funct["(scope)"].block.use(_.value,_.token)}),e.splice(-1,1),_=e[e.length-1]},setState:function($){t.includes(["use","define","generate","filter"],$)&&(_.mode=$)},check:function($){if(_){if(_&&"use"===_.mode)return n($)&&_.variables.push({token:a.tokens.curr,value:$,undef:!0,unused:!1}),!0;if(_&&"define"===_.mode){var e;return e=$,0===_.variables.filter(function(_){if(_.value===e)return _.undef=!1,e}).length&&_.variables.push({token:a.tokens.curr,value:$,undef:!1,unused:!0}),!0}return _&&"generate"===_.mode?(a.funct["(scope)"].block.use($,a.tokens.curr),!0):!!_&&"filter"===_.mode&&(n($)&&a.funct["(scope)"].block.use($,a.tokens.curr),!0)}}}},_Y=function(_){return _.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")},$2=function(n,i,o){i=t.clone(i),a.reset(),C=a.option,F=a.ignored,i&&i.scope?d.scope=i.scope:(d.errors=[],d.internals=[],d.blacklist={},d.scope="(main)"),w(k=Object.create(null),r.ecmaIdentifiers[3]),w(k,r.reservedVars),$=Object.create(null);var s,c,f,x,S,C,F,B,G=Object.create(null);function I(_,$){_&&(Array.isArray(_)||"object"!=typeof _||(_=Object.keys(_)),_.forEach($))}if(i)for(I([i.predef,i.globals],function(_){I(_,function($){var e,t;"-"===$[0]?(e=$.slice(1),d.blacklist[e]=e,delete k[e]):(t=Object.getOwnPropertyDescriptor(_,$),k[$]=!!t&&t.value)})}),I(i.exported||null,function(_){G[_]=!0}),delete i.predef,delete i.exported,S=Object.keys(i),c=0;c0&&(i.implieds=u),(r=a.funct["(scope)"].getUsedOrDefinedGlobals()).length>0&&(i.globals=r),t=1;t0&&(i.unused=o),m)if("number"==typeof m[n]){i.member=m;break}return i},$2.jshint=$2,$2}();"object"==typeof e&&e&&(e.JSHINT=d)},{"./lex.js":17,"./messages.js":18,"./options.js":20,"./prod-params.js":21,"./reg.js":22,"./scope-manager.js":23,"./state.js":24,"./style.js":25,"./vars.js":27,"console-browserify":9,events:11,lodash:12}]},{},[]))("jshint").JSHINT,"object"==typeof exports&&exports&&(exports.JSHINT=JSHINT)}(); \ No newline at end of file diff --git a/scripts/build-ext-demo.js b/scripts/build-ext-demo.js deleted file mode 100644 index e614fff8..00000000 --- a/scripts/build-ext-demo.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file Build extension pages demonstration using the Vite JavaScript API - * @see {@link https://vitejs.dev/guide/api-javascript.html JavaScript API} - */ - -import { build } from "vite"; -import { svelte } from "@sveltejs/vite-plugin-svelte"; -import * as Utils from "./utils.js"; - -/** @type {import("vite").InlineConfig} */ -const sharedConfig = { - ...Utils.baseConfig, - mode: "development", - - define: { - ...Utils.baseConfig.define, - "import.meta.env.SAFARI_VERSION": JSON.stringify(15), - "import.meta.env.EXT_DEMO_BUILD": JSON.stringify(true), - }, -}; - -/** - * Empty resources directory - * Copy public static assets - */ -await Utils.emptyBuildDir("dist"); -Utils.cp("public/ext/shared", "dist"); - -/** Build shared modules */ -build({ - ...sharedConfig, - plugins: [svelte()], - publicDir: "public/ext/vendor/", - build: { - outDir: `dist/`, - emptyOutDir: false, - rollupOptions: { - input: ["entry-ext-action-popup.html", "entry-ext-extension-page.html"], - }, - target: "esnext", // top-level await - }, -}); diff --git a/scripts/build-safari-15.js b/scripts/build-safari-15.js deleted file mode 100644 index 1466bf15..00000000 --- a/scripts/build-safari-15.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @file Build App-WebView and Safari-Extension resources using the Vite JavaScript API - * @see {@link https://vitejs.dev/guide/api-javascript.html JavaScript API} - * - * Safari supports for modules in background since 16.4 - * @see {@link https://developer.apple.com/documentation/safari-release-notes/safari-16_4-release-notes#Safari-Extensions} - * @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/background#browser_compatibility} - * To ensure forward compatibility, background script use independent builds for safari 15 - * - * Content scripts not support import modules, and due to their privileges and the - * speed of injecting user scripts, use a independent build currently - * - * All build processes start at the same time due to asynchronous calls - * The assets name is irrelevant, just need to determine the entry path - */ - -import { build } from "vite"; -import { svelte } from "@sveltejs/vite-plugin-svelte"; -import pluginMarkedDivest from "./vite-plugin-marked-divest.js"; -import * as Utils from "./utils.js"; - -/** @type {import("vite").InlineConfig} */ -const sharedConfig = { - ...Utils.baseConfig, - define: { - ...Utils.baseConfig.define, - "import.meta.env.SAFARI_VERSION": JSON.stringify(15), - }, - build: { - sourcemap: process.env.BETA ? true : false, - target: "safari15", - }, -}; - -/** - * Build App-Shared WebView resources to xcode dist - */ -build({ - ...Utils.baseConfig, - plugins: [svelte(), pluginMarkedDivest()], - build: { - ...sharedConfig.build, - outDir: `${Utils.APP_SHARED_RESOURCES}/dist/`, - copyPublicDir: false, - rollupOptions: { - input: "entry-app-webview.html", - }, - }, -}); - -/** - * Empty resources directory - * Copy public static assets - */ -await Utils.emptyBuildDir(Utils.EXT_SAFARI_RESOURCES); -Utils.cp("public/ext/shared", Utils.EXT_SAFARI_RESOURCES); -Utils.cp("public/ext/safari-15", Utils.EXT_SAFARI_RESOURCES); - -/** Build content scripts */ -[ - { userscripts: "src/ext/content-scripts/entry-userscripts.js" }, - { "dot-user-js": "src/ext/content-scripts/entry-dot-user-js.js" }, - { "script-market": "src/ext/content-scripts/entry-script-market.js" }, -].forEach((input) => { - build({ - ...sharedConfig, - build: { - ...sharedConfig.build, - outDir: `${Utils.EXT_SAFARI_RESOURCES}/dist/content-scripts/`, - emptyOutDir: false, - copyPublicDir: false, - rollupOptions: { - input, - output: { entryFileNames: "[name].js" }, - }, - }, - }); -}); - -/** Build background scripts */ -build({ - ...sharedConfig, - build: { - ...sharedConfig.build, - outDir: `${Utils.EXT_SAFARI_RESOURCES}/dist/`, - emptyOutDir: false, - copyPublicDir: false, - rollupOptions: { - input: { background: "src/ext/background/main.js" }, - output: { entryFileNames: "[name].js" }, - }, - }, -}); - -/** Build shared modules */ -build({ - ...sharedConfig, - plugins: [svelte()], - publicDir: "public/ext/vendor/", - build: { - ...sharedConfig.build, - outDir: `${Utils.EXT_SAFARI_RESOURCES}/dist/`, - emptyOutDir: false, - rollupOptions: { - input: ["entry-ext-action-popup.html", "entry-ext-extension-page.html"], - }, - }, -}); diff --git a/scripts/build-safari-16.4.js b/scripts/build-safari-16.4.js deleted file mode 100644 index 866b844d..00000000 --- a/scripts/build-safari-16.4.js +++ /dev/null @@ -1,116 +0,0 @@ -/** - * @file Build App-WebView and Safari-Extension resources using the Vite JavaScript API - * @see {@link https://vitejs.dev/guide/api-javascript.html JavaScript API} - * - * Safari supports for modules in background since 16.4 - * @see {@link https://developer.apple.com/documentation/safari-release-notes/safari-16_4-release-notes#Safari-Extensions} - * @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/background#browser_compatibility} - * - * Content scripts not support import modules, and due to their privileges and the - * speed of injecting user scripts, use a independent build currently - * - * All build processes start at the same time due to asynchronous calls - * The assets name is irrelevant, just need to determine the entry path - */ - -import { build } from "vite"; -import { svelte } from "@sveltejs/vite-plugin-svelte"; -import pluginMarkedDivest from "./vite-plugin-marked-divest.js"; -import * as Utils from "./utils.js"; - -/** @type {import("vite").InlineConfig} */ -const sharedConfig = { - ...Utils.baseConfig, - define: { - ...Utils.baseConfig.define, - "import.meta.env.SAFARI_VERSION": JSON.stringify(16.4), - }, - build: { - sourcemap: process.env.BETA ? true : false, - target: "safari16.4", - }, -}; - -/** - * Build App-Shared WebView resources to xcode dist - */ -build({ - ...Utils.baseConfig, - plugins: [svelte(), pluginMarkedDivest()], - build: { - ...sharedConfig.build, - outDir: `${Utils.APP_SHARED_RESOURCES}/dist/`, - copyPublicDir: false, - rollupOptions: { - input: "entry-app-webview.html", - }, - }, -}); - -/** - * Empty resources directory - * Copy public static assets - */ -await Utils.emptyBuildDir(Utils.EXT_SAFARI_RESOURCES); -Utils.cp("public/ext/shared", Utils.EXT_SAFARI_RESOURCES); -Utils.cp("public/ext/safari-16.4", Utils.EXT_SAFARI_RESOURCES); - -/** Build content scripts */ -[ - { userscripts: "src/ext/content-scripts/entry-userscripts.js" }, - { "dot-user-js": "src/ext/content-scripts/entry-dot-user-js.js" }, - { "script-market": "src/ext/content-scripts/entry-script-market.js" }, -].forEach((input) => { - build({ - ...sharedConfig, - build: { - ...sharedConfig.build, - outDir: `${Utils.EXT_SAFARI_RESOURCES}/dist/content-scripts/`, - emptyOutDir: false, - copyPublicDir: false, - rollupOptions: { - input, - output: { entryFileNames: "[name].js" }, - }, - }, - }); -}); - -/** - * Build background scripts - * Modular background may not load correctly on Safari startup - * Currently build classic script separately to avoid this error - */ -build({ - ...sharedConfig, - build: { - ...sharedConfig.build, - outDir: `${Utils.EXT_SAFARI_RESOURCES}/dist/`, - emptyOutDir: false, - copyPublicDir: false, - rollupOptions: { - input: { background: "src/ext/background/main.js" }, - output: { entryFileNames: "[name].js" }, - }, - }, -}); - -/** Build shared modules */ -build({ - ...sharedConfig, - plugins: [svelte()], - publicDir: "public/ext/vendor/", - build: { - ...sharedConfig.build, - outDir: `${Utils.EXT_SAFARI_RESOURCES}/dist/`, - emptyOutDir: false, - rollupOptions: { - input: { - // background: "src/ext/background/main.js", - "action-popup": "entry-ext-action-popup.html", - "extension-page": "entry-ext-extension-page.html", - }, - output: { entryFileNames: "[name].js" }, - }, - }, -}); diff --git a/scripts/dev-safari.js b/scripts/dev-safari.js deleted file mode 100644 index c9236b9f..00000000 --- a/scripts/dev-safari.js +++ /dev/null @@ -1,211 +0,0 @@ -/** - * @file Develop Safari extension resources using the Vite JavaScript API - * @see {@link https://vitejs.dev/guide/api-javascript.html JavaScript API} - * This development build and server requires a valid https certificate to support remote real-time development - * Typically using a self-signed certificate, it needs to be installed and trusted by the device or simulator - * @see {@link https://developer.apple.com/library/archive/qa/qa1948/} - * @see {@link https://developer.apple.com/library/archive/technotes/tn2326/} - */ - -import { build, createServer } from "vite"; -import { svelte } from "@sveltejs/vite-plugin-svelte"; -import * as Utils from "./utils.js"; -import https from "node:https"; - -/** @type {import("vite").InlineConfig} */ -const sharedConfig = { - ...Utils.baseConfig, - mode: "development", - define: { - ...Utils.baseConfig.define, - "import.meta.env.SAFARI_VERSION": JSON.stringify(16.4), - }, -}; - -/** - * Build resources for remote real-time development - * @param {import("vite").ViteDevServer} server - * @param {string} origin - */ -async function buildResources(server, origin) { - /** - * empty resources directory - * copy public static assets - */ - await Utils.emptyBuildDir("dist"); - await Utils.emptyBuildDir(Utils.EXT_SAFARI_RESOURCES); - Utils.cp("public/ext/shared", Utils.EXT_SAFARI_RESOURCES); - Utils.cp("public/ext/shared-dev", Utils.EXT_SAFARI_RESOURCES); - if (process.env.SAFARI_PLATFORM === "ios") { - Utils.cp( - "public/ext/safari-dev/manifest-ios.json", - `${Utils.EXT_SAFARI_RESOURCES}/manifest.json`, - ); - } else { - Utils.cp( - "public/ext/safari-dev/manifest-mac.json", - `${Utils.EXT_SAFARI_RESOURCES}/manifest.json`, - ); - } - - /** build content scripts */ - [ - { userscripts: "src/ext/content-scripts/entry-userscripts.js" }, - { "dot-user-js": "src/ext/content-scripts/entry-dot-user-js.js" }, - { "script-market": "src/ext/content-scripts/entry-script-market.js" }, - ].forEach((input) => { - /** build proxy content scripts replace actual code */ - build({ - ...sharedConfig, - plugins: [ - { - name: "generate-content-proxy", - load(id) { - const name = id.replace(/.+entry-/, ""); - const url = `${origin}/dist/content-scripts/${name}`; - return `// proxy content - (function () { - if (window["${id}"]) return; - window["${id}"] = 1; - const xhr = new XMLHttpRequest(); - xhr.open("GET", "${url}", false); - xhr.send(); - const code = xhr.responseText; - try { - Function(code + "//# sourceURL=proxy-${name}")(); - } catch (error) { - console.error(error); - } - })();`; - }, - }, - ], - build: { - outDir: `${Utils.EXT_SAFARI_RESOURCES}/dist/content-scripts/`, - emptyOutDir: false, - copyPublicDir: false, - rollupOptions: { - input, - output: { entryFileNames: "[name].js" }, - }, - }, - }); - /** build content scripts for dev server and watch changes */ - build({ - ...sharedConfig, - build: { - outDir: `dist/content-scripts/`, - emptyOutDir: false, - copyPublicDir: false, - rollupOptions: { - input, - output: { entryFileNames: "[name].js" }, - }, - watch: {}, - minify: false, - }, - }); - }); - - /** generate entrance dist */ - build({ - ...sharedConfig, - publicDir: "public/ext/vendor/", - plugins: [ - /** - * @see {@link https://github.com/vitejs/vite/issues/14263} - * Dev only requires entrances, so order `pre` without transform modules - */ - { - name: "generate-dev-entrance", - transformIndexHtml: { - order: "pre", - async handler(html, ctx) { - const str = await server.transformIndexHtml(ctx.path, html); - return str.replaceAll(`src="/`, `src="${origin}/`); - }, - }, - }, - ], - build: { - outDir: `${Utils.EXT_SAFARI_RESOURCES}/dist/`, - emptyOutDir: false, - rollupOptions: { - input: { - background: "entry-ext-background.html", - "action-popup": "entry-ext-action-popup.html", - "extension-page": "entry-ext-extension-page.html", - }, - }, - }, - }); -} - -/** - * Define shared constants - * Developing in native machine and simulator can just use `https://localhost:port/` as the origin - * But using a fixed domain name on non-native devices such as real iOS devices is a better choice - * The local domain name needs to be resolved to the LAN IP address on LAN DNS or the target device - * When the origin specified here is unreachable, localhost will be automatically used as the alternate - * The origin requires as an exemption to be added to the `manifest.json` due to default CSP limitations - * @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_Security_Policy} - * @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_security_policy} - */ -const serverOptions = await Utils.sharedServerOptions(); -const SERVER_PORT = 55173; -const SERVER_ORIGIN = `https://userscripts.test:${SERVER_PORT}`; - -/** - * Check if the server is reachable with self-signed certificate - * @param {string | URL} url - * @returns {Promise} - */ -async function serverCheck(url) { - const options = { - method: "HEAD", - ca: serverOptions.ca, - headers: { Accept: "*/*" }, - }; - return new Promise((resolve) => { - const req = https.request(url, options, (res) => { - if (res.headers.server === SERVER_ORIGIN) { - resolve(true); - } - resolve(false); - }); - req.on("error", (e) => { - console.error(`${req.host}: ${e.message}`); - resolve(false); - }); - req.end(); - }); -} - -/** main process */ -(async () => { - /** run development server */ - const server = await createServer({ - ...sharedConfig, - publicDir: "public/ext/vendor/", - plugins: [svelte()], - server: { - host: true, - port: SERVER_PORT, - strictPort: true, - https: { key: serverOptions.key, cert: serverOptions.cert }, - headers: { server: SERVER_ORIGIN }, - }, - }); - await server.listen(); - server.printUrls(); - - // Check available origins and build resources - for (let url of [SERVER_ORIGIN, ...server.resolvedUrls.local]) { - if (await serverCheck(url)) { - const origin = url.at(-1) === "/" ? url.slice(0, -1) : url; - console.info(`build with origin: ${origin}`); - buildResources(server, origin); - break; - } - } -})(); diff --git a/scripts/jsconfig.json b/scripts/jsconfig.json deleted file mode 100644 index f0633242..00000000 --- a/scripts/jsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -// https://code.visualstudio.com/docs/languages/jsconfig -// https://www.typescriptlang.org/docs/handbook/tsconfig-json.html -// https://www.typescriptlang.org/tsconfig - -// https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html -// https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html - -{ - "compilerOptions": { - "target": "ESNext", - "module": "NodeNext", - "moduleResolution": "nodenext", - - "verbatimModuleSyntax": true, - "isolatedModules": true, - "resolveJsonModule": true, - - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "skipLibCheck": true, - "sourceMap": true - }, - "include": ["**/*.d.ts", "**/*.js"] -} diff --git a/scripts/preview-app.js b/scripts/preview-app.js deleted file mode 100644 index 1c1ad4eb..00000000 --- a/scripts/preview-app.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @file Preview App WebView resources using the Vite JavaScript API - * @see {@link https://vitejs.dev/guide/api-javascript.html JavaScript API} - */ - -import { preview } from "vite"; -import { baseConfig } from "./utils.js"; - -/** - * Preview App-Shared WebView resources from xcode dist - */ -(async () => { - const previewServer = await preview({ - ...baseConfig, - preview: { - // port: 4173, - open: "entry-app-webview.html", - }, - build: { - outDir: "xcode/App-Shared/Resources/dist/", - }, - }); - previewServer.printUrls(); -})(); diff --git a/scripts/preview-ext-demo.js b/scripts/preview-ext-demo.js deleted file mode 100644 index a14b0a9a..00000000 --- a/scripts/preview-ext-demo.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @file Preview App WebView resources using the Vite JavaScript API - * @see {@link https://vitejs.dev/guide/api-javascript.html JavaScript API} - */ - -import { preview } from "vite"; -import { baseConfig } from "./utils.js"; - -/** - * Preview App-Shared WebView resources from xcode dist - */ -(async () => { - const previewServer = await preview({ - ...baseConfig, - preview: { - // port: 4173, - open: "entry-ext-extension-page.html", - }, - build: { - outDir: "dist/", - }, - }); - previewServer.printUrls(); -})(); diff --git a/scripts/utils.js b/scripts/utils.js deleted file mode 100644 index e0069126..00000000 --- a/scripts/utils.js +++ /dev/null @@ -1,201 +0,0 @@ -/** - * node:process - * @see {@link https://nodejs.org/api/process.html#processchdirdirectory chdir} - * @see {@link https://nodejs.org/api/process.html#processcwd cwd} - * node:child_process - * @see {@link https://nodejs.org/api/child_process.html#child_processexecfilefile-args-options-callback execFile} - * node:util - * @see {@link https://nodejs.org/api/util.html#utilpromisifyoriginal promisify} - * node:url - * @see {@link https://nodejs.org/api/url.html#urlfileurltopathurl fileURLToPath} - * node:fs/promises - * @see {@link https://nodejs.org/api/fs.html#fspromisescopyfilesrc-dest-mode copyFile} - * @see {@link https://nodejs.org/api/fs.html#fspromisesmkdirpath-options mkdir} - * @see {@link https://nodejs.org/api/fs.html#fspromisesreaddirpath-options readdir} - * @see {@link https://nodejs.org/api/fs.html#fspromisesreadfilepath-options readFile} - * @see {@link https://nodejs.org/api/fs.html#fspromisesrealpathpath-options realpath} - * @see {@link https://nodejs.org/api/fs.html#fspromisesrmpath-options rm} - * @see {@link https://nodejs.org/api/fs.html#fspromisesstatpath-options stat} - */ -import { chdir, cwd } from "node:process"; -import { execFile } from "node:child_process"; -import { promisify } from "node:util"; -import { fileURLToPath } from "node:url"; -import { - copyFile, - mkdir, - readdir, - readFile, - realpath, - rm, - stat, -} from "node:fs/promises"; - -/** Promisified execFile */ -const execFileAsync = promisify(execFile); - -/** Define shared constants */ -export const APP_SHARED_RESOURCES = "xcode/App-Shared/Resources"; -export const EXT_SAFARI_RESOURCES = "xcode/Ext-Safari/Resources"; - -/** - * If not then cd to root dir and returns the path - * @see {@link https://nodejs.org/api/esm.html#importmetaurl} - * @returns {Promise} project root directory - */ -export async function rootDir() { - const root = fileURLToPath(new URL("..", import.meta.url)); - if (cwd() !== (await realpath(root))) { - chdir(root); - console.info("cd:", root); - } - return root; -} - -/** - * Empty the build directory safely - * @see {@link https://nodejs.org/api/errors.html#common-system-errors ENOENT} - * @param {string} dir - * @returns {Promise} - */ -export async function emptyBuildDir(dir) { - const buildPaths = ["dist", EXT_SAFARI_RESOURCES]; - if (!buildPaths.includes(dir)) { - console.error("Non-build path, cannot be empty."); - return false; - } - const root = await rootDir(); - try { - for (const sub of await readdir(dir)) { - const path = `${root}/${dir}/${sub}`; - // console.log("rm:", path); // DEBUG - await rm(path, { force: true, recursive: true }); - } - return true; - } catch (error) { - if (error.code === "ENOENT") { - console.info("[SKIPPED] emptyBuildDir:", error.message); - return true; - } - console.error("emptyBuildDir:", error); - return false; - } -} - -/** - * Copy a file or folder recursively - * @param {string} src Source file or directory - * @param {string} dest Destination file or directory - */ -export async function cp(src, dest) { - // console.log("cp:", src, "->", dest); // DEBUG - await rootDir(); - const srcStat = await stat(src); - if (srcStat.isFile()) return copyFile(src, dest); - if (!srcStat.isDirectory()) return; - await mkdir(dest, { recursive: true }); - for (const sub of await readdir(src)) { - if ([".DS_Store"].includes(sub)) continue; - await cp(`${src}/${sub}`, `${dest}/${sub}`); - } -} - -/** - * Read file and return text - * @param {string} file file path - * @returns {Promise} file content - */ -export async function read(file) { - const path = fileURLToPath(new URL(file, import.meta.url)); - return readFile(path, "utf8"); -} - -/** - * @see {@link https://vitejs.dev/config/server-options.html#server-https} - * @see {@link https://nodejs.org/api/https.html#https_https_createserver_options_requestlistener} - * @returns {Promise} https.ServerOptions - */ -export const sharedServerOptions = async () => ({ - ca: await read("./local/ca.pem"), - key: await read("./local/key.pem"), - cert: await read("./local/cert.pem"), -}); - -/** - * @see {@link https://git-scm.com/docs/git-describe} - * @returns {Promise} git tag, eg: v5.0.0-beta.1 - */ -async function getGitTag() { - try { - const { stdout, stderr } = await execFileAsync("git", [ - "describe", - "--tags", - "--abbrev=0", - ]); - stderr && console.log(stderr); - if (stdout) return stdout.trim(); - } catch (error) { - console.error(error); - process.exit(error.code); - } -} - -/** - * @see {@link https://git-scm.com/docs/git-rev-parse} - * @returns {Promise} git commit, eg: 700c978ccbd387921084ee185f495aa1f795d2e0 - */ -async function getGitCommit() { - try { - const { stdout, stderr } = await execFileAsync("git", [ - "rev-parse", - "HEAD", - ]); - stderr && console.log(stderr); - if (stdout) return stdout.trim(); - } catch (error) { - console.error(error); - process.exit(error.code); - } -} - -const gitTag = await getGitTag(); -const gitCommit = await getGitCommit(); -if (!gitTag || !gitCommit) { - console.error("Failed to get git infos, please check."); - process.exit(1); -} - -/** - * Define default vite config options - * Disable auto resolving {@link vite.config.js} - * @see {@link https://vitejs.dev/config/ Config} - * @see {@link https://vitejs.dev/guide/api-javascript.html#inlineconfig InlineConfig} - * @type {import("vite").InlineConfig} - */ -export const baseConfig = { - configFile: false, - envFile: false, - root: await rootDir(), - base: "./", - define: process.env.SAFARI_PLATFORM - ? { - "import.meta.env.BROWSER": JSON.stringify("Safari"), - "import.meta.env.NATIVE_APP": JSON.stringify("app"), - "import.meta.env.SAFARI_PLATFORM": JSON.stringify( - process.env.SAFARI_PLATFORM, - ), - "import.meta.env.GIT_TAG": JSON.stringify(gitTag), - "import.meta.env.GIT_COMMIT": JSON.stringify(gitCommit), - } - : { - "import.meta.env.GIT_TAG": JSON.stringify(gitTag), - "import.meta.env.GIT_COMMIT": JSON.stringify(gitCommit), - }, - resolve: { - alias: { - // NOTE: Don't forget to modify the `paths` in `jsconfig.json` also - "@shared": fileURLToPath(new URL("../src/shared", import.meta.url)), - "@ext": fileURLToPath(new URL("../src/ext/shared", import.meta.url)), - }, - }, -}; diff --git a/scripts/vite-plugin-marked-divest.js b/scripts/vite-plugin-marked-divest.js deleted file mode 100644 index 27093567..00000000 --- a/scripts/vite-plugin-marked-divest.js +++ /dev/null @@ -1,89 +0,0 @@ -import { fileURLToPath } from "node:url"; -import { readFile } from "node:fs/promises"; -import { marked } from "marked"; - -/** - * Exclude files that do not need to be processed - * @param {string} id - * @returns {boolean} - */ -function isExclude(id) { - const res = [/\/src\/app\/_locales\/[A-Za-z0-9_]+\/messages\.js/]; - for (const re of res) { - if (re.test(id)) return false; - } - return true; -} - -/** - * Preprocess `marked` calls and `.md?raw` transformations at build time - * to avoid including `marked` modules and runtime transformations - * @returns {import('vite').Plugin} - */ -function preprocessMarked() { - return { - name: "preprocess-marked", - resolveId: { - order: "pre", - handler(source, importer) { - if (isExclude(importer)) return; - if (source.endsWith(".md?raw")) { - const importerUrl = new URL(importer, import.meta.url); - const sourceUrl = new URL(source, importerUrl); - return fileURLToPath(sourceUrl) + "?marked"; - } - }, - }, - load: { - order: "pre", - async handler(id) { - if (!id.endsWith(".md?marked")) return; - const url = new URL(id, import.meta.url); - const text = await readFile(fileURLToPath(url), "utf8"); - const html = await marked.parse(text); - return `export default ${JSON.stringify(html)}`; - }, - }, - transform(code, id) { - if (isExclude(id)) return; - if (!code.includes("marked.parse")) return; - const node = this.parse(code); - if (node.sourceType !== "module") return; - for (const module of node.body) { - if (module.type !== "ImportDeclaration") continue; - if (!module.source.value.toString().endsWith(".md?raw")) continue; - const specifier = module.specifiers.find( - (specifier) => specifier.type === "ImportDefaultSpecifier", - ); - const varName = specifier.local.name; - code = code.replace(`await marked.parse(${varName})`, varName); - // console.debug(`optimizing 'await marked.parse(${varName})'`, id); // DEBUG - } - return { code }; - }, - }; -} - -/** - * Turn off `Marked` module side effects for better tree-shaking - * @returns {import('vite').Plugin} - */ -function disableMarkedSideEffects() { - return { - name: "disable-marked-side-effects", - transform(code, id) { - if (id.includes("/node_modules/marked")) { - return { code, moduleSideEffects: false }; - } - }, - }; -} - -/** - * @returns {import('vite').Plugin[]} - */ -function markedDivest() { - return [disableMarkedSideEffects(), preprocessMarked()]; -} - -export default markedDivest; diff --git a/src/app/App.svelte b/src/app/App.svelte deleted file mode 100644 index bbfe8df8..00000000 --- a/src/app/App.svelte +++ /dev/null @@ -1,407 +0,0 @@ - - - - -
- {#await initialize() then app} - {#if OOBE} -
-
{gl("quick_start_guide_title")}
- - {@html OOBEText} - -
- {/if} - {#if promptLogger} - - {/if} - {#if enableLogger} -
- - - - -
- {/if} -
-
-
-
- {#if import.meta.env.GIT_TAG && import.meta.env.GIT_COMMIT} - - {import.meta.env.GIT_TAG} - - ( - {import.meta.env.GIT_COMMIT.slice(0, 7)} - ) - {:else} - v{app.version} - ({app.build}) - {/if} -
- {#if platform === "mac"} -
- - {gl("safari_extension_status")}: - {gl(extStatus)} -
- - {/if} -
-
- -
-
- -
{gl("current_directory")}
- -
- - {:catch error} -
- {error} -
- {/await} -
- - diff --git a/src/app/_locales/en/messages.js b/src/app/_locales/en/messages.js deleted file mode 100644 index 4cee3c24..00000000 --- a/src/app/_locales/en/messages.js +++ /dev/null @@ -1,85 +0,0 @@ -import nativeLoggerCaveat from "./native-logger-caveat.md?raw"; -import quickStartGuideMac from "./quick-start-guide-mac.md?raw"; -import quickStartGuideIos from "./quick-start-guide-ios.md?raw"; - -import { marked } from "marked"; - -/** @satisfies {Types.I18nMessages} */ -export const markdown = { - native_logger_caveat: { - message: await marked.parse(nativeLoggerCaveat), - }, - quick_start_guide_mac: { - message: await marked.parse(quickStartGuideMac), - }, - quick_start_guide_ios: { - message: await marked.parse(quickStartGuideIos), - }, -}; - -/** @satisfies {Types.I18nMessages} */ -export const messages = { - enabled: { - message: "Enabled", - }, - disabled: { - message: "Disabled", - }, - unknown: { - message: "Unknown", - }, - error: { - message: "Error", - }, - button_ok: { - message: "OK", - }, - button_dismiss: { - message: "Dismiss", - }, - button_disable: { - message: "Disable", - }, - safari_extension_status: { - message: "Safari Extension Status", - }, - native_logger_enabled_title: { - message: "Native Logger Enabled", - }, - quick_start_guide_title: { - message: "Quick Start Guide", - }, - open_safari_settings: { - message: "Open Safari Settings", - }, - open_safari_preferences: { - message: "Open Safari Preferences", - }, - show_usage_guide: { - message: "Show Usage Guide", - }, - change_directory: { - message: "Change Userscripts Directory", - }, - current_directory: { - message: "CURRENT DIRECTORY:", - }, - documentation: { - message: "Documentation", - }, - discussions: { - message: "Discussions", - }, - report_an_issue: { - message: "Report an Issue", - }, - privacy_policy: { - message: "Privacy Policy", - }, - export_log_files: { - message: "Export log files", - }, - disable_logger: { - message: "Disable Logger", - }, -}; diff --git a/src/app/_locales/en/native-logger-caveat.md b/src/app/_locales/en/native-logger-caveat.md deleted file mode 100644 index f1ba6b62..00000000 --- a/src/app/_locales/en/native-logger-caveat.md +++ /dev/null @@ -1,5 +0,0 @@ -- The logger is for local debugging only and can be streamed through the macOS console while writing to a local file when enabled. -- You can repeat the steps to reproduce the issue after enabling it, then export the log files and inspect them in the app. -- There is no built-in upload function. If you need to submit it to developers, please manually attach the exported log files to your issue report. -- To reduce energy consumption and disk reading and writing, please disbale the logger promptly after debugging. -- If the log file exceeds $1, the logger will be automatically disbaled and the log files will be cleared. diff --git a/src/app/_locales/en/quick-start-guide-ios.md b/src/app/_locales/en/quick-start-guide-ios.md deleted file mode 100644 index 4bc2316b..00000000 --- a/src/app/_locales/en/quick-start-guide-ios.md +++ /dev/null @@ -1,27 +0,0 @@ -### Welcome, follow these two main steps to get the extension up and running: - -- **Open the app and set a directory** - - - When you first launch the app, a local directory will be set by default. - - If needed, you can select a new directory to suit your preferences. - - This directory is used for saving and loading your user scripts. - - Click the current directory to jump to the default directory or the one you set. - -- **Enable the extension in Safari** - - - Manage extensions from the Settings App (Settings > Safari > Extensions) or Safari App (`AA` button on iPhone, `extension-icon` on iPad, the same location where you open the extension's `popup` interface). - - For an optimal experience it's recommended that you "Always Allow" Userscripts for "All Websites", but you could also allow only the sites you want, but please don't forget your settings if your script doesn't work. - -### How to install and inject a user script and some things to note: - -- The mobile extension does not currently have a built-in script editor, but you could still write your own scripts and install them. -- You could save files that extension with `.user.js` directly to the Userscripts directory. - - The script file must contain a valid metadata block to match the web pages and be displayed in the extension popup. -- When you visit a `.user.js` URL in Safari, open the extension popup and you will see an installation prompt, or it will pop up automatically if you have enhanced prompts turned on. - - The URL should end with `.user.js` in `/PATH` part, not the `?QUERY` or `#HASH` parts, otherwise it will not be considered a valid user script URL by the extension. -- When you enabled the extension and write the metadata correctly especially like `@match`, it will automatically complete the injection when you visit a matching web page. - - You could temporarily disable individual user scripts or all of them, just open the extension popup interface to toggle them. - -### That’s it, start improving your quality of life now! - -_Hey, don't forget to read our detailed documentation to learn more._ diff --git a/src/app/_locales/en/quick-start-guide-mac.md b/src/app/_locales/en/quick-start-guide-mac.md deleted file mode 100644 index c6ae6ef7..00000000 --- a/src/app/_locales/en/quick-start-guide-mac.md +++ /dev/null @@ -1,27 +0,0 @@ -### Welcome to this project, you will need two main steps to make the extension work: - -- **Open the app and set a directory** - - - When you first launch the app, a local directory will be set by default. - - If needed, you can select a new directory to suit your preferences. - - This directory is used for saving and loading your user scripts. - - Click the current directory to jump to the default directory or the one you set. - -- **Enable the extension in Safari** - - - Enable Userscripts in Safari > Settings... > Extensions list. - - For an optimal experience it's recommended that you "Always Allow" Userscripts for "All Websites", but you could also allow only the sites you want, but please don't forget your settings if your script doesn't work. - -### How to install and inject a user script and some things to note: - -- The preferred method is of course to create your own scripts, open the extension page and click on the plus sign in the editor to create a new JS, write code and save it. -- You could also save files that extension with `.user.js` directly to the Userscripts directory. - - The script file must contain a valid metadata block to match the web pages and be displayed in the extension popup. -- When you visit a `.user.js` URL in Safari, open the extension popup and you will see an installation prompt, or it will pop up automatically if you have enhanced prompts turned on. - - The URL should end with `.user.js` in `/PATH` part, not the `?QUERY` or `#HASH` parts, otherwise it will not be considered a valid user script URL by the extension. -- When you enabled the extension and write the metadata correctly especially like `@match`, it will automatically complete the injection when you visit a matching web page. - - You could temporarily disable individual user scripts or all of them, just open the extension popup interface to toggle them. - -### That’s it, start improving your quality of life now! - -_Hey, don't forget to read our detailed documentation to learn more._ diff --git a/src/app/_locales/zh/messages.js b/src/app/_locales/zh/messages.js deleted file mode 100644 index e69057b0..00000000 --- a/src/app/_locales/zh/messages.js +++ /dev/null @@ -1,85 +0,0 @@ -import nativeLoggerCaveat from "./native-logger-caveat.md?raw"; -import quickStartGuideMac from "./quick-start-guide-mac.md?raw"; -import quickStartGuideIos from "./quick-start-guide-ios.md?raw"; - -import { marked } from "marked"; - -/** @satisfies {typeof import("../en/messages.js").markdown} */ -export const markdown = { - native_logger_caveat: { - message: await marked.parse(nativeLoggerCaveat), - }, - quick_start_guide_mac: { - message: await marked.parse(quickStartGuideMac), - }, - quick_start_guide_ios: { - message: await marked.parse(quickStartGuideIos), - }, -}; - -/** @satisfies {typeof import("../en/messages.js").messages} */ -export const messages = { - enabled: { - message: "已启用", - }, - disabled: { - message: "已停用", - }, - unknown: { - message: "未知", - }, - error: { - message: "错误", - }, - button_ok: { - message: "确定", - }, - button_dismiss: { - message: "关闭", - }, - button_disable: { - message: "停用", - }, - safari_extension_status: { - message: "Safari 扩展状态", - }, - native_logger_enabled_title: { - message: "本地日志记录器已启用", - }, - quick_start_guide_title: { - message: "快速入门指南", - }, - open_safari_settings: { - message: "打开 Safari 设置", - }, - open_safari_preferences: { - message: "打开 Safari 偏好", - }, - show_usage_guide: { - message: "显示使用指南", - }, - change_directory: { - message: "更改用户脚本目录", - }, - current_directory: { - message: "当前目录:", - }, - documentation: { - message: "详细文档", - }, - discussions: { - message: "交流讨论", - }, - report_an_issue: { - message: "报告问题", - }, - privacy_policy: { - message: "隐私政策", - }, - export_log_files: { - message: "导出日志文件", - }, - disable_logger: { - message: "停用日志记录", - }, -}; diff --git a/src/app/_locales/zh/native-logger-caveat.md b/src/app/_locales/zh/native-logger-caveat.md deleted file mode 100644 index 005723d0..00000000 --- a/src/app/_locales/zh/native-logger-caveat.md +++ /dev/null @@ -1,5 +0,0 @@ -- 日志记录器仅用于本地调试,开启期间可通过 macOS 控制台流式传输,同时写入本地文件。 -- 您可以在开启后重复复现问题的相关操作,然后在 App 中导出日志文件和检查它们。 -- 没有内建的上传功能,如需提交给开发者,请手动将导出的日志文件附加到您的问题报告中。 -- 为减少能耗和磁盘读写,请调试结束后及时关闭日志记录器。 -- 如日志文件超过 $1 将自动关闭日志记录器并清除日志。 diff --git a/src/app/_locales/zh/quick-start-guide-ios.md b/src/app/_locales/zh/quick-start-guide-ios.md deleted file mode 100644 index d24bda16..00000000 --- a/src/app/_locales/zh/quick-start-guide-ios.md +++ /dev/null @@ -1,26 +0,0 @@ -### 欢迎来到这个项目,您需要两个主要步骤来使扩展工作: - -- **打开 App 并设置目录** - - - 该目录用于保存和加载您的用户脚本。 - - 首次启动 App 时已为您设置默认本地目录。 - - 点击当前目录可跳转到默认目录或您设置的目录。 - -- **在 Safari 中启用扩展** - - - 从 `设置` 应用(设置 > Safari > 扩展)或 `Safari` 应用(iPhone 上的“AA”按钮,iPad 上的“扩展图标”,也是您打开扩展的“弹出界面”的位置)管理扩展。 - - 为了获得最佳体验,建议您“始终允许” Userscripts 为“所有网站”,但您也可以仅允许您想要的网站,但当您的脚本不起作用时,请不要忘记您的设置。 - -### 那么,如何安装和注入用户脚本,以及一些注意事项? - -- 移动版扩展目前不包含内置的脚本编辑器,但您仍然可以编写您自己的脚本并安装它们。 -- 您可以直接保存扩展名为 `.user.js` 的文件到您上面设置的 Userscripts 目录中。 - - 您的脚本文件必须包含有效的元数据块以匹配网站页面并正确显示在扩展的弹出界面中。 -- 当您在 Safari 中访问一个 `.user.js` 网址,然后打开扩展弹出界面,您将看到安装提示;如果您启用了增强提示,它会自动弹出。 - - 请注意该网址的 `/路径` 部分应该以 `.user.js` 结尾,而不是 `?查询` 或 `#锚点` 部分,否则该网址将不会被视为有效的用户脚本。 -- 当您启用该扩展并正确编写元数据尤其是像 `@match` 后,当您访问匹配的网页时,它将自动完成注入。 - - 您可以暂时禁用单个用户脚本或所有用户脚本,只需打开扩展弹出界面即可切换它们。 - -### 就这样,现在就开始改善您的生活质量吧! - -_嘿,不要忘记阅读我们的详细文档以了解更多信息。_ diff --git a/src/app/_locales/zh/quick-start-guide-mac.md b/src/app/_locales/zh/quick-start-guide-mac.md deleted file mode 100644 index f9983ced..00000000 --- a/src/app/_locales/zh/quick-start-guide-mac.md +++ /dev/null @@ -1,26 +0,0 @@ -### 欢迎来到这个项目,您需要两个主要步骤来使扩展工作: - -- **打开 App 并设置目录** - - - 该目录用于保存和加载您的用户脚本。 - - 首次启动 App 时已为您设置默认本地目录。 - - 点击当前目录可跳转到默认目录或您设置的目录。 - -- **在 Safari 中启用扩展** - - - 在 Safari > 设置... > 扩展列表中启用 Userscripts 条目。 - - 为了获得最佳体验,建议您“始终允许” Userscripts 为“所有网站”,但您也可以仅允许您想要的网站,但当您的脚本不起作用时,请不要忘记您的设置。 - -### 那么,如何安装和注入用户脚本,以及一些注意事项? - -- 首选的方法当然是撰写您自己的用户脚本,打开扩展页面点击加号创建新脚本,编辑和保存它。 -- 您还可以直接保存扩展名为 `.user.js` 的文件到您上面设置的 Userscripts 目录中。 - - 您的脚本文件必须包含有效的元数据块以匹配网站页面并正确显示在扩展的弹出界面中。 -- 当您在 Safari 中访问一个 `.user.js` 网址,然后打开扩展弹出界面,您将看到安装提示;如果您启用了增强提示,它会自动弹出。 - - 请注意该网址的 `/路径` 部分应该以 `.user.js` 结尾,而不是 `?查询` 或 `#锚点` 部分,否则该网址将不会被视为有效的用户脚本。 -- 当您启用该扩展并正确编写元数据尤其是像 `@match` 后,当您访问匹配的网页时,它将自动完成注入。 - - 您可以暂时禁用单个用户脚本或所有用户脚本,只需打开扩展弹出界面即可切换它们。 - -### 就这样,现在就开始改善您的生活质量吧! - -_嘿,不要忘记阅读我们的详细文档以了解更多信息。_ diff --git a/src/app/_locales/zh_Hant/messages.js b/src/app/_locales/zh_Hant/messages.js deleted file mode 100644 index e0fadede..00000000 --- a/src/app/_locales/zh_Hant/messages.js +++ /dev/null @@ -1,85 +0,0 @@ -import nativeLoggerCaveat from "./native-logger-caveat.md?raw"; -import quickStartGuideMac from "./quick-start-guide-mac.md?raw"; -import quickStartGuideIos from "./quick-start-guide-ios.md?raw"; - -import { marked } from "marked"; - -/** @satisfies {typeof import("../en/messages.js").markdown} */ -export const markdown = { - native_logger_caveat: { - message: await marked.parse(nativeLoggerCaveat), - }, - quick_start_guide_mac: { - message: await marked.parse(quickStartGuideMac), - }, - quick_start_guide_ios: { - message: await marked.parse(quickStartGuideIos), - }, -}; - -/** @satisfies {typeof import("../en/messages.js").messages} */ -export const messages = { - enabled: { - message: "已啟用", - }, - disabled: { - message: "已停用", - }, - unknown: { - message: "未知", - }, - error: { - message: "錯誤", - }, - button_ok: { - message: "確定", - }, - button_dismiss: { - message: "關閉", - }, - button_disable: { - message: "停用", - }, - safari_extension_status: { - message: "Safari 延伸功能狀態", - }, - native_logger_enabled_title: { - message: "本地日誌記錄器已啟用", - }, - quick_start_guide_title: { - message: "快速入門指南", - }, - open_safari_settings: { - message: "開啟 Safari 設定", - }, - open_safari_preferences: { - message: "開啟 Safari 偏好", - }, - show_usage_guide: { - message: "顯示使用指南", - }, - change_directory: { - message: "更改使用者腳本目錄", - }, - current_directory: { - message: "當前目錄:", - }, - documentation: { - message: "詳細文件", - }, - discussions: { - message: "交流討論", - }, - report_an_issue: { - message: "報告問題", - }, - privacy_policy: { - message: "隱私政策", - }, - export_log_files: { - message: "匯出日誌檔案", - }, - disable_logger: { - message: "停用日誌記錄", - }, -}; diff --git a/src/app/_locales/zh_Hant/native-logger-caveat.md b/src/app/_locales/zh_Hant/native-logger-caveat.md deleted file mode 100644 index 0c9b4baa..00000000 --- a/src/app/_locales/zh_Hant/native-logger-caveat.md +++ /dev/null @@ -1,5 +0,0 @@ -- 日誌記錄器僅用於本地除錯,開啟期間可透過 macOS 控制檯流式傳輸,同時寫入本地檔案。 -- 您可以在開啟後重複復現問題的相關操作,然後在 App 中匯出日誌檔案和檢查它們。 -- 沒有內建的上傳功能,如需提交給開發者,請手動將匯出的日誌檔案附加到您的問題報告中。 -- 為減少能耗和磁碟讀寫,請除錯結束後及時關閉日誌記錄器。 -- 如日誌檔案超過 $1 將自動關閉日誌記錄器並清除日誌。 diff --git a/src/app/_locales/zh_Hant/quick-start-guide-ios.md b/src/app/_locales/zh_Hant/quick-start-guide-ios.md deleted file mode 100644 index 0d7f5e51..00000000 --- a/src/app/_locales/zh_Hant/quick-start-guide-ios.md +++ /dev/null @@ -1,26 +0,0 @@ -### 歡迎來到這個專案,您需要兩個主要步驟來使延伸功能工作: - -- **開啟 App 並設定目錄** - - - 該目錄用於儲存和載入您的使用者腳本。 - - 首次啟動 App 時已為您設定預設本地目錄。 - - 點選當前目錄可跳轉到預設目錄或您設定的目錄。 - -- **在 Safari 中啟用延伸功能** - - - 從 `設定` 應用(設定 > Safari > 延伸功能)或 `Safari` 應用(iPhone 上的“AA”按鈕,iPad 上的“延伸功能圖示”,也是您開啟延伸功能的“彈出介面”的位置)管理延伸功能。 - - 為了獲得最佳體驗,建議您“始終允許” Userscripts 為“所有網站”,但您也可以僅允許您想要的網站,但當您的腳本不起作用時,請不要忘記您的設定。 - -### 那麼,如何安裝和注入使用者腳本,以及一些注意事項? - -- 移動版延伸功能目前不包含內建的腳本編輯器,但您仍然可以編寫您自己的腳本並安裝它們。 -- 您可以直接儲存副檔名為 `.user.js` 的檔案到您上面設定的 Userscripts 目錄中。 - - 您的腳本檔案必須包含有效的元資料塊以匹配網站頁面並正確顯示在延伸功能的彈出介面中。 -- 當您在 Safari 中訪問一個 `.user.js` 網址,然後開啟延伸功能彈出介面,您將看到安裝提示;如果您啟用了增強提示,它會自動彈出。 - - 請注意該網址的 `/路徑` 部分應該以 `.user.js` 結尾,而不是 `?查詢` 或 `#錨點` 部分,否則該網址將不會被視為有效的使用者腳本。 -- 當您啟用該延伸功能並正確編寫元資料尤其是像 `@match` 後,當您訪問匹配的網頁時,它將自動完成注入。 - - 您可以暫時禁用單個使用者腳本或所有使用者腳本,只需開啟延伸功能彈出介面即可切換它們。 - -### 就這樣,現在就開始改善您的生活質量吧! - -_嘿,不要忘記閱讀我們的詳細文件以瞭解更多資訊。_ diff --git a/src/app/_locales/zh_Hant/quick-start-guide-mac.md b/src/app/_locales/zh_Hant/quick-start-guide-mac.md deleted file mode 100644 index 3331a109..00000000 --- a/src/app/_locales/zh_Hant/quick-start-guide-mac.md +++ /dev/null @@ -1,26 +0,0 @@ -### 歡迎來到這個專案,您需要兩個主要步驟來使延伸功能工作: - -- **開啟 App 並設定目錄** - - - 該目錄用於儲存和載入您的使用者腳本。 - - 首次啟動 App 時已為您設定預設本地目錄。 - - 點選當前目錄可跳轉到預設目錄或您設定的目錄。 - -- **在 Safari 中啟用延伸功能** - - - 在 Safari > 設定... > 延伸功能列表中啟用 Userscripts 條目。 - - 為了獲得最佳體驗,建議您“始終允許” Userscripts 為“所有網站”,但您也可以僅允許您想要的網站,但當您的腳本不起作用時,請不要忘記您的設定。 - -### 那麼,如何安裝和注入使用者腳本,以及一些注意事項? - -- 首選的方法當然是撰寫您自己的使用者腳本,開啟延伸功能頁面點選加號建立新腳本,編輯和儲存它。 -- 您還可以直接儲存副檔名為 `.user.js` 的檔案到您上面設定的 Userscripts 目錄中。 - - 您的腳本檔案必須包含有效的元資料塊以匹配網站頁面並正確顯示在延伸功能的彈出介面中。 -- 當您在 Safari 中訪問一個 `.user.js` 網址,然後開啟延伸功能彈出介面,您將看到安裝提示;如果您啟用了增強提示,它會自動彈出。 - - 請注意該網址的 `/路徑` 部分應該以 `.user.js` 結尾,而不是 `?查詢` 或 `#錨點` 部分,否則該網址將不會被視為有效的使用者腳本。 -- 當您啟用該延伸功能並正確編寫元資料尤其是像 `@match` 後,當您訪問匹配的網頁時,它將自動完成注入。 - - 您可以暫時禁用單個使用者腳本或所有使用者腳本,只需開啟延伸功能彈出介面即可切換它們。 - -### 就這樣,現在就開始改善您的生活質量吧! - -_嘿,不要忘記閱讀我們的詳細文件以瞭解更多資訊。_ diff --git a/src/app/app.css b/src/app/app.css deleted file mode 100644 index 40c7cfa2..00000000 --- a/src/app/app.css +++ /dev/null @@ -1,121 +0,0 @@ -html { - height: auto; - overflow: visible; - overscroll-behavior: none; -} - -body { - background-color: var(--color-bg-primary); - color: var(--text-color-primary); - font: var(--text-default); - letter-spacing: var(--letter-spacing-medium); - text-rendering: optimizelegibility; - -webkit-font-smoothing: antialiased; -} - -/* ios */ -@supports (-webkit-touch-callout: none) { - /** - * Dynamic Type - * https://support.apple.com/102453 - * https://webkit.org/blog/3709/using-the-system-font-in-web-content/ - * https://developer.apple.com/library/archive/releasenotes/General/WhatsNewInSafari/Articles/Safari_7_0.html#//apple_ref/doc/uid/TP40014305-CH5-SW10 - * https://github.com/w3c/csswg-drafts/issues/3708 - */ - @supports (font: -apple-system-body) { - html { - /* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */ - font: -apple-system-body; /* default 17px */ - } - } - - /* Avoid page zoom */ - input, - textarea, - select { - font-size: max(1rem, 16px); - } -} - -#app { - flex-direction: column; -} - -address, -article, -aside, -button, -div, -footer, -header, -hgroup, -main, -nav, -search, -section { - display: flex; -} - -button { - border: none; - cursor: pointer; - padding: 0; - user-select: none; -} - -button:disabled { - opacity: var(--opacity-disabled); - pointer-events: none; -} - -a, -.link { - background: none; - color: var(--color-blue); - cursor: pointer; - text-decoration: underline; -} - -.truncate { - flex-grow: 1; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.flexible_space { - flex-grow: 1; -} - -x-markdown { - display: flex; - flex-direction: column; - overflow: auto; - text-align: left; - gap: var(--gap); - padding: 0 3rem; - --gap: 0.75rem; -} - -@media (width < 500px) { - x-markdown { - padding: 0 1.5rem; - } -} - -x-markdown :is(h1, h2, h3, h4, h5, h6) { - padding: 0; - margin: 0; -} - -x-markdown ul { - display: flex; - flex-direction: column; - gap: var(--gap); - padding-left: 1.5rem; -} - -x-markdown > ul ul { - margin-top: var(--gap); -} diff --git a/src/app/global.d.ts b/src/app/global.d.ts deleted file mode 100644 index b3f9487f..00000000 --- a/src/app/global.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -// https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html - -/// -/// - -declare global { - interface Window { - webapp: { - updateDirectory: (directory: string) => void; - updateExtStatus: (extStatus: ExtensionStatus) => void; - switchLogger: (enableLogger: boolean, promptLogger: boolean) => void; - }; - webkit: { - messageHandlers: { - controller: { - postMessage: ( - message: T, - ) => Promise>; - }; - }; - }; - } -} - -export {}; diff --git a/src/app/i18n.js b/src/app/i18n.js deleted file mode 100644 index 389042d8..00000000 --- a/src/app/i18n.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @typedef {typeof import("./_locales/en/messages.js").messages} MessagesT - * @typedef {typeof import("./_locales/en/messages.js").markdown} MarkdownT - */ - -/** - * @param {Types.I18nMessages} messages - * @param {string} messageName - * @param {string | string[]} substitutions - * @returns {string} - */ -function getLangFrom(messages, messageName, substitutions = undefined) { - if (!(messageName in messages)) { - console.warn(`i18n - "${messageName}" not found`, messages); - return ""; - } - let text = messages[messageName].message; - // handle substitutions - if (typeof substitutions === "string") { - text = text.replace("$1", substitutions); - } else if (Array.isArray(substitutions)) { - for (let i = 0; i < substitutions.length; i++) { - text = text.replace(`$${i + 1}`, substitutions[i]); - } - } - if (import.meta.env.MODE === "development") { - console.debug("i18n", messages[messageName].message, text, substitutions); - } - return text; -} - -export async function i18nInit() { - const languages = [navigator.language.replace("-", "_")]; - if (["zh-HK", "zh-MO", "zh-TW"].includes(navigator.language)) { - languages.unshift("zh_Hant"); - } - languages.push(navigator.language.split("-")[0]); - languages.push("en"); // fallback - if (import.meta.env.MODE === "development") { - // languages.unshift("en"); // DEBUG - } - for (const language of languages) { - try { - /** @type {{messages: MessagesT, markdown: MarkdownT}} */ - const module = await import(`./_locales/${language}/messages.js`); - const { messages, markdown } = module; - return { - /** @type {Types.GetLang} */ - gl: (n, s) => getLangFrom(messages, n, s), - /** @type {Types.GetLang} */ - md: (n, s) => getLangFrom(markdown, n, s), - }; - } catch (error) { - console.debug("Will fall back to `en`", error); - } - } - throw Error("I18n initialization failed"); -} diff --git a/src/app/jsconfig.json b/src/app/jsconfig.json deleted file mode 100644 index 95a69da9..00000000 --- a/src/app/jsconfig.json +++ /dev/null @@ -1,30 +0,0 @@ -// https://code.visualstudio.com/docs/languages/jsconfig -// https://www.typescriptlang.org/docs/handbook/tsconfig-json.html -// https://www.typescriptlang.org/tsconfig - -// https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html -// https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html - -{ - "compilerOptions": { - "target": "ESNext", - "module": "ESNext", - "moduleResolution": "bundler", - - "verbatimModuleSyntax": true, - "isolatedModules": true, - "resolveJsonModule": true, - - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "skipLibCheck": true, - "sourceMap": true, - - "paths": { - "@shared/*": ["../shared/*"] - } - }, - "include": ["**/*.d.ts", "**/*.js", "**/*.svelte"] -} diff --git a/src/app/main.js b/src/app/main.js deleted file mode 100644 index 8a28fe48..00000000 --- a/src/app/main.js +++ /dev/null @@ -1,42 +0,0 @@ -import "./reset.css"; -import "@shared/variables.css"; -import "./app.css"; -import { mount } from "svelte"; -import App from "./App.svelte"; - -if (import.meta.env.MODE === "development") { - // Simulation in non-WkWebView dev environment - if (import.meta.env.SAFARI_PLATFORM === undefined) { - console.warn("Simulation webkit..."); - window.webkit = { - messageHandlers: { - controller: { - postMessage: async (message) => { - switch (message) { - case "INIT": - return { - build: "2", - directory: "Userscripts App Documents", - enableLogger: true, - extStatus: "unknown", - firstRunTime: 1, - maxLogFileSize: 500_000_000, - platform: "mac", - promptLogger: true, - useSettingsInsteadOfPreferences: true, - version: "2.0.0", - }; - default: - console.debug("Simulation.webkit.messageHandler:", message); - break; - } - }, - }, - }, - }; - } -} - -const app = mount(App, { target: document.getElementById("app") }); - -export default app; diff --git a/src/app/reset.css b/src/app/reset.css deleted file mode 100644 index 0b8335ad..00000000 --- a/src/app/reset.css +++ /dev/null @@ -1,42 +0,0 @@ -*, -*::before, -*::after { - box-sizing: border-box; -} - -body, -p { - margin: 0; -} - -ul { - margin: 0; -} - -button, -input, -select, -textarea { - font-family: inherit; - font-size: 100%; - line-height: inherit; - margin: 0; -} - -button, -input[type="button"], -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; -} - -::-webkit-search-decoration, -::-webkit-search-cancel-button, -::-webkit-search-results-button, -::-webkit-search-results-decoration { - -webkit-appearance: none; -} - -img { - border-style: none; -} diff --git a/src/app/types.d.ts b/src/app/types.d.ts deleted file mode 100644 index f282812b..00000000 --- a/src/app/types.d.ts +++ /dev/null @@ -1,43 +0,0 @@ -declare namespace Types { - /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n/Locale-Specific_Message_reference} */ - type I18nMessages = { - [x: string]: { - message: string; - description?: string; - placeholders?: Object; - }; - }; - - type GetLang = ( - messageName: T, - substitutions?: string | string[], - ) => string; - - type SystemPlatform = "mac" | "ios"; - - type ExtensionStatus = "unknown" | "disabled" | "enabled" | "error"; - - type MessageBody = - | "INIT" - | "CHANGE_DIRECTORY" - | "OPEN_DIRECTORY" - | "SHOW_PREFERENCES" - | "EXPORT_LOG_FILES" - | "DISABLE_LOGGER" - | "DISMISS_LOGGER_PROMPT"; - - type MessageReply = T extends "INIT" - ? { - build: string; - version: string; - platform: SystemPlatform; - directory: string; - extStatus: ExtensionStatus; - useSettingsInsteadOfPreferences: boolean; - enableLogger: boolean; - promptLogger: boolean; - maxLogFileSize: number; - firstRunTime: number; - } - : void; -} diff --git a/src/dev/App.svelte b/src/dev/App.svelte deleted file mode 100644 index 602dae45..00000000 --- a/src/dev/App.svelte +++ /dev/null @@ -1,47 +0,0 @@ - - -
-
- - - -
-

Userscripts dev

- -

- - native-app - , - - action-popup - , - - extension-page - -

- -

This is the development preview environment

-
- - diff --git a/src/dev/app.css b/src/dev/app.css deleted file mode 100644 index 19d0543e..00000000 --- a/src/dev/app.css +++ /dev/null @@ -1,82 +0,0 @@ -/* stylelint-disable */ -:root { - font-family: Inter, Avenir, Helvetica, Arial, sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -.card { - padding: 2em; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } -} diff --git a/src/dev/assets/logo.png b/src/dev/assets/logo.png deleted file mode 100644 index 9fe96182..00000000 Binary files a/src/dev/assets/logo.png and /dev/null differ diff --git a/src/dev/jsconfig.json b/src/dev/jsconfig.json deleted file mode 100644 index 899038cd..00000000 --- a/src/dev/jsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -// https://code.visualstudio.com/docs/languages/jsconfig -// https://www.typescriptlang.org/docs/handbook/tsconfig-json.html -// https://www.typescriptlang.org/tsconfig - -// https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html -// https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html - -{ - "compilerOptions": { - "target": "ESNext", - "module": "ESNext", - "moduleResolution": "bundler", - - "verbatimModuleSyntax": true, - "isolatedModules": true, - "resolveJsonModule": true, - - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "skipLibCheck": true, - "sourceMap": true - }, - "include": ["**/*.d.ts", "**/*.js", "**/*.svelte"] -} diff --git a/src/dev/main.js b/src/dev/main.js deleted file mode 100644 index 85631fee..00000000 --- a/src/dev/main.js +++ /dev/null @@ -1,7 +0,0 @@ -import "./app.css"; -import { mount } from "svelte"; -import App from "./App.svelte"; - -const app = mount(App, { target: document.getElementById("app") }); - -export default app; diff --git a/src/dev/vite-env.d.ts b/src/dev/vite-env.d.ts deleted file mode 100644 index 4078e747..00000000 --- a/src/dev/vite-env.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -/// -/// diff --git a/src/ext/action-popup/App.svelte b/src/ext/action-popup/App.svelte deleted file mode 100644 index 5740e7b5..00000000 --- a/src/ext/action-popup/App.svelte +++ /dev/null @@ -1,755 +0,0 @@ - - -{#if showUpdates} - (showUpdates = false)} - showLoaderOnDisabled={true} - abortClick={abortUpdates} - abort={showUpdates} - > - - -{:else if showInstall} - (showInstall = false)} - showLoaderOnDisabled={true} - > - (showInstall = false)} - installConfirmClick={installConfirm} - /> - -{:else if showAll} - { - showAll = false; - refreshView(); - }} - showLoaderOnDisabled={false} - > - - -{:else} -
-
- - (showUpdates = true)} - title="Show updates" - {disabled} - /> - - -
- {#if !active} - - {/if} - {#if showBetaNews && platform !== "macos"} -
- NEW: - is now available! - (showBetaNews = false)} - title="Close" - /> -
- {/if} - {#if showInstallPrompt} -
- Userscript - {#if scriptChecking} - {showInstallPrompt} - {:else} - {scriptInstalled ? "Installed" : "Detected"}: - - {/if} -
- {/if} - {#if errorNotification} -
- {errorNotification} - (errorNotification = undefined)} - title="Clear error" - /> -
- {/if} -
-
- {#if loading} - - {:else if inactive} -
Popup inactive on extension page
- {:else if firstGuide} -
-

Welcome, first use please: 

- -

to complete the initialization

-
- {:else if initError} -
- Something went wrong:  - -
- {:else if items.length < 1} -
No matched userscripts
- {:else} -
- {#each list as item, i (item.filename)} - toggleItem(item)} - /> - {/each} -
- {/if} -
- {#if !inactive && platform === "macos"} - - {/if} -{/if} - - diff --git a/src/ext/action-popup/Components/PopupItem.svelte b/src/ext/action-popup/Components/PopupItem.svelte deleted file mode 100644 index 0afba81c..00000000 --- a/src/ext/action-popup/Components/PopupItem.svelte +++ /dev/null @@ -1,97 +0,0 @@ - - -
- -
{name}
- {#if subframe}
SUB
{/if} - -
- - diff --git a/src/ext/action-popup/Components/View.svelte b/src/ext/action-popup/Components/View.svelte deleted file mode 100644 index 1bd7ad7c..00000000 --- a/src/ext/action-popup/Components/View.svelte +++ /dev/null @@ -1,89 +0,0 @@ - - -
-
- {headerTitle} - -
-
- {#if loading && showLoaderOnDisabled} - - {:else} -
Slot content is required...
- {/if} -
-
- - diff --git a/src/ext/action-popup/Components/Views/AllItemsView.svelte b/src/ext/action-popup/Components/Views/AllItemsView.svelte deleted file mode 100644 index 20aea85c..00000000 --- a/src/ext/action-popup/Components/Views/AllItemsView.svelte +++ /dev/null @@ -1,56 +0,0 @@ - - -{#if allItems.length} -
- {#each list as item (item.filename)} - allItemsToggleItem(item)} - /> - {/each} -
-{:else} -
No valid files found in directory
-{/if} - - diff --git a/src/ext/action-popup/Components/Views/InstallView.svelte b/src/ext/action-popup/Components/Views/InstallView.svelte deleted file mode 100644 index 8c54b6cc..00000000 --- a/src/ext/action-popup/Components/Views/InstallView.svelte +++ /dev/null @@ -1,176 +0,0 @@ - - -
- {#if installError} -
- - {@html iconError} -
Couldn't install userscript
-

{installError}

-
- {:else if userscript} -
    -
  • {userscript.name}
  • - {#if userscript.description} -
  • {userscript.description}
  • - {/if} - {#if userscript.match} -
  • -
    @match
    - {#each userscript.match as match (match)} -
    {match}
    - {/each} -
  • - {/if} - {#if userscript.include} -
  • -
    @include
    - {#each userscript.include as include (include)} -
    {include}
    - {/each} -
  • - {/if} - {#if userscript.require} -
  • -
    @require
    - {#each userscript.require as require (require)} -
    {require}
    - {/each} -
  • - {/if} - {#if userscript.grant} -
  • -
    @grant
    - {#each userscript.grant as grant (grant)} -
    {grant}
    - {/each} -
  • - {/if} -
-
- -
{@html iconWarn}
-
- Be sure you trust the author before installing. Nefarious code can - exploit your security and privacy. -
-
-
- - -
- {/if} -
- - diff --git a/src/ext/action-popup/Components/Views/UpdateView.svelte b/src/ext/action-popup/Components/Views/UpdateView.svelte deleted file mode 100644 index 6da55f46..00000000 --- a/src/ext/action-popup/Components/Views/UpdateView.svelte +++ /dev/null @@ -1,83 +0,0 @@ - - -{#if updates.length} - {#each updates as item (item.name)} - -
-
{item.name}
- Source - -
- {/each} -

Be sure you trust the author before saving remote code to your device.

- -{:else} -
- - {@html iconUpdate} -
- There are no file updates available -
- -
-
-{/if} - - diff --git a/src/ext/action-popup/app.css b/src/ext/action-popup/app.css deleted file mode 100644 index 88f6c725..00000000 --- a/src/ext/action-popup/app.css +++ /dev/null @@ -1,97 +0,0 @@ -html { - font-size: 100%; - overflow: hidden; -} - -body { - background-color: var(--color-bg-secondary); - color: var(--text-color-primary); - font: var(--text-medium); - letter-spacing: var(--letter-spacing-medium); - text-rendering: optimizelegibility; - -webkit-font-smoothing: antialiased; - position: relative; - width: 18rem; - height: 26rem; -} - -/* ios */ -@supports (-webkit-touch-callout: none) { - html { - font-size: 125%; - overflow: visible; - overscroll-behavior: none; - } - - /** - * Dynamic Type - * https://support.apple.com/102453 - * https://webkit.org/blog/3709/using-the-system-font-in-web-content/ - * https://developer.apple.com/library/archive/releasenotes/General/WhatsNewInSafari/Articles/Safari_7_0.html#//apple_ref/doc/uid/TP40014305-CH5-SW10 - * https://github.com/w3c/csswg-drafts/issues/3708 - */ - @supports (font: -apple-system-body) { - html { - /* stylelint-disable-next-line declaration-property-value-no-unknown,font-family-no-missing-generic-family-keyword */ - font: -apple-system-title3; /* default 20px */ - } - } - - body { - width: auto; - min-width: 16rem; - height: auto; - } - - /* non-fixed width need to stretch */ - @media (width < 320px) { - body { - width: 18rem; - min-height: 16rem; - } - } - - /* Avoid page zoom */ - input, - textarea, - select { - font-size: max(1rem, 16px); - } -} - -noscript { - display: block; -} - -#app { - display: flex; - flex-direction: column; - height: 100%; - justify-content: space-between; -} - -button { - border: none; - cursor: pointer; - padding: 0; - user-select: none; -} - -button:disabled { - opacity: var(--opacity-disabled); - pointer-events: none; -} - -a, -.link { - background: none; - color: var(--color-blue); - cursor: pointer; - text-decoration: underline; -} - -.truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} diff --git a/src/ext/action-popup/main.js b/src/ext/action-popup/main.js deleted file mode 100644 index a5190622..00000000 --- a/src/ext/action-popup/main.js +++ /dev/null @@ -1,38 +0,0 @@ -import "@shared/reset.css"; -import "@shared/variables.css"; -import "./app.css"; -import { mount } from "svelte"; -import App from "./App.svelte"; - -// vite feat that only import in dev mode -if (import.meta.env.MODE === "development") { - try { - const modules = import.meta.glob("@ext/dev.js", { eager: true }); - const browser = modules["/src/ext/shared/dev.js"]["browser"]; - console.debug("DEV-ENV", import.meta.env, modules, browser); - if (!window?.browser?.extension && browser) { - // assign to window simulation WebExtension APIs - window.browser = browser; - // macos popup simulation - const style = document.createElement("style"); - style.textContent = ` -body { - top: 20px; - left: 20px; - box-sizing: content-box; - border: 1px solid light-dark(#bebebe, #585c5f); - border-radius: 10px; - box-shadow: 2px 2px 20px rgba(0, 0, 0, 0.2); - overflow: hidden; -} -`; - browser.platform === "macos" && document.head.append(style); - } - } catch (error) { - console.error(error); - } -} - -const app = mount(App, { target: document.getElementById("app") }); - -export default app; diff --git a/src/ext/background/main.js b/src/ext/background/main.js deleted file mode 100644 index 761eda72..00000000 --- a/src/ext/background/main.js +++ /dev/null @@ -1,608 +0,0 @@ -import { contentScriptRegistration, openExtensionPage } from "@ext/utils.js"; -import * as settingsStorage from "@ext/settings.js"; -import { connectNative, sendNativeMessage } from "@ext/native.js"; - -// first sorts files by run-at value, then by weight value -function userscriptSort(a, b) { - // map the run-at values to numeric values - const runAtValues = { - "document-start": 1, - "document-end": 2, - "document-idle": 3, - }; - const runAtA = a.scriptObject["run-at"]; - const runAtB = b.scriptObject["run-at"]; - if (runAtA !== runAtB && runAtValues[runAtA] && runAtValues[runAtB]) { - return runAtValues[runAtA] > runAtValues[runAtB]; - } - return Number(a.scriptObject.weight) < Number(b.scriptObject.weight); -} - -async function getPlatform() { - let platform = localStorage.getItem("platform"); - if (!platform) { - const message = { name: "REQ_PLATFORM" }; - const response = await sendNativeMessage(message); - if (!response.platform) { - console.error("Failed to get platform"); - return ""; - } - platform = response.platform; - localStorage.setItem("platform", platform); - } - return platform; -} - -function setClipboard(data, type = "text/plain") { - // future enhancement? - // https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/write - // https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText - const onCopy = (e) => { - e.stopImmediatePropagation(); - e.preventDefault(); - e.clipboardData.setData(type, data); - document.removeEventListener("copy", onCopy, true); - }; - - const textarea = document.createElement("textarea"); - textarea.textContent = ""; - document.body.appendChild(textarea); - textarea.select(); - document.addEventListener("copy", onCopy, true); - try { - return document.execCommand("copy"); - } catch (error) { - console.warn("setClipboard failed", error); - document.removeEventListener("copy", onCopy, true); - return false; - } finally { - document.body.removeChild(textarea); - } -} - -async function setBadgeCount() { - const clearBadge = () => browser.browserAction.setBadgeText({ text: null }); - // @todo until better introduce in ios, only set badge on macOS - // set a text badge or an empty string in visionOS will cause the extension's icon to no longer be displayed - const platform = await getPlatform(); - if (platform !== "macos") return clearBadge(); - // @todo settingsStorage.get("global_exclude_match") - const settings = await settingsStorage.get([ - "global_active", - "toolbar_badge_count", - ]); - if (settings["global_active"] === false) return clearBadge(); - if (settings["toolbar_badge_count"] === false) return clearBadge(); - - const currentTab = await browser.tabs.getCurrent(); - // no active tabs exist (user closed all windows) - if (!currentTab) return clearBadge(); - const url = currentTab.url; - // if url doesn't exist, stop - if (!url) return clearBadge(); - // only check for http/s pages - if (!url.startsWith("http://") && !url.startsWith("https://")) - return clearBadge(); - // @todo if url match in global exclude list, clear badge - const frameUrls = new Set(); - const frames = await browser.webNavigation.getAllFrames({ - tabId: currentTab.id, - }); - for (let i = 0; i < frames.length; i++) { - const frameUrl = frames[i].url; - if (frameUrl !== url && frameUrl.startsWith("http")) { - frameUrls.add(frameUrl); - } - } - const message = { - name: "POPUP_BADGE_COUNT", - url, - frameUrls: Array.from(frameUrls), - }; - const response = await sendNativeMessage(message); - if (response?.error) return console.error(response.error); - if (response?.count > 0) { - browser.browserAction.setBadgeText({ text: response.count.toString() }); - } else { - const _url = new URL(url); - if (_url.pathname.endsWith(".user.js")) { - browser.browserAction.setBadgeText({ text: "JS" }); - } else { - clearBadge(); - } - } -} - -// on startup set declarativeNetRequest rulesets -// should also check and refresh when: -// 1. dnr item save event in the page occurs -// 2. dnr item toggle event in the page occurs -// 3. external editor changes script file content -async function setDNRRulesets() { - // not supported below safari 15.4 - if (!browser.declarativeNetRequest.updateDynamicRules) return; - const message = { name: "REQ_REQUESTS" }; - const response = await sendNativeMessage(message); - if (response.error) { - console.error(response.error); - return; - } - // loop through response, parse the rules, push to array and log - /** @type {import("webextension-polyfill").DeclarativeNetRequest.Rule[]} */ - const addRules = []; - let ruleId = 1; - for (let i = 0; i < response.length; i++) { - if ( - ruleId > - browser.declarativeNetRequest.MAX_NUMBER_OF_DYNAMIC_AND_SESSION_RULES - ) { - console.warn( - "Rules exceed the maximum number, some rules will be ignored", - ); - break; - } - const ruleset = response[i]; - /** @type {Array} */ - let rules; - try { - const res = JSON.parse(ruleset.code); - // check if an array or single rule - if (Array.isArray(res)) { - rules = res; - } else if (typeof res === "object") { - rules = [res]; - } else { - console.warn(`Not a valid DNR ruleset: ${ruleset.name}`); - continue; - } - console.info(`Setting DNR ruleset: ${ruleset.name} (${rules.length})`); - } catch (error) { - console.warn( - `Failed parsed into a valid DNR ruleset: ${ruleset.name}`, - error, - ); - continue; - } - for (const rule of rules) { - // simple check if it is a rule object - if (!rule.action || !rule.condition || !rule.id) { - console.warn("Not a valid DNR rule:", rule); - continue; - } - // set unique ids for all rules to ensure no repeats - rule.id = ruleId++; - addRules.push(rule); - } - } - // remove all then add declarativeNetRequest rules - try { - const oldRules = await browser.declarativeNetRequest.getDynamicRules(); - const removeRuleIds = oldRules.map((rule) => rule.id); - await browser.declarativeNetRequest.updateDynamicRules({ - addRules, - removeRuleIds, - }); - } catch (error) { - return console.error(error); - } - console.info(`Finished setting ${addRules.length} DNR rules`); -} - -// the current update logic is similar to setDNRRulesets() -// this feature needs a more detailed redesign in the future -// https://github.com/quoid/userscripts/issues/453 -async function getContextMenuItems() { - // macos exclusive feature - const platform = await getPlatform(); - if (platform !== "macos") return; - // since it's not possible to get a list of currently active menu items - // on update, all context-menu items are cleared, then re-added - // this is done to ensure fresh code changes appear - await browser.menus.removeAll(); - // get the context-menu scripts - const message = { name: "REQ_CONTEXT_MENU_SCRIPTS" }; - const response = await sendNativeMessage(message); - if (response.error) { - console.error(response.error); - return; - } - // add menus items - const items = response.files?.menu || []; - if (items.length) { - console.info(`Setting ${items.length} context-menu userscripts`); - } - for (let i = 0; i < items.length; i++) { - const item = items[i]; - // context-menu scripts require @match value - // @include values are ignored - if (!item.scriptObject.matches.length) continue; - addContextMenuItem(item); - } -} - -async function addContextMenuItem(userscript) { - const patterns = userscript.scriptObject.matches; - browser.menus.create( - { - contexts: ["all"], - documentUrlPatterns: patterns, - id: userscript.scriptObject.filename, - title: userscript.scriptObject.name, - }, - () => { - // add event listener if needed - if (!browser.menus.onClicked.hasListener(contextClick)) { - browser.menus.onClicked.addListener(contextClick); - } - }, - ); -} - -async function contextClick(info, tab) { - // when any created context-menu item is clicked, send message to tab - // the content script for that tag will have the context-menu code - // which will get send back in the response if/when found - const message = { name: "CONTEXT_RUN", menuItemId: info.menuItemId }; - const response = await browser.tabs.sendMessage(tab.id, message); - // if code is returned, execute on that tab - if (!response.code) return; - browser.tabs.executeScript(tab.id, { code: response.code }); -} - -async function nativeChecks() { - const response = await sendNativeMessage({ - name: "NATIVE_CHECKS", - }); - if (response.error) { - settingsStorage.set({ error_native: response }); - return false; - } - settingsStorage.reset("error_native"); - return true; -} - -/** - * Handles messages sent with `browser.runtime.sendMessage` - * Make sure not to return `undefined` or `rejection`, otherwise the reply may never be delivered - * @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage#listener} - * @type {Parameters[0]} - * @returns {Promise<{status: "pending"|"fulfilled"|"rejected", result?: any}>} - */ -async function handleMessage(message, sender) { - switch (message.name) { - case "REQ_USERSCRIPTS": { - // get the page url from the content script that sent request - const url = sender.url; - // use frameId to determine if request came from top level window - // if @noframes true, and isTop false, swift layer won't return code - const isTop = sender.frameId === 0; - // send request to swift layer to provide code for page url - const message = { name: "REQ_USERSCRIPTS", url, isTop }; - try { - const response = await sendNativeMessage(message); - if (import.meta.env.MODE === "development") { - console.debug("REQ_USERSCRIPTS", message, response); - } - // if request failed, send error to content script for logging - if (response.error) return response; - // sort files - response.files.js.sort(userscriptSort); - response.files.css.sort((a, b) => Number(a.weight) < Number(b.weight)); - // return sorted files for injection - return response; - } catch (error) { - console.error(error); - // @ts-ignore -- ignore for now and will reconstruct this in the future. - return { error: String(error) }; - } - } - case "API_CLOSE_TAB": { - try { - await browser.tabs.remove(message.tabId || sender.tab.id); - return { status: "fulfilled" }; - } catch (error) { - console.error(message, sender, error); - return { status: "rejected", result: String(error) }; - } - } - case "API_OPEN_TAB": { - try { - const tab = await browser.tabs.create({ - active: message.active, - index: sender.tab.index + 1, - url: message.url, - }); - return { status: "fulfilled", result: tab }; - } catch (error) { - console.error(message, sender, error); - return { status: "rejected", result: String(error) }; - } - } - case "API_ADD_STYLE": { - try { - await browser.tabs.insertCSS(sender.tab.id, { - code: message.css, - cssOrigin: "user", - }); - return { status: "fulfilled" }; - } catch (error) { - console.error(message, sender, error); - return { status: "rejected", result: String(error) }; - } - } - case "API_GET_TAB": { - if (typeof sender.tab === "undefined") { - const error = "unable to deliver tab due to empty tab id"; - return { status: "rejected", result: error }; - } - try { - const tabData = sessionStorage.getItem(`tab-${sender.tab.id}`); - // if tabData is null, can still parse it and return that - const tabObj = JSON.parse(tabData); - return { status: "fulfilled", result: tabObj }; - } catch (error) { - console.error("failed to parse tab data for getTab", error); - return { status: "rejected", result: String(error) }; - } - } - case "API_SAVE_TAB": { - if (sender.tab != null && sender.tab.id) { - const key = `tab-${sender.tab.id}`; - sessionStorage.setItem(key, JSON.stringify(message.tabObj)); - return { status: "fulfilled" }; - } else { - const error = "unable to save tab, empty tab id"; - return { status: "rejected", result: String(error) }; - } - } - case "API_SET_CLIPBOARD": { - const result = setClipboard(message.clipboardData, message.type); - return { status: "fulfilled", result }; - } - case "API_XHR": { - try { - // initializing an xhr instance - const xhr = new XMLHttpRequest(); - // establish a long-lived port connection to content script - /** @type {import("../global.d.ts").TypeBackground.XHRPort} */ - const port = browser.tabs.connect(sender.tab.id, { - name: message.xhrPortName, - }); - // receive messages from content script and process them - port.onMessage.addListener((msg) => { - if (msg.name === "ABORT") xhr.abort(); - if (msg.name === "DISCONNECT") port.disconnect(); - }); - // handle port disconnect and clean tasks - port.onDisconnect.addListener((p) => { - if (p?.error) { - console.error( - `port disconnected due to an error: ${p.error.message}`, - ); - } - }); - // parse details and set up for xhr instance - /** @type {TypeExtMessages.XHRTransportableDetails} */ - const details = message.details; - /** @type {Parameters[0]} */ - const method = details.method || "GET"; - /** @type {Parameters[1]} */ - const url = details.url; - /** @type {Parameters[3]} */ - const user = details.user || null; - /** @type {Parameters[4]} */ - const password = details.password || null; - /** @type {Parameters[0]} */ - let body = null; - if (typeof details.data === "object") { - /** @type {TypeExtMessages.XHRProcessedData} */ - const data = details.data; - if (typeof data.data === "string") { - if (data.type === "Text") { - // deprecate once body supports more data types - // the `binary` key will no longer needed - if (details.binary) { - const binaryString = data.data; - const view = new Uint8Array(binaryString.length); - for (let i = 0; i < binaryString.length; i++) { - view[i] = binaryString.charCodeAt(i); - } - body = view; - } else { - body = data.data; - } - } - if (data.type === "Document") { - body = data.data; - if (!("content-type" in details.headers)) { - details.headers["content-type"] = data.mime; - } - } - if (data.type === "URLSearchParams") { - body = new URLSearchParams(data.data); - } - } - if (Array.isArray(data.data)) { - if ( - data.type === "ArrayBuffer" || - data.type === "ArrayBufferView" - ) { - body = new Uint8Array(data.data); - } - if (data.type === "Blob") { - body = new Uint8Array(data.data); - if (!("content-type" in details.headers)) { - details.headers["content-type"] = data.mime; - } - } - if (data.type === "FormData") { - body = new FormData(); - for (const [k, v] of data.data) { - if (typeof v === "string") { - body.append(k, v); - } else { - const view = new Uint8Array(v.data); - body.append( - k, - new File([view], v.name, { - type: v.mime, - lastModified: v.lastModified, - }), - ); - } - } - } - } - } - // xhr instances automatically filter out unexpected user values - xhr.timeout = details.timeout; - xhr.responseType = details.responseType; - // record parsed values for subsequent use - const responseType = xhr.responseType; - // avoid unexpected behavior of legacy defaults such as parsing XML - if (responseType === "") xhr.responseType = "text"; - // transfer to content script via arraybuffer and then parse to blob - if (responseType === "blob") xhr.responseType = "arraybuffer"; - // transfer to content script via text and then parse to document - if (responseType === "document") xhr.responseType = "text"; - // add required listeners and send result back to the content script - if (details.hasUploadHandlers) { - for (const handler of Object.keys(details.hasUploadHandlers)) { - /** @param {ProgressEvent} event */ - xhr.upload[handler] = async (event) => { - /** @type {TypeExtMessages.XHRProgress} */ - const progress = { - lengthComputable: event.lengthComputable, - loaded: event.loaded, - total: event.total, - }; - port.postMessage({ handler, progress }); - }; - } - } - const handlers = details.hasHandlers ?? {}; - for (const handler of Object.keys(handlers)) { - xhr[handler] = async () => { - // can not send xhr through postMessage - // construct new object to be sent as "response" - /** @type {TypeExtMessages.XHRTransportableResponse} */ - const response = { - contentType: undefined, // non-standard - readyState: xhr.readyState, - response: xhr.response, - responseHeaders: xhr.getAllResponseHeaders(), - responseType, - responseURL: xhr.responseURL, - status: xhr.status, - statusText: xhr.statusText, - timeout: xhr.timeout, - }; - // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/response#value - if (xhr.readyState < xhr.DONE && xhr.responseType !== "text") { - response.response = null; - } - // get content-type when headers received - if (xhr.readyState >= xhr.HEADERS_RECEIVED) { - response.contentType = xhr.getResponseHeader("Content-Type"); - } - // only process when xhr is complete and data exist - // note the status of the last `progress` event in Safari is DONE/4 - // exclude this event to avoid unnecessary processing and transmission - if ( - xhr.readyState === xhr.DONE && - xhr.response !== null && - handler !== "onprogress" - ) { - // need to convert arraybuffer data to postMessage - if ( - xhr.responseType === "arraybuffer" && - xhr.response instanceof ArrayBuffer - ) { - const buffer = xhr.response; - response.response = Array.from(new Uint8Array(buffer)); - } - } - port.postMessage({ handler, response }); - }; - } - // if onloadend not set in xhr details - // onloadend event won't be passed to content script - // if that happens port DISCONNECT message won't be posted - // so if details lacks onloadend then attach the listener - if (!handlers.onloadend) { - xhr.onloadend = () => { - port.postMessage({ handler: "onloadend" }); - }; - } - if (details.overrideMimeType) { - xhr.overrideMimeType(details.overrideMimeType); - } - xhr.open(method, url, true, user, password); - // must set headers after `xhr.open()`, but before `xhr.send()` - if (typeof details.headers === "object") { - for (const [key, val] of Object.entries(details.headers)) { - xhr.setRequestHeader(key, val); - } - } - xhr.send(body); - } catch (error) { - console.error(error); - } - return { status: "fulfilled" }; - } - case "REFRESH_DNR_RULES": { - setDNRRulesets(); - break; - } - case "REFRESH_CONTEXT_MENU_SCRIPTS": { - getContextMenuItems(); - break; - } - case "WEB_USERJS_POPUP": { - const currentTab = await browser.tabs.getCurrent(); - if (currentTab.id === sender.tab.id) { - browser.browserAction.openPopup(); - } - break; - } - } -} -browser.runtime.onInstalled.addListener(async () => { - await nativeChecks(); - const enable = await settingsStorage.get("augmented_userjs_install"); - await contentScriptRegistration(enable); -}); -browser.runtime.onStartup.addListener(async () => { - setDNRRulesets(); - getContextMenuItems(); -}); -// listens for messages from content script, popup and page -browser.runtime.onMessage.addListener(handleMessage); -// set the badge count -browser.tabs.onActivated.addListener(setBadgeCount); -browser.windows.onFocusChanged.addListener(async (windowId) => { - if (windowId < 1) { - // lose focus - return; - } - nativeChecks(); - setBadgeCount(); - setDNRRulesets(); - getContextMenuItems(); -}); -browser.webNavigation.onCompleted.addListener(setBadgeCount); - -// handle native app messages -const port = connectNative(); -port.onMessage.addListener(async (message) => { - // console.info(message); // DEBUG - if (message.name === "SAVE_LOCATION_CHANGED") { - await openExtensionPage(); - if (message?.userInfo?.returnApp === true) { - sendNativeMessage({ name: "OPEN_APP" }); - } - } - // if (message.name === "OPEN_EXTENSION_PAGE") { - // openExtensionPage(); - // } -}); diff --git a/src/ext/content-scripts/api.js b/src/ext/content-scripts/api.js deleted file mode 100644 index e2bf4cdb..00000000 --- a/src/ext/content-scripts/api.js +++ /dev/null @@ -1,503 +0,0 @@ -async function setValue(key, value) { - if (typeof key !== "string" || !key.length) { - return Promise.reject(new Error("setValue invalid key arg")); - } - const sid = this.US_filename; - if (typeof sid !== "string" || !sid.length) { - return Promise.reject(new Error("setValue invalid call")); - } - const item = {}; - item[`${sid}---${key}`] = value; - return browser.storage.local.set(item); -} - -async function getValue(key, defaultValue) { - if (typeof key !== "string" || !key.length) { - return Promise.reject(new Error("getValue invalid key arg")); - } - const sid = this.US_filename; - if (typeof sid !== "string" || !sid.length) { - return Promise.reject(new Error("getValue invalid call")); - } - const prefixedKey = `${sid}---${key}`; - const results = await browser.storage.local.get(prefixedKey); - if (prefixedKey in results) return results[prefixedKey]; - if (defaultValue !== undefined) return defaultValue; - return undefined; -} - -async function deleteValue(key) { - if (typeof key !== "string" || !key.length) { - return Promise.reject(new Error("deleteValue missing key arg")); - } - const sid = this.US_filename; - if (typeof sid !== "string" || !sid.length) { - return Promise.reject(new Error("deleteValue invalid call")); - } - const prefixedKey = `${sid}---${key}`; - return browser.storage.local.remove(prefixedKey); -} - -async function listValues() { - const sid = this.US_filename; - if (typeof sid !== "string" || !sid.length) { - return Promise.reject(new Error("listValues invalid call")); - } - const prefix = `${sid}---`; - const results = await browser.storage.local.get(); - const keys = []; - for (const key in results) { - key.startsWith(prefix) && keys.push(key.slice(prefix.length)); - } - return keys; -} - -async function sendMessageProxy(message) { - try { - /** @type {{status: "fulfilled"|"rejected", result: any}} */ - const response = await browser.runtime.sendMessage(message); - if (response.status === "fulfilled") { - return response.result; - } else { - return Promise.reject(response.result); - } - } catch (error) { - console.error(error); - return Promise.reject(error); - } -} - -async function openInTab(url, openInBackground = false) { - try { - new URL(url); - } catch (error) { - return Promise.reject(error); - } - return sendMessageProxy({ - name: "API_OPEN_TAB", - url, - active: !openInBackground, - }); -} - -async function closeTab(tabId) { - return sendMessageProxy({ name: "API_CLOSE_TAB", tabId }); -} - -async function getTab() { - return sendMessageProxy({ name: "API_GET_TAB" }); -} - -async function saveTab(tabObj) { - if (tabObj == null) return Promise.reject(new Error("saveTab invalid arg")); - return sendMessageProxy({ name: "API_SAVE_TAB", tabObj }); -} - -async function addStyle(css) { - if (typeof css !== "string" || !css.length) { - return Promise.reject(new Error("addStyle invalid css arg")); - } - return sendMessageProxy({ name: "API_ADD_STYLE", css }); -} - -async function setClipboard(clipboardData, type) { - return sendMessageProxy({ - name: "API_SET_CLIPBOARD", - clipboardData, - type, - }); -} - -/** - * Restore `response.response` to required `responseType` - * @param {TypeExtMessages.XHRTransportableResponse} msgResponse - * @param {TypeExtMessages.XHRResponse} response - */ -function xhrResponseProcessor(msgResponse, response) { - const res = msgResponse; - /** - * only include responseXML when needed - * NOTE: Only add implementation at this time, not enable, to avoid - * unnecessary calculations, and this legacy default behavior is not - * recommended, users should explicitly use `responseType: "document"` - * to obtain it. - if (res.responseType === "" && typeof res.response === "string") { - const mimeTypes = [ - "text/xml", - "application/xml", - "application/xhtml+xml", - "image/svg+xml", - ]; - for (const mimeType of mimeTypes) { - if (res.contentType.includes(mimeType)) { - const parser = new DOMParser(); - res.responseXML = parser.parseFromString(res.response, "text/xml"); - break; - } - } - } - */ - if (res.responseType === "arraybuffer" && Array.isArray(res.response)) { - // arraybuffer responses had their data converted in background - // convert it back to arraybuffer - try { - response.response = new Uint8Array(res.response).buffer; - } catch (err) { - console.error("error parsing xhr arraybuffer", err); - } - } - if (res.responseType === "blob" && Array.isArray(res.response)) { - // blob responses had their data converted in background - // convert it back to blob - try { - const typedArray = new Uint8Array(res.response); - const type = res.contentType ?? ""; - response.response = new Blob([typedArray], { type }); - } catch (err) { - console.error("error parsing xhr blob", err); - } - } - if (res.responseType === "document" && typeof res.response === "string") { - // document responses had their data converted in background - // convert it back to document - try { - const parser = new DOMParser(); - const mimeType = res.contentType.includes("text/html") - ? "text/html" - : "text/xml"; - response.response = parser.parseFromString(res.response, mimeType); - response.responseXML = response.response; - } catch (err) { - console.error("error parsing xhr document", err); - } - } -} - -/** - * Process data into a transportable object - * @param {Parameters[0]} data - * @returns {Promise} - */ -async function xhrDataProcessor(data) { - if (typeof data === "undefined") return undefined; - if (typeof data === "string") { - return { data, type: "Text" }; - } - if (data instanceof Document) { - if (data instanceof XMLDocument) { - try { - return { - data: new XMLSerializer().serializeToString(data), - type: "Document", - mime: data.contentType || "text/xml", - }; - } catch (error) { - console.error( - "XML serialization failed, the data will be omitted", - error, - ); - } - } else { - let html = data.documentElement.outerHTML; - if (data.doctype) { - html = `` + html; - } - return { - data: html, - type: "Document", - mime: data.contentType || "text/html", - }; - } - } - if (data instanceof Blob) { - try { - const buffer = await data.arrayBuffer(); - return { - data: Array.from(new Uint8Array(buffer)), - type: "Blob", - mime: data.type, - }; - } catch (error) { - throw Error("Document serialization failed, the data will be omitted", { - cause: error, - }); - } - } - if (data instanceof ArrayBuffer) { - return { - data: Array.from(new Uint8Array(data)), - type: "ArrayBuffer", - }; - } - if (ArrayBuffer.isView(data)) { - return { - data: Array.from(new Uint8Array(data.buffer)), - type: "ArrayBufferView", - }; - } - if (data instanceof FormData) { - /** @type {TypeExtMessages.XHRProcessedFormData} */ - const entries = []; - for (const [k, v] of data.entries()) { - if (typeof v === "string") { - entries.push([k, v]); - continue; - } else { - const buffer = await v.arrayBuffer(); - entries.push([ - k, - { - data: Array.from(new Uint8Array(buffer)), - lastModified: v.lastModified, - name: v.name, - mime: v.type, - }, - ]); - } - } - return { data: entries, type: "FormData" }; - } - if (data instanceof URLSearchParams) { - return { data: data.toString(), type: "URLSearchParams" }; - } - throw Error("Unexpected data type, the data will be omitted"); -} - -/** - * @param {Object} details - * @param {Object} control - * @param {{resolve: Function, reject: Function}=} promise - * @returns {Promise} - */ -async function xhr(details, control, promise) { - if (details == null) return console.error("xhr invalid details arg"); - if (!details.url) return console.error("xhr details missing url key"); - // define control method, will be replaced after port is established - control.abort = () => console.error("xhr has not yet been initialized"); - // depreciation notice - if (details.binary) { - console.warn( - "Please make sure your xhr `data` is a binary-string since you have set the `binary` true, however this legacy format is no longer recommended.", - "The `binary` key is deprecated and will be removed in the future, use binary data objects such as `Blob`, `ArrayBuffer`, `TypedArray`, etc. instead.", - ); - } - // can not send details (func, blob, etc.) through message - // construct a new processed object send to background page - /** @type {TypeExtMessages.XHRTransportableDetails} */ - const detailsParsed = { - binary: Boolean(details.binary), - data: undefined, - headers: {}, - method: String(details.method), - overrideMimeType: String(details.overrideMimeType), - password: String(details.password), - responseType: details.responseType, - timeout: Number(details.timeout), - url: String(details.url), - user: String(details.user), - hasHandlers: {}, - hasUploadHandlers: {}, - }; - // preprocess data key - try { - detailsParsed.data = await xhrDataProcessor(details.data); - } catch (error) { - console.error(error); - } - // preprocess headers key - if (typeof details.headers === "object") { - for (const [k, v] of Object.entries(details.headers)) { - detailsParsed.headers[k.toLowerCase()] = v; - } - } - // preprocess handlers - /** - * Record the handlers existing in details to a new object - * to avoid modifying the original object, and to prevent - * the original object from being changed by user scripts - * @type {TypeExtMessages.XHRHandlersObj} - */ - const handlers = {}; - /** @type {TypeExtMessages.XHRHandlers} */ - const XHRHandlers = [ - "onreadystatechange", - "onloadstart", - "onprogress", - "onabort", - "onerror", - "onload", - "ontimeout", - "onloadend", - ]; - for (const handler of XHRHandlers) { - // check which handlers are included in the original details object - if ( - handler in XMLHttpRequest.prototype && - typeof details[handler] === "function" - ) { - // add a bool to indicate if event listeners should be attached - detailsParsed.hasHandlers[handler] = true; - // record to the new object - handlers[handler] = details[handler]; - } - } - // preprocess upload handlers - /** @type {TypeExtMessages.XHRUploadHandlersObj} */ - const uploadHandlers = {}; - /** @type {TypeExtMessages.XHRUploadHandlers} */ - const XHRUploadHandlers = [ - "onabort", - "onerror", - "onload", - "onloadend", - "onloadstart", - "onprogress", - "ontimeout", - ]; - if (typeof details.upload === "object") { - for (const handler of XHRUploadHandlers) { - if ( - handler in XMLHttpRequestEventTarget.prototype && - typeof details.upload[handler] === "function" - ) { - detailsParsed.hasUploadHandlers[handler] = true; - uploadHandlers[handler] = details.upload[handler]; - } - } - } - // resolving asynchronous xmlHttpRequest - if (promise) { - detailsParsed.hasHandlers.onloadend = true; - const _onloadend = handlers.onloadend; - handlers.onloadend = (response) => { - promise.resolve(response); - _onloadend?.(response); - }; - } - // make sure to listen to XHR.DONE events only once, to avoid processing - // and transmitting the same response data multiple times - if (detailsParsed.hasHandlers.onreadystatechange) { - delete detailsParsed.hasHandlers.onload; - delete detailsParsed.hasHandlers.onloadend; - } - if (detailsParsed.hasHandlers.onload) { - delete detailsParsed.hasHandlers.onloadend; - } - // generate random port name for single xhr - const xhrPortName = Math.random().toString(36).substring(1, 9); - /** - * port listener, most of the messaging logic goes here - * @type {Parameters[0]} - * @param {import("../global.d.ts").TypeContentScripts.XHRPort} port - */ - const listener = (port) => { - if (port.name !== xhrPortName) return; - // handle port messages - port.onMessage.addListener(async (msg) => { - const handler = msg.handler; - // handle upload progress - if ( - "progress" in msg && - detailsParsed.hasUploadHandlers[handler] && - typeof uploadHandlers[handler] === "function" - ) { - // call userscript handler - uploadHandlers[handler](msg.progress); - return; - } - // handle download events - if ( - "response" in msg && - detailsParsed.hasHandlers[handler] && - typeof handlers[handler] === "function" - ) { - // process xhr response - /** @type {TypeExtMessages.XHRTransportableResponse} */ - const msgResponse = msg.response; - /** @type {TypeExtMessages.XHRResponse} */ - const response = msgResponse; - // only include responseText when needed - if (["", "text"].includes(response.responseType)) { - response.responseText = response.response; - } - // only process when xhr is complete and data exist - if (response.readyState === 4 && response.response !== null) { - xhrResponseProcessor(msgResponse, response); - } - // call userscript handler - handlers[handler](response); - // call the deleted XHR.DONE handlers above - if (response.readyState === 4) { - if (handler === "onreadystatechange") { - if (typeof handlers.onload === "function") { - handlers.onload(response); - } - if (typeof handlers.onloadend === "function") { - handlers.onloadend(response); - } - } else if (handler === "onload") { - if (typeof handlers.onloadend === "function") { - handlers.onloadend(response); - } - } - } - } - // all messages received - if (handler === "onloadend") { - // tell background it's safe to close port - port.postMessage({ name: "DISCONNECT" }); - } - }); - // handle port disconnect and clean tasks - port.onDisconnect.addListener((p) => { - if (p?.error) { - console.error(`port disconnected due to an error: ${p.error.message}`); - } - browser.runtime.onConnect.removeListener(listener); - }); - // fill the method returned to the user script - control.abort = () => port.postMessage({ name: "ABORT" }); - }; - // wait for the background to establish a port connection - browser.runtime.onConnect.addListener(listener); - // pass the basic information to the background through a common message - const message = { - name: "API_XHR", - details: detailsParsed, - xhrPortName, - }; - sendMessageProxy(message); -} - -function xmlHttpRequest(details) { - let promise; - const control = new Promise((resolve, reject) => { - promise = { resolve, reject }; - }); - xhr(details, control, promise); - return control; -} - -function GM_xmlhttpRequest(details) { - const control = {}; - xhr(details, control); - return control; -} - -export default { - setValue, - getValue, - listValues, - deleteValue, - openInTab, - getTab, - saveTab, - closeTab, - addStyle, - setClipboard, - // notification, - // registerMenuCommand, - // getResourceUrl, - xmlHttpRequest, - GM_xmlhttpRequest, -}; diff --git a/src/ext/content-scripts/entry-dot-user-js.js b/src/ext/content-scripts/entry-dot-user-js.js deleted file mode 100644 index 66757ff0..00000000 --- a/src/ext/content-scripts/entry-dot-user-js.js +++ /dev/null @@ -1,12 +0,0 @@ -async function initialize() { - // avoid duplicate injection of content scripts - if (window["CS_ENTRY_DOT_USER_JS"]) return; - window["CS_ENTRY_DOT_USER_JS"] = 1; - // check user settings - const key = "US_AUGMENTED_USERJS_INSTALL"; - if ((await browser.storage.local.get(key))[key] === false) return; - // actual execution content - browser.runtime.sendMessage({ name: "WEB_USERJS_POPUP" }); -} - -initialize(); diff --git a/src/ext/content-scripts/entry-script-market.js b/src/ext/content-scripts/entry-script-market.js deleted file mode 100644 index 45ba17d6..00000000 --- a/src/ext/content-scripts/entry-script-market.js +++ /dev/null @@ -1,63 +0,0 @@ -let url; - -async function injection() { - const tabUrl = new URL(location.href); - let links; - if (tabUrl.hostname.endsWith("greasyfork.org")) { - links = document.querySelectorAll( - '#install-area a.install-link[data-install-format="js"]', - ); - } - for (const link of links) { - if (link["href"]) url = link["href"]; - link.addEventListener( - "click", - (e) => { - e.stopImmediatePropagation(); - e.preventDefault(); - browser.runtime.sendMessage({ name: "WEB_USERJS_POPUP" }); - }, - true, - ); - } -} - -async function listeners() { - /** - * handle messages from background, popup, etc... - * @type {import("webextension-polyfill").Runtime.OnMessageListener} - */ - const handleMessage = async (message) => { - if (import.meta.env.MODE === "development") { - console.debug(message, url); - } - if (message === "TAB_CLICK_USERJS") { - return url; - } - }; - /** Dynamically remove listeners to avoid memory leaks */ - if (document.visibilityState === "visible") { - browser.runtime.onMessage.addListener(handleMessage); - } - document.addEventListener("visibilitychange", () => { - if (document.hidden) { - browser.runtime.onMessage.removeListener(handleMessage); - } else { - browser.runtime.onMessage.addListener(handleMessage); - } - }); -} - -async function initialize() { - // avoid duplicate injection of content scripts - if (window["CS_ENTRY_SCRIPT_MARKET"]) return; - window["CS_ENTRY_SCRIPT_MARKET"] = 1; - // check user settings - const key = "US_AUGMENTED_USERJS_INSTALL"; - if ((await browser.storage.local.get(key))[key] === false) return; - // actual execution content - injection(); - listeners(); -} - -initialize(); diff --git a/src/ext/content-scripts/entry-userscripts.js b/src/ext/content-scripts/entry-userscripts.js deleted file mode 100644 index 362bfacb..00000000 --- a/src/ext/content-scripts/entry-userscripts.js +++ /dev/null @@ -1,294 +0,0 @@ -import USAPI from "./api.js"; -import { colors } from "@shared/colors.js"; - -// code received from background page will be stored in this variable -// code referenced again when strict CSPs block initial injection attempt -let data; -// determines whether strict csp injection has already run (JS only) -let cspFallbackAttempted = false; - -// label used to distinguish frames in console -const label = randomLabel(); -const usTag = window.self === window.top ? "" : `(${label})`; - -function randomLabel() { - const a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - const r = Math.random(); - return a[Math.floor(r * a.length)] + r.toString().slice(5, 6); -} - -function triageJS(userscript) { - const runAt = userscript.scriptObject["run-at"]; - if (runAt === "document-start") { - injectJS(userscript); - } else if (runAt === "document-end") { - if (document.readyState !== "loading") { - injectJS(userscript); - } else { - document.addEventListener( - "DOMContentLoaded", - () => injectJS(userscript), - { once: true }, - ); - } - } else if (runAt === "document-idle") { - if (document.readyState === "complete") { - injectJS(userscript); - } else { - const handle = () => { - if (document.readyState === "complete") { - injectJS(userscript); - document.removeEventListener("readystatechange", handle); - } - }; - document.addEventListener("readystatechange", handle); - } - } -} - -function injectJS(userscript) { - const filename = userscript.scriptObject.filename; - const name = userscript.scriptObject.name; - const code = `\ -(async () => { - try { -// ===UserScript===start=== -${userscript.code} -// ===UserScript====end==== - } catch (error) { - console.error(\`${filename.replaceAll("`", "\\`")}\`, error); - } -})(); //# sourceURL=${filename.replace(/[\s"']/g, "-") + usTag}`; - let injectInto = userscript.scriptObject["inject-into"]; - // change scope to content since strict CSP event detected - if (injectInto === "auto" && (userscript.fallback || cspFallbackAttempted)) { - injectInto = "content"; - console.warn(`Attempting fallback injection for ${name}`); - } - const world = injectInto === "content" ? "content" : "page"; - if (window.self === window.top) { - console.info(`Injecting: ${name} %c(js/${world})`, colors.yellow); - } else { - console.info( - `Injecting: ${name} %c(js/${world})%c - %cframe(${label})(${window.location})`, - colors.yellow, - colors.inherit, - colors.blue, - ); - } - if (world === "page") { - const div = document.createElement("div"); - div.style.display = "none"; - const shadowRoot = div.attachShadow({ mode: "closed" }); - const tag = document.createElement("script"); - tag.textContent = code; - shadowRoot.append(tag); - (document.body ?? document.head ?? document.documentElement).append(div); - } else { - try { - Function( - `{${Object.keys(userscript.apis).join(",")}}`, - code, - )(userscript.apis); - } catch (error) { - console.error(`${filename}`, error); - } - return; - } -} - -function injectCSS(name, code) { - if (window.self === window.top) { - console.info(`Injecting ${name} %c(css)`, colors.green); - } else { - console.info( - `Injecting ${name} %c(css)%c - %cframe(${label})(${window.location})`, - colors.green, - colors.inherit, - colors.blue, - ); - } - // Safari lacks full support for tabs.insertCSS - // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/insertCSS - // specifically frameId and cssOrigin - // if support for those details keys arrives, the method below can be used - // NOTE: manifest V3 does support frameId, but not origin - // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/insertCSS - - // write the css code to head of the document - const tag = document.createElement("style"); - tag.textContent = code; - document.head.appendChild(tag); -} - -function cspFallback(e) { - // if a security policy violation event has occurred - // and the directive is script-src or script-src-elem - // it's fair to assume that there is a strict CSP for javascript - // and that injection was blocked for all userscripts - // when any script-src violation is detected, re-attempt injection - if ( - e.effectiveDirective === "script-src" || - e.effectiveDirective === "script-src-elem" - ) { - // get all "auto" code - // since other code can trigger a security policy violation event - // make sure data var is not undefined before attempting fallback - if (!data || cspFallbackAttempted) return; - // update global that tracks security policy violations - cspFallbackAttempted = true; - // for all userscripts with @inject-into: auto, attempt re-injection - for (let i = 0; i < data.files.js.length; i++) { - const userscript = data.files.js[i]; - if (userscript.scriptObject["inject-into"] !== "auto") continue; - userscript.fallback = 1; - triageJS(userscript); - } - } -} - -async function injection() { - const response = await browser.runtime.sendMessage({ - name: "REQ_USERSCRIPTS", - }); - if (import.meta.env.MODE === "development") { - console.debug("REQ_USERSCRIPTS", response); - } - // cancel injection if errors detected - if (!response || response.error) { - console.error(response?.error || "REQ_USERSCRIPTS returned undefined"); - return; - } - // save response locally in case CSP events occur - data = response; - // combine regular and context-menu scripts - const scripts = [...data.files.js, ...data.files.menu]; - // loop through each userscript and prepare for processing - for (let i = 0; i < scripts.length; i++) { - const userscript = scripts[i]; - const filename = userscript.scriptObject.filename; - const grants = userscript.scriptObject.grant; - const injectInto = userscript.scriptObject["inject-into"]; - // create GM.info object, all userscripts get access to GM.info - userscript.apis = { GM: {} }; - userscript.apis.GM.info = { - script: userscript.scriptObject, - scriptHandler: data.scriptHandler, - scriptHandlerVersion: data.scriptHandlerVersion, - scriptMetaStr: userscript.scriptMetaStr, - version: data.scriptHandlerVersion, - }; - // add GM_info - userscript.apis.GM_info = userscript.apis.GM.info; - // if @grant explicitly set to none, empty grants array - if (grants.includes("none")) grants.length = 0; - // @grant values exist for page scoped userscript - if (grants.length && injectInto === "page") { - // remove grants - grants.length = 0; - // log warning - console.warn( - `${filename} @grant values removed due to @inject-into value: ${injectInto} - https://github.com/quoid/userscripts/issues/265#issuecomment-1213462394`, - ); - } - // @grant exist for auto scoped userscript - if (grants.length && injectInto === "auto") { - // change scope - userscript.scriptObject["inject-into"] = "content"; - // log warning - console.warn( - `${filename} @inject-into value set to 'content' due to @grant values: ${grants} - https://github.com/quoid/userscripts/issues/265#issuecomment-1213462394`, - ); - } - // loop through each userscript @grant value, add methods as needed - for (let j = 0; j < grants.length; j++) { - const grant = grants[j]; - const method = grant.startsWith("GM.") ? grant.slice(3) : grant; - // ensure API method exists in USAPI object - if (!Object.keys(USAPI).includes(method)) continue; - // add granted methods - switch (method) { - case "info": - case "GM_info": - continue; - case "getValue": - case "setValue": - case "deleteValue": - case "listValues": - userscript.apis.GM[method] = USAPI[method].bind({ - US_filename: filename, - }); - break; - case "GM_xmlhttpRequest": - userscript.apis[method] = USAPI[method]; - break; - default: - userscript.apis.GM[method] = USAPI[method]; - } - } - // triage userjs item for injection - triageJS(userscript); - } - // loop through each usercss and inject - for (let i = 0; i < data.files.css.length; i++) { - const userstyle = data.files.css[i]; - injectCSS(userstyle.name, userstyle.code); - } -} - -function listeners() { - /** listen for CSP violations */ - document.addEventListener("securitypolicyviolation", cspFallback, { - once: true, - }); - /** - * listens for messages from background, popup, etc... - * @type {import("webextension-polyfill").Runtime.OnMessageListener} - */ - const handleMessage = (message) => { - const name = message.name; - if (name === "CONTEXT_RUN") { - // from bg script when context-menu item is clicked - // double check to ensure context-menu scripts only run in top windows - if (window !== window.top) return; - // loop through context-menu scripts saved to data object and find match - // if no match found, nothing will execute and error will log - const filename = message.menuItemId; - for (let i = 0; i < data.files.menu.length; i++) { - const item = data.files.menu[i]; - if (item.scriptObject.filename === filename) { - console.info(`Injecting ${filename} %c(js)`, colors.yellow); - injectJS(item); - return; - } - } - console.error(`Couldn't find ${filename} code!`); - } - }; - /** Dynamically remove listeners to avoid memory leaks */ - if (document.visibilityState === "visible") { - browser.runtime.onMessage.addListener(handleMessage); - } - document.addEventListener("visibilitychange", () => { - if (document.hidden) { - browser.runtime.onMessage.removeListener(handleMessage); - } else { - browser.runtime.onMessage.addListener(handleMessage); - } - }); -} - -async function initialize() { - // avoid duplicate injection of content scripts - if (window["CS_ENTRY_USERSCRIPTS"]) return; - window["CS_ENTRY_USERSCRIPTS"] = 1; - // check user settings - const key = "US_GLOBAL_ACTIVE"; - const results = await browser.storage.local.get(key); - if (results[key] === false) return console.info("Userscripts off"); - // start the injection process and add the listeners - injection(); - listeners(); -} - -initialize(); diff --git a/src/ext/extension-page/App.svelte b/src/ext/extension-page/App.svelte deleted file mode 100644 index 22487e8f..00000000 --- a/src/ext/extension-page/App.svelte +++ /dev/null @@ -1,205 +0,0 @@ - - - - -{#if $v4state.includes("init")} -
- - {#if $v4state.includes("init-error")} - Failed to initialize app, check the browser console - {:else} - Initializing app... - {/if} -
-{/if} -
- {#if !sidebarHidden} - -
- {/if} - -
-{#if splitterActive} -
-{/if} -
    - {#each $notifications as item (item.id)} - notifications.remove(item.id)} {item} /> - {/each} -
-{#if $v4state.includes("settings")} - v4state.remove("settings")} let:navRegister> - - -{/if} - - diff --git a/src/ext/extension-page/Appios.svelte b/src/ext/extension-page/Appios.svelte deleted file mode 100644 index 048def7d..00000000 --- a/src/ext/extension-page/Appios.svelte +++ /dev/null @@ -1,88 +0,0 @@ - - -{#if $v4state.includes("init")} -
- - {#if $v4state.includes("init-error")} - Failed to initialize app, check the browser console - {:else} - Initializing app... - {/if} -
-{/if} -
    - {#each $notifications as item (item.id)} - notifications.remove(item.id)} {item} /> - {/each} -
-{#if $v4state.includes("settings")} - -{/if} - - diff --git a/src/ext/extension-page/Components/Editor/CodeMirror.svelte b/src/ext/extension-page/Components/Editor/CodeMirror.svelte deleted file mode 100644 index b2cbacda..00000000 --- a/src/ext/extension-page/Components/Editor/CodeMirror.svelte +++ /dev/null @@ -1,436 +0,0 @@ - - - - - - -{#if initialized} - (searchActive = false)} - {instance} - /> -{/if} - - diff --git a/src/ext/extension-page/Components/Editor/Editor.svelte b/src/ext/extension-page/Components/Editor/Editor.svelte deleted file mode 100644 index e0b7c719..00000000 --- a/src/ext/extension-page/Components/Editor/Editor.svelte +++ /dev/null @@ -1,358 +0,0 @@ - - -
- {#if $v4state.includes("editor-loading") || $v4state.includes("fetching")} - - {/if} - {#if !activeItem} -
No Item Selected
- {/if} -
- {#if sidebarHidden} - - {/if} -
-
- -
{name}
-
-
-
- {#if $v4state.includes("saving")} - Saving... - {:else if $v4state.includes("trashing")} - (◞‸◟) - {:else if $v4state.includes("updating")} - Updating code, - {:else if remote} - Code was remotely fetched, - check carefully before saving! - {:else if temp} - Ready for code! - {:else} - Last modified: {lastModified} - {/if} -
-
-
-
- - - -
-
-
- -
- -
- - diff --git a/src/ext/extension-page/Components/Editor/EditorSearch.svelte b/src/ext/extension-page/Components/Editor/EditorSearch.svelte deleted file mode 100644 index 6c76e4a6..00000000 --- a/src/ext/extension-page/Components/Editor/EditorSearch.svelte +++ /dev/null @@ -1,203 +0,0 @@ - - -{#if active} - -{/if} - - diff --git a/src/ext/extension-page/Components/ModalWrapper.svelte b/src/ext/extension-page/Components/ModalWrapper.svelte deleted file mode 100644 index 9cb4c5aa..00000000 --- a/src/ext/extension-page/Components/ModalWrapper.svelte +++ /dev/null @@ -1,150 +0,0 @@ - - -
- - - -
- -
- - diff --git a/src/ext/extension-page/Components/Notification.svelte b/src/ext/extension-page/Components/Notification.svelte deleted file mode 100644 index afdb56b9..00000000 --- a/src/ext/extension-page/Components/Notification.svelte +++ /dev/null @@ -1,154 +0,0 @@ - - -
  • - -
    - -
    {@html icon}
    - {item.message} - -
    -
  • - - diff --git a/src/ext/extension-page/Components/Settings.svelte b/src/ext/extension-page/Components/Settings.svelte deleted file mode 100644 index 8ef12c4c..00000000 --- a/src/ext/extension-page/Components/Settings.svelte +++ /dev/null @@ -1,845 +0,0 @@ - - -
    - {#each groups as group (group)} -
    -
    -
    {gl(`settings_section_${group}`)}
    - {#if indicators.resetting} - - {/if} -
    - {#each groupItems(group) as item (item.name)} - {@const ariaAttributes = { - "aria-labelledby": `${item.name}_label`, - "aria-describedby": `${item.name}_desc`, - }} -
    -
    -
    - {gl(`settings_${item.name}`)} -
    -
    - {gl(`settings_${item.name}_desc`)} -
    -
    - {#if item.nodeType === "Toggle"} - - settings.updateSingleSetting( - item.name, - !$settings[item.name], - )} - /> - {/if} - {#if item.nodeType === "select"} - - {/if} -
    -
    - {#if indicators.resetting && !indicators.saving[item.name] && !item.protect && (item.name !== "global_exclude_match" || !gemFocused)} - - {/if} - {#if item.nodeType === "textarea"} - {#if indicators.saving[item.name]} -
    - - {@html iconLoader} - {gl(`settings_${item.name}_saving`)} -
    - {/if} - {#if gemFocused} - - - {/if} - {/if} -
    -
    - {#if item.nodeType === "textarea" && item.name === "global_exclude_match"} -
    - -
    - {#each gemParsed.items as p (p)} - - {p.start}{#if p.warn || p.error}{p.value}{:else}{p.value}{/if}{p.separ} - {/each} -
    -
    -
    - {gl(`settings_${item.name}_refer`)} - -
    - {/if} -
    - {/each} -
    - {/each} -
    -
    -
    {gl(`settings_section_native`)}
    -
    -
    -
    -
    {gl("settings_scripts_directory")}
    -
    {gl("settings_scripts_directory_desc")}
    -
    -
    - {#if indicators.loading.changeSaveLocation} - - {@html iconLoader} - {/if} - -
    -
    -
    - -
    -
    -
    -
    -
    {gl(`settings_section_tools`)}
    -
    -
    -
    - {#if indicators.resetting} - - - {:else} - - - - {/if} -
    - -
    {gl("settings_scripts_tools_desc")}
    -
    -
    -
    -
    - {gl(`settings_section_about`)} -
    -
    -
    -

    - Userscripts {import.meta.env.BROWSER ?? ""} - {#if import.meta.env.GIT_TAG && import.meta.env.GIT_COMMIT} - - () - {:else} - v{$settings["version"]} - ({$settings["build"]}) - {/if} -

    -

    - {gl("settings_about_text1")} - - | - - | - -

    -

    - {gl("settings_about_text2")} - - | - -

    -
    -
    -
    -
    - - diff --git a/src/ext/extension-page/Components/Sidebar/Sidebar.svelte b/src/ext/extension-page/Components/Sidebar/Sidebar.svelte deleted file mode 100644 index c5af6b55..00000000 --- a/src/ext/extension-page/Components/Sidebar/Sidebar.svelte +++ /dev/null @@ -1,307 +0,0 @@ - - - - - diff --git a/src/ext/extension-page/Components/Sidebar/SidebarFilter.svelte b/src/ext/extension-page/Components/Sidebar/SidebarFilter.svelte deleted file mode 100644 index d63e8048..00000000 --- a/src/ext/extension-page/Components/Sidebar/SidebarFilter.svelte +++ /dev/null @@ -1,116 +0,0 @@ - - -
    - - - {#each orders as order (order)} - - {/each} - - {#if query} - (query = "")} - {disabled} - title="Clear" - /> - {/if} -
    - - diff --git a/src/ext/extension-page/Components/Sidebar/SidebarItem.svelte b/src/ext/extension-page/Components/Sidebar/SidebarItem.svelte deleted file mode 100644 index c7c27bc7..00000000 --- a/src/ext/extension-page/Components/Sidebar/SidebarItem.svelte +++ /dev/null @@ -1,104 +0,0 @@ - - -
    -
    - -
    {data.name}
    - -
    - {#if description} -
    - {description} -
    - {/if} -
    - - diff --git a/src/ext/extension-page/app.css b/src/ext/extension-page/app.css deleted file mode 100644 index 4ae66302..00000000 --- a/src/ext/extension-page/app.css +++ /dev/null @@ -1,81 +0,0 @@ -html { - font-size: 100%; - height: 100vh; - height: 100svh; /* safari 15.4 */ - overflow: hidden; - overscroll-behavior: none; -} - -/* ios */ -@supports (-webkit-touch-callout: none) { - html { - height: auto; - overflow: visible; - } - - /** - * Dynamic Type - * https://support.apple.com/102453 - * https://webkit.org/blog/3709/using-the-system-font-in-web-content/ - * https://developer.apple.com/library/archive/releasenotes/General/WhatsNewInSafari/Articles/Safari_7_0.html#//apple_ref/doc/uid/TP40014305-CH5-SW10 - * https://github.com/w3c/csswg-drafts/issues/3708 - */ - @supports (font: -apple-system-body) { - html { - /* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */ - font: -apple-system-body; /* default 17px */ - } - } - - /* Avoid page zoom */ - input, - textarea, - select { - font-size: max(1rem, 16px); - } -} - -body { - background-color: var(--color-bg-primary); - color: var(--text-color-primary); - font: var(--text-default); - height: 100%; - text-rendering: optimizelegibility; - -webkit-font-smoothing: antialiased; -} - -noscript { - display: block; -} - -#app { - display: flex; - flex-direction: column; - height: 100%; -} - -a, -.link { - background: none; - color: var(--color-blue); - cursor: pointer; - text-decoration: underline; -} - -.truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -button { - border: none; - cursor: pointer; - padding: 0; - user-select: none; -} - -button:disabled { - opacity: var(--opacity-disabled); - pointer-events: none; -} diff --git a/src/ext/extension-page/codemirror.css b/src/ext/extension-page/codemirror.css deleted file mode 100644 index bd3e5c40..00000000 --- a/src/ext/extension-page/codemirror.css +++ /dev/null @@ -1,214 +0,0 @@ -.CodeMirror { - background-color: transparent; - color: var(--editor-default); - font-family: var(--editor-font); - font-size: var(--editor-font-size); - font-weight: 400; - height: 100%; - line-height: var(--editor-line-height); - text-rendering: unset; - -webkit-font-smoothing: antialiased; -} - -.CodeMirror-gutters { - background-color: transparent; - border-right: 0; -} - -.CodeMirror-activeline-background, -.CodeMirror-activeline-gutter { - background-color: var(--editor-active-line); -} - -.CodeMirror-linenumber { - color: var(--text-color-primary); - font-size: var(--editor-font-size); - opacity: 0.25; -} - -.CodeMirror-activeline .CodeMirror-linenumber { - opacity: 0.5; -} - -.CodeMirror-cursor { - border-left: 2px solid var(--text-color-secondary); /* check */ -} - -.CodeMirror-hints { - background-color: var(--color-bg-theme); - border: 1px solid var(--border-color); - box-shadow: var(--box-shadow); - font: var(--text-small); - font-family: var(--editor-font); - line-height: 1.5rem; -} - -.CodeMirror-hint { - color: var(--text-color-secondary); -} - -li.CodeMirror-hint-active { - background-color: var(--color-blue); - color: light-dark(var(--color-white), var(--color-black)); -} - -.cm-s-default .CodeMirror-selected { - background-color: var(--editor-selected-bg); -} - -div.CodeMirror span.CodeMirror-matchingbracket { - color: var(--editor-matching-bracket-color); - border-bottom: 2px solid var(--editor-matching-bracket-border); -} - -div.CodeMirror span.CodeMirror-nonmatchingbracket { - color: var(--editor-non-matching-bracket); -} - -.CodeMirror .CodeMirror-placeholder, -.cm-s-default .cm-comment { - color: var(--editor-comment); -} - -.cm-s-default .cm-keyword { - color: var(--editor-keyword); -} - -.cm-s-default .cm-def { - color: var(--editor-def); -} - -.cm-s-default .cm-variable, -.cm-s-default .cm-variable-2 { - color: inherit; -} - -.cm-s-default .cm-operator { - color: var(--editor-operator); -} - -.cm-s-default .cm-property { - color: var(--editor-property); -} - -.cm-s-default .cm-string { - color: var(--editor-string); -} - -.cm-s-default .cm-string-2 { - color: var(--editor-string-2); -} - -.cm-s-default .cm-number { - color: var(--editor-number); -} - -.cm-s-default .cm-atom { - color: var(--editor-atom); -} - -.cm-s-default .cm-error { - color: var(--color-red); -} - -.CodeMirror .cm-whitespace::before, -.CodeMirror .CodeMirror-line > span::after, -.CodeMirror .CodeMirror-code > div > pre > span::after { - color: var(--editor-invisible); -} - -.cm-s-default .cm-variable-3, -.cm-s-default .cm-builtin, -.cm-s-default .cm-qualifier, -.cm-s-default .cm-tag { - color: var(--editor-def); -} - -.cm-s-default .cm-searching { - background-color: var(--editor-search-highlight); - padding: 3px 0; -} - -.cm-s-default .cm-search-mark { - border-bottom: 2px solid var(--editor-matching-bracket-border); -} - -/* -.cm-s-default .cm-matchhighlight { - background-color: var(--editor-matched-highlight); -} -*/ - -.CodeMirror-lint-markers { - width: 8px; -} - -.CodeMirror-lint-marker { - border-radius: 50%; - cursor: default; - height: 0.375rem; - left: 0.25rem; - position: relative; - width: 0.375rem; -} - -.CodeMirror-lint-marker-error, -.CodeMirror-lint-marker-warning { - background: var(--color-yellow); - top: -1px; -} - -.CodeMirror-lint-marker-error { - background-color: var(--editor-error); -} - -.CodeMirror-lint-marker-multiple { - background: var(--editor-def); - left: 0; - position: absolute; - top: 0; -} - -.CodeMirror-lint-mark-warning { - background: none; - border-bottom: 2px solid var(--color-yellow); -} - -.CodeMirror-lint-mark-error { - background: none; - border-bottom: 2px solid var(--editor-error); -} - -.CodeMirror-lint-tooltip { - background-color: var(--color-bg-theme); - border: 1px solid var(--border-color); - border-radius: var(--border-radius); - box-shadow: var(--box-shadow); - color: var(--text-color-secondary); - font: var(--text-small); - padding: 0.5rem; - transition: opacity 200ms; -} - -.CodeMirror-lint-message-error, -.CodeMirror-lint-message-warning { - background: none; - padding-left: 1rem; - position: relative; -} - -.CodeMirror-lint-message-error::before, -.CodeMirror-lint-message-warning::before { - background-color: var(--color-yellow); - border-radius: 50%; - content: ""; - height: 0.5rem; - left: 0; - position: absolute; - top: 0.25rem; - width: 0.5rem; -} - -.CodeMirror-lint-message-error::before { - background-color: var(--editor-error); -} diff --git a/src/ext/extension-page/codemirror.js b/src/ext/extension-page/codemirror.js deleted file mode 100644 index a74b0874..00000000 --- a/src/ext/extension-page/codemirror.js +++ /dev/null @@ -1,27 +0,0 @@ -import CodeMirror from "codemirror"; -import "codemirror/mode/javascript/javascript.js"; -import "codemirror/mode/css/css.js"; -import "codemirror/addon/comment/comment.js"; -import "codemirror/addon/comment/continuecomment.js"; -import "codemirror/addon/selection/active-line.js"; -import "codemirror/addon/edit/closebrackets.js"; -import "codemirror/addon/edit/matchbrackets.js"; -import "codemirror/addon/hint/show-hint.js"; -import "codemirror/addon/hint/javascript-hint.js"; -import "codemirror/addon/fold/foldcode.js"; -import "codemirror/addon/fold/foldgutter.js"; -import "codemirror/addon/fold/brace-fold.js"; -import "codemirror/addon/fold/indent-fold.js"; -import "codemirror/addon/search/searchcursor.js"; -import "codemirror/addon/search/match-highlighter.js"; // disabled -import "codemirror/addon/lint/lint.js"; -import "codemirror/addon/lint/javascript-lint.js"; - -import "codemirror/lib/codemirror.css"; -import "codemirror/addon/hint/show-hint.css"; -import "codemirror/addon/fold/foldgutter.css"; -import "codemirror/addon/lint/lint.css"; - -import "cm-show-invisibles/lib/show-invisibles.js"; - -export default CodeMirror; diff --git a/src/ext/extension-page/main.js b/src/ext/extension-page/main.js deleted file mode 100644 index fd0a7abe..00000000 --- a/src/ext/extension-page/main.js +++ /dev/null @@ -1,64 +0,0 @@ -import "@shared/reset.css"; -import "@shared/variables.css"; -import "./app.css"; -import { mount } from "svelte"; -import App from "./App.svelte"; -import Appios from "./Appios.svelte"; - -// vite feat that only import in dev mode -if (import.meta.env.MODE === "development") { - try { - const modules = import.meta.glob("@ext/dev.js", { eager: true }); - const browser = modules["/src/ext/shared/dev.js"]["browser"]; - console.debug("DEV-ENV", import.meta.env, modules, browser); - // basic dev mode relies on extension environment simulation - if (!window?.browser?.extension && browser) { - // assign to window simulation WebExtension APIs - window.browser = browser; - // pre-fetch i18n resource registration to window - const lang = window.navigator.language.replace("-", "_"); - let url = "/public/ext/shared/_locales/en/messages.json"; - if (lang.startsWith("zh")) { - url = "/public/ext/shared/_locales/zh/messages.json"; - } - // demo build for non-extension environment (gh-pages) - if (import.meta.env.EXT_DEMO_BUILD) { - url = "/_locales/en/messages.json"; - if (["zh_HK", "zh_MO", "zh_TW"].includes(lang)) { - url = `/_locales/${lang}/messages.json`; - } else if (lang.startsWith("zh")) { - url = `/_locales/zh/messages.json`; - } - } - try { - const response = await fetch(url); - const messages = await response.json(); - window["i18nMessages"] = messages; - } catch (error) { - console.error("Fetch i18n faild", error); - } - } - } catch (error) { - console.error(error); - } -} - -let app; -const target = document.getElementById("app"); -if (import.meta.env.MODE === "development") { - const platform = await browser.runtime.getPlatformInfo(); - // @ts-ignore -- incomplete polyfill types - if (platform.os === "ios") { - app = mount(Appios, { target }); - } else { - app = mount(App, { target }); - } -} else { - if (import.meta.env.SAFARI_PLATFORM === "ios") { - app = mount(Appios, { target }); - } else { - app = mount(App, { target }); - } -} - -export default app; diff --git a/src/ext/extension-page/store.js b/src/ext/extension-page/store.js deleted file mode 100644 index 0b2959c2..00000000 --- a/src/ext/extension-page/store.js +++ /dev/null @@ -1,176 +0,0 @@ -import { writable } from "svelte/store"; -import { uniqueId, contentScriptRegistration } from "@ext/utils.js"; -import * as settingsStorage from "@ext/settings.js"; -import { sendNativeMessage } from "@ext/native.js"; - -function notificationStore() { - const { subscribe, update } = writable([]); - const add = (item) => { - update((a) => { - a.push(item); - return a; - }); - }; - const remove = (id) => update((a) => a.filter((b) => b.id !== id)); - return { subscribe, add, remove }; -} -export const notifications = notificationStore(); - -function logStore() { - const { subscribe, set, update } = writable([]); - const add = (message, type, notify) => { - const item = { id: uniqueId(), message, time: Date.now(), type }; - if (notify || type === "error") notifications.add(item); // always notify on error - update((a) => { - a.push(item); - return a; - }); - }; - const remove = (id) => update((a) => a.filter((b) => b.id !== id)); - const reset = () => set([]); - return { subscribe, add, remove, reset }; -} -export const log = logStore(); - -function stateStore() { - const { subscribe, update } = writable(["init"]); - // store oldState to see how state transitioned - // ex. if (newState === foo && oldState === bar) baz(); - let oldState = []; - const add = (stateModifier) => { - update((state) => { - // list of acceptable states, mostly for state definition tracking - const states = [ - "init", // the uninitialized app state (start screen) - "init-error", // unique error when initialization fails, shows error on load screen - "settings", // when the settings modal is shown - "items-loading", // when the sidebar items are loading - "saving", // when a file in the editor is being saved - "fetching", // when a new remote file has been added and it being fetched - "trashing", // when deleting the file in the editor - "updating", // when the file in the editor is being updating - ]; - // disallow adding undefined states - if (!states.includes(stateModifier)) { - console.error("invalid state"); - return state; - } - // save pre-changed state to oldState var - oldState = [...state]; - // if current state modifier not present, add it to state array - if (!state.includes(stateModifier)) state.push(stateModifier); - // ready state only when no other states present, remove it if present - if (state.includes("ready")) state.splice(state.indexOf("ready"), 1); - log.add( - `App state updated to: ${state} from: ${oldState}`, - "info", - false, - ); - return state; - }); - // URL hash handle - const params = new URLSearchParams(location.hash.slice(1)); - if (["settings"].includes(stateModifier)) { - params.set("state", stateModifier); - location.hash = params.toString(); - } - }; - const remove = (stateModifier) => { - update((state) => { - // save pre-changed state to oldState var - oldState = [...state]; - // if current state modifier present, remove it from state array - if (state.includes(stateModifier)) - state.splice(state.indexOf(stateModifier), 1); - // if no other states, push ready state - if (state.length === 0) state.push("ready"); - log.add( - `App state updated to: ${state} from: ${oldState}`, - "info", - false, - ); - return state; - }); - // URL hash handle - const params = new URLSearchParams(location.hash.slice(1)); - const state = params.get("state"); - if (state === stateModifier) { - params.delete("state"); - location.hash = params.toString(); - } - }; - const getOldState = () => oldState; - // URL hash handle - const loadUrlState = () => { - const params = new URLSearchParams(location.hash.slice(1)); - const state = params.get("state"); - state && add(state); - }; - return { subscribe, add, getOldState, remove, loadUrlState }; -} -export const v4state = stateStore(); - -function settingsStore() { - const { subscribe, update, set } = writable({}); - let platform; - const init = async (initData) => { - platform = initData.platform; - if (import.meta.env.SAFARI_PLATFORM === "mac") { - // import legacy settings data just one-time - await settingsStorage.legacyImport(); - } - // read settings from persistence storage - const settings = await settingsStorage.get(undefined, { platform }); - if (import.meta.env.MODE === "development") { - console.debug("store.js settingsStore init", initData, settings); - } - set({ ...initData, ...settings }); - // sync popup, backgound, etc... settings changes - settingsStorage.onChangedSettings((sets, area) => { - console.info(`store.js storage.${area}.onChanged`, sets); - update((obj) => Object.assign(obj, sets)); - }); - }; - /** @param {string|string[]} keys */ - const reset = async (keys = undefined) => { - await settingsStorage.reset(keys); - const settings = await settingsStorage.get(undefined, { platform }); - if (import.meta.env.MODE === "development") { - console.debug("store.js settingsStore reset", settings); - } - update((obj) => Object.assign(obj, settings)); - // legacy updates - ["global_active", "global_exclude_match"].forEach((s) => { - updateSingleSettingOld(s, settings[s]); - }); - }; - // temporarily keep the old storage method until it is confirmed that all dependencies are removed - const updateSingleSettingOld = (key, value) => { - // following settings logics is still handled in the native swift layer - if (key === "global_exclude_match") { - const message = { name: "PAGE_UPDATE_BLACKLIST", blacklist: value }; - sendNativeMessage(message).then((response) => { - response.error && log.add(response.error, "error", true); - }); - } - if (key === "global_active") { - sendNativeMessage({ name: "TOGGLE_EXTENSION", active: String(value) }); - } - }; - /** @param {string} key @param {any} value */ - const updateSingleSetting = (key, value) => { - update((settings) => ((settings[key] = value), settings)); - // save settings to persistence storage - settingsStorage.set({ [key]: value }); - // make specific changes take effect - if (key === "augmented_userjs_install") { - contentScriptRegistration(value); - } - // legacy updates - updateSingleSettingOld(key, value); - }; - return { subscribe, set, init, reset, updateSingleSetting }; -} -export const settings = settingsStore(); - -export const items = writable([]); diff --git a/src/ext/global.d.ts b/src/ext/global.d.ts deleted file mode 100644 index 8b626e08..00000000 --- a/src/ext/global.d.ts +++ /dev/null @@ -1,41 +0,0 @@ -// https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html - -/// -/// - -import type Browser from "webextension-polyfill"; - -declare global { - const browser: Browser.Browser; - interface Window { - browser: Browser.Browser; - } -} - -declare namespace TypeBackground { - interface XHRMessage { - handler: string; - progress?: TypeExtMessages.XHRProgress; - response?: TypeExtMessages.XHRTransportableResponse; - } - - interface XHRPort extends Browser.Runtime.Port { - onMessage: Browser.Events.Event< - (message: TypeContentScripts.XHRMessage, port: XHRPort) => void - >; - postMessage: (message: XHRMessage) => void; - } -} - -declare namespace TypeContentScripts { - interface XHRMessage { - name: string; - } - - interface XHRPort extends Browser.Runtime.Port { - onMessage: Browser.Events.Event< - (message: TypeBackground.XHRMessage, port: XHRPort) => void - >; - postMessage(message: XHRMessage): void; - } -} diff --git a/src/ext/jsconfig.json b/src/ext/jsconfig.json deleted file mode 100644 index 26d5891a..00000000 --- a/src/ext/jsconfig.json +++ /dev/null @@ -1,31 +0,0 @@ -// https://code.visualstudio.com/docs/languages/jsconfig -// https://www.typescriptlang.org/docs/handbook/tsconfig-json.html -// https://www.typescriptlang.org/tsconfig - -// https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html -// https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html - -{ - "compilerOptions": { - "target": "ESNext", - "module": "ESNext", - "moduleResolution": "bundler", - - "verbatimModuleSyntax": true, - "isolatedModules": true, - "resolveJsonModule": true, - - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "skipLibCheck": true, - "sourceMap": true, - - "paths": { - "@shared/*": ["../shared/*"], - "@ext/*": ["./shared/*"] - } - }, - "include": ["**/*.d.ts", "**/*.js", "**/*.svelte"] -} diff --git a/src/ext/shared/dev.js b/src/ext/shared/dev.js deleted file mode 100644 index 23633a5e..00000000 --- a/src/ext/shared/dev.js +++ /dev/null @@ -1,533 +0,0 @@ -import { parse, uniqueId, wait } from "./utils"; - -/** - * - * @param {("css"|"js")} type - * @param {boolean?} updates - * @param {boolean?} longName - * @returns - */ -function generateFile( - type, - updates = false, - longName = false, - request = false, -) { - let canUpdate = updates; - const uid = uniqueId(); - let name = request ? `${uid}-request-${type}` : `${uid}-example-${type}`; - if (longName) name = `${uid}${uid}${uid}-example-${type}`; - const randomDate = +( - Number(new Date()) - Math.floor(Math.random() * 10000000000) - ); - let content = - "// ==UserScript==" + - `\n// @name ${name}` + - `\n// @description Custom description for userscript with name "${name}"` + - "\n// @match *://*.*" + - "\n// @exclude-match https://github.com/quoid/userscripts" + - "\n// @version 1.0" + - "\n// @noframes" + - "\n// ==/UserScript==" + - `\n\nconsole.log("I am ${name}");`; - if (type === "css") { - content = content.replace("// ==UserScript==", "/* ==UserStyle=="); - content = content.replace("// ==/UserScript==", "==/UserStyle== */"); - content = content.replaceAll("// @", "@"); - content = content.replace( - `console.log("I am ${name}");`, - "#id,\n.class\n.pseudo-element::after {\n color: red\n}", - ); - canUpdate = false; - } - if (request) { - content = content.replace( - "// @noframes", - "// @noframes\n// @run-at request", - ); - } - if (canUpdate) { - content = content.replace( - "1.0", - "1.0\n// @updateURL https://www.k21p.com/example.user.js", - ); - content = content.replace( - `console.log("I am ${name}");`, - `console.log("I am ${name} and you can update me!");`, - ); - } - return { - content, - filename: `${name}.${type}`, - lastModified: randomDate, - name, - request, - type, - }; -} - -/** - * @typedef {Object} File - * @property {string} content - ... - * @property {string} filename - ... - * @property {number} lastModified - ... - * @property {string} [name] - ... - * @property {boolean} [request] - ... - * @property {"css" | "js"} [type] - ... - */ -/** @type {File[]} */ -const files = [ - generateFile("js", true, true), - generateFile("css"), - generateFile("js", false, false, true), - ...Array.from({ length: 7 }, () => generateFile("js")), -]; - -/** @type {"ios"|"macos"} */ -const platform = "macos"; - -const _browser = { - delay: 200, - platform, - runtime: { - getURL() { - return "https://www.example.com/"; - }, - async getPlatformInfo() { - return { os: platform }; - }, - async sendMessage(message, responseCallback) { - const name = message.name; - console.info(`Got message: ${name}`); - let response = {}; - if (name === "REFRESH_DNR_RULES") { - response = { success: true }; - } - if (!responseCallback) { - return new Promise((resolve) => { - setTimeout(() => resolve(response), _browser.delay); - }); - } - setTimeout(() => responseCallback(response), _browser.delay); - }, - async sendNativeMessage(application, message, responseCallback) { - const name = message.name; - console.info(`Got message: ${name}`); - /** @type {any} */ - let response = {}; - if (name === "PAGE_INIT_DATA") { - response = { - saveLocation: "/Users/someone/Library/Directory", - version: "5.0.0", - build: "55", - }; - } else if (name === "PAGE_LEGACY_IMPORT") { - response = { - active: "true", - autoCloseBrackets: "true", - autoHint: "true", - blacklist: [], - descriptions: "true", - languageCode: "en", - lint: "true", - log: "false", - showCount: "true", - showInvisibles: "true", - sortOrder: "lastModifiedDesc", - tabSize: "4", - }; - } else if (name === "PAGE_ALL_FILES") { - response = []; - files.forEach((file) => { - const content = file.content; - const parsed = parse(content); - const metadata = parsed.metadata; - const canUpdate = !!(metadata.version && metadata.updateURL); - const scriptData = { - canUpdate, - content, - description: metadata.description ? metadata.description[0] : "", - disabled: false, - filename: file.filename, - lastModified: file.lastModified, - metadata, - name: metadata.name[0], - request: file.request, - // type: file.filename.substring(file.filename.lastIndexOf(".") + 1) - type: file.type, - }; - response.push(scriptData); - }); - } else if (name === "TOGGLE_ITEM") { - response = { success: true }; - // response = {error: true}; - } else if (name === "PAGE_UPDATE_SETTINGS") { - response = { success: true }; - } else if (name === "PAGE_UPDATE_BLACKLIST") { - response = { success: true }; - } else if (name === "PAGE_NEW_REMOTE") { - const result = await getRemoteFileContents(message.url); - response = result; - } else if (name === "PAGE_SAVE") { - const newContent = message.content; - const oldFilename = message.item.filename; - const parsed = parse(newContent); - const lastModified = Date.now(); - let canUpdate = false; - // script failed to parse - if (!parsed) { - return { error: "save failed, file has invalid metadata" }; - } - const metaName = parsed.metadata.name[0]; - const newFilename = `${metaName}.${message.item.type}`; - // filename length too long - if (newFilename.length > 255) { - return { error: "save failed, filename too long!" }; - } - - // check if file can be remotely updated - if (parsed.metadata.version && parsed.metadata.updateURL) { - canUpdate = true; - } - - const success = { - canUpdate, - content: newContent, - filename: newFilename, - lastModified, - name, - }; - - // add description if in file metadata - if (parsed.metadata.description) { - // const foo = parsed.metadata; - success.description = parsed.metadata.description[0]; - } - // check if declarative network request - if ( - parsed.metadata["run-at"] && - parsed.metadata["run-at"][0] === "request" - ) { - success.request = true; - } - // overwriting - if (newFilename.toLowerCase() === oldFilename.toLowerCase()) { - saveFile(newContent, lastModified, newFilename, oldFilename); - return success; - } - - // not overwriting, check if filename for that type is taken - if ( - files.find( - (a) => a.filename.toLowerCase() === newFilename.toLowerCase(), - ) - ) { - return { error: "save failed, name already taken!" }; - } - - // not overwriting but all validation passed - saveFile(newContent, lastModified, newFilename, oldFilename); - return success; - } else if (name === "PAGE_UPDATE") { - const url = parse(message.content).metadata.updateURL; - await wait(500); - const result = await getRemoteFileContents(url); - response = result; - // response.error = "Something went wrong!"; - // response.info = "No updates found"; - } else if (name === "TOGGLE_EXTENSION") { - // response = {error: "Failed toggle extension"}; - response = { success: true }; - } else if ( - name === "POPUP_UPDATE_ALL" || - name === "POPUP_UPDATE_SINGLE" - ) { - // response = {error: "Failed refresh scripts"}; - response = { - items: [ - { - name: "Google Images Restored", - filename: "Google Images Restored.js", - disabled: false, - type: "js", - }, - { - name: "Wikipedia Mobile Redirect", - filename: "Wikipedia Mobile Redirect.js", - disabled: true, - type: "js", - }, - { - name: "A Special Userscript", - filename: "A Special Userscript.js", - disabled: false, - type: "js", - }, - { - name: "CSS Adblock", - filename: "CSS Adblock.css", - disabled: false, - type: "css", - }, - { - name: "New Userscript With a Really Really Long Name", - filename: "New Userscript With a Really Really Long Name.css", - disabled: true, - type: "css", - }, - { - name: "Subframe Script Managerial Staffing Company", - filename: "Subframe Script.js", - disabled: false, - subframe: true, - type: "css", - }, - ], - updates: [], - }; - } else if (name === "POPUP_CHECK_UPDATES") { - response = { - updates: [ - { - filename: "Google Images Restored.js", - name: "Google Images Restored", - url: "https://www.k21p.com", - }, - { - filename: "New Userscript With a Really Really Long Name.js", - name: "New Userscript With a Really Really Long Name", - url: "https://www.filmgarb.com", - }, - ], - }; - } else if (name === "POPUP_MATCHES") { - response = { - matches: [ - ...files, - { - name: "Subframe Script Managerial Staffing Company", - filename: "Subframe Script.js", - disabled: false, - subframe: true, - type: "js", - }, - ], - }; - } else if (name === "POPUP_UPDATES") { - response = { - updates: [ - { - filename: "Google Images Restored.js", - name: "Google Images Restored", - url: "https://www.k21p.com", - }, - { - filename: "New Userscript With a Really Really Long Name.js", - name: "New Userscript With a Really Really Long Name", - url: "https://www.filmgarb.com", - }, - ], - }; - response.updates = []; - } else if (name === "REQ_PLATFORM") { - response = { platform: _browser.platform }; - } else if (name === "POPUP_OPEN_EXTENSION_PAGE") { - response = { error: "Failed to get page url" }; - window.open("https://github.com/quoid/userscripts"); - } else if (name === "OPEN_SAVE_LOCATION") { - if (_browser.platform === "macos") { - response = { success: true }; - } else { - response = { - items: [ - { - name: "Google Images Restored", - filename: "Google Images Restored.js", - disabled: false, - type: "js", - metadata: [], - }, - { - name: "Subframe Script Managerial Staffing Company", - filename: "Subframe Script.js", - disabled: false, - type: "css", - metadata: [], - }, - { - name: "Another Script from Managerial Staffing Company", - filename: "Cool Script.js", - disabled: false, - type: "js", - metadata: [], - }, - ], - }; - } - } else if (name === "POPUP_INSTALL_CHECK") { - response = random([ - { success: "Click to install", installed: false }, - { success: "Click to re-install", installed: true }, - ]); - response.metadata = { - description: - 'This userscript re-implements the "View Image" and "Search by image" buttons into google images.', - grant: ["GM.getValue", "GM.setValue", "GM.xmlHttpRequest"], - match: [ - "https://www.example.com/*", - "https://www.example.com/somethingReallylong/goesRightHere", - ], - name: "Test Install Userscript", - require: [ - "https://code.jquery.com/jquery-3.5.1.min.js", - "https://code.jquery.com/jquery-1.7.1.min.js", - ], - source: - "https://greasyforx.org/scripts/00000-something-something-long-name/code/Something%20something%20long20name.user.js", - }; - // response.error = "something went wrong (dev)"; - } - if (!responseCallback) { - return new Promise((resolve) => { - setTimeout(() => resolve(response), _browser.delay); - }); - } - setTimeout(() => responseCallback(response), _browser.delay); - }, - connectNative: () => ({ - onMessage: { - addListener: () => console.info("connectNative - addListener"), - }, - }), - }, - tabs: { - getCurrent(/* responseCallback */) { - const response = random([ - { url: "https://www.filmgarb.com/foo.user.js", id: 101 }, - { - url: `${window.location.origin}/src/ext/shared/dev/DEMO.Alert-URL.user.js`, - id: 102, - }, - // increase probability - { - url: `${window.location.origin}/src/ext/shared/dev/DEMO.Alert-URL.user.js`, - id: 103, - }, - { url: window.location.href, id: 10 }, - ]); - console.info("browser.tabs.getCurrent", response); - return new Promise((resolve) => { - setTimeout(() => resolve(response), _browser.delay); - }); - }, - query(message, responseCallback) { - const response = [ - { url: "https://www.filmgarb.com/foo.user.js", id: 101 }, - ]; - if (!responseCallback) { - return new Promise((resolve) => { - setTimeout(() => resolve(response), _browser.delay); - }); - } - setTimeout(() => responseCallback(response), _browser.delay); - }, - sendMessage(tabId, message, responseCallback) { - let response = {}; - if (message.name === "DEMO_MSG") { - response = {}; - // response.error = "something went wrong (dev)"; - } - if (!responseCallback) { - return new Promise((resolve) => { - setTimeout(() => resolve(response), _browser.delay); - }); - } - setTimeout(() => responseCallback(response), _browser.delay); - }, - }, - webNavigation: { - getAllFrames(message, responseCallback) { - const response = []; - if (!responseCallback) { - return new Promise((resolve) => { - setTimeout(() => resolve(response), _browser.delay); - }); - } - setTimeout(() => responseCallback(response), _browser.delay); - }, - }, - storage: { - local: { - get(items, responseCallback) { - const response = {}; - if (!responseCallback) { - return new Promise((resolve) => { - setTimeout(() => resolve(response), _browser.delay); - }); - } - setTimeout(() => responseCallback(response), _browser.delay); - }, - set() { - return new Promise((resolve) => { - setTimeout(() => resolve(), _browser.delay); - }); - }, - remove: () => - new Promise((resolve) => { - setTimeout(() => resolve(), _browser.delay); - }), - }, - onChanged: { - addListener: () => undefined, - }, - }, - i18n: { - getMessage(n, s = undefined) { - if (!window["i18nMessages"]) return; - return window["i18nMessages"]?.[n]?.message.replace("$1", s); - }, - }, -}; - -async function getRemoteFileContents(url) { - const result = {}; - await fetch(url) - .then((response) => { - if (!response.ok) throw Error(response.statusText); - return response.text(); - }) - .then((text) => { - result.content = text; - }) - .catch((error) => { - console.error(error); - result.error = "Remote url bad response!"; - }); - return result; -} - -function saveFile(content, lastMod, newFilename, oldName) { - const ind = files.findIndex((f) => f.filename === oldName); - const s = { - content, - filename: newFilename, - lastModified: lastMod, - }; - if (ind !== -1) { - // overwrite at index - files[ind] = s; - } else { - // add to beginning of array - files.unshift(s); - } -} - -function random(array) { - return array[Math.floor(Math.random() * array.length)]; -} - -export const browser = _browser; - -export default { - browser: _browser, -}; diff --git a/src/ext/shared/dev/DEMO.Alert-URL.user.js b/src/ext/shared/dev/DEMO.Alert-URL.user.js deleted file mode 100644 index 51ee5902..00000000 --- a/src/ext/shared/dev/DEMO.Alert-URL.user.js +++ /dev/null @@ -1,15 +0,0 @@ -// ==UserScript== -// @name DEMO.Alert-URL -// @description Demo user script alert URL. -// @author Userscripts -// @version 1.0.0 -// @match *://*/* -// @grant none -// @inject-into content -// @run-at document-start -// ==/UserScript== - -(function () { - "use strict"; - alert("DEBUG.Alert-URL:\n\n" + location); -})(); diff --git a/src/ext/shared/native.js b/src/ext/shared/native.js deleted file mode 100644 index 82566825..00000000 --- a/src/ext/shared/native.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @file exchange messages between `web extension` and `native application` - * @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging} - * @see {@link https://developer.apple.com/documentation/safariservices/safari_web_extensions/messaging_between_the_app_and_javascript_in_a_safari_web_extension} - */ - -/** - * @see {@link https://vitejs.dev/guide/env-and-mode.html} - * @returns {string} - */ -const application = () => import.meta.env.NATIVE_APP ?? "application"; - -/** - * @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connectNative} - * @returns {import("webextension-polyfill").Runtime.Port} A `runtime.Port` object - */ -export function connectNative() { - return browser.runtime.connectNative(application()); -} - -/** - * @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendNativeMessage} - * @param {any} message - * @returns {Promise} A response of JSON object or no arguments - */ -export function sendNativeMessage(message) { - return browser.runtime.sendNativeMessage(application(), message); -} diff --git a/src/ext/shared/settings.js b/src/ext/shared/settings.js deleted file mode 100644 index 37d83e1d..00000000 --- a/src/ext/shared/settings.js +++ /dev/null @@ -1,671 +0,0 @@ -/** - * @file wrap a relatively independent settings storage with its own functions - */ - -/** @type {string} */ -const storagePrefix = "US_"; - -/** - * Convert name to storage key - * @param {string} name - * @returns prefixed storage key - */ -const storageKey = (name) => storagePrefix + name.toUpperCase(); - -/** - * @typedef {"sync"|"local"|"managed"|"session"} PossibleAreas - * @typedef {"sync"|"local"} ParamArea - * - * @param {ParamArea} area - storage area - * @returns Dynamic storage reference - */ -const storageRef = async (area) => { - const storages = { - sync: { - area: "sync", - ref: browser.storage.sync, - }, - local: { - area: "local", - ref: browser.storage.local, - }, - }; - // https://developer.apple.com/documentation/safariservices/safari_web_extensions/assessing_your_safari_web_extension_s_browser_compatibility#3584139 - // since storage sync is not implemented in Safari, currently only returns using local storage - if (import.meta.env.BROWSER === "Safari") { - return storages.local; - } - if (area in storages) { - return storages[area]; - } else if (area === undefined) { - const key = storageKey("settings_sync"); - const result = await browser.storage.local.get(key); - return result?.[key] ? storages.sync : storages.local; - } else { - return Promise.reject(new Error(`invalid area ${area}`)); - } -}; - -/** - * @typedef {Object} Platforms platform availability - * @property {any=} macos - overriding defaults - * @property {any=} ipados - overriding defaults - * @property {any=} ios - overriding defaults - * - * @typedef {"INTERNAL"|"general"|"editor"} Group group name - * - * @typedef {Object} Setting The setting item - * @property {string} name - setting's name - * @property {"string"|"number"|"boolean"|"object"|"array"} type - setting's value type - * @property {boolean=} local - local settings will not be synced - * @property {Array=} values - setting's values list - * @property {any} default - setting's default value - * @property {boolean=} disable - disabled settings not be displayed - * @property {boolean=} protect - protected settings cannot be reset - * @property {boolean=} confirm - double confirmation is required when change - * @property {Platforms=} platforms - platform availability and overriding defaults - * @property {Group} group - setting's group name - * @property {string=} legacy - setting's legacy name - * @property {"Toggle"|"select"|"textarea"=} nodeType - setting's node type - * @property {Object=} nodeClass - node class name with setting's value - * - * @typedef {Setting & {key: string}} SettingWithKey The setting item with storage key - */ - -/** @type {Readonly} - Read-only setting template and fallback defaults */ -const settingDefault = deepFreeze({ - name: "setting_default", - type: undefined, - local: false, - values: [], - default: undefined, - disable: false, - protect: false, - confirm: false, - platforms: { macos: undefined, ipados: undefined, ios: undefined }, - group: "INTERNAL", - legacy: "", - nodeType: undefined, - nodeClass: {}, -}); - -/** @type {Readonly} - Read-only settings definition */ -const settingsDefinition = /** @type {const} */ [ - { - name: "error_native", - type: "object", - local: true, - default: { error: undefined }, - group: "INTERNAL", - }, - { - name: "legacy_imported", - type: "number", - local: true, - default: 0, - protect: true, - platforms: { macos: undefined }, - group: "INTERNAL", - }, - { - name: "language_code", - type: "string", - default: "en", - group: "INTERNAL", - legacy: "languageCode", - }, - { - name: "settings_sync", - type: "boolean", - local: true, - default: false, - disable: true, - protect: true, - group: "general", - nodeType: "Toggle", - }, - { - name: "global_active", - type: "boolean", - local: true, - default: true, - group: "general", - legacy: "active", - nodeType: "Toggle", - nodeClass: { warn: false }, - }, - { - name: "augmented_userjs_install", - type: "boolean", - default: true, - group: "general", - nodeType: "Toggle", - }, - { - name: "toolbar_badge_count", - type: "boolean", - default: true, - platforms: { macos: true, ipados: false, ios: false }, - group: "general", - legacy: "showCount", - nodeType: "Toggle", - }, - { - name: "scripts_settings", - type: "object", - default: {}, - disable: true, - group: "INTERNAL", - }, - { - name: "scripts_update_check_interval", - type: "number", - values: [0, 1, 3, 7, 15, 30], - default: 0, - group: "general", - nodeType: "select", - }, - { - name: "scripts_update_check_lasttime", - type: "number", - default: 0, - group: "INTERNAL", - legacy: "lastUpdateCheck", - }, - { - name: "scripts_update_automation", - type: "boolean", - default: false, - disable: true, - confirm: true, - group: "general", - nodeType: "Toggle", - nodeClass: { warn: true }, - }, - { - name: "global_exclude_match", - type: "object", - default: [], - group: "general", - legacy: "blacklist", - nodeType: "textarea", - }, - { - name: "editor_list_sort", - type: "string", - values: ["nameAsc", "nameDesc", "lastModifiedAsc", "lastModifiedDesc"], - default: "lastModifiedDesc", - platforms: { macos: undefined }, - group: "editor", - legacy: "sortOrder", - nodeType: "select", - }, - { - name: "editor_list_descriptions", - type: "boolean", - default: true, - platforms: { macos: undefined }, - group: "editor", - legacy: "descriptions", - nodeType: "Toggle", - }, - { - name: "editor_close_brackets", - type: "boolean", - default: true, - platforms: { macos: undefined }, - group: "editor", - legacy: "autoCloseBrackets", - nodeType: "Toggle", - }, - { - name: "editor_auto_hint", - type: "boolean", - default: true, - platforms: { macos: undefined }, - group: "editor", - legacy: "autoHint", - nodeType: "Toggle", - }, - { - name: "editor_javascript_lint", - type: "boolean", - default: false, - platforms: { macos: undefined }, - group: "editor", - legacy: "lint", - nodeType: "Toggle", - }, - { - name: "editor_show_whitespace", - type: "boolean", - default: true, - platforms: { macos: undefined }, - group: "editor", - legacy: "showInvisibles", - nodeType: "Toggle", - }, - { - name: "editor_tab_size", - type: "number", - values: [1, 2, 3, 4, 5, 6, 8, 10, 12], - default: 4, - platforms: { macos: undefined }, - group: "editor", - legacy: "tabSize", - nodeType: "select", - }, -]; - -/** @type {Readonly<{[key: string]: SettingWithKey}>} - Read-only settings dictionary */ -export const settingsDictionary = deepFreeze( - settingsDefinition.reduce(settingsDefinitionReduceCallbackFn, {}), -); - -/** - * populate the settings-define with setting-default - * and convert settings-define to storage-key object - * @param {{[key: string]: SettingWithKey}} settings settings dictionary - * @param {Setting} setting each setting define - * @returns // {US_GLOBAL_ACTIVE: {key: US_GLOBAL_ACTIVE, name: global_active, ... }, ...} - */ -function settingsDefinitionReduceCallbackFn(settings, setting) { - const key = storageKey(setting.name); - settings[key] = { ...settingDefault, ...setting, key }; - return settings; -} - -/** - * prevent settings define from being modified in any case - * otherwise user settings may be lost in the worst case - * @type {(o: T) => Readonly} - * @param {object} object any object - * @returns {object} deep frozen object - */ -function deepFreeze(object) { - for (const p in object) { - if (typeof object[p] == "object") { - deepFreeze(object[p]); - } - } - return Object.freeze(object); -} - -/** - * compatibility polyfill for Safari < 15.4 - * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#browser_compatibility} - * @todo remove this polyfill when set safari strict_min_version 15.4 - * @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_specific_settings#safari_properties} - */ -if (Object.hasOwn === undefined) { - Object.hasOwn = (obj, prop) => - Object.prototype.hasOwnProperty.call(obj, prop); -} - -// export and define the operation method of settings storage -// they are similar to browser.storage but slightly different - -/** - * settings.get - * @param {string|string[]} keys key | array of keys | undefined for all - * @typedef FnGetOptions - * @property {ParamArea=} area - * @property {keyof Platforms=} platform - * @param {FnGetOptions} options - * @returns settings object - */ -export async function get(keys = undefined, options = {}) { - let { area, platform } = options; - if (![undefined, "local", "sync"].includes(area)) { - return console.error("Unexpected storage area:", area); - } - if (![undefined, "macos", "ios", "ipados"].includes(platform)) { - return console.error("Unexpected platform:", platform); - } - // validate setting value and fix surprises to default - /** @param {string} key @param {any} val */ - const valueFix = (key, val) => { - if (!key || !Object.hasOwn(settingsDictionary, key)) return; - const def = - settingsDictionary[key].platforms[platform] ?? - settingsDictionary[key].default; - // check if value type conforms to settings-dictionary - const type = settingsDictionary[key].type; - if (typeof val != type) { - console.warn( - `Unexpected ${key} value type '${typeof val}' should '${type}', fix to default`, - ); - return def; - } - // check if value conforms to settings-dictionary - const values = settingsDictionary[key].values; - if (values.length && !values.includes(val)) { - console.warn( - `Unexpected ${key} value '${val}' should one of '${values}', fix to default`, - ); - return def; - } - // verified, pass original value - return val; - }; - // [single setting] - if (typeof keys == "string") { - const key = storageKey(keys); - // check if key exist in settings-dictionary - if (!Object.hasOwn(settingsDictionary, key)) { - return console.error("unexpected settings key:", key); - } - // check if only locally stored setting - settingsDictionary[key].local === true && (area = "local"); - const storage = await storageRef(area); - const result = await storage.ref.get(key); - if (Object.hasOwn(result, key)) return valueFix(key, result[key]); - return ( - settingsDictionary[key].platforms[platform] ?? - settingsDictionary[key].default - ); - } - const complexGet = async (settingsDefault, areaKeys) => { - const storage = await storageRef(area); - let local = {}, - sync = {}; - if (storage.area === "sync") { - if (areaKeys.sync.length) { - sync = await storage.ref.get(areaKeys.sync); - } - if (areaKeys.local.length) { - local = await browser.storage.local.get(areaKeys.local); - } - } else { - local = await storage.ref.get(areaKeys.all); - } - const result = Object.assign(settingsDefault, local, sync); - // revert settings object property name - return Object.entries(result).reduce((p, c) => { - p[settingsDictionary[c[0]].name] = valueFix(...c); - return p; - }, {}); - }; - // [muilt settings] - if (Array.isArray(keys)) { - if (!keys.length) { - return console.error("Settings keys empty:", keys); - } - const settingsDefault = {}; - const areaKeys = { local: [], sync: [], all: [] }; - for (const k of keys) { - const key = storageKey(k); - // check if key exist in settings-dictionary - if (!Object.hasOwn(settingsDictionary, key)) { - return console.error("unexpected settings key:", key); - } - settingsDefault[key] = - settingsDictionary[key].platforms[platform] ?? - settingsDictionary[key].default; - // detach only locally stored settings - settingsDictionary[key].local === true - ? areaKeys.local.push(key) - : areaKeys.sync.push(key); - // record all keys in case sync storage is not enabled - areaKeys.all.push(key); - } - return complexGet(settingsDefault, areaKeys); - } - // [all settings] - if (typeof keys == "undefined" || keys === null) { - const settingsDefault = {}; - const areaKeys = { local: [], sync: [], all: [] }; - for (const key of Object.keys(settingsDictionary)) { - settingsDefault[key] = - settingsDictionary[key].platforms[platform] ?? - settingsDictionary[key].default; - // detach only locally stored settings - settingsDictionary[key].local === true - ? areaKeys.local.push(key) - : areaKeys.sync.push(key); - // record all keys in case sync storage is not enabled - areaKeys.all.push(key); - } - return complexGet(settingsDefault, areaKeys); - } - return console.error("Unexpected keys type:", keys); -} - -/** - * settings.set - * @param {object} keys settings object - * @typedef FnSetOptions - * @property {ParamArea=} area - * @param {FnSetOptions} options - */ -export async function set(keys, options = {}) { - const { area } = options; - if (![undefined, "local", "sync"].includes(area)) { - return console.error("unexpected storage area:", area); - } - if (typeof keys != "object") { - return console.error("Unexpected keys type:", keys); - } - if (!Object.keys(keys).length) { - return console.error("Settings object empty:", keys); - } - const areaKeys = { local: {}, sync: {}, all: {} }; - for (const k of Object.keys(keys)) { - const key = storageKey(k); - // check if key exist in settings-dictionary - if (!Object.hasOwn(settingsDictionary, key)) { - return console.error("Unexpected settings keys:", key); - } - // check if value type conforms to settings-dictionary - const type = settingsDictionary[key].type; - if (typeof keys[k] != type) { - if (type === "number" && !Number.isNaN(Number(keys[k]))) { - // compatible with string numbers - keys[k] = Number(keys[k]); // still store it as a number type - } else { - return console.error( - `Unexpected ${k} value type '${typeof keys[k]}' should '${type}'`, - ); - } - } - // check if value conforms to settings-dictionary - const values = settingsDictionary[key].values; - if (values.length && !values.includes(keys[k])) { - return console.error( - `Unexpected ${k} value '${keys[k]}' should one of '${values}'`, - ); - } - // detach only locally stored settings - settingsDictionary[key].local === true - ? (areaKeys.local[key] = keys[k]) - : (areaKeys.sync[key] = keys[k]); - // record all keys in case sync storage is not enabled - areaKeys.all[key] = keys[k]; - } - const storage = await storageRef(area); - // complexSet - try { - if (storage.area === "sync") { - if (Object.keys(areaKeys.sync).length) { - await storage.ref.set(areaKeys.sync); - } - if (Object.keys(areaKeys.local).length) { - await browser.storage.local.set(areaKeys.local); - } - } else { - await storage.ref.set(areaKeys.all); - } - return true; - } catch (error) { - return console.error(error); - } -} - -/** - * settings.reset - * reset to default - * @param {string|string[]} keys key | array of keys | undefined for all - * @typedef FnResetOptions - * @property {ParamArea=} area - * @param {FnResetOptions} options - */ -export async function reset(keys = undefined, options = {}) { - let { area } = options; - if (![undefined, "local", "sync"].includes(area)) { - return console.error("unexpected storage area:", area); - } - // [single setting] - if (typeof keys == "string") { - const key = storageKey(keys); - // check if key exist in settings-dictionary - if (!Object.hasOwn(settingsDictionary, key)) { - return console.error("unexpected settings key:", key, keys); - } - // check if key is protected - if (settingsDictionary[key].protect === true) { - return console.error("protected settings key:", key, keys); - } - settingsDictionary[key].local === true && (area = "local"); - const storage = await storageRef(area); - return storage.ref.remove(key); - } - const complexRemove = async (areaKeys) => { - const storage = await storageRef(area); - try { - if (storage.area === "sync") { - if (areaKeys.sync.length) { - await storage.ref.remove(areaKeys.sync); - } - if (areaKeys.local.length) { - await browser.storage.local.remove(areaKeys.local); - } - } else { - await storage.ref.remove(areaKeys.all); - } - return true; - } catch (error) { - return console.error(error); - } - }; - // [muilt settings] - if (Array.isArray(keys)) { - if (!keys.length) { - return console.error("Settings keys empty:", keys); - } - const areaKeys = { local: [], sync: [], all: [] }; - for (const k of keys) { - const key = storageKey(k); - // check if key exist in settings-dictionary - if (!Object.hasOwn(settingsDictionary, key)) { - return console.error("unexpected settings key:", key, k); - } - // check if key is protected - if (settingsDictionary[key].protect === true) { - return console.error("protected settings key:", key, k); - } - // detach only locally stored settings - settingsDictionary[key].local === true - ? areaKeys.local.push(key) - : areaKeys.sync.push(key); - // record all keys in case sync storage is not enabled - areaKeys.all.push(key); - } - return complexRemove(areaKeys); - } - // [all settings] - if (typeof keys == "undefined" || keys === null) { - const areaKeys = { local: [], sync: [], all: [] }; - for (const key in settingsDictionary) { - // skip protected keys - if (settingsDictionary[key].protect === true) continue; - // detach only locally stored settings - settingsDictionary[key].local === true - ? areaKeys.local.push(key) - : areaKeys.sync.push(key); - // record all keys in case sync storage is not enabled - areaKeys.all.push(key); - // clean up the legacy keys at the same time - const legacyKey = settingsDictionary[key].legacy; - legacyKey && areaKeys.all.push(legacyKey); - } - return complexRemove(areaKeys); - } - return console.error("Unexpected keys type:", keys); -} - -/** - * complex onChanged - * this function is convenient for the svelte store to update the state - * @callback onChangedSettingsCallback - * @param {{[key: string]: any}} settings - changed settings - * @param {PossibleAreas} area - storage area - * @returns {void} - * @param {onChangedSettingsCallback} callback - */ -export function onChangedSettings(callback) { - if (typeof callback != "function") { - return console.error("Unexpected callback:", callback); - } - console.info("storage onChanged addListener"); - /** - * @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/onChanged#listener} - * @param {object} changes - * @param {PossibleAreas} area - */ - const listener = (changes, area) => { - // console.log(`storage.${area}.onChanged`, changes); // DEBUG - const settings = {}; - for (const key in changes) { - if (!Object.hasOwn(settingsDictionary, key)) continue; - settings[settingsDictionary[key].name] = changes[key].newValue; - } - try { - callback(settings, area); - } catch (error) { - console.error("onChanged callback:", error); - } - }; - browser.storage.onChanged.addListener(listener); -} - -// the following functions are used only for compatibility transition periods -// these functions will be removed in the future, perhaps in version 5.0 - -export async function legacyImport() { - // if legacy data has already been imported, skip this process - const imported = await get("legacy_imported"); - if (imported) return console.info("Legacy settings has already imported"); - // start the one-time import process - const result = await browser.runtime.sendNativeMessage("app", { - name: "PAGE_LEGACY_IMPORT", - }); - if (!result) return console.error("PAGE_LEGACY_IMPORT not response"); - if (result.error) return console.error(result.error); - console.info("Import settings data from legacy manifest file"); - const settings = {}; - for (const key of Object.keys(settingsDictionary)) { - const legacy = settingsDictionary[key].legacy; - if (legacy in result) { - let value = result[legacy]; - switch (settingsDictionary[key].type) { - case "boolean": - value = JSON.parse(value); - break; - case "number": - value = Number(value); - break; - } - console.info(`Importing legacy setting: ${legacy}`, value); - settings[settingsDictionary[key].name] = value; - } - } - // import complete tag, to ensure will only be import once - Object.assign(settings, { legacy_imported: Date.now() }); - if (await set(settings, { area: "local" })) { - console.info("Import legacy settings complete"); - // send a message to the Swift layer to safely clean up legacy data - // browser.runtime.sendNativeMessage({name: "PAGE_LEGACY_IMPORTED"}); - return true; - } - return console.error("Import legacy settings abort"); -} diff --git a/src/ext/shared/utils.js b/src/ext/shared/utils.js deleted file mode 100644 index 63875afd..00000000 --- a/src/ext/shared/utils.js +++ /dev/null @@ -1,515 +0,0 @@ -/** - * @param {number} ms millisecond timestamp - * @returns {string} - */ -export function formatDate(ms) { - const d = new Date(ms); - const yr = new Intl.DateTimeFormat("en", { year: "numeric" }).format(d); - const mo = new Intl.DateTimeFormat("en", { month: "short" }).format(d); - const dd = new Intl.DateTimeFormat("en", { day: "2-digit" }).format(d); - const hr = d.getHours(); - const mn = d.getMinutes(); - return `${mo} ${dd}, ${yr} at ${hr}:${mn}`; -} - -export function uniqueId() { - return Math.random().toString(36).substring(2, 10); -} - -/** - * awaitable function for waiting an arbitrary amount of time - * @param {number} ms the amount of time to wait in milliseconds - * @returns {Promise} - */ -export function wait(ms) { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); -} - -// TODO: describe the items array that should get passed to this function -/** - * @param {Array} array - * @param {("lastModifiedAsc"|"lastModifiedDesc"|"nameAsc"|"nameDesc")} order - * @returns - */ -export function sortBy(array, order) { - if (order === "nameAsc") { - array.sort((a, b) => a.name.localeCompare(b.name)); - } else if (order === "nameDesc") { - array.sort((a, b) => b.name.localeCompare(a.name)); - } else if (order === "lastModifiedAsc") { - array.sort((a, b) => (a.lastModified < b.lastModified ? -1 : 1)); - } else if (order === "lastModifiedDesc") { - array.sort((a, b) => (a.lastModified > b.lastModified ? -1 : 1)); - } - // always keep temp file pinned to the top, should only ever have one temp script - // if (array.find(f => f.temp)) array.sort((a, b) => a.temp ? -1 : b.temp ? 1 : 0); - return array; -} - -/** - * - * @param {string} description - * @param {string} name - * @param {("css"|"js")} type - * @returns {string} - */ -export function newScriptDefault(description, name, type) { - if (type === "css") { - return `/* ==UserStyle==\n@name ${name}\n@description ${description}\n@match \n==/UserStyle== */`; - } - return `// ==UserScript==\n// @name ${name}\n// @description ${description}\n// @match *://*/*\n// ==/UserScript==`; -} - -/** - * @param {string} str - * @returns {?{code: string, content: str, metablock: string, metadata: object}} - */ -export function parse(str) { - if (typeof str != "string") return null; - const blocksReg = - /(?:(\/\/ ==UserScript==[ \t]*?\r?\n([\S\s]*?)\r?\n\/\/ ==\/UserScript==)([\S\s]*)|(\/\* ==UserStyle==[ \t]*?\r?\n([\S\s]*?)\r?\n==\/UserStyle== \*\/)([\S\s]*))/; - const blocks = str.match(blocksReg); - - if (!blocks) return null; - - const metablock = blocks[1] != null ? blocks[1] : blocks[4]; - const metas = blocks[2] != null ? blocks[2] : blocks[5]; - const code = blocks[3] != null ? blocks[3].trim() : blocks[6].trim(); - - const metadata = {}; - const metaArray = metas.split("\n"); - metaArray.forEach((m) => { - const parts = m - .trim() - .match(/^(?:[ \t]*(?:\/\/)?[ \t]*@)([\w-]+)[ \t]+([^\s]+[^\r\n\t\v\f]*)/); - const parts2 = m - .trim() - .match(/^(?:[ \t]*(?:\/\/)?[ \t]*@)(noframes)[ \t]*$/); - if (parts) { - metadata[parts[1]] = metadata[parts[1]] || []; - metadata[parts[1]].push(parts[2]); - } else if (parts2) { - metadata[parts2[1]] = metadata[parts2[1]] || []; - metadata[parts2[1]].push(true); - } - }); - // fail if @name is missing or name is empty - if (!metadata.name || metadata.name[0].length < 2) return; - - return { - code, - content: str, - metablock, - metadata, - }; -} - -/** - * @param {string} text editor code - * @returns {{match: boolean, meta: boolean} | {key: string, value: string, text: string}[]} - */ -export function parseMetadata(text) { - const groupsRe = - /(\/\/ ==UserScript==[ \t]*?\r?\n([\S\s]*?)\r?\n\/\/ ==\/UserScript==)([\S\s]*)/; - const groups = text.match(groupsRe); - // userscript code doesn't match the regex expression - // could be missing opening/closing tags, malformed - // or missing metadata between opening/closing tags (group 2 in regex exp) - if (!groups) { - return { match: false, meta: false }; - } - - // userscript code matches but content between opening/closing tag missing - // ex. opening/closing tags present, but newline characters between the tags - const metas = groups[2]; - if (!metas) return { match: true, meta: false }; - - const metadata = []; - const metaArray = metas.split("\n"); - - for (let i = 0; i < metaArray.length; i++) { - const metaRegex = - /^(?:[ \t]*(?:\/\/)?[ \t]*@)([\w-]+)[ \t]*([^\s]+[^\r\n\t\v\f]*)?/; - const meta = metaArray[i]; - const parts = meta.match(metaRegex); - if (parts) - metadata.push({ key: parts[1], value: parts[2], text: parts[0] }); - } - - // if there is content between the opening/closing tags, match will be found - // this additionally checks that there's at least one properly formed key - // if not keys found, assume metadata is missing - // checking that required keys are present will happen elsewhere - if (!Object.keys(metadata).length) return { match: true, meta: false }; - - return metadata; -} - -/** - * @param {string} input a match pattern - * @typedef {string} value - the match pattern - * @typedef {Object} MatchGroups - regexp match groups - * @property {string} start - leading whitespace - * @property {string} separ - separator whitespace - * @property {value} value - the match pattern - * @typedef {MatchGroups & CheckedItem} ParsedItem - parsed result - * @returns {{warn: boolean, error: boolean, items: ParsedItem[], values: value[]}} - */ -export function parseMatchPatterns(input) { - const result = { - warn: false, // global warn - error: false, // global error - items: [], - values: [], - }; - if (typeof input !== "string") return result; - // match the separated values from input string - const matches = input.matchAll( - /(?^\s*|)(?\S+?)(?\s+|$)/g, - ); - for (const match of matches) { - const item = checkMatchPatterns(match.groups.value); - // setting the global error indicator - if (item.warn === true) result.warn = true; - if (item.error === true) result.error = true; - result.items.push({ ...match.groups, ...item }); - result.values.push(match.groups.value.toLowerCase()); - } - return result; -} - -/** - * @param {string} input whitespace separated list of match patterns - * @typedef {Object} CheckedItem - checked result - * @property {boolean} warn - the match pattern has warning - * @property {boolean} error - the match pattern valid or not - * @property {string} point - invalid point or error message - * @returns {CheckedItem} - */ -export function checkMatchPatterns(input) { - if (typeof input !== "string") return; - const result = { - warn: false, - error: true, - point: "", - }; - if (["", "*://*/*"].includes(input)) { - result.warn = true; - result.error = false; - result.point = gl("utils_check_match_patterns_0"); - return result; - } - let scheme, host, path; - /** check scheme component */ - if (input.slice(0, 5).toLowerCase() === "https") { - scheme = input.slice(0, 5); - } else if (input.slice(0, 4).toLowerCase() === "http") { - scheme = input.slice(0, 4); - } else if (input.startsWith("*")) { - scheme = "*"; - } else { - // The scheme component should one of *, https, http - result.point = gl("utils_check_match_patterns_1"); - return result; - } - /** check :// separator */ - if (input.slice(scheme.length, scheme.length + 3) !== "://") { - // The scheme and host should separated by `://` - result.point = gl("utils_check_match_patterns_2"); - return result; - } - // separate host and path - const array = input.slice(scheme.length + 3).split("/"); - if (array.length < 2) { - // The match pattern has no path component - result.point = gl("utils_check_match_patterns_3"); - return result; - } - host = array[0]; - path = "/" + array.slice(1).join("/"); - /** check host component */ - if (host === "*.") { - // The `*.` should followed by part of the hostname - result.point = gl("utils_check_match_patterns_4"); - return result; - } - // allow fully qualified domain name (FQDN) - if (host.at(-1) === ".") host = host.slice(0, -1); - if (host.length < 1 || 255 - 1 < host.length) { - // The host component length should be 1-255 - result.point = gl("utils_check_match_patterns_5"); - return result; - } - let labels = []; // domain labels - let hostPart = ""; // rest part that exclude wildcard - if (host.startsWith("*.")) { - hostPart = host.slice(2); - labels = hostPart.split("."); - } else if (host !== "*") { - hostPart = host; - labels = host.split("."); - } - if (hostPart.includes("*")) { - // The `*` in host component should be independent or `*.` at the start - result.point = gl("utils_check_match_patterns_6"); - return result; - } - for (const label of labels) { - if (label.length === 0) { - // The host component contains empty label(s) - result.point = gl("utils_check_match_patterns_7"); - return result; - } - if (label.startsWith("-") || label.endsWith("-")) { - // The label cannot start or end with `-` character - result.point = gl("utils_check_match_patterns_8"); - return result; - } - if (label.length > 63) { - // The maximum length of the label cannot exceed 63 - result.point = gl("utils_check_match_patterns_9"); - return result; - } - } - // allowed character set of host component - const hostInvalidMatches = hostPart.match(/[^A-Za-z0-9.-]/g); - if (hostInvalidMatches) { - const characters = hostInvalidMatches.join(""); - // The host component contains invalid character(s): ${c} - result.point = gl("utils_check_match_patterns_10", characters); - return result; - } - /** check path component */ - // allowed character set of path component - const pathInvalidMatches = path.match( - /[^\w\]\\!$%&'()*+,./:;=?@[^`{|}~-]/g, // toolsGetValidPathCharacters - ); - if (pathInvalidMatches) { - const characters = pathInvalidMatches.join(""); - // The path component contains invalid character(s): ${c} - result.point = gl("utils_check_match_patterns_11", characters); - return result; - } - result.error = false; - return result; -} - -/** Generate valid path characters in browser js runtime */ -export function toolsGetValidPathCharacters() { - const set = new Set(); - for (let i = 32; i < 128; i++) set.add(String.fromCharCode(i)); - set.delete("?"); - set.delete("#"); - const p = [...set].join(""); - set.delete("="); - set.delete("&"); - const s = [...set].join(""); - const url = new URL(`https://host/${p}?1=${s}&${s}=2`); - const possibles = [...url.pathname, ...url.search]; - const characters = [...new Set(possibles)].sort().join(""); - const symbols = characters.match(/[^\w]/g).join(""); - return { - characters, - symbols, - restr: `/\\w${symbols.replace(/[\^[\]-]/g, "\\$&")}]/`, - }; -} - -/** - * get lang - * @param {string} n messageName - * @param {string | string[]} s substitutions - * const gl = browser.i18n.getMessage; // issue: safari return `undefined` - */ -export const gl = (n, s = undefined) => browser.i18n.getMessage(n, s); - -export const validGrants = new Set([ - "GM.info", - "GM_info", - "GM.addStyle", - "GM.openInTab", - "GM.closeTab", - "GM.setValue", - "GM.getValue", - "GM.deleteValue", - "GM.listValues", - "GM.setClipboard", - "GM.getTab", - "GM.saveTab", - "GM_xmlhttpRequest", - "GM.xmlHttpRequest", - "none", -]); - -export const validMetaKeys = new Set([ - "author", - "description", - "downloadURL", - "exclude", - "exclude-match", - "grant", - "icon", - "include", - "inject-into", - "match", - "name", - "noframes", - "require", - "run-at", - "updateURL", - "version", - "weight", -]); - -export const extensionPaths = { - popup: "/dist/entry-ext-action-popup.html", - page: "/dist/entry-ext-extension-page.html", -}; - -export async function openExtensionPage() { - const url = browser.runtime.getURL(extensionPaths.page); - const tabs = await browser.tabs.query({ url }); - const tab = tabs.find((e) => e.url.startsWith(url)); - if (!tab) return browser.tabs.create({ url }); - await browser.tabs.update(tab.id, { active: true }); - if (!browser.windows.update) return; - await browser.windows.update(tab.windowId, { focused: true }); -} - -/** - * Safari currently does not honor the target attribute of elements in extension contexts - * @param {string} url - */ -export async function openInBlank(url) { - browser.tabs.create({ url }); -} - -/** - * Safari macos currently does not honor the download attribute of elements in extension contexts - * Also not support https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/download - * @param {string} filename - * @param {string} content - * @param {string} type - */ -export async function downloadToFile(filename, content, type = "text/plain") { - let a; - // created only once in the current page so that it can be used repeatedly - if (!window["_download_helper"]) { - if (import.meta.env.SAFARI_PLATFORM === "mac") { - // bypassing safari issues through iframe - const iframe = document.createElement("iframe"); - iframe.style.display = "none"; - document.body.append(iframe); - a = iframe.contentDocument.createElement("a"); - } else { - a = document.createElement("a"); - } - window["_download_helper"] = a; - } else { - a = window["_download_helper"]; - } - const blob = URL.createObjectURL(new Blob([content], { type })); - setTimeout(() => URL.revokeObjectURL(blob), 30000); - a.download = filename; - a.href = blob; - a.click(); -} - -// Safari macos currently does not honor the download attribute of elements in extension contexts -// Also not support https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/download -// eslint-disable-next-line no-unused-vars -- the old implementation is left for reference -async function downloadToFile_old(filename, content, type = "text/plain") { - // there must be an accessible url, otherwise the script cannot be successfully injected - const url = "https://quoid.github.io/userscripts/serve/download.html"; - const tab = await browser.tabs.create({ url }); - const exchange = { filename, content, type }; - const exscript = (o) => { - // make sure executed only once - // @ts-ignore - if (window.US_DOWNLOAD === 1) return; - // @ts-ignore - window.US_DOWNLOAD = 1; - window.stop(); - document.body.textContent = "Download is starting..."; - const a = document.createElement("a"); - a.download = o.filename; - a.href = URL.createObjectURL(new Blob([o.content], { type: o.type })); - a.click(); - document.body.innerHTML += "
    The download should have started.
    "; - a.textContent = o.filename; - document.body.append(a); - }; - // Safari currently unable to stably executeScript on tab loading status - try { - await browser.tabs.executeScript(tab.id, { - code: `(${exscript})(${JSON.stringify(exchange)});`, - }); - } catch { - const handleUpdated = async (tabId) => { - if (tabId !== tab.id) return; - try { - await browser.tabs.executeScript(tabId, { - code: `(${exscript})(${JSON.stringify(exchange)});`, - }); - console.info(`[${filename}] Download is starting...`); - } catch { - console.info(`[${filename}] Start download failed, retrying...`); - } - }; - browser.tabs.onUpdated.addListener(handleUpdated); - // Remove the listener when tab closing - const handleRemoved = (tabId) => { - if (tabId !== tab.id) return; - browser.tabs.onUpdated.removeListener(handleUpdated); - browser.tabs.onRemoved.removeListener(handleRemoved); - }; - browser.tabs.onRemoved.addListener(handleRemoved); - } -} - -/** - * Dynamic registration of content scripts [Safari >= 16.4] - * @param {boolean} enable - whether to register content scripts - */ -export async function contentScriptRegistration(enable) { - if (import.meta.env.SAFARI_VERSION < 16.4) return; - /** - * @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/RegisteredContentScript} - * @type {Parameters[0]} - */ - const scripts = [ - { - id: "dot-user-js", - js: ["dist/content-scripts/dot-user-js.js"], - matches: ["*://*/*.user.js", "*://*/*.user.js?*"], - runAt: "document_start", - }, - { - id: "script-market", - js: ["dist/content-scripts/script-market.js"], - matches: ["*://*.greasyfork.org/*"], - excludeMatches: ["*://*/*.user.js", "*://*/*.user.js?*"], - runAt: "document_end", - }, - ]; - const regScripts = await browser.scripting.getRegisteredContentScripts(); - const ids = regScripts.map((script) => script.id); - for (const script of scripts) { - if (enable && !ids.includes(script.id)) { - await browser.scripting.registerContentScripts([script]); - if (import.meta.env.MODE === "development") { - console.debug("registerContentScripts", script.id); - } - } - if (!enable && ids.includes(script.id)) { - await browser.scripting.unregisterContentScripts({ - ids: [script.id], - }); - if (import.meta.env.MODE === "development") { - console.debug("unregisterContentScripts", script.id); - } - } - } -} diff --git a/src/ext/types.d.ts b/src/ext/types.d.ts deleted file mode 100644 index 1ad82689..00000000 --- a/src/ext/types.d.ts +++ /dev/null @@ -1,102 +0,0 @@ -declare namespace TypeExtMessages { - interface XHRProcessedFile { - data: Array; - lastModified: number; - name: string; - mime: string; - } - - type XHRProcessedFormData = [string, string | XHRProcessedFile][]; - - type XHRProcessedData = - | { - data: string; - type: "Text" | "URLSearchParams"; - } - | { - data: string; - mime: string; - type: "Document"; - } - | { - data: Array; - type: "ArrayBuffer" | "ArrayBufferView"; - } - | { - data: Array; - mime: string; - type: "Blob"; - } - | { - data: XHRProcessedFormData; - type: "FormData"; - }; - - type XHRHandlers = [ - "onreadystatechange", - "onloadstart", - "onprogress", - "onabort", - "onerror", - "onload", - "ontimeout", - "onloadend", - ]; - - type XHRUploadHandlers = [ - "onabort", - "onerror", - "onload", - "onloadend", - "onloadstart", - "onprogress", - "ontimeout", - ]; - - type XHRHandlersObj = { - [handler in XHRHandlers[number]]?: (response: XHRResponse) => void; - }; - - type XHRUploadHandlersObj = { - [handler in XHRUploadHandlers[number]]?: (response: XHRProgress) => void; - }; - - interface XHRTransportableDetails { - binary: boolean; - data: XHRProcessedData; - headers: { [x: Lowercase]: string }; - method: string; - overrideMimeType: string; - password: string; - responseType: XMLHttpRequestResponseType; - timeout: number; - url: string; - user: string; - hasHandlers: { [handler in XHRHandlers[number]]?: boolean }; - hasUploadHandlers: { [handler in XHRUploadHandlers[number]]?: boolean }; - } - - interface XHRTransportableResponse { - contentType: string; // non-standard - readyState: number; - response: string | number[]; - responseHeaders: string; - responseType: XMLHttpRequestResponseType; - responseURL: string; - status: number; - statusText: string; - timeout: number; - } - - interface XHRResponse extends Omit { - response: any; - responseText?: string; - responseXML?: Document; - } - - interface XHRProgress { - lengthComputable: boolean; - loaded: number; - total: number; - } -} diff --git a/src/shared/Components/Dropdown.svelte b/src/shared/Components/Dropdown.svelte deleted file mode 100644 index f9142c3f..00000000 --- a/src/shared/Components/Dropdown.svelte +++ /dev/null @@ -1,127 +0,0 @@ - - -
    - -
      - -
    • At least one slot is required...
    • -
      -
    -
    - - diff --git a/src/shared/Components/IconButton.svelte b/src/shared/Components/IconButton.svelte deleted file mode 100644 index 52ec42cc..00000000 --- a/src/shared/Components/IconButton.svelte +++ /dev/null @@ -1,78 +0,0 @@ - - - - - diff --git a/src/shared/Components/Loader.svelte b/src/shared/Components/Loader.svelte deleted file mode 100644 index f891a160..00000000 --- a/src/shared/Components/Loader.svelte +++ /dev/null @@ -1,61 +0,0 @@ - - -
    - - {@html iconLoader} - {#if abort} -
    - Fetching resources, -
    - {/if} -
    - - diff --git a/src/shared/Components/LogoIcon.svelte b/src/shared/Components/LogoIcon.svelte deleted file mode 100644 index 7b5f74df..00000000 --- a/src/shared/Components/LogoIcon.svelte +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - diff --git a/src/shared/Components/LogoText.svelte b/src/shared/Components/LogoText.svelte deleted file mode 100644 index e5ad9068..00000000 --- a/src/shared/Components/LogoText.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - diff --git a/src/shared/Components/Tag.svelte b/src/shared/Components/Tag.svelte deleted file mode 100644 index 80e00954..00000000 --- a/src/shared/Components/Tag.svelte +++ /dev/null @@ -1,55 +0,0 @@ - - -
    - - diff --git a/src/shared/Components/Toggle.svelte b/src/shared/Components/Toggle.svelte deleted file mode 100644 index 9b1d338f..00000000 --- a/src/shared/Components/Toggle.svelte +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - diff --git a/src/shared/colors.js b/src/shared/colors.js deleted file mode 100644 index 73d9001f..00000000 --- a/src/shared/colors.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Theme colors for console log css - * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/console#styling_console_output} - */ -export const colors = { - inherit: "color: inherit;", - blue: "color: light-dark( #317eff, #006fff);", - green: "color: light-dark( #2bb239, #60f36c);", - yellow: "color: light-dark( #b8722c, #fff600);", -}; diff --git a/src/shared/img/icon-arrow-down.svg b/src/shared/img/icon-arrow-down.svg deleted file mode 100644 index ef9081c3..00000000 --- a/src/shared/img/icon-arrow-down.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/shared/img/icon-arrow-left.svg b/src/shared/img/icon-arrow-left.svg deleted file mode 100644 index 81fbb428..00000000 --- a/src/shared/img/icon-arrow-left.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-arrow-up.svg b/src/shared/img/icon-arrow-up.svg deleted file mode 100644 index 2e9dda6a..00000000 --- a/src/shared/img/icon-arrow-up.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/shared/img/icon-bug.svg b/src/shared/img/icon-bug.svg deleted file mode 100644 index 400d41b4..00000000 --- a/src/shared/img/icon-bug.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/shared/img/icon-check.svg b/src/shared/img/icon-check.svg deleted file mode 100644 index 0f3df840..00000000 --- a/src/shared/img/icon-check.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-clear.svg b/src/shared/img/icon-clear.svg deleted file mode 100644 index 9cf334ca..00000000 --- a/src/shared/img/icon-clear.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-close.svg b/src/shared/img/icon-close.svg deleted file mode 100644 index 444d4aab..00000000 --- a/src/shared/img/icon-close.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-download.svg b/src/shared/img/icon-download.svg deleted file mode 100644 index 04a501f3..00000000 --- a/src/shared/img/icon-download.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-edit.svg b/src/shared/img/icon-edit.svg deleted file mode 100644 index 27cfb98c..00000000 --- a/src/shared/img/icon-edit.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-error.svg b/src/shared/img/icon-error.svg deleted file mode 100644 index 9ef0d10a..00000000 --- a/src/shared/img/icon-error.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-info.svg b/src/shared/img/icon-info.svg deleted file mode 100644 index 3595d077..00000000 --- a/src/shared/img/icon-info.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-loader.svg b/src/shared/img/icon-loader.svg deleted file mode 100644 index 64cc3f45..00000000 --- a/src/shared/img/icon-loader.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - diff --git a/src/shared/img/icon-loupe.svg b/src/shared/img/icon-loupe.svg deleted file mode 100644 index 8a9cb16e..00000000 --- a/src/shared/img/icon-loupe.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-open.svg b/src/shared/img/icon-open.svg deleted file mode 100644 index 5174d28d..00000000 --- a/src/shared/img/icon-open.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-plus.svg b/src/shared/img/icon-plus.svg deleted file mode 100644 index b6bec22c..00000000 --- a/src/shared/img/icon-plus.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-power.svg b/src/shared/img/icon-power.svg deleted file mode 100644 index be9e62ad..00000000 --- a/src/shared/img/icon-power.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-refresh.svg b/src/shared/img/icon-refresh.svg deleted file mode 100644 index 0f435d20..00000000 --- a/src/shared/img/icon-refresh.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-settings.svg b/src/shared/img/icon-settings.svg deleted file mode 100644 index e44ef4d7..00000000 --- a/src/shared/img/icon-settings.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-sidebar.svg b/src/shared/img/icon-sidebar.svg deleted file mode 100644 index 8fe91fb9..00000000 --- a/src/shared/img/icon-sidebar.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/shared/img/icon-sort.svg b/src/shared/img/icon-sort.svg deleted file mode 100644 index 958db7e7..00000000 --- a/src/shared/img/icon-sort.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-sync.svg b/src/shared/img/icon-sync.svg deleted file mode 100644 index 5802ea9c..00000000 --- a/src/shared/img/icon-sync.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-trash.svg b/src/shared/img/icon-trash.svg deleted file mode 100644 index 1e46ac80..00000000 --- a/src/shared/img/icon-trash.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-update.svg b/src/shared/img/icon-update.svg deleted file mode 100644 index f15886fe..00000000 --- a/src/shared/img/icon-update.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/img/icon-warn.svg b/src/shared/img/icon-warn.svg deleted file mode 100644 index 713d4ae8..00000000 --- a/src/shared/img/icon-warn.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/shared/jsconfig.json b/src/shared/jsconfig.json deleted file mode 100644 index eb649856..00000000 --- a/src/shared/jsconfig.json +++ /dev/null @@ -1,30 +0,0 @@ -// https://code.visualstudio.com/docs/languages/jsconfig -// https://www.typescriptlang.org/docs/handbook/tsconfig-json.html -// https://www.typescriptlang.org/tsconfig - -// https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html -// https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html - -{ - "compilerOptions": { - "target": "ESNext", - "module": "ESNext", - "moduleResolution": "bundler", - - "verbatimModuleSyntax": true, - "isolatedModules": true, - "resolveJsonModule": true, - - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "skipLibCheck": true, - "sourceMap": true, - - "paths": { - "@shared/*": ["./*"] - } - }, - "include": ["**/*.d.ts", "**/*.js", "**/*.svelte"] -} diff --git a/src/shared/reset.css b/src/shared/reset.css deleted file mode 100644 index c3329b07..00000000 --- a/src/shared/reset.css +++ /dev/null @@ -1,53 +0,0 @@ -*, -*::before, -*::after { - box-sizing: border-box; -} - -body, -p { - margin: 0; -} - -ul { - list-style: none; - margin: 0; - padding: 0; -} - -button, -input, -select, -textarea { - font-family: inherit; - font-size: 100%; - line-height: inherit; - margin: 0; -} - -button, -input[type="button"], -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; -} - -input[type="search"] { - -webkit-appearance: textfield; -} - -::-webkit-input-placeholder { - color: inherit; - opacity: 0.54; -} - -::-webkit-search-decoration, -::-webkit-search-cancel-button, -::-webkit-search-results-button, -::-webkit-search-results-decoration { - -webkit-appearance: none; -} - -img { - border-style: none; -} diff --git a/src/shared/variables.css b/src/shared/variables.css deleted file mode 100644 index 225c2ae6..00000000 --- a/src/shared/variables.css +++ /dev/null @@ -1,103 +0,0 @@ -/* Base styles */ -:root { - /* Layout variables */ - --border-radius: 0.188rem; - --font-family: -apple-system, "Helvetica Neue", "Helvetica", sans-serif; - --letter-spacing-default: -0.029rem; - --letter-spacing-large: -0.031rem; - --letter-spacing-medium: -0.018rem; - --letter-spacing-small: -0.008rem; - --opacity-disabled: 0.3; - --text-default: 1rem/1.5rem var(--font-family); - --text-large: 1.25rem/1.5rem var(--font-family); - --text-medium: 0.875rem/1.313rem var(--font-family); - --text-small: 0.719rem/1rem var(--font-family); - - /* Editor layout variables */ - --editor-font: monaco, monospace; - --editor-font-size: 14px; - --editor-line-height: 24px; - --editor-active-line: var(--color-bg-secondary); - --editor-error: var(--color-red); - --editor-non-matching-bracket: var(--editor-error); - --editor-selected-bg: rgb(116 178 235 / 0.35); - --editor-matched-highlight: rgb(116 178 235 / 0.2); - --editor-search-highlight: rgb(255 166 0 / 0.3); - - /* Dark theme (default) */ - --color-bg-primary: #323639; - --color-bg-secondary: #2f3337; - --color-bg-theme: var(--color-black); - --color-script-highlighted: #364049; - --color-black: #1d2023; - --color-white: #fff; - --color-blue: #74b1eb; - --color-green: #60f36c; - --color-grey: rgb(255 255 255 / 0.15); - --color-red: #ff453a; - --color-yellow: #e4f360; - --text-color-primary: rgb(255 255 255); - --text-color-secondary: rgb(255 255 255 / 0.65); - --text-color-disabled: rgb(255 255 255 / 0.4); - --box-shadow: 0 0.5rem 1rem 0 rgb(0 0 0 / 0.25); - --button-color: var(--color-black); - --border-color: var(--color-black); - - /* Editor dark theme colors */ - --editor-invisible: rgb(255 255 255 / 0.15); - --editor-number: #77e26a; - --editor-comment: rgb(255 255 255 / 0.35); - --editor-def: #efc371; - --editor-default: #cdcfd1; - --editor-keyword: #96c3ed; - --editor-atom: #59ebf5; - --editor-operator: #8c99a7; - --editor-property: #e86c8a; - --editor-string: #f5eea2; - --editor-string-2: #cdabff; - --editor-cursor: #e3e7eb; - --editor-matching-bracket-color: #fff; - --editor-matching-bracket-border: var(--editor-number); - --editor-blurred-background: rgb(50 54 57 / 0.65); -} - -/* Light theme */ -@media (prefers-color-scheme: light) { - :root { - color-scheme: light dark; - --color-bg-primary: #fafafa; - --color-bg-secondary: #f1f1f1; - --color-bg-theme: var(--color-white); - --color-script-highlighted: #e2ebf3; - --color-black: #333; - --color-white: #fff; - --color-blue: #317eff; - --color-green: #2bb239; - --color-grey: rgb(51 51 51 / 0.15); - --color-red: #ff453a; - --color-yellow: #b8722c; - --text-color-primary: rgb(51 51 51); - --text-color-secondary: rgb(51 51 51 / 0.65); - --text-color-disabled: rgb(51 51 51 / 0.35); - --box-shadow: 0 0.25rem 1rem 0 rgb(0 0 0 / 0.15); - --button-color: var(--color-white); - --border-color: var(--color-grey); - - /* Editor light theme colors */ - --editor-invisible: rgb(51 51 51 / 0.15); - --editor-number: var(--color-green); - --editor-comment: var(--text-color-disabled); - --editor-def: #b86d17; - --editor-default: #777; - --editor-keyword: #3a68ff; - --editor-atom: #00adad; - --editor-operator: #8c99a7; - --editor-property: #ff453a; - --editor-string: var(--editor-atom); - --editor-string-2: #a34fe6; - --editor-cursor: #7e7e7f; - --editor-matching-bracket-color: var(--text-color-primary); - --editor-matching-bracket-border: #ff00ea; - --editor-blurred-background: rgb(255 255 255 / 0.65); - } -} diff --git a/src/shared/vite-env.d.ts b/src/shared/vite-env.d.ts deleted file mode 100644 index 4078e747..00000000 --- a/src/shared/vite-env.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -/// -/// diff --git a/vite.config.js b/vite.config.js deleted file mode 100644 index 56037d79..00000000 --- a/vite.config.js +++ /dev/null @@ -1,28 +0,0 @@ -import { defineConfig } from "vite"; -import { svelte } from "@sveltejs/vite-plugin-svelte"; -import { baseConfig } from "./scripts/utils.js"; - -/** - * About `inline-svg` - * use `?raw` suffix import svg assets as inline - * @see {@link https://vitejs.dev/guide/assets.html#importing-asset-as-string} - * Ignore lint errors `{@html}`, since these are deterministic local svg resources, - * there is no risk of Cross-Site Scripting (XSS) attacks and can be safely disabled. - * @see {@link https://sveltejs.github.io/eslint-plugin-svelte/rules/no-at-html-tags/} - */ - -/** - * About `autoprefixer` - * have config with `.postcssrc.json` file - * @see {@link https://vitejs.dev/guide/features.html#postcss} - * about `missing peer postcss` error, ignore it - */ - -/** @see {@link https://vitejs.dev/config/} */ -export default defineConfig({ - publicDir: "public/ext/vendor/", - plugins: [svelte()], - base: "./", - define: baseConfig.define, - resolve: baseConfig.resolve, -}); diff --git a/xcode/App-Mac/App.entitlements b/xcode/App-Mac/App.entitlements deleted file mode 100644 index aa2f466a..00000000 --- a/xcode/App-Mac/App.entitlements +++ /dev/null @@ -1,16 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.application-groups - - $(MAC_SHARED_GID) - - com.apple.security.files.user-selected.read-write - - com.apple.security.network.client - - - diff --git a/xcode/App-Mac/AppDelegate.swift b/xcode/App-Mac/AppDelegate.swift deleted file mode 100644 index 79c286dc..00000000 --- a/xcode/App-Mac/AppDelegate.swift +++ /dev/null @@ -1,97 +0,0 @@ -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - var window: NSWindow! - private var windowForego = false - private var windowLoaded = false - private let logger = USLogger(#fileID) - - @IBOutlet weak var enbaleNativeLogger: NSMenuItem! - - @objc func handleGetURL(event: NSAppleEventDescriptor, replyEvent: NSAppleEventDescriptor) { - // issue: https://developer.apple.com/forums/thread/697217 -// sendExtensionMessage(name: "URL_SCHEME_STARTED") - // if open panel is already open, stop processing the URL scheme - if NSApplication.shared.keyWindow?.accessibilityIdentifier() == "open-panel" { return } - // handle URL scheme - if let urlString = event.paramDescriptor(forKeyword: AEKeyword(keyDirectObject))?.stringValue, - let url = URL(string: urlString) { - logger?.info("\(#function, privacy: .public) - \(urlString, privacy: .public)") - if url.host == "changesavelocation" { - // avoid opening the panel repeatedly and playing unnecessary warning sounds - if NSApplication.shared.keyWindow?.identifier?.rawValue == "changeSaveLocation" { return } - if windowLoaded { - let viewController = window.contentViewController as? ViewController - viewController?.changeSaveLocation() - } else { - windowForego = true - schemeChangeSaveLocation() - } - } - } - } - - // https://developer.apple.com/documentation/appkit/nsapplicationdelegate/1428623-applicationwillfinishlaunching/ - func applicationWillFinishLaunching(_ notification: Notification) { - // https://developer.apple.com/documentation/foundation/nsappleeventmanager/1416131-seteventhandler - NSAppleEventManager.shared().setEventHandler( - self, - andSelector: #selector(handleGetURL(event:replyEvent:)), - forEventClass: AEEventClass(kInternetEventClass), - andEventID: AEEventID(kAEGetURL) - ) - } - - // https://developer.apple.com/documentation/appkit/nsapplicationdelegate/1428385-applicationdidfinishlaunching - func applicationDidFinishLaunching(_ notification: Notification) { - // Initialize menu items - enbaleNativeLogger.state = Preferences.enableLogger ? .on : .off - // Whether to initialize the main window - logger?.debug("\(#function, privacy: .public) - windowForego: \(self.windowForego, privacy: .public)") - if windowForego { return } - // https://developer.apple.com/documentation/appkit/nswindow/ - window = NSWindow() - window.styleMask = [.titled, .closable, .miniaturizable] -// window.styleMask = [.titled, .closable, .resizable, .miniaturizable] // DEBUG - window.titlebarAppearsTransparent = true - // Initialize webview - window.contentViewController = ViewController() - // https://developer.apple.com/documentation/uikit/appearance_customization/supporting_dark_mode_in_your_interface#2993897 - window.backgroundColor = NSColor(named: NSColor.Name("USBackgroundColor")) -// window.backgroundColor = .clear // DEBUG - window.center() - window.setIsVisible(true) - window.makeMain() - window.makeKeyAndOrderFront(nil) -// window.level = NSWindow.Level.floating // DEBUG - windowLoaded = true - } - - func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool { - return true - } - - func applicationWillTerminate(_ notification: Notification) { - // Insert code here to tear down your application - USLogStoreToFile() - } - - func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { - return true - } - - @IBAction func enableLogger(_ sender: NSMenuItem) { - let enable = sender.state == .on ? false : true - sender.state = enable ? .on : .off - USLoggerSwitch(enable) - } - - @IBAction func applicationHelp(_ sender: NSMenuItem) { - if let url = URL(string: "https://github.com/quoid/userscripts") { - NSWorkspace.shared.open(url) - } - } - -} diff --git a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/1024.png b/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/1024.png deleted file mode 100644 index a4228de1..00000000 Binary files a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/1024.png and /dev/null differ diff --git a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/128.png b/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/128.png deleted file mode 100644 index bc14d5e1..00000000 Binary files a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/128.png and /dev/null differ diff --git a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/16.png b/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/16.png deleted file mode 100644 index 7aa84ac6..00000000 Binary files a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/16.png and /dev/null differ diff --git a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/256-1.png b/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/256-1.png deleted file mode 100644 index 9fe96182..00000000 Binary files a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/256-1.png and /dev/null differ diff --git a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/256.png b/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/256.png deleted file mode 100644 index 9fe96182..00000000 Binary files a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/256.png and /dev/null differ diff --git a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/32-1.png b/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/32-1.png deleted file mode 100644 index 5f167918..00000000 Binary files a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/32-1.png and /dev/null differ diff --git a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/32.png b/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/32.png deleted file mode 100644 index 5f167918..00000000 Binary files a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/32.png and /dev/null differ diff --git a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/512-1.png b/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/512-1.png deleted file mode 100644 index 11859e5f..00000000 Binary files a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/512-1.png and /dev/null differ diff --git a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/512.png b/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/512.png deleted file mode 100644 index 11859e5f..00000000 Binary files a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/512.png and /dev/null differ diff --git a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/64.png b/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/64.png deleted file mode 100644 index 1f09f4e3..00000000 Binary files a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/64.png and /dev/null differ diff --git a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/Contents.json b/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 377279b3..00000000 --- a/xcode/App-Mac/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "images" : [ - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "16.png", - "scale" : "1x" - }, - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "32.png", - "scale" : "2x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "32-1.png", - "scale" : "1x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "64.png", - "scale" : "2x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "128.png", - "scale" : "1x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "256.png", - "scale" : "2x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "256-1.png", - "scale" : "1x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "512.png", - "scale" : "2x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "512-1.png", - "scale" : "1x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "1024.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/xcode/App-Mac/Assets.xcassets/Contents.json b/xcode/App-Mac/Assets.xcassets/Contents.json deleted file mode 100644 index da4a164c..00000000 --- a/xcode/App-Mac/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/xcode/App-Mac/Base.lproj/Main.storyboard b/xcode/App-Mac/Base.lproj/Main.storyboard deleted file mode 100644 index 859f7dde..00000000 --- a/xcode/App-Mac/Base.lproj/Main.storyboard +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/xcode/App-Mac/Functions.swift b/xcode/App-Mac/Functions.swift deleted file mode 100644 index a6608954..00000000 --- a/xcode/App-Mac/Functions.swift +++ /dev/null @@ -1,76 +0,0 @@ -import AppKit -import SafariServices - -private let logger = USLogger(#fileID) - -func getSaveLocationURL() -> URL { - return Preferences.scriptsDirectoryUrl -} - -func setSaveLocationURL(url: URL) -> Bool { - guard FileManager.default.isReadableFile(atPath: url.path) else { - let alert = NSAlert() - alert.messageText = "Cannot read the specified path; please choose a different one." - alert.runModal() - return false - } - guard FileManager.default.isWritableFile(atPath: url.path) else { - let alert = NSAlert() - alert.messageText = "Cannot write to the specified path; please choose a different one." - alert.runModal() - return false - } - Preferences.scriptsDirectoryUrl = url - return Preferences.scriptsDirectoryUrl == url -} - -func sendExtensionMessage(name: String, userInfo: [String : Any]? = nil, completion: ((Error?) -> Void)? = nil) { - SFSafariApplication.dispatchMessage( - withName: name, - toExtensionWithIdentifier: extIdentifier, - userInfo: userInfo - ) { error in // always be called - if error != nil { - debugPrint("Message attempted. Error info: \(String.init(describing: error))") - } - if let userHandle = completion { userHandle(error) } - } -} - -func changeSaveLocationPanel(directoryURL: URL? = nil) -> NSOpenPanel { - let panel = NSOpenPanel() - panel.allowsMultipleSelection = false - panel.canChooseDirectories = true - panel.canCreateDirectories = true - panel.canChooseFiles = false - if directoryURL != nil { - panel.directoryURL = directoryURL - } - panel.title = "Change Save Location - Userscripts" - panel.identifier = NSUserInterfaceItemIdentifier("changeSaveLocation") - return panel -} - -func schemeChangeSaveLocation() { - let saveLocationURL = getSaveLocationURL() - let panel = changeSaveLocationPanel(directoryURL: saveLocationURL) - // shows the path selection panel - let response = panel.runModal() - // check if clicked open button and there is a valid result - guard response == .OK, let url: URL = panel.urls.first else { return } - // revoke implicitly starts security-scoped access - defer { url.stopAccessingSecurityScopedResource() } - // check if path has indeed changed - if url.absoluteString == saveLocationURL.absoluteString { return } - // try set new save location path to bookmark - guard setSaveLocationURL(url: url) else { return } - // use semaphore to ensure the async func executed before app exits - let semaphore = DispatchSemaphore(value: 0) - // notify browser extension of relevant updates - sendExtensionMessage( - name: "SAVE_LOCATION_CHANGED", - userInfo: ["saveLocation": url.absoluteString.removingPercentEncoding ?? url.absoluteString], - completion: { _ in semaphore.signal() } - ) - semaphore.wait() -} diff --git a/xcode/App-Mac/Info.plist b/xcode/App-Mac/Info.plist deleted file mode 100644 index ea3f7898..00000000 --- a/xcode/App-Mac/Info.plist +++ /dev/null @@ -1,51 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - $(MARKETING_VERSION) - CFBundleURLTypes - - - CFBundleTypeRole - Viewer - CFBundleURLName - $(APP_IDENTIFIER) - CFBundleURLSchemes - - $(APP_URL_SCHEME) - - - - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - LSApplicationCategoryType - public.app-category.developer-tools - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2021 Justin Wasack. All rights reserved. - NSMainStoryboardFile - Main - NSPrincipalClass - NSApplication - US_SHARED_GID - $(MAC_SHARED_GID) - US_EXT_IDENTIFIER - $(EXT_IDENTIFIER) - - diff --git a/xcode/App-Mac/ViewController.swift b/xcode/App-Mac/ViewController.swift deleted file mode 100644 index e09d909c..00000000 --- a/xcode/App-Mac/ViewController.swift +++ /dev/null @@ -1,82 +0,0 @@ -import SafariServices.SFSafariApplication - -private let logger = USLogger(#fileID) - -class ViewController: NSViewController { - - @IBOutlet var appName: NSTextField! - @IBOutlet var saveLocation: NSTextField! - @IBOutlet weak var enabledText: NSTextField! - @IBOutlet weak var enabledIcon: NSView! - @IBOutlet weak var openButton: NSButton! - - let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "??" - let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "??" - - override func viewDidLoad() { - super.viewDidLoad() - self.appName.stringValue = "Userscripts Safari Version \(appVersion) (\(buildNumber))" - setExtensionState() - NotificationCenter.default.addObserver( - self, - selector: #selector(setExtensionState), - name: NSApplication.didBecomeActiveNotification, - object: nil - ) - let url = getSaveLocationURL() - self.saveLocation.stringValue = url.absoluteString - self.saveLocation.toolTip = url.absoluteString - if #available(macOS 13, *) { - self.openButton.title = "Open Safari Settings" - } - } - - @objc func setExtensionState() { - SFSafariExtensionManager.getStateOfSafariExtension(withIdentifier: extIdentifier) { (state, error) in - guard let state = state else { - self.enabledText.stringValue = "Safari Extension State Unknown" - if let error = error { - logger?.error("\(#function, privacy: .public) - \(error, privacy: .public)") - } else { - logger?.error("\(#function, privacy: .public) - couldn't get safari extension state in containing app") - } - return - } - DispatchQueue.main.async { - self.enabledIcon.layer?.backgroundColor = state.isEnabled ? NSColor.green.cgColor : NSColor.red.cgColor - self.enabledText.stringValue = state.isEnabled ? "Safari Extension Enabled" : "Safari Extension Disabled" - } - } - } - - @IBAction func changeSaveLocation(_ sender: AnyObject?) { - guard let window = self.view.window else { return } - let saveLocationURL = getSaveLocationURL() - let panel = changeSaveLocationPanel(directoryURL: saveLocationURL) - panel.beginSheetModal(for: window, completionHandler: { response in - // check if clicked open button and there is a valid result - guard response == .OK, let url: URL = panel.urls.first else { return } - // revoke implicitly starts security-scoped access - defer { url.stopAccessingSecurityScopedResource() } - // check if path has indeed changed - if url.absoluteString == saveLocationURL.absoluteString { return } - // try set new save location path to bookmark - guard setSaveLocationURL(url: url) else { return } - // update user interface text display - self.saveLocation.stringValue = url.absoluteString - self.saveLocation.toolTip = url.absoluteString - // notify browser extension of relevant updates - sendExtensionMessage( - name: "SAVE_LOCATION_CHANGED", - userInfo: [ - "saveLocation": url.absoluteString.removingPercentEncoding ?? url.absoluteString, - "returnApp": true - ] - ) - }) - } - - @IBAction func openSafariExtensionPreferences(_ sender: AnyObject?) { - SFSafariApplication.showPreferencesForExtension(withIdentifier: extIdentifier) - } -} diff --git a/xcode/App-Shared/AppIcon.icon/Assets/icon.svg b/xcode/App-Shared/AppIcon.icon/Assets/icon.svg deleted file mode 100644 index f19d064d..00000000 --- a/xcode/App-Shared/AppIcon.icon/Assets/icon.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - icon - - - - - - \ No newline at end of file diff --git a/xcode/App-Shared/AppIcon.icon/icon.json b/xcode/App-Shared/AppIcon.icon/icon.json deleted file mode 100644 index a5558deb..00000000 --- a/xcode/App-Shared/AppIcon.icon/icon.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "fill-specializations" : [ - { - "value" : "automatic" - }, - { - "appearance" : "dark", - "value" : "automatic" - } - ], - "groups" : [ - { - "blend-mode-specializations" : [ - { - "value" : "plus-darker" - }, - { - "appearance" : "dark", - "value" : "plus-lighter" - }, - { - "appearance" : "tinted", - "value" : "normal" - } - ], - "blur-material" : 0.5, - "hidden" : false, - "layers" : [ - { - "blend-mode" : "normal", - "fill-specializations" : [ - { - "value" : "automatic" - }, - { - "appearance" : "dark", - "value" : { - "linear-gradient" : [ - "extended-gray:1.00000,0.80000", - "extended-gray:1.00000,0.70000" - ] - } - }, - { - "appearance" : "tinted", - "value" : { - "linear-gradient" : [ - "extended-gray:1.00000,0.80000", - "extended-gray:1.00000,0.70000" - ] - } - } - ], - "glass" : true, - "hidden" : false, - "image-name" : "icon.svg", - "name" : "icon", - "opacity" : 1 - } - ], - "lighting" : "individual", - "position" : { - "scale" : 1, - "translation-in-points" : [ - 0, - 0 - ] - }, - "shadow-specializations" : [ - { - "value" : { - "kind" : "neutral", - "opacity" : 0.5 - } - }, - { - "appearance" : "light", - "value" : { - "kind" : "layer-color", - "opacity" : 0.5 - } - } - ], - "specular" : true, - "translucency" : { - "enabled" : true, - "value" : 0.2 - } - } - ], - "supported-platforms" : { - "squares" : "shared" - } -} \ No newline at end of file diff --git a/xcode/App-Shared/Shared.xcassets/Contents.json b/xcode/App-Shared/Shared.xcassets/Contents.json deleted file mode 100644 index 73c00596..00000000 --- a/xcode/App-Shared/Shared.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/xcode/App-Shared/Shared.xcassets/USBackgroundColor.colorset/Contents.json b/xcode/App-Shared/Shared.xcassets/USBackgroundColor.colorset/Contents.json deleted file mode 100644 index 59ca3d0d..00000000 --- a/xcode/App-Shared/Shared.xcassets/USBackgroundColor.colorset/Contents.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "colors" : [ - { - "color" : { - "color-space" : "srgb", - "components" : { - "alpha" : "1.000", - "blue" : "0xFA", - "green" : "0xFA", - "red" : "0xFA" - } - }, - "idiom" : "universal" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "color" : { - "color-space" : "srgb", - "components" : { - "alpha" : "1.000", - "blue" : "0x39", - "green" : "0x36", - "red" : "0x32" - } - }, - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/xcode/App-Shared/USchemeHandler.swift b/xcode/App-Shared/USchemeHandler.swift deleted file mode 100644 index 70bbd601..00000000 --- a/xcode/App-Shared/USchemeHandler.swift +++ /dev/null @@ -1,66 +0,0 @@ -import WebKit -import UniformTypeIdentifiers - -let AppWebViewUrlScheme = "userscriptsapp" -let AppWebViewEntryPage = "entry-app-webview.html" -private let logger = USLogger(#fileID) - -// https://developer.apple.com/documentation/webkit/wkurlschemehandler -// https://developer.apple.com/documentation/webkit/wkurlschemetask -class USchemeHandler: NSObject, WKURLSchemeHandler { - - func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) { - // wrapper of didFailWithError - func failHandler(_ errmsg: String) { - logger?.error("\(#function) - \(errmsg, privacy: .public)") - // redirect to a customized error page -// DispatchQueue.main.async { -// webView.load(URLRequest(url: URL(string: "\(AppWebViewUrlScheme):///")!)) -// } - urlSchemeTask.didFailWithError(NSError(domain: "USchemeHandler", code: 0, userInfo: nil)) - } - - // https://developer.apple.com/documentation/dispatch/dispatchqueue - DispatchQueue.global(qos: .userInteractive).async { - guard let url = urlSchemeTask.request.url else { - failHandler("failed to get request url") - return - } - guard url.scheme == AppWebViewUrlScheme else { - failHandler("unexpected url scheme: \(url)") - return - } - var name: String - if #available(macOS 13.0, iOS 16.0, *) { - name = url.path(percentEncoded: false) - } else { - name = url.path - } - if ["", "/"].contains(name) { - name = AppWebViewEntryPage - } - guard let file = Bundle.main.url(forResource: name, withExtension: nil, subdirectory: "dist") else { - failHandler("file not found: \(url)") - return - } - guard let data = try? Data(contentsOf: file) else { - failHandler("faild to get data from: \(url)") - return - } - - // https://developer.apple.com/documentation/uniformtypeidentifiers - // let mime = UTType.init(filenameExtension: file.pathExtension)?.preferredMIMEType ?? "application/octet-stream" - let mime = UTTypeReference.init(filenameExtension: file.pathExtension)?.preferredMIMEType ?? "application/octet-stream" - - let response = URLResponse(url: url, mimeType: mime, expectedContentLength: data.count, textEncodingName: nil) - urlSchemeTask.didReceive(response) - urlSchemeTask.didReceive(data) - urlSchemeTask.didFinish() - } - } - - func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) { - - } - -} diff --git a/xcode/App-Shared/ViewController.swift b/xcode/App-Shared/ViewController.swift deleted file mode 100644 index 83e0040d..00000000 --- a/xcode/App-Shared/ViewController.swift +++ /dev/null @@ -1,413 +0,0 @@ -import WebKit -import SwiftUI - -#if os(iOS) -typealias PlatformViewController = UIViewController -#elseif os(macOS) -import SafariServices.SFSafariApplication -typealias PlatformViewController = NSViewController -#endif - -private let logger = USLogger(#fileID) - -class ViewController: PlatformViewController, WKNavigationDelegate, WKScriptMessageHandlerWithReply { - - @IBOutlet var webView: WKWebView! - - enum ExtensionState: String { - case unknow = "unknow" - case on = "enabled" - case off = "disabled" - case error = "error" - } - var extensionState: ExtensionState = .unknow -#if os(iOS) - var documentPickerHandler: ((URL) -> Void)? -#elseif os(macOS) - var timerExtensionStateCheck: Timer? -#endif - - // https://developer.apple.com/documentation/uikit/uiviewcontroller/1621454-loadview - override func loadView() { - // https://developer.apple.com/documentation/webkit/wkwebviewconfiguration - let configuration = WKWebViewConfiguration() - // https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/2875766-seturlschemehandler - configuration.setURLSchemeHandler(USchemeHandler(), forURLScheme: AppWebViewUrlScheme) - // https://developer.apple.com/documentation/webkit/wkusercontentcontroller - configuration.userContentController.addScriptMessageHandler(self, contentWorld: .page, name: "controller") - // https://developer.apple.com/documentation/webkit/wkwebview - self.webView = WKWebView(frame: .zero, configuration: configuration) -#if os(iOS) - self.webView.isOpaque = false - // https://developer.apple.com/documentation/uikit/appearance_customization/supporting_dark_mode_in_your_interface#2993897 - self.webView.backgroundColor = UIColor(named: "USBackgroundColor") -// self.webView.backgroundColor = .clear // DEBUG -// self.webView.scrollView.isScrollEnabled = false -#elseif os(macOS) - self.webView.frame = NSRect(x: 0, y: 0, width: 600, height: 600) - self.webView.setValue(false, forKey: "drawsBackground") -#endif - // https://developer.apple.com/documentation/webkit/wknavigationdelegate - self.webView.navigationDelegate = self -#if DEBUG - // https://webkit.org/blog/13936/enabling-the-inspection-of-web-content-in-apps/ - if #available(macOS 13.3, iOS 16.4, tvOS 16.4, *) { - // https://developer.apple.com/documentation/webkit/wkwebview/4111163-inspectable/ - self.webView.isInspectable = true - } - logger?.debug("\(#function, privacy: .public) - DEBUG mode: isInspectable = true") -#endif - self.view = self.webView - } - - // https://developer.apple.com/documentation/uikit/uiviewcontroller/1621495-viewdidload - override func viewDidLoad() { - super.viewDidLoad() -#if VITE - let url = URL(string: "https://userscripts.test:55173/entry-app-webview.html")! -#else - let url = URL(string: "\(AppWebViewUrlScheme):///")! -#endif - self.webView.load(URLRequest(url: url)) -#if os(macOS) - NotificationCenter.default.addObserver( - self, - selector: #selector(handleOcclusionStateChange), - name: NSApplication.didChangeOcclusionStateNotification, - object: nil - ) -#endif - } - - // https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview - // DOMContentLoaded -// func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { -// webView.evaluateJavaScript("") -// } - - func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { - if navigationAction.navigationType == .linkActivated { - guard let url = navigationAction.request.url else { - decisionHandler(.allow) - return - } - // allow registration scheme - if url.scheme == AppWebViewUrlScheme { - decisionHandler(.allow) - return - } - // allow specified url prefixes -// let allowPrefixes = [ -// "https://github.com/quoid/userscripts" -// ] -// for prefix in allowPrefixes { -// if url.absoluteString.lowercased().hasPrefix(prefix) { -// decisionHandler(.allow) -// return -// } -// } - // open from external app like safari -#if os(iOS) - if UIApplication.shared.canOpenURL(url) { - UIApplication.shared.open(url) - decisionHandler(.cancel) - return - } -#elseif os(macOS) - if let _ = NSWorkspace.shared.urlForApplication(toOpen: url) { - NSWorkspace.shared.open(url) - decisionHandler(.cancel) - return - } -#endif - decisionHandler(.allow) - } - decisionHandler(.allow) - } - - func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) async -> (Any?, String?) { - guard let name = message.body as? String else { - logger?.error("\(#function, privacy: .public) - Userscripts iOS received a message without a name") - return (nil, "bad message body") - } - logger?.debug("\(#function, privacy: .public) - Got message: \(name)") - switch name { - case "INIT": - let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "0.0.0" - let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "0" - let firstRunTime = Preferences.firstRunTime - if(firstRunTime == 0) { - Preferences.firstRunTime = Int(Date().timeIntervalSince1970 * 1000) - } - var useSettingsInsteadOfPreferences = false -#if os(iOS) - let platform = "ios" -#elseif os(macOS) - let platform = "mac" - do { - let state = try await SFSafariExtensionManager.stateOfSafariExtension(withIdentifier: extIdentifier) - self.extensionState = state.isEnabled ? .on : .off - } catch { - self.extensionState = .error - logger?.error("\(#function, privacy: .public) - \(error, privacy: .public)") - } - if #available(macOS 13, *) { - useSettingsInsteadOfPreferences = true - } -#endif - return ([ - "build": buildNumber, - "version": appVersion, - "platform": platform, - "directory": getCurrentScriptsDirectoryString(), - "extStatus": self.extensionState.rawValue, - "useSettingsInsteadOfPreferences": useSettingsInsteadOfPreferences, - "enableLogger": Preferences.enableLogger, - "promptLogger": Preferences.promptLogger, - "maxLogFileSize": Preferences.maxLogFileSize, - "firstRunTime": firstRunTime, - ], nil) - case "CHANGE_DIRECTORY": - changeSaveLocation() - break - case "OPEN_DIRECTORY": -#if os(iOS) - guard let saveLocation = getSaveLocation() else { - return (nil, "Uninitialized save location") - } - guard var components = URLComponents(url: saveLocation, resolvingAgainstBaseURL: true) else { - return (nil, "ScriptsDirectoryUrl malformed") - } - components.scheme = "shareddocuments" - if let url = components.url, UIApplication.shared.canOpenURL(url) { - await UIApplication.shared.open(url) - } -#elseif os(macOS) - guard openSaveLocation() else { - return (nil, "ScriptsDirectoryUrl malformed") - } -#endif - break -#if os(macOS) - case "SHOW_PREFERENCES": - do { - try await SFSafariApplication.showPreferencesForExtension(withIdentifier: extIdentifier) - } catch { - logger?.error("\(#function, privacy: .public) - \(error, privacy: .public)") - return (nil, error.localizedDescription) - } - break -#endif - case "EXPORT_LOG_FILES": - // write the logStore so far to log files (async, no guarantee) - USLogStoreToFile(prioritize: true) - // call the export func of different platforms - exportLogFiles() - break - case "DISABLE_LOGGER": - USLoggerSwitch(false) - break - case "DISMISS_LOGGER_PROMPT": - Preferences.promptLogger = false - break - default: - return (nil, "Unexpected message body") - } - return (nil, nil) - } - - func updateEnableLoggerState() { - self.webView.evaluateJavaScript("webapp.switchLogger(\(Preferences.enableLogger),\(Preferences.promptLogger))") - } - - func updateCurrentDirectory() { - self.webView.evaluateJavaScript("webapp.updateDirectory('\(getCurrentScriptsDirectoryString())')") - } - -#if os(macOS) - deinit { - NotificationCenter.default.removeObserver( - self, - name: NSApplication.didChangeOcclusionStateNotification, - object: nil - ) - - DistributedNotificationCenter.default.removeObserver( - self, - name: NSNotification.Name("AppleInterfaceThemeChangedNotification"), - object: nil - ) - } -#endif - -} - -#if os(iOS) -// https://developer.apple.com/documentation/uikit/view_controllers/providing_access_to_directories -// https://developer.apple.com/documentation/uikit/uidocumentpickerviewcontroller -extension ViewController: UIDocumentPickerDelegate { - - // UIDocumentPickerDelegate - // https://developer.apple.com/documentation/uikit/uidocumentpickerdelegate/2902364-documentpicker - func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) { - guard let handler = documentPickerHandler else { - logger?.debug("\(#function, privacy: .public) - documentPickerHandler not set") - return - } - // call handler - handler(url) - // reset handler - documentPickerHandler = nil - } - - func changeSaveLocation() { - logger?.info("\(#function, privacy: .public) - Userscripts iOS has requested to set the readLocation") - // set handler - documentPickerHandler = changeSaveLocationHandler - let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: [.folder]) - documentPicker.delegate = self - documentPicker.directoryURL = getDocumentsDirectory() - present(documentPicker, animated: true) - } - - func changeSaveLocationHandler(_ url: URL) { - Preferences.scriptsDirectoryUrl = url - self.updateCurrentDirectory() - } - - func exportLogFiles() { - // set handler - documentPickerHandler = exportLogFilesHandler - let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: [.folder]) - documentPicker.delegate = self - present(documentPicker, animated: true) - } - - func exportLogFilesHandler(_ url: URL) { - guard url.startAccessingSecurityScopedResource() else { - logger?.error("\(#function, privacy: .public) - failed access url: \(url, privacy: .public)") - return - } - defer { url.stopAccessingSecurityScopedResource() } - // export log files and open output directory - do { - let outURL = try USLogFilesExportTo(url) - guard var components = URLComponents(url: outURL, resolvingAgainstBaseURL: true) else { - logger?.error("\(#function, privacy: .public) - url malformed: \(url, privacy: .public)") - return - } - components.scheme = "shareddocuments" - if let url = components.url, UIApplication.shared.canOpenURL(url) { - UIApplication.shared.open(url) - } - } catch { - logger?.error("\(#function, privacy: .public) - Export failed: \(error)") - let alert = UIAlertController( - title: "Export failed", - message: "\(error)", - preferredStyle: .alert - ) - alert.addAction(UIAlertAction(title: "OK", style: .default)) - present(alert, animated: true) - } - } - -} - -#elseif os(macOS) -extension ViewController { - - // Only update the view when the window is visible - @objc func handleOcclusionStateChange() { - let occlusionState = NSApplication.shared.occlusionState - if occlusionState.contains(.visible) { - if timerExtensionStateCheck?.isValid != true { - timerExtensionStateCheck = Timer.scheduledTimer( - timeInterval: 0.2, - target: self, - selector: #selector(handleExtensionStateChange), - userInfo: nil, - repeats: true - ) - } - } else { - timerExtensionStateCheck?.invalidate() - } - } - - // Update webview extension status display via timer - @objc func handleExtensionStateChange() { - SFSafariExtensionManager.getStateOfSafariExtension(withIdentifier: extIdentifier) { (state, error) in - var status: ExtensionState; - if let state = state { - status = state.isEnabled ? .on : .off - } else { - status = .error - if let error = error { - logger?.error("\(#function, privacy: .public) - \(error, privacy: .public)") - } else { - logger?.error("\(#function, privacy: .public) - couldn't get safari extension state in containing app") - } - } - if self.extensionState == status { return } - self.extensionState = status - DispatchQueue.main.async { - self.webView.evaluateJavaScript("webapp.updateExtStatus('\(status.rawValue)')") - } - } - } - - func changeSaveLocation() { - guard let window = self.view.window else { return } - let saveLocationURL = getSaveLocationURL() - let panel = changeSaveLocationPanel(directoryURL: saveLocationURL) - panel.beginSheetModal(for: window, completionHandler: { response in - // check if clicked open button and there is a valid result - guard response == .OK, let url: URL = panel.url else { return } - // revoke implicitly starts security-scoped access - defer { url.stopAccessingSecurityScopedResource() } - // check if path has indeed changed - if url.absoluteString == saveLocationURL.absoluteString { return } - // try set new save location path to bookmark - guard setSaveLocationURL(url: url) else { return } - // update user interface text display - self.updateCurrentDirectory() - // notify browser extension of relevant updates - sendExtensionMessage( - name: "SAVE_LOCATION_CHANGED", - userInfo: [ - "saveLocation": url.absoluteString.removingPercentEncoding ?? url.absoluteString, - "returnApp": true - ] - ) - }) - } - - func exportLogFiles() { - guard let window = self.view.window else { return } - let panel = NSOpenPanel() - panel.allowsMultipleSelection = false - panel.canChooseDirectories = true - panel.canChooseFiles = false - panel.title = "Export Log Files" - panel.beginSheetModal(for: window, completionHandler: { response in - panel.close() - // check if clicked save button and there is a valid result - guard response == .OK, let url: URL = panel.url else { return } - // revoke implicitly starts security-scoped access - defer { url.stopAccessingSecurityScopedResource() } - // export log files and open output directory - do { - let outURL = try USLogFilesExportTo(url) - NSWorkspace.shared.selectFile(outURL.path, inFileViewerRootedAtPath: url.path) - } catch { - logger?.error("\(#function, privacy: .public) - Export failed: \(error)") - let alert = NSAlert() - alert.messageText = "Export failed - \(error)" - alert.runModal() - } - }) - } - -} -#endif diff --git a/xcode/App-iOS/App.entitlements b/xcode/App-iOS/App.entitlements deleted file mode 100644 index c31a146a..00000000 --- a/xcode/App-iOS/App.entitlements +++ /dev/null @@ -1,10 +0,0 @@ - - - - - com.apple.security.application-groups - - $(IOS_SHARED_GID) - - - diff --git a/xcode/App-iOS/AppDelegate.swift b/xcode/App-iOS/AppDelegate.swift deleted file mode 100644 index 1ccbd9fa..00000000 --- a/xcode/App-iOS/AppDelegate.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.swift -// Userscripts-iOS -// -// Created by Justin Wasack on 10/3/21. -// Copyright © 2021 Justin Wasack. All rights reserved. -// - -import UIKit -//import os - -@main -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. - initializeFirstStart() - return true - } - - func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { - return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) - } - -} diff --git a/xcode/App-iOS/Assets.xcassets/AccentColor.colorset/Contents.json b/xcode/App-iOS/Assets.xcassets/AccentColor.colorset/Contents.json deleted file mode 100644 index eb878970..00000000 --- a/xcode/App-iOS/Assets.xcassets/AccentColor.colorset/Contents.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "colors" : [ - { - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/1024.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/1024.png deleted file mode 100644 index 0dcf177a..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/1024.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/120-1.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/120-1.png deleted file mode 100644 index e4698a44..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/120-1.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/120.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/120.png deleted file mode 100644 index e4698a44..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/120.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/152.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/152.png deleted file mode 100644 index ed78f8ce..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/152.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/167.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/167.png deleted file mode 100644 index 6847f70e..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/167.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/180.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/180.png deleted file mode 100644 index ca997d3d..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/180.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/20.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/20.png deleted file mode 100644 index 309a0cf9..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/20.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/29.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/29.png deleted file mode 100644 index 4981e4f3..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/29.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/40-1.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/40-1.png deleted file mode 100644 index 98668ae3..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/40-1.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/40-2.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/40-2.png deleted file mode 100644 index 98668ae3..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/40-2.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/40.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/40.png deleted file mode 100644 index 98668ae3..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/40.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/58-1.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/58-1.png deleted file mode 100644 index 9ff7d864..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/58-1.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/58.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/58.png deleted file mode 100644 index 9ff7d864..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/58.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/60.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/60.png deleted file mode 100644 index f0803ec4..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/60.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/76.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/76.png deleted file mode 100644 index b6c523f8..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/76.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/80-1.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/80-1.png deleted file mode 100644 index 371d99ae..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/80-1.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/80.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/80.png deleted file mode 100644 index 371d99ae..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/80.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/87.png b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/87.png deleted file mode 100644 index 8dd571f3..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/87.png and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index e5940774..00000000 --- a/xcode/App-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "images" : [ - { - "filename" : "40.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "60.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "filename" : "58.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "87.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "filename" : "80.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "120.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "filename" : "120-1.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "filename" : "180.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "filename" : "20.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "filename" : "40-1.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "29.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "filename" : "58-1.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "40-2.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "filename" : "80-1.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "76.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "filename" : "152.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "filename" : "167.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "filename" : "1024.png", - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/xcode/App-iOS/Assets.xcassets/Contents.json b/xcode/App-iOS/Assets.xcassets/Contents.json deleted file mode 100644 index 73c00596..00000000 --- a/xcode/App-iOS/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/xcode/App-iOS/Assets.xcassets/LargeIcon.imageset/Contents.json b/xcode/App-iOS/Assets.xcassets/LargeIcon.imageset/Contents.json deleted file mode 100644 index a19a5492..00000000 --- a/xcode/App-iOS/Assets.xcassets/LargeIcon.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/xcode/App-iOS/Assets.xcassets/LaunchScreen.imageset/Contents.json b/xcode/App-iOS/Assets.xcassets/LaunchScreen.imageset/Contents.json deleted file mode 100644 index ae847694..00000000 --- a/xcode/App-iOS/Assets.xcassets/LaunchScreen.imageset/Contents.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "images" : [ - { - "filename" : "LaunchScreenLightCentered.pdf", - "idiom" : "universal" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "filename" : "LaunchScreenDarkCentered.pdf", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "preserves-vector-representation" : true - } -} diff --git a/xcode/App-iOS/Assets.xcassets/LaunchScreen.imageset/LaunchScreenDarkCentered.pdf b/xcode/App-iOS/Assets.xcassets/LaunchScreen.imageset/LaunchScreenDarkCentered.pdf deleted file mode 100644 index 244ab0ef..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/LaunchScreen.imageset/LaunchScreenDarkCentered.pdf and /dev/null differ diff --git a/xcode/App-iOS/Assets.xcassets/LaunchScreen.imageset/LaunchScreenLightCentered.pdf b/xcode/App-iOS/Assets.xcassets/LaunchScreen.imageset/LaunchScreenLightCentered.pdf deleted file mode 100644 index 936d8c04..00000000 Binary files a/xcode/App-iOS/Assets.xcassets/LaunchScreen.imageset/LaunchScreenLightCentered.pdf and /dev/null differ diff --git a/xcode/App-iOS/Base.lproj/LaunchScreen.storyboard b/xcode/App-iOS/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 178ccbc4..00000000 --- a/xcode/App-iOS/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/xcode/App-iOS/Base.lproj/Main.storyboard b/xcode/App-iOS/Base.lproj/Main.storyboard deleted file mode 100644 index 618dfce1..00000000 --- a/xcode/App-iOS/Base.lproj/Main.storyboard +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/xcode/App-iOS/Info.plist b/xcode/App-iOS/Info.plist deleted file mode 100644 index 51a0de5f..00000000 --- a/xcode/App-iOS/Info.plist +++ /dev/null @@ -1,50 +0,0 @@ - - - - - CFBundleURLTypes - - - CFBundleTypeRole - Viewer - CFBundleURLName - $(APP_IDENTIFIER) - CFBundleURLSchemes - - $(APP_URL_SCHEME) - - - - UIApplicationSceneManifest - - UIApplicationSupportsMultipleScenes - - UISceneConfigurations - - UIWindowSceneSessionRoleApplication - - - UISceneConfigurationName - Default Configuration - UISceneDelegateClassName - $(PRODUCT_MODULE_NAME).SceneDelegate - UISceneStoryboardFile - Main - - - - - UIStatusBarStyle - UIStatusBarStyleDefault - UIViewControllerBasedStatusBarAppearance - - UIFileSharingEnabled - - LSSupportsOpeningDocumentsInPlace - - US_SHARED_GID - $(IOS_SHARED_GID) - US_EXT_IDENTIFIER - $(EXT_IDENTIFIER) - - diff --git a/xcode/App-iOS/Initialization.swift b/xcode/App-iOS/Initialization.swift deleted file mode 100644 index 7585ff7d..00000000 --- a/xcode/App-iOS/Initialization.swift +++ /dev/null @@ -1,49 +0,0 @@ -import Foundation - -private let logger = USLogger(#fileID) - -private func createDemoScript() { - let demoScript = """ -// ==UserScript== -// @name Demo user script -// @description I am a demo user script that you can safely delete (add any files to this folder and I will no longer automatically generate) -// @author Userscripts -// @version 0.0.1 -// @match *://*/* -// @grant none -// @inject-into content -// ==/UserScript== - -(function () { - 'use strict'; - // here is your code -})(); -""" - let url = getDocumentsDirectory() - // get a list of non-hidden files - guard let contents = try? FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: [], options: .skipsHiddenFiles) else { - logger?.error("\(#function, privacy: .public) - failed get contentsOfDirectory") - return - } - if contents.isEmpty { - let fileURL = url.appendingPathComponent("Demo_user_script.user.js") - do { - logger?.info("\(#function, privacy: .public) - try to write demo user script") - try demoScript.write(to: fileURL, atomically: true, encoding: .utf8) - } catch { - logger?.error("\(#function, privacy: .public) - failed to write demo user script") - } - } -} - -func initializeFirstStart() { - // set the scripts directory to the app document on first use - if isCurrentDefaultScriptsDirectory() { - logger?.info("\(#function, privacy: .public) - Initialize default directory") - Preferences.scriptsDirectoryUrl = getDocumentsDirectory() - } - // put a visible file to display the documents directory in files app - if isCurrentInitialScriptsDirectory() { - createDemoScript() - } -} diff --git a/xcode/App-iOS/SceneDelegate.swift b/xcode/App-iOS/SceneDelegate.swift deleted file mode 100644 index d1544f61..00000000 --- a/xcode/App-iOS/SceneDelegate.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// SceneDelegate.swift -// Userscripts-iOS -// -// Created by Justin Wasack on 10/3/21. -// Copyright © 2021 Justin Wasack. All rights reserved. -// - -import UIKit - -// https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle -class SceneDelegate: UIResponder, UIWindowSceneDelegate { - - var window: UIWindow? - - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { - guard let _ = (scene as? UIWindowScene) else { return } - } - - func sceneWillResignActive(_ scene: UIScene) { - USLogStoreToFile() - } - - func sceneWillEnterForeground(_ scene: UIScene) { - if let viewController = window?.rootViewController as? ViewController { - viewController.updateEnableLoggerState() - } - } - -} diff --git a/xcode/App-iOS/Settings.bundle/Root.plist b/xcode/App-iOS/Settings.bundle/Root.plist deleted file mode 100644 index b9ad077e..00000000 --- a/xcode/App-iOS/Settings.bundle/Root.plist +++ /dev/null @@ -1,31 +0,0 @@ - - - - - ApplicationGroupContainerIdentifier - // US_SHARED_GID will be introduced in the custom build script - StringsTable - Root - PreferenceSpecifiers - - - Type - PSGroupSpecifier - Title - GroupDebug - FooterText - FooterText - - - Type - PSToggleSwitchSpecifier - Title - EnableLogger - Key - EnableLogger - DefaultValue - - - - - diff --git a/xcode/App-iOS/Settings.bundle/en.lproj/Root.strings b/xcode/App-iOS/Settings.bundle/en.lproj/Root.strings deleted file mode 100644 index dc826ef0..00000000 Binary files a/xcode/App-iOS/Settings.bundle/en.lproj/Root.strings and /dev/null differ diff --git a/xcode/Ext-Safari/Functions.swift b/xcode/Ext-Safari/Functions.swift deleted file mode 100644 index 220a380a..00000000 --- a/xcode/Ext-Safari/Functions.swift +++ /dev/null @@ -1,1949 +0,0 @@ -import SafariServices - -private let logger = USLogger(#fileID) - -// helpers -func getRequireLocation() -> URL { - // simple helper in case required code save directory needs to change - return getDocumentsDirectory().appendingPathComponent("require") -} - -func dateToMilliseconds(_ date: Date) -> Int { - let since1970 = date.timeIntervalSince1970 - return Int(since1970 * 1000) -} - -func sanitize(_ str: String) -> String { - // removes invalid filename characters from strings - var sanitized = str - if sanitized.first == "." { - sanitized = "%2" + str.dropFirst() - } - sanitized = sanitized.replacingOccurrences(of: "/", with: "%2F") - sanitized = sanitized.replacingOccurrences(of: ":", with: "%3A") - sanitized = sanitized.replacingOccurrences(of: "\\", with: "%5C") - return sanitized -} - -func unsanitize(_ str: String) -> String { - var s = str - if s.hasPrefix("%2") && !s.hasPrefix("%2F") { - s = "." + s.dropFirst(2) - } - if s.removingPercentEncoding != s { - s = s.removingPercentEncoding ?? s - } - return s -} - -func normalizeWeight(_ weight: String) -> String { - if let w = Int(weight) { - if w > 999 { - return "999" - } else if w < 1 { - return "1" - } else { - return weight - } - } else { - return "1" - } -} - -func validateUrl(_ urlString: String) -> Bool { - guard - let parts = jsLikeURL(urlString), - let ptcl = parts["protocol"], - let path = parts["pathname"] - else { - logger?.error("\(#function, privacy: .public) - Invalid URL: \(urlString, privacy: .public)") - return false - } - if ptcl != "https:" && ptcl != "http:" { - logger?.error("\(#function, privacy: .public) - Invalid URL protocol: \(urlString, privacy: .public)") - return false - } - if !path.hasSuffix(".css") && !path.hasSuffix(".js") { - logger?.error("\(#function, privacy: .public) - Invalid URL suffix: \(urlString, privacy: .public)") - return false - } - return true -} - -func isVersionNewer(_ oldVersion: String, _ newVersion: String) -> Bool { - let oldVersions = oldVersion.components(separatedBy: ".") - let newVersions = newVersion.components(separatedBy: ".") - for (index, version) in newVersions.enumerated() { - let a = Int(version) ?? 0 - let oldVersionValue = oldVersions.indices.contains(index) ? oldVersions[index] : "0" - let b = Int(oldVersionValue) ?? 0 - if a > b { - return true - } - if a < b { - return false - } - } - return false -} - -func isEncoded(_ str: String) -> Bool { - if let decoded = str.removingPercentEncoding { - return decoded != str - } - return false -} - -// parser REs - force try b/c pattern is known to be valid regex -let re0 = try! NSRegularExpression(pattern: #"(?:(\/\/ ==UserScript==[ \t]*?\r?\n([\S\s]*?)\r?\n\/\/ ==\/UserScript==)([\S\s]*)|(\/\* ==UserStyle==[ \t]*?\r?\n([\S\s]*?)\r?\n==\/UserStyle== \*\/)([\S\s]*))"#, options: []) -// RE for meta line -let re1 = try! NSRegularExpression(pattern: #"^(?:[ \t]*(?:\/\/)?[ \t]*@)([\w-]+)[ \t]+([^\s]+[^\r\n\t\v\f]*)"#, options: []) -// this pattern checks for specific keys that won't have values -let re2 = try! NSRegularExpression(pattern: #"^(?:[ \t]*(?:\/\/)?[ \t]*@)(noframes)[ \t]*$"#, options: []) - -// parser -func parse(_ content: String) -> [String: Any]? { - // returns structured data from content of file - // will fail to parse if metablock or required @name key missing - let range = NSRange(location: 0, length: content.utf16.count) - // return nil/fail if metablock missing - guard let match = re0.firstMatch(in: content, options: [], range: range) else { - logger?.debug("\(#function, privacy: .public) - Non matched content: \(content, privacy: .public)") - return nil - } - - // at this point the text content has passed initial validation, it contains valid metadata - // the metadata can be in userscript or userstyle format, need to check for this and adjust group numbers - // rather than being too strict, text content can precede the opening userscript tag, however it will be ignored - // adjust start index of file content while assigning group numbers to account for any text content preceding opening tag - let contentStartIndex = content.index(content.startIndex, offsetBy: match.range.lowerBound) - let contentEndIndex = content.index(contentStartIndex, offsetBy: 15) - let metaHeadContent = content[contentStartIndex.. Bool { - let content = data - let url = getDocumentsDirectory().appendingPathComponent("manifest.json") - do { - let encoder = JSONEncoder() - encoder.outputFormatting = .prettyPrinted - let encoded = try encoder.encode(content) - let fileContent = String(decoding: encoded, as: UTF8.self) - try fileContent.write(to: url, atomically: false, encoding: .utf8) - return true - } catch { - logger?.error("\(#function, privacy: .public) - failed to update manifest: \(error, privacy: .public)") - return false - } -} - -func getManifest() -> Manifest { - let url = getDocumentsDirectory().appendingPathComponent("manifest.json") - if - let content = try? String(contentsOf: url, encoding: .utf8), - let data = content.data(using: .utf8), - let decoded = try? JSONDecoder().decode(Manifest.self, from: Data(data)) - { - return decoded - } else { - // manifest missing, improperly formatted or missing key - // create new manifest with default key/vals - let manifest = Manifest( - blacklist: [], - declarativeNetRequest: [], - disabled: [], - exclude: [:], - excludeMatch: [:], - include: [:], - match: [:], - require: [:], - settings: defaultSettings - ) - _ = updateManifest(with: manifest) - return manifest - } -} - -func updateManifestMatches(_ optionalFilesArray: [[String: Any]] = []) -> Bool { - logger?.info("\(#function, privacy: .public) - started") - // only get all files if files were not provided - var files = [[String: Any]]() - if optionalFilesArray.isEmpty { - guard let getFiles = getAllFiles() else {return false} - files = getFiles - } else { - files = optionalFilesArray - } - var manifest = getManifest() - for file in files { - // can be force unwrapped because getAllFiles didn't return nil - let metadata = file["metadata"] as! [String: [String]] - let filename = file["filename"] as! String - // skip request type userscripts - let runAt = metadata["run-at"]?[0] ?? "document-end" - if runAt == "request" { - continue - } - // populate excludes & matches - var excludeMatched = [String]() - var matched = [String]() - var excluded = [String]() - var included = [String]() - if metadata["exclude-match"] != nil { - excludeMatched.append(contentsOf: metadata["exclude-match"]!) - } - if metadata["match"] != nil { - matched.append(contentsOf: metadata["match"]!) - } - if metadata["include"] != nil { - included.append(contentsOf: metadata["include"]!) - } - if metadata["exclude"] != nil { - excluded.append(contentsOf: metadata["exclude"]!) - } - // if in declarativeNetRequest array, remove it - if manifest.declarativeNetRequest.contains(filename) { - if let index = manifest.declarativeNetRequest.firstIndex(of: filename) { - manifest.declarativeNetRequest.remove(at: index) - } else { - logger?.error("\(#function, privacy: .public) - failed to remove \(filename, privacy: .public) from dNR array") - } - } - - // update manifest values - manifest.excludeMatch = updatePatternDict(filename, excludeMatched, manifest.excludeMatch) - manifest.match = updatePatternDict(filename, matched, manifest.match) - manifest.exclude = updatePatternDict(filename, excluded, manifest.exclude) - manifest.include = updatePatternDict(filename, included, manifest.include) - - if !updateManifest(with: manifest) { - logger?.error("\(#function, privacy: .public) - failed to update manifest matches") - return false - } - } - logger?.info("\(#function, privacy: .public) - completed") - return true -} - -func updatePatternDict(_ filename: String, _ filePatterns: [String], _ manifestKeys: [String: [String]]) -> [String: [String]] { - // will hold the exclude/match patterns in manifest that have file name as value - var patternsInManifestForFile = [String]() - // new var from func argument, so it can be manipulated - var returnDictionary = manifestKeys - // patterns from manifest - let keys = returnDictionary.keys - // determine what patterns already have this filename as a value - for key in keys { - // key is an array of filenames - guard let filenames = returnDictionary[key] else { - logger?.error("\(#function, privacy: .public) - failed to get values for manifest key, \(key, privacy: .public)") - continue - } - for name in filenames { - // name is a single filename - // if name is same as filename, file already added for this pattern - // add it to patternsInManifestForFile for later comparison - if name == filename { - patternsInManifestForFile.append(key) - } - } - } - // patterns in file metadata and patterns in manifest that have filename as a value - // filename already present in manifest for these patterns, do nothing with these - // let common = filePatterns.filter{patternsInManifestForFile.contains($0)} - // patterns in file metadata, but don't have the filename as a value within the manifest - // these are the manifest patterns that the filename needs to be added to - let addFilenameTo = filePatterns.filter{!patternsInManifestForFile.contains($0)} - - // the patterns that have the filename as a value, but not present in file metadata - // ie. these are the manifest patterns we need to remove the filename from - let removeFilenameFrom = patternsInManifestForFile.filter{!filePatterns.contains($0)} - - // check if filename needs to be added or new key/val needs to be created - for pattern in addFilenameTo { - if returnDictionary[pattern] != nil { - returnDictionary[pattern]?.append(filename) - } else { - returnDictionary[pattern] = [filename] - } - } - - for pattern in removeFilenameFrom { - // get the index of the filename within the array - let ind = returnDictionary[pattern]?.firstIndex(of: filename) - // remove filename from array by index - returnDictionary[pattern]?.remove(at: ind!) - // if filename was the last item in array, remove the url pattern from dictionary - if returnDictionary[pattern]!.isEmpty { - returnDictionary.removeValue(forKey: pattern) - } - } - - return returnDictionary -} - -func updateManifestRequired(_ optionalFilesArray: [[String: Any]] = []) -> Bool { - logger?.info("\(#function, privacy: .public) - started") - // only get all files if files were not provided - var files = [[String: Any]]() - if optionalFilesArray.isEmpty { - guard let getFiles = getAllFiles() else { - logger?.info("\(#function, privacy: .public) - count not get files") - return false - } - files = getFiles - } else { - files = optionalFilesArray - } - logger?.info("\(#function, privacy: .public) - will loop through \(files.count, privacy: .public)") - var manifest = getManifest() - for file in files { - // can be force unwrapped because getAllFiles didn't return nil - let filename = file["filename"] as! String - let metadata = file["metadata"] as! [String: [String]] - let type = file["type"] as! String - let required = metadata["require"] ?? [] - logger?.info("\(#function, privacy: .public) - begin \(filename, privacy: .public)") - // get required resources for file, if fail, skip updating manifest - if !getRequiredCode(filename, required, type) { - logger?.error("\(#function, privacy: .public) - couldn't fetch remote content for \(filename, privacy: .public)") - continue - } - - // create filenames from sanitized resource urls - // getRequiredCode does the same thing when saving to disk - // populate array with entries for manifest - var r = [String]() - for resource in required { - let sanitizedResourceName = sanitize(resource) - r.append(sanitizedResourceName) - } - - // if there are values, write them to manifest - // if failed to write to manifest, continue to next file & log error - if !r.isEmpty && r != manifest.require[filename] { - manifest.require[filename] = r - if !updateManifest(with: manifest) { - logger?.error("\(#function, privacy: .public) - couldn't update manifest when getting required resources") - } - } - logger?.info("\(#function, privacy: .public) - end \(filename, privacy: .public)") - } - logger?.info("\(#function, privacy: .public) - completed") - return true -} - -func updateManifestDeclarativeNetRequests(_ optionalFilesArray: [[String: Any]] = []) -> Bool { - logger?.info("\(#function, privacy: .public) - started") - var files = [[String: Any]]() - if optionalFilesArray.isEmpty { - guard let getFiles = getAllFiles() else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return false - } - files = getFiles - } else { - files = optionalFilesArray - } - var manifest = getManifest() - for file in files { - // can be force unwrapped because getAllFiles didn't return nil - // and getAllFiles always returns the following - let metadata = file["metadata"] as! [String: [String]] - let filename = file["filename"] as! String - let runAt = metadata["run-at"]?[0] ?? "document-end" - // if not a request type, ignore - if runAt != "request" { - continue - } - var update = false - // if filename already in manifest - if !manifest.declarativeNetRequest.contains(filename) { - manifest.declarativeNetRequest.append(filename) - update = true - } - // if filename in another array remove it - for (pattern, filenames) in manifest.match { - for fn in filenames { - if fn == filename, let index = manifest.match[pattern]?.firstIndex(of: filename) { - manifest.match[pattern]?.remove(at: index) - update = true - } - } - } - for (pattern, filenames) in manifest.excludeMatch { - for fn in filenames { - if fn == filename, let index = manifest.excludeMatch[pattern]?.firstIndex(of: filename) { - manifest.excludeMatch[pattern]?.remove(at: index) - update = true - } - } - } - for (pattern, filenames) in manifest.include { - for fn in filenames { - if fn == filename, let index = manifest.include[pattern]?.firstIndex(of: filename) { - manifest.include[pattern]?.remove(at: index) - update = true - } - } - } - for (pattern, filenames) in manifest.exclude { - for fn in filenames { - if fn == filename, let index = manifest.exclude[pattern]?.firstIndex(of: filename) { - manifest.exclude[pattern]?.remove(at: index) - update = true - } - } - } - if update, !updateManifest(with: manifest) { - logger?.error("\(#function, privacy: .public) - failed at (2)") - return false - } - } - logger?.info("\(#function, privacy: .public) - completed") - return true -} - -func purgeManifest(_ optionalFilesArray: [[String: Any]] = []) -> Bool { - logger?.info("\(#function, privacy: .public) - started") - // purge all manifest keys of any stale entries - var update = false, manifest = getManifest(), allSaveLocationFilenames = [String]() - // only get all files if files were not provided - var allFiles = [[String: Any]]() - if optionalFilesArray.isEmpty { - // if getAllFiles fails to return, ignore and pass an empty array - let getFiles = getAllFiles() ?? [] - allFiles = getFiles - } else { - allFiles = optionalFilesArray - } - // populate array with filenames - for file in allFiles { - if let filename = file["filename"] as? String { - allSaveLocationFilenames.append(filename) - } - } - // loop through manifest keys, if no file exists for value, remove value from manifest - // if there are no more filenames in pattern, remove pattern from manifest - for (pattern, filenames) in manifest.match { - for filename in filenames { - if !allSaveLocationFilenames.contains(filename) { - if let index = manifest.match[pattern]?.firstIndex(of: filename) { - manifest.match[pattern]?.remove(at: index) - update = true - logger?.info("\(#function, privacy: .public) - Could not find \(filename, privacy: .public) in save location, removed from match pattern - \(pattern, privacy: .public)") - } - } - } - if let length = manifest.match[pattern]?.count { - if length < 1, let ind = manifest.match.index(forKey: pattern) { - manifest.match.remove(at: ind) - logger?.info("\(#function, privacy: .public) - No more files for \(pattern, privacy: .public) match pattern, removed from manifest") - } - } - } - for (pattern, filenames) in manifest.excludeMatch { - for filename in filenames { - if !allSaveLocationFilenames.contains(filename) { - if let index = manifest.excludeMatch[pattern]?.firstIndex(of: filename) { - manifest.excludeMatch[pattern]?.remove(at: index) - update = true - logger?.info("\(#function, privacy: .public) - Could not find \(filename, privacy: .public) in save location, removed from exclude-match pattern - \(pattern, privacy: .public)") - } - } - } - if let length = manifest.excludeMatch[pattern]?.count { - if length < 1, let ind = manifest.excludeMatch.index(forKey: pattern) { - manifest.excludeMatch.remove(at: ind) - logger?.info("\(#function, privacy: .public) - No more files for \(pattern, privacy: .public) exclude-match pattern, removed from manifest") - } - } - } - for (pattern, filenames) in manifest.exclude { - for filename in filenames { - if !allSaveLocationFilenames.contains(filename) { - if let index = manifest.exclude[pattern]?.firstIndex(of: filename) { - manifest.exclude[pattern]?.remove(at: index) - update = true - logger?.info("\(#function, privacy: .public) - Could not find \(filename, privacy: .public) in save location, removed from exclude pattern - \(pattern, privacy: .public)") - } - } - } - if let length = manifest.exclude[pattern]?.count { - if length < 1, let ind = manifest.exclude.index(forKey: pattern) { - manifest.exclude.remove(at: ind) - logger?.info("\(#function, privacy: .public) - No more files for \(pattern, privacy: .public) exclude pattern, removed from manifest") - } - } - } - for (pattern, filenames) in manifest.include { - for filename in filenames { - if !allSaveLocationFilenames.contains(filename) { - if let index = manifest.include[pattern]?.firstIndex(of: filename) { - manifest.include[pattern]?.remove(at: index) - update = true - logger?.info("\(#function, privacy: .public) - Could not find \(filename, privacy: .public) in save location, removed from exclude pattern - \(pattern, privacy: .public)") - } - } - } - if let length = manifest.include[pattern]?.count { - if length < 1, let ind = manifest.include.index(forKey: pattern) { - manifest.include.remove(at: ind) - logger?.info("\(#function, privacy: .public) - No more files for \(pattern, privacy: .public) exclude pattern, removed from manifest") - } - } - } - // loop through manifest required - for (filename, _) in manifest.require { - if !allSaveLocationFilenames.contains(filename) { - if let index = manifest.require.index(forKey: filename) { - manifest.require.remove(at: index) - // remove associated resources - if !getRequiredCode(filename, [], (filename as NSString).pathExtension) { - logger?.error("\(#function, privacy: .public) - failed to remove required resources when purging \(filename, privacy: .public) from manifest required records") - } - update = true - logger?.info("\(#function, privacy: .public) - No more required resources for \(filename, privacy: .public), removed from manifest along with resource folder") - } - } - } - // loop through manifest disabled - for filename in manifest.disabled { - if !allSaveLocationFilenames.contains(filename) { - if let index = manifest.disabled.firstIndex(of: filename) { - manifest.disabled.remove(at: index) - update = true - logger?.info("\(#function, privacy: .public) - Could not find \(filename, privacy: .public) in save location, removed from disabled") - } - } - } - // loop through manifest declarativeNetRequest - for filename in manifest.declarativeNetRequest { - if !allSaveLocationFilenames.contains(filename) { - if let index = manifest.declarativeNetRequest.firstIndex(of: filename) { - manifest.declarativeNetRequest.remove(at: index) - update = true - logger?.info("\(#function, privacy: .public) - Could not find \(filename, privacy: .public) in save location, removed from dNR") - } - } - } - // remove obsolete settings - for setting in manifest.settings { - if !defaultSettings.keys.contains(setting.key) { - manifest.settings.removeValue(forKey: setting.key) - update = true - logger?.info("\(#function, privacy: .public) - Removed obsolete setting - \(setting.key, privacy: .public)") - } - } - if update, !updateManifest(with: manifest) { - logger?.error("\(#function, privacy: .public) - failed to purge manifest") - return false - } - logger?.info("\(#function, privacy: .public) - completed") - return true -} - -// settings -func checkSettings() -> Bool { - // iterate over default settings and individually check if each present - // if missing add setting to manifest about to be returned - // missing keys will occur when new settings introduced - var manifest = getManifest() - var update = false - for (key, value) in defaultSettings { - if manifest.settings[key] == nil { - manifest.settings[key] = value - update = true - } - } - if update, !updateManifest(with: manifest) { - logger?.error("\(#function, privacy: .public) - failed to update manifest settings") - return false - } - return true -} - -func updateSettings(_ settings: [String: String]) -> Bool { - var manifest = getManifest() - manifest.settings = settings - if updateManifest(with: manifest) != true { - logger?.error("\(#function, privacy: .public) - failed to update settings") - return false - } - return true -} - -// files -func getAllFiles(includeCode: Bool = false) -> [[String: Any]]? { - logger?.info("\(#function, privacy: .public) - started") - // returns all files of proper type with filenames, metadata & more - var files = [[String: Any]]() - let fm = FileManager.default - let manifest = getManifest() - guard let saveLocation = getSaveLocation() else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return nil - } - // security scope - let didStartAccessing = saveLocation.startAccessingSecurityScopedResource() - defer { - if didStartAccessing {saveLocation.stopAccessingSecurityScopedResource()} - } - // get all file urls within save location - guard let urls = try? fm.contentsOfDirectory(at: saveLocation, includingPropertiesForKeys: []) else { - logger?.error("\(#function, privacy: .public) - failed at (2)") - return nil - } - for url in urls { - var fileData = [String: Any]() - // only read contents for css & js files - let filename = url.lastPathComponent - if (!filename.hasSuffix(".css") && !filename.hasSuffix(".js")) { - continue - } - // file will be skipped if metablock is missing - guard - let content = try? String(contentsOf: url, encoding: .utf8), - let dateMod = try? fm.attributesOfItem(atPath: url.path)[.modificationDate] as? Date, - let parsed = parse(content), - let metadata = parsed["metadata"] as? [String: [String]], - let type = filename.split(separator: ".").last - else { - logger?.info("\(#function, privacy: .public) - ignoring \(filename, privacy: .public), file missing or metadata missing from file contents") - continue - } - fileData["canUpdate"] = false - fileData["content"] = content - fileData["disabled"] = manifest.disabled.contains(filename) - fileData["filename"] = filename - fileData["lastModified"] = dateToMilliseconds(dateMod) - fileData["metadata"] = metadata - // force unwrap name since parser ensure it exists - fileData["name"] = metadata["name"]![0] - fileData["type"] = "\(type)" - // add extra data if a request userscript - let runAt = metadata["run-at"]?[0] ?? "document-end" - if runAt == "request" { - fileData["request"] = true - } - if metadata["description"] != nil { - fileData["description"] = metadata["description"]![0] - } - if metadata["version"] != nil && metadata["updateURL"] != nil { - fileData["canUpdate"] = true - } - fileData["noframes"] = metadata["noframes"] != nil ? true : false - // if asked, also return the code string - if (includeCode) { - // can force unwrap because always returned from parser - fileData["code"] = parsed["code"] as! String - } - files.append(fileData) - } - logger?.info("\(#function, privacy: .public) - completed") - return files -} - -func getRequiredCode(_ filename: String, _ resources: [String], _ fileType: String) -> Bool { - let directory = getRequireLocation().appendingPathComponent(filename) - // if file requires no resource but directory exists, remove it - // this resource is not user-generated and can be downloaded again, so just remove it instead of moves to the trash - // also in ios, the volume “Data” has no trash and item can only be removed directly - if resources.isEmpty { - if FileManager.default.fileExists(atPath: directory.path) { - do { - try FileManager.default.removeItem(at: directory) - } catch { - logger?.error("\(#function, privacy: .public) - failed to remove directory: \(error, privacy: .public)") - } - } - return true - } - // record URLs for subsequent processing - var resourceUrls = Set() - // loop through resource urls and attempt to fetch it - for resourceUrlString in resources { - // get the path of the url string - guard let resourceUrlPath = URLComponents(string: resourceUrlString)?.path else { - // if path can not be obtained, skip and log - logger?.info("\(#function, privacy: .public) - failed to get path on \(filename, privacy: .public) for \(resourceUrlString, privacy: .public)") - continue - } - // skip urls pointing to files of different types - if resourceUrlPath.hasSuffix(fileType) { - let resourceFilename = sanitize(resourceUrlString) - let fileURL = directory.appendingPathComponent(resourceFilename) - // insert url to resolve symlink into set - resourceUrls.insert(fileURL.standardizedFileURL) - // only attempt to get resource if it does not yet exist - if FileManager.default.fileExists(atPath: fileURL.path) {continue} - // get the remote file contents - guard let contents = getRemoteFileContents(resourceUrlString) else {continue} - // check if file specific folder exists at requires directory - if !FileManager.default.fileExists(atPath: directory.path) { - guard ((try? FileManager.default.createDirectory(at: directory, withIntermediateDirectories: false)) != nil) else { - logger?.info("\(#function, privacy: .public) - failed to create required code directory for \(filename, privacy: .public)") - return false - } - } - // finally write file to directory - guard ((try? contents.write(to: fileURL, atomically: false, encoding: .utf8)) != nil) else { - logger?.info("\(#function, privacy: .public) - failed to write content to file for \(filename, privacy: .public) from \(resourceUrlString, privacy: .public)") - return false - } - } - } - // cleanup downloaded files that are no longer required - do { - var downloadedUrls = Set() - // get all downloaded resources url - let fileUrls = try FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: []) - // insert url to resolve symlink into set - for url in fileUrls { downloadedUrls.insert(url.standardizedFileURL) } - // exclude currently required resources - let abandonedUrls = downloadedUrls.subtracting(resourceUrls) - // loop through abandoned urls and attempt to remove it - for abandonFileUrl in abandonedUrls { - do { - try FileManager.default.removeItem(at: abandonFileUrl) - logger?.info("\(#function, privacy: .public) - cleanup abandoned resource: \(unsanitize(abandonFileUrl.lastPathComponent), privacy: .public)") - } catch { - logger?.error("\(#function, privacy: .public) - failed to remove abandoned resource: \(error, privacy: .public)") - } - } - } catch { - logger?.error("\(#function, privacy: .public) - failed to cleanup resources: \(error, privacy: .public)") - } - return true -} - -func checkForRemoteUpdates(_ optionalFilesArray: [[String: Any]] = []) -> [[String: String]]? { - // only get all files if files were not provided - var files = [[String: Any]]() - if optionalFilesArray.isEmpty { - guard let getFiles = getAllFiles() else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return nil - } - files = getFiles - } else { - files = optionalFilesArray - } - - var hasUpdates = [[String: String]]() - for file in files { - // can be force unwrapped because getAllFiles didn't return nil - let filename = file["filename"] as! String - let canUpdate = file["canUpdate"] as! Bool - let metadata = file["metadata"] as! [String: [String]] - let type = file["type"] as! String - let name = metadata["name"]![0] - logger?.info("\(#function, privacy: .public) - Checking for remote updates for \(filename, privacy: .public)") - if canUpdate { - let currentVersion = metadata["version"]![0] - let updateUrl = metadata["updateURL"]![0] - // before fetching remote contents, ensure it points to a file of the same type - if !validateUrl(updateUrl) {continue} - guard - let remoteFileContents = getRemoteFileContents(updateUrl), - let remoteFileContentsParsed = parse(remoteFileContents), - let remoteMetadata = remoteFileContentsParsed["metadata"] as? [String: [String]], - let remoteVersion = remoteMetadata["version"]?[0] - else { - logger?.error("\(#function, privacy: .public) - failed to parse remote file contents") - return nil - } - let remoteVersionNewer = isVersionNewer(currentVersion, remoteVersion) - if remoteVersionNewer { - hasUpdates.append(["name": name, "filename": filename, "type": type, "url": updateUrl]) - } - } - } - logger?.info("\(#function, privacy: .public) - Finished checking for remote updates for \(files.count, privacy: .public) files") - return hasUpdates -} - -func getRemoteFileContents(_ url: String) -> String? { - logger?.info("\(#function, privacy: .public) - started for \(url, privacy: .public)") - // if url is http change to https - var urlChecked = url - if urlChecked.hasPrefix("http:") { - urlChecked = urlChecked.replacingOccurrences(of: "http:", with: "https:") - logger?.info("\(#function, privacy: .public) - \(url, privacy: .public) is using insecure http, attempt to fetch remote content with https") - } - // convert url string to url - guard let solidURL = fixedURL(string: urlChecked) else { - logger?.error("\(#function, privacy: .public) - failed at (1), invalid URL: \(url, privacy: .public)") - return nil - } - var contents = "" - // get remote file contents, synchronously - let semaphore = DispatchSemaphore(value: 0) - var task: URLSessionDataTask? - task = URLSession.shared.dataTask(with: solidURL) { data, response, error in - if let r = response as? HTTPURLResponse, data != nil, error == nil { - if r.statusCode == 200 { - contents = String(data: data!, encoding: .utf8) ?? "" - } else { - logger?.error("\(#function, privacy: .public) - http statusCode (\(r.statusCode, privacy: .public)): \(url, privacy: .public)") - } - } - if let error = error { - logger?.error("\(#function, privacy: .public) - task error: \(error, privacy: .public) (\(url, privacy: .public))") - } - semaphore.signal() - } - task?.resume() - // wait 30 seconds before timing out - if semaphore.wait(timeout: .now() + 30) == .timedOut { - task?.cancel() - logger?.error("\(#function, privacy: .public) - 30 seconds timeout: \(url, privacy: .public)") - } - - // if made it to this point and contents still an empty string, something went wrong with the request - if contents.isEmpty { - logger?.error("\(#function, privacy: .public) - failed at (2), contents empty: \(url, privacy: .public)") - return nil - } - logger?.info("\(#function, privacy: .public) - completed for \(url, privacy: .public)") - return contents -} - -func updateAllFiles(_ optionalFilesArray: [[String: Any]] = []) -> Bool { - // get names of all files with updates available - guard - let filesWithUpdates = checkForRemoteUpdates(optionalFilesArray), - let saveLocation = getSaveLocation() - else { - logger?.error("\(#function, privacy: .public) - failed to update files (1)") - return false - } - // security scope - let didStartAccessing = saveLocation.startAccessingSecurityScopedResource() - defer { - if didStartAccessing {saveLocation.stopAccessingSecurityScopedResource()} - } - for file in filesWithUpdates { - // can be force unwrapped because checkForRemoteUpdates didn't return nil - let filename = file["filename"]! - let fileUrl = saveLocation.appendingPathComponent(filename) - guard - let content = try? String(contentsOf: fileUrl, encoding: .utf8), - let parsed = parse(content), - let metadata = parsed["metadata"] as? [String: [String]], - let updateUrl = metadata["updateURL"]?[0] - else { - logger?.error("\(#function, privacy: .public) - failed to update files (2)") - continue - } - let downloadUrl = metadata["downloadURL"] != nil ? metadata["downloadURL"]![0] : updateUrl - guard - let remoteFileContents = getRemoteFileContents(downloadUrl), - ((try? remoteFileContents.write(to: fileUrl, atomically: false, encoding: .utf8)) != nil) - else { - logger?.error("\(#function, privacy: .public) - failed to update files (3)") - continue - } - logger?.info("\(#function, privacy: .public) - updated \(filename, privacy: .public) with contents fetched from \(downloadUrl, privacy: .public)") - } - return true -} - -func toggleFile(_ filename: String,_ action: String) -> Bool { - // if file doesn't exist return false - guard let saveLocation = getSaveLocation() else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return false - } - let didStartAccessing = saveLocation.startAccessingSecurityScopedResource() - defer { - if didStartAccessing {saveLocation.stopAccessingSecurityScopedResource()} - } - let path = saveLocation.appendingPathComponent(filename).path - if !FileManager.default.fileExists(atPath: path) { - logger?.error("\(#function, privacy: .public) - failed at (2)") - return false - } - var manifest = getManifest() - // if file is already disabled - if action == "disable" && manifest.disabled.contains(filename) || action == "enabled" && !manifest.disabled.contains(filename) { - return true - } - // add filename to disabled array if disabling - if (action == "disable") {manifest.disabled.append(filename)} - // remove filename from disabled array if enabling - if (action == "enable") { - guard let index = manifest.disabled.firstIndex(of: filename) else { - logger?.error("\(#function, privacy: .public) - failed at (3)") - return false - } - manifest.disabled.remove(at: index) - } - if !updateManifest(with: manifest) { - logger?.error("\(#function, privacy: .public) - failed at (4)") - return false - } - return true -} - -func checkDefaultDirectories() -> Bool { - let defaultSaveLocation = getDocumentsDirectory().appendingPathComponent("scripts") - let requireLocation = getRequireLocation() - let urls = [defaultSaveLocation, requireLocation] - for url in urls { - if !FileManager.default.fileExists(atPath: url.path) { - do { - try FileManager.default.createDirectory(at: url, withIntermediateDirectories: false) - } catch { - // could not create the save location directory, show error - logger?.error("\(#function, privacy: .public) - failed at (1) - \(url, privacy: .public) - \(error, privacy: .public)") - return false - } - } - } - return true -} - -// matching -func stringToRegex(_ stringPattern: String) -> NSRegularExpression? { - let pattern = #"[\.|\?|\^|\$|\+|\{|\}|\[|\]|\||\\(|\)|\/]"# - var patternReplace = "^\(stringPattern.replacingOccurrences(of: pattern, with: #"\\$0"#, options: .regularExpression))$" - patternReplace = patternReplace.replacingOccurrences(of: "*", with: ".*") - guard let regex = try? NSRegularExpression(pattern: patternReplace, options: .caseInsensitive) else { - return nil - } - return regex -} - -// RE for parse matchPattern -let re3 = try! NSRegularExpression(pattern: #"^(http:|https:|\*:)\/\/((?:\*\.)?(?:[a-z0-9-]+\.)+(?:[a-z0-9]+)|\*\.[a-z]+|\*|[a-z0-9]+)(\/[^\s]*)$"#, options: .caseInsensitive) - -func match(_ url: String, _ matchPattern: String) -> Bool { - guard - let parts = jsLikeURL(url), - let ptcl = parts["protocol"], - let host = parts["hostname"], - var path = parts["pathname"] - else { - logger?.error("\(#function, privacy: .public) - invalid url \(url, privacy: .public)") - return false - } - - // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns#path - // The value for the path matches against the string which is the URL path plus the URL query string - if let search = parts["search"], search.count > 0 { - path += search - } - - // matchPattern is the value from metatdata key @match or @exclude-match - if (matchPattern == "") { - return true - } - // currently only http/s supported - if (ptcl != "http:" && ptcl != "https:") { - return false - } - let range = NSMakeRange(0, matchPattern.utf16.count) - guard let parts = re3.firstMatch(in: matchPattern, options: [], range: range) else { - logger?.error("\(#function, privacy: .public) - malformed regex match pattern - \(matchPattern, privacy: .public)") - return false - } - // ensure url protocol matches pattern protocol - let protocolPattern = matchPattern[Range(parts.range(at: 1), in: matchPattern)!] - if (protocolPattern != "*:" && ptcl != protocolPattern) { - return false - } - // construct host regex from matchPattern - let matchPatternHost = matchPattern[Range(parts.range(at: 2), in: matchPattern)!] - var hostPattern = "^\(matchPatternHost.replacingOccurrences(of: ".", with: "\\."))$" - hostPattern = hostPattern.replacingOccurrences(of: "^*$", with: ".*") - hostPattern = hostPattern.replacingOccurrences(of: "*\\.", with: "(.*\\.)?") - guard let hostRegEx = try? NSRegularExpression(pattern: hostPattern, options: .caseInsensitive) else { - logger?.error("\(#function, privacy: .public) - invalid host regex") - return false - } - // construct path regex from matchPattern - let matchPatternPath = matchPattern[Range(parts.range(at: 3), in: matchPattern)!] - guard let pathRegEx = stringToRegex(String(matchPatternPath)) else { - logger?.error("\(#function, privacy: .public) - invalid path regex") - return false - } - guard - (hostRegEx.firstMatch(in: host, options: [], range: NSMakeRange(0, host.utf16.count)) != nil), - (pathRegEx.firstMatch(in: path, options: [], range: NSMakeRange(0, path.utf16.count)) != nil) - else { - return false - } - - return true -} - -func include(_ url: String,_ pattern: String) -> Bool { - var regex:NSRegularExpression - if pattern.hasPrefix("/") && pattern.hasSuffix("/") { - let p = String(pattern.dropFirst().dropLast()) - guard let exp = try? NSRegularExpression(pattern: p, options: .caseInsensitive) else { - logger?.error("\(#function, privacy: .public) - invalid regex") - return false - } - regex = exp - } else { - guard let exp = stringToRegex(pattern) else { - logger?.error("\(#function, privacy: .public) - coudn't convert string to regex") - return false - } - regex = exp - } - if (regex.firstMatch(in: url, options: [], range: NSMakeRange(0, url.utf16.count)) == nil) { - return false - } - return true -} - -func getMatchedFiles(_ url: String, _ optionalManifest: Manifest?, _ checkBlocklist: Bool) -> [String] { - logger?.info("\(#function, privacy: .public) - Getting matched files for \(url, privacy: .private(mask: .hash))") - // logger?.debug("\(#function, privacy: .public) - Getting matched files for \(url, privacy: .public)") - let manifest = optionalManifest ?? getManifest() - - // filenames that should not load for the passed url - // the manifest values from @exclude and @exclude-match populate this set - var excludedFilenames: Set = [] - // filenames that should load for the passed url - // the manifest values from @include and @match populate this set - var matchedFilenames: Set = [] - // all exclude-match patterns from manifest - let excludeMatchPatterns = manifest.excludeMatch.keys - // all match patterns from manifest - let matchPatterns = manifest.match.keys - // all include expressions from manifest - let includeExpressions = manifest.include.keys - // all exclude expressions from manifest - let excludeExpressions = manifest.exclude.keys - - // if url matches a pattern in blocklist, no injection for this url - if (checkBlocklist) { - for pattern in manifest.blacklist { - if match(url, pattern) { - // return empty array - return Array(matchedFilenames) - } - } - } - - // loop through all the @exclude-match patterns - // if any match passed url, push all filenames to excludedFilenames set - for pattern in excludeMatchPatterns { - if match(url, pattern) { - guard let filenames = manifest.excludeMatch[pattern] else { - logger?.error("\(#function, privacy: .public) - failed at (2) for \(pattern, privacy: .public)") - continue - } - excludedFilenames = excludedFilenames.union(filenames) - } - } - for exp in excludeExpressions { - if include(url, exp) { - guard let filenames = manifest.exclude[exp] else { - logger?.error("\(#function, privacy: .public) - failed at (3) for \(exp, privacy: .public)") - continue - } - excludedFilenames = excludedFilenames.union(filenames) - } - } - for pattern in matchPatterns { - if match(url, pattern) { - guard let filenames = manifest.match[pattern] else { - logger?.error("\(#function, privacy: .public) - failed at (4) for \(pattern, privacy: .public)") - continue - } - matchedFilenames = matchedFilenames.union(filenames) - } - } - for exp in includeExpressions { - if include(url, exp) { - guard let filenames = manifest.include[exp] else { - logger?.error("\(#function, privacy: .public) - failed at (5) for \(exp, privacy: .public)") - continue - } - matchedFilenames = matchedFilenames.union(filenames) - } - } - matchedFilenames = matchedFilenames.subtracting(excludedFilenames) - logger?.info("\(#function, privacy: .public) - Got \(matchedFilenames.count) matched files for \(url, privacy: .private(mask: .hash))") - // logger?.debug("\(#function, privacy: .public) - Got \(matchedFilenames.count) matched files for \(url, privacy: .public)") - return Array(matchedFilenames) -} - -// injection -func getCode(_ filenames: [String], _ isTop: Bool)-> [String: Any]? { - var cssFiles = [Any]() - var jsFiles = [Any]() - var menuFiles = [Any]() - - guard let saveLocation = getSaveLocation() else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return nil - } - - for filename in filenames { - guard - let contents = getFileContentsParsed(saveLocation.appendingPathComponent(filename)), - var code = contents["code"] as? String, - let type = filename.split(separator: ".").last - else { - // if guard fails, log error continue to next file - logger?.error("\(#function, privacy: .public) - failed at (2) for \(filename, privacy: .public)") - continue - } - // can force unwrap b/c getFileContentsParsed ensures metadata exists - let metadata = contents["metadata"] as! [String: [String]] - let name = metadata["name"]![0] - - // if metadata has noframes option and the url is not the top window, don't load - if (metadata["noframes"] != nil && !isTop) { - continue - } - - // get run-at values and set default if missing - // if type request, ignore - var runAt = metadata["run-at"]?[0] ?? "document-end" - if runAt == "request" { - continue - } - - // normalize weight - var weight = metadata["weight"]?[0] ?? "1" - weight = normalizeWeight(weight) - - // get inject-into and set default if missing - var injectInto = metadata["inject-into"]?[0] ?? "auto" - let injectVals: Set = ["auto", "content", "page"] - let runAtVals: Set = ["context-menu", "document-start", "document-end", "document-idle"] - let validGrants: Set = [ - "GM.info", - "GM_info", - "GM.addStyle", - "GM.openInTab", - "GM.closeTab", - "GM.setValue", - "GM.getValue", - "GM.deleteValue", - "GM.listValues", - "GM.setClipboard", - "GM.getTab", - "GM.saveTab", - "GM_xmlhttpRequest", - "GM.xmlHttpRequest" - ] - // if either is invalid use default value - if !injectVals.contains(injectInto) { - injectInto = "auto" - } - if !runAtVals.contains(runAt) { - runAt = "document-end" - } - - // attempt to get all @grant value - var grants = metadata["grant"] ?? [] - - if !grants.isEmpty { - if grants.contains("none") { - // `@grant none` takes precedence - grants = [] - } else { - // remove duplicates - grants = Array(Set(grants)) - // filter out grant values that are not in validGrant set - grants = grants.filter{validGrants.contains($0)} - } - } - - - // set GM.info data - let description = metadata["description"]?[0] ?? "" - let excludes = metadata["exclude"] ?? [] - let excludeMatches = metadata["exclude-match"] ?? [] - let icon = metadata["icon"]?[0] ?? "" - let includes = metadata["include"] ?? [] - let matches = metadata["match"] ?? [] - let requires = metadata["require"] ?? [] - let version = metadata["version"]?[0] ?? "" - let noframes = metadata["noframes"] != nil ? true : false - var scriptObject:[String: Any] = [ - "description": description, - "excludes": excludes, - "exclude-match": excludeMatches, - "filename": filename, - "grant": grants, - "icon": icon, - "includes": includes, - "inject-into": injectInto, - "matches": matches, - "name": name, - "noframes": noframes, - "namespace": "", - "resources": "", - "require": requires, - "run-at": runAt, - "version": version - ] - // certain metadata keys use a different key name then the actual key name - // for compatibility keeping this when applicable, although the rationale is not clear to me - // for unique keys passed to scriptObject, using the same key name that is present in actual userscript - // this key map is used to check for existence of keys in next loop - let keyMap = [ - "exclude": "excludes", - "include": "includes", - "match": "matches", - "resource": "resources", - ] - for metaline in metadata { - let key = keyMap[metaline.key] ?? metaline.key - if !scriptObject.keys.contains(key) { - let value = metaline.value - // metalines without values aren't included in parsed metadata object - // the only exception is @noframes - scriptObject[key] = !value.isEmpty ? value : value[0] - } - } - let scriptMetaStr = contents["metablock"] as? String ?? "??" - - // attempt to get require resource from disk - // if required resource is inaccessible, log error and continue - if let required = metadata["require"] { - // reverse required metadata - // if required is ["A", "B", "C"], C gets added above B which is above A, etc.. - // the reverse of that is desired - for require in required.reversed() { - let sanitizedName = sanitize(require) - let requiredFileURL = getRequireLocation().appendingPathComponent(filename).appendingPathComponent(sanitizedName) - if let requiredContent = try? String(contentsOf: requiredFileURL, encoding: .utf8) { - code = "\(requiredContent)\n\(code)" - } else { - logger?.error("\(#function, privacy: .public) - failed at (3) for \(require, privacy: .public)") - } - } - } - - if type == "css" { - cssFiles.append([ - "code": code, - "filename": filename, - "name": name, - "type": "css", - "weight": weight - ]) - } else if type == "js" { - if runAt == "context-menu" { - #if os(macOS) - menuFiles.append([ - "code": code, - "scriptMetaStr": scriptMetaStr, - "scriptObject": scriptObject, - "type": "js", - "weight": weight - ]) - #endif - } else { - jsFiles.append([ - "code": code, - "scriptMetaStr": scriptMetaStr, - "scriptObject": scriptObject, - "type": "js", - "weight": weight - ]) - } - } - } - let resp = [ - "files": ["css": cssFiles, "js": jsFiles, "menu": menuFiles], - "scriptHandler": "Userscripts", - "scriptHandlerVersion": Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "??" - ] as [String : Any] - return resp -} - -func getFileContentsParsed(_ url: URL) -> [String: Any]? { - guard let saveLocation = getSaveLocation() else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return nil - } - // security scope - let didStartAccessing = saveLocation.startAccessingSecurityScopedResource() - defer { - if didStartAccessing {saveLocation.stopAccessingSecurityScopedResource()} - } - // check that url is a valid path to a directory or single file - guard - FileManager.default.fileExists(atPath: url.path), - let content = try? String(contentsOf: url, encoding: .utf8), - let parsed = parse(content) - else { - return nil - } - return parsed -} - -func getInjectionFilenames(_ url: String) -> [String]? { - var filenames = [String]() - let manifest = getManifest() - guard let active = manifest.settings["active"] else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return nil - } - // if injection is disabled return empty array - if active != "true" { - return filenames - } - let matched = getMatchedFiles(url, manifest, true) - // filter out all disabled files - filenames = matched.filter{!manifest.disabled.contains($0)} - return filenames -} - -func getRequestScripts() -> [[String: String]]? { - var requestScripts = [[String: String]]() - // check the manifest to see if injection is enabled - let manifest = getManifest() - guard let active = manifest.settings["active"] else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return nil - } - // if not enabled, do not apply any net requests, ie. return empty array - if active != "true" { - return requestScripts - } - guard let files = getAllFiles(includeCode: true) else { - logger?.error("\(#function, privacy: .public) - failed at (2)") - return nil - } - for file in files { - let isRequest = file["request"] as? Bool ?? false - // skip any non-request userscripts - if !isRequest { - continue - } - // can be force unwrapped because getAllFiles always returns these - let name = file["name"] as! String - let code = file["code"] as! String - let filename = file["filename"] as! String - - if !manifest.disabled.contains(filename) { - requestScripts.append(["name": name, "code": code]) - } - } - return requestScripts -} - -func getContextMenuScripts() -> [String: Any]? { - var menuFilenames = [String]() - // check the manifest to see if injection is enabled - let manifest = getManifest() - guard let active = manifest.settings["active"] else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return nil - } - // if not enabled return empty array - if active != "true" { - return ["files": ["menu": []]] - } - // get all files at save location - guard let files = getAllFiles() else { - logger?.error("\(#function, privacy: .public) - failed at (2)") - return nil - } - // loop through files and find @run-at context-menu script filenames - for file in files { - guard let filename = file["filename"] as? String else { - logger?.error("\(#function, privacy: .public) - failed at (3), couldn't get filename") - continue - } - guard let fileMetadata = file["metadata"] as? [String: [String]] else { - logger?.error("\(#function, privacy: .public) - failed at (4), couldn't get metadata for \(filename, privacy: .public)") - continue - } - let runAt = fileMetadata["run-at"]?[0] ?? "document-end" - if runAt != "context-menu" || manifest.disabled.contains(filename) { - continue - } - menuFilenames.append(filename) - } - // get and return script objects for all context-menu scripts - guard let scripts = getCode(menuFilenames, true) else { - logger?.error("\(#function, privacy: .public) - failed at (5)") - return nil - } - return scripts -} - -// popup -func getPopupMatches(_ url: String, _ subframeUrls: [String]) -> [[String: Any]]? { - var matches = [[String: Any]]() - // if the url doesn't start with http/s return empty array - if !url.starts(with: "http://") && !url.starts(with: "https://") { - return matches - } - // get all the files saved to manifest that match the passed url - let matched = getMatchedFiles(url, nil, false) - // get all the files at the save location - guard - let files = getAllFiles() - else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return nil - } - // filter out the files that are present in both files and matched - // force unwrap filename to string since getAllFiles always returns it - matches = files.filter{matched.contains($0["filename"] as! String)} - - // get the subframe url matches - var frameUrlsMatched = [[String: Any]]() - var frameUrlsMatches = [String]() - // filter out the top page url from the frame urls - let frameUrls = subframeUrls.filter{$0 != url} - // for each url just pushed to frameUrls, get all the files saved to manifest that match their url - for frameUrl in frameUrls { - let frameMatches = getMatchedFiles(frameUrl, nil, false) - for frameMatch in frameMatches { - // for the match against the frameUrl, see if it has @noframes - // if so, it should not be appended to frameUrlsMatches - // filter all files for the first one that matches the frameMatch filename - // can force unwrap filename b/c getAllFiles always returns it - let frameMatchMetadata = files.filter{$0["filename"] as! String == frameMatch}.first - // can force unwrap noframes b/c getAllFiles always returns it - let noFrames = frameMatchMetadata?["noframes"] as? Bool ?? false - if !matched.contains(frameMatch) && !noFrames { - frameUrlsMatches.append(frameMatch) - } - } - } - - // filter out the files that are present in both files and frameUrlsMatches - // force unwrap filename to string since getAllFiles always returns it - frameUrlsMatched = files.filter{frameUrlsMatches.contains($0["filename"] as! String)} - // loop through frameUrlsMatched and add subframe key/val - for (index, var frameUrlsMatch) in frameUrlsMatched.enumerated() { - frameUrlsMatch["subframe"] = true - frameUrlsMatched[index] = frameUrlsMatch - } - // add frameUrlsMatched to matches array - matches.append(contentsOf: frameUrlsMatched) - return matches -} - -func popupUpdateAll() -> Bool { - guard - let files = getAllFiles(), - updateAllFiles(files), - updateManifestMatches(files), - updateManifestRequired(files), - purgeManifest(files) - else { - return false - } - return true -} - -func getPopupBadgeCount(_ url: String, _ subframeUrls: [String]) -> Int? { - if !url.starts(with: "http://") && !url.starts(with: "https://") { - return 0 - } - let manifest = getManifest() - guard - var matches = getPopupMatches(url, subframeUrls) - else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return nil - } - for pattern in manifest.blacklist { - if match(url, pattern) { - return 0 - } - } - matches = matches.filter{!manifest.disabled.contains($0["filename"] as! String)} - return matches.count -} - -func popupUpdateSingle(_ filename: String, _ url: String, _ subframeUrls: [String]) -> [[String: Any]]? { - guard let saveLocation = getSaveLocation() else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return nil - } - // security scope - let didStartAccessing = saveLocation.startAccessingSecurityScopedResource() - defer { - if didStartAccessing {saveLocation.stopAccessingSecurityScopedResource()} - } - let fileUrl = saveLocation.appendingPathComponent(filename) - guard - let content = try? String(contentsOf: fileUrl, encoding: .utf8), - let parsed = parse(content), - let metadata = parsed["metadata"] as? [String: [String]], - let updateUrl = metadata["updateURL"]?[0] - else { - logger?.error("\(#function, privacy: .public) - failed at (2)") - return nil - } - let downloadUrl = metadata["downloadURL"] != nil ? metadata["downloadURL"]![0] : updateUrl - guard - let remoteFileContents = getRemoteFileContents(downloadUrl), - ((try? remoteFileContents.write(to: fileUrl, atomically: false, encoding: .utf8)) != nil) - else { - logger?.error("\(#function, privacy: .public) - failed at (3)") - return nil - } - guard - let files = getAllFiles(), - updateManifestMatches(files), - updateManifestRequired(files), - purgeManifest(files), - let matches = getPopupMatches(url, subframeUrls) - else { - logger?.error("\(#function, privacy: .public) - failed at (4)") - return nil - } - return matches -} - -// page -func getInitData() -> [String: Any]? { - guard let saveLocation = getSaveLocation() else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return nil - } - return [ - "saveLocation": saveLocation.path, - "platform": getPlatform(), - "scheme": Bundle.main.infoDictionary?["US_URL_SCHEME"] as! String, - "version": Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "??", - "build": Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "??" - ] -} - -func getLegacyData() -> [String: Any]? { - let manifest = getManifest() - var data:[String: Any] = manifest.settings - data["blacklist"] = manifest.blacklist - return data -} - -func saveFile(_ item: [String: Any],_ content: String) -> [String: Any] { - var response = [String: Any]() - let newContent = content - guard let saveLocation = getSaveLocation() else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return ["error": "failed to get save location when attempting to save"] - } - guard - let oldFilename = item["filename"] as? String, - let type = item["type"] as? String - else { - return ["error": "invalid argument in save function"] - } - guard - let parsed = parse(newContent), - let metadata = parsed["metadata"] as? [String: [String]] - else { - return ["error": "failed to parse metadata"] - } - guard let n = metadata["name"]?[0] else { - return ["error": "@name not found in metadata"] - } - var name = sanitize(n) - - // construct new file name - let newFilename = "\(name).user.\(type)" - - // security scope - let didStartAccessing = saveLocation.startAccessingSecurityScopedResource() - defer { - if didStartAccessing {saveLocation.stopAccessingSecurityScopedResource()} - } - guard - let allFilesUrls = try? FileManager.default.contentsOfDirectory(at: saveLocation, includingPropertiesForKeys: []) - else { - return ["error": "failed to read save urls in save function"] - } - - // validate file before save - var allFilenames:[String] = [] // stores the indv filenames for later comparison - // old and new filenames are equal, overwriting and can skip - if oldFilename.lowercased() != newFilename.lowercased() { - // loop through all the file urls in the save location and save filename to var - for fileUrl in allFilesUrls { - // skip file if it is not of the proper type - let filename = fileUrl.lastPathComponent - if (!filename.hasSuffix(type)) { - continue - } - // if file is of the proper type, add it to the allFilenames array - allFilenames.append(filename.lowercased()) - } - } - - if allFilenames.contains(newFilename.lowercased()) { - return ["error": "filename already taken"] - } - - if newFilename.count > 250 { - return ["error": "filename too long"] - } - - // file passed validation - - // attempt to save to disk - let newFileUrl = saveLocation.appendingPathComponent(newFilename) - do { - try newContent.write(to: newFileUrl, atomically: false, encoding: .utf8) - } catch { - logger?.error("\(#function, privacy: .public) - failed at (2)") - return ["error": "failed to write file to disk"] - } - - // saved to disk successfully - - // get the file last modified date - guard - let dateMod = try? FileManager.default.attributesOfItem(atPath: newFileUrl.path)[.modificationDate] as? Date - else { - logger?.error("\(#function, privacy: .public) - failed at (3)") - return ["error": "failed to read modified date in save function"] - } - - // remove old file and manifest records for old file if they exist - if oldFilename.lowercased() != newFilename.lowercased() { - // if user changed the filename, remove file with old filename - let oldFileUrl = saveLocation.appendingPathComponent(oldFilename) - // however, when creating a new file, if user changes the temp given name by app... - // oldFilename (the temp name in activeItem) and newFilename (@name in file contents) will differ - // the file with oldFilename will not be on the filesystem and can not be deleted - // for that edge case, using try? rather than try(!) to allow failures - try? FileManager.default.trashItem(at: oldFileUrl, resultingItemURL: nil) - } - - // update manifest for new file and purge anything from old file - guard - let allFiles = getAllFiles(), - updateManifestMatches(allFiles), - updateManifestRequired(allFiles), - updateManifestDeclarativeNetRequests(allFiles), - purgeManifest(allFiles) - else { - logger?.error("\(#function, privacy: .public) - failed at (4)") - return ["error": "file save but manifest couldn't be updated"] - } - - // un-santized name - name = unsanitize(name) - - // build response dict - response["canUpdate"] = false - response["content"] = newContent - response["filename"] = newFilename - response["lastModified"] = dateToMilliseconds(dateMod) - response["name"] = name - if metadata["description"] != nil { - response["description"] = metadata["description"]![0] - } - if metadata["version"] != nil && metadata["updateURL"] != nil { - response["canUpdate"] = true - } - // if a request "type" userscript add key/val - let runAt = metadata["run-at"]?[0] ?? "document-end" - if runAt == "request" { - response["request"] = true - } - - return response -} - -func trashFile(_ item: [String: Any]) -> Bool { - guard - let saveLocation = getSaveLocation(), - let filename = item["filename"] as? String - else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return false - } - // security scope - let didStartAccessing = saveLocation.startAccessingSecurityScopedResource() - defer { - if didStartAccessing {saveLocation.stopAccessingSecurityScopedResource()} - } - let url = saveLocation.appendingPathComponent(filename) - // if file is already removed from path, assume it was removed by user and return true - if (FileManager.default.fileExists(atPath: url.path)) { - do { - try FileManager.default.trashItem(at: url, resultingItemURL: nil) - } catch { - logger?.error("\(#function, privacy: .public) - \(error, privacy: .public)") - return false - } - } - // update manifest - guard updateManifestMatches(), updateManifestRequired(), purgeManifest() else { - logger?.error("\(#function, privacy: .public) - failed at (2)") - return false - } - return true; -} - -func getFileRemoteUpdate(_ content: String) -> [String: String] { - guard - let parsed = parse(content), - let metadata = parsed["metadata"] as? [String: [String]] - else { - // can't parse editor contents - return ["error": "Update failed, metadata missing"] - } - // editor contents missing version value - guard let version = metadata["version"]?[0] else { - return ["error": "Update failed, version value required"] - } - // editor contents missing updateURL - guard let updateURL = metadata["updateURL"]?[0] else { - return ["error": "Update failed, update url required"] - } - // set download url - let downloadURL = (metadata["downloadURL"] != nil) ? metadata["downloadURL"]![0] : updateURL - // basic url validation - guard validateUrl(updateURL) else { - return ["error": "Update failed, invalid updateURL"] - } - guard validateUrl(downloadURL) else { - return ["error": "Update failed, invalid downloadURL"] - } - // get the remote file contents for checking version - guard var remoteContent = getRemoteFileContents(updateURL) else { - return ["error": "Update failed, updateURL unreachable"] - } - // parse remote file contents - guard - let remoteParsed = parse(remoteContent), - let remoteMetadata = remoteParsed["metadata"] as? [String: [String]], - let remoteVersion = remoteMetadata["version"]?[0] - else { - // can't parse editor contents - return ["error": "Update failed, couldn't parse remote file contents"] - } - // check if update is needed - if !isVersionNewer(version, remoteVersion) { - return ["info": "No updates found"] - } - // at this point it is known an update is available, get new code from downloadURL - // is there's a specific downloadURL overwrite remoteContents with code from downloadURL - if updateURL != downloadURL { - guard let remoteDownloadContent = getRemoteFileContents(downloadURL) else { - return ["error": "Update failed, downloadURL unreachable"] - } - remoteContent = remoteDownloadContent - } - return ["content": remoteContent] -} - -// background -func nativeChecks() -> [String: String] { - logger?.info("\(#function, privacy: .public) - started") - #if os(iOS) - // check the save location is set - guard (getSaveLocation() != nil) else { - logger?.error("\(#function, privacy: .public) - save location unset (iOS)") - return [ - "error": "Native checks error (0)", - "saveLocation": "unset", - "scheme": Bundle.main.infoDictionary?["US_URL_SCHEME"] as! String - ] - } - #endif - // check the default directories - guard checkDefaultDirectories() else { - logger?.error("\(#function, privacy: .public) - checkDefaultDirectories failed") - return ["error": "Native checks error (1)"] - } - // check the settings - guard checkSettings() else { - logger?.error("\(#function, privacy: .public) - checkSettings failed") - return ["error": "Native checks error (2)"] - } - // get all files to pass as arguments to function below - guard let allFiles = getAllFiles() else { - logger?.error("\(#function, privacy: .public) - getAllFiles failed") - return ["error": "Native checks error (3)"] - } - // purge the manifest of old records - guard purgeManifest(allFiles) else { - logger?.error("\(#function, privacy: .public) - purgeManifest failed") - return ["error": "Native checks error (4)"] - } - // update matches in manifest - guard updateManifestMatches(allFiles) else { - logger?.error("\(#function, privacy: .public) - updateManifestMatches failed") - return ["error": "Native checks error (5)"] - } - // update the required resources - guard updateManifestRequired(allFiles) else { - logger?.error("\(#function, privacy: .public) - updateManifestRequired failed") - return ["error": "Native checks error (6)"] - } - // update declarativeNetRequest - guard updateManifestDeclarativeNetRequests(allFiles) else { - logger?.error("\(#function, privacy: .public) - updateManifestDeclarativeNetRequests failed") - return ["error": "Native checks error (7)"] - } - // pass some info in response - logger?.info("\(#function, privacy: .public) - completed") - return ["success": "Native checks complete"] -} - -// userscript install -func installCheck(_ content: String) -> [String: Any] { - // this func checks a userscript's metadata to determine if it's already installed - - guard let files = getAllFiles() else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return ["error": "installCheck failed at (1)"] - } - - guard - let parsed = parse(content), - let metadata = parsed["metadata"] as? [String: [String]], - let newName = metadata["name"]?[0] - else { - return ["error": "userscript metadata is invalid"] - } - - // loop through all files nad get their names and filenames - // we will check the new name/filename to see if this is a unique userscript - // or if it will overwrite an existing userscript - var names = [String]() - for file in files { - // can be force unwrapped because getAllFiles didn't return nil - let name = file["name"] as! String - - // populate array - names.append(name) - } - - var directive = "" - #if os(macOS) - directive = "Click" - #elseif os(iOS) - directive = "Tap" - #endif - - if names.contains(newName) { - return [ - "success": "\(directive) to re-install", - "metadata": metadata, - "installed": true - ] - } - - return [ - "success": "\(directive) to install", - "metadata": metadata, - "installed": false - ]; -} - -func installUserscript(_ url: String, _ type: String, _ content: String) -> [String: Any] { - guard - let parsed = parse(content), - let metadata = parsed["metadata"] as? [String: [String]], - let n = metadata["name"]?[0] - else { - logger?.error("\(#function, privacy: .public) - failed at (1)") - return ["error": "installUserscript failed at (1)"] - } - let name = sanitize(n) - let filename = "\(name).user.\(type)" - - let saved = saveFile(["filename": filename, "type": type], content) - return saved -} diff --git a/xcode/Ext-Safari/Info.plist b/xcode/Ext-Safari/Info.plist deleted file mode 100644 index 2cc72fe3..00000000 --- a/xcode/Ext-Safari/Info.plist +++ /dev/null @@ -1,41 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - $(MARKETING_VERSION) - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSExtension - - NSExtensionPointIdentifier - com.apple.Safari.web-extension - NSExtensionPrincipalClass - $(PRODUCT_MODULE_NAME).SafariWebExtensionHandler - - NSHumanReadableDescription - Save and run javascript for the web pages you visit - US_SHARED_GID-macos - $(MAC_SHARED_GID) - US_SHARED_GID-iphoneos - $(IOS_SHARED_GID) - US_EXT_IDENTIFIER - $(EXT_IDENTIFIER) - US_URL_SCHEME - $(APP_URL_SCHEME) - - diff --git a/xcode/Ext-Safari/Mac.entitlements b/xcode/Ext-Safari/Mac.entitlements deleted file mode 100644 index aa2f466a..00000000 --- a/xcode/Ext-Safari/Mac.entitlements +++ /dev/null @@ -1,16 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.application-groups - - $(MAC_SHARED_GID) - - com.apple.security.files.user-selected.read-write - - com.apple.security.network.client - - - diff --git a/xcode/Ext-Safari/SafariWebExtensionHandler.swift b/xcode/Ext-Safari/SafariWebExtensionHandler.swift deleted file mode 100644 index 84b84dd2..00000000 --- a/xcode/Ext-Safari/SafariWebExtensionHandler.swift +++ /dev/null @@ -1,294 +0,0 @@ -import SafariServices - -class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { - func beginRequest(with context: NSExtensionContext) { - defer { USLogStoreToFile() } - let logger = USLogger(#fileID) - let item = context.inputItems[0] as? NSExtensionItem - let message = item?.userInfo?[SFExtensionMessageKey] as? [String: Any] - // if message received without name, ignore - guard let name = message?["name"] as? String else { - logger?.error("\(#function, privacy: .public) - could not get message name from web extension") - return - } - logger?.info("\(#function, privacy: .public) - Got message with name: \(name, privacy: .public)") - // got a valid message, construct response based on message received - let response = NSExtensionItem() - // send standard error when there's an issue parsing inbound message - var inBoundError = false - // these if/else if statement are formatted so that they can be neatly collapsed in Xcode - // typically the "else if" would be on the same line as the preceding statements close bracket - // ie. } else if { - if name == "OPEN_APP" { - if let scheme = Bundle.main.infoDictionary?["US_URL_SCHEME"], - let url = URL(string: "\(scheme):") { - #if os(macOS) - NSWorkspace.shared.open(url) - #endif - } - } - else if name == "NATIVE_CHECKS" { - let result = nativeChecks() - response.userInfo = [SFExtensionMessageKey: result] - } - else if name == "REQ_PLATFORM" { - let platform = getPlatform() - response.userInfo = [SFExtensionMessageKey: ["platform": platform]] - } - else if name == "REQ_USERSCRIPTS" { - if let url = message?["url"] as? String, let isTop = message?["isTop"] as? Bool { - if - let matches = getInjectionFilenames(url), - let code = getCode(matches, isTop) - { - response.userInfo = [SFExtensionMessageKey: code] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "REQ_USERSCRIPTS failed"]] - } - } else { - inBoundError = true - } - } - else if name == "REQ_REQUESTS" { - if let requestScripts = getRequestScripts() { - response.userInfo = [SFExtensionMessageKey: requestScripts] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to get requestScripts"]] - } - } - else if name == "REQ_CONTEXT_MENU_SCRIPTS" { - if let contextMenuScripts = getContextMenuScripts() { - response.userInfo = [SFExtensionMessageKey: contextMenuScripts] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to get contextMenuScripts"]] - } - } - else if name == "POPUP_BADGE_COUNT" { - if let url = message?["url"] as? String, let frameUrls = message?["frameUrls"] as? [String] { - if let matches = getPopupBadgeCount(url, frameUrls) { - response.userInfo = [SFExtensionMessageKey: ["count": matches]] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to update badge count"]] - } - } else { - inBoundError = true - } - } - else if name == "POPUP_MATCHES"{ - if let url = message?["url"] as? String, let frameUrls = message?["frameUrls"] as? [String] { - if let matches = getPopupMatches(url, frameUrls) { - response.userInfo = [SFExtensionMessageKey: ["matches": matches]] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to get matches"]] - } - } else { - inBoundError = true - } - } - else if name == "POPUP_UPDATES" { - if let updates = checkForRemoteUpdates() { - response.userInfo = [SFExtensionMessageKey: ["updates": updates]] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to get updates"]] - } - } - else if name == "POPUP_UPDATE_ALL" { - if popupUpdateAll(), let updates = checkForRemoteUpdates() { - response.userInfo = [SFExtensionMessageKey: ["updates": updates]] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to run update sequence"]] - } - } - else if name == "POPUP_UPDATE_SINGLE" { - if - let filename = message?["filename"] as? String, - let url = message?["url"] as? String, - let frameUrls = message?["frameUrls"] as? [String] - { - if let matches = popupUpdateSingle(filename, url, frameUrls) { - response.userInfo = [SFExtensionMessageKey: ["items": matches]] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to update file"]] - } - } else { - inBoundError = true - } - } - else if name == "POPUP_CHECK_UPDATES" { - if let updates = checkForRemoteUpdates() { - response.userInfo = [SFExtensionMessageKey: ["updates": updates]] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to check for updates"]] - } - } - else if name == "TOGGLE_EXTENSION" { - if let active = message?["active"] as? String, ["true", "false"].contains(active) { - var manifest = getManifest() - manifest.settings["active"] = active - if updateManifest(with: manifest) { - response.userInfo = [SFExtensionMessageKey: ["success": true]] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to update injection state"]] - } - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "missing or wrong message content"]] - } - } - else if name == "TOGGLE_ITEM" { - // the current status of the item to toggle comes in as 0 || 1 - if - let item = message?["item"] as? [String: Any], - let filename = item["filename"] as? String, - let current = item["disabled"] as? Int - { - let action = current == 0 ? "disable" : "enable" - if toggleFile(filename, action) { - response.userInfo = [SFExtensionMessageKey: ["success": true]] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to toggle file"]] - } - } else { - inBoundError = true - } - } - else if name == "OPEN_SAVE_LOCATION" { - #if os(macOS) - if openSaveLocation() { - response.userInfo = [SFExtensionMessageKey: ["success": true]] - } - #elseif os(iOS) - if let files = getAllFiles() { - response.userInfo = [SFExtensionMessageKey: ["items": files]] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to get all files"]] - } - #endif - } - else if name == "CHANGE_SAVE_LOCATION" { - #if os(macOS) - if let scheme = Bundle.main.infoDictionary?["US_URL_SCHEME"], - let url = URL(string: "\(scheme)://changesavelocation") { - NSWorkspace.shared.open(url) - } - #endif - } - else if name == "POPUP_INSTALL_CHECK" { - if let content = message?["content"] as? String { - response.userInfo = [SFExtensionMessageKey: installCheck(content)] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to get script content"]] - } - } - else if name == "POPUP_INSTALL_SCRIPT" { - if - let url = message?["url"] as? String, - let type = message?["type"] as? String, - let content = message?["content"] as? String - { - response.userInfo = [SFExtensionMessageKey: installUserscript(url, type, content)] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to get script content (2)"]] - } - } - else if name == "PAGE_INIT_DATA" { - if let initData = getInitData(), checkDefaultDirectories() { - response.userInfo = [SFExtensionMessageKey: initData] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to get init data"]] - } - } - else if name == "PAGE_LEGACY_IMPORT" { - #if os(macOS) - if let settings = getLegacyData() { - response.userInfo = [SFExtensionMessageKey: settings] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to get legacy data"]] - } - #endif - } - else if name == "PAGE_ALL_FILES" { - #if os(macOS) - if let files = getAllFiles() { - response.userInfo = [SFExtensionMessageKey: files] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to get all files"]] - } - #endif - } - else if name == "PAGE_SAVE" { - #if os(macOS) - if - let item = message?["item"] as? [String: Any], - let content = message?["content"] as? String - { - let saveResponse = saveFile(item, content) - response.userInfo = [SFExtensionMessageKey: saveResponse] - } else { - inBoundError = true - } - #endif - } - else if name == "PAGE_TRASH" { - #if os(macOS) - if let item = message?["item"] as? [String: Any] { - if trashFile(item) { - response.userInfo = [SFExtensionMessageKey: ["success": true]] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to trash file"]] - } - } else { - inBoundError = true - } - #endif - } - else if name == "PAGE_UPDATE" { - #if os(macOS) - if let content = message?["content"] as? String { - let updateResponse = getFileRemoteUpdate(content) - response.userInfo = [SFExtensionMessageKey: updateResponse] - } else { - inBoundError = true - } - #endif - } - else if name == "CANCEL_REQUESTS" { - URLSession.shared.getAllTasks { tasks in - for task in tasks { - task.cancel() - } - } - response.userInfo = [SFExtensionMessageKey: ["success": true]] - } - else if name == "PAGE_UPDATE_SETTINGS" { - #if os(macOS) - if let settings = message?["settings"] as? [String: String] { - if updateSettings(settings) { - response.userInfo = [SFExtensionMessageKey: ["success": true]] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "Failed to save settings to disk"]] - } - } else { - inBoundError = true - } - #endif - } - else if name == "PAGE_UPDATE_BLACKLIST" { - if let blacklist = message?["blacklist"] as? [String] { - var manifest = getManifest() - manifest.blacklist = blacklist - if !updateManifest(with: manifest) { - response.userInfo = [SFExtensionMessageKey: ["error": "Failed to save blacklist to disk"]] - } else { - response.userInfo = [SFExtensionMessageKey: ["success": true]] - } - } else { - inBoundError = true - } - } - // send inBoundError if found - if inBoundError { - response.userInfo = [SFExtensionMessageKey: ["error": "Failed to parse inbound message"]] - } - context.completeRequest(returningItems: [response], completionHandler: nil) - } -} diff --git a/xcode/Ext-Safari/iOS.entitlements b/xcode/Ext-Safari/iOS.entitlements deleted file mode 100644 index c31a146a..00000000 --- a/xcode/Ext-Safari/iOS.entitlements +++ /dev/null @@ -1,10 +0,0 @@ - - - - - com.apple.security.application-groups - - $(IOS_SHARED_GID) - - - diff --git a/xcode/Shared/Logger.swift b/xcode/Shared/Logger.swift deleted file mode 100644 index f2137a70..00000000 --- a/xcode/Shared/Logger.swift +++ /dev/null @@ -1,232 +0,0 @@ -import OSLog -import SwiftUI - -private let logger = USLogger(#fileID) -private let logDir = "Library/Caches/\(projectName)/Debug" -private let logFile = "\(bundleIdentifier).log" - -func USLogger(_ category: String) -> Logger? { -#if DEBUG // Always enable logger in DEBUG builds - print("DEBUG: logger enabled") -#else - guard Preferences.enableLogger else { return nil } -#endif - let subsystem = Bundle.main.bundleIdentifier! - return Logger(subsystem: subsystem, category: category) -} - -func USLoggerSwitch(_ enable: Bool) { - Preferences.enableLogger = enable - if enable { - USLogStoreToFile() // clean up - } else { - USLogStoreToFile(prioritize: true) - } - // update app gui - if bundleIdentifier != extIdentifier { -#if os(macOS) && APP - if let appDelegate = NSApp.delegate as? AppDelegate { - // update app menu item state - appDelegate.enbaleNativeLogger?.state = enable ? .on : .off - // update app webview state - if let viewController = appDelegate.window?.contentViewController as? ViewController { - viewController.updateEnableLoggerState() - } - } -#elseif os(iOS) && APP - if let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate, - let viewController = sceneDelegate.window?.rootViewController as? ViewController { - // update app webview state - viewController.updateEnableLoggerState() - } -#endif - } -} - -// https://forums.swift.org/t/best-way-to-append-text-to-a-text-file/35764 -// Swift has no easy way to append to files, use POSIX APIs -private func appendToFile(_ file: URL, content: String) -> Bool { - guard file.isFileURL else { - print("Not a file scheme URL") - return false - } - if file.hasDirectoryPath { - print("Should be a file but is indicated as a directory URL") - return false - } - do { - let dir = file.deletingLastPathComponent() - try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true, attributes: nil) - } catch { - print("Failed mkdir - \(error)") - return false - } - let fileDescriptor = open(file.path, O_CREAT | O_WRONLY | O_APPEND, S_IRUSR | S_IWUSR) - if fileDescriptor == -1 { - perror("Failed open") - return false - } - defer { close(fileDescriptor) } - guard let textData = content.cString(using: .utf8) else { - print("Failed cString") - return false - } - let result = write(fileDescriptor, textData, strlen(textData)) - if result == -1 { - perror("Failed write") - return false - } - return true -} - -private func stringFromLogLevel(_ level: OSLogEntryLog.Level) -> String { - switch level { - case .undefined: - return "Undefined" - case .debug: - return "Debug" - case .info: - return "Info" - case .notice: - return "Notice" - case .error: - return "Error" - case .fault: - return "Fault" - @unknown default: - return "Unknown" - } -} - -// The last time written to the log file -private var lastDate: Date = Date().addingTimeInterval(-3600) - -private func writeLogStoreToFile() { - logger?.debug("\(#function, privacy: .public) - USLogStoreToFile start") - guard let logDirURL: URL = getProjectSharedDirectoryURL(path: logDir) else { - logger?.error("\(#function, privacy: .public) - Failed get logDirURL") - return - } - let logFileURL: URL = logDirURL.appendingPathComponent(logFile, isDirectory: false) - // log file size limit - if let fileSize = try? FileManager.default.attributesOfItem(atPath: logFileURL.path)[.size] as? Int { -#if DEBUG - print("DEBUG: logFileSize/maxLogFileSize", fileSize, Preferences.maxLogFileSize) -#endif - if fileSize > Preferences.maxLogFileSize { - logger?.info("\(#function, privacy: .public) - Logger disabling due to max file size exceeded") - USLoggerSwitch(false) - } - } -#if DEBUG - print("DEBUG: enableLogger", Preferences.enableLogger) -#endif - guard Preferences.enableLogger else { - // clean log files - logger?.info("\(#function, privacy: .public) - Cleaning log files") - do { - try FileManager.default.removeItem(at: logDirURL) - } catch { - logger?.error("\(#function, privacy: .public) - \(error)") - } - // reset logger prompt - Preferences.promptLogger = true - return - } - // log array written to the file in one go - var logs: [String] = [] - do { - let logStore = try OSLogStore(scope: .currentProcessIdentifier) - // `position` doesn't work in `getEntries`, always returns all logs - // instead use `predicate` to filter -// let position = logStore.position(date: lastDate) - let nowDate = Date() - let predicate = NSPredicate( - format: "date between {%@, %@}", - lastDate as CVarArg, - nowDate as CVarArg - ) - lastDate = nowDate - let entries = try logStore.getEntries(matching: predicate) - for entry in entries { - if let osLogEntry = entry as? OSLogEntryLog { - lastDate = osLogEntry.date - // format a single log line - let log = [ - osLogEntry.date.description, - stringFromLogLevel(osLogEntry.level), - osLogEntry.process, - osLogEntry.subsystem, - osLogEntry.category, - osLogEntry.composedMessage - - ].joined(separator: "\t") - logs.append(log) - } - } - } catch { - logger?.error("\(#function, privacy: .public) - Failed get entries: \(error)") - return - } - var content = logs.joined(separator: "\n") - // separate single write, there may be several duplicates before and after - content += "\n-------------------------\n" - guard appendToFile(logFileURL, content: content) else { - logger?.error("\(#function, privacy: .public) - Failed appendToFile") - return - } -} - -func USLogStoreToFile(prioritize: Bool = false) { - // Note qos `.background` doesn't seem to work in extension - DispatchQueue.global(qos: prioritize ? .userInteractive : .utility).async { - writeLogStoreToFile() - } -} - -func USLogFilesExportTo(_ directory: URL) throws -> URL { - - struct USLogExportError: Error, CustomStringConvertible { - enum errType: String { - case notDirectory = "Not a directory URL" - case logDirURLNil = "Failed get logDirURL" - case noLogDir = "The log is not ready, please try again later (d)" - case noLogFiles = "The log is not ready, please try again later (f)" - case exportFailed = "Export failed" - } - let type: errType - var error: Error? = nil - var description: String { - if let error = self.error { - return "\(error) - \(self.type.rawValue)" - } - return self.type.rawValue - } - } - - logger?.debug("\(#function, privacy: .public) - USLogFilesExportTo start") - guard directory.hasDirectoryPath else { - throw USLogExportError(type: .notDirectory) - } - guard let logDirURL: URL = getProjectSharedDirectoryURL(path: logDir) else { - throw USLogExportError(type: .logDirURLNil) - } - guard directoryExists(path: logDirURL.path) else { - throw USLogExportError(type: .noLogDir) - } - guard directoryEmpty(at: logDirURL) == false else { - throw USLogExportError(type: .noLogFiles) - } - let timeInterval = Date().timeIntervalSince1970 - let timestampSrt = String(Int(timeInterval)) - // Use timestamps to ensure no destination folders already exist - let outdir = "\(projectName)-logs-\(timestampSrt)" - let dstURL = directory.appendingPathComponent(outdir, isDirectory: true) - do { - try FileManager.default.copyItem(at: logDirURL, to: dstURL) - return dstURL - } catch { - throw USLogExportError(type: .logDirURLNil, error: error) - } - -} diff --git a/xcode/Shared/Preferences.swift b/xcode/Shared/Preferences.swift deleted file mode 100644 index 20f0b60e..00000000 --- a/xcode/Shared/Preferences.swift +++ /dev/null @@ -1,301 +0,0 @@ -import Foundation - -private let logger = USLogger(#fileID) -private let SDefaults = UserDefaults(suiteName: groupIdentifier) // Shared UserDefaults - -// https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties#Property-Wrappers -// https://docs.swift.org/swift-book/documentation/the-swift-programming-language/generics/ -@propertyWrapper -private struct SharedUserDefaults { - private let key: String - private let defaultValue: T - - init(wrappedValue: T, _ key: String) { - self.key = key - self.defaultValue = wrappedValue - SDefaults?.register(defaults: [key: wrappedValue]) - } - - var wrappedValue: T { - get { SDefaults?.object(forKey: key) as? T ?? defaultValue } - set { SDefaults?.set(newValue, forKey: key) } - } -} - -#if os(macOS) -/* https://developer.apple.com/documentation/security/app_sandbox/accessing_files_from_the_macos_app_sandbox - # Design ideas and processes - Since the security-scoped URL bookmark is only available in the current app, - pass to extensions can only use URL bookmark with an implicit security scope. - app set URL write to: - - `_SetterId` (setter app bundleIdentifier) - - `_Transfer` (with an implicit security scope) - - `_SecurityScoped_` (with an explicit security scope) - app get URL read from: `_SecurityScoped_` - ext get URL read flow: - - if `_Transfer` exist, remove to `_SecurityScoped_` - - if `_Transfer` empty, read from `_SecurityScoped_` - */ -@propertyWrapper -private struct SecurityScopedBookmark { - private let key: String - private let keySetter: String - private let keyTransfer: String - private let keySecurityScoped: String - private let defaultValue: URL - - init(wrappedValue: URL, _ key: String) { - self.key = key - self.keySetter = key + "/SetterId" - self.keyTransfer = key + "/Transfer" - self.keySecurityScoped = key + "/SecurityScoped/" + bundleIdentifier - self.defaultValue = wrappedValue - } - - private func createBookmark(_ url: URL, _ withSecurityScope: Bool) -> Data? { - do { - return try url.bookmarkData( - options: withSecurityScope ? .withSecurityScope : [], - includingResourceValuesForKeys: nil, - relativeTo: nil - ) - } catch { - logger?.error("\(#function, privacy: .public) - \(error, privacy: .public)") - } - return nil - } - - private func resolvBookmark(_ data: Data, _ withSecurityScope: Bool, _ isStale: inout Bool) -> URL? { - do { - return try URL( - resolvingBookmarkData: data, - options: withSecurityScope ? .withSecurityScope : [], - relativeTo: nil, - bookmarkDataIsStale: &isStale - ) - } catch { - logger?.error("\(#function, privacy: .public) - \(error, privacy: .public)") - } - return nil - } - - private func updateBookmark() { - guard let setterIdentifier = SDefaults?.string(forKey: keySetter) else { - logger?.debug("\(#function, privacy: .public) - setterId not exist: \(key, privacy: .public)") - return - } - guard bundleIdentifier != setterIdentifier else { return } // update only in non-setter environment - guard let data = SDefaults?.data(forKey: keyTransfer) else { // no need to update due empty data - logger?.debug("\(#function, privacy: .public) - no update: \(key, privacy: .public)") - return - } - var isStale = false // no need to renew since will remove anyway - guard let url = resolvBookmark(data, false, &isStale) else { // get URL bookmark with an implicit security scope - removeBookmark() - return - } - defer { url.stopAccessingSecurityScopedResource() } // revoke implicitly starts security-scoped access - if let data = createBookmark(url, true) { // set URL bookmark with an explicit security scope - logger?.info("\(#function, privacy: .public) - update bookmark: \(key, privacy: .public) \(url, privacy: .public)") - SDefaults?.removeObject(forKey: keyTransfer) - SDefaults?.set(data, forKey: keySecurityScoped) - } - } - - private func removeBookmark() { - logger?.info("\(#function, privacy: .public) - remove invalid bookmark: \(key, privacy: .public)") - SDefaults?.removeObject(forKey: keyTransfer) - SDefaults?.removeObject(forKey: keySecurityScoped) - if let setterIdentifier = SDefaults?.string(forKey: keySetter) { - SDefaults?.removeObject(forKey: key + "/SecurityScoped/" + setterIdentifier) - } - } - - // NOTE: This function will be deleted after several public versions of v4.5.0 - private func legacyBookmarkImporter() { - guard key == "ScriptsDirectoryUrlBookmarkData" else { return } - guard bundleIdentifier == extIdentifier else { return } - func legacyCleanup() { - logger?.debug("\(#function, privacy: .public) - cleanup legacy bookmark data") - SDefaults?.removeObject(forKey: "hostSelectedSaveLocation") // shared - UserDefaults.standard.removeObject(forKey: "saveLocation") // ext - UserDefaults.standard.removeObject(forKey: "userSaveLocation") // ext - } - guard let data = UserDefaults.standard.data(forKey: "userSaveLocation") else { // get from old key - logger?.debug("\(#function, privacy: .public) - legacy bookmark not exist") - return - } - guard SDefaults?.string(forKey: keySetter) == nil else { // already a new key - return legacyCleanup() - } - logger?.debug("\(#function, privacy: .public) - Import legacy bookmark data") - var isStale = false // no need to renew since will remove anyway - guard let url = resolvBookmark(data, true, &isStale) else { // get URL bookmark with an explicit security scope - return legacyCleanup() - } - guard url.startAccessingSecurityScopedResource() else { - return legacyCleanup() - } - defer { url.stopAccessingSecurityScopedResource() } - guard let transferData = createBookmark(url, false) else { - return legacyCleanup() - } - SDefaults?.set(bundleIdentifier, forKey: keySetter) - SDefaults?.set(transferData, forKey: keyTransfer) // set URL bookmark with an implicit security scope - SDefaults?.set(data, forKey: keySecurityScoped) // set URL bookmark with an explicit security scope - legacyCleanup() - } - - var wrappedValue: URL { - get { - legacyBookmarkImporter() - updateBookmark() - logger?.info("\(#function, privacy: .public) - try get bookmark: \(key, privacy: .public)") - guard let data = SDefaults?.data(forKey: keySecurityScoped) else { - logger?.debug("\(#function, privacy: .public) - bookmark not exist: \(key, privacy: .public)") - return defaultValue - } - var isStale = false - guard let url = resolvBookmark(data, true, &isStale) else { // get URL bookmark with an explicit security scope - removeBookmark() // remove data that cannot be resolved - return defaultValue - } - if isStale, url.startAccessingSecurityScopedResource() { // renew URL bookmark - defer { url.stopAccessingSecurityScopedResource() } - if let data = createBookmark(url, true) { // set URL bookmark with an explicit security scope - logger?.info("\(#function, privacy: .public) - renew bookmark: \(key, privacy: .public) \(url, privacy: .public)") - SDefaults?.set(data, forKey: keySecurityScoped) - } - } - return url - } - set(url) { - let k = key // key cannot be log directly with error: Escaping autoclosure captures mutating 'self' parameter - logger?.info("\(#function, privacy: .public) - try set bookmark: \(k, privacy: .public) \(url, privacy: .public)") - guard let tdata = createBookmark(url, false), let sdata = createBookmark(url, true) else { - logger?.info("\(#function, privacy: .public) - failed create bookmark: \(k, privacy: .public) \(url, privacy: .public)") - return - } - SDefaults?.set(bundleIdentifier, forKey: keySetter) - SDefaults?.set(tdata, forKey: keyTransfer) // set URL bookmark with an implicit security scope - SDefaults?.set(sdata, forKey: keySecurityScoped) // set URL bookmark with an explicit security scope - } - } -} -#elseif os(iOS) -/* https://developer.apple.com/documentation/uikit/view_controllers/providing_access_to_directories#3331285 - iOS and macOS have completely different processes, iOS has no implicit security scope - The security-scoped URL is not bind to the app and can be shared directly between the app and ext - Separating the wrappers for the two platforms is intentional for ease of viewing code logic - */ -@propertyWrapper -private struct SecurityScopedBookmark { - private let key: String - private let defaultValue: URL - - init(wrappedValue: URL, _ key: String) { - self.key = key - self.defaultValue = wrappedValue - } - - private func createBookmark(_ url: URL) -> Data? { - do { - return try url.bookmarkData(options: .minimalBookmark, includingResourceValuesForKeys: nil, relativeTo: nil) - } catch { - logger?.error("\(#function, privacy: .public) - \(error, privacy: .public)") - } - return nil - } - - private func resolvBookmark(_ data: Data, _ isStale: inout Bool) -> URL? { - do { - return try URL(resolvingBookmarkData: data, bookmarkDataIsStale: &isStale) - } catch { - logger?.error("\(#function, privacy: .public) - \(error, privacy: .public)") - } - return nil - } - - // NOTE: This function will be deleted after several public versions of v4.5.0 - private func legacyBookmarkImporter() { - guard let data = SDefaults?.data(forKey: "iosReadLocation") else { // get from old key - logger?.debug("\(#function, privacy: .public) - legacy bookmark not exist") - return - } - logger?.debug("\(#function, privacy: .public) - Import legacy bookmark data") - SDefaults?.set(data, forKey: key) - SDefaults?.removeObject(forKey: "iosReadLocation") - } - - var wrappedValue: URL { - get { - legacyBookmarkImporter() - logger?.info("\(#function, privacy: .public) - try get bookmark: \(key, privacy: .public)") - guard let data = SDefaults?.data(forKey: key) else { - logger?.debug("\(#function, privacy: .public) - bookmark not exist: \(key, privacy: .public)") - return defaultValue - } - var isStale = false - guard let url = resolvBookmark(data, &isStale) else { // get security-scoped URL - // Note: temporary mitigation measures for occasional failures on some iOS devices -// SDefaults?.removeObject(forKey: key) // remove data that cannot be resolved - logger?.warning("\(#function, privacy: .public) - faild resolv bookmark, return default") - return defaultValue - } - if isStale, url.startAccessingSecurityScopedResource() { // renew URL bookmark - defer { url.stopAccessingSecurityScopedResource() } - if let data = createBookmark(url) { // set security-scoped URL - logger?.info("\(#function, privacy: .public) - renew bookmark: \(key, privacy: .public) \(url, privacy: .public)") - SDefaults?.set(data, forKey: key) - } - } - return url - } - set(url) { - let k = key // key cannot be log directly with error: Escaping autoclosure captures mutating 'self' parameter - logger?.info("\(#function, privacy: .public) - try set bookmark: \(k, privacy: .public) \(url, privacy: .public)") - // true - when url from UIDocumentPicker - // false - when set default app document - let didStartAccessing = url.startAccessingSecurityScopedResource() - defer { - if didStartAccessing { url.stopAccessingSecurityScopedResource() } - } - guard let data = createBookmark(url) else { - logger?.info("\(#function, privacy: .public) - failed create bookmark: \(k, privacy: .public) \(url, privacy: .public)") - return - } - SDefaults?.set(data, forKey: key) // set security-scoped URL - } - } -} -#endif - -// Define shared preferences, default values determine data type -struct Preferences { - // Example preference, can be get or set with: Preferences.propertyName - // @SharedUserDefaults("SharedUserDefaultsKeyName") - // static var propertyName = "DefaultValue" // Type -> String - - // This is a separate wrapper, type is URL - @SecurityScopedBookmark("ScriptsDirectoryUrlBookmarkData") - static var scriptsDirectoryUrl = getDefaultScriptsDirectoryUrl() - - @SharedUserDefaults("EnableLogger") - static var enableLogger = false - - @SharedUserDefaults("PromptLogger") - static var promptLogger = true - - @SharedUserDefaults("MaxLogFileSize") - static var maxLogFileSize = 500_000_000 // 500MB - - @SharedUserDefaults("FirstRunTime") - static var firstRunTime = 0 { - willSet { - print("willSet \(newValue)") - } - didSet { - print("didSet \(oldValue)") - } - } -} diff --git a/xcode/Shared/UrlPolyfill.swift b/xcode/Shared/UrlPolyfill.swift deleted file mode 100644 index 4f8d4180..00000000 --- a/xcode/Shared/UrlPolyfill.swift +++ /dev/null @@ -1,105 +0,0 @@ -import Foundation - -extension CharacterSet { - // https://developer.apple.com/documentation/foundation/characterset#2902136 - public static let urlAllowed_ = CharacterSet(charactersIn: "#") - .union(.urlFragmentAllowed) - .union(.urlHostAllowed) - .union(.urlPasswordAllowed) - .union(.urlPathAllowed) - .union(.urlQueryAllowed) - .union(.urlUserAllowed) -} - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI -func encodeURI(_ uri: String) -> String { - // https://developer.apple.com/documentation/foundation/characterset#2902136 -// var urlAllowed = CharacterSet(charactersIn: "#") -// urlAllowed.formUnion(.urlFragmentAllowed) -// urlAllowed.formUnion(.urlHostAllowed) -// urlAllowed.formUnion(.urlPasswordAllowed) -// urlAllowed.formUnion(.urlPathAllowed) -// urlAllowed.formUnion(.urlQueryAllowed) -// urlAllowed.formUnion(.urlUserAllowed) - return uri.addingPercentEncoding(withAllowedCharacters: .urlAllowed_) ?? uri -} - -func fixedURL(string urlString: String) -> URL? { - let rawUrlString = urlString.removingPercentEncoding ?? urlString - var url: URL? - if #available(macOS 14.0, iOS 17.0, *) { - url = URL(string: rawUrlString, encodingInvalidCharacters: true) - } else { - url = URL(string: encodeURI(rawUrlString)) - } - return url -} - -// https://developer.mozilla.org/en-US/docs/Web/API/URL -func jsLikeURL(_ urlString: String, baseString: String? = nil) -> [String: String]? { - var _url: URL? - if let baseString = baseString { - guard let baseUrl = fixedURL(string: baseString) else { - return nil - } - _url = URL(string: urlString, relativeTo: baseUrl) - } else { - _url = fixedURL(string: urlString) - } - guard let url = _url else { - return nil - } - guard let scheme = url.scheme else { - return nil - } - var port = "" - if let portInt = url.port { port = String(portInt) } - if (scheme == "http" && port == "80") { port = "" } - if (scheme == "https" && port == "443") { port = "" } - /* - The issue still exists as of macOS 14.4, iOS 17.0 - https://stackoverflow.com/questions/74445926/url-host-deprecated-but-replacement-crashes - https://forums.swift.org/t/does-url-query-percentencoded-calls-url-host-percentencoded-under-the-hood/70452 - https://forums.developer.apple.com/forums/thread/722451 - */ - if #available(macOS 15.0, iOS 18.0, *) { - guard let hostname = url.host(percentEncoded: true) else { return nil } - let host = (port == "") ? hostname : "\(hostname):\(port)" - let query = url.query(percentEncoded: true) ?? "" - let fragment = url.fragment(percentEncoded: true) ?? "" - return [ - "hash": fragment == "" ? "" : "#\(fragment)", - "host": host, - "hostname": hostname, - // "href": url.absoluteString, - "origin": "\(scheme)://\(host)", - "password": url.password(percentEncoded: true) ?? "", - "pathname": url.path(percentEncoded: true), - "port": port, - "protocol": "\(scheme):", - "search": query == "" ? "" : "?\(query)", - "username": url.user(percentEncoded: true) ?? "" - ] - } else { - guard let hostname = url.host else { return nil } - let host = (port == "") ? hostname : "\(hostname):\(port)" - let query = url.query ?? "" - let fragment = url.fragment ?? "" - /// If the path has a trailing slash, it is stripped. https://developer.apple.com/documentation/foundation/nsurl/1408809-path - let strippedPath = url.path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? url.path - let pathname = (strippedPath != "/" && url.hasDirectoryPath) ? "\(strippedPath)/" : strippedPath - return [ - "hash": fragment == "" ? "" : "#\(fragment)", - "host": host, - "hostname": hostname, - // "href": url.absoluteString, - "origin": "\(scheme)://\(host)", - "password": url.password ?? "", - "pathname": pathname, - "port": port, - "protocol": "\(scheme):", - "search": query == "" ? "" : "?\(query)", - "username": url.user?.addingPercentEncoding(withAllowedCharacters: .urlUserAllowed) ?? "" - ] - } -} diff --git a/xcode/Shared/Utilities.swift b/xcode/Shared/Utilities.swift deleted file mode 100644 index a60de5d2..00000000 --- a/xcode/Shared/Utilities.swift +++ /dev/null @@ -1,168 +0,0 @@ -import SwiftUI - -let bundleIdentifier = Bundle.main.bundleIdentifier! -let groupIdentifier = Bundle.main.infoDictionary!["US_SHARED_GID"] as! String -let extIdentifier = Bundle.main.infoDictionary?["US_EXT_IDENTIFIER"] as! String -let projectName = "Userscripts" -//let projectName = Bundle.main.infoDictionary!["PROJECT_NAME"] as! String -private let logger = USLogger(#fileID) - -func getPlatform() -> String { -#if os(macOS) - return "macos" -#elseif os(iOS) - // https://developer.apple.com/documentation/uikit/uiuserinterfaceidiom - // There is no reliable way to detect visionOS for now, will match `.phone` in Apple Vision (Designed for iPad) mode - switch UIDevice.current.userInterfaceIdiom { - case .phone: - return "ios" - case .pad, .mac: - return "ipados" - case .vision: - return "visionos" - case .tv: - return "tvos" - case .carPlay: - return "carplay" - case .unspecified: - return "unspecified" - @unknown default: - return "unknown" - } -#endif -} - -func directoryExists(path: String) -> Bool { - var isDirectory = ObjCBool(true) - let exists = FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory) - let inTrash = path.contains(".Trash") ? false : true - return exists && inTrash && isDirectory.boolValue -} - -func directoryEmpty(at url: URL) -> Bool? { - // get a list of non-hidden files - guard let contents = try? FileManager.default.contentsOfDirectory( - at: url, - includingPropertiesForKeys: [], - options: .skipsHiddenFiles - ) else { - logger?.error("\(#function, privacy: .public) - failed get contentsOfDirectory") - return nil - } - return contents.isEmpty -} - -func getDocumentsDirectory() -> URL { - let fm = FileManager.default - let paths = fm.urls(for: .documentDirectory, in: .userDomainMask) - let documentsDirectory = paths[0] - return documentsDirectory -} - -func getProjectSharedDirectoryURL(path: String? = nil) -> URL? { - // https://developer.apple.com/documentation/foundation/filemanager/1412643-containerurl/ - guard let sharedContainerURL = FileManager.default.containerURL( - forSecurityApplicationGroupIdentifier: groupIdentifier - ) else { - logger?.error("\(#function, privacy: .public) - Failed get sharedContainerURL") - return nil - } - guard let path = path else { - return sharedContainerURL - } - if #available(macOS 13.0, iOS 16.0, *) { - return sharedContainerURL.appending(path: path, directoryHint: .isDirectory) - } else { - return sharedContainerURL.appendingPathComponent(path, isDirectory: true) - } -} - -func getDefaultScriptsDirectoryUrl() -> URL { -#if os(iOS) - return URL(string: "default://uninitialized")! -#elseif os(macOS) - var url: URL - if #available(macOS 13.0, iOS 16.0, *) { - url = getDocumentsDirectory().appending(path: "scripts") - } else { - url = getDocumentsDirectory().appendingPathComponent("scripts") - } - // if not in safari extension environment, replace with extension path - if bundleIdentifier != extIdentifier { - var path: String - if #available(macOS 13.0, iOS 16.0, *) { - path = url.path(percentEncoded: false) - } else { - path = url.path.removingPercentEncoding ?? url.path - } - let truePath = path.replacingOccurrences(of: bundleIdentifier, with: extIdentifier) - url = URL(fileURLWithPath: truePath, isDirectory: true) - } - return url -#endif -} - -#if os(iOS) -// Initialization directory is only required in iOS -func isCurrentDefaultScriptsDirectory() -> Bool { - return Preferences.scriptsDirectoryUrl == getDefaultScriptsDirectoryUrl() -} -#endif - -// For mac, the initial directory is Ext-Documents (default directory) -// For ios, the initial directory is App-Documents -// In ios only App-Documents can be displayed in Files App -func isCurrentInitialScriptsDirectory() -> Bool { - let url = Preferences.scriptsDirectoryUrl.standardizedFileURL -#if os(iOS) - return url == getDocumentsDirectory().standardizedFileURL -#elseif os(macOS) - return url == getDefaultScriptsDirectoryUrl().standardizedFileURL -#endif -} - -func getCurrentScriptsDirectoryString() -> String { - if isCurrentInitialScriptsDirectory() { - return "Userscripts App Documents" - } - let url = Preferences.scriptsDirectoryUrl.standardizedFileURL - if #available(macOS 13.0, iOS 16.0, *) { - return url.path(percentEncoded: false) - } else { - return url.path.removingPercentEncoding ?? url.path - } -} - -func getSaveLocation() -> URL? { -#if os(iOS) - if isCurrentDefaultScriptsDirectory() { - logger?.info("\(#function, privacy: .public) - Uninitialized save location") - return nil - } -#endif - let url = Preferences.scriptsDirectoryUrl - logger?.debug("\(#function, privacy: .public) - \(url, privacy: .public)") - return url -} - -func openSaveLocation() -> Bool { -#if os(macOS) - guard let saveLocation = getSaveLocation() else { - return false - } - let didStartAccessing = saveLocation.startAccessingSecurityScopedResource() - defer { - if didStartAccessing {saveLocation.stopAccessingSecurityScopedResource()} - } - NSWorkspace.shared.selectFile(nil, inFileViewerRootedAtPath: saveLocation.path) -#endif - return true -} - -func resetSaveLocation() { - logger?.info("\(#function, privacy: .public) - Reset save location") -#if os(iOS) - Preferences.scriptsDirectoryUrl = getDocumentsDirectory() -#elseif os(macOS) -#endif -} diff --git a/xcode/Tests-Mac/UrlCodecTests.swift b/xcode/Tests-Mac/UrlCodecTests.swift deleted file mode 100644 index ca54bcfd..00000000 --- a/xcode/Tests-Mac/UrlCodecTests.swift +++ /dev/null @@ -1,213 +0,0 @@ -import XCTest - -final class UrlCodecTests: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - // Any test you write for XCTest can be annotated as throws and async. - // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. - // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. - } - - func testPerformanceExample() throws { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } - } - - func testEncodeURI() throws { - - func check(_ urlString: String, _ res: String) -> Bool { - let url = encodeURI(urlString) - if (url != res) { - print(urlString, url) - return false - } - return true - } - - XCTAssert(check("http://user:password@host:80/path?q=1#id", - "http://user:password@host:80/path?q=1#id")) - - XCTAssert(check("https://用户名:密码@中.文:80/path/中文/?a=中文#中文", - "https://%E7%94%A8%E6%88%B7%E5%90%8D:%E5%AF%86%E7%A0%81@%E4%B8%AD.%E6%96%87:80/path/%E4%B8%AD%E6%96%87/?a=%E4%B8%AD%E6%96%87#%E4%B8%AD%E6%96%87")) - - XCTAssert(check("https://用户名:密码@中.文:80/path/中%E6%96%87/?a=中&b=%E6%96%87&c#中文", - "https://%E7%94%A8%E6%88%B7%E5%90%8D:%E5%AF%86%E7%A0%81@%E4%B8%AD.%E6%96%87:80/path/%E4%B8%AD%25E6%2596%2587/?a=%E4%B8%AD&b=%25E6%2596%2587&c#%E4%B8%AD%E6%96%87")) - - } - - func testJsLikeURL() throws { - - func diffPrint(_ dA: Dictionary?, _ dB: Dictionary) { - guard let dA = dA else { - return print("dA is nil") - } - for k in dA.keys { - if dA[k] != dB[k] { - print(k, dA[k] ?? "nil", dB[k] ?? "nil") - } - } - } - - func check(_ urlString: String, _ res: Dictionary) -> Bool { - let url = jsLikeURL(urlString) - if (url != res) { - print(urlString) - diffPrint(url, res) - return false - } - return true - } - - /** javascript get res - - url = new URL("http://user:password@host:80/path?q=1#id") - res = {} - for(let k of ["hash","host","hostname","href","origin","password","pathname","port","protocol","search","username"]){ - res[k] = url[k]; - } - JSON.stringify(res) - */ - - XCTAssert(check("http://user:password@host:80/path?q=1#id", [ - "hash": "#id", - "host": "host", - "hostname": "host", - // "href": "http://user:password@host/path?q=1#id", - "origin": "http://host", - "password": "password", - "pathname": "/path", - "port": "", - "protocol": "http:", - "search": "?q=1", - "username": "user" - ])) - - XCTAssert(check("http://host.test:8080/path?#id", [ - "hash": "#id", - "host": "host.test:8080", - "hostname": "host.test", - // "href": "http://host.test:8080/path?#id", - "origin": "http://host.test:8080", - "password": "", - "pathname": "/path", - "port": "8080", - "protocol": "http:", - "search": "", - "username": "" - ])) - - XCTAssert(check("http://host.test:8080/path?", [ - "hash": "", - "host": "host.test:8080", - "hostname": "host.test", - // "href": "http://host.test:8080/path?", - "origin": "http://host.test:8080", - "password": "", - "pathname": "/path", - "port": "8080", - "protocol": "http:", - "search": "", - "username": "" - ])) - - XCTAssert(check("http://host.test/path#id", [ - "hash": "#id", - "host": "host.test", - "hostname": "host.test", - // "href": "http://host.test/path#id", - "origin": "http://host.test", - "password": "", - "pathname": "/path", - "port": "", - "protocol": "http:", - "search": "", - "username": "" - ])) - - XCTAssert(check("http://host.test/path", [ - "hash": "", - "host": "host.test", - "hostname": "host.test", - // "href": "http://host.test/path", - "origin": "http://host.test", - "password": "", - "pathname": "/path", - "port": "", - "protocol": "http:", - "search": "", - "username": "" - ])) - - XCTAssert(check("http://host.test/path//", [ - "hash": "", - "host": "host.test", - "hostname": "host.test", - // "href": "http://host.test/path//", - "origin": "http://host.test", - "password": "", - "pathname": "/path//", - "port": "", - "protocol": "http:", - "search": "", - "username": "" - ])) - - XCTAssert(check("http://host.test/", [ - "hash": "", - "host": "host.test", - "hostname": "host.test", - // "href": "http://host.test/", - "origin": "http://host.test", - "password": "", - "pathname": "/", - "port": "", - "protocol": "http:", - "search": "", - "username": "" - ])) - - XCTAssert(check("https://用户名:密码@host.test:80/path/中%E6%96%87/?a=中&b=%E6%96%87&c#中文", [ - "hash": "#%E4%B8%AD%E6%96%87", - "host": "host.test:80", - "hostname": "host.test", - // "href": "https://%E7%94%A8%E6%88%B7%E5%90%8D:%E5%AF%86%E7%A0%81@host.test:80/path/%E4%B8%AD%E6%96%87/?a=%E4%B8%AD&b=%E6%96%87&c#%E4%B8%AD%E6%96%87", - "origin": "https://host.test:80", - "password": "%E5%AF%86%E7%A0%81", - "pathname": "/path/%E4%B8%AD%E6%96%87/", - "port": "80", - "protocol": "https:", - "search": "?a=%E4%B8%AD&b=%E6%96%87&c", - "username": "%E7%94%A8%E6%88%B7%E5%90%8D" - ])) - - if #available(macOS 14.0, iOS 17.0, *) { - XCTAssert(check("https://用户名:密码@中.文:80/path/中%E6%96%87/?a=中&b=%E6%96%87&c#中文", [ - "hash": "#%E4%B8%AD%E6%96%87", - "host": "xn--fiq.xn--7dv:80", - "hostname": "xn--fiq.xn--7dv", - // "href": "https://%E7%94%A8%E6%88%B7%E5%90%8D:%E5%AF%86%E7%A0%81@xn--fiq.xn--7dv:80/path/%E4%B8%AD%E6%96%87/?a=%E4%B8%AD&b=%E6%96%87&c#%E4%B8%AD%E6%96%87", - "origin": "https://xn--fiq.xn--7dv:80", - "password": "%E5%AF%86%E7%A0%81", - "pathname": "/path/%E4%B8%AD%E6%96%87/", - "port": "80", - "protocol": "https:", - "search": "?a=%E4%B8%AD&b=%E6%96%87&c", - "username": "%E7%94%A8%E6%88%B7%E5%90%8D" - ])) - } - - } // testJsLikeURL() -> END - -} diff --git a/xcode/Tests-Mac/UserscriptsTests.swift b/xcode/Tests-Mac/UserscriptsTests.swift deleted file mode 100644 index b099c0b8..00000000 --- a/xcode/Tests-Mac/UserscriptsTests.swift +++ /dev/null @@ -1,307 +0,0 @@ -// -// UserscriptsTests.swift -// UserscriptsTests -// -// Created by Justin Wasack on 1/23/22. -// Copyright © 2022 Justin Wasack. All rights reserved. -// - -import XCTest -@testable import Userscripts_Mac_Safari_Extension - -class UserscriptsTests: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - // Any test you write for XCTest can be annotated as throws and async. - // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. - // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. - } - - func testStringSanitization() throws { - // given - let strs = [ - "String", - "https://something.com/?foo=12", - "I have backslashes \\\\", - ".....ok", - ":Akneh.,><>dkie:lm", - "..解锁B站大会员番剧、", - "解锁B站大会员番剧、B站视频解析下载;全网VIP视频免费破解去广告;全网音乐直接下载;油管、Facebook等国外视频解析下载;网盘搜索引擎破解无限下载等", - "5CLksm3AAbb2F2F2f----___--+87363&^#%o%3O3", - "Example Userscript Name" - ] - - // when - var result = [String]() - for str in strs { - let sanitizedString = sanitize(str) - let unsanitizedString = unsanitize(sanitizedString) - result.append(unsanitizedString) - } - - // then - XCTAssert(result.elementsEqual(strs)) - } - - func testEncodedCheck() throws { - let urls = [ - "https://greasyfork.org/scripts/416338-redirect-外链跳转/code/redirect%20外链跳转.user.js", - "https://raw.githubusercontent.com/Anarios/return-youtube-dislike/main/Extensions/UserScript/Return%20Youtube%20Dislike.user.js", - "https://cdn.frankerfacez.com/static/ffz_injector.user.js", - "http://www.k21p.com/example.user.js", // add http protocol - "https://example.test/%%%test.user.js", // removingPercentEncoding -> nil - "https://greasyfork.org/scripts/416338-redirect-外链跳转/code/redirect 外链跳转.user.js" - ] - var result = [String]() - for url in urls { - if isEncoded(url) { - result.append(url) - } - } - // 2 urls already percent encoded - XCTAssert(result.count == 2) - } - - func testGetRemoteFileContents() throws { - var urls:[String] = [ - "https://greasyfork.org/scripts/416338-redirect-外链跳转/code/redirect%20外链跳转.user.js", - "https://greasyfork.org/scripts/416338-redirect-外链跳转/code/redirect 外链跳转.user.js", - "https://update.greasyfork.org/scripts/460897/1277476/gbCookies.js#sha256-Sv+EuBerch8z/6LvAU0m/ufvjmqB1Q/kbQrX7zAvOPk=", - "https://raw.githubusercontent.com/Anarios/return-youtube-dislike/main/Extensions/UserScript/Return%20Youtube%20Dislike.user.js", - "https://cdn.frankerfacez.com/static/ffz_injector.user.js", - "http://www.k21p.com/example.user.js" // add http protocol - ] - if #available(macOS 14.0, iOS 17.0, *) { - urls += [ - "https://☁️.com/", // IDN / Non-Punycode-encoded domain name - ] - } - for url in urls { - if getRemoteFileContents(url) == nil { - print(#function, url) - XCTAssert(false) - } - } - } - - func testFileRemoteUpdate() throws { - let urls = [ - "https://www.k21p.com/example.user.js", - "https://www.k21p.com/example.user.js?foo=bar", // query string - "http://www.k21p.com/example.user.js", // http protocol - "https://greasyfork.org/scripts/416338-redirect-外链跳转/code/redirect 外链跳转.user.js", // non latin chars - "https://www.k21p.com/example.user.jsx" // should fail - - ] - var result = [Int]() - for url in urls { - let content = """ - // ==UserScript== - // @name test - // @match *://*/* - // @version 0.1 - // @updateURL http://www.k21p.com/example.user.js - // @downloadURL \(url) - // ==/UserScript== - """; - let response = getFileRemoteUpdate(content) - if !response.keys.contains("error") { - result.append(1) - } - } - XCTAssert(result.count == (urls.count - 1)) - } - - func testMatching() throws { - /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns#examples - let patternDict = [ - "": [ - "http://example.org/", - "https://a.org/some/path/" - ], - "*://*/*": [ - "http://example.org/", - "https://a.org/some/path/", - "https://www.example.com/", - "https://example.org/foo/bar.html", - "https://☁️.com/", - "https://🙂.☁️/", - ], - "*://*.mozilla.org/*": [ - "http://mozilla.org/", - "https://mozilla.org/", - "http://a.mozilla.org/", - "http://a.b.mozilla.org/", - "https://b.mozilla.org/path/", - ], - "*://mozilla.org/": [ - "http://mozilla.org/", - "https://mozilla.org/", - ], - "https://*/path": [ - "https://mozilla.org/path", - "https://a.mozilla.org/path", - "https://something.com/path", - ], - "https://*/path/": [ - "https://mozilla.org/path/", - "https://a.mozilla.org/path/", - "https://something.com/path/", - ], - "https://mozilla.org/*": [ - "https://mozilla.org/", - "https://mozilla.org/path", - "https://mozilla.org/another", - "https://mozilla.org/path/to/doc", - "https://mozilla.org/path/to/doc?foo=1", - ], - "https://mozilla.org/a/b/c/": [ - "https://mozilla.org/a/b/c/", - "https://mozilla.org/a/b/c/#section1", - ], - "https://mozilla.org/*/b/*/": [ - "https://mozilla.org/a/b/c/", - "https://mozilla.org/d/b/f/", - "https://mozilla.org/a/b/c/d/", - "https://mozilla.org/a/b/c/d/#section1", - "https://mozilla.org/a/b/c/d/?foo=/", - "https://mozilla.org/a?foo=21314&bar=/b/&extra=c/", - ], - "*://www.google.com/*": [ - "https://www.google.com/://aa", - "https://www.google.com/preferences?prev=https://www.google.com/", - "https://www.google.com/preferences?prev=", - "https://www.google.com/", - ], - "*://localhost/*": [ - "http://localhost:8000/", - "https://localhost:3000/foo.html", - ], - "http://127.0.0.1/*": [ - "http://127.0.0.1/", - "http://127.0.0.1/foo/bar.html", - "http://127.0.0.1/?bar=1", - "http://127.0.0.1/foo?bar=1", - ], - "*://*.example.com/*?a=1*": [ - "http://example.com/?a=1", - "https://www.example.com/index?a=1&b=2", - ], - "*://*.example.com/path/": [ - "http://example.com/path/", - "http://a.example.com/path/", - "https://example.com/path/", - "https://a.b.example.com/path/", - "https://☁️.example.com/path/", - ], - "*://*.example.com/path/*": [ - "https://example.com/path/", - "https://example.com/path/foo", - "https://example.com/path/foo?bar", - "https://example.com/path/?foo=bar", - "https://example.com/path/☁️?☁️=🙂", - ], - ] - let patternDictFails = [ - "*://*/*": [ - "ftp://ftp.example.org/", // unmatched scheme) - "file:///a/", // unmatched scheme - ], - "*://*.mozilla.org/*": [ - "ftp://mozilla.org/", // unmatched scheme - "http://mozilla.com/", // unmatched host - "http://firefox.org/", // unmatched host - ], - "*://mozilla.org/": [ - "ftp://mozilla.org/", // unmatched scheme - "http://a.mozilla.org/", // unmatched host - "http://mozilla.org/a", // unmatched path - ], - "https://*/path": [ - "http://mozilla.org/path", // unmatched scheme - "https://mozilla.org/path/", // unmatched path - "https://mozilla.org/a", // unmatched path - "https://mozilla.org/", // unmatched path - "https://mozilla.org/path?foo=1", // unmatched path due to URL query string - ], - "https://*/path/": [ - "http://mozilla.org/path/", // unmatched scheme - "https://mozilla.org/path", // unmatched path - "https://mozilla.org/a", // unmatched path - "https://mozilla.org/", // unmatched path - "https://mozilla.org/path/?foo=1", // unmatched path due to URL query string - ], - "https://mozilla.org/*": [ - "http://mozilla.org/path", // unmatched scheme - "https://mozilla.com/path", // unmatched host - ], - "https://mozilla.org/*/b/*/": [ - "https://mozilla.org/b/*/", // unmatched path - "https://mozilla.org/a/b/", // unmatched path - "https://mozilla.org/a/b/c/d/?foo=bar", // unmatched path due to URL query string - ], - "https://www.example.com/*": [ - "file://www.example.com/", - "ftp://www.example.com/", - "ws://www.example.com/", - "http://www.example.com/", - ], - "http://www.example.com/index.html": [ - "http://www.example.com/", - "https://www.example.com/index.html", - ], - "*://localhost/*": [ - "https://localhost.com/", - "ftp://localhost:8080/", - ], - "https://www.example*/*": [ - "https://www.example.com/", - ], - "*://*.example.com/*?a=1*": [ - "http://example.com/", - "https://www.example.com/?a=2", - ], - "*://*.example.com/foo/": [ - "https://example.com/foo", - "https://example.com/foo?bar", - "https://example.com/foo/bar", - "https://example.com/foo/?bar", - ], - ] - for (pattern, urls) in patternDict { - for url in urls { - if !match(url, pattern) { - print(#function, "patternDict", url, pattern) - XCTAssert(false) - } - } - } - for (pattern, urls) in patternDictFails { - for url in urls { - if match(url, pattern) { - print(#function, "patternDictFails", url, pattern) - XCTAssert(false) - } - } - } - } - - func testPerformanceExample() throws { - // This is an example of a performance test case. - measure { - // Put the code you want to measure the time of here. - } - } - -} diff --git a/xcode/Userscripts.xcodeproj/project.pbxproj b/xcode/Userscripts.xcodeproj/project.pbxproj deleted file mode 100644 index 8708c6b7..00000000 --- a/xcode/Userscripts.xcodeproj/project.pbxproj +++ /dev/null @@ -1,928 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXBuildFile section */ - 007596BF2E10B67F008F8C04 /* AppIcon.icon in Resources */ = {isa = PBXBuildFile; fileRef = 007596BE2E10B67F008F8C04 /* AppIcon.icon */; }; - 007596C02E10B67F008F8C04 /* AppIcon.icon in Resources */ = {isa = PBXBuildFile; fileRef = 007596BE2E10B67F008F8C04 /* AppIcon.icon */; }; - 030C64F62AC62CC900548FBD /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 030C64F52AC62CC900548FBD /* Settings.bundle */; }; - 030C64FC2AD0B24C00548FBD /* Initialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030C64FB2AD0B24C00548FBD /* Initialization.swift */; }; - 030FCAD42B182008004D13CD /* UrlCodecTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030FCAD32B182008004D13CD /* UrlCodecTests.swift */; }; - 030FCADC2B189AAB004D13CD /* UrlPolyfill.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030FCAD52B1851F8004D13CD /* UrlPolyfill.swift */; }; - 030FCADD2B18BF70004D13CD /* UrlPolyfill.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030FCAD52B1851F8004D13CD /* UrlPolyfill.swift */; }; - 030FCADF2B18BF72004D13CD /* UrlPolyfill.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030FCAD52B1851F8004D13CD /* UrlPolyfill.swift */; }; - 032CBD3C2CBCF19A00B31D5E /* dist in Resources */ = {isa = PBXBuildFile; fileRef = 039F59522AD9591C002E9977 /* dist */; }; - 032CBD3D2CBCF1AB00B31D5E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4CF6E9270A38BD00111584 /* ViewController.swift */; }; - 032CBD3E2CBCF1AB00B31D5E /* USchemeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039F59552ADA2FE2002E9977 /* USchemeHandler.swift */; }; - 0336619F294DF7C900CFE179 /* Functions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0336619E294DF7C900CFE179 /* Functions.swift */; }; - 039F59532AD9591C002E9977 /* dist in Resources */ = {isa = PBXBuildFile; fileRef = 039F59522AD9591C002E9977 /* dist */; }; - 039F59562ADA2FE2002E9977 /* USchemeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039F59552ADA2FE2002E9977 /* USchemeHandler.swift */; }; - 03B81A152CB8466F00B3D17C /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B81A142CB8466B00B3D17C /* Logger.swift */; }; - 03B81A162CB8466F00B3D17C /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B81A142CB8466B00B3D17C /* Logger.swift */; }; - 03B81A172CB8466F00B3D17C /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B81A142CB8466B00B3D17C /* Logger.swift */; }; - 03B81A182CB8466F00B3D17C /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B81A142CB8466B00B3D17C /* Logger.swift */; }; - 03B81A192CB8466F00B3D17C /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B81A142CB8466B00B3D17C /* Logger.swift */; }; - 03C24F972ABD2CBB00F130F9 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C24F962ABD2CBB00F130F9 /* Preferences.swift */; }; - 03C24F982ABD2CBB00F130F9 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C24F962ABD2CBB00F130F9 /* Preferences.swift */; }; - 03C24F992ABD2CBB00F130F9 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C24F962ABD2CBB00F130F9 /* Preferences.swift */; }; - 03C24F9A2ABD2CBB00F130F9 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C24F962ABD2CBB00F130F9 /* Preferences.swift */; }; - 03C24F9B2ABD2CBB00F130F9 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C24F962ABD2CBB00F130F9 /* Preferences.swift */; }; - 03D4054B2CC66DC90091FE6F /* Shared.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 03D405482CC66DC90091FE6F /* Shared.xcassets */; }; - 03D4054D2CC66DC90091FE6F /* Shared.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 03D405482CC66DC90091FE6F /* Shared.xcassets */; }; - 03E20D06291E170000B4F692 /* dist in Resources */ = {isa = PBXBuildFile; fileRef = 03E20D05291E170000B4F692 /* dist */; }; - 03E20D07291E170000B4F692 /* dist in Resources */ = {isa = PBXBuildFile; fileRef = 03E20D05291E170000B4F692 /* dist */; }; - 4A143AAC279DE6FF0029BFD0 /* UserscriptsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A143AAB279DE6FF0029BFD0 /* UserscriptsTests.swift */; }; - 4A143AB2279DEA170029BFD0 /* Functions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AED6491268CDB58001794BF /* Functions.swift */; }; - 4A301B2A270A474400C7E9E1 /* SafariWebExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A57BA07227235CE008A9763 /* SafariWebExtensionHandler.swift */; }; - 4A301B2B270A474F00C7E9E1 /* _locales in Resources */ = {isa = PBXBuildFile; fileRef = 4A36A617268266B30018536B /* _locales */; }; - 4A301B2C270A475200C7E9E1 /* images in Resources */ = {isa = PBXBuildFile; fileRef = 4A36A616268266B30018536B /* images */; }; - 4A301B32270A49F200C7E9E1 /* Functions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AED6491268CDB58001794BF /* Functions.swift */; }; - 4A36A61A268266B30018536B /* images in Resources */ = {isa = PBXBuildFile; fileRef = 4A36A616268266B30018536B /* images */; }; - 4A36A61B268266B30018536B /* _locales in Resources */ = {isa = PBXBuildFile; fileRef = 4A36A617268266B30018536B /* _locales */; }; - 4A4CF6DE270A38BD00111584 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4CF6DD270A38BD00111584 /* AppDelegate.swift */; }; - 4A4CF6E8270A38BD00111584 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4CF6E7270A38BD00111584 /* SceneDelegate.swift */; }; - 4A4CF6EA270A38BD00111584 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4CF6E9270A38BD00111584 /* ViewController.swift */; }; - 4A4CF6ED270A38BD00111584 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4A4CF6EB270A38BD00111584 /* LaunchScreen.storyboard */; }; - 4A4CF6F0270A38BD00111584 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4A4CF6EE270A38BD00111584 /* Main.storyboard */; }; - 4A4CF6F8270A38BF00111584 /* Userscripts-iOS-Safari-Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 4A4CF6F7270A38BF00111584 /* Userscripts-iOS-Safari-Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 4A4CF710270A38BF00111584 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4A4CF6F1270A38BF00111584 /* Assets.xcassets */; }; - 4A57B9F2227235CD008A9763 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A57B9F1227235CD008A9763 /* AppDelegate.swift */; }; - 4A57B9F5227235CD008A9763 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4A57B9F3227235CD008A9763 /* Main.storyboard */; }; - 4A57B9F9227235CE008A9763 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4A57B9F8227235CE008A9763 /* Assets.xcassets */; }; - 4A57BA00227235CE008A9763 /* Userscripts-Mac-Safari-Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 4A57B9FF227235CE008A9763 /* Userscripts-Mac-Safari-Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 4A57BA08227235CE008A9763 /* SafariWebExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A57BA07227235CE008A9763 /* SafariWebExtensionHandler.swift */; }; - 4AED6492268CDB58001794BF /* Functions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AED6491268CDB58001794BF /* Functions.swift */; }; - 7878ED24299BA27B00E36A24 /* SafariWebExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A57BA07227235CE008A9763 /* SafariWebExtensionHandler.swift */; }; - 78B25583299D4C27000B2E9B /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78B25582299D4C27000B2E9B /* Utilities.swift */; }; - 78B25584299D4C27000B2E9B /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78B25582299D4C27000B2E9B /* Utilities.swift */; }; - 78B25585299D4C27000B2E9B /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78B25582299D4C27000B2E9B /* Utilities.swift */; }; - 78B25586299D4C27000B2E9B /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78B25582299D4C27000B2E9B /* Utilities.swift */; }; - 78B25587299D4C27000B2E9B /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78B25582299D4C27000B2E9B /* Utilities.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 4A143AAD279DE6FF0029BFD0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4A57B9E4227235CD008A9763 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4A57B9EB227235CD008A9763; - remoteInfo = Userscripts; - }; - 4A4CF6F9270A38BF00111584 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4A57B9E4227235CD008A9763 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4A4CF6F6270A38BF00111584; - remoteInfo = "Userscripts-iOS Extension"; - }; - 4A57BA01227235CE008A9763 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4A57B9E4227235CD008A9763 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4A57B9FE227235CE008A9763; - remoteInfo = "Userscripts Extension"; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 4A4CF713270A38BF00111584 /* Embed Foundation Extensions */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 13; - files = ( - 4A4CF6F8270A38BF00111584 /* Userscripts-iOS-Safari-Extension.appex in Embed Foundation Extensions */, - ); - name = "Embed Foundation Extensions"; - runOnlyForDeploymentPostprocessing = 0; - }; - 4A57BA19227235CE008A9763 /* Embed Foundation Extensions */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 13; - files = ( - 4A57BA00227235CE008A9763 /* Userscripts-Mac-Safari-Extension.appex in Embed Foundation Extensions */, - ); - name = "Embed Foundation Extensions"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 007596BE2E10B67F008F8C04 /* AppIcon.icon */ = {isa = PBXFileReference; lastKnownFileType = folder.iconcomposer.icon; path = AppIcon.icon; sourceTree = ""; }; - 030C64F52AC62CC900548FBD /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; - 030C64FB2AD0B24C00548FBD /* Initialization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Initialization.swift; sourceTree = ""; }; - 030FCAD32B182008004D13CD /* UrlCodecTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UrlCodecTests.swift; sourceTree = ""; }; - 030FCAD52B1851F8004D13CD /* UrlPolyfill.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UrlPolyfill.swift; sourceTree = ""; }; - 0336619E294DF7C900CFE179 /* Functions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Functions.swift; sourceTree = ""; }; - 039F59522AD9591C002E9977 /* dist */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dist; sourceTree = ""; }; - 039F59552ADA2FE2002E9977 /* USchemeHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = USchemeHandler.swift; sourceTree = ""; }; - 039F59662B03AE5A002E9977 /* Userscripts-Vite.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Userscripts-Vite.xcconfig"; sourceTree = ""; }; - 03B81A142CB8466B00B3D17C /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = ""; }; - 03C24F962ABD2CBB00F130F9 /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = ""; }; - 03D405482CC66DC90091FE6F /* Shared.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Shared.xcassets; sourceTree = ""; }; - 03E20D05291E170000B4F692 /* dist */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dist; sourceTree = ""; }; - 4A143AA9279DE6FF0029BFD0 /* Mac-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Mac-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 4A143AAB279DE6FF0029BFD0 /* UserscriptsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserscriptsTests.swift; sourceTree = ""; }; - 4A36A616268266B30018536B /* images */ = {isa = PBXFileReference; lastKnownFileType = folder; path = images; sourceTree = ""; }; - 4A36A617268266B30018536B /* _locales */ = {isa = PBXFileReference; lastKnownFileType = folder; path = _locales; sourceTree = ""; }; - 4A4CF6DB270A38BD00111584 /* Userscripts-iOS-App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Userscripts-iOS-App.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 4A4CF6DD270A38BD00111584 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 4A4CF6E7270A38BD00111584 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; - 4A4CF6E9270A38BD00111584 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 4A4CF6EC270A38BD00111584 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 4A4CF6EF270A38BD00111584 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 4A4CF6F1270A38BF00111584 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 4A4CF6F2270A38BF00111584 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 4A4CF6F7270A38BF00111584 /* Userscripts-iOS-Safari-Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Userscripts-iOS-Safari-Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; - 4A4CF718270A38C700111584 /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = ""; }; - 4A57B9EC227235CD008A9763 /* Userscripts-Debug.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Userscripts-Debug.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 4A57B9EF227235CD008A9763 /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = ""; }; - 4A57B9F1227235CD008A9763 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 4A57B9F4227235CD008A9763 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 4A57B9F8227235CE008A9763 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 4A57B9FA227235CE008A9763 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 4A57B9FF227235CE008A9763 /* Userscripts-Mac-Safari-Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Userscripts-Mac-Safari-Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; - 4A57BA07227235CE008A9763 /* SafariWebExtensionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariWebExtensionHandler.swift; sourceTree = ""; }; - 4A57BA0E227235CE008A9763 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 4A57BA1D227235E6008A9763 /* Mac.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Mac.entitlements; sourceTree = ""; }; - 4AD66D2026826D8100B004E8 /* manifest.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = manifest.json; sourceTree = ""; }; - 4AED6491268CDB58001794BF /* Functions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Functions.swift; sourceTree = ""; }; - 78391D4629A4CB3C00979E34 /* Userscripts-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Userscripts-Debug.xcconfig"; sourceTree = ""; }; - 78391D4729A4CB3C00979E34 /* Userscripts-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Userscripts-Release.xcconfig"; sourceTree = ""; }; - 7878ED2D299BA40800E36A24 /* iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = iOS.entitlements; sourceTree = ""; }; - 7878ED2F299BBEBF00E36A24 /* iOS-Safari-Extension.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "iOS-Safari-Extension.xcconfig"; sourceTree = ""; }; - 7878ED31299BBEBF00E36A24 /* Mac-Tests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Mac-Tests.xcconfig"; sourceTree = ""; }; - 7878ED32299BBEBF00E36A24 /* Mac-Safari-Extension.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Mac-Safari-Extension.xcconfig"; sourceTree = ""; }; - 7878ED34299BBEBF00E36A24 /* iOS-App.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "iOS-App.xcconfig"; sourceTree = ""; }; - 7878ED38299BBEBF00E36A24 /* Mac-App.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Mac-App.xcconfig"; sourceTree = ""; }; - 78B25582299D4C27000B2E9B /* Utilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utilities.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 4A143AA6279DE6FF0029BFD0 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A4CF6D8270A38BD00111584 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A4CF6F4270A38BF00111584 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A57B9E9227235CD008A9763 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A57B9FC227235CE008A9763 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 0316A9992AD7709600AAEC8A /* App-Shared */ = { - isa = PBXGroup; - children = ( - 039F59512AD95485002E9977 /* Resources */, - 007596BE2E10B67F008F8C04 /* AppIcon.icon */, - 03D405482CC66DC90091FE6F /* Shared.xcassets */, - 4A4CF6E9270A38BD00111584 /* ViewController.swift */, - 039F59552ADA2FE2002E9977 /* USchemeHandler.swift */, - ); - path = "App-Shared"; - sourceTree = ""; - }; - 039F59512AD95485002E9977 /* Resources */ = { - isa = PBXGroup; - children = ( - 039F59522AD9591C002E9977 /* dist */, - ); - path = Resources; - sourceTree = ""; - }; - 4A143AAA279DE6FF0029BFD0 /* Tests-Mac */ = { - isa = PBXGroup; - children = ( - 4A143AAB279DE6FF0029BFD0 /* UserscriptsTests.swift */, - 030FCAD32B182008004D13CD /* UrlCodecTests.swift */, - ); - path = "Tests-Mac"; - sourceTree = ""; - }; - 4A4CF6DC270A38BD00111584 /* App-iOS */ = { - isa = PBXGroup; - children = ( - 4A4CF6F2270A38BF00111584 /* Info.plist */, - 4A4CF718270A38C700111584 /* App.entitlements */, - 030C64F52AC62CC900548FBD /* Settings.bundle */, - 4A4CF6F1270A38BF00111584 /* Assets.xcassets */, - 4A4CF6DD270A38BD00111584 /* AppDelegate.swift */, - 4A4CF6E7270A38BD00111584 /* SceneDelegate.swift */, - 030C64FB2AD0B24C00548FBD /* Initialization.swift */, - 4A4CF6EB270A38BD00111584 /* LaunchScreen.storyboard */, - 4A4CF6EE270A38BD00111584 /* Main.storyboard */, - ); - path = "App-iOS"; - sourceTree = ""; - }; - 4A57B9E3227235CD008A9763 = { - isa = PBXGroup; - children = ( - 7878ED2E299BBEBF00E36A24 /* xcconfig */, - 78B25581299D4C27000B2E9B /* Shared */, - 4A57BA06227235CE008A9763 /* Ext-Safari */, - 0316A9992AD7709600AAEC8A /* App-Shared */, - 4A57B9EE227235CD008A9763 /* App-Mac */, - 4A4CF6DC270A38BD00111584 /* App-iOS */, - 4A143AAA279DE6FF0029BFD0 /* Tests-Mac */, - 4A57B9ED227235CD008A9763 /* Products */, - ); - sourceTree = ""; - usesTabs = 1; - }; - 4A57B9ED227235CD008A9763 /* Products */ = { - isa = PBXGroup; - children = ( - 4A57B9EC227235CD008A9763 /* Userscripts-Debug.app */, - 4A57B9FF227235CE008A9763 /* Userscripts-Mac-Safari-Extension.appex */, - 4A4CF6DB270A38BD00111584 /* Userscripts-iOS-App.app */, - 4A4CF6F7270A38BF00111584 /* Userscripts-iOS-Safari-Extension.appex */, - 4A143AA9279DE6FF0029BFD0 /* Mac-Tests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 4A57B9EE227235CD008A9763 /* App-Mac */ = { - isa = PBXGroup; - children = ( - 4A57B9FA227235CE008A9763 /* Info.plist */, - 4A57B9EF227235CD008A9763 /* App.entitlements */, - 4A57B9F8227235CE008A9763 /* Assets.xcassets */, - 4A57B9F1227235CD008A9763 /* AppDelegate.swift */, - 0336619E294DF7C900CFE179 /* Functions.swift */, - 4A57B9F3227235CD008A9763 /* Main.storyboard */, - ); - path = "App-Mac"; - sourceTree = ""; - }; - 4A57BA06227235CE008A9763 /* Ext-Safari */ = { - isa = PBXGroup; - children = ( - 4A57BA0E227235CE008A9763 /* Info.plist */, - 4A57BA1D227235E6008A9763 /* Mac.entitlements */, - 7878ED2D299BA40800E36A24 /* iOS.entitlements */, - 4AF1DD0D268265DB00086E88 /* Resources */, - 4A57BA07227235CE008A9763 /* SafariWebExtensionHandler.swift */, - 4AED6491268CDB58001794BF /* Functions.swift */, - ); - path = "Ext-Safari"; - sourceTree = ""; - }; - 4AF1DD0D268265DB00086E88 /* Resources */ = { - isa = PBXGroup; - children = ( - 4A36A617268266B30018536B /* _locales */, - 4A36A616268266B30018536B /* images */, - 03E20D05291E170000B4F692 /* dist */, - 4AD66D2026826D8100B004E8 /* manifest.json */, - ); - path = Resources; - sourceTree = ""; - }; - 7878ED2E299BBEBF00E36A24 /* xcconfig */ = { - isa = PBXGroup; - children = ( - 039F59662B03AE5A002E9977 /* Userscripts-Vite.xcconfig */, - 78391D4629A4CB3C00979E34 /* Userscripts-Debug.xcconfig */, - 78391D4729A4CB3C00979E34 /* Userscripts-Release.xcconfig */, - 7878ED38299BBEBF00E36A24 /* Mac-App.xcconfig */, - 7878ED32299BBEBF00E36A24 /* Mac-Safari-Extension.xcconfig */, - 7878ED34299BBEBF00E36A24 /* iOS-App.xcconfig */, - 7878ED2F299BBEBF00E36A24 /* iOS-Safari-Extension.xcconfig */, - 7878ED31299BBEBF00E36A24 /* Mac-Tests.xcconfig */, - ); - path = xcconfig; - sourceTree = ""; - }; - 78B25581299D4C27000B2E9B /* Shared */ = { - isa = PBXGroup; - children = ( - 03B81A142CB8466B00B3D17C /* Logger.swift */, - 78B25582299D4C27000B2E9B /* Utilities.swift */, - 03C24F962ABD2CBB00F130F9 /* Preferences.swift */, - 030FCAD52B1851F8004D13CD /* UrlPolyfill.swift */, - ); - path = Shared; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 4A143AA8279DE6FF0029BFD0 /* Mac-Tests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4A143AB1279DE6FF0029BFD0 /* Build configuration list for PBXNativeTarget "Mac-Tests" */; - buildPhases = ( - 4A143AA5279DE6FF0029BFD0 /* Sources */, - 4A143AA6279DE6FF0029BFD0 /* Frameworks */, - 4A143AA7279DE6FF0029BFD0 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 4A143AAE279DE6FF0029BFD0 /* PBXTargetDependency */, - ); - name = "Mac-Tests"; - productName = "Mac-Tests"; - productReference = 4A143AA9279DE6FF0029BFD0 /* Mac-Tests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 4A4CF6DA270A38BD00111584 /* iOS-App */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4A4CF717270A38BF00111584 /* Build configuration list for PBXNativeTarget "iOS-App" */; - buildPhases = ( - 4A4CF6D7270A38BD00111584 /* Sources */, - 4A4CF6D8270A38BD00111584 /* Frameworks */, - 4A4CF6D9270A38BD00111584 /* Resources */, - 4A4CF713270A38BF00111584 /* Embed Foundation Extensions */, - 030C64F72AC713A600548FBD /* UScript: Introduce values to app Settings.bundle */, - ); - buildRules = ( - ); - dependencies = ( - 4A4CF6FA270A38BF00111584 /* PBXTargetDependency */, - ); - name = "iOS-App"; - productName = "iOS-App"; - productReference = 4A4CF6DB270A38BD00111584 /* Userscripts-iOS-App.app */; - productType = "com.apple.product-type.application"; - }; - 4A4CF6F6270A38BF00111584 /* iOS-Safari-Extension */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4A4CF716270A38BF00111584 /* Build configuration list for PBXNativeTarget "iOS-Safari-Extension" */; - buildPhases = ( - 4A4CF6F3270A38BF00111584 /* Sources */, - 4A4CF6F4270A38BF00111584 /* Frameworks */, - 4A4CF6F5270A38BF00111584 /* Resources */, - 039F59592ADFA415002E9977 /* UScript: Produce ext manifest.json */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "iOS-Safari-Extension"; - productName = "iOS-Safari-Extension"; - productReference = 4A4CF6F7270A38BF00111584 /* Userscripts-iOS-Safari-Extension.appex */; - productType = "com.apple.product-type.app-extension"; - }; - 4A57B9EB227235CD008A9763 /* Mac-App */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4A57BA1A227235CE008A9763 /* Build configuration list for PBXNativeTarget "Mac-App" */; - buildPhases = ( - 4A57B9E8227235CD008A9763 /* Sources */, - 4A57B9E9227235CD008A9763 /* Frameworks */, - 4A57B9EA227235CD008A9763 /* Resources */, - 4A57BA19227235CE008A9763 /* Embed Foundation Extensions */, - ); - buildRules = ( - ); - dependencies = ( - 4A57BA02227235CE008A9763 /* PBXTargetDependency */, - ); - name = "Mac-App"; - productName = "Mac-App"; - productReference = 4A57B9EC227235CD008A9763 /* Userscripts-Debug.app */; - productType = "com.apple.product-type.application"; - }; - 4A57B9FE227235CE008A9763 /* Mac-Safari-Extension */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4A57BA16227235CE008A9763 /* Build configuration list for PBXNativeTarget "Mac-Safari-Extension" */; - buildPhases = ( - 4A57B9FB227235CE008A9763 /* Sources */, - 4A57B9FC227235CE008A9763 /* Frameworks */, - 4A57B9FD227235CE008A9763 /* Resources */, - 039F59572ADF9558002E9977 /* UScript: Produce ext manifest.json */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Mac-Safari-Extension"; - productName = "Mac-Safari-Extension"; - productReference = 4A57B9FF227235CE008A9763 /* Userscripts-Mac-Safari-Extension.appex */; - productType = "com.apple.product-type.app-extension"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 4A57B9E4227235CD008A9763 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastSwiftUpdateCheck = 1320; - LastUpgradeCheck = 1420; - ORGANIZATIONNAME = "Justin Wasack"; - TargetAttributes = { - 4A143AA8279DE6FF0029BFD0 = { - CreatedOnToolsVersion = 13.2.1; - TestTargetID = 4A57B9EB227235CD008A9763; - }; - 4A4CF6DA270A38BD00111584 = { - CreatedOnToolsVersion = 13.0; - }; - 4A4CF6F6270A38BF00111584 = { - CreatedOnToolsVersion = 13.0; - }; - 4A57B9EB227235CD008A9763 = { - CreatedOnToolsVersion = 10.2.1; - }; - 4A57B9FE227235CE008A9763 = { - CreatedOnToolsVersion = 10.2.1; - SystemCapabilities = { - com.apple.Sandbox = { - enabled = 1; - }; - }; - }; - }; - }; - buildConfigurationList = 4A57B9E7227235CD008A9763 /* Build configuration list for PBXProject "Userscripts" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 4A57B9E3227235CD008A9763; - productRefGroup = 4A57B9ED227235CD008A9763 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 4A57B9EB227235CD008A9763 /* Mac-App */, - 4A57B9FE227235CE008A9763 /* Mac-Safari-Extension */, - 4A4CF6DA270A38BD00111584 /* iOS-App */, - 4A4CF6F6270A38BF00111584 /* iOS-Safari-Extension */, - 4A143AA8279DE6FF0029BFD0 /* Mac-Tests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 4A143AA7279DE6FF0029BFD0 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A4CF6D9270A38BD00111584 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4A4CF6F0270A38BD00111584 /* Main.storyboard in Resources */, - 4A4CF6ED270A38BD00111584 /* LaunchScreen.storyboard in Resources */, - 03D4054B2CC66DC90091FE6F /* Shared.xcassets in Resources */, - 007596BF2E10B67F008F8C04 /* AppIcon.icon in Resources */, - 030C64F62AC62CC900548FBD /* Settings.bundle in Resources */, - 4A4CF710270A38BF00111584 /* Assets.xcassets in Resources */, - 039F59532AD9591C002E9977 /* dist in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A4CF6F5270A38BF00111584 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4A301B2C270A475200C7E9E1 /* images in Resources */, - 03E20D07291E170000B4F692 /* dist in Resources */, - 4A301B2B270A474F00C7E9E1 /* _locales in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A57B9EA227235CD008A9763 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4A57B9F9227235CE008A9763 /* Assets.xcassets in Resources */, - 032CBD3C2CBCF19A00B31D5E /* dist in Resources */, - 007596C02E10B67F008F8C04 /* AppIcon.icon in Resources */, - 03D4054D2CC66DC90091FE6F /* Shared.xcassets in Resources */, - 4A57B9F5227235CD008A9763 /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A57B9FD227235CE008A9763 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E20D06291E170000B4F692 /* dist in Resources */, - 4A36A61A268266B30018536B /* images in Resources */, - 4A36A61B268266B30018536B /* _locales in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 030C64F72AC713A600548FBD /* UScript: Introduce values to app Settings.bundle */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "$(SRCROOT)/$(SRC_DIR)/Settings.bundle/Root.plist", - "$(TARGET_BUILD_DIR)/$(INFOPLIST_PATH)", - ); - name = "UScript: Introduce values to app Settings.bundle"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(TARGET_BUILD_DIR)/$(EXECUTABLE_FOLDER_PATH)/Settings.bundle/Root.plist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "# Dynamically introduce US_SHARED_GID in xcconfig for Settings.bundle\nUS_SHARED_GID=$(/usr/libexec/PlistBuddy -c \"Print US_SHARED_GID\" \"$TARGET_BUILD_DIR/$INFOPLIST_PATH\")\nSETTINGS_BUNDLE=$TARGET_BUILD_DIR/$EXECUTABLE_FOLDER_PATH/Settings.bundle/Root.plist\n/usr/libexec/PlistBuddy -c \"Set ApplicationGroupContainerIdentifier $US_SHARED_GID\" \"$SETTINGS_BUNDLE\"\n"; - }; - 039F59572ADF9558002E9977 /* UScript: Produce ext manifest.json */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "$(SRCROOT)/$(MANIFEST_FILE)", - "$(SRCROOT)/$(SRC_DIR)/Resources/_locales/en/messages.json", - "$(TARGET_BUILD_DIR)/$(INFOPLIST_PATH)", - ); - name = "UScript: Produce ext manifest.json"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(TARGET_BUILD_DIR)/$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/manifest.json", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "sed \"s/_VERSION_/$MARKETING_VERSION/\" $SRCROOT/$MANIFEST_FILE > $TARGET_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/manifest.json\nsed -i \"\" \"s/_NAME_/$MANIFEST_NAME/\" $TARGET_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/_locales/en/messages.json\n"; - }; - 039F59592ADFA415002E9977 /* UScript: Produce ext manifest.json */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "$(SRCROOT)/$(MANIFEST_FILE)", - "$(SRCROOT)/$(SRC_DIR)/Resources/_locales/en/messages.json", - "$(TARGET_BUILD_DIR)/$(INFOPLIST_PATH)", - ); - name = "UScript: Produce ext manifest.json"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(TARGET_BUILD_DIR)/$(CONTENTS_FOLDER_PATH)/manifest.json", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "sed \"s/_VERSION_/$MARKETING_VERSION/\" $SRCROOT/$MANIFEST_FILE > $TARGET_BUILD_DIR/$CONTENTS_FOLDER_PATH/manifest.json\nsed -i \"\" \"s/_NAME_/$MANIFEST_NAME/\" $TARGET_BUILD_DIR/$CONTENTS_FOLDER_PATH/_locales/en/messages.json\n"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 4A143AA5279DE6FF0029BFD0 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7878ED24299BA27B00E36A24 /* SafariWebExtensionHandler.swift in Sources */, - 030FCADC2B189AAB004D13CD /* UrlPolyfill.swift in Sources */, - 030FCAD42B182008004D13CD /* UrlCodecTests.swift in Sources */, - 4A143AB2279DEA170029BFD0 /* Functions.swift in Sources */, - 03C24F9B2ABD2CBB00F130F9 /* Preferences.swift in Sources */, - 78B25587299D4C27000B2E9B /* Utilities.swift in Sources */, - 4A143AAC279DE6FF0029BFD0 /* UserscriptsTests.swift in Sources */, - 03B81A152CB8466F00B3D17C /* Logger.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A4CF6D7270A38BD00111584 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4A4CF6EA270A38BD00111584 /* ViewController.swift in Sources */, - 4A4CF6DE270A38BD00111584 /* AppDelegate.swift in Sources */, - 03C24F992ABD2CBB00F130F9 /* Preferences.swift in Sources */, - 030C64FC2AD0B24C00548FBD /* Initialization.swift in Sources */, - 78B25585299D4C27000B2E9B /* Utilities.swift in Sources */, - 4A4CF6E8270A38BD00111584 /* SceneDelegate.swift in Sources */, - 039F59562ADA2FE2002E9977 /* USchemeHandler.swift in Sources */, - 03B81A162CB8466F00B3D17C /* Logger.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A4CF6F3270A38BF00111584 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 78B25586299D4C27000B2E9B /* Utilities.swift in Sources */, - 03B81A182CB8466F00B3D17C /* Logger.swift in Sources */, - 4A301B2A270A474400C7E9E1 /* SafariWebExtensionHandler.swift in Sources */, - 030FCADD2B18BF70004D13CD /* UrlPolyfill.swift in Sources */, - 03C24F9A2ABD2CBB00F130F9 /* Preferences.swift in Sources */, - 4A301B32270A49F200C7E9E1 /* Functions.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A57B9E8227235CD008A9763 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03B81A172CB8466F00B3D17C /* Logger.swift in Sources */, - 4A57B9F2227235CD008A9763 /* AppDelegate.swift in Sources */, - 03C24F972ABD2CBB00F130F9 /* Preferences.swift in Sources */, - 78B25583299D4C27000B2E9B /* Utilities.swift in Sources */, - 0336619F294DF7C900CFE179 /* Functions.swift in Sources */, - 032CBD3D2CBCF1AB00B31D5E /* ViewController.swift in Sources */, - 032CBD3E2CBCF1AB00B31D5E /* USchemeHandler.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A57B9FB227235CE008A9763 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 78B25584299D4C27000B2E9B /* Utilities.swift in Sources */, - 03B81A192CB8466F00B3D17C /* Logger.swift in Sources */, - 4A57BA08227235CE008A9763 /* SafariWebExtensionHandler.swift in Sources */, - 030FCADF2B18BF72004D13CD /* UrlPolyfill.swift in Sources */, - 03C24F982ABD2CBB00F130F9 /* Preferences.swift in Sources */, - 4AED6492268CDB58001794BF /* Functions.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 4A143AAE279DE6FF0029BFD0 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 4A57B9EB227235CD008A9763 /* Mac-App */; - targetProxy = 4A143AAD279DE6FF0029BFD0 /* PBXContainerItemProxy */; - }; - 4A4CF6FA270A38BF00111584 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 4A4CF6F6270A38BF00111584 /* iOS-Safari-Extension */; - targetProxy = 4A4CF6F9270A38BF00111584 /* PBXContainerItemProxy */; - }; - 4A57BA02227235CE008A9763 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 4A57B9FE227235CE008A9763 /* Mac-Safari-Extension */; - targetProxy = 4A57BA01227235CE008A9763 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 4A4CF6EB270A38BD00111584 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 4A4CF6EC270A38BD00111584 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; - 4A4CF6EE270A38BD00111584 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 4A4CF6EF270A38BD00111584 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 4A57B9F3227235CD008A9763 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 4A57B9F4227235CD008A9763 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 039F59602B03A48A002E9977 /* Vite */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 039F59662B03AE5A002E9977 /* Userscripts-Vite.xcconfig */; - buildSettings = { - }; - name = Vite; - }; - 039F59612B03A48A002E9977 /* Vite */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7878ED38299BBEBF00E36A24 /* Mac-App.xcconfig */; - buildSettings = { - }; - name = Vite; - }; - 039F59622B03A48A002E9977 /* Vite */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7878ED32299BBEBF00E36A24 /* Mac-Safari-Extension.xcconfig */; - buildSettings = { - }; - name = Vite; - }; - 039F59632B03A48A002E9977 /* Vite */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7878ED34299BBEBF00E36A24 /* iOS-App.xcconfig */; - buildSettings = { - }; - name = Vite; - }; - 039F59642B03A48A002E9977 /* Vite */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7878ED2F299BBEBF00E36A24 /* iOS-Safari-Extension.xcconfig */; - buildSettings = { - }; - name = Vite; - }; - 039F59652B03A48A002E9977 /* Vite */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7878ED31299BBEBF00E36A24 /* Mac-Tests.xcconfig */; - buildSettings = { - }; - name = Vite; - }; - 4A143AAF279DE6FF0029BFD0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7878ED31299BBEBF00E36A24 /* Mac-Tests.xcconfig */; - buildSettings = { - }; - name = Debug; - }; - 4A143AB0279DE6FF0029BFD0 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7878ED31299BBEBF00E36A24 /* Mac-Tests.xcconfig */; - buildSettings = { - }; - name = Release; - }; - 4A4CF711270A38BF00111584 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7878ED34299BBEBF00E36A24 /* iOS-App.xcconfig */; - buildSettings = { - }; - name = Debug; - }; - 4A4CF712270A38BF00111584 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7878ED34299BBEBF00E36A24 /* iOS-App.xcconfig */; - buildSettings = { - }; - name = Release; - }; - 4A4CF714270A38BF00111584 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7878ED2F299BBEBF00E36A24 /* iOS-Safari-Extension.xcconfig */; - buildSettings = { - }; - name = Debug; - }; - 4A4CF715270A38BF00111584 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7878ED2F299BBEBF00E36A24 /* iOS-Safari-Extension.xcconfig */; - buildSettings = { - }; - name = Release; - }; - 4A57BA14227235CE008A9763 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 78391D4629A4CB3C00979E34 /* Userscripts-Debug.xcconfig */; - buildSettings = { - }; - name = Debug; - }; - 4A57BA15227235CE008A9763 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 78391D4729A4CB3C00979E34 /* Userscripts-Release.xcconfig */; - buildSettings = { - }; - name = Release; - }; - 4A57BA17227235CE008A9763 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7878ED32299BBEBF00E36A24 /* Mac-Safari-Extension.xcconfig */; - buildSettings = { - }; - name = Debug; - }; - 4A57BA18227235CE008A9763 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7878ED32299BBEBF00E36A24 /* Mac-Safari-Extension.xcconfig */; - buildSettings = { - }; - name = Release; - }; - 4A57BA1B227235CE008A9763 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7878ED38299BBEBF00E36A24 /* Mac-App.xcconfig */; - buildSettings = { - }; - name = Debug; - }; - 4A57BA1C227235CE008A9763 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7878ED38299BBEBF00E36A24 /* Mac-App.xcconfig */; - buildSettings = { - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 4A143AB1279DE6FF0029BFD0 /* Build configuration list for PBXNativeTarget "Mac-Tests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 039F59652B03A48A002E9977 /* Vite */, - 4A143AAF279DE6FF0029BFD0 /* Debug */, - 4A143AB0279DE6FF0029BFD0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - 4A4CF716270A38BF00111584 /* Build configuration list for PBXNativeTarget "iOS-Safari-Extension" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 039F59642B03A48A002E9977 /* Vite */, - 4A4CF714270A38BF00111584 /* Debug */, - 4A4CF715270A38BF00111584 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - 4A4CF717270A38BF00111584 /* Build configuration list for PBXNativeTarget "iOS-App" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 039F59632B03A48A002E9977 /* Vite */, - 4A4CF711270A38BF00111584 /* Debug */, - 4A4CF712270A38BF00111584 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - 4A57B9E7227235CD008A9763 /* Build configuration list for PBXProject "Userscripts" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 039F59602B03A48A002E9977 /* Vite */, - 4A57BA14227235CE008A9763 /* Debug */, - 4A57BA15227235CE008A9763 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - 4A57BA16227235CE008A9763 /* Build configuration list for PBXNativeTarget "Mac-Safari-Extension" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 039F59622B03A48A002E9977 /* Vite */, - 4A57BA17227235CE008A9763 /* Debug */, - 4A57BA18227235CE008A9763 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - 4A57BA1A227235CE008A9763 /* Build configuration list for PBXNativeTarget "Mac-App" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 039F59612B03A48A002E9977 /* Vite */, - 4A57BA1B227235CE008A9763 /* Debug */, - 4A57BA1C227235CE008A9763 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; -/* End XCConfigurationList section */ - }; - rootObject = 4A57B9E4227235CD008A9763 /* Project object */; -} diff --git a/xcode/Userscripts.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/xcode/Userscripts.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 91c880ee..00000000 --- a/xcode/Userscripts.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/xcode/Userscripts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/xcode/Userscripts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/xcode/Userscripts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/xcode/Userscripts.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/xcode/Userscripts.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5..00000000 --- a/xcode/Userscripts.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/xcode/Userscripts.xcodeproj/xcshareddata/xcschemes/Mac-Vite-Dev.xcscheme b/xcode/Userscripts.xcodeproj/xcshareddata/xcschemes/Mac-Vite-Dev.xcscheme deleted file mode 100644 index 0a3c056b..00000000 --- a/xcode/Userscripts.xcodeproj/xcshareddata/xcschemes/Mac-Vite-Dev.xcscheme +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/xcode/Userscripts.xcodeproj/xcshareddata/xcschemes/Mac.xcscheme b/xcode/Userscripts.xcodeproj/xcshareddata/xcschemes/Mac.xcscheme deleted file mode 100644 index d78f492e..00000000 --- a/xcode/Userscripts.xcodeproj/xcshareddata/xcschemes/Mac.xcscheme +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/xcode/Userscripts.xcodeproj/xcshareddata/xcschemes/iOS-Vite-Dev.xcscheme b/xcode/Userscripts.xcodeproj/xcshareddata/xcschemes/iOS-Vite-Dev.xcscheme deleted file mode 100644 index c87e739c..00000000 --- a/xcode/Userscripts.xcodeproj/xcshareddata/xcschemes/iOS-Vite-Dev.xcscheme +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/xcode/Userscripts.xcodeproj/xcshareddata/xcschemes/iOS.xcscheme b/xcode/Userscripts.xcodeproj/xcshareddata/xcschemes/iOS.xcscheme deleted file mode 100644 index 9c0ceed5..00000000 --- a/xcode/Userscripts.xcodeproj/xcshareddata/xcschemes/iOS.xcscheme +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/xcode/xcconfig/Mac-App.xcconfig b/xcode/xcconfig/Mac-App.xcconfig deleted file mode 100644 index 81ab00d6..00000000 --- a/xcode/xcconfig/Mac-App.xcconfig +++ /dev/null @@ -1,23 +0,0 @@ -SRC_DIR = App-Mac -ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon -CODE_SIGN_ENTITLEMENTS = $(SRC_DIR)/App.entitlements -COMBINE_HIDPI_IMAGES = YES -ENABLE_HARDENED_RUNTIME = YES -GENERATE_INFOPLIST_FILE = YES -INFOPLIST_FILE = $(SRC_DIR)/Info.plist -INFOPLIST_KEY_CFBundleDisplayName = $(PROJECT_NAME)-$(TARGET_NAME) -INFOPLIST_KEY_CFBundleDisplayName[config=Debug] = $(PROJECT_NAME)-$(TARGET_NAME)-Debug -INFOPLIST_KEY_CFBundleDisplayName[config=Vite] = $(PROJECT_NAME)-$(TARGET_NAME)-Vite -LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Frameworks -PRODUCT_BUNDLE_IDENTIFIER = $(APP_IDENTIFIER) -PRODUCT_NAME = $(PROJECT_NAME) -PRODUCT_NAME[config=Debug] = $(PROJECT_NAME)-Debug -PRODUCT_NAME[config=Vite] = $(PROJECT_NAME)-Vite -SWIFT_ACTIVE_COMPILATION_CONDITIONS = APP $(inherited) - -// Provisioning Profile -PROVISIONING_PROFILE_SPECIFIER[config=Release] = match AppStore $(APP_IDENTIFIER) macos - -// Override this file -#include? "Mac-App.dev.xcconfig" diff --git a/xcode/xcconfig/Mac-Safari-Extension.xcconfig b/xcode/xcconfig/Mac-Safari-Extension.xcconfig deleted file mode 100644 index 07b33fb0..00000000 --- a/xcode/xcconfig/Mac-Safari-Extension.xcconfig +++ /dev/null @@ -1,20 +0,0 @@ -// Shared config file -#include? "Safari-Extension.xcconfig" - -CODE_SIGN_ENTITLEMENTS = $(SRC_DIR)/Mac.entitlements -ENABLE_HARDENED_RUNTIME = YES -GENERATE_INFOPLIST_FILE = YES -INFOPLIST_FILE = $(SRC_DIR)/Info.plist -INFOPLIST_KEY_CFBundleDisplayName = $(PRODUCT_NAME) -INFOPLIST_KEY_CFBundleDisplayName[config=Debug] = $(PRODUCT_NAME)-Debug -LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks -PRODUCT_BUNDLE_IDENTIFIER = $(EXT_IDENTIFIER) -PRODUCT_NAME = $(PROJECT_NAME)-$(TARGET_NAME) -SKIP_INSTALL = YES -SWIFT_ACTIVE_COMPILATION_CONDITIONS = EXT $(inherited) - -// Provisioning Profile -PROVISIONING_PROFILE_SPECIFIER[config=Release] = match AppStore $(EXT_IDENTIFIER) macos - -// Override this file -#include? "Mac-Safari-Extension.dev.xcconfig" diff --git a/xcode/xcconfig/Mac-Tests.xcconfig b/xcode/xcconfig/Mac-Tests.xcconfig deleted file mode 100644 index 01a14d09..00000000 --- a/xcode/xcconfig/Mac-Tests.xcconfig +++ /dev/null @@ -1,11 +0,0 @@ -BUNDLE_LOADER = $(TEST_HOST) -CURRENT_PROJECT_VERSION = 1 -GENERATE_INFOPLIST_FILE = YES -MARKETING_VERSION = 1.0 -PRODUCT_BUNDLE_IDENTIFIER = $(ORG_IDENTIFIER).UserscriptsTests -PRODUCT_NAME = $(TARGET_NAME) -SWIFT_EMIT_LOC_STRINGS = NO -TEST_HOST = $(BUILT_PRODUCTS_DIR)/Userscripts-Debug.app/Contents/MacOS/Userscripts-Debug - -// Override this file -#include? "Mac-Tests.dev.xcconfig" diff --git a/xcode/xcconfig/Safari-Extension.xcconfig b/xcode/xcconfig/Safari-Extension.xcconfig deleted file mode 100644 index d2724321..00000000 --- a/xcode/xcconfig/Safari-Extension.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -SRC_DIR = Ext-Safari -MANIFEST_FILE = $(SRC_DIR)/Resources/manifest.json -MANIFEST_NAME = $(PROJECT_NAME) -MANIFEST_NAME[config=Debug] = $(PROJECT_NAME)-Debug -MANIFEST_NAME[config=Vite] = $(PROJECT_NAME)-Vite \ No newline at end of file diff --git a/xcode/xcconfig/Userscripts-Base.xcconfig b/xcode/xcconfig/Userscripts-Base.xcconfig deleted file mode 100644 index 505bf3a9..00000000 --- a/xcode/xcconfig/Userscripts-Base.xcconfig +++ /dev/null @@ -1,65 +0,0 @@ -ALWAYS_SEARCH_USER_PATHS = NO -CLANG_ANALYZER_NONNULL = YES -CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE -CLANG_CXX_LIBRARY = libc++ -CLANG_ENABLE_MODULES = YES -CLANG_ENABLE_OBJC_ARC = YES -CLANG_ENABLE_OBJC_WEAK = YES -CLANG_WARN__DUPLICATE_METHOD_MATCH = YES -CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES -CLANG_WARN_BOOL_CONVERSION = YES -CLANG_WARN_COMMA = YES -CLANG_WARN_CONSTANT_CONVERSION = YES -CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES -CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR -CLANG_WARN_DOCUMENTATION_COMMENTS = YES -CLANG_WARN_EMPTY_BODY = YES -CLANG_WARN_ENUM_CONVERSION = YES -CLANG_WARN_INFINITE_RECURSION = YES -CLANG_WARN_INT_CONVERSION = YES -CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES -CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES -CLANG_WARN_OBJC_LITERAL_CONVERSION = YES -CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR -CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES -CLANG_WARN_RANGE_LOOP_ANALYSIS = YES -CLANG_WARN_STRICT_PROTOTYPES = YES -CLANG_WARN_SUSPICIOUS_MOVE = YES -CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE -CLANG_WARN_UNREACHABLE_CODE = YES -CODE_SIGN_IDENTITY = Apple Development -CODE_SIGN_STYLE = Automatic -COPY_PHASE_STRIP = NO -DEAD_CODE_STRIPPING = YES -DEBUG_INFORMATION_FORMAT[config=Debug] = dwarf -DEBUG_INFORMATION_FORMAT[config=Release] = dwarf-with-dsym -ENABLE_NS_ASSERTIONS[config=Release] = NO -ENABLE_STRICT_OBJC_MSGSEND = YES -ENABLE_TESTABILITY[config=Debug] = YES -GCC_C_LANGUAGE_STANDARD = gnu11 -GCC_DYNAMIC_NO_PIC[config=Debug] = NO -GCC_NO_COMMON_BLOCKS = YES -GCC_OPTIMIZATION_LEVEL[config=Debug] = 0 -GCC_PREPROCESSOR_DEFINITIONS[config=Debug] = DEBUG=1 $(inherited) -GCC_WARN_64_TO_32_BIT_CONVERSION = YES -GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR -GCC_WARN_UNDECLARED_SELECTOR = YES -GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE -GCC_WARN_UNUSED_FUNCTION = YES -GCC_WARN_UNUSED_VARIABLE = YES -IPHONEOS_DEPLOYMENT_TARGET = 15.0 -MACOSX_DEPLOYMENT_TARGET = 12.0 -MTL_ENABLE_DEBUG_INFO[config=Debug] = INCLUDE_SOURCE -MTL_ENABLE_DEBUG_INFO[config=Release] = NO -MTL_FAST_MATH = YES -ONLY_ACTIVE_ARCH[config=Debug] = YES -SDKROOT = macosx -SWIFT_ACTIVE_COMPILATION_CONDITIONS[config=Debug] = DEBUG $(inherited) -SWIFT_ACTIVE_COMPILATION_CONDITIONS[config=Vite] = DEBUG VITE $(inherited) -SWIFT_COMPILATION_MODE[config=Release] = wholemodule -SWIFT_OPTIMIZATION_LEVEL[config=Debug] = -Onone -SWIFT_OPTIMIZATION_LEVEL[config=Release] = -O -SWIFT_VERSION = 5.0 - -// Override this file -#include? "Userscripts-Base.dev.xcconfig" diff --git a/xcode/xcconfig/Userscripts-Debug.xcconfig b/xcode/xcconfig/Userscripts-Debug.xcconfig deleted file mode 100644 index 8d2ac4cd..00000000 --- a/xcode/xcconfig/Userscripts-Debug.xcconfig +++ /dev/null @@ -1,24 +0,0 @@ -#include "Userscripts-Base.xcconfig" - -INFOPLIST_KEY_NSHumanReadableCopyright = Copyright © Userscripts -CURRENT_PROJECT_VERSION = 1 -MARKETING_VERSION = 1.0.0 - -// Development -CODE_SIGN_IDENTITY = Apple Development -// Developer Team ID -DEVELOPMENT_TEAM = XXXXXXXXXX -// Organization Identifier -ORG_IDENTIFIER = dev.debug -// Application Identifier -APP_IDENTIFIER = $(ORG_IDENTIFIER).userscripts -// Safari Extension Identifier -EXT_IDENTIFIER = $(APP_IDENTIFIER).ext.safari -// App Groups and Group Containers -IOS_SHARED_GID = group.$(ORG_IDENTIFIER).userscripts -MAC_SHARED_GID = $(DEVELOPMENT_TEAM).$(ORG_IDENTIFIER).userscripts -// App URL Scheme -APP_URL_SCHEME = userscriptsdebug - -// Override this file -#include? "Userscripts-Debug.dev.xcconfig" diff --git a/xcode/xcconfig/Userscripts-Release.xcconfig b/xcode/xcconfig/Userscripts-Release.xcconfig deleted file mode 100644 index 8c52d66b..00000000 --- a/xcode/xcconfig/Userscripts-Release.xcconfig +++ /dev/null @@ -1,26 +0,0 @@ -#include "Userscripts-Base.xcconfig" - -INFOPLIST_KEY_NSHumanReadableCopyright = Copyright © 2018–2025 Justin Wasack. All rights reserved. -CURRENT_PROJECT_VERSION = 1 -MARKETING_VERSION = 1.0.0 - -// Distribution -CODE_SIGN_STYLE = Manual -CODE_SIGN_IDENTITY = Apple Distribution -// Developer Team ID -DEVELOPMENT_TEAM = J74Q8V8V8N -// Organization Identifier -ORG_IDENTIFIER = com.userscripts -// Application Identifier -APP_IDENTIFIER = $(ORG_IDENTIFIER).macos -// Safari Extension Identifier -EXT_IDENTIFIER = $(APP_IDENTIFIER).Userscripts-Extension -// App Groups and Group Containers -// https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_application-groups -IOS_SHARED_GID = group.$(ORG_IDENTIFIER).ios -MAC_SHARED_GID = $(DEVELOPMENT_TEAM).$(ORG_IDENTIFIER).macos -// App URL Scheme -APP_URL_SCHEME = userscriptsurlscheme - -// Override this file -#include? "Userscripts-Release.dev.xcconfig" diff --git a/xcode/xcconfig/Userscripts-Vite.xcconfig b/xcode/xcconfig/Userscripts-Vite.xcconfig deleted file mode 100644 index 6224a75b..00000000 --- a/xcode/xcconfig/Userscripts-Vite.xcconfig +++ /dev/null @@ -1,24 +0,0 @@ -#include "Userscripts-Base.xcconfig" - -INFOPLIST_KEY_NSHumanReadableCopyright = Copyright © Userscripts -CURRENT_PROJECT_VERSION = 2 -MARKETING_VERSION = 2.0.0 - -// Development -CODE_SIGN_IDENTITY = Apple Development -// Developer Team ID -DEVELOPMENT_TEAM = XXXXXXXXXX -// Organization Identifier -ORG_IDENTIFIER = dev.vite -// Application Identifier -APP_IDENTIFIER = $(ORG_IDENTIFIER).userscripts -// Safari Extension Identifier -EXT_IDENTIFIER = $(APP_IDENTIFIER).ext.safari -// App Groups and Group Containers -IOS_SHARED_GID = group.$(ORG_IDENTIFIER).userscripts -MAC_SHARED_GID = $(DEVELOPMENT_TEAM).$(ORG_IDENTIFIER).userscripts -// App URL Scheme -APP_URL_SCHEME = userscripts-vite - -// Override this file -#include? "Userscripts-Vite.dev.xcconfig" diff --git a/xcode/xcconfig/iOS-App.xcconfig b/xcode/xcconfig/iOS-App.xcconfig deleted file mode 100644 index 5dbd1119..00000000 --- a/xcode/xcconfig/iOS-App.xcconfig +++ /dev/null @@ -1,34 +0,0 @@ -SRC_DIR = App-iOS -ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon -ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor -CODE_SIGN_ENTITLEMENTS = $(SRC_DIR)/App.entitlements -GENERATE_INFOPLIST_FILE = YES -INFOPLIST_FILE = $(SRC_DIR)/Info.plist -INFOPLIST_KEY_CFBundleDisplayName = $(PROJECT_NAME) -INFOPLIST_KEY_CFBundleDisplayName[config=Debug] = $(PROJECT_NAME)-D -INFOPLIST_KEY_CFBundleDisplayName[config=Vite] = $(PROJECT_NAME)-V -INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES -INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen -INFOPLIST_KEY_UIMainStoryboardFile = Main -INFOPLIST_KEY_UIStatusBarHidden = NO -INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight -INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight -LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks -OTHER_LDFLAGS = -framework SafariServices -framework WebKit -PRODUCT_BUNDLE_IDENTIFIER = $(APP_IDENTIFIER) -PRODUCT_NAME = $(PROJECT_NAME)-$(TARGET_NAME) -SDKROOT = iphoneos -SWIFT_EMIT_LOC_STRINGS = YES -SUPPORTED_PLATFORMS = iphoneos iphonesimulator -SUPPORTS_MACCATALYST = NO -SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO -TARGETED_DEVICE_FAMILY = 1,2 -VALIDATE_PRODUCT[config=Release] = YES -SWIFT_ACTIVE_COMPILATION_CONDITIONS = APP $(inherited) - -// Provisioning Profile -PROVISIONING_PROFILE_SPECIFIER[config=Release] = match AppStore $(APP_IDENTIFIER) - -// Override this file -#include? "iOS-App.dev.xcconfig" diff --git a/xcode/xcconfig/iOS-Safari-Extension.xcconfig b/xcode/xcconfig/iOS-Safari-Extension.xcconfig deleted file mode 100644 index 0d65c2ca..00000000 --- a/xcode/xcconfig/iOS-Safari-Extension.xcconfig +++ /dev/null @@ -1,24 +0,0 @@ -// Shared config file -#include? "Safari-Extension.xcconfig" - -CODE_SIGN_ENTITLEMENTS = $(SRC_DIR)/iOS.entitlements -GENERATE_INFOPLIST_FILE = YES -INFOPLIST_FILE = $(SRC_DIR)/Info.plist -INFOPLIST_KEY_CFBundleDisplayName = $(PRODUCT_NAME) -INFOPLIST_KEY_CFBundleDisplayName[config=Debug] = $(PROJECT_NAME)-D -LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @executable_path/../../Frameworks -OTHER_LDFLAGS = -framework SafariServices -PRODUCT_BUNDLE_IDENTIFIER = $(EXT_IDENTIFIER) -PRODUCT_NAME = $(PROJECT_NAME)-$(TARGET_NAME) -SDKROOT = iphoneos -SKIP_INSTALL = YES -SWIFT_EMIT_LOC_STRINGS = YES -TARGETED_DEVICE_FAMILY = 1,2 -VALIDATE_PRODUCT[config=Release] = YES -SWIFT_ACTIVE_COMPILATION_CONDITIONS = EXT $(inherited) - -// Provisioning Profile -PROVISIONING_PROFILE_SPECIFIER[config=Release] = match AppStore $(EXT_IDENTIFIER) - -// Override this file -#include? "iOS-Safari-Extension.dev.xcconfig"