Просмотр исходного кода

feat: TagUI v6.110 执行环境

master
fellow99 7 месяцев назад
Родитель
Сommit
39cceb6d0d
100 измененных файлов: 9316 добавлений и 0 удалений
  1. 176
    0
      .github/workflows/code_check.yml
  2. 115
    0
      .github/workflows/package_release.yml
  3. 112
    0
      .gitignore
  4. 202
    0
      LICENSE.md
  5. 110
    0
      README.md
  6. 20
    0
      docs/Makefile
  7. Двоичные данные
      docs/_static/cmdline.gif
  8. Двоичные данные
      docs/_static/deploy-a-flow.mp4
  9. Двоичные данные
      docs/_static/element_attributes.png
  10. Двоичные данные
      docs/_static/find_xpath.png
  11. Двоичные данные
      docs/_static/live-mode.mp4
  12. Двоичные данные
      docs/_static/run-a-flow.mp4
  13. Двоичные данные
      docs/_static/run-headless-flow.mp4
  14. Двоичные данные
      docs/_static/schedule-a-flow.mp4
  15. Двоичные данные
      docs/_static/tagui-logo.png
  16. Двоичные данные
      docs/_static/text.png
  17. Двоичные данные
      docs/_static/vcredist_x86.exe
  18. 228
    0
      docs/advanced.rst
  19. 70
    0
      docs/conf.py
  20. 23
    0
      docs/dep_options.rst
  21. 114
    0
      docs/faq.rst
  22. 46
    0
      docs/index.rst
  23. 400
    0
      docs/main_concepts.rst
  24. 35
    0
      docs/make.bat
  25. 1240
    0
      docs/reference.rst
  26. 63
    0
      docs/setup.rst
  27. 24
    0
      docs/setup_troubleshooting.rst
  28. 43
    0
      docs/tools.rst
  29. 23
    0
      flows/samples/1_google.tag
  30. 19
    0
      flows/samples/2_github.tag
  31. 31
    0
      flows/samples/3_conditions.tag
  32. 13
    0
      flows/samples/4_loops.tag
  33. 12
    0
      flows/samples/5_repositories.tag
  34. 16
    0
      flows/samples/6_datatables.tag
  35. 12
    0
      flows/samples/7_newtab.tag
  36. 20
    0
      flows/samples/8_chineseflow.tag
  37. 32
    0
      flows/samples/9_lazada.tag
  38. 4
    0
      flows/samples/form_data.csv
  39. 8
    0
      flows/samples/tagui_local.csv
  40. 339
    0
      src/chrome/Resurrectio_LICENSE.GPL
  41. 41
    0
      src/chrome/background.js
  42. 23
    0
      src/chrome/control.html
  43. 95
    0
      src/chrome/control.js
  44. 33
    0
      src/chrome/manifest.json
  45. 1267
    0
      src/chrome/recorder.js
  46. 28
    0
      src/chrome/style.css
  47. 7
    0
      src/chrome/tagui.html
  48. 528
    0
      src/chrome/tagui.js
  49. Двоичные данные
      src/chrome/tagui_icon_128.png
  50. Двоичные данные
      src/chrome/tagui_icon_16.png
  51. Двоичные данные
      src/chrome/tagui_icon_48.png
  52. 66
    0
      src/end_processes
  53. 64
    0
      src/end_processes.cmd
  54. 23
    0
      src/erina
  55. 24
    0
      src/erina.cmd
  56. 32
    0
      src/installer/TagUIBundle/Bundle.wxs
  57. 69
    0
      src/installer/TagUIBundle/HyperlinkTheme.wxl
  58. 81
    0
      src/installer/TagUIBundle/HyperlinkTheme.xml
  59. 34
    0
      src/installer/TagUIBundle/TagUIBundle.sln
  60. 44
    0
      src/installer/TagUIBundle/TagUIBundle.wixproj
  61. Двоичные данные
      src/installer/TagUIBundle/TagUILogo.ico
  62. Двоичные данные
      src/installer/TagUIBundle/TagUILogo.png
  63. 52
    0
      src/installer/TagUIv6.48/ContentClass/ContentClass.csproj
  64. 37
    0
      src/installer/TagUIv6.48/InstallerClassDll/InstallerClass.Designer.cs
  65. 80
    0
      src/installer/TagUIv6.48/InstallerClassDll/InstallerClass.cs
  66. 55
    0
      src/installer/TagUIv6.48/InstallerClassDll/InstallerClassDll.csproj
  67. 36
    0
      src/installer/TagUIv6.48/InstallerClassDll/Properties/AssemblyInfo.cs
  68. 64
    0
      src/installer/TagUIv6.48/TagUIv6.48.sln
  69. 800
    0
      src/installer/TagUIv6.48/TagUIv6.48.vdproj
  70. 82
    0
      src/languages/bengali.csv
  71. 2
    0
      src/languages/build.csv
  72. 32
    0
      src/languages/build.tag
  73. 83
    0
      src/languages/chinese.csv
  74. 83
    0
      src/languages/english.csv
  75. 82
    0
      src/languages/french.csv
  76. 82
    0
      src/languages/german.csv
  77. 82
    0
      src/languages/hindi.csv
  78. 85
    0
      src/languages/hungarian.csv
  79. 82
    0
      src/languages/indonesian.csv
  80. 82
    0
      src/languages/italian.csv
  81. 82
    0
      src/languages/japanese.csv
  82. 82
    0
      src/languages/korean.csv
  83. 82
    0
      src/languages/malay.csv
  84. 84
    0
      src/languages/malayalam.csv
  85. 82
    0
      src/languages/polish.csv
  86. 82
    0
      src/languages/portuguese.csv
  87. 82
    0
      src/languages/romanian.csv
  88. 82
    0
      src/languages/russian.csv
  89. 82
    0
      src/languages/serbian.csv
  90. 82
    0
      src/languages/spanish.csv
  91. 82
    0
      src/languages/tagalog.csv
  92. 82
    0
      src/languages/tamil.csv
  93. 82
    0
      src/languages/template.csv
  94. 82
    0
      src/languages/thai.csv
  95. 82
    0
      src/languages/vietnamese.csv
  96. Двоичные данные
      src/media/TagUI Enterprise Setup v1.7.docx
  97. 174
    0
      src/media/TagUI Technical Webinar.md
  98. Двоичные данные
      src/media/find_xpath.png
  99. Двоичные данные
      src/media/flowchart.png
  100. 0
    0
      src/media/flowchart.scap

