| name: Code Check | |||||
| on: | |||||
| push: | |||||
| branches: [ master ] | |||||
| pull_request: | |||||
| branches: [ master ] | |||||
| workflow_call: | |||||
| workflow_dispatch: | |||||
| jobs: | |||||
| code_check: | |||||
| strategy: | |||||
| matrix: | |||||
| os: [windows-latest, macOS-latest, ubuntu-latest] | |||||
| runs-on: ${{ matrix.os }} | |||||
| outputs: | |||||
| output1: ${{ steps.compare_output_windows.outputs.diff }} | |||||
| output2: ${{ steps.compare_output_macos_linux.outputs.diff }} | |||||
| steps: | |||||
| # Checks-out repository under $GITHUB_WORKSPACE, so job can access it | |||||
| - uses: actions/checkout@v3 | |||||
| # Setup Amazon Coretto OpenJDK | |||||
| - uses: actions/setup-java@v3 | |||||
| with: | |||||
| distribution: 'corretto' | |||||
| java-version: '8' | |||||
| - name: Install Microsoft Visual C++ Redistributable using chocolatey (Windows) | |||||
| if: (matrix.os == 'windows-latest') | |||||
| uses: crazy-max/ghaction-chocolatey@v1 | |||||
| with: | |||||
| args: install vcredist2012 | |||||
| - name: Install TagUI (Windows) | |||||
| if: (matrix.os == 'windows-latest') | |||||
| run: | | |||||
| # Add src to path variable | |||||
| echo "${{github.workspace}}\src" >> $env:GITHUB_PATH | |||||
| # Add tagui_logging file for generated js file to persist | |||||
| Out-File -FilePath "${{github.workspace}}\src\tagui_logging" | |||||
| - name: Install TagUI (macOS / Linux) | |||||
| if: (matrix.os != 'windows-latest') | |||||
| run: | | |||||
| # Add src to path variable | |||||
| sudo ln -sf ${{github.workspace}}/src/tagui /usr/local/bin/tagui | |||||
| # Add tagui_logging file for generated js file to persist | |||||
| cd "${{github.workspace}}/src" | |||||
| touch tagui_logging | |||||
| chmod -R 777 "${{github.workspace}}" | |||||
| - name: Add Unx, PHP, CasperJS and SlimerJS dependency files (Windows) | |||||
| if: (matrix.os == 'windows-latest') | |||||
| run: | | |||||
| cd "${{github.workspace}}\src" | |||||
| # Add unx dependencies | |||||
| Invoke-WebRequest -Uri 'https://storage.googleapis.com/tagui-dependencies/unx.zip' -OutFile unxzip.zip | |||||
| Expand-Archive -LiteralPath unxzip.zip | |||||
| MOVE-ITEM -Path "${{github.workspace}}\src\unxzip\*" -Destination "${{github.workspace}}\src" | |||||
| Remove-Item unxzip.zip | |||||
| # Add PHP dependency files | |||||
| Invoke-WebRequest 'https://windows.php.net/downloads/releases/archives/php-5.6.30-Win32-VC11-x86.zip' -OutFile php.zip | |||||
| Expand-Archive -LiteralPath php.zip | |||||
| Remove-Item php.zip | |||||
| # Add SikuliX dependency files | |||||
| Invoke-WebRequest -Uri 'https://storage.googleapis.com/tagui-dependencies/sikulix.zip' -OutFile sikulixzip.zip | |||||
| Expand-Archive -LiteralPath sikulixzip.zip | |||||
| MOVE-ITEM -Path "${{github.workspace}}\src\sikulixzip\*" -Destination "${{github.workspace}}\src" | |||||
| Remove-Item sikulixzip.zip | |||||
| # Add CasperJS dependency files | |||||
| Invoke-WebRequest 'https://github.com/casperjs/casperjs/archive/refs/tags/1.1.4-1.zip' -OutFile casperjszip.zip | |||||
| Expand-Archive -LiteralPath casperjszip.zip | |||||
| MOVE-ITEM -Path "${{github.workspace}}\src\casperjszip\*" -Destination "${{github.workspace}}\src" | |||||
| Remove-Item casperjszip.zip | |||||
| Rename-Item -Path '${{github.workspace}}\src\casperjs-1.1.4-1' -NewName '${{github.workspace}}\src\casperjs' | |||||
| # Add SlimerJS dependency files | |||||
| Invoke-WebRequest 'https://github.com/laurentj/slimerjs/releases/download/1.0.0/slimerjs-1.0.0.zip' -OutFile slimerjszip.zip | |||||
| Expand-Archive -LiteralPath slimerjszip.zip | |||||
| MOVE-ITEM -Path "${{github.workspace}}\src\slimerjszip\*" -Destination "${{github.workspace}}\src" | |||||
| Remove-Item slimerjszip.zip | |||||
| Rename-Item -Path '${{github.workspace}}\src\slimerjs-1.0.0' -NewName '${{github.workspace}}\src\slimerjs' | |||||
| # Add PhantomJS dependency files | |||||
| Invoke-WebRequest 'https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-windows.zip' -OutFile phantomjszip.zip | |||||
| Expand-Archive -LiteralPath phantomjszip.zip | |||||
| MOVE-ITEM -Path "${{github.workspace}}\src\phantomjszip\*" -Destination "${{github.workspace}}\src" | |||||
| Remove-Item phantomjszip.zip | |||||
| Rename-Item -Path '${{github.workspace}}\src\phantomjs-2.1.1-windows' -NewName '${{github.workspace}}\src\phantomjs' | |||||
| - name: Add SikuliX, CasperJS and SlimerJS dependency files (macOS / Linux) | |||||
| if: (matrix.os != 'windows-latest') | |||||
| run: | | |||||
| cd "${{github.workspace}}/src" | |||||
| # Add SikuliX dependency files | |||||
| curl -L 'https://storage.googleapis.com/tagui-dependencies/sikulix.zip' > sikulixzip.zip | |||||
| unzip sikulixzip.zip | |||||
| rm sikulixzip.zip | |||||
| # Add CasperJS dependency files | |||||
| curl -L 'https://github.com/casperjs/casperjs/archive/refs/tags/1.1.4-1.zip' > casperjs.zip | |||||
| unzip casperjs.zip | |||||
| rm casperjs.zip | |||||
| mv casperjs-1.1.4-1 casperjs | |||||
| # Add SlimerJS dependency files | |||||
| curl -L 'https://github.com/laurentj/slimerjs/releases/download/1.0.0/slimerjs-1.0.0.zip' > slimerjs.zip | |||||
| unzip slimerjs.zip | |||||
| rm slimerjs.zip | |||||
| mv slimerjs-1.0.0 slimerjs | |||||
| - name: Add PhantomJS dependency files (macOS) | |||||
| if: (matrix.os == 'macOS-latest') | |||||
| run: | | |||||
| cd "${{github.workspace}}/src" | |||||
| curl -L 'https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-macosx.zip' > phantomjs.zip | |||||
| unzip phantomjs.zip | |||||
| rm phantomjs.zip | |||||
| mv phantomjs-2.1.1-macosx phantomjs | |||||
| - name: Add PhantomJS dependency files (Linux) | |||||
| if: (matrix.os == 'ubuntu-latest') | |||||
| run: | | |||||
| cd "${{github.workspace}}/src" | |||||
| curl -L 'https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2' > phantomjs.tar.bz2 | |||||
| tar -xf phantomjs.tar.bz2 | |||||
| rm phantomjs.tar.bz2 | |||||
| mv phantomjs-2.1.1-linux-x86_64 phantomjs | |||||
| - name: Run visual automation flow for first time to install jython standalone jar - expected to fail (Windows) | |||||
| if: (matrix.os == 'windows-latest') | |||||
| timeout-minutes: 2 | |||||
| continue-on-error: true | |||||
| run: | |||||
| tagui "${{github.workspace}}\src\test\positive_test.tag" -n | |||||
| - name: Run visual automation flow again for successful run (Windows) | |||||
| if: (matrix.os == 'windows-latest') | |||||
| run: | |||||
| tagui "${{github.workspace}}\src\test\positive_test.tag" -n | |||||
| - name: Run visual automation flow for first time to install jython standalone jar - expected to fail (macOS / Linux) | |||||
| if: (matrix.os != 'windows-latest') | |||||
| timeout-minutes: 2 | |||||
| continue-on-error: true | |||||
| run: | |||||
| tagui "${{github.workspace}}/src/test/positive_test.tag" -n | |||||
| - name: Run visual automation flow again for successful run (macOS / Linux) | |||||
| if: (matrix.os != 'windows-latest') | |||||
| run: | |||||
| tagui "${{github.workspace}}/src/test/positive_test.tag" -n | |||||
| - name: Compare output of positive_test.js and positive_test.signature (Windows) | |||||
| if: (matrix.os == 'windows-latest') | |||||
| id: compare_output_windows | |||||
| run: | | |||||
| Compare-Object (Get-Content '${{github.workspace}}\src\test\positive_test.js') (Get-Content '${{github.workspace}}\src\test\positive_test.signature') -PassThru | Set-Content '${{github.workspace}}\src\test\output.txt' | |||||
| if(Test-Path -Path '${{github.workspace}}\src\test\output.txt' -PathType Leaf) {exit 1} | |||||
| - name: Compare output of positive_test.js and positive_test.signature (macOS / Linux) | |||||
| if: (matrix.os != 'windows-latest') | |||||
| id: compare_output_macos_linux | |||||
| run: | |||||
| if ! diff "${{github.workspace}}/src/test/positive_test.js" "${{github.workspace}}/src/test/positive_test.signature" >/dev/null; then exit 1; fi | 
| name: Package Release | |||||
| on: | |||||
| push: | |||||
| tags: | |||||
| - "v*" | |||||
| jobs: | |||||
| code_check: | |||||
| uses: kelaberetiv/TagUI/.github/workflows/code_check.yml@master | |||||
| create_release: | |||||
| needs: code_check | |||||
| runs-on: ubuntu-latest | |||||
| steps: | |||||
| - name: Checkout | |||||
| uses: actions/checkout@v2 | |||||
| - name: Add SikuliX, CasperJS, SlimerJS and SikuliX-Linux dependency files | |||||
| run: | | |||||
| cd "${{github.workspace}}/src" | |||||
| # Add SikuliX dependency files | |||||
| curl -L 'https://storage.googleapis.com/tagui-dependencies/sikulix.zip' > sikulixzip.zip | |||||
| unzip sikulixzip.zip | |||||
| rm sikulixzip.zip | |||||
| # Add CasperJS dependency files | |||||
| curl -L 'https://github.com/casperjs/casperjs/archive/refs/tags/1.1.4-1.zip' > casperjs.zip | |||||
| unzip casperjs.zip | |||||
| rm casperjs.zip | |||||
| mv casperjs-1.1.4-1 casperjs | |||||
| # Add SlimerJS dependency files | |||||
| curl -L 'https://github.com/laurentj/slimerjs/releases/download/1.0.0/slimerjs-1.0.0.zip' > slimerjs.zip | |||||
| unzip slimerjs.zip | |||||
| rm slimerjs.zip | |||||
| mv slimerjs-1.0.0 slimerjs | |||||
| # Add PhantomJS dependency files | |||||
| curl -L 'https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2' > phantomjs.tar.bz2 | |||||
| tar -xf phantomjs.tar.bz2 | |||||
| rm phantomjs.tar.bz2 | |||||
| mv phantomjs-2.1.1-linux-x86_64 phantomjs | |||||
| cd "${{github.workspace}}" | |||||
| mkdir tagui | |||||
| rm -r .git | |||||
| shopt -s extglob dotglob | |||||
| mv !(tagui) tagui | |||||
| shopt -u dotglob | |||||
| sudo chmod -R 755 "${{github.workspace}}/tagui" | |||||
| - name: Zip Linux Folder | |||||
| run: | | |||||
| cd "${{github.workspace}}" | |||||
| zip -r TagUI_Linux.zip tagui | |||||
| - name: Add PhantomJS-macOS dependency files (macOS) | |||||
| run: | | |||||
| cd "${{github.workspace}}/tagui/src" | |||||
| # Add PhantomJS dependency files | |||||
| rm -r phantomjs | |||||
| # Add PhantomJS dependency files | |||||
| curl -L 'https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-macosx.zip' > phantomjs.zip | |||||
| unzip phantomjs.zip | |||||
| rm phantomjs.zip | |||||
| mv phantomjs-2.1.1-macosx phantomjs | |||||
| sudo chmod -R 755 "${{github.workspace}}/tagui" | |||||
| - name: Zip macOS Folder | |||||
| run: | | |||||
| cd "${{github.workspace}}" | |||||
| zip -r TagUI_macOS.zip tagui | |||||
| - name: Add Unx, PHP, PhantomJS-Windows dependency files (Windows) | |||||
| run: | | |||||
| cd "${{github.workspace}}/tagui/src" | |||||
| # Add unx dependencies | |||||
| curl -L 'https://storage.googleapis.com/tagui-dependencies/unx.zip' > unxzip.zip | |||||
| unzip unxzip.zip | |||||
| rm unxzip.zip | |||||
| # Add PHP dependency files | |||||
| curl -L 'https://windows.php.net/downloads/releases/archives/php-5.6.30-Win32-VC11-x86.zip' > phpzip.zip | |||||
| mkdir php | |||||
| unzip phpzip.zip -d ./php | |||||
| rm phpzip.zip | |||||
| # Add PhantomJS dependency files | |||||
| rm -r phantomjs | |||||
| # Add PhantomJS dependency files | |||||
| curl -L 'https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-windows.zip' > phantomjs.zip | |||||
| unzip phantomjs.zip | |||||
| rm phantomjs.zip | |||||
| mv phantomjs-2.1.1-windows phantomjs | |||||
| sudo chmod -R 755 "${{github.workspace}}/tagui" | |||||
| - name: Zip Windows Folder | |||||
| run: | | |||||
| cd "${{github.workspace}}" | |||||
| zip -r TagUI_Windows.zip tagui | |||||
| - name: Create Release | |||||
| uses: softprops/action-gh-release@v1 | |||||
| if: startsWith(github.ref, 'refs/tags/') | |||||
| with: | |||||
| files: | | |||||
| TagUI_Windows.zip | |||||
| TagUI_macOS.zip | |||||
| TagUI_Linux.zip | 
| # exclude docs build | |||||
| /docs/_build/* | |||||
| # exclude folders for packaged installation | |||||
| /src/casperjs/* | |||||
| /src/phantomjs/* | |||||
| /src/sikulix/* | |||||
| /src/slimerjs/* | |||||
| /src/php/* | |||||
| /src/unx/* | |||||
| # exclude custom global functions file | |||||
| /src/tagui_global.js | |||||
| # exclude custom global repository file | |||||
| /src/tagui_global.csv | |||||
| # exclude custom datatable temp file | |||||
| /src/tagui_datatable_transpose.csv | |||||
| /src/tagui_datatable.csv | |||||
| # exclude audit report csv file | |||||
| /src/tagui_report.csv | |||||
| # exclude tagui_no_logging flag | |||||
| /src/tagui_no_logging | |||||
| # exclude tagui_logging flag | |||||
| /src/tagui_logging | |||||
| # exclude translation temp build files | |||||
| /src/languages/build.js | |||||
| /src/languages/build.log | |||||
| /src/languages/build.raw | |||||
| # exclude translation engine log file | |||||
| /src/translate.log | |||||
| # exclude generated files for cli assistant | |||||
| /src/tagui_helper | |||||
| /src/tagui_helper.cmd | |||||
| # exclude local log files from api service | |||||
| /src/tagui_service.in | |||||
| /src/tagui_service.out | |||||
| /src/tagui_service.log | |||||
| /src/tagui_service.act | |||||
| /src/tagui_service.run | |||||
| /src/tagui_service.done | |||||
| # exclude local files for chrome integration | |||||
| /src/chrome/tagui_user_profile | |||||
| /src/tagui_chrome.in | |||||
| /src/tagui_chrome.out | |||||
| /src/tagui_chrome.log | |||||
| # exclude local files for R integration | |||||
| /src/tagui_r/tagui_r.in | |||||
| /src/tagui_r/tagui_r.out | |||||
| /src/tagui_r/tagui_r.txt | |||||
| /src/tagui_r/tagui_r.log | |||||
| /src/tagui_r/tagui_r_windows.log | |||||
| # exclude local files for python integration | |||||
| /src/tagui_py/tagui_py.in | |||||
| /src/tagui_py/tagui_py.out | |||||
| /src/tagui_py/tagui_py.txt | |||||
| /src/tagui_py/tagui_py.log | |||||
| /src/tagui_py/tagui_py_windows.log | |||||
| # exclude local files for sikuli integration | |||||
| /src/tagui.sikuli/tagui_sikuli.in | |||||
| /src/tagui.sikuli/tagui_sikuli.out | |||||
| /src/tagui.sikuli/tagui_sikuli.txt | |||||
| /src/tagui.sikuli/tagui.log | |||||
| /src/tagui.sikuli/tagui_windows.log | |||||
| /src/tagui.sikuli/sikulix* | |||||
| /src/tagui.sikuli/SikuliX* | |||||
| /src/tagui.sikuli/runsikulix* | |||||
| # exclude local files for excel integration | |||||
| /src/excel_steps.scpt | |||||
| /src/excel_steps.vbs | |||||
| # exclude local files for word integration | |||||
| /src/word_steps.scpt | |||||
| /src/word_steps.vbs | |||||
| /src/word_steps.cmd | |||||
| /src/word_steps.out | |||||
| # exclude local files for pdf integration | |||||
| /src/pdf_steps.scpt | |||||
| /src/pdf_steps.vbs | |||||
| /src/pdf_steps.cmd | |||||
| /src/pdf_steps.out | |||||
| # exclude local files for catboost integration | |||||
| /src/catboost/* | |||||
| # exclude packages and generated files for Office RPA | |||||
| /src/office/word/packages/* | |||||
| /src/office/excel/packages/* | |||||
| /src/office/word/TagUIWordAddIn/bin/* | |||||
| /src/office/word/TagUIWordAddIn/obj/* | |||||
| /src/office/excel/TagUIExcelAddIn/bin/* | |||||
| /src/office/excel/TagUIExcelAddIn/obj/* | |||||
| # exclude packages and generated files for installer | |||||
| /src/installer/TagUIBundle/bin/* | |||||
| /src/installer/TagUIBundle/obj/* | |||||
| /src/installer/TagUIv6.48/Debug/* | |||||
| /src/installer/TagUIv6.48/Release/* | 
| Apache License | |||||
| Version 2.0, January 2004 | |||||
| http://www.apache.org/licenses/ | |||||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |||||
| 1. Definitions. | |||||
| "License" shall mean the terms and conditions for use, reproduction, | |||||
| and distribution as defined by Sections 1 through 9 of this document. | |||||
| "Licensor" shall mean the copyright owner or entity authorized by | |||||
| the copyright owner that is granting the License. | |||||
| "Legal Entity" shall mean the union of the acting entity and all | |||||
| other entities that control, are controlled by, or are under common | |||||
| control with that entity. For the purposes of this definition, | |||||
| "control" means (i) the power, direct or indirect, to cause the | |||||
| direction or management of such entity, whether by contract or | |||||
| otherwise, or (ii) ownership of fifty percent (50%) or more of the | |||||
| outstanding shares, or (iii) beneficial ownership of such entity. | |||||
| "You" (or "Your") shall mean an individual or Legal Entity | |||||
| exercising permissions granted by this License. | |||||
| "Source" form shall mean the preferred form for making modifications, | |||||
| including but not limited to software source code, documentation | |||||
| source, and configuration files. | |||||
| "Object" form shall mean any form resulting from mechanical | |||||
| transformation or translation of a Source form, including but | |||||
| not limited to compiled object code, generated documentation, | |||||
| and conversions to other media types. | |||||
| "Work" shall mean the work of authorship, whether in Source or | |||||
| Object form, made available under the License, as indicated by a | |||||
| copyright notice that is included in or attached to the work | |||||
| (an example is provided in the Appendix below). | |||||
| "Derivative Works" shall mean any work, whether in Source or Object | |||||
| form, that is based on (or derived from) the Work and for which the | |||||
| editorial revisions, annotations, elaborations, or other modifications | |||||
| represent, as a whole, an original work of authorship. For the purposes | |||||
| of this License, Derivative Works shall not include works that remain | |||||
| separable from, or merely link (or bind by name) to the interfaces of, | |||||
| the Work and Derivative Works thereof. | |||||
| "Contribution" shall mean any work of authorship, including | |||||
| the original version of the Work and any modifications or additions | |||||
| to that Work or Derivative Works thereof, that is intentionally | |||||
| submitted to Licensor for inclusion in the Work by the copyright owner | |||||
| or by an individual or Legal Entity authorized to submit on behalf of | |||||
| the copyright owner. For the purposes of this definition, "submitted" | |||||
| means any form of electronic, verbal, or written communication sent | |||||
| to the Licensor or its representatives, including but not limited to | |||||
| communication on electronic mailing lists, source code control systems, | |||||
| and issue tracking systems that are managed by, or on behalf of, the | |||||
| Licensor for the purpose of discussing and improving the Work, but | |||||
| excluding communication that is conspicuously marked or otherwise | |||||
| designated in writing by the copyright owner as "Not a Contribution." | |||||
| "Contributor" shall mean Licensor and any individual or Legal Entity | |||||
| on behalf of whom a Contribution has been received by Licensor and | |||||
| subsequently incorporated within the Work. | |||||
| 2. Grant of Copyright License. Subject to the terms and conditions of | |||||
| this License, each Contributor hereby grants to You a perpetual, | |||||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||||
| copyright license to reproduce, prepare Derivative Works of, | |||||
| publicly display, publicly perform, sublicense, and distribute the | |||||
| Work and such Derivative Works in Source or Object form. | |||||
| 3. Grant of Patent License. Subject to the terms and conditions of | |||||
| this License, each Contributor hereby grants to You a perpetual, | |||||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||||
| (except as stated in this section) patent license to make, have made, | |||||
| use, offer to sell, sell, import, and otherwise transfer the Work, | |||||
| where such license applies only to those patent claims licensable | |||||
| by such Contributor that are necessarily infringed by their | |||||
| Contribution(s) alone or by combination of their Contribution(s) | |||||
| with the Work to which such Contribution(s) was submitted. If You | |||||
| institute patent litigation against any entity (including a | |||||
| cross-claim or counterclaim in a lawsuit) alleging that the Work | |||||
| or a Contribution incorporated within the Work constitutes direct | |||||
| or contributory patent infringement, then any patent licenses | |||||
| granted to You under this License for that Work shall terminate | |||||
| as of the date such litigation is filed. | |||||
| 4. Redistribution. You may reproduce and distribute copies of the | |||||
| Work or Derivative Works thereof in any medium, with or without | |||||
| modifications, and in Source or Object form, provided that You | |||||
| meet the following conditions: | |||||
| (a) You must give any other recipients of the Work or | |||||
| Derivative Works a copy of this License; and | |||||
| (b) You must cause any modified files to carry prominent notices | |||||
| stating that You changed the files; and | |||||
| (c) You must retain, in the Source form of any Derivative Works | |||||
| that You distribute, all copyright, patent, trademark, and | |||||
| attribution notices from the Source form of the Work, | |||||
| excluding those notices that do not pertain to any part of | |||||
| the Derivative Works; and | |||||
| (d) If the Work includes a "NOTICE" text file as part of its | |||||
| distribution, then any Derivative Works that You distribute must | |||||
| include a readable copy of the attribution notices contained | |||||
| within such NOTICE file, excluding those notices that do not | |||||
| pertain to any part of the Derivative Works, in at least one | |||||
| of the following places: within a NOTICE text file distributed | |||||
| as part of the Derivative Works; within the Source form or | |||||
| documentation, if provided along with the Derivative Works; or, | |||||
| within a display generated by the Derivative Works, if and | |||||
| wherever such third-party notices normally appear. The contents | |||||
| of the NOTICE file are for informational purposes only and | |||||
| do not modify the License. You may add Your own attribution | |||||
| notices within Derivative Works that You distribute, alongside | |||||
| or as an addendum to the NOTICE text from the Work, provided | |||||
| that such additional attribution notices cannot be construed | |||||
| as modifying the License. | |||||
| You may add Your own copyright statement to Your modifications and | |||||
| may provide additional or different license terms and conditions | |||||
| for use, reproduction, or distribution of Your modifications, or | |||||
| for any such Derivative Works as a whole, provided Your use, | |||||
| reproduction, and distribution of the Work otherwise complies with | |||||
| the conditions stated in this License. | |||||
| 5. Submission of Contributions. Unless You explicitly state otherwise, | |||||
| any Contribution intentionally submitted for inclusion in the Work | |||||
| by You to the Licensor shall be under the terms and conditions of | |||||
| this License, without any additional terms or conditions. | |||||
| Notwithstanding the above, nothing herein shall supersede or modify | |||||
| the terms of any separate license agreement you may have executed | |||||
| with Licensor regarding such Contributions. | |||||
| 6. Trademarks. This License does not grant permission to use the trade | |||||
| names, trademarks, service marks, or product names of the Licensor, | |||||
| except as required for reasonable and customary use in describing the | |||||
| origin of the Work and reproducing the content of the NOTICE file. | |||||
| 7. Disclaimer of Warranty. Unless required by applicable law or | |||||
| agreed to in writing, Licensor provides the Work (and each | |||||
| Contributor provides its Contributions) on an "AS IS" BASIS, | |||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |||||
| implied, including, without limitation, any warranties or conditions | |||||
| of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | |||||
| PARTICULAR PURPOSE. You are solely responsible for determining the | |||||
| appropriateness of using or redistributing the Work and assume any | |||||
| risks associated with Your exercise of permissions under this License. | |||||
| 8. Limitation of Liability. In no event and under no legal theory, | |||||
| whether in tort (including negligence), contract, or otherwise, | |||||
| unless required by applicable law (such as deliberate and grossly | |||||
| negligent acts) or agreed to in writing, shall any Contributor be | |||||
| liable to You for damages, including any direct, indirect, special, | |||||
| incidental, or consequential damages of any character arising as a | |||||
| result of this License or out of the use or inability to use the | |||||
| Work (including but not limited to damages for loss of goodwill, | |||||
| work stoppage, computer failure or malfunction, or any and all | |||||
| other commercial damages or losses), even if such Contributor | |||||
| has been advised of the possibility of such damages. | |||||
| 9. Accepting Warranty or Additional Liability. While redistributing | |||||
| the Work or Derivative Works thereof, You may choose to offer, | |||||
| and charge a fee for, acceptance of support, warranty, indemnity, | |||||
| or other liability obligations and/or rights consistent with this | |||||
| License. However, in accepting such obligations, You may act only | |||||
| on Your own behalf and on Your sole responsibility, not on behalf | |||||
| of any other Contributor, and only if You agree to indemnify, | |||||
| defend, and hold each Contributor harmless for any liability | |||||
| incurred by, or claims asserted against, such Contributor by reason | |||||
| of your accepting any such warranty or additional liability. | |||||
| END OF TERMS AND CONDITIONS | |||||
| APPENDIX: How to apply the Apache License to your work. | |||||
| To apply the Apache License to your work, attach the following | |||||
| boilerplate notice, with the fields enclosed by brackets "[]" | |||||
| replaced with your own identifying information. (Don't include | |||||
| the brackets!) The text should be enclosed in the appropriate | |||||
| comment syntax for the file format. We also recommend that a | |||||
| file or class name and description of purpose be included on the | |||||
| same "printed page" as the copyright notice for easier | |||||
| identification within third-party archives. | |||||
| Copyright 2022 AISG Limited | |||||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| you may not use this file except in compliance with the License. | |||||
| You may obtain a copy of the License at | |||||
| http://www.apache.org/licenses/LICENSE-2.0 | |||||
| Unless required by applicable law or agreed to in writing, software | |||||
| distributed under the License is distributed on an "AS IS" BASIS, | |||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| See the License for the specific language governing permissions and | |||||
| limitations under the License. | 
| <img src="https://raw.githubusercontent.com/kelaberetiv/TagUI/master/src/media/tagui_logo.png" height="111" align="right"> | |||||
| # TagUI | # TagUI | ||||
| **Free RPA tool by [AI Singapore](https://aisingapore.org), a government-funded programme to accelerate AI. To start, click the download link below. Take the [free course](https://learn.aisingapore.org/courses/learn-rpa-with-tagui-beginners-course/). Ask any questions at [our Telegram](https://t.me/rpa_chat).** | |||||
| **[Download v6.110](https://tagui.readthedocs.io/en/latest/setup.html) | [Usage Guide](https://tagui.readthedocs.io/en/latest/index.html) | [Demos](https://github.com/aimakerspace/TagUI-Bricks) | [Samples](https://github.com/kelaberetiv/TagUI/tree/master/flows/samples) | [Slides](https://docs.google.com/presentation/d/1pltAMzr0MZsttgg1w2ORH3ontR6Q51W9/edit?usp=sharing&ouid=115132044557947023533&rtpof=true&sd=true) | [Podcast](https://botnirvana.org/podcast/tagui/) | [Video](https://www.youtube.com/watch?v=C5itbB3sCq0) | [Forum](https://community.aisingapore.org/groups/tagui-rpa/forum/) | [中文](http://www.tagui.com.cn)** | |||||
| --- | |||||
| Write flows in simple TagUI language and automate away repetitive time-consuming tasks on your computer. Tasks include those on websites (native support for Chrome and Edge), desktop apps, or the command line. The TagUI project is open-source and free forever. It's easy to setup and use, and works on Windows, macOS and Linux. | |||||
| Besides English, flows can be written in [22 other languages](https://github.com/kelaberetiv/TagUI/tree/master/src/languages), so you can do RPA using your [native language](https://github.com/kelaberetiv/TagUI/blob/master/flows/samples/8_chineseflow.tag). Check out this [demo video automating data collection](https://www.youtube.com/watch?v=o2WMUt0298U) in 4 different languages. With the new TagUI turbo mode, you can even run your automation 10X faster than normal human speed! | |||||
| # Language designed for RPA | |||||
| In TagUI language, you use steps like `click` and `type` to interact with identifiers, which include web identifiers, image snapshots, screen coordinates, or [even text using OCR](https://tagui.readthedocs.io/en/latest/advanced.html#visual-automation-tricks). Below is an example to login to Xero accounting: | |||||
| ``` | |||||
| https://login.xero.com/identity/user/login | |||||
| type email as user@gmail.com | |||||
| type password as 12345678 | |||||
| click Log in | |||||
| ``` | |||||
| ``` | |||||
| // besides web identifiers, images of UI elements can be used | |||||
| type email_box.png as user@gmail.com | |||||
| type password_box.png as 12345678 | |||||
| click login_button.png | |||||
| ``` | |||||
| Grabbing data from a table on a website can be [as easy as below](https://tagui.readthedocs.io/en/latest/reference.html#table) (where n is the nth table on the webpage) | |||||
| ``` | |||||
| table n to forex_rates.csv | |||||
| ``` | |||||
| Moving data between TagUI and Excel is as easy as using [standard Excel formula](https://tagui.readthedocs.io/en/latest/reference.html#excel) that you are familiar with | |||||
| ``` | |||||
| top_salesman = [Monthly Report.xlsx]August!E11 | |||||
| ``` | |||||
| Sending a Telegram notification is trivially easy ([first message @taguibot](https://tagui.readthedocs.io/en/latest/reference.html#telegram) to authorise it to send messages) | |||||
| ``` | |||||
| telegram id Hello World. Olá Mundo. नमस्ते दुनिया. 안녕하세요 세계. 世界,你好。 | |||||
| ``` | |||||
| # Do RPA Any Way You Want | |||||
| You can use TagUI [MS Office Plug-ins](https://github.com/kelaberetiv/TagUI/blob/master/src/office/README.md) ([sample doc](https://github.com/kelaberetiv/TagUI/files/7031942/Week.3.docx)) to easily create and deploy Word doc as RPA robots, and set up RPA data parameters using Excel. Enjoy a full-featured RPA IDE with toolbar of TagUI steps and tooltips, snapshot tool to automate using computer vision, task pane for settings and run output. | |||||
| You can also create and edit your RPA robots using commonly used text editors like Notepad, Notepad++, VS Code, Sublime, TextEdit, Vim, etc. For VS Code users, you can install [TagUI language extension](https://marketplace.visualstudio.com/items?itemName=TagUisupport.tagui-support). For Notepad++ users, you can download [TagUI plug-ins here](https://github.com/tilyanPristka/TagUI-Snippets-for-NotepadPP) for syntax highlighting, shortcuts and snippets. | |||||
| For cloud lovers, you can run TagUI on your web browser or phone using [free Google Cloud](https://github.com/kelaberetiv/TagUI/issues/913), up to 5 concurrent sessions. For more control running on the cloud, you can run this [Docker image](https://hub.docker.com/r/openiap/nodered-tagui) (use edge tag) or [Docker file](https://github.com/open-rpa/openflow/blob/master/OpenFlowNodeRED/Dockerfiletagui) on your preferred vendor. Or run on [free Node-RED instance](https://app.openiap.io/) on OpenFlow. | |||||
|  | |||||
| # Ecosystem and Communities | |||||
| TagUI has a bustling user community, and extended community champions create new RPA tools for their own communities, based on TagUI. Python users can [pip install rpa](https://github.com/tebelorg/RPA-Python) to use the #1 Python RPA package. Already there is [TagUI for C# .NET](https://www.nuget.org/packages/tagui), and TagUI for Go is being built. For event-driven RPA with thousands of connectors, check out [TagUI module for Node-RED](https://flows.nodered.org/node/node-red-contrib-tagui), a popular free and open-source workflow automation tool. | |||||
| For Microsoft [Power Automate Desktop](https://flow.microsoft.com/en-us/desktop/) users, you'll be happy to know that there's 2-way integration with TagUI out of the box (for business continuity if you switch between the 2 apps). Also, do check out other leading open-source RPA tools, to see if they meet your needs better - [OpenRPA](https://github.com/open-rpa/openrpa) & [OpenFlow](https://github.com/open-rpa/openflow), [OpenBots](https://www.linkedin.com/posts/openbots_openbots-studio-demo-support-for-tag-ui-activity-6788174021964943361-RrUD), [Robocorp](https://youtu.be/HAfQpNZVbKI). All of them support enterprise-grade orchestrating and running TagUI robots from their orchestrator. | |||||
| There is also a Chinese [usage guide](http://www.tagui.com.cn) and [TagUI repository](https://gitee.com/TagUIcn). We welcome more languages with open arms. | |||||
| # Enterprise Security by design | |||||
| Security Considerations | |||||
| - TagUI default implementation is an on-user-computer on-prem RPA tool that does not exist on any cloud | |||||
| - TagUI is not a SaaS or software on the cloud running on vendor's cloud, it runs on actual users' computers | |||||
| - Industry-specific certifications like PCI-DSS, HIPAA, SOX aren't applicable because TagUI doesn't store data | |||||
| - In decentralised bottom-up RPA, not advisable and no need for bot credentials as users are held accountable | |||||
| Data Considerations | |||||
| - For data at rest, storage encryption would be on user's computer's OS-level as it is run on user's computer | |||||
| - For data in use, recommend user to manually enter sensitive info like password before letting robot take over | |||||
| - For data in motion, users' enterprise app websites are now https by default for secure data entry and retrieval | |||||
| More Information | |||||
| - [See this guide](https://github.com/kelaberetiv/TagUI/raw/master/src/media/TagUI%20Enterprise%20Setup%20v1.7.docx) on enterprise installation, including whitelisting details, TagUI architecture and dependencies | |||||
| - With -report option, there is a summary and detailed logs of robots, with support for centralised reporting | |||||
| # How to get started | |||||
| Join the community and ask any questions at our [Telegram chat group](https://t.me/rpa_chat) or our [AISG community site](https://community.aisingapore.org/groups/tagui-rpa/). Take [TagUI free course](https://learn.aisingapore.org/courses/learn-rpa-with-tagui-beginners-course/) over one morning or afternoon, and start using the most popular open-source RPA software. Share this [TagUI slide deck](https://docs.google.com/presentation/d/1pltAMzr0MZsttgg1w2ORH3ontR6Q51W9/edit?usp=sharing&ouid=115132044557947023533&rtpof=true&sd=true) with your team or customers to win their buy-in to use TagUI. | |||||
| If you are maintaining your own fork of TagUI (for eg tech leads, RPA consultants, individual developers), see this [maintainer training video series](https://www.youtube.com/watch?v=oq8HlJujraE) to understand how TagUI works behind the scenes, and for you to modify all aspects of TagUI and extend the software to your customers' exact needs, made-to-measure. | |||||
| # TagUI v5.11 | |||||
| For technical details of TagUI, such as architecture diagram and codebase structure, [see the old homepage](https://github.com/kelaberetiv/TagUI/tree/pre_v6) | |||||
| # Credits | |||||
| Open-source project|Maintainer|From|How does this contribute to TagUI project | |||||
| :------------------|:---------|:---|:---------------------------------------- | |||||
| [TagUI for China](http://www.tagui.com.cn)|[报表哥](https://www.zhihu.com/people/baobiaoge)|China|usage guide and repository in Chinese | |||||
| [TagUI for Notepad++](https://github.com/tilyanPristka/TagUI-Snippets-for-NotepadPP)|[Md Ardyansyah](https://www.linkedin.com/in/muhammad-ardyansyah/)|Indonesia|various TagUI plug-ins for Notepad++ | |||||
| [TagUI for VS Code](https://marketplace.visualstudio.com/items?itemName=TagUisupport.tagui-support)|[Subhas Malik](https://www.linkedin.com/in/subhasmalik/)|India|language extension for Visual Studio Code | |||||
| [TagUI for Robocorp](https://youtu.be/HAfQpNZVbKI)|[Nived N](https://www.linkedin.com/in/nived-n-776470139/)|India|run TagUI in Robocorp or Robot Framework | |||||
| [TagUI for Node-RED](https://flows.nodered.org/node/node-red-contrib-tagui)|[Allan Zimmermann](https://www.linkedin.com/in/skadefro/)|Denmark|low-code event-driven workflow automation | |||||
| [TagUI for C# .NET](https://www.nuget.org/packages/tagui)|[Allan Zimmermann](https://www.linkedin.com/in/skadefro/)|Denmark|C# version of TagUI (Install-Package tagui) | |||||
| [TagUI for Docker](https://hub.docker.com/r/openiap/nodered-tagui)|[Allan Zimmermann](https://www.linkedin.com/in/skadefro/)|Denmark|replicable RPA environment for everyone | |||||
| [RPA for Python](https://github.com/tebelorg/RPA-Python)|[Ken Soh](https://github.com/kensoh)|Singapore|Python version of TagUI (pip install rpa) | |||||
| [TagUI v3.0](https://github.com/kensoh/TagUI/tree/before_aisg)|[Ken Soh](https://github.com/kensoh)|Singapore|personal project before AI Singapore | |||||
| [SikuliX](http://sikulix.com)|[Raimund Hocke](https://github.com/RaiMan/)|Germany|computer vision, OCR, input hardware | |||||
| [CasperJS](http://casperjs.org)|[Nicolas Perriault](https://github.com/n1k0)|France|high-level JavaScript execution engine | |||||
| [PhantomJS](https://github.com/ariya/phantomjs)|[Ariya Hidayat](https://github.com/ariya)|Indonesia|foundation JavaScript execution engine | |||||
| [SlimerJS](https://slimerjs.org)|[Laurent Jouanneau](https://github.com/laurentj)|France|browser automation for FireFox <= v59 | |||||
| # Sponsor | |||||
| This project is supported by the [National Research Foundation](https://www.nrf.gov.sg), Singapore under its AI Singapore Programme (AISG-RP-2019-050). Any opinions, findings and conclusions or recommendations expressed in this material are those of the author(s) and do not reflect the views of National Research Foundation, Singapore. | 
| # Minimal makefile for Sphinx documentation | |||||
| # | |||||
| # You can set these variables from the command line, and also | |||||
| # from the environment for the first two. | |||||
| SPHINXOPTS ?= | |||||
| SPHINXBUILD ?= sphinx-build | |||||
| SOURCEDIR = . | |||||
| BUILDDIR = _build | |||||
| # Put it first so that "make" without argument is like "make help". | |||||
| help: | |||||
| @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) | |||||
| .PHONY: help Makefile | |||||
| # Catch-all target: route all unknown targets to Sphinx using the new | |||||
| # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). | |||||
| %: Makefile | |||||
| @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) | 
 
							 
							 
							 
							 
							| Advanced concepts | |||||
| =================== | |||||
| Saving run results of flow | |||||
| ---------------------------- | |||||
| You can save an html log of the run and the flow run results to ``tagui/src/tagui_report.csv`` with the ``-report`` option (shortcut ``-r``). :: | |||||
| tagui my_flow.tag -report | |||||
| The CSV file will show one line for each run, when it started, how long it took to complete, any error message during run, the link to the log file for that run, and the user's workgroup\\userid. | |||||
| Handling exceptions and errors | |||||
| -------------------------------- | |||||
| There are 3 ways to handle exceptions in TagUI when things do not go as planned. | |||||
| The first way is **local error handling**. This means using if conditions to check specifically for certain scenarios and handling the scenarios accordingly. For example, check if some UI element is missing, then do xyz steps. Using this way, a workflow can have multiple fine-grain exception handling. | |||||
| The second way is **workflow error handling**. A workflow can be chained as follows to handle error or success accordingly. The workflow error.tag will run only if flow.tag errors out. The workflow success.tag will run only if flow.tag runs successfully. TagUI will automatically throw error when it detects an expected UI element missing (and autosave screenshot) or some other unknown errors. | |||||
| Windows example from the command prompt:: | |||||
| call tagui flow.tag || tagui error.tag | |||||
| call tagui flow.tag && tagui success.tag | |||||
| macOS / Linux example from the terminal:: | |||||
| tagui flow.tag || tagui error.tag | |||||
| tagui flow.tag && tagui success.tag | |||||
| The third way is **global error handling**. Configuration can be done for TagUI such that after every run, special handling is done to send data or files generated from the report option to some target folder or API endpoint for error / success handling. For example, syncing all automation runs to central storage for auditing purpose. The special handling applies to all TagUI flows that are run. | |||||
| .. _datatables: | |||||
| Datatables for batch automation | |||||
| ------------------------------- | |||||
| Datatables are :ref:`csv files <what-are-csv-files>` which can be used to run your flows multiple times with different inputs. | |||||
| A datatable (``trade_data.csv``) could look like this: | |||||
| = ============ ============= ======== ====== ====== ========= | |||||
| # trade username password pair size direction | |||||
| - ------------ ------------- -------- ------ ------ --------- | |||||
| 1 Trade USDSGD test_account 12345678 USDSGD 10000 BUY | |||||
| 2 Trade USDSGD test_account 12345678 USDJPY 1000 SELL | |||||
| 3 Trade EURUSD test_account 12345678 EURUSD 100000 BUY | |||||
| = ============ ============= ======== ====== ====== ========= | |||||
| To use it, you run your flow with ``tagui my_flow.tag trade_data.csv``. TagUI will run ``my_flow.tag`` once for each row in the datatable (except for the header). | |||||
| Within the flow, TagUI can use the variables ``trade``, ``username``, ``password``, etc as if they were in the :ref:`local object repository <object-repository>` and the values will be from that run's row. | |||||
| To know which iteration your flow is in you can use the ``iteration`` variable:: | |||||
| echo current iteration: `iteration` | |||||
| if iteration equals to 1 | |||||
| // go to login URL and do the login steps | |||||
| www.xero.com | |||||
| // do rest of the steps for every iteration | |||||
| .. _object-repository: | |||||
| Object repositories for reusability | |||||
| ----------------------------------- | |||||
| Object repositories are optional :ref:`csv files <what-are-csv-files>` which can store variables for use in flows. They help to separate your flows from your personal data (like login information for web flows), and allow you to share common information between multiple flows for easy updating. | |||||
| Each flow has a **local object repository** and all flows share the **global object repository**. The local object repository is the ``tagui_local.csv`` in the same folder as the flow. The global object repository is the ``tagui_global.csv`` in the ``tagui/src/`` folder. | |||||
| An object repository could look like this: | |||||
| ============== ================================= | |||||
| object definition | |||||
| -------------- --------------------------------- | |||||
| email user-email-textbox | |||||
| create account btn btn--green btn-xl signup-btn | |||||
| ============== ================================= | |||||
| Within the flow, TagUI can use the objects ``email``, ``create account`` as variables and they will be replaced directly by the definitions before it is run. Local definitions take precedence over global definitions. | |||||
| If ``user-email-textbox`` was the identifier for some web text input, then you could use the following in your flow:: | |||||
| type `email` as my_email@email.com | |||||
| Running flows within a flow | |||||
| ----------------------------- | |||||
| You can modularise your RPA workflows by breaking a large workflow file into many subflow files. For more complex RPA scenarios, you can even let a subflow run other subflows. | |||||
| Some common reasons for doing that include the convenience of reusing the same subflow in other flows, doing something specific which is easier to organise by keeping the sequence of steps in a subflow, or storing your Python or JavaScript code and functions in separate subflows (using py begin and py finish code blocks for example). | |||||
| A flow can run another flow, like this:: | |||||
| tagui login_crm.tag | |||||
| Flows can also be stored in subfolders:: | |||||
| // Windows example | |||||
| tagui CRM\login.tag | |||||
| // Mac/Linux example | |||||
| tagui CRM/login.tag | |||||
| Variables in the parent flow are accessible in the child flow and vice versa:: | |||||
| // in this case, username and password variables are available in login.tag | |||||
| username = 'jennifer'; password = '12345678'; | |||||
| tagui login.tag | |||||
| // you can also define variables on separate lines instead of all in 1 line | |||||
| username = 'jennifer' | |||||
| password = '12345678' | |||||
| tagui login.tag | |||||
| // in login.tag you can define and return variables for its parent to use | |||||
| echo `login_result` | |||||
| You can even combine multiple sequences of steps into one subflow as follows. By designing a subflow this way, you can assign the variable ``action = 'login'`` in the parent flow to determine which sequence of steps gets executed when the subflow is called with ``tagui`` step:: | |||||
| // crm_steps.tag | |||||
| if action equals to 'login' | |||||
| do some steps | |||||
| do some more steps | |||||
| else if action equals to 'report' | |||||
| do some steps | |||||
| do some more steps | |||||
| else if action equals to 'logout' | |||||
| do some steps | |||||
| do some more steps | |||||
| else | |||||
| echo ERROR - action undefined | |||||
| Turbo mode to run 10X faster | |||||
| ------------------------------- | |||||
| To run TagUI with turbo option (use with caution):: | |||||
| tagui flow.tag -turbo | |||||
| or | |||||
| tagui flow.tag -t | |||||
| Most websites and desktop apps are not designed for the super-human speed user. If your RPA runs at a speed beyond what those websites are designed and tested for, you are surely going to run into problems with some apps. Problems could be fields and data not filling up properly, not triggering expected validations, form submissions with missing data, account being blocked etc. | |||||
| And the problems might happen randomly, including working on your PC but not working on another PC due to difference in CPU speed. Because of this, using turbo mode option is not recommended. You may save some cheap computer time, but if something is broken or does not work, you may end up spending expensive human time (your time) to troubleshoot or fix. | |||||
| However, this is very useful for some users for some specific scenarios. For eg, data collection from apps, data entry in web applications that can handle super-human speed reliably, as part of a chatbot doing backend RPA for user, for fast and rapid prototyping, perhaps taking part in RPA competitions and hackathons etc. Thoroughly test for your use case before using! | |||||
| Visual automation tricks | |||||
| ------------------------------------ | |||||
| For many steps, you can end the step with ``using ocr`` or ``using OCR`` to tell TagUI to interact on some UI element on the screen using OCR (optical character recognition). See the examples below. Steps which this can be done: click, rclick, dclick, hover, type, select, read, snap, exist(), present(). | |||||
| .. code-block:: none | |||||
| click Submit using ocr | |||||
| if exist('Special Offer using ocr') | |||||
| click Add To Cart using OCR | |||||
| // various usage combinations for select step | |||||
| select Dress Color using OCR as Dark Blue using OCR | |||||
| select dress_color.png as Bright Pink using ocr | |||||
| select Dress Color using OCR as dark_black.png | |||||
| select dress_color.png as bright_white.png | |||||
| If you make the background of a UI element in a ``.png`` file 100% transparent using an image editor, TagUI will be able to target the element regardless of its background. | |||||
| Conversely, you can also remove the foreground content near some anchor element like a frame, to allow you to OCR varying content in the empty area using the **read** step. | |||||
| .. _python: | |||||
| Writing Python within flows | |||||
| -------------------------------- | |||||
| You can write Python code in TagUI flows. Python needs to be `installed separately <https://www.python.org/downloads/>`_. | |||||
| The ``py`` step can be used to run commands in Python (TagUI will call ``python`` on the command line). You can pass string values back to TagUI with `print()`. The ``stdout`` will be stored in the ``py_result`` variable in TagUI. | |||||
| .. code-block:: none | |||||
| py a=1 | |||||
| py b=2 | |||||
| py c=a+b | |||||
| py print(c) | |||||
| echo `py_result` | |||||
| You can also use ``py begin`` and ``py finish`` before and after a Python code block:: | |||||
| py begin | |||||
| a=1 | |||||
| b=2 | |||||
| c=a+b | |||||
| print(c) | |||||
| py finish | |||||
| echo `py_result` | |||||
| You can pass a variable to Python like this:: | |||||
| phone = 1234567 | |||||
| py_step('phone = ' + phone) | |||||
| py print(phone) | |||||
| echo `py_result` | |||||
| name = 'Donald' | |||||
| py_step('name = "' + name + '"') | |||||
| py print(name) | |||||
| echo `py_result` | |||||
| To pass and return more complex data, for example multiple variables, you can use JavaScript and Python JSON libraries to send and receive back JSON strings. `See an example here <https://github.com/kelaberetiv/TagUI/issues/898#issuecomment-752833953>`_ of passing 2 variables, doing some processing, and returning 2 variables. | |||||
| Create log files for debugging | |||||
| --------------------------------- | |||||
| To do advanced debugging, you can create log files when running flows by creating an empty ``tagui_logging`` file in ``tagui/src/``. | |||||
| - ``my_flow.log`` stores step-by-step output of the execution. | |||||
| - ``my_flow.js`` is the generated JavaScript file that was run. | |||||
| - ``my_flow.raw`` is the expanded flow after parsing modules. | |||||
| Running TagUI on the cloud | |||||
| ----------------------------- | |||||
| For cloud lovers, you can run TagUI on your web browser or phone using `free Google Cloud <https://github.com/kelaberetiv/TagUI/issues/913>`_. You can run up to 5 sessions concurrently on different tabs of your browser. | |||||
| For more control running on the cloud, you can run this `Docker image <https://hub.docker.com/r/openiap/nodered-tagui>`_ (use edge tag for the latest version) or `Docker file <https://github.com/open-rpa/openflow/blob/master/OpenFlowNodeRED/Dockerfiletagui>`_ on your preferred cloud vendor. | |||||
| Or run on `free Node-RED instance <https://app.openiap.io/>`_ on OpenFlow. The Docker image, Docker file and OpenFlow cloud are maintained and sponsored by `Allan Zimmermann <https://www.linkedin.com/in/skadefro/>`_. | 
| # Configuration file for the Sphinx documentation builder. | |||||
| # | |||||
| # This file only contains a selection of the most common options. For a full | |||||
| # list see the documentation: | |||||
| # https://www.sphinx-doc.org/en/master/usage/configuration.html | |||||
| # At top on conf.py (with other import statements) | |||||
| import recommonmark | |||||
| from recommonmark.transform import AutoStructify | |||||
| # -- Path setup -------------------------------------------------------------- | |||||
| # If extensions (or modules to document with autodoc) are in another directory, | |||||
| # add these directories to sys.path here. If the directory is relative to the | |||||
| # documentation root, use os.path.abspath to make it absolute, like shown here. | |||||
| # | |||||
| # import os | |||||
| # import sys | |||||
| # sys.path.insert(0, os.path.abspath('.')) | |||||
| # -- Project information ----------------------------------------------------- | |||||
| project = 'TagUI' | |||||
| copyright = '2021, AI Singapore' | |||||
| author = 'Ken Soh, Siow Yi Sheng' | |||||
| # The full version, including alpha/beta/rc tags | |||||
| release = '6.46.0' | |||||
| # -- General configuration --------------------------------------------------- | |||||
| # Add any Sphinx extension module names here, as strings. They can be | |||||
| # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom | |||||
| # ones. | |||||
| extensions = [ | |||||
| 'recommonmark', | |||||
| 'sphinx.ext.autosectionlabel', | |||||
| ] | |||||
| autosectionlabel_prefix_document = True | |||||
| # Add any paths that contain templates here, relative to this directory. | |||||
| templates_path = ['_templates'] | |||||
| # List of patterns, relative to source directory, that match files and | |||||
| # directories to ignore when looking for source files. | |||||
| # This pattern also affects html_static_path and html_extra_path. | |||||
| exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] | |||||
| # -- Options for HTML output ------------------------------------------------- | |||||
| # The theme to use for HTML and HTML Help pages. See the documentation for | |||||
| # a list of builtin themes. | |||||
| # | |||||
| html_theme = 'sphinx_rtd_theme' | |||||
| # Add any paths that contain custom static files (such as style sheets) here, | |||||
| # relative to this directory. They are copied after the builtin static files, | |||||
| # so a file named "default.css" will overwrite the builtin "default.css". | |||||
| html_static_path = ['_static'] | |||||
| master_doc = 'index' | |||||
| def setup(app): | |||||
| app.add_config_value( | |||||
| 'recommonmark_config', { | |||||
| 'url_resolver': lambda url: github_doc_root + url, | |||||
| 'auto_toc_tree_section': 'Contents', | |||||
| }, True) | |||||
| app.add_transform(AutoStructify) | 
| Deprecated command line options | |||||
| ================================ | |||||
| chrome | |||||
| run on visible Chrome web browser instead of invisible PhantomJS (first install Chrome) | |||||
| firefox | |||||
| run on visible Firefox web browser instead of invisible browser (first install Firefox) | |||||
| speed | |||||
| skip 3-second delay between datatable iterations (and skip restarting of Chrome browser) | |||||
| upload | |||||
| upload automation flow and result to hastebin.com (expires 30 days after last view) | |||||
| debug | |||||
| show run-time backend messages from PhantomJS mode for detailed tracing and logging | |||||
| test | |||||
| testing with check step test assertions for CI/CD integration (output XUnit XML file) | |||||
| baseline | |||||
| output execution log and relative-path output files to a separate baseline directory | 
| Frequently Asked Questions | |||||
| ============================= | |||||
| How is TagUI licensed? | |||||
| ------------------------- | |||||
| TagUI is a free, open-source, cross-platform software released under the Apache 2.0 license. | |||||
| .. _find-xpath: | |||||
| How do I find the XPath of a web element? | |||||
| --------------------------------------------- | |||||
| In Chrome/Edge, right-click on the element, click Inspect, right-click on the highlighted HTML, then: | |||||
| .. image:: ./_static/find_xpath.png | |||||
| For some web pages, the XPath of an element can change. To combat this, you can find a stable element in the web page and writing a custom XPath relative to that stable element. | |||||
| XPath is very powerful and can allow you to select web elements in many ways. Learn more about XPath at `W3Schools <https://www.w3schools.com/xml/xpath_intro.asp>`_. Alternatively, check out `SelectorsHub Chrome extension <https://chrome.google.com/webstore/detail/selectorshub/ndgimibanhlabgdgjcpbbndiehljcpfh?hl=en>`_ tool. | |||||
| .. _element_attributes: | |||||
| How do I find the id, name, class or other attributes of a web element? | |||||
| ---------------------------------------------------------------------------- | |||||
| In Chrome/Edge, right-click on the element, click Inspect. There will be some highlighted HTML, like this: | |||||
| .. image:: ./_static/element_attributes.png | |||||
| This highlighted element has a ``class`` attribute of "chat-line__body". It doesn't have any ``id`` or ``name`` attribute | |||||
| .. _how-to-use-command-prompt: | |||||
| How do I use the Command Prompt? | |||||
| ---------------------------------------- | |||||
| Hold the Windows key and press R. Then type ``cmd`` and press Enter to enter the Command Prompt. | |||||
| From here, you can run a command by typing it and pressing Enter. | |||||
| .. _how-to-use-terminal: | |||||
| How do I use the Terminal? | |||||
| ---------------------------------------- | |||||
| Hold Command and press spacebar, then type ``terminal`` and press Enter. | |||||
| From here, you can run a command by typing it and pressing Enter. | |||||
| .. _what-are-csv-files: | |||||
| What are csv files? | |||||
| ------------------------------------------------- | |||||
| CSV files are files which stores data in a table form. They can be opened with Microsoft Excel and Google Sheets. Each line is a row of values. The values are split into different columns by commas ``,``, which is why CSV stands for Comma Separated Values. | |||||
| .. _run-on-schedule: | |||||
| Running flows on a fixed schedule | |||||
| -------------------------------------- | |||||
| It is often useful to run flows automatically on a fixed schedule: monthly, weekly, daily or even every 5 minutes. | |||||
| On Windows, `use the Task Scheduler <https://www.digitalcitizen.life/how-create-task-basic-task-wizard>`_. | |||||
| .. raw:: html | |||||
| <video playsinline autoplay muted loop width="100%"> | |||||
| <source src="./_static/schedule-a-flow.mp4" type="video/mp4"> | |||||
| Your browser does not support the video tag. | |||||
| </video> | |||||
| | | |||||
| On macOS / Linux, `use crontab command <https://www.ostechnix.com/a-beginners-guide-to-cron-jobs/>`_. | |||||
| How do I kill any unfinished TagUI processes? | |||||
| ----------------------------------------------- | |||||
| If you Ctrl+C to break a TagUI automation, you can use ``tagui/src/end_processes`` (for macOS / Linux) or ``end_processes.cmd`` (for Windows) to kill any dead processes of TagUI integrations (Chrome, Edge, SikuliX, Python etc). | |||||
| Why doesn't TagUI work on zoom levels other than 100%? | |||||
| ------------------------------------------------------------- | |||||
| TagUI mimics the user mouse-clicks at the (x,y) coordinates of web elements, so using a different zoom level for your web browser will cause clicks to be triggered at wrong coordinates. Make sure TagUI's Chrome/Edge browser is set to 100% zoom for best results. | |||||
| Is TagUI safe and secure to use? | |||||
| -------------------------------- | |||||
| As TagUI and the foundation it's built on is open-source software, it means users can read the source code of TagUI and all its dependencies to check if there is a security flaw or malicious code. This is an advantage compared to using commercial software that is closed-source, as users cannot see what is the code behind the software. | |||||
| Following are links to the source code for TagUI and its open-source dependencies. You can dig through the source code for the other open-source dependencies below, or make the fair assumption that security issues would have been spotted by users and fixed, as these projects are mature and have large user bases. | |||||
| - TagUI - https://github.com/kelaberetiv/TagUI | |||||
| - SikuliX - https://github.com/RaiMan/SikuliX1 | |||||
| - CasperJS - https://github.com/casperjs/casperjs | |||||
| - PhantomJS - https://github.com/ariya/phantomjs | |||||
| - SlimerJS - https://github.com/laurentj/slimerjs | |||||
| - Python - https://github.com/python/cpython | |||||
| - R - https://github.com/wch/r-source | |||||
| - PHP - https://github.com/php/php-src | |||||
| See this section on why TagUI has enterprise security by design - https://github.com/kelaberetiv/TagUI#enterprise-security-by-design | |||||
| Does TagUI track what I automate? | |||||
| --------------------------------------- | |||||
| No. TagUI does not send outgoing web traffic or outgoing data, other than what the user is automating on, for example visiting a website. | |||||
| .. _visual-automation-troubleshooting: | |||||
| Why doesn’t my visual automation work? | |||||
| ---------------------------------------- | |||||
| On macOS, it may be due to `how the image was captured <https://github.com/kelaberetiv/TagUI/issues/240#issuecomment-863112988>`_. | |||||
| On Linux, you may need to `set up OpenCV and Tesseract <https://sikulix-2014.readthedocs.io/en/latest/newslinux.html#version-1-1-4-special-for-linux-people>`_. | 
| TagUI | |||||
| ================================= | |||||
| .. image:: _static/tagui-logo.png | |||||
| :width: 400px | |||||
| A free, open-source, cross-platform RPA tool that helps you automate your desktop, web, mouse and keyboard actions easily. Here's what a simple TagUI flow looks like: | |||||
| .. code-block:: none | |||||
| // below is an example to login to Xero accounting website | |||||
| https://login.xero.com/identity/user/login | |||||
| type email as user@gmail.com | |||||
| type password as 12345678 | |||||
| click Log in | |||||
| .. code-block:: none | |||||
| // besides web identifiers, images of UI elements can be used | |||||
| type email_box.png as user@gmail.com | |||||
| type password_box.png as 12345678 | |||||
| click login_button.png | |||||
| .. code-block:: none | |||||
| // (x,y) coordinates of user-interface elements can also be used | |||||
| type (720,400) as user@gmail.com | |||||
| type (720,440) as 12345678 | |||||
| click (720,500) | |||||
| .. toctree:: | |||||
| :maxdepth: 1 | |||||
| :caption: Contents: | |||||
| :hidden: | |||||
| Installation <setup> | |||||
| Main concepts <main_concepts> | |||||
| Advanced concepts <advanced> | |||||
| Reference <reference> | |||||
| Tools <tools> | |||||
| FAQ <faq> | |||||
| :doc:`Download TagUI v6.46 here </setup>`. | 
| Main concepts | |||||
| ==================== | |||||
| Flows | |||||
| -------------- | |||||
| TagUI automates your actions by running *flows*, which are text files with ``.tag`` file extension. | |||||
| You can run a flow in the :ref:`Command Prompt/Terminal<how-to-use-command-prompt>` like this:: | |||||
| tagui my_flow.tag | |||||
| .. raw:: html | |||||
| <video playsinline autoplay muted loop width="100%"> | |||||
| <source src="./_static/run-a-flow.mp4" type="video/mp4"> | |||||
| Your browser does not support the video tag. | |||||
| </video> | |||||
| | | |||||
| TagUI looks for ``my_flow.tag`` in your current working directory. You can also provide the full path:: | |||||
| tagui c:\tagui\samples\1_google.tag | |||||
| You can also :ref:`run flows on a fixed schedule <run-on-schedule>`. | |||||
| Run by double-click | |||||
| ********************** | |||||
| You can create a shortcut file with ``-deploy``:: | |||||
| tagui my_flow.tag -deploy | |||||
| or using the shortcut ``-d``:: | |||||
| tagui my_flow.tag -d | |||||
| This creates a shortcut (my_flow.cmd) to run your flow just by double clicking the shortcut. The shortcut is in the same folder as your flow, but you can move it to your desktop or anywhere else. | |||||
| .. raw:: html | |||||
| <video playsinline autoplay muted loop width="100%"> | |||||
| <source src="./_static/deploy-a-flow.mp4" type="video/mp4"> | |||||
| Your browser does not support the video tag. | |||||
| </video> | |||||
| | | |||||
| If you want to create the shortcut with options like ``-headless`` (``-h``), you can include them:: | |||||
| tagui my_flow.tag -h -d | |||||
| .. note:: If you move your flow file to another folder, you will need to create a new shortcut file. | |||||
| Run from a URL | |||||
| ********************** | |||||
| You can also run a flow directly from a URL:: | |||||
| tagui https://raw.githubusercontent.com/kelaberetiv/TagUI/master/flows/samples/1_google.tag | |||||
| Hide the browser | |||||
| ********************** | |||||
| You can run web flows without showing web browser by running TagUI with ``-headless`` option. :: | |||||
| tagui my_flow.tag -headless | |||||
| or using the shortcut ``-h``:: | |||||
| tagui my_flow.tag -h | |||||
| This allows you to continue using your desktop normally while the flow is running, but it will not work if your flow uses visual automation, because it reads and clicks what is on your screen. | |||||
| .. raw:: html | |||||
| <video playsinline autoplay muted loop width="100%"> | |||||
| <source src="./_static/run-headless-flow.mp4" type="video/mp4"> | |||||
| Your browser does not support the video tag. | |||||
| </video> | |||||
| | | |||||
| Steps | |||||
| --------- | |||||
| Flows are made out of *steps*. Below are some common steps. | |||||
| You can see the full list of steps in the :ref:`steps reference <step-reference>`. | |||||
| click | |||||
| ********** | |||||
| One of the most common steps is click. You can use it to click on a web element: | |||||
| .. code-block:: none | |||||
| click Getting started | |||||
| This command tells TagUI to try to click on any element which has “Getting started” as its “id”, “name”, “class” or “title” attributes (:ref:`How to find an element’s attributes <element_attributes>`), or as a last resort, has “Getting started” in its text. | |||||
| This method usually works for targeting what you want, but you can be more explicit by providing an XPath. XPath is a powerful way to choose which web element you want to target. For example: | |||||
| .. code-block:: none | |||||
| click //a[@class="icon icon-home"] | |||||
| You can also click on a certain point on your screen: | |||||
| .. code-block:: none | |||||
| click (500,300) | |||||
| Here, 500 and 300 are x-y coordinates. This command clicks on a point which is 500 pixels from the left of your screen and 300 pixels from the top of your screen. A good way to discover which coordinates to input is to use the ``mouse_xy()`` :ref:`helper function <helper-functions>` in live mode. | |||||
| Lastly, you can use visual automation to click where it matches a previously saved image. This command looks for button.png in the same folder as your flow, then looks for a similar image on your screen, and clicks it: | |||||
| .. code-block:: none | |||||
| click button.png | |||||
| It’s often a good idea to keep your flows and images organised. You can create a folder (eg. named images) for your images and use the image like this instead: | |||||
| .. code-block:: none | |||||
| click image/button.png | |||||
| visit | |||||
| ********** | |||||
| You can visit a webpage simply by entering the url: | |||||
| .. code-block:: none | |||||
| https://somewebsite.com | |||||
| type | |||||
| ********** | |||||
| You can type into web inputs. This command finds the element “some-input” in the same way as for the **click** step and types “some-text” into it: | |||||
| .. code-block:: none | |||||
| type some-input as some-text | |||||
| You can use [clear] to clear the input and [enter] to hit the Enter key: | |||||
| .. code-block:: none | |||||
| type some-input as [clear]some-text[enter] | |||||
| You can also use an image as the target, just like with the **click** step: | |||||
| .. code-block:: none | |||||
| type some-input.png as some-text | |||||
| read | |||||
| ********** | |||||
| The **read** step allows you to save text from web elements or from the screen into a variable. | |||||
| This command finds the element “some-element” and saves its value into a variable called “some-variable”: | |||||
| .. code-block:: none | |||||
| read some-element to some-variable | |||||
| **read** can also use visual automation and OCR to read text from a region of your screen. The output from this may not be completely accurate as it relies on OCR. | |||||
| This command reads all the text in the rectangle formed between the points (300,400) and (500,550): | |||||
| .. code-block:: none | |||||
| read (300,400)-(500,550) to some-variable | |||||
| You can also use XPath to read some attribute values from web elements. This command reads the id attribute from the element: | |||||
| .. code-block:: none | |||||
| read //some-element/@some-attribute to some-variable | |||||
| assign | |||||
| ********** | |||||
| You can assign values into variables. This makes them easier to reference and work with. | |||||
| This example uses the ``count()`` :ref:`helper function <helper-functions>`, counts the number of elements found with id/name/text with ‘row’ in them and assigns it to a variable ``row_count`` for later use: | |||||
| .. code-block:: none | |||||
| row_count = count('row') | |||||
| Identifiers | |||||
| --------------- | |||||
| You have probably noticed that different steps have different ways that they target elements, called **identifiers**. Let's look at the different types of identifiers. | |||||
| .. note:: The DOM and XPath identifiers only work for Chrome/Edge. To automate other browsers, use the Point/Region and Image identifiers. | |||||
| .. _dom: | |||||
| DOM | |||||
| ********** | |||||
| .. code-block:: none | |||||
| click Getting started | |||||
| This matches an element in the DOM (Document Object Model) of the web page, matching either the :ref:`id, name, class attributes <element_attributes>` or the text of the element itself. | |||||
| .. _xpath: | |||||
| XPath | |||||
| ********** | |||||
| .. code-block:: none | |||||
| click //body/div[1]/nav/div/div[1]/a | |||||
| This matches the :ref:`XPath <find-xpath>` of an element in the web page. | |||||
| It is a more explicit and powerful way of targeting web elements. | |||||
| .. note:: You can use CSS selectors too in place of XPath, but XPath is preferred. | |||||
| .. _point: | |||||
| Point | |||||
| ********** | |||||
| .. code-block:: none | |||||
| click (200,500) | |||||
| This matches the point on the screen 200 pixels from the left of the screen and 500 pixels from the top of the screen. This uses *visual automation*. | |||||
| .. _region: | |||||
| Region | |||||
| ********** | |||||
| .. code-block:: none | |||||
| read (300,400)-(500,550) to some-variable | |||||
| This matches the rectangle formed between the two points (300,400) and (500,550). See :ref:`Point <point>`. This uses *visual automation*. | |||||
| .. _image: | |||||
| Image | |||||
| ********** | |||||
| .. code-block:: none | |||||
| click button.png | |||||
| This matches any area on the screen that looks similar to an image file ``button.png`` (in the folder of the flow). You first need to take a screenshot of ``button.png``. This uses *visual automation*. | |||||
| .. code-block:: none | |||||
| click image/button.png | |||||
| This allows you to look for ``button.png`` within the ``image`` folder. | |||||
| .. _live-mode: | |||||
| Live mode | |||||
| --------------- | |||||
| We recommend using live mode when you want to write your own flows or try out some step. In :ref:`Command Prompt/Terminal <how-to-use-command-prompt>`:: | |||||
| tagui live | |||||
| This starts up a live session, where you can run steps one line at a time and immediately see the output. Within a TagUI flow, you can also use ``live`` step to pause execution and enter live mode. | |||||
| .. raw:: html | |||||
| <video playsinline autoplay muted loop width="100%"> | |||||
| <source src="./_static/live-mode.mp4" type="video/mp4"> | |||||
| Your browser does not support the video tag. | |||||
| </video> | |||||
| | | |||||
| .. _if-conditions: | |||||
| If conditions | |||||
| --------------- | |||||
| You may want your flow to do something different depending on some factors. You can use an if condition to do this. | |||||
| For example, if the URL contains the word “success”, then we want to click some buttons: | |||||
| .. code-block:: none | |||||
| if url() contains "success" | |||||
| click button1.png | |||||
| click button2.png | |||||
| ``url()`` is a :ref:`helper function <helper-functions>` that gets the url of the current webpage. Note that the other lines are *indented*, ie. there are spaces (or tabs) in front of them. This means that they are in the *if block*. The steps in the *if block* will only be run if the condition is met, ie. the url contains the word “success”. | |||||
| .. note:: | |||||
| Before v6, you need to use ``{`` and ``}`` to surround your *if block*. | |||||
| From v6 onwards, the curly braces ``{}`` are optional. | |||||
| Another common case is to check if some element exists. Here, we say that “if some-element doesn’t appear after waiting for the timeout, then visit this webpage”. | |||||
| .. code-block:: none | |||||
| if !exist('some-element') | |||||
| https://tagui.readthedocs.io/ | |||||
| The ! negates the condition and comes from JavaScript, which TagUI code eventually translates to. | |||||
| In below example, we check if a variable row_count, which we assigned a value earlier, is equal to 5: | |||||
| .. code-block:: none | |||||
| if row_count equals to 5 | |||||
| some steps | |||||
| Here’s how we check if it is more than or less than 5: | |||||
| .. code-block:: none | |||||
| if row_count more than 5 | |||||
| some steps | |||||
| .. code-block:: none | |||||
| if row_count less than 5 | |||||
| some steps | |||||
| .. _for-loops: | |||||
| For loops | |||||
| ----------- | |||||
| You can use loops to do the same thing many times within the same flow. In order to run one flow many times with different variables, the standard way is to use :ref:`datatables <datatables>`. | |||||
| In this example, we repeat the steps within the block for a total of 20 times: | |||||
| .. code-block:: none | |||||
| for n from 1 to 20 | |||||
| some step to take | |||||
| some other step | |||||
| some more step | |||||
| .. _helper-functions: | |||||
| Helper functions | |||||
| --------------------- | |||||
| Helper functions are useful JavaScript functions which can get values to use in your steps. | |||||
| Each helper function is followed by brackets ``()``. Some helper functions take inputs within these brackets. You can see the full list of helper functions in the :ref:`helper functions reference <helper-functions-reference>`. | |||||
| csv_row() | |||||
| ********************* | |||||
| Turns some variables into csv text for writing to a csv file. It takes variables as its input, surrounded by square brackets ``[]`` (which is actually a JavaScript array). | |||||
| .. code-block:: none | |||||
| read name_element to name | |||||
| read price_element to price | |||||
| read details_element to details | |||||
| write `csv_row([name, price, details])` to product_list.csv | |||||
| clipboard() | |||||
| ********************* | |||||
| Gets text from the clipboard:: | |||||
| dclick pdf_document.png | |||||
| wait 3 seconds | |||||
| keyboard [ctrl]a | |||||
| keyboard [ctrl]c | |||||
| text_contents = clipboard() | |||||
| You can also give it an input, which puts the input *onto* the clipboard instead. This can be useful for pasting large amounts of text directly, which is faster than using the **type** step:: | |||||
| long_text = "This is a very long text which takes a long time to type" | |||||
| clipboard(long_text) | |||||
| click text_input | |||||
| keyboard [ctrl]v | |||||
| keyboard [enter] | |||||
| mouse_x(), mouse_y() | |||||
| ********************* | |||||
| Gets the mouse's x or y coordinates. | |||||
| This is useful for modifying x or y coordinates with numbers for using in steps like ``read`` and ``click``. The example below clicks 200 pixels to the right of ``element.png``:: | |||||
| hover element.png | |||||
| x = mouse_x() + 200 | |||||
| y = mouse_y() | |||||
| click (`x`,`y`) | |||||
| mouse_xy() | |||||
| ********************* | |||||
| In live mode, you can use find out the coordinates of your mouse using ``echo `mouse_xy()``` so that you can use the coordinates in your flows:: | |||||
| echo `mouse_xy()` | 
| @ECHO OFF | |||||
| pushd %~dp0 | |||||
| REM Command file for Sphinx documentation | |||||
| if "%SPHINXBUILD%" == "" ( | |||||
| set SPHINXBUILD=sphinx-build | |||||
| ) | |||||
| set SOURCEDIR=. | |||||
| set BUILDDIR=_build | |||||
| if "%1" == "" goto help | |||||
| %SPHINXBUILD% >NUL 2>NUL | |||||
| if errorlevel 9009 ( | |||||
| echo. | |||||
| echo.The 'sphinx-build' command was not found. Make sure you have Sphinx | |||||
| echo.installed, then set the SPHINXBUILD environment variable to point | |||||
| echo.to the full path of the 'sphinx-build' executable. Alternatively you | |||||
| echo.may add the Sphinx directory to PATH. | |||||
| echo. | |||||
| echo.If you don't have Sphinx installed, grab it from | |||||
| echo.http://sphinx-doc.org/ | |||||
| exit /b 1 | |||||
| ) | |||||
| %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% | |||||
| goto end | |||||
| :help | |||||
| %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% | |||||
| :end | |||||
| popd | 
| Installation | |||||
| =================== | |||||
| Windows | |||||
| ------------------------------- | |||||
| **You are recommended to download** `TagUI Windows Installer <https://github.com/kelaberetiv/TagUI/releases/download/v6.46.0/TagUI_Windows.exe>`_, instead of the advanced steps below. If you use the installer, specify an installation folder which you have write permission, for example ``C:\RPA`` or a ``RPA`` folder on your Windows Deskop. After your installation, continue from step 6. | |||||
| 1. Read the above, or download zip file `TagUI v6.46 for Windows <https://github.com/kelaberetiv/TagUI/releases/download/v6.46.0/TagUI_Windows.zip>`_ | |||||
| 2. Unzip the contents to ``C:\`` | |||||
| 3. `Install OpenJDK for Windows <https://corretto.aws/downloads/latest/amazon-corretto-8-x64-windows-jdk.msi>`_ | |||||
| 4. `Install Chrome web browser <https://www.google.com/chrome/>`_ | |||||
| 5. `Add c:\\tagui\\src to start of path <https://www.c-sharpcorner.com/article/add-a-directory-to-path-environment-variable-in-windows-10/>`_ | |||||
| 6. Open :ref:`Command Prompt <how-to-use-command-prompt>` | |||||
| 7. Copy, paste and run this command: | |||||
| .. code-block:: bat | |||||
| tagui c:\tagui\flows\samples\1_google.tag | |||||
| 8. Finally, run this command to pull the `latest features and bug fixes <https://github.com/kelaberetiv/TagUI/issues?q=is%3Aissue+is%3Aopen+in%3Atitle+fixed+OR+done+>`_ | |||||
| .. code-block:: bat | |||||
| tagui update | |||||
| 9. :ref:`Having problems? Click here.<troubleshooting-windows>` You have run your first TagUI flow! 🎉 | |||||
| **To install TagUI Microsoft Word Plug-in (a full-featured app to make RPA very easy)**, download the `MS Word Plug-in installer <https://github.com/kelaberetiv/TagUI/releases/download/v6.64.0/TagUIWordAddInSetupV3.15.zip>`_, unzip the file and double-click Setup.exe. See this `video by RPA Learners <https://www.youtube.com/watch?v=mtiuzU6e4XE>`_ on installing and running your first MS Word RPA bot. Download `MS Excel Plug-in installer <https://github.com/kelaberetiv/TagUI/releases/download/v6.64.0/TagUIExcelAddInSetupv3.06.zip>`_ to define RPA data parameters in Excel and run TagUI from Excel. See this `video by RPA Learners <https://www.youtube.com/watch?v=YsA9hpveROs>`_ on installing and creating visualisations with the Excel plug-in. | |||||
| macOS / Linux | |||||
| ----------------------------------- | |||||
| 1. Download TagUI v6.46 for `macOS <https://github.com/kelaberetiv/TagUI/releases/download/v6.46.0/TagUI_macOS.zip>`_ or `Linux <https://github.com/kelaberetiv/TagUI/releases/download/v6.46.0/TagUI_Linux.zip>`_ | |||||
| 2. Unzip the contents to your desktop on macOS, or ``/home/your_userid`` on Linux | |||||
| 3. Install OpenJDK for `macOS <https://corretto.aws/downloads/latest/amazon-corretto-8-x64-macos-jdk.pkg>`_ or `Linux <https://corretto.aws/downloads/latest/amazon-corretto-8-x64-linux-jdk.tar.gz>`_ | |||||
| 4. `Install Chrome web browser <https://www.google.com/chrome/>`_ | |||||
| 5. Open :ref:`Terminal <how-to-use-terminal>` | |||||
| 6. Copy, paste and run these commands, replacing ``your_tagui_path`` accordingly: | |||||
| .. code-block:: bash | |||||
| sudo ln -sf /your_tagui_path/tagui/src/tagui /usr/local/bin/tagui | |||||
| tagui /your_tagui_path/tagui/flows/samples/1_google.tag | |||||
| 7. Finally, run this command to pull the `latest features and bug fixes <https://github.com/kelaberetiv/TagUI/issues?q=is%3Aissue+is%3Aopen+in%3Atitle+fixed+OR+done+>`_ | |||||
| .. code-block:: bash | |||||
| tagui update | |||||
| 8. :ref:`Having problems? Click here.<troubleshooting-macos-linux>` You have run your first TagUI flow! 🎉 | 
| .. _troubleshooting-windows: | |||||
| Troubleshooting Windows | |||||
| ================================ | |||||
| - If you see ``MSVCR110.dll is missing`` error, install :download:`Visual C++ Redistributable <./_static/vcredist_x86.exe>` | |||||
| - If you cannot unzip to ``C:\`` folder, unzip to your Windows Desktop instead | |||||
| .. _troubleshooting-macos-linux: | |||||
| Troubleshooting macOS | |||||
| ================================ | |||||
| - For newer versions of macOS (Monterey onwards), you will need to `install PHP separately <https://github.com/kelaberetiv/TagUI/issues/1137#issuecomment-989465983>`_ | |||||
| - macOS now has tighter security controls, see solutions for the `PhantomJS <https://github.com/kelaberetiv/TagUI/issues/601>`_ and `Java popups <https://github.com/kelaberetiv/TagUI/issues/598>`_ | |||||
| Troubleshooting Linux | |||||
| ================================ | |||||
| - You may need to google and install PHP on Linux, for eg Ubuntu does not come with PHP | |||||
| - On Linux, visual automation, OCR and keyboard step require `some manual setup <https://sikulix-2014.readthedocs.io/en/latest/newslinux.html>`_ | 
| Tools | |||||
| ==================== | |||||
| These are separate apps which help you in writing TagUI flows. | |||||
| TagUI Chrome Extension | |||||
| -------------------------- | |||||
| The TagUI Chrome extension (`download <https://chrome.google.com/webstore/detail/tagui-web-automation/egdllmehgfgjebhlkjmcnhiocfcidnjk/>`_) helps you write web flows. | |||||
| It records steps such as page navigation, clicking of web elements and entering information. It then displays the steps for you to paste into your flow. | |||||
| Usage | |||||
| ************************* | |||||
| 1. Go to the website URL you want to start the automation at. | |||||
| 2. Click the TagUI icon, then **Start**. | |||||
| 3. Carry out the steps you want to automate, or right click on elements to record other steps. | |||||
| 4. Click the TagUI icon, then **Stop**. | |||||
| 5. Click **Export** to view the generated TagUI steps. | |||||
| The recording isn't foolproof (for example, the underlying recording engine cannot capture frames, popup windows or tab key input). It's meant to simplify flow creation with some edits, instead of typing everything manually. | |||||
| `See this video <https://www.youtube.com/watch?v=bFvsc4a8hWQ>`_ for an example of recording a sequence of steps, editing for adjustments and playing back the automation. | |||||
| TagUI Writer, Screenshoter & Editor | |||||
| ---------------------------------------- | |||||
| TagUI Writer is a Windows app helps write TagUI flows. When pressing Ctrl + Left-click, a popup menu appears with the list of TagUI steps for you to paste into your text editor. | |||||
| TagUI Screenshoter app helps in capturing screenshots for TagUI visual automation. | |||||
| TagUI Editor allows you to edit and run TagUI scripts via AutoHotKey. | |||||
| `Download these here. <https://github.com/adegard/tagui_scripts>`_. These third-party tools are created by Arnaud Degardin `@adegard <https://github.com/adegard>`_. | |||||
| .. image:: https://raw.githubusercontent.com/adegard/tagui_scripts/master/TagUI_Editor.gif | |||||
| RPA for Python (for Python users) | |||||
| --------------------------------------- | |||||
| RPA for Python is a Python package (``pip install rpa`` to install) which allows you to use TagUI through a Python API. Check out `the documentation <https://github.com/tebelorg/RPA-Python>`_. It is based on a fork of TagUI optimised for use by the Python package. Created and maintained by TagUI's creator Ken Soh `@kensoh <https://github.com/kensoh>`_. | |||||
| .. image:: https://raw.githubusercontent.com/tebelorg/Tump/master/tagui_python.gif | 
| // This flow makes a search on Google, clicks the first result and screenshots the page | |||||
| // First, visit google.com (www.google.com without https:// works as well) | |||||
| https://www.google.com | |||||
| // Look on the web page for an element with 'q' in its text, id or name | |||||
| // (or some other attributes), then type 'latest movies' and enter | |||||
| // type q as latest movies[enter] | |||||
| // Use a more accurate identifier below instead because | |||||
| // google.com webpage differs for different locations | |||||
| type //*[@name="q"] as latest movies[enter] | |||||
| // Click first result using XPath, an identification method | |||||
| // Learn XPath: https://www.w3schools.com/xml/xpath_intro.asp | |||||
| // XPath Cheatsheet: https://www.linkedin.com/posts/kensoh_xpath-rpa-tagui-activity-6829673864633704448-Iw-D | |||||
| click (//*[@class="yuRUbf"])[1]//a | |||||
| // Wait for 3 seconds so the page can load (wait 3 seconds works as well) | |||||
| wait 3 | |||||
| // Save a screenshot of the web page to top_result.png | |||||
| snap page to top_result.png | 
| // This flow visits a GitHub page, reads some info from the page and makes a download | |||||
| // Visit the webpage | |||||
| https://github.com/kelaberetiv/TagUI | |||||
| // Save text from the element using XPath into variable license_type, | |||||
| // then show the variable value on the console using echo step | |||||
| // Learn XPath: https://www.w3schools.com/xml/xpath_intro.asp | |||||
| // XPath Cheatsheet: https://www.linkedin.com/posts/kensoh_xpath-rpa-tagui-activity-6829673864633704448-Iw-D | |||||
| read (//*[@class="Link--muted"])[3] to license_type | |||||
| echo `license_type` | |||||
| // Look for a web element with provided XPath, CSS or attributes | |||||
| // Then click to download the file to the folder of current flow | |||||
| click //get-repo | |||||
| click //*[contains(@href, "master.zip")] | |||||
| // Wait 15 seconds to give the download time to complete on slow networks | |||||
| wait 15 | 
| // This flow demonstrates the usage of conditions | |||||
| // Assign the string 'dog, cat' to the variable 'animals' | |||||
| // Assign the number 12 to the variable 'cupcakes' | |||||
| animals = 'dog, cat' | |||||
| cupcakes = 12 | |||||
| // If the condition is true, then show 'animals' value in the command line output, or else do nothing | |||||
| if animals equals to 'dog, cat' | |||||
| echo animals | |||||
| // If the condition is true, then show 'contains dog' and 'another instruction' in command line output | |||||
| if animals contains 'dog' | |||||
| echo contains dog | |||||
| echo another instruction | |||||
| // If the condition is true, then show 'some instructions' in the command line output | |||||
| // or else check if the second condition is true, then show 'other instructions' | |||||
| // or else show 'yet other instructions' | |||||
| some_number = 1 | |||||
| if some_number equals to 1 | |||||
| echo some instructions | |||||
| else if some_number equals to 2 | |||||
| echo other instructions | |||||
| else | |||||
| echo yet other instructions | |||||
| // Other examples of comparisons below work as you expect | |||||
| // not equals to | |||||
| // lesser than | |||||
| // greater than or equals to | 
| // This flow demonstrates the usage of loops | |||||
| // Do the instructions within the indentation 3 times | |||||
| // the first time, 'n' has a value of 1, the second time, 'n' is 2, the third time, 'n' is 3 | |||||
| // Visit the URL with a different 'n' value each time | |||||
| // We need to use backticks (`) here like `n` to tell tagui to use the variable 'n' | |||||
| for n from 1 to 3 | |||||
| https://www.ebay.com.sg/b/Consumer-Electronics-Mixed-Lots/259701/bn_7203680?_pgn=`n` | |||||
| // Save the src attribute from the element (ie. the image link) using XPath and call it 'image_link' | |||||
| read (//img[@class="s-item__image-img"])[1]/@src to image_link | |||||
| // Show the 'image_link' value in the command line output | |||||
| echo `image_link` | 
| // This flow demonstrates the use of object repositories, ie. storing values in tagui_local.csv | |||||
| // Visit the web page | |||||
| https://vk.com/kensoh | |||||
| // Look in tagui_local.csv in the flow's folder for a value for 'email' and find that element | |||||
| // if tagui_local.csv doesn't exist, then look in tagui_global.csv in tagui/src folder | |||||
| // and tries the same thing, so when the flow is run, it will become | |||||
| // type quick_email as mickey_mouse@disney.com | |||||
| type `email` as `user_email` | |||||
| type `password` as `user_password` | 
| // This flow demonstrates usage of datatables to run a flow multiple times, once per line in a csv | |||||
| // IMPORTANT: run this sample with 'form_data.csv' behind, | |||||
| // like 'tagui 6_datatables.tag form_data.csv' | |||||
| // TagUI runs this flow once for each data row in 'form_data.csv', | |||||
| // using the variable values in that row. | |||||
| // Visit the web page | |||||
| https://www.w3schools.com/html/html_forms.asp | |||||
| // Clear the input and then type the 'firstname'/'lastname' | |||||
| // from the right row in 'form_data.csv' | |||||
| type firstname as [clear]`firstname` | |||||
| type lastname as [clear]`lastname` | |||||
| click submit | 
| // This flow shows how to interact with webpages which open in a new tab when you visit a link | |||||
| // Visit the web page | |||||
| http://tebel.org | |||||
| // Clicking the ABOUT footer here opens a new tab window | |||||
| click ABOUT | |||||
| // about_tebel appears in the url of the new tab, so "popup about_tebel" tells TagUI | |||||
| // to do this step (ie. look for "file-about_tebel-LC2") within the new tab | |||||
| popup about_tebel | |||||
| show file-about_tebel-LC2 | 
| // This flow demonstrates usage of non-English in flows | |||||
| // To run this, edit tagui/src/tagui_config.txt and | |||||
| // change the line - var tagui_language = 'english'; | |||||
| // to this line - var tagui_language = 'chinese'; | |||||
| // You can find the full list of translated words for each language in | |||||
| // tagui/src/languages folder with the language csv files | |||||
| https://ca.yahoo.com | |||||
| // Set the output language to chinese | |||||
| tagui_language = 'chinese' | |||||
| 输入 search-input 为 github | |||||
| 显示 search-input | |||||
| 点击 search-button | |||||
| 等待 2.5秒 | |||||
| 回声 完毕 | 
| // This flow makes a search on Lazada and saves the top 40 results to a CSV file | |||||
| // visit www.lazada.sg (www.lazada.sg without https:// works as well) | |||||
| https://www.lazada.sg/ | |||||
| // Look on the web page for an element with 'q' in its text, id or name | |||||
| // (or some other attributes), then type 'oat milk' into the textbox | |||||
| type q as oat milk | |||||
| // Click on the search icon (that web element contains the text SEARCH) | |||||
| click SEARCH | |||||
| // Use dump step to create a blank CSV file with just the header | |||||
| dump #,Item,Price,Link to Oat Milk.csv | |||||
| // Use a for loop to repeat for the 40 records on search results | |||||
| for n from 1 to 40 | |||||
| // Read the item description, price and URL link to variables | |||||
| // Learn XPath: https://www.w3schools.com/xml/xpath_intro.asp | |||||
| // XPath Cheatsheet: https://www.linkedin.com/posts/kensoh_xpath-rpa-tagui-activity-6829673864633704448-Iw-D | |||||
| read (//*[@data-qa-locator="product-item"])[`n`]//img/@alt to item | |||||
| read (//*[@data-qa-locator="product-item"])[`n`]//*[contains(text(),"$")] to price | |||||
| read (//*[@data-qa-locator="product-item"])[`n`]//a/@href to partial_link | |||||
| // Add the 'https:' prefix to the incomplete links extracted | |||||
| link = 'https:' + partial_link | |||||
| // Show the values of the current record using echo step | |||||
| echo `n`,`item`,`price`,`link` | |||||
| // Use write step to append current record to CSV file | |||||
| write `csv_row([n, item, price, link])` to Oat Milk.csv | 
| #,firstname,lastname | |||||
| 1,tony,stark | |||||
| 2,bruce,wayne | |||||
| 3,peter,parker | 
| OBJECT,DEFINITION | |||||
| email,quick_email | |||||
| password,quick_pass | |||||
| user_email,mickey_mouse@disney.com | |||||
| user_password,iloveminnie4eva | |||||
| show info,Show full information | |||||
| click link,click `facebook_link` | |||||
| facebook_link,//*[@id="profile_full"]//a | 
| GNU GENERAL PUBLIC LICENSE | |||||
| Version 2, June 1991 | |||||
| Copyright (C) 1989, 1991 Free Software Foundation, Inc., | |||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||||
| Everyone is permitted to copy and distribute verbatim copies | |||||
| of this license document, but changing it is not allowed. | |||||
| Preamble | |||||
| The licenses for most software are designed to take away your | |||||
| freedom to share and change it. By contrast, the GNU General Public | |||||
| License is intended to guarantee your freedom to share and change free | |||||
| software--to make sure the software is free for all its users. This | |||||
| General Public License applies to most of the Free Software | |||||
| Foundation's software and to any other program whose authors commit to | |||||
| using it. (Some other Free Software Foundation software is covered by | |||||
| the GNU Lesser General Public License instead.) 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 | |||||
| this service 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 make restrictions that forbid | |||||
| anyone to deny you these rights or to ask you to surrender the rights. | |||||
| These restrictions translate to certain responsibilities for you if you | |||||
| distribute copies of the software, or if you modify it. | |||||
| For example, if you distribute copies of such a program, whether | |||||
| gratis or for a fee, you must give the recipients all the rights that | |||||
| you have. 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. | |||||
| We protect your rights with two steps: (1) copyright the software, and | |||||
| (2) offer you this license which gives you legal permission to copy, | |||||
| distribute and/or modify the software. | |||||
| Also, for each author's protection and ours, we want to make certain | |||||
| that everyone understands that there is no warranty for this free | |||||
| software. If the software is modified by someone else and passed on, we | |||||
| want its recipients to know that what they have is not the original, so | |||||
| that any problems introduced by others will not reflect on the original | |||||
| authors' reputations. | |||||
| Finally, any free program is threatened constantly by software | |||||
| patents. We wish to avoid the danger that redistributors of a free | |||||
| program will individually obtain patent licenses, in effect making the | |||||
| program proprietary. To prevent this, we have made it clear that any | |||||
| patent must be licensed for everyone's free use or not licensed at all. | |||||
| The precise terms and conditions for copying, distribution and | |||||
| modification follow. | |||||
| GNU GENERAL PUBLIC LICENSE | |||||
| TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |||||
| 0. This License applies to any program or other work which contains | |||||
| a notice placed by the copyright holder saying it may be distributed | |||||
| under the terms of this General Public License. The "Program", below, | |||||
| refers to any such program or work, and a "work based on the Program" | |||||
| means either the Program or any derivative work under copyright law: | |||||
| that is to say, a work containing the Program or a portion of it, | |||||
| either verbatim or with modifications and/or translated into another | |||||
| language. (Hereinafter, translation is included without limitation in | |||||
| the term "modification".) Each licensee is addressed as "you". | |||||
| Activities other than copying, distribution and modification are not | |||||
| covered by this License; they are outside its scope. The act of | |||||
| running the Program is not restricted, and the output from the Program | |||||
| is covered only if its contents constitute a work based on the | |||||
| Program (independent of having been made by running the Program). | |||||
| Whether that is true depends on what the Program does. | |||||
| 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the | |||||
| notices that refer to this License and to the absence of any warranty; | |||||
| and give any other recipients of the Program a copy of this License | |||||
| along with the Program. | |||||
| You may charge a fee for the physical act of transferring a copy, and | |||||
| you may at your option offer warranty protection in exchange for a fee. | |||||
| 2. You may modify your copy or copies of the Program or any portion | |||||
| of it, thus forming a work based on the Program, and copy and | |||||
| distribute such modifications or work under the terms of Section 1 | |||||
| above, provided that you also meet all of these conditions: | |||||
| a) You must cause the modified files to carry prominent notices | |||||
| stating that you changed the files and the date of any change. | |||||
| b) You must cause any work that you distribute or publish, that in | |||||
| whole or in part contains or is derived from the Program or any | |||||
| part thereof, to be licensed as a whole at no charge to all third | |||||
| parties under the terms of this License. | |||||
| c) If the modified program normally reads commands interactively | |||||
| when run, you must cause it, when started running for such | |||||
| interactive use in the most ordinary way, to print or display an | |||||
| announcement including an appropriate copyright notice and a | |||||
| notice that there is no warranty (or else, saying that you provide | |||||
| a warranty) and that users may redistribute the program under | |||||
| these conditions, and telling the user how to view a copy of this | |||||
| License. (Exception: if the Program itself is interactive but | |||||
| does not normally print such an announcement, your work based on | |||||
| the Program is not required to print an announcement.) | |||||
| These requirements apply to the modified work as a whole. If | |||||
| identifiable sections of that work are not derived from the Program, | |||||
| and can be reasonably considered independent and separate works in | |||||
| themselves, then this License, and its terms, do not apply to those | |||||
| sections when you distribute them as separate works. But when you | |||||
| distribute the same sections as part of a whole which is a work based | |||||
| on the Program, the distribution of the whole must be on the terms of | |||||
| this License, whose permissions for other licensees extend to the | |||||
| entire whole, and thus to each and every part regardless of who wrote it. | |||||
| Thus, it is not the intent of this section to claim rights or contest | |||||
| your rights to work written entirely by you; rather, the intent is to | |||||
| exercise the right to control the distribution of derivative or | |||||
| collective works based on the Program. | |||||
| In addition, mere aggregation of another work not based on the Program | |||||
| with the Program (or with a work based on the Program) on a volume of | |||||
| a storage or distribution medium does not bring the other work under | |||||
| the scope of this License. | |||||
| 3. You may copy and distribute the Program (or a work based on it, | |||||
| under Section 2) in object code or executable form under the terms of | |||||
| Sections 1 and 2 above provided that you also do one of the following: | |||||
| a) Accompany it with the complete corresponding machine-readable | |||||
| source code, which must be distributed under the terms of Sections | |||||
| 1 and 2 above on a medium customarily used for software interchange; or, | |||||
| b) Accompany it with a written offer, valid for at least three | |||||
| years, to give any third party, for a charge no more than your | |||||
| cost of physically performing source distribution, a complete | |||||
| machine-readable copy of the corresponding source code, to be | |||||
| distributed under the terms of Sections 1 and 2 above on a medium | |||||
| customarily used for software interchange; or, | |||||
| c) Accompany it with the information you received as to the offer | |||||
| to distribute corresponding source code. (This alternative is | |||||
| allowed only for noncommercial distribution and only if you | |||||
| received the program in object code or executable form with such | |||||
| an offer, in accord with Subsection b above.) | |||||
| The source code for a work means the preferred form of the work for | |||||
| making modifications to it. For an executable work, complete source | |||||
| code means all the source code for all modules it contains, plus any | |||||
| associated interface definition files, plus the scripts used to | |||||
| control compilation and installation of the executable. However, as a | |||||
| special exception, the source code distributed need not include | |||||
| anything that is normally distributed (in either source or binary | |||||
| form) with the major components (compiler, kernel, and so on) of the | |||||
| operating system on which the executable runs, unless that component | |||||
| itself accompanies the executable. | |||||
| If distribution of executable or object code is made by offering | |||||
| access to copy from a designated place, then offering equivalent | |||||
| access to copy the source code from the same place counts as | |||||
| distribution of the source code, even though third parties are not | |||||
| compelled to copy the source along with the object code. | |||||
| 4. You may not copy, modify, sublicense, or distribute the Program | |||||
| except as expressly provided under this License. Any attempt | |||||
| otherwise to copy, modify, sublicense or distribute the Program is | |||||
| void, and will automatically terminate your rights under this License. | |||||
| However, parties who have received copies, or rights, from you under | |||||
| this License will not have their licenses terminated so long as such | |||||
| parties remain in full compliance. | |||||
| 5. You are not required to accept this License, since you have not | |||||
| signed it. However, nothing else grants you permission to modify or | |||||
| distribute the Program or its derivative works. These actions are | |||||
| prohibited by law if you do not accept this License. Therefore, by | |||||
| modifying or distributing the Program (or any work based on the | |||||
| Program), you indicate your acceptance of this License to do so, and | |||||
| all its terms and conditions for copying, distributing or modifying | |||||
| the Program or works based on it. | |||||
| 6. Each time you redistribute the Program (or any work based on the | |||||
| Program), the recipient automatically receives a license from the | |||||
| original licensor to copy, distribute or modify the Program subject to | |||||
| these terms and conditions. You may not impose any further | |||||
| restrictions on the recipients' exercise of the rights granted herein. | |||||
| You are not responsible for enforcing compliance by third parties to | |||||
| this License. | |||||
| 7. If, as a consequence of a court judgment or allegation of patent | |||||
| infringement or for any other reason (not limited to patent issues), | |||||
| 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 | |||||
| distribute so as to satisfy simultaneously your obligations under this | |||||
| License and any other pertinent obligations, then as a consequence you | |||||
| may not distribute the Program at all. For example, if a patent | |||||
| license would not permit royalty-free redistribution of the Program by | |||||
| all those who receive copies directly or indirectly through you, then | |||||
| the only way you could satisfy both it and this License would be to | |||||
| refrain entirely from distribution of the Program. | |||||
| If any portion of this section is held invalid or unenforceable under | |||||
| any particular circumstance, the balance of the section is intended to | |||||
| apply and the section as a whole is intended to apply in other | |||||
| circumstances. | |||||
| It is not the purpose of this section to induce you to infringe any | |||||
| patents or other property right claims or to contest validity of any | |||||
| such claims; this section has the sole purpose of protecting the | |||||
| integrity of the free software distribution system, which is | |||||
| implemented by public license practices. Many people have made | |||||
| generous contributions to the wide range of software distributed | |||||
| through that system in reliance on consistent application of that | |||||
| system; it is up to the author/donor to decide if he or she is willing | |||||
| to distribute software through any other system and a licensee cannot | |||||
| impose that choice. | |||||
| This section is intended to make thoroughly clear what is believed to | |||||
| be a consequence of the rest of this License. | |||||
| 8. If the distribution and/or use of the Program is restricted in | |||||
| certain countries either by patents or by copyrighted interfaces, the | |||||
| original copyright holder who places the Program under this License | |||||
| may add an explicit geographical distribution limitation excluding | |||||
| those countries, so that distribution is permitted only in or among | |||||
| countries not thus excluded. In such case, this License incorporates | |||||
| the limitation as if written in the body of this License. | |||||
| 9. The Free Software Foundation may publish revised and/or new versions | |||||
| of the 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 a version number of this License which applies to it and "any | |||||
| later version", you have the option of following the terms and conditions | |||||
| either of that version or of any later version published by the Free | |||||
| Software Foundation. If the Program does not specify a version number of | |||||
| this License, you may choose any version ever published by the Free Software | |||||
| Foundation. | |||||
| 10. If you wish to incorporate parts of the Program into other free | |||||
| programs whose distribution conditions are different, write to the author | |||||
| to ask for permission. For software which is copyrighted by the Free | |||||
| Software Foundation, write to the Free Software Foundation; we sometimes | |||||
| make exceptions for this. Our decision will be guided by the two goals | |||||
| of preserving the free status of all derivatives of our free software and | |||||
| of promoting the sharing and reuse of software generally. | |||||
| NO WARRANTY | |||||
| 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. | |||||
| 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |||||
| WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | |||||
| REDISTRIBUTE 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. | |||||
| 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 | |||||
| convey the exclusion of warranty; and each file should have at least | |||||
| the "copyright" line and a pointer to where the full notice is found. | |||||
| <one line to give the program's name and a brief idea of what it does.> | |||||
| Copyright (C) <year> <name of author> | |||||
| 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 2 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, write to the Free Software Foundation, Inc., | |||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |||||
| Also add information on how to contact you by electronic and paper mail. | |||||
| If the program is interactive, make it output a short notice like this | |||||
| when it starts in an interactive mode: | |||||
| Gnomovision version 69, Copyright (C) year name of author | |||||
| Gnomovision 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, the commands you use may | |||||
| be called something other than `show w' and `show c'; they could even be | |||||
| mouse-clicks or menu items--whatever suits your program. | |||||
| You should also get your employer (if you work as a programmer) or your | |||||
| school, if any, to sign a "copyright disclaimer" for the program, if | |||||
| necessary. Here is a sample; alter the names: | |||||
| Yoyodyne, Inc., hereby disclaims all copyright interest in the program | |||||
| `Gnomovision' (which makes passes at compilers) written by James Hacker. | |||||
| <signature of Ty Coon>, 1 April 1989 | |||||
| Ty Coon, President of Vice | |||||
| This 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. | 
| var testcase_items = new Array(); | |||||
| var active = false; | |||||
| var empty = true; | |||||
| var tab_id = null; | |||||
| console.log('init'); | |||||
| chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { | |||||
| console.log(request); | |||||
| if (request.action == "append") { | |||||
| testcase_items[testcase_items.length] = request.obj; | |||||
| empty = false; | |||||
| sendResponse({}); | |||||
| } | |||||
| if (request.action == "poke") { | |||||
| testcase_items[testcase_items.length - 1] = request.obj; | |||||
| sendResponse({}); | |||||
| } | |||||
| if (request.action == "get_status") { | |||||
| sendResponse({'active': active, 'empty': empty}); | |||||
| } | |||||
| if (request.action == "start") { | |||||
| if(!active) { | |||||
| active = true; | |||||
| empty = true; | |||||
| testcase_items = new Array(); | |||||
| tab_id = request.recorded_tab; | |||||
| chrome.tabs.update(tab_id, {url: request.start_url}, function(tab) { | |||||
| alert("\n▹ click OK to start recording your actions\n▹ right-click for shortcuts to TagUI steps\n"); | |||||
| chrome.tabs.sendMessage(tab_id, {action: "open", 'url': request.start_url}); | |||||
| sendResponse({start: true}); | |||||
| }); | |||||
| } | |||||
| } | |||||
| if (request.action == "stop") { | |||||
| active = false; | |||||
| chrome.tabs.sendMessage(tab_id, {action: "stop"}); | |||||
| sendResponse({}); | |||||
| } | |||||
| if (request.action == "get_items") { | |||||
| sendResponse({'items': testcase_items}); | |||||
| } | |||||
| }); | 
| <html> | |||||
| <head> | |||||
| <title>TagUI Web Automation</title> | |||||
| <link rel="stylesheet" type="text/css" href="./style.css" /> | |||||
| <script src="control.js"></script> | |||||
| </head> | |||||
| <body> | |||||
| <form name="control"> | |||||
| <div align="center"> | |||||
| <input type="text" size="51" name="url" /><p></p> | |||||
| <input type="submit" id="bgo" name="submit" value=" START " /> | |||||
| <input type="submit" id="bstop" name="bstop" value=" STOP " style="display:none;" /> | |||||
| <input type="submit" id="bexport" name="bexport" value=" EXPORT " style="display: none;" /> | |||||
| </div> | |||||
| </form> | |||||
| <!-- | |||||
| <p class="tagline" align="center"> | |||||
| <span id="tagline">Create </span><a href="https://github.com/kelaberetiv/TagUI" target="_new">TagUI automation flows</a> | |||||
| <span id="tagline"> by recording your actions</span> | |||||
| </p> | |||||
| --> | |||||
| </body> | |||||
| </html> | 
| //----------------------------------------------- | |||||
| // Proxy to access current tab recorder instance | |||||
| // ---------------------------------------------- | |||||
| function RecorderProxy() { | |||||
| this.active = null; | |||||
| } | |||||
| RecorderProxy.prototype.start = function(url) { | |||||
| chrome.tabs.getSelected(null, function(tab) { | |||||
| chrome.runtime.sendMessage({action: "start", recorded_tab: tab.id, start_url: url}); | |||||
| }); | |||||
| } | |||||
| RecorderProxy.prototype.stop = function() { | |||||
| chrome.runtime.sendMessage({action: "stop"}); | |||||
| } | |||||
| RecorderProxy.prototype.open = function(url, callback) { | |||||
| chrome.tabs.getSelected(null, function(tab) { | |||||
| chrome.tabs.sendMessage(tab.id, {action: "open", 'url': url}, callback); | |||||
| }); | |||||
| } | |||||
| //----------------------------------------------- | |||||
| // UI | |||||
| //---------------------------------------------- | |||||
| function RecorderUI() { | |||||
| this.recorder = new RecorderProxy(); | |||||
| chrome.runtime.sendMessage({action: "get_status"}, function(response) { | |||||
| if (response.active) { | |||||
| ui.set_started(); | |||||
| } else { | |||||
| if (!response.empty) { | |||||
| ui.set_stopped(); | |||||
| } | |||||
| chrome.tabs.getSelected(null, function(tab) { | |||||
| document.forms[0].elements["url"].value = tab.url; | |||||
| }); | |||||
| } | |||||
| }); | |||||
| } | |||||
| RecorderUI.prototype.start = function() { | |||||
| var url = document.forms[0].elements["url"].value; | |||||
| if (url == "") { | |||||
| return false; | |||||
| } | |||||
| if ( (url.indexOf("http://") == -1) && (url.indexOf("https://")) ) { | |||||
| url = "http://" + url; | |||||
| } | |||||
| ui.set_started() | |||||
| ui.recorder.start(url); | |||||
| return false; | |||||
| } | |||||
| RecorderUI.prototype.set_started = function() { | |||||
| var e = document.getElementById("bstop"); | |||||
| e.style.display = ''; | |||||
| e.onclick = ui.stop; | |||||
| e = document.getElementById("bgo"); | |||||
| e.style.display = 'none'; | |||||
| e = document.getElementById("bexport"); | |||||
| e.style.display = 'none'; | |||||
| } | |||||
| RecorderUI.prototype.stop = function() { | |||||
| ui.set_stopped(); | |||||
| ui.recorder.stop(); | |||||
| return false; | |||||
| } | |||||
| RecorderUI.prototype.set_stopped = function() { | |||||
| var e = document.getElementById("bstop"); | |||||
| e.style.display = 'none'; | |||||
| e = document.getElementById("bgo"); | |||||
| e.style.display = ''; | |||||
| e = document.getElementById("bexport"); | |||||
| e.style.display = ''; | |||||
| } | |||||
| RecorderUI.prototype.export = function(options) { | |||||
| chrome.tabs.create({url: "./tagui.html"}); | |||||
| } | |||||
| var ui; | |||||
| // bind events to ui elements | |||||
| window.onload = function(){ | |||||
| document.querySelector('input#bgo').onclick=function() {ui.start(); return false;}; | |||||
| document.querySelector('input#bstop').onclick=function() {ui.stop(); return false;}; | |||||
| document.querySelector('input#bexport').onclick=function() {ui.export(); return false;}; | |||||
| ui = new RecorderUI(); | |||||
| } | 
| { | |||||
| "manifest_version": 2, | |||||
| "name": "TagUI RPA Web Recorder", "short_name": "TagUI RPA", "version": "5.11.0", | |||||
| "description": "Create TagUI automation flows by recording your actions", | |||||
| "homepage_url": "https://github.com/kelaberetiv/TagUI", | |||||
| "browser_action": { | |||||
| "default_title": "TagUI RPA Web Recorder", | |||||
| "default_popup": "control.html", | |||||
| "default_icon": { | |||||
| "16": "tagui_icon_16.png" | |||||
| } | |||||
| }, | |||||
| "icons": { | |||||
| "16": "tagui_icon_16.png", | |||||
| "48": "tagui_icon_48.png", | |||||
| "128": "tagui_icon_128.png" | |||||
| }, | |||||
| "permissions": [ | |||||
| "tabs", | |||||
| "background", | |||||
| "http://*/*", | |||||
| "https://*/*" | |||||
| ], | |||||
| "background": { | |||||
| "scripts": ["background.js"] | |||||
| }, | |||||
| "content_scripts": [{ | |||||
| "matches": ["http://*/*", "https://*/*"], | |||||
| "js": ["recorder.js"] | |||||
| }], | |||||
| "offline_enabled": false, | |||||
| "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'" | |||||
| } | 
| body { | |||||
| font-family: sans-serif; | |||||
| font-size: 100%; | |||||
| text-decoration: none; | |||||
| color: black; | |||||
| background: #FFFFFF; | |||||
| width: auto; | |||||
| margin: auto; | |||||
| } | |||||
| .tagline { | |||||
| color: black; | |||||
| } | |||||
| input[type=submit], input[type=button] { | |||||
| border: 3px solid #1E82C9; | |||||
| color: #1E82C9; | |||||
| padding: 1em 1em; | |||||
| background: #FFFFFF; | |||||
| font-size: 1em; | |||||
| font-weight: bold; | |||||
| border-radius: 0em; | |||||
| -webkit-border-radius: 0em; | |||||
| -moz-border-radius: 0em; | |||||
| -ms-border-radius: 0em; | |||||
| -o-border-radius: 0em; | |||||
| cursor: pointer; | |||||
| } | 
| <html> | |||||
| <head> | |||||
| <title>TagUI Renderer</title> | |||||
| <script src="tagui.js"></script> | |||||
| </head> | |||||
| <body></body> | |||||
| </html> | 
| // -------------------------------------------------------------------------------- | |||||
| // CasperRenderer - class to render recorded steps to TagUI automation flow format | |||||
| // -------------------------------------------------------------------------------- | |||||
| if (typeof(EventTypes) == "undefined") { | |||||
| EventTypes = {}; | |||||
| } | |||||
| EventTypes.OpenUrl = 0; | |||||
| EventTypes.Click = 1; | |||||
| EventTypes.Change = 2; | |||||
| EventTypes.Comment = 3; | |||||
| EventTypes.Submit = 4; | |||||
| EventTypes.CheckPageTitle = 5; | |||||
| EventTypes.CheckPageLocation = 6; | |||||
| EventTypes.CheckTextPresent = 7; | |||||
| EventTypes.CheckValue = 8; | |||||
| EventTypes.CheckValueContains = 9; | |||||
| EventTypes.CheckText = 10; | |||||
| EventTypes.CheckHref = 11; | |||||
| EventTypes.CheckEnabled = 12; | |||||
| EventTypes.CheckDisabled = 13; | |||||
| EventTypes.CheckSelectValue = 14; | |||||
| EventTypes.CheckSelectOptions = 15; | |||||
| EventTypes.CheckImageSrc = 16; | |||||
| EventTypes.PageLoad = 17; | |||||
| EventTypes.ScreenShot = 18; | |||||
| EventTypes.ElementScreenShot = 24; | |||||
| EventTypes.MoveCursorToElement = 25; | |||||
| EventTypes.PrintElementText = 26; | |||||
| EventTypes.SaveElementText = 27; | |||||
| EventTypes.ExplicitWait = 28; | |||||
| EventTypes.FetchElementText = 29; | |||||
| EventTypes.SelectElementOption = 30; | |||||
| EventTypes.CancelLastStep = 31; | |||||
| EventTypes.NoteDownElement = 32; | |||||
| EventTypes.InspectElement = 33; | |||||
| EventTypes.Cancel = 99; | |||||
| EventTypes.MouseDown = 19; | |||||
| EventTypes.MouseUp = 20; | |||||
| EventTypes.MouseDrag = 21; | |||||
| EventTypes.MouseDrop = 22; | |||||
| EventTypes.KeyPress = 23; | |||||
| function CasperRenderer(document) { | |||||
| this.document = document; | |||||
| this.title = "Automation Flow"; | |||||
| this.items = null; | |||||
| this.history = new Array(); | |||||
| this.last_events = new Array(); | |||||
| } | |||||
| CasperRenderer.prototype.text = function(text) { | |||||
| this.document.writeln(text); | |||||
| } | |||||
| CasperRenderer.prototype.stmt = function(text, indent) { | |||||
| if(indent==undefined) indent = 0; | |||||
| var output = (new Array(4*indent)).join(" ") + text; | |||||
| this.document.writeln(output); | |||||
| } | |||||
| CasperRenderer.prototype.pyrepr = function(text, escape) { | |||||
| var s = text; | |||||
| if (escape) s = s.replace(/(['"])/g, "\\$1"); | |||||
| return s; | |||||
| } | |||||
| CasperRenderer.prototype.space = function() { | |||||
| this.document.write("\n"); | |||||
| } | |||||
| CasperRenderer.prototype.regexp_escape = function(text) { | |||||
| return text.replace(/[-[\]{}()*+?.,\\^$|#\s\/]/g, "\\$&"); | |||||
| }; | |||||
| CasperRenderer.prototype.cleanStringForXpath = function(str, escape) { | |||||
| var parts = str.match(/[^'"]+|['"]/g); | |||||
| parts = parts.map(function(part){ | |||||
| if (part === "'") { | |||||
| return '"\'"'; | |||||
| } | |||||
| if (part === '"') { | |||||
| return "'\"'"; | |||||
| } | |||||
| return part; | |||||
| }); | |||||
| var xpath = ''; | |||||
| if(parts.length>1) { | |||||
| xpath = "concat(" + parts.join(",") + ")"; | |||||
| } else { | |||||
| xpath = parts[0]; | |||||
| } | |||||
| if(escape) xpath = xpath.replace(/(["])/g, "\\$1"); | |||||
| return xpath; | |||||
| } | |||||
| var d = {}; | |||||
| d[EventTypes.OpenUrl] = "openUrl"; | |||||
| d[EventTypes.Click] = "click"; | |||||
| //d[EventTypes.Change] = "change"; | |||||
| d[EventTypes.Comment] = "comment"; | |||||
| d[EventTypes.Submit] = "submit"; | |||||
| d[EventTypes.CheckPageTitle] = "checkPageTitle"; | |||||
| d[EventTypes.CheckPageLocation] = "checkPageLocation"; | |||||
| d[EventTypes.CheckTextPresent] = "checkTextPresent"; | |||||
| d[EventTypes.CheckValue] = "checkValue"; | |||||
| d[EventTypes.CheckText] = "checkText"; | |||||
| d[EventTypes.CheckHref] = "checkHref"; | |||||
| d[EventTypes.CheckEnabled] = "checkEnabled"; | |||||
| d[EventTypes.CheckDisabled] = "checkDisabled"; | |||||
| d[EventTypes.CheckSelectValue] = "checkSelectValue"; | |||||
| d[EventTypes.CheckSelectOptions] = "checkSelectOptions"; | |||||
| d[EventTypes.CheckImageSrc] = "checkImageSrc"; | |||||
| d[EventTypes.PageLoad] = "pageLoad"; | |||||
| d[EventTypes.ScreenShot] = "screenShot"; | |||||
| d[EventTypes.ElementScreenShot] = "elementScreenShot"; | |||||
| d[EventTypes.NoteDownElement] = "noteDownElement"; | |||||
| d[EventTypes.InspectElement] = "inspectElement"; | |||||
| d[EventTypes.MoveCursorToElement] = "moveCursorToElement"; | |||||
| d[EventTypes.PrintElementText] = "printElementText"; | |||||
| d[EventTypes.SaveElementText] = "saveElementText"; | |||||
| d[EventTypes.FetchElementText] = "fetchElementText"; | |||||
| d[EventTypes.SelectElementOption] = "selectElementOption"; | |||||
| d[EventTypes.ExplicitWait] = "explicitWait"; | |||||
| d[EventTypes.CancelLastStep] = "cancelLastStep"; | |||||
| d[EventTypes.Cancel] = "cancel"; | |||||
| //d[EventTypes.MouseDown] = "mousedown"; | |||||
| //d[EventTypes.MouseUp] = "mouseup"; | |||||
| d[EventTypes.MouseDrag] = "mousedrag"; | |||||
| d[EventTypes.KeyPress] = "keypress"; | |||||
| CasperRenderer.prototype.dispatch = d; | |||||
| var cc = EventTypes; | |||||
| CasperRenderer.prototype.render = function(with_xy) { | |||||
| this.with_xy = with_xy; | |||||
| var etypes = EventTypes; | |||||
| this.document.open(); | |||||
| this.document.write("<" + "pre" + ">"); | |||||
| this.document.write("<span style=\"font-size: 18px\">"); | |||||
| var last_down = null; | |||||
| var forget_click = false; | |||||
| for (var i=0; i < this.items.length; i++) { | |||||
| var item = this.items[i]; | |||||
| if(i==0) { | |||||
| if(item.type!=etypes.OpenUrl) { | |||||
| this.text("ERROR - steps did not start with opening an url"); | |||||
| } | |||||
| else { | |||||
| this.startUrl(item); | |||||
| continue; | |||||
| } | |||||
| } | |||||
| // remember last MouseDown to identify drag | |||||
| if(item.type==etypes.MouseDown) { | |||||
| last_down = this.items[i]; | |||||
| continue; | |||||
| } | |||||
| if(item.type==etypes.MouseUp && last_down) { | |||||
| if(last_down.x == item.x && last_down.y == item.y) { | |||||
| forget_click = false; | |||||
| continue; | |||||
| } | |||||
| else { | |||||
| item.before = last_down; | |||||
| this[this.dispatch[etypes.MouseDrag]](item); | |||||
| last_down = null; | |||||
| forget_click = true; | |||||
| continue; | |||||
| } | |||||
| } | |||||
| if(item.type==etypes.Click && forget_click) { | |||||
| forget_click = false; | |||||
| continue; | |||||
| } | |||||
| // ignore click due to clicking on right-click menu | |||||
| if(i>0 && item.type==etypes.Click && | |||||
| ((this.items[i-1].type>=5 && this.items[i-1].type<=16) || | |||||
| (this.items[i-1].type==18 || this.items[i-1].type>=24))) | |||||
| { | |||||
| continue; | |||||
| } | |||||
| if (this.dispatch[item.type]) { | |||||
| this[this.dispatch[item.type]](item); | |||||
| } | |||||
| } | |||||
| this.document.write("<" + "/" + "span" + ">"); | |||||
| this.document.write("<" + "/" + "pre" + ">"); | |||||
| this.document.close(); | |||||
| } | |||||
| CasperRenderer.prototype.rewriteUrl = function(url) { | |||||
| return url; | |||||
| } | |||||
| CasperRenderer.prototype.shortUrl = function(url) { | |||||
| return url.substr(url.indexOf('/', 10), 999999999); | |||||
| } | |||||
| CasperRenderer.prototype.startUrl = function(item) { | |||||
| var url = this.pyrepr(this.rewriteUrl(item.url)); | |||||
| this.stmt(url); | |||||
| } | |||||
| CasperRenderer.prototype.openUrl = function(item) { | |||||
| var url = this.pyrepr(this.rewriteUrl(item.url)); | |||||
| var history = this.history; | |||||
| // if the user apparently hit the back button, render the event as such | |||||
| if (url == history[history.length - 2]) { | |||||
| this.stmt('this.back();'); | |||||
| history.pop(); | |||||
| history.pop(); | |||||
| } else { | |||||
| this.stmt(url); | |||||
| } | |||||
| } | |||||
| CasperRenderer.prototype.pageLoad = function(item) { | |||||
| var url = this.pyrepr(this.rewriteUrl(item.url)); | |||||
| this.history.push(url); | |||||
| } | |||||
| CasperRenderer.prototype.normalizeWhitespace = function(s) { | |||||
| return s.replace(/^\s*/, '').replace(/\s*$/, '').replace(/\s+/g, ' '); | |||||
| } | |||||
| //CasperRenderer.prototype.getControlXPath = function(item) { | |||||
| // var type = item.info.type; | |||||
| // var way; | |||||
| // if ((type == "submit" || type == "button") && item.info.value) | |||||
| // // way = '@value=' + this.pyrepr(this.normalizeWhitespace(item.info.value)); | |||||
| // way = this.pyrepr(this.normalizeWhitespace(item.info.value)); | |||||
| // else if (item.info.name) | |||||
| // // way = '@name=' + this.pyrepr(item.info.name); | |||||
| // way = this.pyrepr(item.info.name); | |||||
| // else if (item.info.id) | |||||
| // // way = '@id=' + this.pyrepr(item.info.id); | |||||
| // way = this.pyrepr(item.info.id) | |||||
| //// else | |||||
| //// way = 'TODO'; | |||||
| // | |||||
| // return way; | |||||
| //} | |||||
| CasperRenderer.prototype.getControl = function(item) { | |||||
| return item.info.selector; // default identifiers to css for accuracy, to optimize later | |||||
| var type = item.info.type; | |||||
| var tag = item.info.tagName.toLowerCase(); | |||||
| var selector; | |||||
| if (item.info.id) | |||||
| // selector = tag+'#'+item.info.id; | |||||
| selector = this.pyrepr(item.info.id); | |||||
| else if ((type == "submit" || type == "button") && item.info.value) | |||||
| { | |||||
| // selector = tag+'[type='+type+'][value='+this.pyrepr(this.normalizeWhitespace(item.info.value))+']'; | |||||
| if (item.info.name) | |||||
| selector = '//*[@value="' + this.pyrepr(item.info.value) + '" or @name="' + this.pyrepr(item.info.name) + '"]'; | |||||
| else | |||||
| selector = '//*[@value="' + this.pyrepr(item.info.value) + '"]'; | |||||
| } | |||||
| else if (item.info.name) | |||||
| // selector = tag+'[name='+this.pyrepr(item.info.name)+']'; | |||||
| selector = this.pyrepr(item.info.name); | |||||
| // else if (item.info.className) | |||||
| // // selector = tag+'#'+item.info.className; | |||||
| // selector = this.pyrepr(item.info.className); | |||||
| else | |||||
| selector = item.info.selector; | |||||
| return selector; | |||||
| } | |||||
| CasperRenderer.prototype.getLinkXPath = function(item) { | |||||
| var way; | |||||
| if (item.info.id) | |||||
| way = '@id=' + '"' + this.pyrepr(item.info.id) + '"'; | |||||
| // else if (item.info.title) | |||||
| // way = '@title=' + '"' + this.pyrepr(item.info.title) + '"'; | |||||
| else if (item.text) | |||||
| { | |||||
| if (item.text.indexOf('[whitespace]')==-1) // return normally if not beginning / ending whitespace | |||||
| way = 'text()=' + '"' + this.cleanStringForXpath(item.text, true) + '"'; | |||||
| else // otherwise return using contains keyword in order to match the element via text comparison | |||||
| way = 'contains(text(),' + '"' + this.cleanStringForXpath(item.text.replace(/\[whitespace\]/g,''), true) + '")'; | |||||
| if (item.info.href) | |||||
| way += ' or contains("' + this.pyrepr(item.info.href) + '",@href)'; | |||||
| } | |||||
| else if (item.info.href) | |||||
| way = 'contains("' + this.pyrepr(item.info.href) + '",@href)'; | |||||
| return way; | |||||
| } | |||||
| CasperRenderer.prototype.click = function(item) { | |||||
| var tag = item.info.tagName.toLowerCase(); | |||||
| if(this.with_xy && !(tag == 'a' || tag == 'input' || tag == 'button')) { | |||||
| this.stmt('this.mouse.click('+ item.x + ', '+ item.y +');'); | |||||
| } | |||||
| else { | |||||
| var selector; | |||||
| if (tag == 'a') { | |||||
| var xpath_selector = this.getLinkXPath(item); | |||||
| if(xpath_selector) { | |||||
| selector = '//a['+xpath_selector+']'; | |||||
| } | |||||
| else { | |||||
| selector = item.info.selector; | |||||
| } | |||||
| } | |||||
| else if (tag == 'input' || tag == 'button') { | |||||
| // selector = this.getFormSelector(item) + this.getControl(item); | |||||
| selector = this.getControl(item); | |||||
| } | |||||
| else { | |||||
| selector = item.info.selector; | |||||
| } | |||||
| if (selector.charAt(0) == '#') {selector = selector.substring(1);} | |||||
| this.stmt('click ' + selector); | |||||
| } | |||||
| } | |||||
| CasperRenderer.prototype.getFormSelector = function(item) { | |||||
| var info = item.info; | |||||
| if(!info.form) { | |||||
| return ''; | |||||
| } | |||||
| if(info.form.name) { | |||||
| return "form[name=" + info.form.name + "] "; | |||||
| } | |||||
| else if(info.form.id) { | |||||
| return "form#" + info.form.id + " "; | |||||
| } | |||||
| else { | |||||
| return "form "; | |||||
| } | |||||
| } | |||||
| CasperRenderer.prototype.mousedrag = function(item) { | |||||
| if(this.with_xy) { | |||||
| this.stmt('this.mouse.down('+ item.before.x + ', '+ item.before.y +');'); | |||||
| this.stmt('this.mouse.move('+ item.x + ', '+ item.y +');'); | |||||
| this.stmt('this.mouse.up('+ item.x + ', '+ item.y +');'); | |||||
| } | |||||
| } | |||||
| CasperRenderer.prototype.keypress = function(item) { | |||||
| // var text = item.text.replace('\n','').replace('\r', '\\r'); | |||||
| // change above to [enter] to handle typing of enter key | |||||
| var text = item.text.replace(/\r\n/g,'[enter]').replace(/\r/g, '[enter]').replace(/\n/g, '[enter]'); | |||||
| var selector; selector = this.getControl(item); | |||||
| if (selector.charAt(0) == '#') {selector = selector.substring(1);} | |||||
| this.stmt('type ' + selector + ' as ' + text); | |||||
| } | |||||
| CasperRenderer.prototype.submit = function(item) { | |||||
| // the submit has been called somehow (user, script) so no need to trigger it | |||||
| } | |||||
| CasperRenderer.prototype.screenShot = function(item) { | |||||
| this.stmt('snap page'); | |||||
| } | |||||
| CasperRenderer.prototype.elementScreenShot = function(item) { | |||||
| var selector; selector = this.getControl(item); | |||||
| if (selector.charAt(0) == '#') {selector = selector.substring(1);} | |||||
| this.stmt('snap ' + selector); | |||||
| } | |||||
| CasperRenderer.prototype.inspectElement = function(item) { | |||||
| } | |||||
| CasperRenderer.prototype.noteDownElement = function(item) { | |||||
| var selector; selector = this.getControl(item); | |||||
| if (selector.charAt(0) == '#') {selector = selector.substring(1);} | |||||
| this.stmt('// element is ' + selector); | |||||
| } | |||||
| CasperRenderer.prototype.moveCursorToElement = function(item) { | |||||
| var selector; selector = this.getControl(item); | |||||
| if (selector.charAt(0) == '#') {selector = selector.substring(1);} | |||||
| this.stmt('hover ' + selector); | |||||
| } | |||||
| CasperRenderer.prototype.fetchElementText = function(item) { | |||||
| var selector; selector = this.getControl(item); | |||||
| if (selector.charAt(0) == '#') {selector = selector.substring(1);} | |||||
| this.stmt('read ' + selector + ' to variable'); | |||||
| } | |||||
| CasperRenderer.prototype.selectElementOption = function(item) { | |||||
| var selector; selector = this.getControl(item); var value = this.pyrepr(item.info.value); | |||||
| if (selector.charAt(0) == '#') {selector = selector.substring(1);} | |||||
| this.stmt('select ' + selector + ' as ' + value); | |||||
| } | |||||
| CasperRenderer.prototype.cancelLastStep = function(item) { | |||||
| this.stmt('cancel the last step'); | |||||
| } | |||||
| CasperRenderer.prototype.printElementText = function(item) { | |||||
| var selector; selector = this.getControl(item); | |||||
| if (selector.charAt(0) == '#') {selector = selector.substring(1);} | |||||
| this.stmt('show ' + selector); | |||||
| } | |||||
| CasperRenderer.prototype.saveElementText = function(item) { | |||||
| var selector; selector = this.getControl(item); | |||||
| if (selector.charAt(0) == '#') {selector = selector.substring(1);} | |||||
| this.stmt('save ' + selector); | |||||
| } | |||||
| CasperRenderer.prototype.explicitWait = function(item) { | |||||
| this.stmt('wait'); | |||||
| } | |||||
| CasperRenderer.prototype.cancel = function(item) { | |||||
| } | |||||
| CasperRenderer.prototype.checkPageTitle = function(item) { | |||||
| // var title = this.pyrepr(item.title, true); | |||||
| // this.stmt('casper.then(function() {'); | |||||
| // this.stmt(' test.assertTitle('+ title +');'); | |||||
| // this.stmt('});'); | |||||
| } | |||||
| CasperRenderer.prototype.checkPageLocation = function(item) { | |||||
| // var url = this.regexp_escape(item.url); | |||||
| // this.stmt('casper.then(function() {'); | |||||
| // this.stmt(' test.assertUrlMatch(/^'+ url +'$/);'); | |||||
| // this.stmt('});'); | |||||
| } | |||||
| CasperRenderer.prototype.checkTextPresent = function(item) { | |||||
| // var selector = 'x("//*[contains(text(), '+this.pyrepr(item.text, true)+')]")'; | |||||
| // this.waitAndTestSelector(selector); | |||||
| } | |||||
| CasperRenderer.prototype.checkValue = function(item) { | |||||
| // var type = item.info.type; | |||||
| // var way = this.getControlXPath(item); | |||||
| // var selector = ''; | |||||
| // if (type == 'checkbox' || type == 'radio') { | |||||
| // var selected; | |||||
| // if (item.info.checked) | |||||
| // selected = '@checked' | |||||
| // else | |||||
| // selected = 'not(@checked)' | |||||
| // selector = 'x("//input[' + way + ' and ' +selected+ ']")'; | |||||
| // } | |||||
| // else { | |||||
| // var value = this.pyrepr(item.info.value) | |||||
| // var tag = item.info.tagName.toLowerCase(); | |||||
| // selector = 'x("//'+tag+'[' + way + ' and @value='+value+']")'; | |||||
| // } | |||||
| // this.waitAndTestSelector(selector); | |||||
| } | |||||
| CasperRenderer.prototype.checkText = function(item) { | |||||
| // var selector = ''; | |||||
| // if ((item.info.type == "submit") || (item.info.type == "button")) { | |||||
| // selector = 'x("//input[@value='+this.pyrepr(item.text, true)+']")'; | |||||
| // } else { | |||||
| // selector = 'x("//*[normalize-space(text())='+this.cleanStringForXpath(item.text, true)+']")'; | |||||
| // } | |||||
| // this.waitAndTestSelector(selector); | |||||
| } | |||||
| CasperRenderer.prototype.checkHref = function(item) { | |||||
| // var href = this.pyrepr(this.shortUrl(item.info.href)); var xpath_selector = this.getLinkXPath(item); | |||||
| // if(xpath_selector) { | |||||
| // selector = '//a['+xpath_selector+' and @href='+ href +']'; | |||||
| // } else { | |||||
| // selector = item.info.selector+'[href='+ href +']'; | |||||
| // } | |||||
| // this.stmt('casper.then(function() {'); | |||||
| // this.stmt(' test.assertExists('+selector+');'); | |||||
| // this.stmt('});'); | |||||
| } | |||||
| CasperRenderer.prototype.checkEnabled = function(item) { | |||||
| // var way = this.getControlXPath(item); var tag = item.info.tagName.toLowerCase(); | |||||
| // this.waitAndTestSelector('x("//'+tag+'[' + way + ' and not(@disabled)]")'); | |||||
| } | |||||
| CasperRenderer.prototype.checkDisabled = function(item) { | |||||
| // var way = this.getControlXPath(item); var tag = item.info.tagName.toLowerCase(); | |||||
| // this.waitAndTestSelector('x("//'+tag+'[' + way + ' and @disabled]")'); | |||||
| } | |||||
| CasperRenderer.prototype.checkSelectValue = function(item) { | |||||
| // var value = this.pyrepr(item.info.value); var way = this.getControlXPath(item); | |||||
| // this.waitAndTestSelector('x("//select[' + way + ']/option[@selected and @value='+value+']")'); | |||||
| } | |||||
| CasperRenderer.prototype.checkSelectOptions = function(item) { | |||||
| // this.stmt('/* TODO */'); | |||||
| } | |||||
| CasperRenderer.prototype.checkImageSrc = function(item) { | |||||
| // var src = this.pyrepr(this.shortUrl(item.info.src)); | |||||
| // this.waitAndTestSelector('x("//img[@src=' + src + ']")'); | |||||
| } | |||||
| CasperRenderer.prototype.waitAndTestSelector = function(selector) { | |||||
| // this.stmt('test.assertExists(' + selector + ');') | |||||
| } | |||||
| var dt = new CasperRenderer(document); | |||||
| window.onload = function onpageload() { | |||||
| var with_xy = false; | |||||
| if(window.location.search=="?xy=true") { | |||||
| with_xy = true; | |||||
| } | |||||
| chrome.runtime.sendMessage({action: "get_items"}, function(response) { | |||||
| dt.items = response.items; | |||||
| dt.render(with_xy); | |||||
| }); | |||||
| }; | 
 
							 
							 
							| #!/usr/bin/env bash | |||||
| # TO MANUALLY KILL TAGUI PROCESSES, EG IF CTRL+C WAS USED TO QUIT TAGUI ~ TEBEL.ORG # | |||||
| # aggressive failsafe for tagui and friends that have not exited gracefully | |||||
| # works by scanning processes for tagui keywords and killing them one by one | |||||
| while true; do | |||||
| php_process_id="$(ps x | grep tagui_chrome\.php | grep -v 'grep tagui_chrome\.php' | sed -e 's/^[ ]*//' | cut -d' ' -f 1 | sort -nur | head -n 1)" | |||||
| if [ -n "$php_process_id" ]; then | |||||
| kill $php_process_id > /dev/null 2>&1 | |||||
| else | |||||
| break | |||||
| fi | |||||
| done | |||||
| while true; do | |||||
| chrome_process_id="$(ps x | grep remote-debugging-port=9222 | grep tagui_user_profile | grep window-size | sed -e 's/^[ ]*//' | cut -d' ' -f 1 | sort -nur | head -n 1)" | |||||
| if [ -n "$chrome_process_id" ]; then | |||||
| kill $chrome_process_id > /dev/null 2>&1 | |||||
| else | |||||
| break | |||||
| fi | |||||
| done | |||||
| while true; do | |||||
| sikuli_process_id="$(ps x | grep tagui\.sikuli | grep -v 'grep tagui\.sikuli' | sed -e 's/^[ ]*//' | cut -d' ' -f 1 | sort -nur | head -n 1)" | |||||
| if [ -n "$sikuli_process_id" ]; then | |||||
| kill $sikuli_process_id > /dev/null 2>&1 | |||||
| else | |||||
| break | |||||
| fi | |||||
| done | |||||
| while true; do | |||||
| python_process_id="$(ps x | grep tagui_py\.py | grep -v 'grep tagui_py\.py' | sed -e 's/^[ ]*//' | cut -d' ' -f 1 | sort -nur | head -n 1)" | |||||
| if [ -n "$python_process_id" ]; then | |||||
| kill $python_process_id > /dev/null 2>&1 | |||||
| else | |||||
| break | |||||
| fi | |||||
| done | |||||
| while true; do | |||||
| r_process_id="$(ps x | grep tagui_r\.R | grep -v 'grep tagui_r\.R' | sed -e 's/^[ ]*//' | cut -d' ' -f 1 | sort -nur | head -n 1)" | |||||
| if [ -n "$r_process_id" ]; then | |||||
| kill $r_process_id > /dev/null 2>&1 | |||||
| else | |||||
| break | |||||
| fi | |||||
| done | |||||
| # get END_PROCESSES directory to create end_processes_signal to quit datatable loops | |||||
| SOURCE="${BASH_SOURCE[0]}" # slimerjs's implementation instead of cd "`dirname "$0"`" | |||||
| while [ -h "$SOURCE" ]; do END_PROCESSES_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" | |||||
| SOURCE="$(readlink "$SOURCE")"; [[ $SOURCE != /* ]] && SOURCE="$END_PROCESSES_DIR/$SOURCE"; done | |||||
| END_PROCESSES_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"; e_p_signal=false | |||||
| while true; do | |||||
| tagui_process_id="$(ps x | grep tagui/src/ | grep -v 'grep tagui/src/' | grep -v 'end_processes' | sed -e 's/^[ ]*//' | cut -d' ' -f 1 | sort -nur | head -n 1)" | |||||
| if [ -n "$tagui_process_id" ]; then | |||||
| if [ "$e_p_signal" == false ]; then e_p_signal=true; touch "$END_PROCESSES_DIR/end_processes_signal"; fi | |||||
| kill $tagui_process_id > /dev/null 2>&1 | |||||
| else | |||||
| break | |||||
| fi | |||||
| done | 
| @echo off | |||||
| rem # TO MANUALLY KILL TAGUI PROCESSES, EG IF CTRL+C WAS USED TO QUIT TAGUI ~ TEBEL.ORG # | |||||
| rem aggressive failsafe for tagui and friends that have not exited gracefully | |||||
| rem works by scanning processes for tagui keywords and killing them one by one | |||||
| rem set path to unix utilities for windows command prompt | |||||
| if exist "%~dp0unx\gawk.exe" set "path=%~dp0unx;%path%" | |||||
| :repeat_kill_php | |||||
| for /f "tokens=* usebackq" %%p in (`wmic process where "caption like '%%php.exe%%' and commandline like '%%tagui_chrome.php%%'" get processid 2^>nul ^| cut -d" " -f 1 ^| sort -nur ^| head -n 1`) do set php_process_id=%%p | |||||
| if not "%php_process_id%"=="" ( | |||||
| taskkill /PID %php_process_id% /T /F > nul 2>&1 | |||||
| goto repeat_kill_php | |||||
| ) | |||||
| :repeat_kill_chrome | |||||
| for /f "tokens=* usebackq" %%p in (`wmic process where "caption like '%%chrome.exe%%' and commandline like '%%tagui_user_profile_ --remote-debugging-port=9222%%'" get processid 2^>nul ^| cut -d" " -f 1 ^| sort -nur ^| head -n 1`) do set chrome_process_id=%%p | |||||
| if not "%chrome_process_id%"=="" ( | |||||
| taskkill /PID %chrome_process_id% /T /F > nul 2>&1 | |||||
| goto repeat_kill_chrome | |||||
| ) | |||||
| :repeat_kill_edge | |||||
| for /f "tokens=* usebackq" %%p in (`wmic process where "caption like '%%msedge.exe%%' and commandline like '%%tagui_user_profile_ --remote-debugging-port=9222%%'" get processid 2^>nul ^| cut -d" " -f 1 ^| sort -nur ^| head -n 1`) do set edge_process_id=%%p | |||||
| if not "%edge_process_id%"=="" ( | |||||
| taskkill /PID %edge_process_id% /T /F > nul 2>&1 | |||||
| goto repeat_kill_edge | |||||
| ) | |||||
| :repeat_kill_sikuli | |||||
| for /f "tokens=* usebackq" %%p in (`wmic process where "commandline like '%%tagui.sikuli%%' and not caption like '%%wmic%%' and not caption like '%%cmd.exe%%'" get processid 2^>nul ^| cut -d" " -f 1 ^| sort -nur ^| head -n 1`) do set sikuli_process_id=%%p | |||||
| if not "%sikuli_process_id%"=="" ( | |||||
| taskkill /PID %sikuli_process_id% /T /F > nul 2>&1 | |||||
| goto repeat_kill_sikuli | |||||
| ) | |||||
| :repeat_kill_python | |||||
| for /f "tokens=* usebackq" %%p in (`wmic process where "commandline like '%%tagui_py.py%%' and not caption like '%%wmic%%' and not caption like '%%cmd.exe%%'" get processid 2^>nul ^| cut -d" " -f 1 ^| sort -nur ^| head -n 1`) do set python_process_id=%%p | |||||
| if not "%python_process_id%"=="" ( | |||||
| taskkill /PID %python_process_id% /T /F > nul 2>&1 | |||||
| goto repeat_kill_python | |||||
| ) | |||||
| :repeat_kill_r | |||||
| for /f "tokens=* usebackq" %%p in (`wmic process where "commandline like '%%tagui_r.R%%' and not caption like '%%wmic%%' and not caption like '%%cmd.exe%%'" get processid 2^>nul ^| cut -d" " -f 1 ^| sort -nur ^| head -n 1`) do set r_process_id=%%p | |||||
| if not "%r_process_id%"=="" ( | |||||
| taskkill /PID %r_process_id% /T /F > nul 2>&1 | |||||
| goto repeat_kill_r | |||||
| ) | |||||
| rem set variable to avoid leaving remnant end_processes_signal to quit datatable loops | |||||
| set e_p_signal=false | |||||
| :repeat_kill_tagui | |||||
| for /f "tokens=* usebackq" %%p in (`wmic process where "executablepath like '%%\\tagui\\src\\%%' and not caption like '%%cut.exe%%' and not caption like '%%sort.exe%%' and not caption like '%%head.exe%%'" get processid 2^>nul ^| cut -d" " -f 1 ^| sort -nur ^| head -n 1`) do set tagui_process_id=%%p | |||||
| if not "%tagui_process_id%"=="" ( | |||||
| if %e_p_signal%==false ( | |||||
| set e_p_signal=true | |||||
| type nul > "%~dp0end_processes_signal" | |||||
| ) | |||||
| taskkill /PID %tagui_process_id% /T /F > nul 2>&1 | |||||
| goto repeat_kill_tagui | |||||
| ) | 
| #!/usr/bin/env bash | |||||
| # HELPER ASSISTANT SCRIPT FOR RUNNING TAGUI FRAMEWORK ~ TEBEL.ORG # | |||||
| # save location of initial directory where helper is called | |||||
| initial_dir=`pwd` | |||||
| # change current directory to TAGUI directory | |||||
| SOURCE="${BASH_SOURCE[0]}" # slimerjs's implementation instead of cd "`dirname "$0"`" | |||||
| while [ -h "$SOURCE" ]; do TAGUI_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" | |||||
| SOURCE="$(readlink "$SOURCE")"; [[ $SOURCE != /* ]] && SOURCE="$TAGUI_DIR/$SOURCE"; done | |||||
| TAGUI_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"; cd "$TAGUI_DIR" | |||||
| # delete helper file if it exists to prevent running an old call | |||||
| if [ -f "tagui_helper" ]; then rm tagui_helper; fi | |||||
| # call php helper to interpret parameters passed in to cli helper | |||||
| php -q tagui_helper.php $1 $2 $3 $4 $5 $6 $7 $8 $9 | |||||
| # run generated output from php helper to call automation flow | |||||
| if [ -f "tagui_helper" ]; then ./tagui_helper; fi | |||||
| # change back to initial directory where tagui is called | |||||
| cd "$initial_dir" | 
| @echo off | |||||
| rem # HELPER ASSISTANT SCRIPT FOR RUNNING TAGUI FRAMEWORK ~ TEBEL.ORG # | |||||
| rem enable windows for loop advanced flow control | |||||
| setlocal enableextensions enabledelayedexpansion | |||||
| rem save location of initial directory where helper is called | |||||
| set "initial_dir=%cd%" | |||||
| rem change current directory to TAGUI directory | |||||
| cd /d "%~dp0" | |||||
| rem delete helper file if it exists to prevent running an old call | |||||
| if exist "tagui_helper.cmd" del "tagui_helper.cmd" | |||||
| rem call php helper to interpret parameters passed in to cli helper | |||||
| if exist "%~dp0php\php.exe" set "path=%~dp0php;%path%" | |||||
| php -q tagui_helper.php %1 %2 %3 %4 %5 %6 %7 %8 %9 | |||||
| rem run generated output from php helper to call automation flow | |||||
| if exist "tagui_helper.cmd" tagui_helper | |||||
| rem change back to initial directory where tagui is called | |||||
| cd /d "%initial_dir%" | 
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> | |||||
| <Bundle Name="TagUI Bundle" Version="1.0.0.0" Manufacturer="AISG" UpgradeCode="8f65f60b-2aba-4833-a207-4a377f832fe2" IconSourceFile="TagUILogo.ico"> | |||||
| <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense"> | |||||
| <bal:WixStandardBootstrapperApplication | |||||
| LogoFile="TagUILogo.png" | |||||
| SuppressOptionsUI="yes" | |||||
| LicenseUrl="" | |||||
| ThemeFile="HyperlinkTheme.xml" | |||||
| LocalizationFile="HyperlinkTheme.wxl" | |||||
| xmlns:bal="http://schemas.microsoft.com/wix/BalExtension" /> | |||||
| </BootstrapperApplicationRef> | |||||
| <Chain> | |||||
| <MsiPackage | |||||
| SourceFile="TagUIv6.48.msi" | |||||
| DisplayInternalUI="yes" | |||||
| /> | |||||
| <MsiPackage | |||||
| SourceFile="amazon-corretto-8.292.10.1-windows-x64.msi" | |||||
| DisplayInternalUI="yes" | |||||
| Vital="no" | |||||
| /> | |||||
| <ExePackage | |||||
| SourceFile="vcredist_x86.exe" | |||||
| InstallCommand="/q /ACTION=Install" | |||||
| Vital="no" | |||||
| RepairCommand="/q ACTION=Repair /hideconsole" /> | |||||
| </Chain> | |||||
| </Bundle> | |||||
| </Wix> | 
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | |||||
| <WixLocalization Culture="en-us" Language="1033" xmlns="http://schemas.microsoft.com/wix/2006/localization"> | |||||
| <String Id="Caption">[WixBundleName] Setup</String> | |||||
| <String Id="Title">[WixBundleName]</String> | |||||
| <String Id="Description">This bundle setup will install the following: | |||||
| - TagUI v6.48 | |||||
| - Amazon Corretto 8 (x64) | |||||
| - Microsoft Visual C++ 2012 Redistributable (x86) - 11.0.61030</String> | |||||
| <String Id="InstallHeader">Welcome</String> | |||||
| <String Id="InstallMessage">Setup will install [WixBundleName] on your computer. Click install to continue, options to set the install directory or Close to exit.</String> | |||||
| <String Id="InstallVersion">Version [WixBundleVersion]</String> | |||||
| <String Id="ConfirmCancelMessage">Are you sure you want to cancel?</String> | |||||
| <String Id="ExecuteUpgradeRelatedBundleMessage">Previous version</String> | |||||
| <String Id="HelpHeader">Setup Help</String> | |||||
| <String Id="HelpText">/install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or | |||||
| creates a complete local copy of the bundle in directory. Install is the default. | |||||
| /passive | /quiet - displays minimal UI with no prompts or displays no UI and | |||||
| no prompts. By default UI and all prompts are displayed. | |||||
| /norestart - suppress any attempts to restart. By default UI will prompt before restart. | |||||
| /log log.txt - logs to a specific file. By default a log file is created in %TEMP%.</String> | |||||
| <String Id="HelpCloseButton">&Close</String> | |||||
| <String Id="InstallLicenseLinkText">[WixBundleName] <a href="#">license terms</a>.</String> | |||||
| <String Id="InstallAcceptCheckbox">I &agree to the license terms and conditions</String> | |||||
| <String Id="InstallOptionsButton">&Options</String> | |||||
| <String Id="InstallInstallButton">&Install</String> | |||||
| <String Id="InstallCloseButton">&Close</String> | |||||
| <String Id="OptionsHeader">Setup Options</String> | |||||
| <String Id="OptionsLocationLabel">Install location:</String> | |||||
| <String Id="OptionsBrowseButton">&Browse</String> | |||||
| <String Id="OptionsOkButton">&OK</String> | |||||
| <String Id="OptionsCancelButton">&Cancel</String> | |||||
| <String Id="ProgressHeader">Setup Progress</String> | |||||
| <String Id="ProgressLabel">Processing:</String> | |||||
| <String Id="OverallProgressPackageText">Initializing...</String> | |||||
| <String Id="ProgressCancelButton">&Cancel</String> | |||||
| <String Id="ModifyHeader">Modify Setup</String> | |||||
| <String Id="ModifyRepairButton">&Repair</String> | |||||
| <String Id="ModifyUninstallButton">&Uninstall</String> | |||||
| <String Id="ModifyCloseButton">&Close</String> | |||||
| <String Id="SuccessRepairHeader">Repair Successfully Completed</String> | |||||
| <String Id="SuccessUninstallHeader">Uninstall Successfully Completed</String> | |||||
| <String Id="SuccessInstallHeader">Installation Successfully Completed</String> | |||||
| <String Id="SuccessHeader">Setup Successful</String> | |||||
| <String Id="SuccessLaunchButton">&Launch</String> | |||||
| <String Id="SuccessRestartText">You must restart your computer before you can use the software.</String> | |||||
| <String Id="SuccessRestartButton">&Restart</String> | |||||
| <String Id="SuccessCloseButton">&Close</String> | |||||
| <String Id="FailureHeader">Setup Failed</String> | |||||
| <String Id="FailureInstallHeader">Setup Failed</String> | |||||
| <String Id="FailureUninstallHeader">Uninstall Failed</String> | |||||
| <String Id="FailureRepairHeader">Repair Failed</String> | |||||
| <String Id="FailureHyperlinkLogText">One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>.</String> | |||||
| <String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String> | |||||
| <String Id="FailureRestartButton">&Restart</String> | |||||
| <String Id="FailureCloseButton">&Close</String> | |||||
| <String Id="FilesInUseHeader">Files In Use</String> | |||||
| <String Id="FilesInUseLabel">The following applications are using files that need to be updated:</String> | |||||
| <String Id="FilesInUseCloseRadioButton">Close the &applications and attempt to restart them.</String> | |||||
| <String Id="FilesInUseDontCloseRadioButton">&Do not close applications. A reboot will be required.</String> | |||||
| <String Id="FilesInUseOkButton">&OK</String> | |||||
| <String Id="FilesInUseCancelButton">&Cancel</String> | |||||
| <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> | |||||
| </WixLocalization> | 
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | |||||
| <Theme xmlns="http://wixtoolset.org/schemas/thmutil/2010"> | |||||
| <Window Width="485" Height="300" HexStyle="100a0000" FontId="0">#(loc.Caption)</Window> | |||||
| <Font Id="0" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font> | |||||
| <Font Id="1" Height="-24" Weight="500" Foreground="000000">Segoe UI</Font> | |||||
| <Font Id="2" Height="-22" Weight="500" Foreground="666666">Segoe UI</Font> | |||||
| <Font Id="3" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font> | |||||
| <Font Id="4" Height="-12" Weight="500" Foreground="ff0000" Background="FFFFFF" Underline="yes">Segoe UI</Font> | |||||
| <Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" Visible="yes"/> | |||||
| <Text X="80" Y="11" Width="-11" Height="64" FontId="1" Visible="yes" DisablePrefix="yes">#(loc.Title)</Text> | |||||
| <Text X="80" Y="41" Width="-11" Height="64" FontId="3" Visible="yes" DisablePrefix="yes">#(loc.Description)</Text> | |||||
| <Page Name="Help"> | |||||
| <Text X="11" Y="100" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.HelpHeader)</Text> | |||||
| <Text X="11" Y="132" Width="-11" Height="-35" FontId="3" DisablePrefix="yes">#(loc.HelpText)</Text> | |||||
| <Button Name="HelpCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.HelpCloseButton)</Button> | |||||
| </Page> | |||||
| <Page Name="Install"> | |||||
| <Hypertext Name="EulaHyperlink" X="11" Y="121" Width="-11" Height="51" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallLicenseLinkText)</Hypertext> | |||||
| <Checkbox Name="EulaAcceptCheckbox" X="-11" Y="-41" Width="260" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallAcceptCheckbox)</Checkbox> | |||||
| <Button Name="OptionsButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.InstallOptionsButton)</Button> | |||||
| <Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button> | |||||
| <Button Name="WelcomeCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallCloseButton)</Button> | |||||
| </Page> | |||||
| <Page Name="Options"> | |||||
| <Text X="11" Y="100" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.OptionsHeader)</Text> | |||||
| <Text X="11" Y="141" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OptionsLocationLabel)</Text> | |||||
| <Editbox Name="FolderEditbox" X="11" Y="163" Width="-91" Height="21" TabStop="yes" FontId="3" FileSystemAutoComplete="yes" /> | |||||
| <Button Name="BrowseButton" X="-11" Y="142" Width="75" Height="23" TabStop="yes" FontId="3">#(loc.OptionsBrowseButton)</Button> | |||||
| <Button Name="OptionsOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.OptionsOkButton)</Button> | |||||
| <Button Name="OptionsCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.OptionsCancelButton)</Button> | |||||
| </Page> | |||||
| <Page Name="FilesInUse"> | |||||
| <Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.FilesInUseHeader)</Text> | |||||
| <Text X="11" Y="121" Width="-11" Height="34" FontId="3" DisablePrefix="yes">#(loc.FilesInUseLabel)</Text> | |||||
| <Text Name="FilesInUseText" X="11" Y="150" Width="-11" Height="-86" FontId="3" DisablePrefix="yes" HexStyle="0x0000C000"></Text> | |||||
| <Button Name="FilesInUseCloseRadioButton" X="11" Y="-60" Width="-11" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes" HexStyle="0x000009">#(loc.FilesInUseCloseRadioButton)</Button> | |||||
| <Button Name="FilesInUseDontCloseRadioButton" X="11" Y="-40" Width="-11" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes" HexStyle="0x000009">#(loc.FilesInUseDontCloseRadioButton)</Button> | |||||
| <Button Name="FilesInUseOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FilesInUseOkButton)</Button> | |||||
| <Button Name="FilesInUseCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.FilesInUseCancelButton)</Button> | |||||
| </Page> | |||||
| <Page Name="Progress"> | |||||
| <Text X="11" Y="100" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ProgressHeader)</Text> | |||||
| <Text X="11" Y="141" Width="70" Height="17" FontId="3" DisablePrefix="yes">#(loc.ProgressLabel)</Text> | |||||
| <Text Name="OverallProgressPackageText" X="85" Y="141" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OverallProgressPackageText)</Text> | |||||
| <Progressbar Name="OverallCalculatedProgressbar" X="11" Y="163" Width="-11" Height="15" /> | |||||
| <Button Name="ProgressCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ProgressCancelButton)</Button> | |||||
| </Page> | |||||
| <Page Name="Modify"> | |||||
| <Text X="11" Y="100" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ModifyHeader)</Text> | |||||
| <Button Name="RepairButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.ModifyRepairButton)</Button> | |||||
| <Button Name="UninstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyUninstallButton)</Button> | |||||
| <Button Name="ModifyCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyCloseButton)</Button> | |||||
| </Page> | |||||
| <Page Name="Success"> | |||||
| <Text Name="SuccessHeader" X="11" Y="100" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessHeader)</Text> | |||||
| <Text Name="SuccessInstallHeader" X="11" Y="100" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessInstallHeader)</Text> | |||||
| <Text Name="SuccessRepairHeader" X="11" Y="100" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRepairHeader)</Text> | |||||
| <Text Name="SuccessUninstallHeader" X="11" Y="100" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessUninstallHeader)</Text> | |||||
| <Button Name="LaunchButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessLaunchButton)</Button> | |||||
| <Text Name="SuccessRestartText" X="-11" Y="-51" Width="400" Height="34" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRestartText)</Text> | |||||
| <Button Name="SuccessRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessRestartButton)</Button> | |||||
| <Button Name="SuccessCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.SuccessCloseButton)</Button> | |||||
| </Page> | |||||
| <Page Name="Failure"> | |||||
| <Text Name="FailureHeader" X="11" Y="100" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureHeader)</Text> | |||||
| <Text Name="FailureInstallHeader" X="11" Y="100" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureInstallHeader)</Text> | |||||
| <Text Name="FailureUninstallHeader" X="11" Y="100" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureUninstallHeader)</Text> | |||||
| <Text Name="FailureRepairHeader" X="11" Y="100" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRepairHeader)</Text> | |||||
| <Hypertext Name="FailureLogFileLink" X="11" Y="141" Width="-11" Height="42" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureHyperlinkLogText)</Hypertext> | |||||
| <Hypertext Name="FailureMessageText" X="22" Y="183" Width="-11" Height="51" FontId="3" TabStop="yes" HideWhenDisabled="yes" /> | |||||
| <Text Name="FailureRestartText" X="-11" Y="-51" Width="400" Height="34" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRestartText)</Text> | |||||
| <Button Name="FailureRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FailureRestartButton)</Button> | |||||
| <Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.FailureCloseButton)</Button> | |||||
| </Page> | |||||
| </Theme> | 
|  | |||||
| Microsoft Visual Studio Solution File, Format Version 12.00 | |||||
| # Visual Studio Version 16 | |||||
| VisualStudioVersion = 16.0.30907.101 | |||||
| MinimumVisualStudioVersion = 10.0.40219.1 | |||||
| Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "TagUIBundle", "TagUIBundle.wixproj", "{8F65F60B-2ABA-4833-A207-4A377F832FE2}" | |||||
| EndProject | |||||
| Global | |||||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||||
| Debug|Any CPU = Debug|Any CPU | |||||
| Debug|Default = Debug|Default | |||||
| Debug|x86 = Debug|x86 | |||||
| Release|Any CPU = Release|Any CPU | |||||
| Release|Default = Release|Default | |||||
| Release|x86 = Release|x86 | |||||
| EndGlobalSection | |||||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | |||||
| {8F65F60B-2ABA-4833-A207-4A377F832FE2}.Debug|Any CPU.ActiveCfg = Debug|x86 | |||||
| {8F65F60B-2ABA-4833-A207-4A377F832FE2}.Debug|Any CPU.Build.0 = Debug|x86 | |||||
| {8F65F60B-2ABA-4833-A207-4A377F832FE2}.Debug|Default.ActiveCfg = Debug|x86 | |||||
| {8F65F60B-2ABA-4833-A207-4A377F832FE2}.Debug|x86.ActiveCfg = Debug|x86 | |||||
| {8F65F60B-2ABA-4833-A207-4A377F832FE2}.Debug|x86.Build.0 = Debug|x86 | |||||
| {8F65F60B-2ABA-4833-A207-4A377F832FE2}.Release|Any CPU.ActiveCfg = Release|x86 | |||||
| {8F65F60B-2ABA-4833-A207-4A377F832FE2}.Release|Default.ActiveCfg = Release|x86 | |||||
| {8F65F60B-2ABA-4833-A207-4A377F832FE2}.Release|x86.ActiveCfg = Release|x86 | |||||
| {8F65F60B-2ABA-4833-A207-4A377F832FE2}.Release|x86.Build.0 = Release|x86 | |||||
| EndGlobalSection | |||||
| GlobalSection(SolutionProperties) = preSolution | |||||
| HideSolutionNode = FALSE | |||||
| EndGlobalSection | |||||
| GlobalSection(ExtensibilityGlobals) = postSolution | |||||
| SolutionGuid = {296B0760-1D8F-4052-B89F-C42DB7F375F2} | |||||
| EndGlobalSection | |||||
| EndGlobal | 
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||||
| <PropertyGroup> | |||||
| <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |||||
| <Platform Condition=" '$(Platform)' == '' ">x86</Platform> | |||||
| <ProductVersion>3.10</ProductVersion> | |||||
| <ProjectGuid>8f65f60b-2aba-4833-a207-4a377f832fe2</ProjectGuid> | |||||
| <SchemaVersion>2.0</SchemaVersion> | |||||
| <OutputName>TagUIBundle</OutputName> | |||||
| <OutputType>Bundle</OutputType> | |||||
| </PropertyGroup> | |||||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "> | |||||
| <OutputPath>bin\$(Configuration)\</OutputPath> | |||||
| <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath> | |||||
| <DefineConstants>Debug</DefineConstants> | |||||
| <SuppressPdbOutput>True</SuppressPdbOutput> | |||||
| </PropertyGroup> | |||||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> | |||||
| <OutputPath>bin\$(Configuration)\</OutputPath> | |||||
| <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath> | |||||
| </PropertyGroup> | |||||
| <ItemGroup> | |||||
| <Compile Include="Bundle.wxs" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <WixExtension Include="WixBalExtension"> | |||||
| <HintPath>$(WixExtDir)\WixBalExtension.dll</HintPath> | |||||
| <Name>WixBalExtension</Name> | |||||
| </WixExtension> | |||||
| </ItemGroup> | |||||
| <Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " /> | |||||
| <Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " /> | |||||
| <Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' "> | |||||
| <Error Text="The WiX Toolset v3.11 (or newer) build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" /> | |||||
| </Target> | |||||
| <!-- | |||||
| To modify your build process, add your task inside one of the targets below and uncomment it. | |||||
| Other similar extension points exist, see Wix.targets. | |||||
| <Target Name="BeforeBuild"> | |||||
| </Target> | |||||
| <Target Name="AfterBuild"> | |||||
| </Target> | |||||
| --> | |||||
| </Project> | 
 
							| <?xml version="1.0" encoding="utf-8"?> | |||||
| <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||||
| <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | |||||
| <PropertyGroup> | |||||
| <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |||||
| <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |||||
| <ProjectGuid>{5D90BF6B-24C5-4DE2-8091-3F982808EC4F}</ProjectGuid> | |||||
| <OutputType>Library</OutputType> | |||||
| <AppDesignerFolder>Properties</AppDesignerFolder> | |||||
| <RootNamespace>ContentClass</RootNamespace> | |||||
| <AssemblyName>ContentClass</AssemblyName> | |||||
| <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> | |||||
| <FileAlignment>512</FileAlignment> | |||||
| <Deterministic>true</Deterministic> | |||||
| </PropertyGroup> | |||||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||||
| <DebugSymbols>true</DebugSymbols> | |||||
| <DebugType>full</DebugType> | |||||
| <Optimize>false</Optimize> | |||||
| <OutputPath>bin\Debug\</OutputPath> | |||||
| <DefineConstants>DEBUG;TRACE</DefineConstants> | |||||
| <ErrorReport>prompt</ErrorReport> | |||||
| <WarningLevel>4</WarningLevel> | |||||
| </PropertyGroup> | |||||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | |||||
| <DebugType>pdbonly</DebugType> | |||||
| <Optimize>true</Optimize> | |||||
| <OutputPath>bin\Release\</OutputPath> | |||||
| <DefineConstants>TRACE</DefineConstants> | |||||
| <ErrorReport>prompt</ErrorReport> | |||||
| <WarningLevel>4</WarningLevel> | |||||
| </PropertyGroup> | |||||
| <ItemGroup> | |||||
| <Reference Include="System" /> | |||||
| <Reference Include="System.Core" /> | |||||
| <Reference Include="System.Xml.Linq" /> | |||||
| <Reference Include="System.Data.DataSetExtensions" /> | |||||
| <Reference Include="Microsoft.CSharp" /> | |||||
| <Reference Include="System.Data" /> | |||||
| <Reference Include="System.Net.Http" /> | |||||
| <Reference Include="System.Xml" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <Folder Include="Properties\" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <Content Include=".\tagui\**\*.*"> | |||||
| <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | |||||
| </Content> | |||||
| </ItemGroup> | |||||
| <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |||||
| </Project> | 
|  | |||||
| namespace InstallerClassDll | |||||
| { | |||||
| partial class InstallerClass | |||||
| { | |||||
| /// <summary> | |||||
| /// Required designer variable. | |||||
| /// </summary> | |||||
| private System.ComponentModel.IContainer components = null; | |||||
| /// <summary> | |||||
| /// Clean up any resources being used. | |||||
| /// </summary> | |||||
| /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> | |||||
| protected override void Dispose(bool disposing) | |||||
| { | |||||
| if (disposing && (components != null)) | |||||
| { | |||||
| components.Dispose(); | |||||
| } | |||||
| base.Dispose(disposing); | |||||
| } | |||||
| #region Component Designer generated code | |||||
| /// <summary> | |||||
| /// Required method for Designer support - do not modify | |||||
| /// the contents of this method with the code editor. | |||||
| /// </summary> | |||||
| private void InitializeComponent() | |||||
| { | |||||
| components = new System.ComponentModel.Container(); | |||||
| } | |||||
| #endregion | |||||
| } | |||||
| } | 
| using Microsoft.Win32; | |||||
| using System; | |||||
| using System.Collections; | |||||
| using System.Collections.Generic; | |||||
| using System.ComponentModel; | |||||
| using System.Configuration.Install; | |||||
| namespace InstallerClassDll | |||||
| { | |||||
| [RunInstaller(true)] | |||||
| public partial class InstallerClass : System.Configuration.Install.Installer | |||||
| { | |||||
| public InstallerClass() | |||||
| { | |||||
| InitializeComponent(); | |||||
| } | |||||
| [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)] | |||||
| public override void Install(IDictionary stateSaver) | |||||
| { | |||||
| base.Install(stateSaver); | |||||
| } | |||||
| [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)] | |||||
| public override void Commit(IDictionary savedState) | |||||
| { | |||||
| base.Commit(savedState); | |||||
| string environmentKey = @"Environment"; | |||||
| string pathUrl = this.Context.Parameters["targetdir"].Trim('\\') + @"\tagui\src"; | |||||
| string oldPath = (string)Registry.CurrentUser.CreateSubKey(environmentKey).GetValue("PATH", "", RegistryValueOptions.DoNotExpandEnvironmentNames); | |||||
| var index = oldPath.IndexOf(pathUrl); | |||||
| if (index < 0) | |||||
| { | |||||
| Registry.CurrentUser.CreateSubKey(environmentKey).SetValue("PATH", pathUrl + ";" + oldPath, RegistryValueKind.ExpandString); | |||||
| } | |||||
| } | |||||
| [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)] | |||||
| public override void Rollback(IDictionary savedState) | |||||
| { | |||||
| base.Rollback(savedState); | |||||
| } | |||||
| [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)] | |||||
| public override void Uninstall(IDictionary savedState) | |||||
| { | |||||
| base.Uninstall(savedState); | |||||
| string environmentKey = "Environment"; | |||||
| string pathUrl = ""; | |||||
| string removeString = ""; | |||||
| string oldPath = (string)Registry.CurrentUser.CreateSubKey(environmentKey).GetValue("Path", "", RegistryValueOptions.DoNotExpandEnvironmentNames); | |||||
| string[] pathArr = oldPath.Split(';'); | |||||
| foreach (string path in pathArr) | |||||
| { | |||||
| if (path.Contains(@"tagui\src")) | |||||
| { | |||||
| pathUrl = path; | |||||
| removeString = path + ";"; | |||||
| break; | |||||
| } | |||||
| } | |||||
| var index = oldPath.IndexOf(removeString); | |||||
| if (index < 0) | |||||
| { | |||||
| removeString = pathUrl; | |||||
| index = oldPath.IndexOf(removeString); | |||||
| } | |||||
| if (index > -1) | |||||
| { | |||||
| oldPath = oldPath.Remove(index, pathUrl.Length); | |||||
| Registry.CurrentUser.CreateSubKey(environmentKey).SetValue("Path", oldPath, RegistryValueKind.ExpandString); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | 
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||||
| <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | |||||
| <PropertyGroup> | |||||
| <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |||||
| <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |||||
| <ProjectGuid>{5ACF735E-DF15-439F-B5FF-BB454E12D005}</ProjectGuid> | |||||
| <OutputType>Library</OutputType> | |||||
| <AppDesignerFolder>Properties</AppDesignerFolder> | |||||
| <RootNamespace>InstallerClassDll</RootNamespace> | |||||
| <AssemblyName>InstallerClassDll</AssemblyName> | |||||
| <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> | |||||
| <FileAlignment>512</FileAlignment> | |||||
| <Deterministic>true</Deterministic> | |||||
| </PropertyGroup> | |||||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||||
| <DebugSymbols>true</DebugSymbols> | |||||
| <DebugType>full</DebugType> | |||||
| <Optimize>false</Optimize> | |||||
| <OutputPath>bin\Debug\</OutputPath> | |||||
| <DefineConstants>DEBUG;TRACE</DefineConstants> | |||||
| <ErrorReport>prompt</ErrorReport> | |||||
| <WarningLevel>4</WarningLevel> | |||||
| </PropertyGroup> | |||||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | |||||
| <DebugType>pdbonly</DebugType> | |||||
| <Optimize>true</Optimize> | |||||
| <OutputPath>bin\Release\</OutputPath> | |||||
| <DefineConstants>TRACE</DefineConstants> | |||||
| <ErrorReport>prompt</ErrorReport> | |||||
| <WarningLevel>4</WarningLevel> | |||||
| </PropertyGroup> | |||||
| <ItemGroup> | |||||
| <Reference Include="System" /> | |||||
| <Reference Include="System.Configuration.Install" /> | |||||
| <Reference Include="System.Core" /> | |||||
| <Reference Include="System.Management" /> | |||||
| <Reference Include="System.Xml.Linq" /> | |||||
| <Reference Include="System.Data.DataSetExtensions" /> | |||||
| <Reference Include="Microsoft.CSharp" /> | |||||
| <Reference Include="System.Data" /> | |||||
| <Reference Include="System.Net.Http" /> | |||||
| <Reference Include="System.Xml" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <Compile Include="InstallerClass.cs"> | |||||
| <SubType>Component</SubType> | |||||
| </Compile> | |||||
| <Compile Include="InstallerClass.Designer.cs"> | |||||
| <DependentUpon>InstallerClass.cs</DependentUpon> | |||||
| </Compile> | |||||
| <Compile Include="Properties\AssemblyInfo.cs" /> | |||||
| </ItemGroup> | |||||
| <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |||||
| </Project> | 
| using System.Reflection; | |||||
| using System.Runtime.CompilerServices; | |||||
| using System.Runtime.InteropServices; | |||||
| // General Information about an assembly is controlled through the following | |||||
| // set of attributes. Change these attribute values to modify the information | |||||
| // associated with an assembly. | |||||
| [assembly: AssemblyTitle("InstallerClassDll")] | |||||
| [assembly: AssemblyDescription("")] | |||||
| [assembly: AssemblyConfiguration("")] | |||||
| [assembly: AssemblyCompany("")] | |||||
| [assembly: AssemblyProduct("InstallerClassDll")] | |||||
| [assembly: AssemblyCopyright("Copyright © 2021")] | |||||
| [assembly: AssemblyTrademark("")] | |||||
| [assembly: AssemblyCulture("")] | |||||
| // Setting ComVisible to false makes the types in this assembly not visible | |||||
| // to COM components. If you need to access a type in this assembly from | |||||
| // COM, set the ComVisible attribute to true on that type. | |||||
| [assembly: ComVisible(false)] | |||||
| // The following GUID is for the ID of the typelib if this project is exposed to COM | |||||
| [assembly: Guid("5acf735e-df15-439f-b5ff-bb454e12d005")] | |||||
| // Version information for an assembly consists of the following four values: | |||||
| // | |||||
| // Major Version | |||||
| // Minor Version | |||||
| // Build Number | |||||
| // Revision | |||||
| // | |||||
| // You can specify all the values or you can default the Build and Revision Numbers | |||||
| // by using the '*' as shown below: | |||||
| // [assembly: AssemblyVersion("1.0.*")] | |||||
| [assembly: AssemblyVersion("1.0.0.0")] | |||||
| [assembly: AssemblyFileVersion("1.0.0.0")] | 
|  | |||||
| Microsoft Visual Studio Solution File, Format Version 12.00 | |||||
| # Visual Studio Version 16 | |||||
| VisualStudioVersion = 16.0.30907.101 | |||||
| MinimumVisualStudioVersion = 10.0.40219.1 | |||||
| Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "TagUIv6.48", "TagUIv6.48.vdproj", "{3066A781-CFDC-4016-97DD-A2A6B6764645}" | |||||
| EndProject | |||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InstallerClassDll", "InstallerClassDll\InstallerClassDll.csproj", "{5ACF735E-DF15-439F-B5FF-BB454E12D005}" | |||||
| EndProject | |||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContentClass", "ContentClass\ContentClass.csproj", "{5D90BF6B-24C5-4DE2-8091-3F982808EC4F}" | |||||
| EndProject | |||||
| Global | |||||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||||
| Debug|Any CPU = Debug|Any CPU | |||||
| Debug|Default = Debug|Default | |||||
| Release|Any CPU = Release|Any CPU | |||||
| Release|Default = Release|Default | |||||
| EndGlobalSection | |||||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | |||||
| {3066A781-CFDC-4016-97DD-A2A6B6764645}.Debug|Any CPU.ActiveCfg = Debug | |||||
| {3066A781-CFDC-4016-97DD-A2A6B6764645}.Debug|Any CPU.Build.0 = Debug | |||||
| {3066A781-CFDC-4016-97DD-A2A6B6764645}.Debug|Default.ActiveCfg = Debug | |||||
| {3066A781-CFDC-4016-97DD-A2A6B6764645}.Debug|Default.Build.0 = Debug | |||||
| {3066A781-CFDC-4016-97DD-A2A6B6764645}.Release|Any CPU.ActiveCfg = Release | |||||
| {3066A781-CFDC-4016-97DD-A2A6B6764645}.Release|Any CPU.Build.0 = Release | |||||
| {3066A781-CFDC-4016-97DD-A2A6B6764645}.Release|Default.ActiveCfg = Release | |||||
| {3066A781-CFDC-4016-97DD-A2A6B6764645}.Release|Default.Build.0 = Release | |||||
| {5ACF735E-DF15-439F-B5FF-BB454E12D005}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {5ACF735E-DF15-439F-B5FF-BB454E12D005}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
| {5ACF735E-DF15-439F-B5FF-BB454E12D005}.Debug|Default.ActiveCfg = Debug|Any CPU | |||||
| {5ACF735E-DF15-439F-B5FF-BB454E12D005}.Debug|Default.Build.0 = Debug|Any CPU | |||||
| {5ACF735E-DF15-439F-B5FF-BB454E12D005}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {5ACF735E-DF15-439F-B5FF-BB454E12D005}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
| {5ACF735E-DF15-439F-B5FF-BB454E12D005}.Release|Default.ActiveCfg = Release|Any CPU | |||||
| {5ACF735E-DF15-439F-B5FF-BB454E12D005}.Release|Default.Build.0 = Release|Any CPU | |||||
| {5D90BF6B-24C5-4DE2-8091-3F982808EC4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {5D90BF6B-24C5-4DE2-8091-3F982808EC4F}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
| {5D90BF6B-24C5-4DE2-8091-3F982808EC4F}.Debug|Default.ActiveCfg = Debug|Any CPU | |||||
| {5D90BF6B-24C5-4DE2-8091-3F982808EC4F}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {5D90BF6B-24C5-4DE2-8091-3F982808EC4F}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
| {5D90BF6B-24C5-4DE2-8091-3F982808EC4F}.Release|Default.ActiveCfg = Release|Any CPU | |||||
| {5D90BF6B-24C5-4DE2-8091-3F982808EC4F}.Release|Default.Build.0 = Release|Any CPU | |||||
| EndGlobalSection | |||||
| GlobalSection(SolutionProperties) = preSolution | |||||
| HideSolutionNode = FALSE | |||||
| EndGlobalSection | |||||
| GlobalSection(ExtensibilityGlobals) = postSolution | |||||
| SolutionGuid = {4EF7A5BE-6B28-4985-86AB-B1B5B2D6E7B2} | |||||
| EndGlobalSection | |||||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||||
| Debug|Any CPU = Debug|Any CPU | |||||
| Debug|Default = Debug|Default | |||||
| Debug|x86 = Debug|x86 | |||||
| Release|Any CPU = Release|Any CPU | |||||
| Release|Default = Release|Default | |||||
| Release|x86 = Release|x86 | |||||
| EndGlobalSection | |||||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||||
| Debug|Any CPU = Debug|Any CPU | |||||
| Debug|Default = Debug|Default | |||||
| Release|Any CPU = Release|Any CPU | |||||
| Release|Default = Release|Default | |||||
| EndGlobalSection | |||||
| EndGlobal | 
| "DeployProject" | |||||
| { | |||||
| "VSVersion" = "3:800" | |||||
| "ProjectType" = "8:{978C614F-708E-4E1A-B201-565925725DBA}" | |||||
| "IsWebType" = "8:FALSE" | |||||
| "ProjectName" = "8:TagUIv6.48" | |||||
| "LanguageId" = "3:1033" | |||||
| "CodePage" = "3:1252" | |||||
| "UILanguageId" = "3:1033" | |||||
| "SccProjectName" = "8:" | |||||
| "SccLocalPath" = "8:" | |||||
| "SccAuxPath" = "8:" | |||||
| "SccProvider" = "8:" | |||||
| "Hierarchy" | |||||
| { | |||||
| "Entry" | |||||
| { | |||||
| "MsmKey" = "8:_B9A61D6DAA38358116915FA8464F56AB" | |||||
| "OwnerKey" = "8:_C87D1685D2654ADDA276496F1AD42C6D" | |||||
| "MsmSig" = "8:_UNDEFINED" | |||||
| } | |||||
| "Entry" | |||||
| { | |||||
| "MsmKey" = "8:_C87D1685D2654ADDA276496F1AD42C6D" | |||||
| "OwnerKey" = "8:_UNDEFINED" | |||||
| "MsmSig" = "8:_UNDEFINED" | |||||
| } | |||||
| "Entry" | |||||
| { | |||||
| "MsmKey" = "8:_UNDEFINED" | |||||
| "OwnerKey" = "8:_C87D1685D2654ADDA276496F1AD42C6D" | |||||
| "MsmSig" = "8:_UNDEFINED" | |||||
| } | |||||
| "Entry" | |||||
| { | |||||
| "MsmKey" = "8:_UNDEFINED" | |||||
| "OwnerKey" = "8:_B9A61D6DAA38358116915FA8464F56AB" | |||||
| "MsmSig" = "8:_UNDEFINED" | |||||
| } | |||||
| } | |||||
| "Configurations" | |||||
| { | |||||
| "Debug" | |||||
| { | |||||
| "DisplayName" = "8:Debug" | |||||
| "IsDebugOnly" = "11:TRUE" | |||||
| "IsReleaseOnly" = "11:FALSE" | |||||
| "OutputFilename" = "8:Debug\\TagUIv6.48.msi" | |||||
| "PackageFilesAs" = "3:2" | |||||
| "PackageFileSize" = "3:-2147483648" | |||||
| "CabType" = "3:1" | |||||
| "Compression" = "3:2" | |||||
| "SignOutput" = "11:FALSE" | |||||
| "CertificateFile" = "8:" | |||||
| "PrivateKeyFile" = "8:" | |||||
| "TimeStampServer" = "8:" | |||||
| "InstallerBootstrapper" = "3:2" | |||||
| "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}" | |||||
| { | |||||
| "Enabled" = "11:TRUE" | |||||
| "PromptEnabled" = "11:TRUE" | |||||
| "PrerequisitesLocation" = "2:1" | |||||
| "Url" = "8:" | |||||
| "ComponentsUrl" = "8:" | |||||
| "Items" | |||||
| { | |||||
| "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.7.2" | |||||
| { | |||||
| "Name" = "8:Microsoft .NET Framework 4.7.2 (x86 and x64)" | |||||
| "ProductCode" = "8:.NETFramework,Version=v4.7.2" | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| "Release" | |||||
| { | |||||
| "DisplayName" = "8:Release" | |||||
| "IsDebugOnly" = "11:FALSE" | |||||
| "IsReleaseOnly" = "11:TRUE" | |||||
| "OutputFilename" = "8:Release\\TagUIv6.48.msi" | |||||
| "PackageFilesAs" = "3:2" | |||||
| "PackageFileSize" = "3:-2147483648" | |||||
| "CabType" = "3:1" | |||||
| "Compression" = "3:2" | |||||
| "SignOutput" = "11:FALSE" | |||||
| "CertificateFile" = "8:" | |||||
| "PrivateKeyFile" = "8:" | |||||
| "TimeStampServer" = "8:" | |||||
| "InstallerBootstrapper" = "3:2" | |||||
| "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}" | |||||
| { | |||||
| "Enabled" = "11:TRUE" | |||||
| "PromptEnabled" = "11:TRUE" | |||||
| "PrerequisitesLocation" = "2:1" | |||||
| "Url" = "8:" | |||||
| "ComponentsUrl" = "8:" | |||||
| "Items" | |||||
| { | |||||
| "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.7.2" | |||||
| { | |||||
| "Name" = "8:Microsoft .NET Framework 4.7.2 (x86 and x64)" | |||||
| "ProductCode" = "8:.NETFramework,Version=v4.7.2" | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| "Deployable" | |||||
| { | |||||
| "CustomAction" | |||||
| { | |||||
| "{4AA51A2D-7D85-4A59-BA75-B0809FC8B380}:_4375B8D96BF0419E9EE07A298194ABAA" | |||||
| { | |||||
| "Name" = "8:Primary output from InstallerClassDll (Active)" | |||||
| "Condition" = "8:" | |||||
| "Object" = "8:_C87D1685D2654ADDA276496F1AD42C6D" | |||||
| "FileType" = "3:1" | |||||
| "InstallAction" = "3:3" | |||||
| "Arguments" = "8:" | |||||
| "EntryPoint" = "8:" | |||||
| "Sequence" = "3:1" | |||||
| "Identifier" = "8:_B431797E_776C_4FB2_B80F_861BE0C84F37" | |||||
| "InstallerClass" = "11:TRUE" | |||||
| "CustomActionData" = "8:" | |||||
| } | |||||
| "{4AA51A2D-7D85-4A59-BA75-B0809FC8B380}:_DBF60F851B2448938B4514F3CF2ECC5D" | |||||
| { | |||||
| "Name" = "8:Primary output from InstallerClassDll (Active)" | |||||
| "Condition" = "8:" | |||||
| "Object" = "8:_C87D1685D2654ADDA276496F1AD42C6D" | |||||
| "FileType" = "3:1" | |||||
| "InstallAction" = "3:1" | |||||
| "Arguments" = "8:" | |||||
| "EntryPoint" = "8:" | |||||
| "Sequence" = "3:1" | |||||
| "Identifier" = "8:_B18DCAFF_5375_419E_B5C5_1DC70853125F" | |||||
| "InstallerClass" = "11:TRUE" | |||||
| "CustomActionData" = "8:" | |||||
| } | |||||
| "{4AA51A2D-7D85-4A59-BA75-B0809FC8B380}:_E61AA83FB1B547EEB7D84E58FBF050EB" | |||||
| { | |||||
| "Name" = "8:Primary output from InstallerClassDll (Active)" | |||||
| "Condition" = "8:" | |||||
| "Object" = "8:_C87D1685D2654ADDA276496F1AD42C6D" | |||||
| "FileType" = "3:1" | |||||
| "InstallAction" = "3:4" | |||||
| "Arguments" = "8:" | |||||
| "EntryPoint" = "8:" | |||||
| "Sequence" = "3:1" | |||||
| "Identifier" = "8:_666BF6D5_F6F0_4F4A_9A5A_19A5A8CB9768" | |||||
| "InstallerClass" = "11:TRUE" | |||||
| "CustomActionData" = "8:" | |||||
| } | |||||
| "{4AA51A2D-7D85-4A59-BA75-B0809FC8B380}:_E70F756F5CCE4BE59227F28D1F4F3846" | |||||
| { | |||||
| "Name" = "8:Primary output from InstallerClassDll (Active)" | |||||
| "Condition" = "8:" | |||||
| "Object" = "8:_C87D1685D2654ADDA276496F1AD42C6D" | |||||
| "FileType" = "3:1" | |||||
| "InstallAction" = "3:2" | |||||
| "Arguments" = "8:" | |||||
| "EntryPoint" = "8:" | |||||
| "Sequence" = "3:1" | |||||
| "Identifier" = "8:_350D0CA8_D23B_4D40_ABF8_0128819032E8" | |||||
| "InstallerClass" = "11:TRUE" | |||||
| "CustomActionData" = "8:/targetdir=\"[TARGETDIR]\\\"" | |||||
| } | |||||
| } | |||||
| "DefaultFeature" | |||||
| { | |||||
| "Name" = "8:DefaultFeature" | |||||
| "Title" = "8:" | |||||
| "Description" = "8:" | |||||
| } | |||||
| "ExternalPersistence" | |||||
| { | |||||
| "LaunchCondition" | |||||
| { | |||||
| "{A06ECF26-33A3-4562-8140-9B0E340D4F24}:_8278E63FD67F45C68B54FED1A9872076" | |||||
| { | |||||
| "Name" = "8:.NET Framework" | |||||
| "Message" = "8:[VSDNETMSG]" | |||||
| "FrameworkVersion" = "8:.NETFramework,Version=v4.7.2" | |||||
| "AllowLaterVersions" = "11:FALSE" | |||||
| "InstallUrl" = "8:http://go.microsoft.com/fwlink/?LinkId=863262" | |||||
| } | |||||
| } | |||||
| } | |||||
| "File" | |||||
| { | |||||
| "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_B9A61D6DAA38358116915FA8464F56AB" | |||||
| { | |||||
| "AssemblyRegister" = "3:1" | |||||
| "AssemblyIsInGAC" = "11:FALSE" | |||||
| "AssemblyAsmDisplayName" = "8:System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" | |||||
| "ScatterAssemblies" | |||||
| { | |||||
| "_B9A61D6DAA38358116915FA8464F56AB" | |||||
| { | |||||
| "Name" = "8:System.Net.Http.dll" | |||||
| "Attributes" = "3:512" | |||||
| } | |||||
| } | |||||
| "SourcePath" = "8:System.Net.Http.dll" | |||||
| "TargetName" = "8:" | |||||
| "Tag" = "8:" | |||||
| "Folder" = "8:_4985F465D87A4916A308011CB96F87F7" | |||||
| "Condition" = "8:" | |||||
| "Transitive" = "11:FALSE" | |||||
| "Vital" = "11:TRUE" | |||||
| "ReadOnly" = "11:FALSE" | |||||
| "Hidden" = "11:FALSE" | |||||
| "System" = "11:FALSE" | |||||
| "Permanent" = "11:FALSE" | |||||
| "SharedLegacy" = "11:FALSE" | |||||
| "PackageAs" = "3:1" | |||||
| "Register" = "3:1" | |||||
| "Exclude" = "11:FALSE" | |||||
| "IsDependency" = "11:TRUE" | |||||
| "IsolateTo" = "8:" | |||||
| } | |||||
| } | |||||
| "FileType" | |||||
| { | |||||
| } | |||||
| "Folder" | |||||
| { | |||||
| "{3C67513D-01DD-4637-8A68-80971EB9504F}:_4985F465D87A4916A308011CB96F87F7" | |||||
| { | |||||
| "DefaultLocation" = "8:[TARGETDIR]" | |||||
| "Name" = "8:#1925" | |||||
| "AlwaysCreate" = "11:FALSE" | |||||
| "Condition" = "8:" | |||||
| "Transitive" = "11:FALSE" | |||||
| "Property" = "8:TARGETDIR" | |||||
| "Folders" | |||||
| { | |||||
| } | |||||
| } | |||||
| "{1525181F-901A-416C-8A58-119130FE478E}:_5CD1DA937E1D4509966851F6FFFA12AC" | |||||
| { | |||||
| "Name" = "8:#1919" | |||||
| "AlwaysCreate" = "11:FALSE" | |||||
| "Condition" = "8:" | |||||
| "Transitive" = "11:FALSE" | |||||
| "Property" = "8:ProgramMenuFolder" | |||||
| "Folders" | |||||
| { | |||||
| } | |||||
| } | |||||
| "{1525181F-901A-416C-8A58-119130FE478E}:_6057B46C94ED4936BF0D03A3913817D3" | |||||
| { | |||||
| "Name" = "8:#1916" | |||||
| "AlwaysCreate" = "11:FALSE" | |||||
| "Condition" = "8:" | |||||
| "Transitive" = "11:FALSE" | |||||
| "Property" = "8:DesktopFolder" | |||||
| "Folders" | |||||
| { | |||||
| } | |||||
| } | |||||
| } | |||||
| "LaunchCondition" | |||||
| { | |||||
| } | |||||
| "Locator" | |||||
| { | |||||
| } | |||||
| "MsiBootstrapper" | |||||
| { | |||||
| "LangId" = "3:1033" | |||||
| "RequiresElevation" = "11:FALSE" | |||||
| } | |||||
| "Product" | |||||
| { | |||||
| "Name" = "8:Microsoft Visual Studio" | |||||
| "ProductName" = "8:TagUIv6.48" | |||||
| "ProductCode" = "8:{47D65736-8E32-46FD-BDE9-078B4099BE14}" | |||||
| "PackageCode" = "8:{0F53DE87-F75B-4BBA-ADEA-592420B408A3}" | |||||
| "UpgradeCode" = "8:{147318CE-14F4-4693-8AC4-019A44ABD583}" | |||||
| "AspNetVersion" = "8:4.0.30319.0" | |||||
| "RestartWWWService" = "11:FALSE" | |||||
| "RemovePreviousVersions" = "11:FALSE" | |||||
| "DetectNewerInstalledVersion" = "11:TRUE" | |||||
| "InstallAllUsers" = "11:FALSE" | |||||
| "ProductVersion" = "8:1.0.0" | |||||
| "Manufacturer" = "8:AISG" | |||||
| "ARPHELPTELEPHONE" = "8:" | |||||
| "ARPHELPLINK" = "8:" | |||||
| "Title" = "8:TagUIv6.48" | |||||
| "Subject" = "8:" | |||||
| "ARPCONTACT" = "8:AISG" | |||||
| "Keywords" = "8:" | |||||
| "ARPCOMMENTS" = "8:" | |||||
| "ARPURLINFOABOUT" = "8:" | |||||
| "ARPPRODUCTICON" = "8:" | |||||
| "ARPIconIndex" = "3:0" | |||||
| "SearchPath" = "8:" | |||||
| "UseSystemSearchPath" = "11:TRUE" | |||||
| "TargetPlatform" = "3:0" | |||||
| "PreBuildEvent" = "8:" | |||||
| "PostBuildEvent" = "8:" | |||||
| "RunPostBuildEvent" = "3:0" | |||||
| } | |||||
| "Registry" | |||||
| { | |||||
| "HKLM" | |||||
| { | |||||
| "Keys" | |||||
| { | |||||
| } | |||||
| } | |||||
| "HKCU" | |||||
| { | |||||
| "Keys" | |||||
| { | |||||
| } | |||||
| } | |||||
| "HKCR" | |||||
| { | |||||
| "Keys" | |||||
| { | |||||
| } | |||||
| } | |||||
| "HKU" | |||||
| { | |||||
| "Keys" | |||||
| { | |||||
| } | |||||
| } | |||||
| "HKPU" | |||||
| { | |||||
| "Keys" | |||||
| { | |||||
| } | |||||
| } | |||||
| } | |||||
| "Sequences" | |||||
| { | |||||
| } | |||||
| "Shortcut" | |||||
| { | |||||
| } | |||||
| "UserInterface" | |||||
| { | |||||
| "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_089219B2D043460F960D600CF1ADAFA3" | |||||
| { | |||||
| "Name" = "8:#1900" | |||||
| "Sequence" = "3:2" | |||||
| "Attributes" = "3:1" | |||||
| "Dialogs" | |||||
| { | |||||
| "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_7824FE3EA9144E50BA65B50D3CD0C82E" | |||||
| { | |||||
| "Sequence" = "3:200" | |||||
| "DisplayName" = "8:Installation Folder" | |||||
| "UseDynamicProperties" = "11:TRUE" | |||||
| "IsDependency" = "11:FALSE" | |||||
| "SourcePath" = "8:<VsdDialogDir>\\VsdAdminFolderDlg.wid" | |||||
| "Properties" | |||||
| { | |||||
| "BannerBitmap" | |||||
| { | |||||
| "Name" = "8:BannerBitmap" | |||||
| "DisplayName" = "8:#1001" | |||||
| "Description" = "8:#1101" | |||||
| "Type" = "3:8" | |||||
| "ContextData" = "8:Bitmap" | |||||
| "Attributes" = "3:4" | |||||
| "Setting" = "3:1" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| } | |||||
| } | |||||
| "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_B5AAA98532974D29BF03B86C37BAD77D" | |||||
| { | |||||
| "Sequence" = "3:300" | |||||
| "DisplayName" = "8:Confirm Installation" | |||||
| "UseDynamicProperties" = "11:TRUE" | |||||
| "IsDependency" = "11:FALSE" | |||||
| "SourcePath" = "8:<VsdDialogDir>\\VsdAdminConfirmDlg.wid" | |||||
| "Properties" | |||||
| { | |||||
| "BannerBitmap" | |||||
| { | |||||
| "Name" = "8:BannerBitmap" | |||||
| "DisplayName" = "8:#1001" | |||||
| "Description" = "8:#1101" | |||||
| "Type" = "3:8" | |||||
| "ContextData" = "8:Bitmap" | |||||
| "Attributes" = "3:4" | |||||
| "Setting" = "3:1" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| } | |||||
| } | |||||
| "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_F03619DF4157430FADC8B49D3E7D965B" | |||||
| { | |||||
| "Sequence" = "3:100" | |||||
| "DisplayName" = "8:Welcome" | |||||
| "UseDynamicProperties" = "11:TRUE" | |||||
| "IsDependency" = "11:FALSE" | |||||
| "SourcePath" = "8:<VsdDialogDir>\\VsdAdminWelcomeDlg.wid" | |||||
| "Properties" | |||||
| { | |||||
| "BannerBitmap" | |||||
| { | |||||
| "Name" = "8:BannerBitmap" | |||||
| "DisplayName" = "8:#1001" | |||||
| "Description" = "8:#1101" | |||||
| "Type" = "3:8" | |||||
| "ContextData" = "8:Bitmap" | |||||
| "Attributes" = "3:4" | |||||
| "Setting" = "3:1" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| "CopyrightWarning" | |||||
| { | |||||
| "Name" = "8:CopyrightWarning" | |||||
| "DisplayName" = "8:#1002" | |||||
| "Description" = "8:#1102" | |||||
| "Type" = "3:3" | |||||
| "ContextData" = "8:" | |||||
| "Attributes" = "3:0" | |||||
| "Setting" = "3:1" | |||||
| "Value" = "8:#1202" | |||||
| "DefaultValue" = "8:#1202" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| "Welcome" | |||||
| { | |||||
| "Name" = "8:Welcome" | |||||
| "DisplayName" = "8:#1003" | |||||
| "Description" = "8:#1103" | |||||
| "Type" = "3:3" | |||||
| "ContextData" = "8:" | |||||
| "Attributes" = "3:0" | |||||
| "Setting" = "3:1" | |||||
| "Value" = "8:#1203" | |||||
| "DefaultValue" = "8:#1203" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_33AB957A39A44AFAA041B4A4D7A18D93" | |||||
| { | |||||
| "Name" = "8:#1901" | |||||
| "Sequence" = "3:1" | |||||
| "Attributes" = "3:2" | |||||
| "Dialogs" | |||||
| { | |||||
| "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_C9DD990A2E60422CA80BEE27CB53D1FA" | |||||
| { | |||||
| "Sequence" = "3:100" | |||||
| "DisplayName" = "8:Progress" | |||||
| "UseDynamicProperties" = "11:TRUE" | |||||
| "IsDependency" = "11:FALSE" | |||||
| "SourcePath" = "8:<VsdDialogDir>\\VsdProgressDlg.wid" | |||||
| "Properties" | |||||
| { | |||||
| "BannerBitmap" | |||||
| { | |||||
| "Name" = "8:BannerBitmap" | |||||
| "DisplayName" = "8:#1001" | |||||
| "Description" = "8:#1101" | |||||
| "Type" = "3:8" | |||||
| "ContextData" = "8:Bitmap" | |||||
| "Attributes" = "3:4" | |||||
| "Setting" = "3:1" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| "ShowProgress" | |||||
| { | |||||
| "Name" = "8:ShowProgress" | |||||
| "DisplayName" = "8:#1009" | |||||
| "Description" = "8:#1109" | |||||
| "Type" = "3:5" | |||||
| "ContextData" = "8:1;True=1;False=0" | |||||
| "Attributes" = "3:0" | |||||
| "Setting" = "3:0" | |||||
| "Value" = "3:1" | |||||
| "DefaultValue" = "3:1" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_3CF7F30CE7B0485D87D7433EB7CA40A9" | |||||
| { | |||||
| "Name" = "8:#1900" | |||||
| "Sequence" = "3:1" | |||||
| "Attributes" = "3:1" | |||||
| "Dialogs" | |||||
| { | |||||
| "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_32C765498F644712A381B93C55AC1FC9" | |||||
| { | |||||
| "Sequence" = "3:300" | |||||
| "DisplayName" = "8:Confirm Installation" | |||||
| "UseDynamicProperties" = "11:TRUE" | |||||
| "IsDependency" = "11:FALSE" | |||||
| "SourcePath" = "8:<VsdDialogDir>\\VsdConfirmDlg.wid" | |||||
| "Properties" | |||||
| { | |||||
| "BannerBitmap" | |||||
| { | |||||
| "Name" = "8:BannerBitmap" | |||||
| "DisplayName" = "8:#1001" | |||||
| "Description" = "8:#1101" | |||||
| "Type" = "3:8" | |||||
| "ContextData" = "8:Bitmap" | |||||
| "Attributes" = "3:4" | |||||
| "Setting" = "3:1" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| } | |||||
| } | |||||
| "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_C078B55A04644ADBB0202774369E8A8E" | |||||
| { | |||||
| "Sequence" = "3:100" | |||||
| "DisplayName" = "8:Welcome" | |||||
| "UseDynamicProperties" = "11:TRUE" | |||||
| "IsDependency" = "11:FALSE" | |||||
| "SourcePath" = "8:<VsdDialogDir>\\VsdWelcomeDlg.wid" | |||||
| "Properties" | |||||
| { | |||||
| "BannerBitmap" | |||||
| { | |||||
| "Name" = "8:BannerBitmap" | |||||
| "DisplayName" = "8:#1001" | |||||
| "Description" = "8:#1101" | |||||
| "Type" = "3:8" | |||||
| "ContextData" = "8:Bitmap" | |||||
| "Attributes" = "3:4" | |||||
| "Setting" = "3:1" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| "CopyrightWarning" | |||||
| { | |||||
| "Name" = "8:CopyrightWarning" | |||||
| "DisplayName" = "8:#1002" | |||||
| "Description" = "8:#1102" | |||||
| "Type" = "3:3" | |||||
| "ContextData" = "8:" | |||||
| "Attributes" = "3:0" | |||||
| "Setting" = "3:1" | |||||
| "Value" = "8:#1202" | |||||
| "DefaultValue" = "8:#1202" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| "Welcome" | |||||
| { | |||||
| "Name" = "8:Welcome" | |||||
| "DisplayName" = "8:#1003" | |||||
| "Description" = "8:#1103" | |||||
| "Type" = "3:3" | |||||
| "ContextData" = "8:" | |||||
| "Attributes" = "3:0" | |||||
| "Setting" = "3:1" | |||||
| "Value" = "8:#1203" | |||||
| "DefaultValue" = "8:#1203" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| } | |||||
| } | |||||
| "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_F04616A3D94044788E704A7FB97577DB" | |||||
| { | |||||
| "Sequence" = "3:200" | |||||
| "DisplayName" = "8:Installation Folder" | |||||
| "UseDynamicProperties" = "11:TRUE" | |||||
| "IsDependency" = "11:FALSE" | |||||
| "SourcePath" = "8:<VsdDialogDir>\\VsdFolderDlg.wid" | |||||
| "Properties" | |||||
| { | |||||
| "BannerBitmap" | |||||
| { | |||||
| "Name" = "8:BannerBitmap" | |||||
| "DisplayName" = "8:#1001" | |||||
| "Description" = "8:#1101" | |||||
| "Type" = "3:8" | |||||
| "ContextData" = "8:Bitmap" | |||||
| "Attributes" = "3:4" | |||||
| "Setting" = "3:1" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| "InstallAllUsersVisible" | |||||
| { | |||||
| "Name" = "8:InstallAllUsersVisible" | |||||
| "DisplayName" = "8:#1059" | |||||
| "Description" = "8:#1159" | |||||
| "Type" = "3:5" | |||||
| "ContextData" = "8:1;True=1;False=0" | |||||
| "Attributes" = "3:0" | |||||
| "Setting" = "3:0" | |||||
| "Value" = "3:1" | |||||
| "DefaultValue" = "3:1" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_7ADFBF8C565A497BA16AEE03853EEBC2" | |||||
| { | |||||
| "UseDynamicProperties" = "11:FALSE" | |||||
| "IsDependency" = "11:FALSE" | |||||
| "SourcePath" = "8:<VsdDialogDir>\\VsdBasicDialogs.wim" | |||||
| } | |||||
| "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_B871217B17CE489BAB1E2B4904AD6FD2" | |||||
| { | |||||
| "UseDynamicProperties" = "11:FALSE" | |||||
| "IsDependency" = "11:FALSE" | |||||
| "SourcePath" = "8:<VsdDialogDir>\\VsdUserInterface.wim" | |||||
| } | |||||
| "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_C90F4678E93244CFB994268766ED3230" | |||||
| { | |||||
| "Name" = "8:#1902" | |||||
| "Sequence" = "3:2" | |||||
| "Attributes" = "3:3" | |||||
| "Dialogs" | |||||
| { | |||||
| "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_B645F3C60989493B9E902413649A383E" | |||||
| { | |||||
| "Sequence" = "3:100" | |||||
| "DisplayName" = "8:Finished" | |||||
| "UseDynamicProperties" = "11:TRUE" | |||||
| "IsDependency" = "11:FALSE" | |||||
| "SourcePath" = "8:<VsdDialogDir>\\VsdAdminFinishedDlg.wid" | |||||
| "Properties" | |||||
| { | |||||
| "BannerBitmap" | |||||
| { | |||||
| "Name" = "8:BannerBitmap" | |||||
| "DisplayName" = "8:#1001" | |||||
| "Description" = "8:#1101" | |||||
| "Type" = "3:8" | |||||
| "ContextData" = "8:Bitmap" | |||||
| "Attributes" = "3:4" | |||||
| "Setting" = "3:1" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_D99685A98ED242DA927C873093792257" | |||||
| { | |||||
| "Name" = "8:#1901" | |||||
| "Sequence" = "3:2" | |||||
| "Attributes" = "3:2" | |||||
| "Dialogs" | |||||
| { | |||||
| "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_BB002AB27DA24EA6B097A629ABE5CDB6" | |||||
| { | |||||
| "Sequence" = "3:100" | |||||
| "DisplayName" = "8:Progress" | |||||
| "UseDynamicProperties" = "11:TRUE" | |||||
| "IsDependency" = "11:FALSE" | |||||
| "SourcePath" = "8:<VsdDialogDir>\\VsdAdminProgressDlg.wid" | |||||
| "Properties" | |||||
| { | |||||
| "BannerBitmap" | |||||
| { | |||||
| "Name" = "8:BannerBitmap" | |||||
| "DisplayName" = "8:#1001" | |||||
| "Description" = "8:#1101" | |||||
| "Type" = "3:8" | |||||
| "ContextData" = "8:Bitmap" | |||||
| "Attributes" = "3:4" | |||||
| "Setting" = "3:1" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| "ShowProgress" | |||||
| { | |||||
| "Name" = "8:ShowProgress" | |||||
| "DisplayName" = "8:#1009" | |||||
| "Description" = "8:#1109" | |||||
| "Type" = "3:5" | |||||
| "ContextData" = "8:1;True=1;False=0" | |||||
| "Attributes" = "3:0" | |||||
| "Setting" = "3:0" | |||||
| "Value" = "3:1" | |||||
| "DefaultValue" = "3:1" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_E2C085F5548A400FACFEEE84F8B98B80" | |||||
| { | |||||
| "Name" = "8:#1902" | |||||
| "Sequence" = "3:1" | |||||
| "Attributes" = "3:3" | |||||
| "Dialogs" | |||||
| { | |||||
| "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_AFF663A762DD43D681522E5C51A13D79" | |||||
| { | |||||
| "Sequence" = "3:100" | |||||
| "DisplayName" = "8:Finished" | |||||
| "UseDynamicProperties" = "11:TRUE" | |||||
| "IsDependency" = "11:FALSE" | |||||
| "SourcePath" = "8:<VsdDialogDir>\\VsdFinishedDlg.wid" | |||||
| "Properties" | |||||
| { | |||||
| "BannerBitmap" | |||||
| { | |||||
| "Name" = "8:BannerBitmap" | |||||
| "DisplayName" = "8:#1001" | |||||
| "Description" = "8:#1101" | |||||
| "Type" = "3:8" | |||||
| "ContextData" = "8:Bitmap" | |||||
| "Attributes" = "3:4" | |||||
| "Setting" = "3:1" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| "UpdateText" | |||||
| { | |||||
| "Name" = "8:UpdateText" | |||||
| "DisplayName" = "8:#1058" | |||||
| "Description" = "8:#1158" | |||||
| "Type" = "3:15" | |||||
| "ContextData" = "8:" | |||||
| "Attributes" = "3:0" | |||||
| "Setting" = "3:1" | |||||
| "Value" = "8:#1258" | |||||
| "DefaultValue" = "8:#1258" | |||||
| "UsePlugInResources" = "11:TRUE" | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| "MergeModule" | |||||
| { | |||||
| } | |||||
| "ProjectOutput" | |||||
| { | |||||
| "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_76A5081321E84E148958F1D319BADD01" | |||||
| { | |||||
| "SourcePath" = "8:" | |||||
| "TargetName" = "8:" | |||||
| "Tag" = "8:" | |||||
| "Folder" = "8:_4985F465D87A4916A308011CB96F87F7" | |||||
| "Condition" = "8:" | |||||
| "Transitive" = "11:FALSE" | |||||
| "Vital" = "11:TRUE" | |||||
| "ReadOnly" = "11:FALSE" | |||||
| "Hidden" = "11:FALSE" | |||||
| "System" = "11:FALSE" | |||||
| "Permanent" = "11:FALSE" | |||||
| "SharedLegacy" = "11:FALSE" | |||||
| "PackageAs" = "3:1" | |||||
| "Register" = "3:1" | |||||
| "Exclude" = "11:FALSE" | |||||
| "IsDependency" = "11:FALSE" | |||||
| "IsolateTo" = "8:" | |||||
| "ProjectOutputGroupRegister" = "3:1" | |||||
| "OutputConfiguration" = "8:" | |||||
| "OutputGroupCanonicalName" = "8:ContentFiles" | |||||
| "OutputProjectGuid" = "8:{5D90BF6B-24C5-4DE2-8091-3F982808EC4F}" | |||||
| "ShowKeyOutput" = "11:TRUE" | |||||
| "ExcludeFilters" | |||||
| { | |||||
| } | |||||
| } | |||||
| "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_C87D1685D2654ADDA276496F1AD42C6D" | |||||
| { | |||||
| "SourcePath" = "8:InstallerClassDll\\obj\\Debug\\InstallerClassDll.dll" | |||||
| "TargetName" = "8:" | |||||
| "Tag" = "8:" | |||||
| "Folder" = "8:_4985F465D87A4916A308011CB96F87F7" | |||||
| "Condition" = "8:" | |||||
| "Transitive" = "11:FALSE" | |||||
| "Vital" = "11:TRUE" | |||||
| "ReadOnly" = "11:FALSE" | |||||
| "Hidden" = "11:FALSE" | |||||
| "System" = "11:FALSE" | |||||
| "Permanent" = "11:FALSE" | |||||
| "SharedLegacy" = "11:FALSE" | |||||
| "PackageAs" = "3:1" | |||||
| "Register" = "3:1" | |||||
| "Exclude" = "11:FALSE" | |||||
| "IsDependency" = "11:FALSE" | |||||
| "IsolateTo" = "8:" | |||||
| "ProjectOutputGroupRegister" = "3:1" | |||||
| "OutputConfiguration" = "8:" | |||||
| "OutputGroupCanonicalName" = "8:Built" | |||||
| "OutputProjectGuid" = "8:{5ACF735E-DF15-439F-B5FF-BB454E12D005}" | |||||
| "ShowKeyOutput" = "11:TRUE" | |||||
| "ExcludeFilters" | |||||
| { | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | 
| EN,BN | |||||
| click,ক্লিক | |||||
| tap,টোকা | |||||
| move,পদক্ষেপ | |||||
| hover,বাতাসে ভাসিতে থাকা | |||||
| type,আদর্শ | |||||
| enter,প্রবেশ করান | |||||
| select,নির্বাচন করা | |||||
| choose,পছন্দ | |||||
| read,পড়া | |||||
| fetch,আনা | |||||
| show,প্রদর্শনী | |||||
| print,ছাপা | |||||
| save,রক্ষা | |||||
| echo,প্রতিধ্বনি | |||||
| dump,মনমরা ভাব | |||||
| write,লেখা | |||||
| snap,ক্ষুদ্র তালা | |||||
| table,টেবিল | |||||
| mouse,মাউস | |||||
| keyboard,কীবোর্ড | |||||
| live,জীবিত | |||||
| download,ডাউনলোড | |||||
| upload,আপলোড | |||||
| load,বোঝা | |||||
| receive,গ্রহণ করা | |||||
| frame,ফ্রেম | |||||
| popup,পপআপ | |||||
| wait,অপেক্ষা করুন | |||||
| timeout,সময় শেষ | |||||
| seconds,সেকেন্ড | |||||
| second,দ্বিতীয় | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,অন্যথায় যদি | |||||
| else,আর | |||||
| if,যদি | |||||
| for,জন্য | |||||
| while,যখন | |||||
| check,চেক | |||||
| more than or equals to,এর চেয়ে বেশি বা সমান | |||||
| more than or equal to,এর চেয়ে বেশি বা সমান | |||||
| greater than or equals to,এর থেকে বড় বা সমান | |||||
| greater than or equal to,এর চেয়ে বড় বা সমান | |||||
| higher than or equals to,বেশী বা সমান যাও | |||||
| higher than or equal to,এর চেয়ে বেশি বা সমান | |||||
| less than or equals to,কম বা তার সমান | |||||
| less than or equal to,অপেক্ষাকৃত ছোট বা সমান | |||||
| lesser than or equals to,কম বা তুলনায় সমান | |||||
| lesser than or equal to,কম বা এর সমান | |||||
| lower than or equals to,কম বা এর সমান | |||||
| lower than or equal to,কম বা এর সমান | |||||
| more than,অধিক | |||||
| greater than,অপেক্ষা বৃহত্তর | |||||
| higher than,তুলনায় বেশী | |||||
| less than,কম তুলনায় | |||||
| lesser than,তুলনায় কম | |||||
| lower than,ক্ষুদ্রতর | |||||
| not equals to,সমান নয় | |||||
| not equal to,সমান নয় | |||||
| equals to,সমান সমান | |||||
| equal to,সমান | |||||
| not contains,অন্তর্ভুক্ত নেই | |||||
| not contain,অন্তর্ভুক্ত না | |||||
| contains,রয়েছে | |||||
| contain,ধারণ করা | |||||
| and,এবং | |||||
| or,অথবা | |||||
| from,থেকে | |||||
| to,থেকে | |||||
| as,যেমন | |||||
| title(),খেতাব() | |||||
| url(),url() | |||||
| text(),টেক্সট() | |||||
| timer(),টাইমার() | |||||
| count(),গণনা() | |||||
| present(),বর্তমানে() | |||||
| visible(),প্রোফাইল() | |||||
| mouse_xy(),মাউস_xy() | |||||
| mouse_x(),মাউস_x() | |||||
| mouse_y(),মাউস_y() | 
| #,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 | |||||
| language,id,ko,ru,tl,vi,th,hi,ta,bn,pt,es,it,pl,hu,sr,ro | 
| https://translate.google.com/ | |||||
| // this TagUI automation flow 'self-builds' language definitions given as parameter 1 using Google Translate | |||||
| // more details on ISO-639-1 Code and Google Translate here - https://cloud.google.com/translate/docs/languages | |||||
| // define constants of vocabulary list | |||||
| vocab_list = '|click|tap|move|hover|type|enter|select|choose|read|fetch|show|print|save|echo|dump|write|snap|table|mouse|keyboard|live|download|upload|load|receive|frame|popup|wait|timeout|seconds|second|api|dom|js|vision|else if|else|if|for|while|check|more than or equals to|more than or equal to|greater than or equals to|greater than or equal to|higher than or equals to|higher than or equal to|less than or equals to|less than or equal to|lesser than or equals to|lesser than or equal to|lower than or equals to|lower than or equal to|more than|greater than|higher than|less than|lesser than|lower than|not equals to|not equal to|equals to|equal to|not contains|not contain|contains|contain|and|or|from|to|as|title()|url()|text()|timer()|count()|present()|visible()|mouse'+'_xy()|mouse'+'_x()|mouse'+'_y()|' | |||||
| // convert vocabulary list into array | |||||
| vocab_array = vocab_list.split('|') | |||||
| // set ISO-639-1 Code from parameter 1 | |||||
| ic = p1 | |||||
| //show info (useful when quiet option is used) | |||||
| echo PROCESSING NOW - `ic` | |||||
| // create language .csv header | |||||
| dump EN,`ic.toUpperCase()`\r\n to `ic.toLowerCase()`.csv | |||||
| echo `vocab_array.length-2` | |||||
| // loop and process array | |||||
| for number from 1 to vocab_array.length-2 | |||||
| https://translate.google.com.sg/#en/`ic`/`vocab_array[number]` | |||||
| // time delay to slow down translation speed, adjust accordingly | |||||
| wait 2 seconds | |||||
| read //*[@lang="`ic`"]/span/span to translation | |||||
| echo `vocab_array[number]` - `translation.toLowerCase().replace(' (','(')` | |||||
| write `vocab_array[number]`,`translation.toLowerCase().replace(' (','(')` to `ic.toLowerCase()`.csv | |||||
| //show info (useful when quiet option is used) | |||||
| echo PROCESSING DONE - `ic`\n | 
| EN,ZH | |||||
| click,点击 | |||||
| tap,点击 | |||||
| move,移到 | |||||
| hover,移到 | |||||
| type,输入 | |||||
| enter,输入 | |||||
| select,选择 | |||||
| choose,选择 | |||||
| read,读取 | |||||
| fetch,读取 | |||||
| show,显示 | |||||
| print,显示 | |||||
| save,储存 | |||||
| echo,回声 | |||||
| dump,转储 | |||||
| write,写入 | |||||
| snap,快照 | |||||
| table,表格 | |||||
| mouse,滑鼠 | |||||
| keyboard,键盘 | |||||
| live,互动 | |||||
| download,下载 | |||||
| upload,上载 | |||||
| load,加载 | |||||
| receive,接收 | |||||
| frame,框架 | |||||
| popup,弹出 | |||||
| wait,等待 | |||||
| timeout,倒数 | |||||
| seconds,秒 | |||||
| second,秒 | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| vision,视觉 | |||||
| else if,否则如果 | |||||
| else,否则 | |||||
| if,如果 | |||||
| for,让 | |||||
| while,当 | |||||
| check,验证 | |||||
| more than or equals to,多过或等于 | |||||
| more than or equal to,多过或等于 | |||||
| greater than or equals to,多过或等于 | |||||
| greater than or equal to,多过或等于 | |||||
| higher than or equals to,多过或等于 | |||||
| higher than or equal to,多过或等于 | |||||
| less than or equals to,少过或等于 | |||||
| less than or equal to,少过或等于 | |||||
| lesser than or equals to,少过或等于 | |||||
| lesser than or equal to,少过或等于 | |||||
| lower than or equals to,少过或等于 | |||||
| lower than or equal to,少过或等于 | |||||
| more than,多过 | |||||
| greater than,多过 | |||||
| higher than,多过 | |||||
| less than,少过 | |||||
| lesser than,少过 | |||||
| lower than,少过 | |||||
| not equals to,不等于 | |||||
| not equal to,不等于 | |||||
| equals to,等于 | |||||
| equal to,等于 | |||||
| not contains,不包括 | |||||
| not contain,不包括 | |||||
| contains,包括 | |||||
| contain,包括 | |||||
| and,和 | |||||
| or,或 | |||||
| from,从 | |||||
| to,到 | |||||
| as,为 | |||||
| title(),标题() | |||||
| url(),网址() | |||||
| text(),文本() | |||||
| timer(),计时() | |||||
| count(),计数() | |||||
| present(),存在() | |||||
| visible(),可见() | |||||
| mouse_xy(),滑鼠_xy() | |||||
| mouse_x(),滑鼠_x() | |||||
| mouse_y(),滑鼠_y() | 
| EN,EN | |||||
| click,click | |||||
| tap,tap | |||||
| move,move | |||||
| hover,hover | |||||
| type,type | |||||
| enter,enter | |||||
| select,select | |||||
| choose,choose | |||||
| read,read | |||||
| fetch,fetch | |||||
| show,show | |||||
| print,print | |||||
| save,save | |||||
| echo,echo | |||||
| dump,dump | |||||
| write,write | |||||
| snap,snap | |||||
| table,table | |||||
| mouse,mouse | |||||
| keyboard,keyboard | |||||
| live,live | |||||
| download,download | |||||
| upload,upload | |||||
| load,load | |||||
| receive,receive | |||||
| frame,frame | |||||
| popup,popup | |||||
| wait,wait | |||||
| timeout,timeout | |||||
| seconds,seconds | |||||
| second,second | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| vision,vision | |||||
| else if,else if | |||||
| else,else | |||||
| if,if | |||||
| for,for | |||||
| while,while | |||||
| check,check | |||||
| more than or equals to,more than or equals to | |||||
| more than or equal to,more than or equal to | |||||
| greater than or equals to,greater than or equals to | |||||
| greater than or equal to,greater than or equal to | |||||
| higher than or equals to,higher than or equals to | |||||
| higher than or equal to,higher than or equal to | |||||
| less than or equals to,less than or equals to | |||||
| less than or equal to,less than or equal to | |||||
| lesser than or equals to,lesser than or equals to | |||||
| lesser than or equal to,lesser than or equal to | |||||
| lower than or equals to,lower than or equals to | |||||
| lower than or equal to,lower than or equal to | |||||
| more than,more than | |||||
| greater than,greater than | |||||
| higher than,higher than | |||||
| less than,less than | |||||
| lesser than,lesser than | |||||
| lower than,lower than | |||||
| not equals to,not equals to | |||||
| not equal to,not equal to | |||||
| equals to,equals to | |||||
| equal to,equal to | |||||
| not contains,not contains | |||||
| not contain,not contain | |||||
| contains,contains | |||||
| contain,contain | |||||
| and,and | |||||
| or,or | |||||
| from,from | |||||
| to,to | |||||
| as,as | |||||
| title(),title() | |||||
| url(),url() | |||||
| text(),text() | |||||
| timer(),timer() | |||||
| count(),count() | |||||
| present(),present() | |||||
| visible(),visible() | |||||
| mouse_xy(),mouse_xy() | |||||
| mouse_x(),mouse_x() | |||||
| mouse_y(),mouse_y() | 
| EN,FR | |||||
| click,cliquer | |||||
| tap,tapper | |||||
| move,deplacer | |||||
| hover,flotter | |||||
| type,type | |||||
| enter,entrer | |||||
| select,sélectionner | |||||
| choose,choisir | |||||
| read,lire | |||||
| fetch,chercher | |||||
| show,montrer | |||||
| print,imprimer | |||||
| save,enregistrer | |||||
| echo,écho | |||||
| dump,déverser | |||||
| write,écrire | |||||
| snap,enclencher | |||||
| table,table | |||||
| mouse,souris | |||||
| keyboard,clavier | |||||
| live,vivre | |||||
| download,télécharger | |||||
| upload,charger | |||||
| load,charge | |||||
| receive,recevoir | |||||
| frame,cadrer | |||||
| popup,apparaitre | |||||
| wait,attendre | |||||
| timeout,délai | |||||
| seconds,secondes | |||||
| second,seconde | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,sinon si | |||||
| else,sinon | |||||
| if,si | |||||
| for,pour | |||||
| while,tandis que | |||||
| check,vérifier | |||||
| more than or equals to,plus ou égal à | |||||
| more than or equal to,plus que ou égal à | |||||
| greater than or equals to,supérieur ou égal à | |||||
| greater than or equal to,plus grand ou égal à | |||||
| higher than or equals to,supérieur ou égal à | |||||
| higher than or equal to,supérieur ou égal à | |||||
| less than or equals to,inférieur ou égal à | |||||
| less than or equal to,inférieur ou égal à | |||||
| lesser than or equals to,inférieur ou égal à | |||||
| lesser than or equal to,inférieur ou égal à | |||||
| lower than or equals to,inférieur ou égal à | |||||
| lower than or equal to,inférieur ou égal à | |||||
| more than,plus que | |||||
| greater than,plus grand que | |||||
| higher than,plus haut que | |||||
| less than,moins que | |||||
| lesser than,inférieures à | |||||
| lower than,plus bas que | |||||
| not equals to,n'est pas égal à | |||||
| not equal to,pas égal à | |||||
| equals to,est égal à | |||||
| equal to,égal à | |||||
| not contains,ne contient pas | |||||
| not contain,contient pas de | |||||
| contains,contient | |||||
| contain,contenir | |||||
| and,et | |||||
| or,ou | |||||
| from,de | |||||
| to,à | |||||
| as,comme | |||||
| title(),titre() | |||||
| url(),url() | |||||
| text(),texte() | |||||
| timer(),minuteur() | |||||
| count(),compter() | |||||
| present(),présent() | |||||
| visible(),visible() | |||||
| mouse_xy(),souris_xy() | |||||
| mouse_x(),souris_x() | |||||
| mouse_y(),souris_y() | 
| EN,DE | |||||
| click,klicken | |||||
| tap,tippen | |||||
| move,bewegen | |||||
| hover,darüber bewegen | |||||
| type,eingeben | |||||
| enter,eingeben | |||||
| select,wählen | |||||
| choose,wählen | |||||
| read,lesen | |||||
| fetch,holen | |||||
| show,anzeigen | |||||
| print,drucken | |||||
| save,speichern | |||||
| echo,echo | |||||
| dump,dump | |||||
| write,schreiben | |||||
| snap,schnapp | |||||
| table,tabelle | |||||
| mouse,maus | |||||
| keyboard,tastatur | |||||
| live,aktuell | |||||
| download,herunterladen | |||||
| upload,hochladen | |||||
| load,laden | |||||
| receive,erhalten | |||||
| frame,rahmen | |||||
| popup,pop-up | |||||
| wait,warte | |||||
| timeout,timeout | |||||
| seconds,sekunden | |||||
| second,zweite | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,sonst wenn | |||||
| else,sonst | |||||
| if,ob | |||||
| for,zum | |||||
| while,solange | |||||
| check,prüfen | |||||
| more than or equals to,mehr als oder gleich | |||||
| more than or equal to,mehr als oder gleich | |||||
| greater than or equals to,größer oder gleich | |||||
| greater than or equal to,größer als oder gleich wie | |||||
| higher than or equals to,höher als oder gleich | |||||
| higher than or equal to,höher als oder gleich | |||||
| less than or equals to,kleiner als oder gleich | |||||
| less than or equal to,gleich oder kleiner als | |||||
| lesser than or equals to,kleiner oder gleich | |||||
| lesser than or equal to,kleiner oder gleich | |||||
| lower than or equals to,niedriger als oder gleich | |||||
| lower than or equal to,kleiner oder gleich | |||||
| more than,mehr als | |||||
| greater than,größer als | |||||
| higher than,höher als | |||||
| less than,weniger als | |||||
| lesser than,weniger als | |||||
| lower than,niedriger als | |||||
| not equals to,nicht gleich | |||||
| not equal to,nicht gleichzusetzen mit | |||||
| equals to,ist gleich | |||||
| equal to,gleich | |||||
| not contains,enthält nicht | |||||
| not contain,nicht enthalten | |||||
| contains,enthält | |||||
| contain,enthalten | |||||
| and,und | |||||
| or,oder | |||||
| from,von | |||||
| to,nach | |||||
| as,wie | |||||
| title(),titel() | |||||
| url(),url() | |||||
| text(),text() | |||||
| timer(),stoppuhr() | |||||
| count(),anzahl() | |||||
| present(),vorhanden() | |||||
| visible(),sichtbar() | |||||
| mouse_xy(),maus_xy() | |||||
| mouse_x(),maus_x() | |||||
| mouse_y(),maus_y() | 
| EN,HI | |||||
| click,क्लिक | |||||
| tap,दबाएं | |||||
| move,स्थान-परिवर्तन | |||||
| hover,मंडराएं | |||||
| type,लिखो | |||||
| enter,दर्ज | |||||
| select,चुनते हैं | |||||
| choose,चुनें | |||||
| read,पढ़ें | |||||
| fetch,लाएं | |||||
| show,दिखाएँ | |||||
| print,छापें | |||||
| save,सुरक्षित करें | |||||
| echo,प्रिन्ट | |||||
| dump,डालें | |||||
| write,लिखें | |||||
| snap,स्क्रीनशॉट | |||||
| table,तालिका | |||||
| mouse,माउस | |||||
| keyboard,कीबोर्ड | |||||
| live,लाइव | |||||
| download,डाउनलोड | |||||
| upload,अपलोड | |||||
| load,भरें | |||||
| receive,प्राप्त करें | |||||
| frame,ढांचा | |||||
| popup,पॉप अप | |||||
| wait,रुकिए | |||||
| timeout,समय समाप्त | |||||
| seconds,सेकंड | |||||
| second,दूसरा | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,और अगर | |||||
| else,अन्य | |||||
| if,अगर | |||||
| for,के लिये | |||||
| while,जबकि | |||||
| check,चेक | |||||
| more than or equals to,से अधिक या बराबर है | |||||
| more than or equal to,से अधिक या उसके बराबर | |||||
| greater than or equals to,से अधिक या बराबर है | |||||
| greater than or equal to,इससे बड़ा या इसके बराबर | |||||
| higher than or equals to,से अधिक या बराबर है | |||||
| higher than or equal to,से अधिक या उसके बराबर | |||||
| less than or equals to,से कम या बराबर है | |||||
| less than or equal to,से कम या बराबर | |||||
| lesser than or equals to,से कम या बराबर है | |||||
| lesser than or equal to,उससे कम या बराबर | |||||
| lower than or equals to,से कम या बराबर है | |||||
| lower than or equal to,से कम या उसके बराबर | |||||
| more than,इससे अधिक | |||||
| greater than,से अधिक | |||||
| higher than,उससे ऊँचा | |||||
| less than,से कम | |||||
| lesser than,के मुकाबले कम | |||||
| lower than,से कम | |||||
| not equals to,नहीं करने के लिए बराबर | |||||
| not equal to,बराबर नही है | |||||
| equals to,बराबर है | |||||
| equal to,के बराबर | |||||
| not contains,शामिल नहीं है | |||||
| not contain,शामिल नहीं | |||||
| contains,शामिल | |||||
| contain,शामिल | |||||
| and,तथा | |||||
| or,या | |||||
| from,से | |||||
| to,को | |||||
| as,जैसा | |||||
| title(),शीर्षक() | |||||
| url(),यूआरएल() | |||||
| text(),टेक्स्ट() | |||||
| timer(),टाइमर() | |||||
| count(),गिनती() | |||||
| present(),मौजूद() | |||||
| visible(),दृश्य() | |||||
| mouse_xy(),माउस_xy() | |||||
| mouse_x(),माउस_x() | |||||
| mouse_y(),माउस_y() | 
| EN,HU | |||||
| click,kattint | |||||
| rclick,jobbkattint | |||||
| dclick,dublakattint | |||||
| tap,koppint | |||||
| move,mozog | |||||
| hover,lebeg | |||||
| type,írd | |||||
| enter,belép | |||||
| select,választ | |||||
| choose,választ | |||||
| read,olvas | |||||
| fetch,lekérés | |||||
| show,mutat | |||||
| print,nyomtatás | |||||
| save,mentés | |||||
| echo,kiír | |||||
| dump,lerak | |||||
| write,ír | |||||
| snap,kép | |||||
| ask,kérdez | |||||
| table,táblázat | |||||
| mouse,egér | |||||
| keyboard,billentyűzet | |||||
| live,élő | |||||
| download,letöltés | |||||
| upload,feltölt | |||||
| load,betöltés | |||||
| receive,kap | |||||
| frame,keret | |||||
| popup,felugrik | |||||
| wait,várj | |||||
| timeout,időtúllépés | |||||
| seconds,másodperc | |||||
| second,második | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,egyébként ha | |||||
| else,különben | |||||
| if,ha | |||||
| for,bejár | |||||
| while,míg | |||||
| check,jelölje be | |||||
| more than or equals to,több vagy egyenlő | |||||
| more than or equal to,több vagy egyenlő | |||||
| greater than or equals to,nagyobb vagy egyenlő | |||||
| greater than or equal to,nagyobb vagy egyenlő | |||||
| higher than or equals to,magasabb vagy egyenlő | |||||
| higher than or equal to,nagyobb vagy egyenlő | |||||
| less than or equals to,kevesebb vagy egyenlő | |||||
| less than or equal to,kevesebb vagy egyenlő | |||||
| lesser than or equals to,kisebb vagy egyenlő | |||||
| lesser than or equal to,kisebb vagy egyenlő | |||||
| lower than or equals to,kisebb vagy egyenlő | |||||
| lower than or equal to,kisebb vagy egyenlő | |||||
| more than,több mint | |||||
| greater than,nagyobb mint | |||||
| higher than,magasabb mint | |||||
| less than,kevesebb mint | |||||
| lesser than,kevesebb mint | |||||
| lower than,alacsonyabb mint | |||||
| not equals to,nem egyenlő | |||||
| not equal to,nem egyenlő | |||||
| equals to,egyenlő | |||||
| equal to,egyenlő | |||||
| not contains,nem tartalmaz | |||||
| not contain,nem tartalmazhat | |||||
| contains,tartalmaz | |||||
| contain,tartalmaz | |||||
| and,és | |||||
| or,vagy | |||||
| from,tól | |||||
| to,ide | |||||
| as,mint | |||||
| title(),cím() | |||||
| url(),url() | |||||
| text(),szöveg() | |||||
| timer(),időzítő() | |||||
| count(),számol() | |||||
| present(),megjelenik() | |||||
| visible(),látható() | |||||
| mouse_xy(),egér_xy() | |||||
| mouse_x(),egér_x() | |||||
| mouse_y(),egér_y() | 
| EN,ID | |||||
| click,klik | |||||
| tap,keran | |||||
| move,pindah | |||||
| hover,hover | |||||
| type,mengetik | |||||
| enter,memasukkan | |||||
| select,memilih | |||||
| choose,memilih | |||||
| read,baca baca | |||||
| fetch,mengambil | |||||
| show,menunjukkan | |||||
| print,mencetak | |||||
| save,menyimpan | |||||
| echo,gema | |||||
| dump,membuang | |||||
| write,menulis | |||||
| snap,jepret | |||||
| table,meja | |||||
| mouse,mouse | |||||
| keyboard,keyboard | |||||
| live,hidup | |||||
| download,download | |||||
| upload,upload | |||||
| load,beban | |||||
| receive,menerima | |||||
| frame,bingkai | |||||
| popup,muncul | |||||
| wait,tunggu | |||||
| timeout,waktu habis | |||||
| seconds,detik | |||||
| second,kedua | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,lain jika | |||||
| else,lain | |||||
| if,jika | |||||
| for,untuk | |||||
| while,sementara | |||||
| check,memeriksa | |||||
| more than or equals to,lebih dari atau sama dengan | |||||
| more than or equal to,lebih dari atau sama dengan | |||||
| greater than or equals to,lebih besar dari atau sama dengan | |||||
| greater than or equal to,lebih dari atau sama dengan | |||||
| higher than or equals to,lebih tinggi dari atau sama dengan | |||||
| higher than or equal to,lebih tinggi dari atau sama dengan | |||||
| less than or equals to,kurang dari atau sama dengan | |||||
| less than or equal to,kurang dari atau sama dengan | |||||
| lesser than or equals to,kurang dari atau sama dengan | |||||
| lesser than or equal to,kurang dari atau sama dengan | |||||
| lower than or equals to,lebih rendah dari atau sama dengan | |||||
| lower than or equal to,lebih rendah dari atau sama dengan | |||||
| more than,lebih dari | |||||
| greater than,lebih besar dari | |||||
| higher than,lebih tinggi dari | |||||
| less than,kurang dari | |||||
| lesser than,lebih rendah dari | |||||
| lower than,lebih rendah dari | |||||
| not equals to,tidak sama dengan | |||||
| not equal to,tidak sebanding dengan | |||||
| equals to,sama dengan | |||||
| equal to,sama dengan | |||||
| not contains,tidak berisi | |||||
| not contain,tidak mengandung | |||||
| contains,mengandung | |||||
| contain,berisi | |||||
| and,dan | |||||
| or,atau | |||||
| from,dari | |||||
| to,untuk | |||||
| as,sebagai | |||||
| title(),judul() | |||||
| url(),url() | |||||
| text(),teks() | |||||
| timer(),timer() | |||||
| count(),menghitung() | |||||
| present(),menyajikan() | |||||
| visible(),terlihat() | |||||
| mouse_xy(),mouse_xy() | |||||
| mouse_x(),mouse_x() | |||||
| mouse_y(),mouse_y() | 
| EN,IT | |||||
| click,clic | |||||
| tap,rubinetto | |||||
| move,mossa | |||||
| hover,librarsi | |||||
| type,tipo | |||||
| enter,accedere | |||||
| select,selezionare | |||||
| choose,scegliere | |||||
| read,leggere | |||||
| fetch,andare a prendere | |||||
| show,mostrare | |||||
| print,stampare | |||||
| save,salvare | |||||
| echo,eco | |||||
| dump,cumulo di rifiuti | |||||
| write,scrivi | |||||
| snap,schiocco | |||||
| table,tavolo | |||||
| mouse,topo | |||||
| keyboard,tastiera | |||||
| live,vivere | |||||
| download,scaricare | |||||
| upload,caricare | |||||
| load,caricare | |||||
| receive,ricevere | |||||
| frame,telaio | |||||
| popup,apparire | |||||
| wait,aspettare | |||||
| timeout,tempo scaduto | |||||
| seconds,secondi | |||||
| second,secondo | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,altrimenti se | |||||
| else,altro | |||||
| if,se | |||||
| for,per | |||||
| while,mentre | |||||
| check,dai un'occhiata | |||||
| more than or equals to,più o uguale a | |||||
| more than or equal to,più o uguale a | |||||
| greater than or equals to,maggiore o uguale a | |||||
| greater than or equal to,maggiore o uguale a | |||||
| higher than or equals to,superiore o uguale a | |||||
| higher than or equal to,superiore o uguale a | |||||
| less than or equals to,inferiore o uguale a | |||||
| less than or equal to,minore o uguale a | |||||
| lesser than or equals to,minore o uguale a | |||||
| lesser than or equal to,minore o uguale a | |||||
| lower than or equals to,inferiore o uguale a | |||||
| lower than or equal to,inferiore o uguale a | |||||
| more than,più di | |||||
| greater than,più grande di | |||||
| higher than,superiore a | |||||
| less than,meno di | |||||
| lesser than,minore di | |||||
| lower than,piu 'basso di | |||||
| not equals to,non è uguale a | |||||
| not equal to,non uguale a | |||||
| equals to,uguale a | |||||
| equal to,uguale a | |||||
| not contains,non contiene | |||||
| not contain,non contenere | |||||
| contains,contiene | |||||
| contain,contenere | |||||
| and,e | |||||
| or,o | |||||
| from,a partire dal | |||||
| to,a | |||||
| as,come | |||||
| title(),titolo() | |||||
| url(),url() | |||||
| text(),testo() | |||||
| timer(),timer() | |||||
| count(),contare() | |||||
| present(),presente() | |||||
| visible(),visibile() | |||||
| mouse_xy(),topo_xy() | |||||
| mouse_x(),topo_x() | |||||
| mouse_y(),topo_y() | 
| EN,JA | |||||
| click,クリック | |||||
| tap,タップ | |||||
| move,動く | |||||
| hover,ホバー | |||||
| type,入力する | |||||
| enter,入る | |||||
| select,選択する | |||||
| choose,選択する | |||||
| read,読む | |||||
| fetch,取得する | |||||
| show,表示する | |||||
| print,印刷する | |||||
| save,追記保存する | |||||
| echo,出力する | |||||
| dump,ダンプ | |||||
| write,上書き保存する | |||||
| snap,スクリーンショット | |||||
| table,表 | |||||
| mouse,マウス | |||||
| keyboard,キーボード | |||||
| live,ライブ | |||||
| download,ダウンロード | |||||
| upload,アップロード | |||||
| load,読み込む | |||||
| receive,受け取る | |||||
| frame,フレーム | |||||
| popup,現れる | |||||
| wait,待つ | |||||
| timeout,タイムアウト | |||||
| seconds,秒 | |||||
| second,秒 | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,else if | |||||
| else,else | |||||
| if,if | |||||
| for,for | |||||
| while,while | |||||
| check,チェック | |||||
| more than or equals to,以上または等しい | |||||
| more than or equal to,以上 | |||||
| greater than or equals to,より大きいか等しい | |||||
| greater than or equal to,以上 | |||||
| higher than or equals to,より高いか等しい | |||||
| higher than or equal to,以上 | |||||
| less than or equals to,より小さいか等しい | |||||
| less than or equal to,以下 | |||||
| lesser than or equals to,より小さいか等しい | |||||
| lesser than or equal to,より小さいか等しい | |||||
| lower than or equals to,より小さいか等しい | |||||
| lower than or equal to,より小さいか等しい | |||||
| more than,より多い | |||||
| greater than,より大きい | |||||
| higher than,よりも高い | |||||
| less than,未満 | |||||
| lesser than,より小さい | |||||
| lower than,より低い | |||||
| not equals to,等しくない | |||||
| not equal to,等しいではない | |||||
| equals to,等しい | |||||
| equal to,に等しい | |||||
| not contains,含まれていない | |||||
| not contain,含まれていない | |||||
| contains,含まれる | |||||
| contain,含む | |||||
| and,そして | |||||
| or,または | |||||
| from,から | |||||
| to,に | |||||
| as,として | |||||
| title(),タイトル() | |||||
| url(),url() | |||||
| text(),テキスト() | |||||
| timer(),タイマー() | |||||
| count(),カウント() | |||||
| present(),プレゼント() | |||||
| visible(),visible() | |||||
| mouse_xy(),マウス_xy() | |||||
| mouse_x(),マウス_x() | |||||
| mouse_y(),マウス_y() | 
| EN,KO | |||||
| click,딸깍 | |||||
| tap,꼭지 | |||||
| move,움직임 | |||||
| hover,공중 선회 | |||||
| type,유형 | |||||
| enter,들어가다 | |||||
| select,고르다 | |||||
| choose,고르다 | |||||
| read,독서 | |||||
| fetch,술책 | |||||
| show,보여 주다 | |||||
| print,인쇄 | |||||
| save,구하다 | |||||
| echo,에코 | |||||
| dump,덤프 | |||||
| write,쓰다 | |||||
| snap,스냅 | |||||
| table,표 | |||||
| mouse,마우스 | |||||
| keyboard,건반 | |||||
| live,살고 있다 | |||||
| download,다운로드 | |||||
| upload,업로드 | |||||
| load,하중 | |||||
| receive,받다 | |||||
| frame,틀 | |||||
| popup,팝업 | |||||
| wait,기다림 | |||||
| timeout,타임 아웃 | |||||
| seconds,초 | |||||
| second,둘째 | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,그밖에 만약 | |||||
| else,그밖에 | |||||
| if,만약 | |||||
| for,에 대한 | |||||
| while,동안 | |||||
| check,검사 | |||||
| more than or equals to,이상 또는 같음 | |||||
| more than or equal to,이상 | |||||
| greater than or equals to,보다 크거나 같음 | |||||
| greater than or equal to,보다 크거나 같음 | |||||
| higher than or equals to,보다 높거나 같음 | |||||
| higher than or equal to,보다 크거나 같음 | |||||
| less than or equals to,보다 작거나 같음 | |||||
| less than or equal to,보다 작거나 같음 | |||||
| lesser than or equals to,보다 작거나 같음 | |||||
| lesser than or equal to,작거나 같음 | |||||
| lower than or equals to,보다 작거나 같음 | |||||
| lower than or equal to,보다 작거나 같음 | |||||
| more than,이상 | |||||
| greater than,보다 큰 | |||||
| higher than,이상 | |||||
| less than,미만 | |||||
| lesser than,보다 작은 | |||||
| lower than,보다 낮은 | |||||
| not equals to,같지 않음 | |||||
| not equal to,같지 않음 | |||||
| equals to,같음 | |||||
| equal to,동일 | |||||
| not contains,포함하지 않음 | |||||
| not contain,포함하지 않음 | |||||
| contains,포함하다 | |||||
| contain,있다 | |||||
| and,과 | |||||
| or,또는 | |||||
| from,에서 | |||||
| to,에 | |||||
| as,같이 | |||||
| title(),표제() | |||||
| url(),url() | |||||
| text(),본문() | |||||
| timer(),시간제 노동자() | |||||
| count(),카운트() | |||||
| present(),선물() | |||||
| visible(),명백한() | |||||
| mouse_xy(),마우스_xy() | |||||
| mouse_x(),마우스_x() | |||||
| mouse_y(),마우스_y() | 
| EN,MS | |||||
| click,klik | |||||
| tap,keran | |||||
| move,pindah | |||||
| hover,hover | |||||
| type,mengetik | |||||
| enter,memasukkan | |||||
| select,memilih | |||||
| choose,memilih | |||||
| read,baca baca | |||||
| fetch,mengambil | |||||
| show,menunjukkan | |||||
| print,mencetak | |||||
| save,menyimpan | |||||
| echo,gema | |||||
| dump,membuang | |||||
| write,menulis | |||||
| snap,jepret | |||||
| table,meja | |||||
| mouse,mouse | |||||
| keyboard,keyboard | |||||
| live,hidup | |||||
| download,download | |||||
| upload,upload | |||||
| load,beban | |||||
| receive,menerima | |||||
| frame,bingkai | |||||
| popup,muncul | |||||
| wait,tunggu | |||||
| timeout,waktu habis | |||||
| seconds,detik | |||||
| second,kedua | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,lain jika | |||||
| else,lain | |||||
| if,jika | |||||
| for,untuk | |||||
| while,sementara | |||||
| check,memeriksa | |||||
| more than or equals to,lebih dari atau sama dengan | |||||
| more than or equal to,lebih dari atau sama dengan | |||||
| greater than or equals to,lebih besar dari atau sama dengan | |||||
| greater than or equal to,lebih dari atau sama dengan | |||||
| higher than or equals to,lebih tinggi dari atau sama dengan | |||||
| higher than or equal to,lebih tinggi dari atau sama dengan | |||||
| less than or equals to,kurang dari atau sama dengan | |||||
| less than or equal to,kurang dari atau sama dengan | |||||
| lesser than or equals to,kurang dari atau sama dengan | |||||
| lesser than or equal to,kurang dari atau sama dengan | |||||
| lower than or equals to,lebih rendah dari atau sama dengan | |||||
| lower than or equal to,lebih rendah dari atau sama dengan | |||||
| more than,lebih dari | |||||
| greater than,lebih besar dari | |||||
| higher than,lebih tinggi dari | |||||
| less than,kurang dari | |||||
| lesser than,lebih rendah dari | |||||
| lower than,lebih rendah dari | |||||
| not equals to,tidak sama dengan | |||||
| not equal to,tidak sebanding dengan | |||||
| equals to,sama dengan | |||||
| equal to,sama dengan | |||||
| not contains,tidak berisi | |||||
| not contain,tidak mengandung | |||||
| contains,mengandung | |||||
| contain,berisi | |||||
| and,dan | |||||
| or,atau | |||||
| from,dari | |||||
| to,untuk | |||||
| as,sebagai | |||||
| title(),judul() | |||||
| url(),url() | |||||
| text(),teks() | |||||
| timer(),timer() | |||||
| count(),menghitung() | |||||
| present(),menyajikan() | |||||
| visible(),terlihat() | |||||
| mouse_xy(),mouse_xy() | |||||
| mouse_x(),mouse_x() | |||||
| mouse_y(),mouse_y() | 
| EN,ML | |||||
| click,ക്ലിക്കുചെയ്യുക | |||||
| tap,ടാപ്പുചെയ്യുക | |||||
| move,നീക്കുക | |||||
| hover,ഹോവർ ചെയ്യുക | |||||
| type,ടൈപ്പ് ചെയ്യുക | |||||
| enter,നൽകുക | |||||
| select,തിരഞ്ഞെടുക്കുക | |||||
| choose,തിരഞ്ഞെടുക്കുക | |||||
| read,വായിക്കുക | |||||
| fetch,ലഭ്യമാക്കുക | |||||
| show,കാണിക്കുക | |||||
| print,അച്ചടിക്കുക | |||||
| save,രക്ഷിക്കും | |||||
| echo,എക്കോ | |||||
| dump,ഡമ്പ് | |||||
| write,എഴുതുക | |||||
| snap,സ്നാപ്പ് | |||||
| ask,ചോദിക്കുക | |||||
| table,മേശ | |||||
| mouse,മൗസ് | |||||
| keyboard,കീബോർഡ് | |||||
| live,തത്സമയം | |||||
| download,ഡൗൺലോഡ് | |||||
| upload,അപ്ലോഡുചെയ്യുക | |||||
| load,ലോഡ് | |||||
| receive,സ്വീകരിക്കുക | |||||
| frame,ഫ്രെയിം | |||||
| popup,പോപ്പപ്പ് | |||||
| wait,കാത്തിരിക്കുക | |||||
| timeout,ടൈം ഔട്ട് | |||||
| seconds,സെക്കൻഡ് | |||||
| second,രണ്ടാമത്തേത് | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| vision,കാഴ്ച | |||||
| else if,അല്ലെങ്കിൽ | |||||
| else,അല്ലെങ്കിൽ | |||||
| if,എങ്കിൽ | |||||
| for,വേണ്ടി | |||||
| while,ആയിരിക്കുമ്പോൾ | |||||
| check,ചെക്ക് | |||||
| more than or equals to,എന്നതിനേക്കാൾ കൂടുതൽ അല്ലെങ്കിൽ തുല്യമാണ് | |||||
| more than or equal to,കൂടുതലോ തുല്യമോ | |||||
| greater than or equals to,എന്നതിനേക്കാൾ വലുത് അല്ലെങ്കിൽ തുല്യമാണ് | |||||
| greater than or equal to,വലുതോ തുല്യമോ | |||||
| higher than or equals to,എന്നതിനേക്കാൾ ഉയർന്നതോ തുല്യമോ | |||||
| higher than or equal to,എന്നതിനേക്കാൾ ഉയർന്നതോ തുല്യമോ | |||||
| less than or equals to,കുറവ് അല്ലെങ്കിൽ തുല്യമാണ് | |||||
| less than or equal to,കുറവോ തുല്യമോ | |||||
| lesser than or equals to,കുറവ് അല്ലെങ്കിൽ തുല്യമാണ് | |||||
| lesser than or equal to,കുറവോ തുല്യമോ | |||||
| lower than or equals to,എന്നതിനേക്കാൾ കുറവാണ് അല്ലെങ്കിൽ തുല്യമാണ് | |||||
| lower than or equal to,കുറവോ തുല്യമോ | |||||
| more than,അതിലും കൂടുതൽ | |||||
| greater than,എന്നതിനേക്കാൾ വലുത് | |||||
| higher than,എന്നതിനേക്കാൾ ഉയർന്നത് | |||||
| less than,അതിൽ കുറവ് | |||||
| lesser than,കുറവ് | |||||
| lower than,അതിനേക്കാൾ താന്നത് | |||||
| not equals to,എന്നതിന് തുല്യമല്ല | |||||
| not equal to,തുല്യമല്ല | |||||
| equals to,എന്നതിന് തുല്യമാണ് | |||||
| equal to,തുല്യമാണ് | |||||
| not contains,അടങ്ങിയിട്ടില്ല | |||||
| not contain,അടങ്ങിയിട്ടില്ല | |||||
| contains,അടങ്ങിയിരിക്കുന്നു | |||||
| contain,അടങ്ങിയിട്ടുണ്ട് | |||||
| and,ഒപ്പം | |||||
| or,അഥവാ | |||||
| from,മുതൽ | |||||
| to,ടു | |||||
| as,പോലെ | |||||
| title(),ശീർഷകം() | |||||
| url(),വെബ്സൈറ്റ്() | |||||
| text(),വാചകം() | |||||
| timer(),ടൈമർ() | |||||
| count(),എണ്ണം() | |||||
| present(),വർത്തമാന() | |||||
| visible(),ദൃശ്യമാണ്() | |||||
| mouse_xy(),മൗസ്_xy() | |||||
| mouse_x(),മൗസ്_x() | |||||
| mouse_y(),മൗസ്_y() | 
| EN,PL | |||||
| click,kliknij | |||||
| tap,kran | |||||
| move,ruszaj się | |||||
| hover,wahać się | |||||
| type,rodzaj | |||||
| enter,wchodzić | |||||
| select,wybierz | |||||
| choose,wybierać | |||||
| read,czytać | |||||
| fetch,sprowadzać | |||||
| show,pokazać | |||||
| print,wydrukować | |||||
| save,zapisać | |||||
| echo,echo | |||||
| dump,wysypisko | |||||
| write,pisać | |||||
| snap,kłapnięcie | |||||
| table,stół | |||||
| mouse,mysz | |||||
| keyboard,klawiatura | |||||
| live,relacja na żywo | |||||
| download,pobieranie | |||||
| upload,przekazać plik | |||||
| load,załadować | |||||
| receive,otrzymać | |||||
| frame,rama | |||||
| popup,popup | |||||
| wait,czekać | |||||
| timeout,koniec czasu | |||||
| seconds,towary drugiej jakości | |||||
| second,druga | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,jeśli jeszcze | |||||
| else,jeszcze | |||||
| if,gdyby | |||||
| for,dla | |||||
| while,podczas gdy | |||||
| check,czek | |||||
| more than or equals to,większy lub równy | |||||
| more than or equal to,większy lub równy | |||||
| greater than or equals to,większy lub równy | |||||
| greater than or equal to,większe bądź równe | |||||
| higher than or equals to,wyższy lub równy | |||||
| higher than or equal to,wyższy lub równy | |||||
| less than or equals to,mniejszy niż lub równy | |||||
| less than or equal to,mniejszy lub równy | |||||
| lesser than or equals to,mniejsze lub równe | |||||
| lesser than or equal to,mniejsze lub równe | |||||
| lower than or equals to,niższe lub równe | |||||
| lower than or equal to,mniejsze lub równe | |||||
| more than,więcej niż | |||||
| greater than,lepszy niż | |||||
| higher than,wyższy niż | |||||
| less than,mniej niż | |||||
| lesser than,mniejszy niż | |||||
| lower than,niższa niż | |||||
| not equals to,nie równa się | |||||
| not equal to,nie równa się | |||||
| equals to,równa się | |||||
| equal to,równy | |||||
| not contains,nie zawiera | |||||
| not contain,nie zawierają | |||||
| contains,zawiera | |||||
| contain,zawierać | |||||
| and,i | |||||
| or,lub | |||||
| from,od | |||||
| to,do | |||||
| as,tak jak | |||||
| title(),tytuł() | |||||
| url(),adres url() | |||||
| text(),tekst() | |||||
| timer(),regulator czasowy() | |||||
| count(),liczyć() | |||||
| present(),teraźniejszość() | |||||
| visible(),widoczny() | |||||
| mouse_xy(),mysz_xy() | |||||
| mouse_x(),mysz_x() | |||||
| mouse_y(),mysz_y() | 
| EN,PT | |||||
| click,clique | |||||
| tap,toque | |||||
| move,mover | |||||
| hover,flutuar | |||||
| type,tipo | |||||
| enter,entrar | |||||
| select,selecione | |||||
| choose,escolher | |||||
| read,ler | |||||
| fetch,buscar | |||||
| show,exposição | |||||
| print,impressão | |||||
| save,salve | |||||
| echo,eco | |||||
| dump,despejar | |||||
| write,escreva | |||||
| snap,snap | |||||
| table,mesa | |||||
| mouse,rato | |||||
| keyboard,teclado | |||||
| live,viver | |||||
| download,baixar | |||||
| upload,envio | |||||
| load,carga | |||||
| receive,receber | |||||
| frame,armação | |||||
| popup,aparecer | |||||
| wait,esperar | |||||
| timeout,tempo esgotado | |||||
| seconds,segundos | |||||
| second,segundo | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,senão se | |||||
| else,outro | |||||
| if,e se | |||||
| for,para | |||||
| while,enquanto | |||||
| check,verifica | |||||
| more than or equals to,mais ou igual a | |||||
| more than or equal to,mais ou igual a | |||||
| greater than or equals to,maior ou igual a | |||||
| greater than or equal to,maior ou igual a | |||||
| higher than or equals to,superior ou igual a | |||||
| higher than or equal to,maior ou igual a | |||||
| less than or equals to,menor ou igual a | |||||
| less than or equal to,menos que ou igual a | |||||
| lesser than or equals to,menor ou igual a | |||||
| lesser than or equal to,menor ou igual a | |||||
| lower than or equals to,menor ou igual a | |||||
| lower than or equal to,inferior ou igual a | |||||
| more than,mais que | |||||
| greater than,melhor que | |||||
| higher than,mais alto que | |||||
| less than,menos que | |||||
| lesser than,menor que | |||||
| lower than,mais baixo que | |||||
| not equals to,não é igual a | |||||
| not equal to,não igual a | |||||
| equals to,igual a | |||||
| equal to,igual a | |||||
| not contains,não contém | |||||
| not contain,não contém | |||||
| contains,contém | |||||
| contain,conter | |||||
| and,e | |||||
| or,ou | |||||
| from,a partir de | |||||
| to,para | |||||
| as,como | |||||
| title(),título() | |||||
| url(),url() | |||||
| text(),texto() | |||||
| timer(),cronômetro() | |||||
| count(),contagem() | |||||
| present(),presente() | |||||
| visible(),visível() | |||||
| mouse_xy(),rato_xy() | |||||
| mouse_x(),rato_x() | |||||
| mouse_y(),rato_y() | 
| EN,RO | |||||
| click,clic | |||||
| tap,atingeți | |||||
| move,mișcare | |||||
| hover,planare | |||||
| type,tip | |||||
| enter,introduce | |||||
| select,selectați | |||||
| choose,alege | |||||
| read,citit | |||||
| fetch,aduce | |||||
| show,spectacol | |||||
| print,imprimare | |||||
| save,salvați | |||||
| echo,ecou | |||||
| dump,depozit | |||||
| write,scrie | |||||
| snap,agrafă | |||||
| table,masa | |||||
| mouse,mouse | |||||
| keyboard,tastatura | |||||
| live,trăi | |||||
| download,descarca | |||||
| upload,încărcați | |||||
| load,sarcină | |||||
| receive,a primi | |||||
| frame,cadru | |||||
| popup,pop-up | |||||
| wait,aștepta | |||||
| timeout,pauză | |||||
| seconds,secunde | |||||
| second,secunde | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,altfel dacă | |||||
| else,altfel | |||||
| if,dacă | |||||
| for,pentru | |||||
| while,in timp ce | |||||
| check,verifica | |||||
| more than or equals to,mai mult sau egal cu | |||||
| more than or equal to,mai mult sau egal cu | |||||
| greater than or equals to,mai mare sau egal cu | |||||
| greater than or equal to,mai mare sau egal cu | |||||
| higher than or equals to,mai mare sau egal cu | |||||
| higher than or equal to,mai mare sau egal cu | |||||
| less than or equals to,mai puțin sau egal cu | |||||
| less than or equal to,mai mică sau egală cu | |||||
| lesser than or equals to,mai mică sau egală cu | |||||
| lesser than or equal to,mai mică sau egală cu | |||||
| lower than or equals to,mai mică sau egală cu | |||||
| lower than or equal to,mai mică sau egală cu | |||||
| more than,mai mult decât | |||||
| greater than,mai mare ca | |||||
| higher than,mai mare decât | |||||
| less than,mai puțin decât | |||||
| lesser than,mai puțin decât | |||||
| lower than,mai putin decat | |||||
| not equals to,nu este egal cu | |||||
| not equal to,nu este egal cu | |||||
| equals to,este egal cu | |||||
| equal to,egal cu | |||||
| not contains,nu conține | |||||
| not contain,nu conține | |||||
| contains,conține | |||||
| contain,conține | |||||
| and,și | |||||
| or,sau | |||||
| from,din | |||||
| to,la | |||||
| as,la fel de | |||||
| title(),titlu() | |||||
| url(),url-ul() | |||||
| text(),text() | |||||
| timer(),cronometru() | |||||
| count(),numara() | |||||
| present(),prezent() | |||||
| visible(),vizibil() | |||||
| mouse_xy(),mouse_xy() | |||||
| mouse_x(),mouse_x() | |||||
| mouse_y(),mouse_y() | 
| EN,RU | |||||
| click,щелчок | |||||
| tap,нажмите | |||||
| move,переехать | |||||
| hover,зависать | |||||
| type,тип | |||||
| enter,войти | |||||
| select,выбрать | |||||
| choose,выберите | |||||
| read,читать | |||||
| fetch,получать | |||||
| show,показать | |||||
| print,распечатать | |||||
| save,спасти | |||||
| echo,эхо | |||||
| dump,свалка | |||||
| write,записывать | |||||
| snap,щелчок | |||||
| table,таблица | |||||
| mouse,мышь | |||||
| keyboard,клавиатура | |||||
| live,жить | |||||
| download,скачать | |||||
| upload,загружать | |||||
| load,нагрузка | |||||
| receive,получать | |||||
| frame,рамка | |||||
| popup,выскакивать | |||||
| wait,подождите | |||||
| timeout,тайм-аут | |||||
| seconds,секунд | |||||
| second,второй | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,иначе если | |||||
| else,еще | |||||
| if,если | |||||
| for,для | |||||
| while,в то время как | |||||
| check,проверить | |||||
| more than or equals to,больше или равно | |||||
| more than or equal to,больше или равно | |||||
| greater than or equals to,больше или равно | |||||
| greater than or equal to,больше или равно | |||||
| higher than or equals to,выше или равна | |||||
| higher than or equal to,выше или равно | |||||
| less than or equals to,меньше или равно | |||||
| less than or equal to,меньше или равно | |||||
| lesser than or equals to,меньше или равно | |||||
| lesser than or equal to,меньше или равно | |||||
| lower than or equals to,ниже или равна | |||||
| lower than or equal to,ниже или равно | |||||
| more than,больше чем | |||||
| greater than,больше чем | |||||
| higher than,выше чем | |||||
| less than,меньше чем | |||||
| lesser than,меньше чем | |||||
| lower than,ниже чем | |||||
| not equals to,не соответствует | |||||
| not equal to,не равный | |||||
| equals to,равно | |||||
| equal to,равно | |||||
| not contains,не содержит | |||||
| not contain,не содержать | |||||
| contains,содержит | |||||
| contain,содержать | |||||
| and,а также | |||||
| or,или | |||||
| from,из | |||||
| to,в | |||||
| as,в виде | |||||
| title(),заглавие() | |||||
| url(),url() | |||||
| text(),текст() | |||||
| timer(),таймер() | |||||
| count(),кол-() | |||||
| present(),настоящее время() | |||||
| visible(),видимый() | |||||
| mouse_xy(),мышь_xy() | |||||
| mouse_x(),мышь_x() | |||||
| mouse_y(),мышь_y() | 
| EN,SR | |||||
| click,кликните | |||||
| tap,славина | |||||
| move,потез | |||||
| hover,лебдети | |||||
| type,тип | |||||
| enter,унесите | |||||
| select,изаберите | |||||
| choose,изаберите | |||||
| read,читати | |||||
| fetch,донеси | |||||
| show,схов | |||||
| print,принт | |||||
| save,сачувати | |||||
| echo,одјек | |||||
| dump,депонија | |||||
| write,пиши | |||||
| snap,снап | |||||
| table,сто | |||||
| mouse,миш | |||||
| keyboard,тастатура | |||||
| live,живи | |||||
| download,преузимање | |||||
| upload,отпремити | |||||
| load,оптерећење | |||||
| receive,примити | |||||
| frame,рам | |||||
| popup,попуп | |||||
| wait,чекати | |||||
| timeout,пауза у утакмици | |||||
| seconds,секунде | |||||
| second,друго | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,друго ако | |||||
| else,друго | |||||
| if,ако | |||||
| for,за | |||||
| while,док | |||||
| check,провери | |||||
| more than or equals to,више него једнако | |||||
| more than or equal to,више или једнако | |||||
| greater than or equals to,веће или једнако | |||||
| greater than or equal to,већи или једнак | |||||
| higher than or equals to,више или једнако | |||||
| higher than or equal to,веће или једнако | |||||
| less than or equals to,мање или једнако | |||||
| less than or equal to,мање или једнако | |||||
| lesser than or equals to,мање или једнако | |||||
| lesser than or equal to,мањи или једнаки | |||||
| lower than or equals to,нижа или једнака | |||||
| lower than or equal to,мањи или једнаки | |||||
| more than,више од | |||||
| greater than,веће од | |||||
| higher than,већи од | |||||
| less than,мање од | |||||
| lesser than,мање од | |||||
| lower than,ниже од | |||||
| not equals to,није једнако | |||||
| not equal to,није једнако | |||||
| equals to,једнако | |||||
| equal to,једнако | |||||
| not contains,не садржи | |||||
| not contain,не садржи | |||||
| contains,садржи | |||||
| contain,садржати | |||||
| and,и | |||||
| or,или | |||||
| from,од | |||||
| to,до | |||||
| as,као | |||||
| title(),титле() | |||||
| url(),урл() | |||||
| text(),тект() | |||||
| timer(),тајмер() | |||||
| count(),цоунт() | |||||
| present(),поклон() | |||||
| visible(),висибле() | |||||
| mouse_xy(),миш_xy() | |||||
| mouse_x(),миш_x() | |||||
| mouse_y(),миш_y() | 
| EN,ES | |||||
| click,hacer clic | |||||
| tap,grifo | |||||
| move,movimiento | |||||
| hover,flotar | |||||
| type,tipo | |||||
| enter,entrar | |||||
| select,seleccionar | |||||
| choose,escoger | |||||
| read,leer | |||||
| fetch,ha podido recuperar | |||||
| show,espectáculo | |||||
| print,impresión | |||||
| save,salvar | |||||
| echo,eco | |||||
| dump,tugurio | |||||
| write,escribir | |||||
| snap,chasquido | |||||
| table,mesa | |||||
| mouse,ratón | |||||
| keyboard,teclado | |||||
| live,vivir | |||||
| download,descargar | |||||
| upload,subir | |||||
| load,carga | |||||
| receive,recibir | |||||
| frame,marco | |||||
| popup,surgir | |||||
| wait,espere | |||||
| timeout,se acabó el tiempo | |||||
| seconds,segundos | |||||
| second,segundo | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,de lo contrario si | |||||
| else,más | |||||
| if,si | |||||
| for,para | |||||
| while,mientras | |||||
| check,comprobar | |||||
| more than or equals to,más que o igual a | |||||
| more than or equal to,más que o igual a | |||||
| greater than or equals to,mayor que o igual a | |||||
| greater than or equal to,mayor qué o igual a | |||||
| higher than or equals to,mayor que o igual a | |||||
| higher than or equal to,mayor o igual que | |||||
| less than or equals to,menor que o igual a | |||||
| less than or equal to,menos que o igual a | |||||
| lesser than or equals to,menor que o igual a | |||||
| lesser than or equal to,menor que o igual a | |||||
| lower than or equals to,menor que o igual a | |||||
| lower than or equal to,menor o igual a | |||||
| more than,mas que | |||||
| greater than,mas grande que | |||||
| higher than,más alto que | |||||
| less than,menos que | |||||
| lesser than,menor que | |||||
| lower than,más bajo que | |||||
| not equals to,no es igual a | |||||
| not equal to,no igual a | |||||
| equals to,igual a | |||||
| equal to,igual a | |||||
| not contains,no contiene | |||||
| not contain,no contiene | |||||
| contains,contiene | |||||
| contain,contiene | |||||
| and,y | |||||
| or,o | |||||
| from,de | |||||
| to,a | |||||
| as,como | |||||
| title(),título() | |||||
| url(),url() | |||||
| text(),texto() | |||||
| timer(),minutero() | |||||
| count(),contar() | |||||
| present(),presente() | |||||
| visible(),visible() | |||||
| mouse_xy(),ratón_xy() | |||||
| mouse_x(),ratón_x() | |||||
| mouse_y(),ratón_y() | 
| EN,TL | |||||
| click,mag-click | |||||
| tap,tapikin ang | |||||
| move,ilipat | |||||
| hover,hover | |||||
| type,uri | |||||
| enter,ipasok | |||||
| select,piliin | |||||
| choose,pumili | |||||
| read,basahin | |||||
| fetch,kunin | |||||
| show,ipakita | |||||
| print,print | |||||
| save,i-save | |||||
| echo,echo | |||||
| dump,dump | |||||
| write,isulat | |||||
| snap,snap | |||||
| table,talahanayan | |||||
| mouse,daga | |||||
| keyboard,teklado | |||||
| live,mabuhay | |||||
| download,i-download | |||||
| upload,mag-upload | |||||
| load,load | |||||
| receive,tumanggap | |||||
| frame,frame | |||||
| popup,popup | |||||
| wait,maghintay | |||||
| timeout,timeout | |||||
| seconds,segundo | |||||
| second,pangalawa | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,ibang tao kung | |||||
| else,iba pa | |||||
| if,kung | |||||
| for,para sa | |||||
| while,habang | |||||
| check,suriin | |||||
| more than or equals to,higit sa o katumbas ng | |||||
| more than or equal to,higit sa o katumbas ng | |||||
| greater than or equals to,mas malaki kaysa sa o katumbas ng | |||||
| greater than or equal to,mas malaki kaysa sa o katumbas ng | |||||
| higher than or equals to,mas mataas kaysa o katumbas ng | |||||
| higher than or equal to,mas mataas kaysa sa o katumbas ng | |||||
| less than or equals to,mas mababa sa o katumbas ng | |||||
| less than or equal to,mas mababa sa o katumbas ng | |||||
| lesser than or equals to,mas mababa kaysa sa o katumbas ng | |||||
| lesser than or equal to,mas mababa kaysa sa o katumbas ng | |||||
| lower than or equals to,mas mababa kaysa o katumbas ng | |||||
| lower than or equal to,mas mababa kaysa sa o katumbas ng | |||||
| more than,higit sa | |||||
| greater than,mahigit sa | |||||
| higher than,mas mataas kaysa sa | |||||
| less than,mas mababa sa | |||||
| lesser than,mas mababa kaysa sa | |||||
| lower than,mas mababa sa | |||||
| not equals to,hindi katumbas ng | |||||
| not equal to,hindi katumbas ng | |||||
| equals to,katumbas ng | |||||
| equal to,katumbas ng | |||||
| not contains,hindi naglalaman | |||||
| not contain,hindi naglalaman | |||||
| contains,ay naglalaman | |||||
| contain,naglalaman ng | |||||
| and,at | |||||
| or,o | |||||
| from,mula sa | |||||
| to,sa | |||||
| as,bilang | |||||
| title(),pamagat() | |||||
| url(),url() | |||||
| text(),teksto() | |||||
| timer(),timer() | |||||
| count(),bilangin() | |||||
| present(),kasalukuyan() | |||||
| visible(),nakikita() | |||||
| mouse_xy(),daga_xy() | |||||
| mouse_x(),daga_x() | |||||
| mouse_y(),daga_y() | 
| EN,TA | |||||
| click,கிளிக் | |||||
| tap,மெதுவாகத்தட்டு | |||||
| move,நகர்த்து | |||||
| hover,வட்டமிடு | |||||
| type,தட்டச்சிடு | |||||
| enter,நுழை | |||||
| select,தேர்ந்தெடு | |||||
| choose,தேர்வு | |||||
| read,படி | |||||
| fetch,எடு | |||||
| show,காட்டு | |||||
| print,அச்சடி | |||||
| save,சேமி | |||||
| echo,வெளியீடு | |||||
| dump,கொட்டு | |||||
| write,எழுது | |||||
| snap,படம் எடு | |||||
| table,அட்டவணை | |||||
| mouse,சுட்டி | |||||
| keyboard,விசைப்பலகை | |||||
| live,நேரடி | |||||
| download,பதிவிறக்கு | |||||
| upload,பதிவேற்று | |||||
| load,பதிவேற்று | |||||
| receive,பெறு | |||||
| frame,சட்ட | |||||
| popup,மேல் மீட்பு | |||||
| wait,காத்திரு | |||||
| timeout,நேரம் முடிந்தது | |||||
| seconds,விநாடிகள் | |||||
| second,விநாடி | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,வேறு ஏதேனும் இருந்தால் | |||||
| else,வேறு | |||||
| if,என்றால் | |||||
| for,ஐந்து | |||||
| while,போது | |||||
| check,சரிபார்க்கவும் | |||||
| more than or equals to,விட அல்லது சமமாக | |||||
| more than or equal to,அதிகமாக அல்லது சமமாக | |||||
| greater than or equals to,அதிகமாக அல்லது சமமாக | |||||
| greater than or equal to,அதிகமாக அல்லது சமமாக | |||||
| higher than or equals to,அதிகமாக அல்லது சமமாக | |||||
| higher than or equal to,அதிகமாக அல்லது சமமாக | |||||
| less than or equals to,குறைவாக அல்லது சமமாக | |||||
| less than or equal to,குறைவாக அல்லது சமமாக | |||||
| lesser than or equals to,விட குறைவாக அல்லது சமமாக | |||||
| lesser than or equal to,குறைவான அல்லது சமமாக | |||||
| lower than or equals to,விட குறைவாக அல்லது சமமாக | |||||
| lower than or equal to,குறைவாக அல்லது சமமாக | |||||
| more than,விட | |||||
| greater than,விட அதிகமாக | |||||
| higher than,விட அதிக | |||||
| less than,குறைவாக | |||||
| lesser than,குறைவாக | |||||
| lower than,விட குறைவாக | |||||
| not equals to,சமமாக இல்லை | |||||
| not equal to,சமமாக இல்லை | |||||
| equals to,சமமாக | |||||
| equal to,சமமாக | |||||
| not contains,இல்லை | |||||
| not contain,இல்லை | |||||
| contains,கொண்டிருந்தால் | |||||
| contain,கொண்டிருக்கும் | |||||
| and,மற்றும் | |||||
| or,அல்லது | |||||
| from,இருந்து | |||||
| to,வரை | |||||
| as,போன்ற | |||||
| title(),தலைப்பு() | |||||
| url(),இணைய முகவரிக்கு() | |||||
| text(),உரை() | |||||
| timer(),டைமர்() | |||||
| count(),எண்ண() | |||||
| present(),தற்போது() | |||||
| visible(),புலப்படும்() | |||||
| mouse_xy(),சுட்டி_xy() | |||||
| mouse_x(),சுட்டி_x() | |||||
| mouse_y(),சுட்டி_y() | 
| EN,IC | |||||
| click, | |||||
| tap, | |||||
| move, | |||||
| hover, | |||||
| type, | |||||
| enter, | |||||
| select, | |||||
| choose, | |||||
| read, | |||||
| fetch, | |||||
| show, | |||||
| print, | |||||
| save, | |||||
| echo, | |||||
| dump, | |||||
| write, | |||||
| snap, | |||||
| table, | |||||
| mouse, | |||||
| keyboard, | |||||
| live, | |||||
| download, | |||||
| upload, | |||||
| load, | |||||
| receive, | |||||
| frame, | |||||
| popup, | |||||
| wait, | |||||
| timeout, | |||||
| seconds, | |||||
| second, | |||||
| api, | |||||
| dom, | |||||
| js, | |||||
| else if, | |||||
| else, | |||||
| if, | |||||
| for, | |||||
| while, | |||||
| check, | |||||
| more than or equals to, | |||||
| more than or equal to, | |||||
| greater than or equals to, | |||||
| greater than or equal to, | |||||
| higher than or equals to, | |||||
| higher than or equal to, | |||||
| less than or equals to, | |||||
| less than or equal to, | |||||
| lesser than or equals to, | |||||
| lesser than or equal to, | |||||
| lower than or equals to, | |||||
| lower than or equal to, | |||||
| more than, | |||||
| greater than, | |||||
| higher than, | |||||
| less than, | |||||
| lesser than, | |||||
| lower than, | |||||
| not equals to, | |||||
| not equal to, | |||||
| equals to, | |||||
| equal to, | |||||
| not contains, | |||||
| not contain, | |||||
| contains, | |||||
| contain, | |||||
| and, | |||||
| or, | |||||
| from, | |||||
| to, | |||||
| as, | |||||
| title(), | |||||
| url(), | |||||
| text(), | |||||
| timer(), | |||||
| count(), | |||||
| present(), | |||||
| visible(), | |||||
| mouse_xy(), | |||||
| mouse_x(), | |||||
| mouse_y(), | 
| EN,TH | |||||
| click,คลิก | |||||
| tap,แตะเบา ๆ | |||||
| move,ย้าย | |||||
| hover,โฉบ | |||||
| type,ชนิด | |||||
| enter,เข้าสู่ | |||||
| select,เลือก | |||||
| choose,เลือก | |||||
| read,อ่าน | |||||
| fetch,นำมา | |||||
| show,แสดง | |||||
| print,พิมพ์ | |||||
| save,ประหยัด | |||||
| echo,เสียงสะท้อน | |||||
| dump,เท | |||||
| write,เขียน | |||||
| snap,ตะครุบ | |||||
| table,ตาราง | |||||
| mouse,เม้าส์ | |||||
| keyboard,แป้นพิมพ์ | |||||
| live,มีชีวิต | |||||
| download,ดาวน์โหลด | |||||
| upload,อัปโหลด | |||||
| load,ภาระ | |||||
| receive,รับ | |||||
| frame,กรอบ | |||||
| popup,ป๊อปอัพ | |||||
| wait,รอ | |||||
| timeout,หมดเวลา | |||||
| seconds,วินาที | |||||
| second,ที่สอง | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,อื่นถ้า | |||||
| else,อื่น | |||||
| if,ถ้า | |||||
| for,สำหรับ | |||||
| while,ในขณะที่ | |||||
| check,ตรวจสอบ | |||||
| more than or equals to,มากกว่าหรือเท่ากับ | |||||
| more than or equal to,มากกว่าหรือเท่ากับ | |||||
| greater than or equals to,ใหญ่กว่าหรือเท่ากับ | |||||
| greater than or equal to,มากกว่าหรือเท่ากับ | |||||
| higher than or equals to,สูงกว่าหรือเท่ากับ | |||||
| higher than or equal to,สูงกว่าหรือเท่ากับ | |||||
| less than or equals to,น้อยกว่าหรือเท่ากับ | |||||
| less than or equal to,น้อยกว่าหรือเท่ากับ | |||||
| lesser than or equals to,น้อยกว่าหรือเท่ากับ | |||||
| lesser than or equal to,น้อยกว่าหรือเท่ากับ | |||||
| lower than or equals to,ต่ำกว่าหรือเท่ากับ | |||||
| lower than or equal to,ต่ำกว่าหรือเท่ากับ | |||||
| more than,มากกว่า | |||||
| greater than,มากกว่า | |||||
| higher than,สูงกว่า | |||||
| less than,น้อยกว่า | |||||
| lesser than,น้อยกว่า | |||||
| lower than,ต่ำกว่า | |||||
| not equals to,ไม่เท่ากับ | |||||
| not equal to,ไม่เท่ากับ | |||||
| equals to,เท่ากับ | |||||
| equal to,เท่ากับ | |||||
| not contains,ไม่มี | |||||
| not contain,ไม่ประกอบด้วย | |||||
| contains,มี | |||||
| contain,บรรจุ | |||||
| and,และ | |||||
| or,หรือ | |||||
| from,จาก | |||||
| to,ไปยัง | |||||
| as,เช่น | |||||
| title(),หัวข้อ() | |||||
| url(),url() | |||||
| text(),ข้อความ() | |||||
| timer(),จับเวลา() | |||||
| count(),นับ() | |||||
| present(),นำเสนอ() | |||||
| visible(),สามารถมองเห็นได้() | |||||
| mouse_xy(),เม้าส์_xy() | |||||
| mouse_x(),เม้าส์_x() | |||||
| mouse_y(),เม้าส์_y() | 
| EN,VI | |||||
| click,nhấp chuột | |||||
| tap,gõ | |||||
| move,di chuyển | |||||
| hover,bay lượn | |||||
| type,kiểu | |||||
| enter,đi vào | |||||
| select,lựa chọn | |||||
| choose,chọn | |||||
| read,đọc | |||||
| fetch,lấy | |||||
| show,chỉ | |||||
| print,in | |||||
| save,tiết kiệm | |||||
| echo,echo | |||||
| dump,đổ | |||||
| write,viết | |||||
| snap,chụp nhanh | |||||
| table,bàn | |||||
| mouse,chuột | |||||
| keyboard,bàn phím | |||||
| live,trực tiếp | |||||
| download,tải về | |||||
| upload,tải lên | |||||
| load,tải trọng | |||||
| receive,nhận được | |||||
| frame,khung | |||||
| popup,bật lên | |||||
| wait,chờ đợi | |||||
| timeout,hết giờ | |||||
| seconds,giây | |||||
| second,thứ hai | |||||
| api,api | |||||
| dom,dom | |||||
| js,js | |||||
| else if,khác nếu | |||||
| else,khác | |||||
| if,nếu | |||||
| for,cho | |||||
| while,trong khi | |||||
| check,kiểm tra | |||||
| more than or equals to,nhiều hơn hoặc bằng | |||||
| more than or equal to,nhiều hơn hoặc bằng | |||||
| greater than or equals to,lớn hơn hoặc bằng | |||||
| greater than or equal to,lớn hơn hoặc bằng | |||||
| higher than or equals to,cao hơn hoặc bằng | |||||
| higher than or equal to,cao hơn hoặc bằng | |||||
| less than or equals to,ít hơn hoặc bằng | |||||
| less than or equal to,ít hơn hoặc bằng | |||||
| lesser than or equals to,nhỏ hơn hoặc bằng | |||||
| lesser than or equal to,nhỏ hơn hoặc bằng | |||||
| lower than or equals to,thấp hơn hoặc bằng | |||||
| lower than or equal to,thấp hơn hoặc bằng | |||||
| more than,nhiều hơn | |||||
| greater than,lớn hơn | |||||
| higher than,cao hơn | |||||
| less than,ít hơn | |||||
| lesser than,ít hơn | |||||
| lower than,thấp hơn | |||||
| not equals to,không bằng | |||||
| not equal to,không bằng | |||||
| equals to,tương đương với | |||||
| equal to,tương đương với | |||||
| not contains,không chứa | |||||
| not contain,không chứa | |||||
| contains,chứa đựng | |||||
| contain,chứa | |||||
| and,và | |||||
| or,hoặc là | |||||
| from,từ | |||||
| to,đến | |||||
| as,như | |||||
| title(),chức vụ() | |||||
| url(),url() | |||||
| text(),bản văn() | |||||
| timer(),hẹn giờ() | |||||
| count(),đếm() | |||||
| present(),hiện tại() | |||||
| visible(),có thể nhìn thấy() | |||||
| mouse_xy(),chuột_xy() | |||||
| mouse_x(),chuột_x() | |||||
| mouse_y(),chuột_y() | 
| # TagUI Technical Webinar | |||||
| ### Video recording - https://www.youtube.com/watch?v=C5itbB3sCq0 | |||||
| TagUI is a free and open-source RPA tool by [AI Singapore](https://aisingapore.org), a government-funded programme to accelerate AI. TagUI has a bustling user community with ~3k downloads monthly, and extended community champions create new RPA tools for their own communities, based on TagUI. So there's a flavour of the RPA tool which has a flat learning curve for you. | |||||
| # Different flavours of TagUI | |||||
| ### Human languages | |||||
| - TagUI in English - https://github.com/kelaberetiv/TagUI | |||||
| - TagUI in other languages - https://github.com/kelaberetiv/TagUI/tree/master/src/languages | |||||
| - TagUI in MS Word & Excel - https://github.com/kelaberetiv/TagUI/blob/master/src/office/README.md | |||||
| - TagUI in VS Code - [how to install the extension](https://www.linkedin.com/posts/kensoh_hi-vs-code-folks-who-love-rpa-now-you-can-activity-6805445134034042880--PWT) and its [Marketplace homepage](https://marketplace.visualstudio.com/items?itemName=TagUisupport.tagui-support) | |||||
| - TagUI in Node-RED - https://flows.nodered.org/node/node-red-contrib-tagui | |||||
| - TagUI on cloud - https://colab.research.google.com/drive/1RimeT6-u6_nCyLAFJ0Aq9OvRaEg2UPrg?usp=sharing | |||||
| - TagUI on Docker - https://hub.docker.com/r/openiap/nodered-tagui | |||||
| - TagUI can be orchestrated in other open-source RPA tools - [OpenRPA](https://github.com/open-rpa/openrpa) & [OpenFlow](https://github.com/open-rpa/openflow), [OpenBots](https://www.linkedin.com/posts/openbots_openbots-studio-demo-support-for-tag-ui-activity-6788174021964943361-RrUD), [Robocorp](https://youtu.be/HAfQpNZVbKI) | |||||
| ### Programming languages | |||||
| - TagUI in Python - https://github.com/tebelorg/RPA-Python | |||||
| - Python on cloud - https://colab.research.google.com/drive/13bQO6G_hzE1teX35a3NZ4T5K-ICFFdB5?usp=sharing | |||||
| - Python on Docker - https://hub.docker.com/r/openiap/nodered-tagui | |||||
| - TagUI in C# .NET - https://www.nuget.org/packages/tagui | |||||
| - TagUI in Go - [work-in-progress by Suhail Ahmed from Dubai](https://www.linkedin.com/posts/kensoh_hi-fans-of-go-programming-language-would-activity-6804658389772324864-_OgH) | |||||
| # How to get started? | |||||
| My team-mate Ruth is now working on free video courses for TagUI. For now, following are useful resources to get started. The Telegram group chat and weekly Zoom meeting are especially useful resources if you have any questions to ask. Folks from community will also share their experiences. The community forum is a great place to share your RPA workflows. | |||||
| ### Useful references | |||||
| - Slide deck - https://docs.google.com/presentation/d/1pltAMzr0MZsttgg1w2ORH3ontR6Q51W9/edit?usp=sharing&ouid=115132044557947023533&rtpof=true&sd=true | |||||
| - Intro webinar - https://www.youtube.com/watch?v=hKc4eNBhMws | |||||
| - Technical webinar - https://www.youtube.com/watch?v=C5itbB3sCq0 | |||||
| - Podcast - https://botnirvana.org/podcast/tagui/ | |||||
| - Usage guide - https://tagui.readthedocs.io/en/latest/ | |||||
| - Simple examples - https://github.com/kelaberetiv/TagUI/tree/master/flows/samples | |||||
| - Advance examples - https://github.com/aimakerspace/TagUI-Bricks | |||||
| ### Community channels | |||||
| - Community forum - https://community.aisingapore.org/groups/tagui-rpa/forum | |||||
| - Weekly Zoom Q&A - [Thursday 4-5pm SGT (UTC+8)](https://github.com/kelaberetiv/TagUI/issues/914) | |||||
| - Telegram group chat - https://t.me/rpa_chat | |||||
| # Usage guide walkthrough | |||||
| ### Documentation - https://tagui.readthedocs.io/en/latest | |||||
| # Some requested scenarios | |||||
| ### Auto-resize image snapshots | |||||
| ``` | |||||
| // for example when using an image which is double the size, | |||||
| // the following will search for half that size on screen | |||||
| // and the setting applies to the rest of the workflow | |||||
| vision Settings.AlwaysResize = 0.5 | |||||
| ``` | |||||
| ### OCR using SikuliX in TagUI | |||||
| ``` | |||||
| // first, open the PDF file in one of the following ways | |||||
| dclick pdf_icon.png (desktop) | |||||
| run cmd /c start c:\folder\filename.pdf (Windows) | |||||
| run open /Users/folder/filename.pdf (macOS) | |||||
| keyboard step to search for the file and open | |||||
| // second, apply OCR using one of the following ways | |||||
| read pdf_frame.png to ocr_text | |||||
| read (200,200)-(600,600) to ocr_text | |||||
| hover anchor.png | |||||
| x = mouse_x() | |||||
| y = mouse_y() | |||||
| x1 = x + 100 | |||||
| y1 = y + 100 | |||||
| x2 = x + 500 | |||||
| y2 = y + 500 | |||||
| read (`x1`,`y1`)-(`x2`,`y2`) to ocr_text | |||||
| // optionally do data cleaning or extraction | |||||
| ocr_text = del_chars(ocr_text, '\t\r') | |||||
| name = get_text(pdf_text, 'Name:', 'State:') | |||||
| // finally, save result to a text file | |||||
| dump `ocr_text` to ocr_result.txt | |||||
| // note that for text PDF instead of scanned PDF, | |||||
| // you can copy to clipboard instead of using OCR | |||||
| keyboard [ctrl]a | |||||
| keyboard [ctrl]c | |||||
| ocr_text = clipboard() | |||||
| ``` | |||||
| ### Passing variables to SikuliX | |||||
| ``` | |||||
| // by using vision_step() function to form the actual command in SikuliX | |||||
| info_text = 'abc' | |||||
| vision_step('info_text = "' + info_text + '"'); | |||||
| info_number = 123 | |||||
| vision_step('info_number = ' + info_number); | |||||
| // saving and reading from a file is possible but need more lines of code | |||||
| ``` | |||||
| ### Returning variables from SikuliX | |||||
| ``` | |||||
| // save variable to output file using | |||||
| vision info_text = info_text + 'def' | |||||
| vision output_sikuli_text(info_text) | |||||
| // get variable from output file using | |||||
| some_variable = fetch_sikuli_text() | |||||
| echo `some_variable` | |||||
| ``` | |||||
| ### Convert PDF table to Excel | |||||
| ``` | |||||
| // TagUI's Python integration lets you access Python packages | |||||
| // check out this Python package that can do this very well | |||||
| https://github.com/atlanhq/camelot | |||||
| // you can run Python code in TagUI with the py step | |||||
| py a = 1 | |||||
| py b = 2 | |||||
| py c = a + b | |||||
| py print(c) | |||||
| echo `py_result` | |||||
| // or use py begin and py finish for Python code blocks | |||||
| py begin | |||||
| a = 1 | |||||
| b = 2 | |||||
| c = a + b | |||||
| print(c) | |||||
| py finish | |||||
| echo `py_result` | |||||
| // you can also run a certain Python script in 1 line | |||||
| py exec(open("full path to Python file").read()) | |||||
| // alternatively, use Python version of TagUI directly | |||||
| https://github.com/tebelorg/RPA-Python | |||||
| ``` | |||||
| ### Enter Excel data to website | |||||
| ``` | |||||
| // see example in human language TagUI, this can also be done in MS Word and Excel | |||||
| https://github.com/aimakerspace/TagUI-Bricks/blob/master/IMDA-ICMS-CITREP/README.md | |||||
| // see example in Python version of TagUI, entering Excel data for RPA Challenge | |||||
| https://github.com/tebelorg/RPA-Python/issues/120#issuecomment-610518196 | |||||
| ``` | |||||
| ### Shopee search to Telegram | |||||
| ``` | |||||
| // go to Shopee website | |||||
| https://shopee.sg | |||||
| // interact with the website using XPath, attributes or computer vision | |||||
| // for XPath, it can be found easily using SelectorsHub Chrome extension | |||||
| // search for item in search bar and click search button | |||||
| type //input as gryphon osmanthus sencha | |||||
| click //button[@type='button'] | |||||
| // grab and form the URL of first result from the search | |||||
| read (//*[@class = "col-xs-2-4 shopee-search-item-result__item"])[1]//@href to sub_link | |||||
| full_link = 'https://shopee.sg/' + sub_link | |||||
| // send telegram notification message with link to result | |||||
| telegram 1234567890 `full_link` | |||||
| ``` | 
 
							