+ 176
- 0
.github/workflows/code_check.yml Просмотреть файл

@@ -0,0 +1,176 @@
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

+ 115
- 0
.github/workflows/package_release.yml Просмотреть файл

@@ -0,0 +1,115 @@
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

+ 112
- 0
.gitignore Просмотреть файл

@@ -0,0 +1,112 @@
# 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/*

+ 202
- 0
LICENSE.md Просмотреть файл

@@ -0,0 +1,202 @@

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.

+ 110
- 0
README.md Просмотреть файл

@@ -1,2 +1,112 @@
<img src="https://raw.githubusercontent.com/kelaberetiv/TagUI/master/src/media/tagui_logo.png" height="111" align="right">

# 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)&ensp;|&ensp;[Usage Guide](https://tagui.readthedocs.io/en/latest/index.html)&ensp;|&ensp;[Demos](https://github.com/aimakerspace/TagUI-Bricks)&ensp;|&ensp;[Samples](https://github.com/kelaberetiv/TagUI/tree/master/flows/samples)&ensp;|&ensp;[Slides](https://docs.google.com/presentation/d/1pltAMzr0MZsttgg1w2ORH3ontR6Q51W9/edit?usp=sharing&ouid=115132044557947023533&rtpof=true&sd=true)&ensp;|&ensp;[Podcast](https://botnirvana.org/podcast/tagui/)&ensp;|&ensp;[Video](https://www.youtube.com/watch?v=C5itbB3sCq0)&ensp;|&ensp;[Forum](https://community.aisingapore.org/groups/tagui-rpa/forum/)&ensp;|&ensp;[中文](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.

![Word Plug-in v3](https://raw.githubusercontent.com/kelaberetiv/TagUI/master/src/office/word/word_addin_v3.png)

# 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.

+ 20
- 0
docs/Makefile Просмотреть файл

@@ -0,0 +1,20 @@
# 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)

Двоичные данные
docs/_static/cmdline.gif Просмотреть файл


Двоичные данные
docs/_static/deploy-a-flow.mp4 Просмотреть файл


Двоичные данные
docs/_static/element_attributes.png Просмотреть файл


Двоичные данные
docs/_static/find_xpath.png Просмотреть файл


Двоичные данные
docs/_static/live-mode.mp4 Просмотреть файл


Двоичные данные
docs/_static/run-a-flow.mp4 Просмотреть файл


Двоичные данные
docs/_static/run-headless-flow.mp4 Просмотреть файл


Двоичные данные
docs/_static/schedule-a-flow.mp4 Просмотреть файл


Двоичные данные
docs/_static/tagui-logo.png Просмотреть файл


Двоичные данные
docs/_static/text.png Просмотреть файл


Двоичные данные
docs/_static/vcredist_x86.exe Просмотреть файл


+ 228
- 0
docs/advanced.rst Просмотреть файл

@@ -0,0 +1,228 @@
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/>`_.

+ 70
- 0
docs/conf.py Просмотреть файл

@@ -0,0 +1,70 @@
# 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)

+ 23
- 0
docs/dep_options.rst Просмотреть файл

@@ -0,0 +1,23 @@
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

+ 114
- 0
docs/faq.rst Просмотреть файл

@@ -0,0 +1,114 @@
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>`_.

+ 46
- 0
docs/index.rst Просмотреть файл

@@ -0,0 +1,46 @@
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>`.

+ 400
- 0
docs/main_concepts.rst Просмотреть файл

@@ -0,0 +1,400 @@
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()`

+ 35
- 0
docs/make.bat Просмотреть файл

@@ -0,0 +1,35 @@
@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

+ 1240
- 0
docs/reference.rst
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 63
- 0
docs/setup.rst Просмотреть файл

@@ -0,0 +1,63 @@
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! 🎉

+ 24
- 0
docs/setup_troubleshooting.rst Просмотреть файл

@@ -0,0 +1,24 @@
.. _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>`_

+ 43
- 0
docs/tools.rst Просмотреть файл

@@ -0,0 +1,43 @@
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

+ 23
- 0
flows/samples/1_google.tag Просмотреть файл

@@ -0,0 +1,23 @@
// 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

+ 19
- 0
flows/samples/2_github.tag Просмотреть файл

@@ -0,0 +1,19 @@
// 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

+ 31
- 0
flows/samples/3_conditions.tag Просмотреть файл

@@ -0,0 +1,31 @@
// 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

+ 13
- 0
flows/samples/4_loops.tag Просмотреть файл

@@ -0,0 +1,13 @@
// 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`

+ 12
- 0
flows/samples/5_repositories.tag Просмотреть файл

@@ -0,0 +1,12 @@
// 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`

+ 16
- 0
flows/samples/6_datatables.tag Просмотреть файл

@@ -0,0 +1,16 @@
// 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

+ 12
- 0
flows/samples/7_newtab.tag Просмотреть файл

@@ -0,0 +1,12 @@
// 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

+ 20
- 0
flows/samples/8_chineseflow.tag Просмотреть файл

@@ -0,0 +1,20 @@
// 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秒

回声 完毕

+ 32
- 0
flows/samples/9_lazada.tag Просмотреть файл

@@ -0,0 +1,32 @@
// 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

+ 4
- 0
flows/samples/form_data.csv Просмотреть файл

@@ -0,0 +1,4 @@
#,firstname,lastname
1,tony,stark
2,bruce,wayne
3,peter,parker

+ 8
- 0
flows/samples/tagui_local.csv Просмотреть файл

@@ -0,0 +1,8 @@
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

+ 339
- 0
src/chrome/Resurrectio_LICENSE.GPL Просмотреть файл

@@ -0,0 +1,339 @@
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.

+ 41
- 0
src/chrome/background.js Просмотреть файл

@@ -0,0 +1,41 @@
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});
}
});

+ 23
- 0
src/chrome/control.html Просмотреть файл

@@ -0,0 +1,23 @@
<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>

+ 95
- 0
src/chrome/control.js Просмотреть файл

@@ -0,0 +1,95 @@
//-----------------------------------------------
// 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();
}

+ 33
- 0
src/chrome/manifest.json Просмотреть файл

@@ -0,0 +1,33 @@
{
"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'"
}

+ 1267
- 0
src/chrome/recorder.js
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 28
- 0
src/chrome/style.css Просмотреть файл

@@ -0,0 +1,28 @@
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;
}

+ 7
- 0
src/chrome/tagui.html Просмотреть файл

@@ -0,0 +1,7 @@
<html>
<head>
<title>TagUI Renderer</title>
<script src="tagui.js"></script>
</head>
<body></body>
</html>

+ 528
- 0
src/chrome/tagui.js Просмотреть файл

@@ -0,0 +1,528 @@
// --------------------------------------------------------------------------------
// 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);
});
};

Двоичные данные
src/chrome/tagui_icon_128.png Просмотреть файл


Двоичные данные
src/chrome/tagui_icon_16.png Просмотреть файл


Двоичные данные
src/chrome/tagui_icon_48.png Просмотреть файл


+ 66
- 0
src/end_processes Просмотреть файл

@@ -0,0 +1,66 @@
#!/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

+ 64
- 0
src/end_processes.cmd Просмотреть файл

@@ -0,0 +1,64 @@
@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
)

+ 23
- 0
src/erina Просмотреть файл

@@ -0,0 +1,23 @@
#!/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"

+ 24
- 0
src/erina.cmd Просмотреть файл

@@ -0,0 +1,24 @@
@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%"

+ 32
- 0
src/installer/TagUIBundle/Bundle.wxs Просмотреть файл

@@ -0,0 +1,32 @@
<?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>

+ 69
- 0
src/installer/TagUIBundle/HyperlinkTheme.wxl Просмотреть файл

@@ -0,0 +1,69 @@
<?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">&amp;Close</String>
<String Id="InstallLicenseLinkText">[WixBundleName] &lt;a href="#"&gt;license terms&lt;/a&gt;.</String>
<String Id="InstallAcceptCheckbox">I &amp;agree to the license terms and conditions</String>
<String Id="InstallOptionsButton">&amp;Options</String>
<String Id="InstallInstallButton">&amp;Install</String>
<String Id="InstallCloseButton">&amp;Close</String>
<String Id="OptionsHeader">Setup Options</String>
<String Id="OptionsLocationLabel">Install location:</String>
<String Id="OptionsBrowseButton">&amp;Browse</String>
<String Id="OptionsOkButton">&amp;OK</String>
<String Id="OptionsCancelButton">&amp;Cancel</String>
<String Id="ProgressHeader">Setup Progress</String>
<String Id="ProgressLabel">Processing:</String>
<String Id="OverallProgressPackageText">Initializing...</String>
<String Id="ProgressCancelButton">&amp;Cancel</String>
<String Id="ModifyHeader">Modify Setup</String>
<String Id="ModifyRepairButton">&amp;Repair</String>
<String Id="ModifyUninstallButton">&amp;Uninstall</String>
<String Id="ModifyCloseButton">&amp;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">&amp;Launch</String>
<String Id="SuccessRestartText">You must restart your computer before you can use the software.</String>
<String Id="SuccessRestartButton">&amp;Restart</String>
<String Id="SuccessCloseButton">&amp;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 &lt;a href="#"&gt;log file&lt;/a&gt;.</String>
<String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String>
<String Id="FailureRestartButton">&amp;Restart</String>
<String Id="FailureCloseButton">&amp;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 &amp;applications and attempt to restart them.</String>
<String Id="FilesInUseDontCloseRadioButton">&amp;Do not close applications. A reboot will be required.</String>
<String Id="FilesInUseOkButton">&amp;OK</String>
<String Id="FilesInUseCancelButton">&amp;Cancel</String>
<String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
</WixLocalization>

+ 81
- 0
src/installer/TagUIBundle/HyperlinkTheme.xml Просмотреть файл

@@ -0,0 +1,81 @@
<?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>

+ 34
- 0
src/installer/TagUIBundle/TagUIBundle.sln Просмотреть файл

@@ -0,0 +1,34 @@

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

+ 44
- 0
src/installer/TagUIBundle/TagUIBundle.wixproj Просмотреть файл

@@ -0,0 +1,44 @@
<?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>

Двоичные данные
src/installer/TagUIBundle/TagUILogo.ico Просмотреть файл


Двоичные данные
src/installer/TagUIBundle/TagUILogo.png Просмотреть файл


+ 52
- 0
src/installer/TagUIv6.48/ContentClass/ContentClass.csproj Просмотреть файл

@@ -0,0 +1,52 @@
<?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>

+ 37
- 0
src/installer/TagUIv6.48/InstallerClassDll/InstallerClass.Designer.cs Просмотреть файл

@@ -0,0 +1,37 @@

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
}
}

+ 80
- 0
src/installer/TagUIv6.48/InstallerClassDll/InstallerClass.cs Просмотреть файл

@@ -0,0 +1,80 @@
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);
}
}
}
}

+ 55
- 0
src/installer/TagUIv6.48/InstallerClassDll/InstallerClassDll.csproj Просмотреть файл

@@ -0,0 +1,55 @@
<?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>

+ 36
- 0
src/installer/TagUIv6.48/InstallerClassDll/Properties/AssemblyInfo.cs Просмотреть файл

@@ -0,0 +1,36 @@
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")]

+ 64
- 0
src/installer/TagUIv6.48/TagUIv6.48.sln Просмотреть файл

@@ -0,0 +1,64 @@

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

+ 800
- 0
src/installer/TagUIv6.48/TagUIv6.48.vdproj Просмотреть файл

@@ -0,0 +1,800 @@
"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"
{
}
}
}
}
}

+ 82
- 0
src/languages/bengali.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 2
- 0
src/languages/build.csv Просмотреть файл

@@ -0,0 +1,2 @@
#,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

+ 32
- 0
src/languages/build.tag Просмотреть файл

@@ -0,0 +1,32 @@
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

+ 83
- 0
src/languages/chinese.csv Просмотреть файл

@@ -0,0 +1,83 @@
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()

+ 83
- 0
src/languages/english.csv Просмотреть файл

@@ -0,0 +1,83 @@
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()

+ 82
- 0
src/languages/french.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 82
- 0
src/languages/german.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 82
- 0
src/languages/hindi.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 85
- 0
src/languages/hungarian.csv Просмотреть файл

@@ -0,0 +1,85 @@
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()

+ 82
- 0
src/languages/indonesian.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 82
- 0
src/languages/italian.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 82
- 0
src/languages/japanese.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 82
- 0
src/languages/korean.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 82
- 0
src/languages/malay.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 84
- 0
src/languages/malayalam.csv Просмотреть файл

@@ -0,0 +1,84 @@
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()

+ 82
- 0
src/languages/polish.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 82
- 0
src/languages/portuguese.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 82
- 0
src/languages/romanian.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 82
- 0
src/languages/russian.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 82
- 0
src/languages/serbian.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 82
- 0
src/languages/spanish.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 82
- 0
src/languages/tagalog.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 82
- 0
src/languages/tamil.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 82
- 0
src/languages/template.csv Просмотреть файл

@@ -0,0 +1,82 @@
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(),

+ 82
- 0
src/languages/thai.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

+ 82
- 0
src/languages/vietnamese.csv Просмотреть файл

@@ -0,0 +1,82 @@
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()

Двоичные данные
src/media/TagUI Enterprise Setup v1.7.docx Просмотреть файл


+ 174
- 0
src/media/TagUI Technical Webinar.md Просмотреть файл

@@ -0,0 +1,174 @@
# 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`
```

Двоичные данные
src/media/find_xpath.png Просмотреть файл


Двоичные данные
src/media/flowchart.png Просмотреть файл


+ 0
- 0
src/media/flowchart.scap Просмотреть файл


Некоторые файлы не были показаны из-за большого количества измененных файлов

Загрузка…
Отмена
Сохранить