Compare commits
139 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
f56f934514
|
|||
|
c9aaad376b
|
|||
|
3ebd2478fe
|
|||
|
b3fbaa1d97
|
|||
|
94da974373
|
|||
|
fd76d3ce59
|
|||
|
7c5420d279
|
|||
|
c2ab89457b
|
|||
|
8f87fae452
|
|||
|
d5c9c3550a
|
|||
|
b654cc3469
|
|||
|
fdb99d57d6
|
|||
|
e3e611d47b
|
|||
|
b8ef37188c
|
|||
|
f8d68789fc
|
|||
|
e0c9df41d7
|
|||
|
1363ed4f8a
|
|||
|
3e914b7a99
|
|||
|
d690256369
|
|||
|
18c37feed8
|
|||
|
d21a8721cf
|
|||
|
d0192d9a72
|
|||
|
684963bc2b
|
|||
|
220b995f28
|
|||
|
998d706bf7
|
|||
|
f4a394bd3b
|
|||
|
898bbe4827
|
|||
|
66b69d5629
|
|||
|
818729d6ed
|
|||
|
33a2a90eb1
|
|||
|
2ff6c193c9
|
|||
|
647ce980b4
|
|||
|
f557c5aff6
|
|||
|
2e67915bb6
|
|||
|
cce142d636
|
|||
|
e398e1acc4
|
|||
|
5c6756d98f
|
|||
|
f0ccd04718
|
|||
|
fe0545efc0
|
|||
|
15bfc1c35e
|
|||
|
a0635658bd
|
|||
|
cde7a1ab40
|
|||
|
c8d68bdb2a
|
|||
|
d18e67881c
|
|||
|
cdfccdd022
|
|||
|
44f6a002bf
|
|||
|
b85db52c77
|
|||
|
3ebc986132
|
|||
|
5973508f80
|
|||
|
9a9e4ebedf
|
|||
|
a78e3201cb
|
|||
|
fbdeea47eb
|
|||
|
761a4f187e
|
|||
|
77bb68e3a9
|
|||
|
189d913567
|
|||
|
2e9fdcf9bd
|
|||
|
f57a46cd29
|
|||
|
305abb3e47
|
|||
|
|
ef904032d7 | ||
|
|
55c1058832 | ||
|
879a9a658c
|
|||
|
893679c843
|
|||
|
f935b184d7
|
|||
|
010a440e3e
|
|||
|
51023a0e14
|
|||
|
55d5cae85f
|
|||
|
d564f064d6
|
|||
|
1750b6ff11
|
|||
|
0690e1551b
|
|||
|
d1a7460c05
|
|||
|
70e349d7e3
|
|||
|
568c3fc219
|
|||
|
f55ecae8f3
|
|||
|
e4436ad7b7
|
|||
|
67d7019a93
|
|||
|
4b45c0a2a2
|
|||
|
b3aae7b837
|
|||
|
122286bd7b
|
|||
|
6708bb17a3
|
|||
|
5fa7cd9d85
|
|||
|
25ac27dd64
|
|||
|
a659e03512
|
|||
|
4d081adda2
|
|||
|
279d48d8ee
|
|||
|
c017578631
|
|||
|
f4baade73b
|
|||
|
f68053b461
|
|||
|
ec18ceb6db
|
|||
|
68c4778ed8
|
|||
|
cf28156e70
|
|||
|
149fe89f89
|
|||
|
c124d93285
|
|||
|
06e5d42c9c
|
|||
|
c42b60a58c
|
|||
|
1e8bdcddd8
|
|||
|
90c2295bb8
|
|||
|
cca7b48d3b
|
|||
|
2d9dec2d74
|
|||
|
30741f124e
|
|||
|
f256a9db06
|
|||
|
baf850308f
|
|||
|
|
d9174d2a20 | ||
|
a5dad1e7bb
|
|||
|
aa4278e7a7
|
|||
|
4dfff72a9c
|
|||
|
624b24b1be
|
|||
|
c14f035147
|
|||
|
2d787f458d
|
|||
|
9169e5177e
|
|||
|
077c63d793
|
|||
|
2696fe05d4
|
|||
| 3d042a3739 | |||
|
|
ad57bc5f78 | ||
|
|
5f2bb97d65 | ||
|
d9cb0edebe
|
|||
|
56c2bb2e4c
|
|||
|
3326468637
|
|||
|
23eeccb5e4
|
|||
|
7cd8e4af9b
|
|||
|
a14aa856ab
|
|||
|
d80d5e37c0
|
|||
|
60c6924870
|
|||
|
c3871cd542
|
|||
| 585051e324 | |||
|
77d22521c0
|
|||
|
5f1f9f7fff
|
|||
|
f8a2bdd464
|
|||
|
6e0c6c6ce0
|
|||
|
8fd37af0d3
|
|||
|
8f71f8195e
|
|||
|
1c75f11e9f
|
|||
|
711f6b59f3
|
|||
|
568158484e
|
|||
|
81d17dd982
|
|||
|
07b34a7650
|
|||
|
10da0f4980
|
|||
|
02591c5cff
|
|||
|
1675b9b751
|
|||
|
6bf0c45277
|
@@ -3,7 +3,9 @@
|
|||||||
"projectOwner": "Aetherinox",
|
"projectOwner": "Aetherinox",
|
||||||
"repoType": "github",
|
"repoType": "github",
|
||||||
"repoHost": "https://github.com",
|
"repoHost": "https://github.com",
|
||||||
"files": ["README.md"],
|
"files": [
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
"imageSize": 40,
|
"imageSize": 40,
|
||||||
"commit": true,
|
"commit": true,
|
||||||
"commitConvention": "angular",
|
"commitConvention": "angular",
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
# #
|
# #
|
||||||
# @file .editorconfig
|
# @file .editorconfig
|
||||||
# @author Aetherinox https://github.com/Aetherinox
|
# @author Aetherinox
|
||||||
# https://git.binaryninja.net/Aetherinox
|
# @repo https://github.com/TheBinaryNinja/tvapp2
|
||||||
|
# https://git.binaryninja.net/Aetherinox
|
||||||
# @ref http://editorconfig.org
|
# @ref http://editorconfig.org
|
||||||
# #
|
# #
|
||||||
|
|
||||||
|
|||||||
8
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -14,6 +14,9 @@ body:
|
|||||||
4. Before creating this bug report, ensure you updated your applications to the latest versions.
|
4. Before creating this bug report, ensure you updated your applications to the latest versions.
|
||||||
Check your configurations to ensure there are no typos or errors.
|
Check your configurations to ensure there are no typos or errors.
|
||||||
Docker users should attempt to re-pull the TVApp2 image to ensure caching is not the cause of an issue.
|
Docker users should attempt to re-pull the TVApp2 image to ensure caching is not the cause of an issue.
|
||||||
|
5. To get detailed logs of the issue, set the environment variable:
|
||||||
|
`LOG_LEVEL=5`
|
||||||
|
Restart the docker container and you should get more detailed logs.
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
@@ -126,9 +129,9 @@ body:
|
|||||||
- type: textarea
|
- type: textarea
|
||||||
id: docker-compose
|
id: docker-compose
|
||||||
attributes:
|
attributes:
|
||||||
label: docker-compose.yml
|
label: docker-compose.yml / Run command
|
||||||
description: |
|
description: |
|
||||||
Copy / paste your `docker-compose.yml` file here
|
Copy / paste your `docker-compose.yml` file or run command here
|
||||||
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: logs
|
id: logs
|
||||||
@@ -137,6 +140,7 @@ body:
|
|||||||
description: |
|
description: |
|
||||||
Paste your docker logs here.
|
Paste your docker logs here.
|
||||||
You can get your docker logs by opening terminal and running `docker logs tvapp2`
|
You can get your docker logs by opening terminal and running `docker logs tvapp2`
|
||||||
|
To get detailed logs, set the environment variable `LOG_LEVEL=5` and restart the container.
|
||||||
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: screenshots
|
id: screenshots
|
||||||
|
|||||||
98
.github/workflows/deploy-clean.yml
vendored
@@ -12,15 +12,16 @@
|
|||||||
# secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/
|
# secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/
|
||||||
# secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/
|
# secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/
|
||||||
# secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token
|
# secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token
|
||||||
# secrets.ORG_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
# secrets.ORG_TOKEN org github personal access token (fine-grained)
|
||||||
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
# secrets.ORG_TOKEN_CL org github personal access token (classic)
|
||||||
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
# secrets.ORG_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
# secrets.ORG_BINARYNINJA_GITEA_TOKEN org gitea personal access token (classic) with package:write permission
|
# secrets.ORG_GITEA_TOKEN org gitea personal access token (classic) with package:write permission
|
||||||
# secrets.BINARYSERV_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK
|
# secrets.BOT_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK
|
||||||
# secrets.BINARYSERV_GPG_PASSPHRASE bot gpg private key passphrase
|
# secrets.BOT_GPG_PASSPHRASE bot gpg private key passphrase
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_RELEASES discord webhook to report release notifications from github to discord
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_RELEASES discord webhook to report release notifications from github to discord
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_WORKFLOWS discord webhook to report workflow notifications from github to discord
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_WORKFLOWS discord webhook to report workflow notifications from github to discord
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_UPDATES discord webhook to report activity notifications from github to discord
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_UPDATES discord webhook to report activity notifications from github to discord
|
||||||
|
#
|
||||||
#
|
#
|
||||||
# @local these workflows can be tested locally through the use of `act`
|
# @local these workflows can be tested locally through the use of `act`
|
||||||
# https://github.com/nektos/act
|
# https://github.com/nektos/act
|
||||||
@@ -32,14 +33,21 @@
|
|||||||
# act -W .github/workflows/deploy-clean.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
# act -W .github/workflows/deploy-clean.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "⚙️ Deploy › Clean"
|
# #
|
||||||
run-name: "⚙️ Deploy › Clean"
|
|
||||||
|
name: '🧹 Deployments › Clean'
|
||||||
|
run-name: '🧹 Deployments › Clean'
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# triggers
|
# triggers
|
||||||
# #
|
# #
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Trigger > Workflow Dispatch
|
||||||
|
# #
|
||||||
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
|
|
||||||
@@ -78,67 +86,6 @@ env:
|
|||||||
BOT_NAME_2: BinaryServ
|
BOT_NAME_2: BinaryServ
|
||||||
BOT_NAME_DEPENDABOT: dependabot[bot]
|
BOT_NAME_DEPENDABOT: dependabot[bot]
|
||||||
BOT_NAME_RENOVATE: renovate[bot]
|
BOT_NAME_RENOVATE: renovate[bot]
|
||||||
LABELS_JSON: |
|
|
||||||
[
|
|
||||||
{ "name": "AC › Changes Made", "color": "8F1784", "description": "Requested changes have been made and are pending a re-scan" },
|
|
||||||
{ "name": "AC › Changes Required", "color": "8F1784", "description": "Requires changes to be made to the package before being accepted" },
|
|
||||||
{ "name": "AC › Failed", "color": "a61f2d", "description": "Autocheck failed to run through a complete cycle, requires investigation" },
|
|
||||||
{ "name": "AC › Needs Rebase", "color": "8F1784", "description": "Due to the permissions on the requesting repo, this pull request must be rebased by the author" },
|
|
||||||
{ "name": "AC › Passed", "color": "146b4a", "description": "Ready to be reviewed" },
|
|
||||||
{ "name": "AC › Review Required", "color": "8F1784", "description": "PR needs to be reviewed by another person, after the requested changes have been made" },
|
|
||||||
{ "name": "AC › Security Warning", "color": "761620", "description": "Does not conform to developer policies, or includes potentially dangerous code" },
|
|
||||||
{ "name": "AC › Skipped Scan", "color": "8F1784", "description": "Author has skipped code scan" },
|
|
||||||
{ "name": "Status 𐄂 Duplicate", "color": "75536b", "description": "Issue or pull request already exists" },
|
|
||||||
{ "name": "Status 𐄂 Accepted", "color": "2e7539", "description": "This pull request has been accepted" },
|
|
||||||
{ "name": "Status 𐄂 Autoclosed", "color": "3E0915", "description": "Originally stale and was autoclosed for no activity" },
|
|
||||||
{ "name": "Status 𐄂 Denied", "color": "ba4058", "description": "Pull request has been denied" },
|
|
||||||
{ "name": "Status 𐄂 Locked", "color": "550F45", "description": "Automatically locked by EuropaServ for a prolonged period of inactivity" },
|
|
||||||
{ "name": "Status 𐄂 Need Info", "color": "2E3C4C", "description": "Not enough information to resolve" },
|
|
||||||
{ "name": "Status 𐄂 No Action", "color": "030406", "description": "Closed without any action being taken" },
|
|
||||||
{ "name": "Status 𐄂 Pending", "color": "984b12", "description": "Pending pull request" },
|
|
||||||
{ "name": "Status 𐄂 Released", "color": "1b6626", "description": "Issues or PR has been implemented and is now live" },
|
|
||||||
{ "name": "Status 𐄂 Reopened", "color": "8a6f14", "description": "A previously closed PR which has been re-opened" },
|
|
||||||
{ "name": "Status 𐄂 Review", "color": "9e1451", "description": "Currently pending review" },
|
|
||||||
{ "name": "Status 𐄂 Stale", "color": "928282", "description": "Has not had any activity in over 30 days" },
|
|
||||||
{ "name": "Type ◦ Bug", "color": "9a2c2c", "description": "Something isn't working" },
|
|
||||||
{ "name": "Type ◦ Dependency", "color": "243759", "description": "Item is associated to dependency" },
|
|
||||||
{ "name": "Type ◦ Docs", "color": "0e588d", "description": "Improvements or modifications to docs" },
|
|
||||||
{ "name": "Type ◦ Feature", "color": "3c4e93", "description": "Feature request" },
|
|
||||||
{ "name": "Type ◦ Git Action", "color": "030406", "description": "GitHub Action / workflow" },
|
|
||||||
{ "name": "Type ◦ Pull Request", "color": "8F1784", "description": "Normal pull request" },
|
|
||||||
{ "name": "Type ◦ Roadmap", "color": "8F1784", "description": "Feature or bug currently planned for implementation" },
|
|
||||||
{ "name": "Type ◦ Internal", "color": "A51994", "description": "Assigned items are for internal developer use" },
|
|
||||||
{ "name": "Build ◦ Desktop", "color": "c7ca4a", "description": "Specific to desktop" },
|
|
||||||
{ "name": "Build ◦ Linux", "color": "c7ca4a", "description": "Specific to Linux" },
|
|
||||||
{ "name": "Build ◦ MacOS", "color": "c7ca4a", "description": "Specific to MacOS" },
|
|
||||||
{ "name": "Build ◦ Mobile", "color": "c7ca4a", "description": "Specific to mobile" },
|
|
||||||
{ "name": "Build ◦ Web", "color": "c7ca4a", "description": "Specific to web" },
|
|
||||||
{ "name": "Build ◦ Windows", "color": "c7ca4a", "description": "Specific to Windows" },
|
|
||||||
{ "name": "› API", "color": "F99B50", "description": "Plugin API, CLI, browser JS API" },
|
|
||||||
{ "name": "› Auto-type", "color": "9141E0", "description": "Auto-type functionality in desktop apps" },
|
|
||||||
{ "name": "› Browser", "color": "9141E0", "description": "Browser plugins and passing data to <=> from app" },
|
|
||||||
{ "name": "› Customization", "color": "E3F0FC", "description": "Customizations: plugins, themes, configs" },
|
|
||||||
{ "name": "› Design", "color": "FA70DE", "description": "Design related queries" },
|
|
||||||
{ "name": "› Dist", "color": "FA70DE", "description": "Installers and other forms of software distribution" },
|
|
||||||
{ "name": "› Enterprise", "color": "11447a", "description": "Issues about collaboration, administration, and so on" },
|
|
||||||
{ "name": "› Hardware", "color": "5a7503", "description": "YubiKey, other tokens, biometrics" },
|
|
||||||
{ "name": "› Import/Export", "color": "F5FFCC", "description": "Import from and export to different file formats" },
|
|
||||||
{ "name": "› Improvement", "color": "185c98", "description": "Enhance an existing feature" },
|
|
||||||
{ "name": "› Performance", "color": "006b75", "description": "Web and desktop performance issues" },
|
|
||||||
{ "name": "› Plugin Request", "color": "FCE9CA", "description": "Requested changes should be implemented as a plugin" },
|
|
||||||
{ "name": "› Security", "color": "F75D39", "description": "Security issues" },
|
|
||||||
{ "name": "› Self-Hosting", "color": "fad8c7", "description": "Self-hosting installations and configs" },
|
|
||||||
{ "name": "› Storage", "color": "5319e7", "description": "Storage providers: Dropbox, Google, WebDAV, etc." },
|
|
||||||
{ "name": "› Updater", "color": "1BADDE", "description": "Auto-updater issues" },
|
|
||||||
{ "name": "› UX", "color": "1BADDE", "description": "UX and usability" },
|
|
||||||
{ "name": "› Website", "color": "fef2c0", "description": "Website related issues" },
|
|
||||||
{ "name": "⚠ Urgent", "color": "a8740e", "description": "Requires urgent attention" },
|
|
||||||
{ "name": "⚠ Announcement", "color": "DB4712", "description": "Announcements" },
|
|
||||||
{ "name": "📰 Progress Report", "color": "392297", "description": "Development updates" },
|
|
||||||
{ "name": "📦 Release", "color": "277542", "description": "Release announcements" },
|
|
||||||
{ "name": "✔️ Poll", "color": "972255", "description": "Community polls" },
|
|
||||||
{ "name": "❔ Question", "color": "FFFFFF", "description": "All questions" }
|
|
||||||
]
|
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# jobs
|
# jobs
|
||||||
@@ -146,10 +93,13 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
cleanup:
|
cleanup:
|
||||||
|
name: >-
|
||||||
|
🧹 Deployments › Clean
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
runs-on: apollo-x64
|
||||||
timeout-minutes: 20
|
timeout-minutes: 5
|
||||||
permissions: write-all
|
permissions: write-all
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
# #
|
# #
|
||||||
@@ -160,6 +110,7 @@ jobs:
|
|||||||
🕛 Get Timestamp
|
🕛 Get Timestamp
|
||||||
id: task_cleanup_set_timestamp
|
id: task_cleanup_set_timestamp
|
||||||
run: |
|
run: |
|
||||||
|
echo "YEAR=$(date +'%Y')" >> $GITHUB_ENV
|
||||||
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV
|
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV
|
||||||
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV
|
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV
|
||||||
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV
|
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV
|
||||||
@@ -202,6 +153,7 @@ jobs:
|
|||||||
git log --format="[\`%h\`](${{ github.server_url }}/${{ github.repository }}/commit/%H) %s - %an" --since=7.days >> $GITHUB_ENV
|
git log --format="[\`%h\`](${{ github.server_url }}/${{ github.repository }}/commit/%H) %s - %an" --since=7.days >> $GITHUB_ENV
|
||||||
echo 'EOF' >> $GITHUB_ENV
|
echo 'EOF' >> $GITHUB_ENV
|
||||||
|
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Cleanup › Notify Github › Success
|
# Cleanup › Notify Github › Success
|
||||||
# #
|
# #
|
||||||
|
|||||||
63
.github/workflows/deploy-docker-dockerhub.yml
vendored
@@ -280,6 +280,7 @@ jobs:
|
|||||||
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV # 02-25-2025 12:49
|
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV # 02-25-2025 12:49
|
||||||
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV # 20250225
|
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV # 20250225
|
||||||
echo "NOW_DOCKER_TS=$(date -u +'%FT%T.%3NZ')" >> $GITHUB_ENV # 2025-02-25T12:50:11.569Z
|
echo "NOW_DOCKER_TS=$(date -u +'%FT%T.%3NZ')" >> $GITHUB_ENV # 2025-02-25T12:50:11.569Z
|
||||||
|
echo "GITHUB_SHA1=`git rev-parse HEAD`" >> ${GITHUB_ENV}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Dockerhub › Install Dependencies
|
# Release › Dockerhub › Install Dependencies
|
||||||
@@ -421,6 +422,8 @@ jobs:
|
|||||||
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
org.opencontainers.image.registry=dockerhub
|
org.opencontainers.image.registry=dockerhub
|
||||||
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
org.tvapp2.image.build-release="${{ inputs.DEV_RELEASE == true && 'development' || 'stable' }}"
|
||||||
|
org.tvapp2.image.build-sha1=${GITHUB_SHA1}
|
||||||
annotations: |
|
annotations: |
|
||||||
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
@@ -431,6 +434,8 @@ jobs:
|
|||||||
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
org.opencontainers.image.registry=dockerhub
|
org.opencontainers.image.registry=dockerhub
|
||||||
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
org.tvapp2.image.build-release="${{ inputs.DEV_RELEASE == true && 'development' || 'stable' }}"
|
||||||
|
org.tvapp2.image.build-sha1=${GITHUB_SHA1}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Dockerhub › Build and Push › Amd64
|
# Release › Dockerhub › Build and Push › Amd64
|
||||||
@@ -452,8 +457,10 @@ jobs:
|
|||||||
sbom: false
|
sbom: false
|
||||||
build-args: |-
|
build-args: |-
|
||||||
ARCH=amd64
|
ARCH=amd64
|
||||||
|
RELEASE=${{ inputs.DEV_RELEASE == true && 'development' || 'stable' }}
|
||||||
VERSION=${{ env.IMAGE_VERSION }}
|
VERSION=${{ env.IMAGE_VERSION }}
|
||||||
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
||||||
|
GIT_SHA1=${{ env.GITHUB_SHA1 }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Dockerhub › Export Digest › Amd64
|
# Release › Dockerhub › Export Digest › Amd64
|
||||||
@@ -503,8 +510,10 @@ jobs:
|
|||||||
sbom: false
|
sbom: false
|
||||||
build-args: |-
|
build-args: |-
|
||||||
ARCH=arm64
|
ARCH=arm64
|
||||||
|
RELEASE=${{ inputs.DEV_RELEASE == true && 'development' || 'stable' }}
|
||||||
VERSION=${{ env.IMAGE_VERSION }}
|
VERSION=${{ env.IMAGE_VERSION }}
|
||||||
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
||||||
|
GIT_SHA1=${{ env.GITHUB_SHA1 }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Dockerhub › Export Digest › Arm64
|
# Release › Dockerhub › Export Digest › Arm64
|
||||||
@@ -534,22 +543,6 @@ jobs:
|
|||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
retention-days: 10
|
retention-days: 10
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Dockerhub › Push Manifest
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '📦 Push Manifest'
|
|
||||||
id: task_release_dh_manifest
|
|
||||||
uses: int128/docker-manifest-create-action@v2
|
|
||||||
with:
|
|
||||||
tags: |
|
|
||||||
${{ steps.task_release_dh_meta.outputs.tags }}
|
|
||||||
sources: |
|
|
||||||
${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_dh_push_amd64.outputs.digest }}
|
|
||||||
${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_dh_push_arm64.outputs.digest }}
|
|
||||||
index-annotations: |
|
|
||||||
${{ steps.task_release_dh_meta.outputs.labels }}
|
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Dockerhub › Checkpoint › Amd64
|
# Release › Dockerhub › Checkpoint › Amd64
|
||||||
# #
|
# #
|
||||||
@@ -558,23 +551,24 @@ jobs:
|
|||||||
id: task_release_dh_checkpoint
|
id: task_release_dh_checkpoint
|
||||||
run: |
|
run: |
|
||||||
echo ""
|
echo ""
|
||||||
echo "[ GITHUB ] ---------------------------------------------------------------------------------------------"
|
echo "---- [ GITHUB ] ----------------------------------------------------------------------------------------"
|
||||||
echo "github.actor.............................. ${{ github.actor }}"
|
echo "github.actor.............................. ${{ github.actor }}"
|
||||||
echo "github.ref ............................... ${{ github.ref }}"
|
echo "github.ref ............................... ${{ github.ref }}"
|
||||||
echo "github.ref_name .......................... ${{ github.ref_name }}"
|
echo "github.ref_name .......................... ${{ github.ref_name }}"
|
||||||
echo "github.event_name ........................ ${{ github.event_name }}"
|
echo "github.event_name ........................ ${{ github.event_name }}"
|
||||||
echo "github.repository_owner .................. ${{ github.repository_owner }}"
|
echo "github.repository_owner .................. ${{ github.repository_owner }}"
|
||||||
echo "github.repository ........................ ${{ github.repository }}"
|
echo "github.repository ........................ ${{ github.repository }}"
|
||||||
echo ""
|
echo "github.sha ............................... ${{ github.sha }}"
|
||||||
echo "[ INPUTS ] ---------------------------------------------------------------------------------------------"
|
echo -e ""
|
||||||
|
echo "---- [ INPUTS ] ----------------------------------------------------------------------------------------"
|
||||||
echo "inputs.IMAGE_NAME ........................ ${{ inputs.IMAGE_NAME }}"
|
echo "inputs.IMAGE_NAME ........................ ${{ inputs.IMAGE_NAME }}"
|
||||||
echo "inputs.IMAGE_VERSION ..................... ${{ inputs.IMAGE_VERSION }}"
|
echo "inputs.IMAGE_VERSION ..................... ${{ inputs.IMAGE_VERSION }}"
|
||||||
echo "inputs.IMAGE_DOCKERHUB_AUTHOR ............ ${{ inputs.IMAGE_DOCKERHUB_AUTHOR }}"
|
echo "inputs.IMAGE_DOCKERHUB_AUTHOR ............ ${{ inputs.IMAGE_DOCKERHUB_AUTHOR }}"
|
||||||
echo "inputs.IMAGE_DOCKERHUB_USERNAME .......... ${{ inputs.IMAGE_DOCKERHUB_USERNAME }}"
|
echo "inputs.IMAGE_DOCKERHUB_USERNAME .......... ${{ inputs.IMAGE_DOCKERHUB_USERNAME }}"
|
||||||
echo "inputs.DEV_RELEASE ....................... ${{ inputs.DEV_RELEASE }}"
|
echo "inputs.DEV_RELEASE ....................... ${{ inputs.DEV_RELEASE }}"
|
||||||
echo "inputs.DRY_RUN ........................... ${{ inputs.DRY_RUN }}"
|
echo "inputs.DRY_RUN ........................... ${{ inputs.DRY_RUN }}"
|
||||||
echo ""
|
echo -e ""
|
||||||
echo "[ ENV ] ------------------------------------------------------------------------------------------------"
|
echo "---- [ ENV ] -------------------------------------------------------------------------------------------"
|
||||||
echo "env.IMAGE_NAME ........................... ${{ env.IMAGE_NAME }}"
|
echo "env.IMAGE_NAME ........................... ${{ env.IMAGE_NAME }}"
|
||||||
echo "env.IMAGE_VERSION ........................ ${{ env.IMAGE_VERSION }}"
|
echo "env.IMAGE_VERSION ........................ ${{ env.IMAGE_VERSION }}"
|
||||||
echo "env.IMAGE_VERSION_1DIGIT ................. ${{ env.IMAGE_VERSION_1DIGIT }}"
|
echo "env.IMAGE_VERSION_1DIGIT ................. ${{ env.IMAGE_VERSION_1DIGIT }}"
|
||||||
@@ -589,22 +583,39 @@ jobs:
|
|||||||
echo "env.REGISTRY_REPO_ORG_AUTHOR_LC .......... ${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}"
|
echo "env.REGISTRY_REPO_ORG_AUTHOR_LC .......... ${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}"
|
||||||
echo "env.REGISTRY_REPO_AUTHOR_LC .............. ${{ env.REGISTRY_REPO_AUTHOR_LC }}"
|
echo "env.REGISTRY_REPO_AUTHOR_LC .............. ${{ env.REGISTRY_REPO_AUTHOR_LC }}"
|
||||||
echo "env.DOCKER_SHA ........................... ${{ env.DOCKER_SHA }}"
|
echo "env.DOCKER_SHA ........................... ${{ env.DOCKER_SHA }}"
|
||||||
echo ""
|
echo "env.GITHUB_SHA1 .......................... ${{ env.GITHUB_SHA1 }}"
|
||||||
echo "[ DOCKER IMAGES ] --------------------------------------------------------------------------------------"
|
echo -e ""
|
||||||
|
echo "---- [ DOCKER IMAGES ] ---------------------------------------------------------------------------------"
|
||||||
echo "registry ................................. Dockerhub"
|
echo "registry ................................. Dockerhub"
|
||||||
echo "tags ..................................... ${{ steps.task_release_dh_meta.outputs.tags }}"
|
echo "tags ..................................... ${{ steps.task_release_dh_meta.outputs.tags }}"
|
||||||
echo "labels ................................... ${{ steps.task_release_dh_meta.outputs.labels }}"
|
echo "labels ................................... ${{ steps.task_release_dh_meta.outputs.labels }}"
|
||||||
echo "digest ................................... ${{ steps.task_release_dh_push_amd64.outputs.digest }}"
|
echo "digest ................................... ${{ steps.task_release_dh_push_amd64.outputs.digest }}"
|
||||||
echo ""
|
echo -e ""
|
||||||
echo "(release) tags ........................... ${{ steps.task_release_dh_meta.outputs.tags }}"
|
echo "(release) tags ........................... ${{ steps.task_release_dh_meta.outputs.tags }}"
|
||||||
echo "(release) labels ......................... ${{ steps.task_release_dh_meta.outputs.labels }}"
|
echo "(release) labels ......................... ${{ steps.task_release_dh_meta.outputs.labels }}"
|
||||||
echo ""
|
echo -e ""
|
||||||
echo "[ DOCKER DIGESTS ] -------------------------------------------------------------------------------------"
|
echo "---- [ DOCKER DIGESTS ] --------------------------------------------------------------------------------"
|
||||||
echo "docker image id (amd64) .................. ${{ steps.task_release_dh_push_amd64.outputs.imageid }}"
|
echo "docker image id (amd64) .................. ${{ steps.task_release_dh_push_amd64.outputs.imageid }}"
|
||||||
echo "docker digest (amd64) .................... ${{ steps.task_release_dh_push_amd64.outputs.digest }}"
|
echo "docker digest (amd64) .................... ${{ steps.task_release_dh_push_amd64.outputs.digest }}"
|
||||||
echo "docker image id (arm64) .................. ${{ steps.task_release_dh_push_arm64.outputs.imageid }}"
|
echo "docker image id (arm64) .................. ${{ steps.task_release_dh_push_arm64.outputs.imageid }}"
|
||||||
echo "docker digest (arm64) .................... ${{ steps.task_release_dh_push_arm64.outputs.digest }}"
|
echo "docker digest (arm64) .................... ${{ steps.task_release_dh_push_arm64.outputs.digest }}"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Dockerhub › Push Manifest
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📦 Push Manifest'
|
||||||
|
id: task_release_dh_manifest
|
||||||
|
uses: int128/docker-manifest-create-action@v2
|
||||||
|
with:
|
||||||
|
tags: |
|
||||||
|
${{ steps.task_release_dh_meta.outputs.tags }}
|
||||||
|
sources: |
|
||||||
|
${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_dh_push_amd64.outputs.digest }}
|
||||||
|
${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_dh_push_arm64.outputs.digest }}
|
||||||
|
index-annotations: |
|
||||||
|
${{ steps.task_release_dh_meta.outputs.labels }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Dockerhub › Get Weekly Commits
|
# Release › Dockerhub › Get Weekly Commits
|
||||||
# #
|
# #
|
||||||
|
|||||||
65
.github/workflows/deploy-docker-gitea.yml
vendored
@@ -292,6 +292,7 @@ jobs:
|
|||||||
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV # 02-25-2025 12:49
|
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV # 02-25-2025 12:49
|
||||||
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV # 20250225
|
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV # 20250225
|
||||||
echo "NOW_DOCKER_TS=$(date -u +'%FT%T.%3NZ')" >> $GITHUB_ENV # 2025-02-25T12:50:11.569Z
|
echo "NOW_DOCKER_TS=$(date -u +'%FT%T.%3NZ')" >> $GITHUB_ENV # 2025-02-25T12:50:11.569Z
|
||||||
|
echo "GITHUB_SHA1=`git rev-parse HEAD`" >> ${GITHUB_ENV}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Gitea › Install Dependencies
|
# Release › Gitea › Install Dependencies
|
||||||
@@ -437,6 +438,8 @@ jobs:
|
|||||||
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
org.opencontainers.image.registry=gitea
|
org.opencontainers.image.registry=gitea
|
||||||
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
org.tvapp2.image.build-release="${{ inputs.DEV_RELEASE == true && 'development' || 'stable' }}"
|
||||||
|
org.tvapp2.image.build-sha1=${GITHUB_SHA1}
|
||||||
annotations: |
|
annotations: |
|
||||||
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
@@ -447,6 +450,8 @@ jobs:
|
|||||||
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
org.opencontainers.image.registry=gitea
|
org.opencontainers.image.registry=gitea
|
||||||
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
org.tvapp2.image.build-release="${{ inputs.DEV_RELEASE == true && 'development' || 'stable' }}"
|
||||||
|
org.tvapp2.image.build-sha1=${GITHUB_SHA1}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Gitea › Meta › arm64
|
# Release › Gitea › Meta › arm64
|
||||||
@@ -485,6 +490,8 @@ jobs:
|
|||||||
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
org.opencontainers.image.registry=gitea
|
org.opencontainers.image.registry=gitea
|
||||||
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
org.tvapp2.image.build-release="${{ inputs.DEV_RELEASE == true && 'development' || 'stable' }}"
|
||||||
|
org.tvapp2.image.build-sha1=${GITHUB_SHA1}
|
||||||
annotations: |
|
annotations: |
|
||||||
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
@@ -495,6 +502,8 @@ jobs:
|
|||||||
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
org.opencontainers.image.registry=gitea
|
org.opencontainers.image.registry=gitea
|
||||||
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
org.tvapp2.image.build-release="${{ inputs.DEV_RELEASE == true && 'development' || 'stable' }}"
|
||||||
|
org.tvapp2.image.build-sha1=${GITHUB_SHA1}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Gitea › Meta › Release
|
# Release › Gitea › Meta › Release
|
||||||
@@ -576,8 +585,10 @@ jobs:
|
|||||||
sbom: false
|
sbom: false
|
||||||
build-args: |-
|
build-args: |-
|
||||||
ARCH=amd64
|
ARCH=amd64
|
||||||
|
RELEASE=${{ inputs.DEV_RELEASE == true && 'development' || 'stable' }}
|
||||||
VERSION=${{ env.IMAGE_VERSION }}
|
VERSION=${{ env.IMAGE_VERSION }}
|
||||||
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
||||||
|
GIT_SHA1=${{ env.GITHUB_SHA1 }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Gitea › Export Digest › Amd64
|
# Release › Gitea › Export Digest › Amd64
|
||||||
@@ -627,8 +638,10 @@ jobs:
|
|||||||
sbom: false
|
sbom: false
|
||||||
build-args: |-
|
build-args: |-
|
||||||
ARCH=arm64
|
ARCH=arm64
|
||||||
|
RELEASE=${{ inputs.DEV_RELEASE == true && 'development' || 'stable' }}
|
||||||
VERSION=${{ env.IMAGE_VERSION }}
|
VERSION=${{ env.IMAGE_VERSION }}
|
||||||
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
||||||
|
GIT_SHA1=${{ env.GITHUB_SHA1 }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Gitea › Export Digest › Arm64
|
# Release › Gitea › Export Digest › Arm64
|
||||||
@@ -658,22 +671,6 @@ jobs:
|
|||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
retention-days: 10
|
retention-days: 10
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Gitea › Push Manifest
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '📦 Push Manifest'
|
|
||||||
id: task_release_gi_manifest
|
|
||||||
uses: int128/docker-manifest-create-action@v2
|
|
||||||
with:
|
|
||||||
tags: |
|
|
||||||
${{ steps.task_release_gi_meta_release.outputs.tags }}
|
|
||||||
sources: |
|
|
||||||
${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gi_push_amd64.outputs.digest }}
|
|
||||||
${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gi_push_arm64.outputs.digest }}
|
|
||||||
index-annotations: |
|
|
||||||
${{ steps.task_release_gi_meta_release.outputs.labels }}
|
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Gitea › Checkpoint
|
# Release › Gitea › Checkpoint
|
||||||
# #
|
# #
|
||||||
@@ -682,15 +679,16 @@ jobs:
|
|||||||
id: task_release_gi_checkpoint
|
id: task_release_gi_checkpoint
|
||||||
run: |
|
run: |
|
||||||
echo ""
|
echo ""
|
||||||
echo "[ GITHUB ] ---------------------------------------------------------------------------------------------"
|
echo "---- [ GITHUB ] ----------------------------------------------------------------------------------------"
|
||||||
echo "github.actor.............................. ${{ github.actor }}"
|
echo "github.actor.............................. ${{ github.actor }}"
|
||||||
echo "github.ref ............................... ${{ github.ref }}"
|
echo "github.ref ............................... ${{ github.ref }}"
|
||||||
echo "github.ref_name .......................... ${{ github.ref_name }}"
|
echo "github.ref_name .......................... ${{ github.ref_name }}"
|
||||||
echo "github.event_name ........................ ${{ github.event_name }}"
|
echo "github.event_name ........................ ${{ github.event_name }}"
|
||||||
echo "github.repository_owner .................. ${{ github.repository_owner }}"
|
echo "github.repository_owner .................. ${{ github.repository_owner }}"
|
||||||
echo "github.repository ........................ ${{ github.repository }}"
|
echo "github.repository ........................ ${{ github.repository }}"
|
||||||
echo ""
|
echo "github.sha ............................... ${{ github.sha }}"
|
||||||
echo "[ INPUTS ] ---------------------------------------------------------------------------------------------"
|
echo -e ""
|
||||||
|
echo "---- [ INPUTS ] ----------------------------------------------------------------------------------------"
|
||||||
echo "inputs.IMAGE_NAME ........................ ${{ inputs.IMAGE_NAME }}"
|
echo "inputs.IMAGE_NAME ........................ ${{ inputs.IMAGE_NAME }}"
|
||||||
echo "inputs.IMAGE_VERSION ..................... ${{ inputs.IMAGE_VERSION }}"
|
echo "inputs.IMAGE_VERSION ..................... ${{ inputs.IMAGE_VERSION }}"
|
||||||
echo "inputs.IMAGE_GITEA_USERNAME .............. ${{ inputs.IMAGE_GITEA_AUTHOR }}"
|
echo "inputs.IMAGE_GITEA_USERNAME .............. ${{ inputs.IMAGE_GITEA_AUTHOR }}"
|
||||||
@@ -698,8 +696,8 @@ jobs:
|
|||||||
echo "inputs.IMAGE_GITEA_WEBSITE ............... ${{ inputs.IMAGE_GITEA_WEBSITE }}"
|
echo "inputs.IMAGE_GITEA_WEBSITE ............... ${{ inputs.IMAGE_GITEA_WEBSITE }}"
|
||||||
echo "inputs.DEV_RELEASE ....................... ${{ inputs.DEV_RELEASE }}"
|
echo "inputs.DEV_RELEASE ....................... ${{ inputs.DEV_RELEASE }}"
|
||||||
echo "inputs.DRY_RUN ........................... ${{ inputs.DRY_RUN }}"
|
echo "inputs.DRY_RUN ........................... ${{ inputs.DRY_RUN }}"
|
||||||
echo ""
|
echo -e ""
|
||||||
echo "[ ENV ] ------------------------------------------------------------------------------------------------"
|
echo "---- [ ENV ] -------------------------------------------------------------------------------------------"
|
||||||
echo "env.IMAGE_NAME ........................... ${{ env.IMAGE_NAME }}"
|
echo "env.IMAGE_NAME ........................... ${{ env.IMAGE_NAME }}"
|
||||||
echo "env.IMAGE_VERSION ........................ ${{ env.IMAGE_VERSION }}"
|
echo "env.IMAGE_VERSION ........................ ${{ env.IMAGE_VERSION }}"
|
||||||
echo "env.IMAGE_VERSION_1DIGIT ................. ${{ env.IMAGE_VERSION_1DIGIT }}"
|
echo "env.IMAGE_VERSION_1DIGIT ................. ${{ env.IMAGE_VERSION_1DIGIT }}"
|
||||||
@@ -715,8 +713,9 @@ jobs:
|
|||||||
echo "env.REGISTRY_REPO_ORG_AUTHOR_LC .......... ${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}"
|
echo "env.REGISTRY_REPO_ORG_AUTHOR_LC .......... ${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}"
|
||||||
echo "env.REGISTRY_REPO_AUTHOR_LC .............. ${{ env.REGISTRY_REPO_AUTHOR_LC }}"
|
echo "env.REGISTRY_REPO_AUTHOR_LC .............. ${{ env.REGISTRY_REPO_AUTHOR_LC }}"
|
||||||
echo "env.DOCKER_SHA ........................... ${{ env.DOCKER_SHA }}"
|
echo "env.DOCKER_SHA ........................... ${{ env.DOCKER_SHA }}"
|
||||||
echo ""
|
echo "env.GITHUB_SHA1 .......................... ${{ env.GITHUB_SHA1 }}"
|
||||||
echo "[ DOCKER IMAGES ] --------------------------------------------------------------------------------------"
|
echo -e ""
|
||||||
|
echo "---- [ DOCKER IMAGES ] ---------------------------------------------------------------------------------"
|
||||||
echo "registry ................................. Gitea"
|
echo "registry ................................. Gitea"
|
||||||
echo "(amd64) tags ............................. ${{ steps.task_release_gi_meta_amd64.outputs.tags }}"
|
echo "(amd64) tags ............................. ${{ steps.task_release_gi_meta_amd64.outputs.tags }}"
|
||||||
echo "(amd64) labels ........................... ${{ steps.task_release_gi_meta_amd64.outputs.labels }}"
|
echo "(amd64) labels ........................... ${{ steps.task_release_gi_meta_amd64.outputs.labels }}"
|
||||||
@@ -728,13 +727,29 @@ jobs:
|
|||||||
echo ""
|
echo ""
|
||||||
echo "(release) tags ........................... ${{ steps.task_release_gi_meta_release.outputs.tags }}"
|
echo "(release) tags ........................... ${{ steps.task_release_gi_meta_release.outputs.tags }}"
|
||||||
echo "(release) labels ......................... ${{ steps.task_release_gi_meta_release.outputs.labels }}"
|
echo "(release) labels ......................... ${{ steps.task_release_gi_meta_release.outputs.labels }}"
|
||||||
echo ""
|
echo -e ""
|
||||||
echo "[ DOCKER DIGESTS ] -------------------------------------------------------------------------------------"
|
echo "---- [ DOCKER DIGESTS ] --------------------------------------------------------------------------------"
|
||||||
echo "docker image id (amd64) .................. ${{ steps.task_release_gi_push_amd64.outputs.imageid }}"
|
echo "docker image id (amd64) .................. ${{ steps.task_release_gi_push_amd64.outputs.imageid }}"
|
||||||
echo "docker digest (amd64) .................... ${{ steps.task_release_gi_push_amd64.outputs.digest }}"
|
echo "docker digest (amd64) .................... ${{ steps.task_release_gi_push_amd64.outputs.digest }}"
|
||||||
echo "docker image id (arm64) .................. ${{ steps.task_release_gi_push_arm64.outputs.imageid }}"
|
echo "docker image id (arm64) .................. ${{ steps.task_release_gi_push_arm64.outputs.imageid }}"
|
||||||
echo "docker digest (arm64) .................... ${{ steps.task_release_gi_push_arm64.outputs.digest }}"
|
echo "docker digest (arm64) .................... ${{ steps.task_release_gi_push_arm64.outputs.digest }}"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Push Manifest
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📦 Push Manifest'
|
||||||
|
id: task_release_gi_manifest
|
||||||
|
uses: int128/docker-manifest-create-action@v2
|
||||||
|
with:
|
||||||
|
tags: |
|
||||||
|
${{ steps.task_release_gi_meta_release.outputs.tags }}
|
||||||
|
sources: |
|
||||||
|
${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gi_push_amd64.outputs.digest }}
|
||||||
|
${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gi_push_arm64.outputs.digest }}
|
||||||
|
index-annotations: |
|
||||||
|
${{ steps.task_release_gi_meta_release.outputs.labels }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Gitea › Get Weekly Commits
|
# Release › Gitea › Get Weekly Commits
|
||||||
# #
|
# #
|
||||||
|
|||||||
122
.github/workflows/deploy-docker-github.yml
vendored
@@ -277,6 +277,7 @@ jobs:
|
|||||||
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV # 02-25-2025 12:49
|
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV # 02-25-2025 12:49
|
||||||
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV # 20250225
|
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV # 20250225
|
||||||
echo "NOW_DOCKER_TS=$(date -u +'%FT%T.%3NZ')" >> $GITHUB_ENV # 2025-02-25T12:50:11.569Z
|
echo "NOW_DOCKER_TS=$(date -u +'%FT%T.%3NZ')" >> $GITHUB_ENV # 2025-02-25T12:50:11.569Z
|
||||||
|
echo "GITHUB_SHA1=`git rev-parse HEAD`" >> ${GITHUB_ENV}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Github › Install Dependencies
|
# Release › Github › Install Dependencies
|
||||||
@@ -419,6 +420,8 @@ jobs:
|
|||||||
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
org.opencontainers.image.registry=github
|
org.opencontainers.image.registry=github
|
||||||
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
org.tvapp2.image.build-release="${{ inputs.DEV_RELEASE == true && 'development' || 'stable' }}"
|
||||||
|
org.tvapp2.image.build-sha1=${GITHUB_SHA1}
|
||||||
annotations: |
|
annotations: |
|
||||||
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
@@ -429,6 +432,8 @@ jobs:
|
|||||||
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
org.opencontainers.image.registry=github
|
org.opencontainers.image.registry=github
|
||||||
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
org.tvapp2.image.build-release="${{ inputs.DEV_RELEASE == true && 'development' || 'stable' }}"
|
||||||
|
org.tvapp2.image.build-sha1=${GITHUB_SHA1}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Github › Build and Push › Amd64
|
# Release › Github › Build and Push › Amd64
|
||||||
@@ -455,8 +460,10 @@ jobs:
|
|||||||
sbom: false
|
sbom: false
|
||||||
build-args: |-
|
build-args: |-
|
||||||
ARCH=amd64
|
ARCH=amd64
|
||||||
|
RELEASE=${{ inputs.DEV_RELEASE == true && 'development' || 'stable' }}
|
||||||
VERSION=${{ env.IMAGE_VERSION }}
|
VERSION=${{ env.IMAGE_VERSION }}
|
||||||
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
||||||
|
GIT_SHA1=${{ env.GITHUB_SHA1 }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Github › Export Digest › Amd64
|
# Release › Github › Export Digest › Amd64
|
||||||
@@ -511,8 +518,10 @@ jobs:
|
|||||||
sbom: false
|
sbom: false
|
||||||
build-args: |-
|
build-args: |-
|
||||||
ARCH=arm64
|
ARCH=arm64
|
||||||
|
RELEASE=${{ inputs.DEV_RELEASE == true && 'development' || 'stable' }}
|
||||||
VERSION=${{ env.IMAGE_VERSION }}
|
VERSION=${{ env.IMAGE_VERSION }}
|
||||||
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
||||||
|
GIT_SHA1=${{ env.GITHUB_SHA1 }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Github › Export Digest › Arm64
|
# Release › Github › Export Digest › Arm64
|
||||||
@@ -542,6 +551,63 @@ jobs:
|
|||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
retention-days: 10
|
retention-days: 10
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Github › Checkpoint
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '⚠️ Checkpoint'
|
||||||
|
id: task_release_gh_checkpoint
|
||||||
|
run: |
|
||||||
|
echo ""
|
||||||
|
echo "---- [ GITHUB ] ----------------------------------------------------------------------------------------"
|
||||||
|
echo "github.actor.............................. ${{ github.actor }}"
|
||||||
|
echo "github.ref ............................... ${{ github.ref }}"
|
||||||
|
echo "github.ref_name .......................... ${{ github.ref_name }}"
|
||||||
|
echo "github.event_name ........................ ${{ github.event_name }}"
|
||||||
|
echo "github.repository_owner .................. ${{ github.repository_owner }}"
|
||||||
|
echo "github.repository ........................ ${{ github.repository }}"
|
||||||
|
echo "github.sha ............................... ${{ github.sha }}"
|
||||||
|
echo -e ""
|
||||||
|
echo "---- [ INPUTS ] ----------------------------------------------------------------------------------------"
|
||||||
|
echo "inputs.IMAGE_NAME ........................ ${{ inputs.IMAGE_NAME }}"
|
||||||
|
echo "inputs.IMAGE_VERSION ..................... ${{ inputs.IMAGE_VERSION }}"
|
||||||
|
echo "inputs.IMAGE_GHCR_AUTHOR ................. ${{ inputs.IMAGE_GHCR_AUTHOR }}"
|
||||||
|
echo "inputs.IMAGE_GHCR_USERNAME ............... ${{ inputs.IMAGE_GHCR_USERNAME }}"
|
||||||
|
echo "inputs.DEV_RELEASE ....................... ${{ inputs.DEV_RELEASE }}"
|
||||||
|
echo "inputs.DRY_RUN ........................... ${{ inputs.DRY_RUN }}"
|
||||||
|
echo -e ""
|
||||||
|
echo "---- [ ENV ] -------------------------------------------------------------------------------------------"
|
||||||
|
echo "env.IMAGE_NAME ........................... ${{ env.IMAGE_NAME }}"
|
||||||
|
echo "env.IMAGE_VERSION ........................ ${{ env.IMAGE_VERSION }}"
|
||||||
|
echo "env.IMAGE_VERSION_1DIGIT ................. ${{ env.IMAGE_VERSION_1DIGIT }}"
|
||||||
|
echo "env.IMAGE_VERSION_2DIGIT ................. ${{ env.IMAGE_VERSION_2DIGIT }}"
|
||||||
|
echo "env.IMAGE_GHCR_AUTHOR .................... ${{ env.IMAGE_GHCR_AUTHOR }}"
|
||||||
|
echo "env.IMAGE_GHCR_USERNAME .................. ${{ env.IMAGE_GHCR_USERNAME }}"
|
||||||
|
echo "env.NOW .................................. ${{ env.NOW }}"
|
||||||
|
echo "env.NOW_SHORT ............................ ${{ env.NOW_SHORT }}"
|
||||||
|
echo "env.NOW_LONG ............................. ${{ env.NOW_LONG }}"
|
||||||
|
echo "env.NOW_DOCKER_LABEL ..................... ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
echo "env.NOW_DOCKER_TS ........................ ${{ env.NOW_DOCKER_TS }}"
|
||||||
|
echo "env.REGISTRY_REPO_ORG_AUTHOR_LC .......... ${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}"
|
||||||
|
echo "env.REGISTRY_REPO_AUTHOR_LC .............. ${{ env.REGISTRY_REPO_AUTHOR_LC }}"
|
||||||
|
echo "env.DOCKER_SHA ........................... ${{ env.DOCKER_SHA }}"
|
||||||
|
echo "env.GITHUB_SHA1 .......................... ${{ env.GITHUB_SHA1 }}"
|
||||||
|
echo -e ""
|
||||||
|
echo "---- [ DOCKER IMAGES ] ---------------------------------------------------------------------------------"
|
||||||
|
echo "registry ................................. Github GHCR"
|
||||||
|
echo "tags ..................................... ${{ steps.task_release_gh_meta.outputs.tags }}"
|
||||||
|
echo "labels ................................... ${{ steps.task_release_gh_meta.outputs.labels }}"
|
||||||
|
echo "digest ................................... ${{ steps.task_release_gh_push_amd64.outputs.digest }}"
|
||||||
|
echo -e ""
|
||||||
|
echo "(release) tags ........................... ${{ steps.task_release_gh_meta.outputs.tags }}"
|
||||||
|
echo "(release) labels ......................... ${{ steps.task_release_gh_meta.outputs.labels }}"
|
||||||
|
echo -e ""
|
||||||
|
echo "---- [ DOCKER DIGESTS ] --------------------------------------------------------------------------------"
|
||||||
|
echo "docker image id (amd64) .................. ${{ steps.task_release_gh_push_amd64.outputs.imageid }}"
|
||||||
|
echo "docker digest (amd64) .................... ${{ steps.task_release_gh_push_amd64.outputs.digest }}"
|
||||||
|
echo "docker image id (arm64) .................. ${{ steps.task_release_gh_push_arm64.outputs.imageid }}"
|
||||||
|
echo "docker digest (arm64) .................... ${{ steps.task_release_gh_push_arm64.outputs.digest }}"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Github › Push Manifest
|
# Release › Github › Push Manifest
|
||||||
# #
|
# #
|
||||||
@@ -559,62 +625,6 @@ jobs:
|
|||||||
index-annotations: |
|
index-annotations: |
|
||||||
${{ steps.task_release_gh_meta.outputs.labels }}
|
${{ steps.task_release_gh_meta.outputs.labels }}
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Github › Checkpoint
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '⚠️ Checkpoint'
|
|
||||||
id: task_release_gh_checkpoint
|
|
||||||
run: |
|
|
||||||
echo ""
|
|
||||||
echo "[ GITHUB ] ---------------------------------------------------------------------------------------------"
|
|
||||||
echo "github.actor.............................. ${{ github.actor }}"
|
|
||||||
echo "github.ref ............................... ${{ github.ref }}"
|
|
||||||
echo "github.ref_name .......................... ${{ github.ref_name }}"
|
|
||||||
echo "github.event_name ........................ ${{ github.event_name }}"
|
|
||||||
echo "github.repository_owner .................. ${{ github.repository_owner }}"
|
|
||||||
echo "github.repository ........................ ${{ github.repository }}"
|
|
||||||
echo ""
|
|
||||||
echo "[ INPUTS ] ---------------------------------------------------------------------------------------------"
|
|
||||||
echo "inputs.IMAGE_NAME ........................ ${{ inputs.IMAGE_NAME }}"
|
|
||||||
echo "inputs.IMAGE_VERSION ..................... ${{ inputs.IMAGE_VERSION }}"
|
|
||||||
echo "inputs.IMAGE_GHCR_AUTHOR ................. ${{ inputs.IMAGE_GHCR_AUTHOR }}"
|
|
||||||
echo "inputs.IMAGE_GHCR_USERNAME ............... ${{ inputs.IMAGE_GHCR_USERNAME }}"
|
|
||||||
echo "inputs.DEV_RELEASE ....................... ${{ inputs.DEV_RELEASE }}"
|
|
||||||
echo "inputs.DRY_RUN ........................... ${{ inputs.DRY_RUN }}"
|
|
||||||
echo ""
|
|
||||||
echo "[ ENV ] ------------------------------------------------------------------------------------------------"
|
|
||||||
echo "env.IMAGE_NAME ........................... ${{ env.IMAGE_NAME }}"
|
|
||||||
echo "env.IMAGE_VERSION ........................ ${{ env.IMAGE_VERSION }}"
|
|
||||||
echo "env.IMAGE_VERSION_1DIGIT ................. ${{ env.IMAGE_VERSION_1DIGIT }}"
|
|
||||||
echo "env.IMAGE_VERSION_2DIGIT ................. ${{ env.IMAGE_VERSION_2DIGIT }}"
|
|
||||||
echo "env.IMAGE_GHCR_AUTHOR .................... ${{ env.IMAGE_GHCR_AUTHOR }}"
|
|
||||||
echo "env.IMAGE_GHCR_USERNAME .................. ${{ env.IMAGE_GHCR_USERNAME }}"
|
|
||||||
echo "env.NOW .................................. ${{ env.NOW }}"
|
|
||||||
echo "env.NOW_SHORT ............................ ${{ env.NOW_SHORT }}"
|
|
||||||
echo "env.NOW_LONG ............................. ${{ env.NOW_LONG }}"
|
|
||||||
echo "env.NOW_DOCKER_LABEL ..................... ${{ env.NOW_DOCKER_LABEL }}"
|
|
||||||
echo "env.NOW_DOCKER_TS ........................ ${{ env.NOW_DOCKER_TS }}"
|
|
||||||
echo "env.DOCKER_IMAGE ......................... ${{ env.DOCKER_IMAGE }}"
|
|
||||||
echo "env.REGISTRY_REPO_ORG_AUTHOR_LC .......... ${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}"
|
|
||||||
echo "env.REGISTRY_REPO_AUTHOR_LC .............. ${{ env.REGISTRY_REPO_AUTHOR_LC }}"
|
|
||||||
echo "env.DOCKER_SHA ........................... ${{ env.DOCKER_SHA }}"
|
|
||||||
echo ""
|
|
||||||
echo "[ DOCKER IMAGES ] --------------------------------------------------------------------------------------"
|
|
||||||
echo "registry ................................. Github GHCR"
|
|
||||||
echo "tags ..................................... ${{ steps.task_release_gh_meta.outputs.tags }}"
|
|
||||||
echo "labels ................................... ${{ steps.task_release_gh_meta.outputs.labels }}"
|
|
||||||
echo "digest ................................... ${{ steps.task_release_gh_push_amd64.outputs.digest }}"
|
|
||||||
echo ""
|
|
||||||
echo "(release) tags ........................... ${{ steps.task_release_gh_meta.outputs.tags }}"
|
|
||||||
echo "(release) labels ......................... ${{ steps.task_release_gh_meta.outputs.labels }}"
|
|
||||||
echo ""
|
|
||||||
echo "[ DOCKER DIGESTS ] -------------------------------------------------------------------------------------"
|
|
||||||
echo "docker image id (amd64) .................. ${{ steps.task_release_gh_push_amd64.outputs.imageid }}"
|
|
||||||
echo "docker digest (amd64) .................... ${{ steps.task_release_gh_push_amd64.outputs.digest }}"
|
|
||||||
echo "docker image id (arm64) .................. ${{ steps.task_release_gh_push_arm64.outputs.imageid }}"
|
|
||||||
echo "docker digest (arm64) .................... ${{ steps.task_release_gh_push_arm64.outputs.digest }}"
|
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Github › Get Weekly Commits
|
# Release › Github › Get Weekly Commits
|
||||||
# #
|
# #
|
||||||
|
|||||||
62
.github/workflows/documentation.yml
vendored
@@ -43,13 +43,55 @@ run-name: "📒 Docs › Build"
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Trigger › Release
|
||||||
|
#
|
||||||
|
# update documentation every time a release is made
|
||||||
|
# #
|
||||||
|
|
||||||
release:
|
release:
|
||||||
types:
|
types:
|
||||||
- published
|
- published
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Trigger › Push
|
||||||
|
#
|
||||||
|
# update documentation every time a file in docs/ folder is modified
|
||||||
|
# #
|
||||||
|
|
||||||
push:
|
push:
|
||||||
paths:
|
paths:
|
||||||
- docs/**
|
- docs/**
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Trigger › Workflow Dispatch
|
||||||
|
#
|
||||||
|
# If any values are not provided, will use fallback env variable
|
||||||
|
# #
|
||||||
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Image Name
|
||||||
|
#
|
||||||
|
# used in github image path
|
||||||
|
# ghcr.io/${{ env.IMAGE_GHCR_AUTHOR }}/${{ env.IMAGE_NAME }}
|
||||||
|
# #
|
||||||
|
|
||||||
|
WORKING_DIR:
|
||||||
|
description: '📁 Docs Folder'
|
||||||
|
required: true
|
||||||
|
default: './docs/site'
|
||||||
|
type: string
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Trigger › Cron
|
||||||
|
#
|
||||||
|
# update documentation every X hours
|
||||||
|
# #
|
||||||
|
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 */12 * * *"
|
- cron: "0 */12 * * *"
|
||||||
|
|
||||||
@@ -58,11 +100,12 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
env:
|
env:
|
||||||
ASSIGN_USER: Aetherinox
|
WORKING_DIR: ${{ github.event.inputs.WORKING_DIR || './docs/site' }}
|
||||||
BOT_NAME_1: EuropaServ
|
ASSIGN_USER: Aetherinox
|
||||||
BOT_NAME_2: BinaryServ
|
BOT_NAME_1: EuropaServ
|
||||||
BOT_NAME_DEPENDABOT: dependabot[bot]
|
BOT_NAME_2: BinaryServ
|
||||||
BOT_NAME_RENOVATE: renovate[bot]
|
BOT_NAME_DEPENDABOT: dependabot[bot]
|
||||||
|
BOT_NAME_RENOVATE: renovate[bot]
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# jobs
|
# jobs
|
||||||
@@ -106,7 +149,8 @@ jobs:
|
|||||||
# Documentation › Setup Python
|
# Documentation › Setup Python
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "🐍 Setup Python"
|
- name: >-
|
||||||
|
🐍 Setup Python
|
||||||
id: task_docs_python_setup
|
id: task_docs_python_setup
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
@@ -128,6 +172,7 @@ jobs:
|
|||||||
pip install mkdocs
|
pip install mkdocs
|
||||||
pip install mkdocs-material
|
pip install mkdocs-material
|
||||||
pip install mike
|
pip install mike
|
||||||
|
pip install mkdocs-embed-external-markdown
|
||||||
pip install mkdocs-git-committers-plugin-2
|
pip install mkdocs-git-committers-plugin-2
|
||||||
pip install mkdocs-encryptcontent-plugin
|
pip install mkdocs-encryptcontent-plugin
|
||||||
pip install mkdocs-redirects mkdocs-glightbox pymdown-extensions mkdocs-git-revision-date-localized-plugin mkdocs-git-authors-plugin mkdocs-link-embeds-plugin
|
pip install mkdocs-redirects mkdocs-glightbox pymdown-extensions mkdocs-git-revision-date-localized-plugin mkdocs-git-authors-plugin mkdocs-link-embeds-plugin
|
||||||
@@ -141,12 +186,13 @@ jobs:
|
|||||||
# Documentation › Deploy
|
# Documentation › Deploy
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "💽 Deploy"
|
- name: >-
|
||||||
|
💽 Deploy
|
||||||
id: task_docs_deploy
|
id: task_docs_deploy
|
||||||
uses: peaceiris/actions-gh-pages@v4
|
uses: peaceiris/actions-gh-pages@v4
|
||||||
with:
|
with:
|
||||||
personal_token: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
personal_token: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
||||||
publish_dir: ./docs/site
|
publish_dir: "${{ env.WORKING_DIR }}"
|
||||||
|
|
||||||
|
|
||||||
# #
|
# #
|
||||||
|
|||||||
230
.github/workflows/history-clean.yml
vendored
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
# #
|
||||||
|
# @type github workflow
|
||||||
|
# @author Aetherinox
|
||||||
|
# @url https://github.com/Aetherinox
|
||||||
|
# @usage cleans all commit history for a repository
|
||||||
|
# edit the 'environment:' to determine which deployment to keep clean
|
||||||
|
# - can be ran manually
|
||||||
|
#
|
||||||
|
# @secrets secrets.SELF_TOKEN self github personal access token (fine-grained)
|
||||||
|
# secrets.SELF_TOKEN_CL self github personal access token (classic)
|
||||||
|
# secrets.NPM_TOKEN self npmjs access token
|
||||||
|
# secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/
|
||||||
|
# secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/
|
||||||
|
# secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token
|
||||||
|
# secrets.ORG_TOKEN org github personal access token (fine-grained)
|
||||||
|
# secrets.ORG_TOKEN_CL org github personal access token (classic)
|
||||||
|
# secrets.ORG_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
|
# secrets.ORG_GITEA_TOKEN org gitea personal access token (classic) with package:write permission
|
||||||
|
# secrets.BOT_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK
|
||||||
|
# secrets.BOT_GPG_PASSPHRASE bot gpg private key passphrase
|
||||||
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_RELEASES discord webhook to report release notifications from github to discord
|
||||||
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_WORKFLOWS discord webhook to report workflow notifications from github to discord
|
||||||
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_UPDATES discord webhook to report activity notifications from github to discord
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# @local these workflows can be tested locally through the use of `act`
|
||||||
|
# https://github.com/nektos/act
|
||||||
|
# Extract act to folder
|
||||||
|
# Add system env var with path to act.exe
|
||||||
|
# Run the commands:
|
||||||
|
# git pull https://github.com/username/repo
|
||||||
|
# act -W .github/workflows/history-clean.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04
|
||||||
|
# act -W .github/workflows/history-clean.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
|
# #
|
||||||
|
|
||||||
|
name: '🧹 History › Clean'
|
||||||
|
run-name: '🧹 History › Clean'
|
||||||
|
|
||||||
|
# #
|
||||||
|
# triggers
|
||||||
|
# #
|
||||||
|
|
||||||
|
on:
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Trigger > Workflow Dispatch
|
||||||
|
# #
|
||||||
|
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Commit Label
|
||||||
|
#
|
||||||
|
# the label to use when repository is cleaned
|
||||||
|
# #
|
||||||
|
|
||||||
|
COMMIT_LABEL:
|
||||||
|
description: '🏷️ Commit Label'
|
||||||
|
required: true
|
||||||
|
default: 'cleanup'
|
||||||
|
type: string
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Main Branch
|
||||||
|
#
|
||||||
|
# main branch re-recreate
|
||||||
|
# #
|
||||||
|
|
||||||
|
BRANCH_MAIN:
|
||||||
|
description: '🌳 Main Branch'
|
||||||
|
required: true
|
||||||
|
default: 'main'
|
||||||
|
type: string
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Deployment Environment Name
|
||||||
|
#
|
||||||
|
# this is the name of the deployment item
|
||||||
|
# #
|
||||||
|
|
||||||
|
DEPLOYMENT_ENV:
|
||||||
|
description: '📦 Deployment Environment'
|
||||||
|
required: true
|
||||||
|
default: 'orion'
|
||||||
|
type: string
|
||||||
|
|
||||||
|
# #
|
||||||
|
# environment variables
|
||||||
|
# #
|
||||||
|
|
||||||
|
env:
|
||||||
|
COMMIT_LABEL: ${{ github.event.inputs.COMMIT_LABEL || 'cleanup' }}
|
||||||
|
BRANCH_MAIN: ${{ github.event.inputs.BRANCH_MAIN || 'main' }}
|
||||||
|
DEPLOYMENT_ENV: ${{ github.event.inputs.DEPLOYMENT_ENV || 'orion' }}
|
||||||
|
BOT_NAME_1: EuropaServ
|
||||||
|
BOT_NAME_2: BinaryServ
|
||||||
|
BOT_NAME_DEPENDABOT: dependabot[bot]
|
||||||
|
BOT_NAME_RENOVATE: renovate[bot]
|
||||||
|
|
||||||
|
# #
|
||||||
|
# jobs
|
||||||
|
# #
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
history-clean:
|
||||||
|
name: >-
|
||||||
|
🧹 History › Clean
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
runs-on: apollo-x64
|
||||||
|
timeout-minutes: 5
|
||||||
|
steps:
|
||||||
|
|
||||||
|
# #
|
||||||
|
# History › Clean › Set TImestamps
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: >-
|
||||||
|
🕛 Get Timestamp
|
||||||
|
id: task_history_clean_set_timestamp
|
||||||
|
run: |
|
||||||
|
echo "YEAR=$(date +'%Y')" >> $GITHUB_ENV
|
||||||
|
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV
|
||||||
|
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV
|
||||||
|
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV
|
||||||
|
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# #
|
||||||
|
# History › Clean › Checkout
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: >-
|
||||||
|
✅ Checkout
|
||||||
|
id: task_history_clean_gh_checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
# #
|
||||||
|
# History › Clean › Git Identify
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: >-
|
||||||
|
🪪 Configure Git Identity
|
||||||
|
id: task_history_clean_git_ident
|
||||||
|
run: |
|
||||||
|
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
git config --local user.name "github-actions[bot]"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# History › Clean › Pre-Commit
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: >-
|
||||||
|
📦 Commit › Pre-commit
|
||||||
|
id: task_history_clean_commit_pre
|
||||||
|
run: |
|
||||||
|
now=$(date -u '+%m/%d/%Y %H:%M')
|
||||||
|
commit_label="${{ env.COMMIT_LABEL }}" >> $GITHUB_ENV
|
||||||
|
echo -e "$commit_label"
|
||||||
|
commit_message="\\\`️️🧹 $commit_label 🧹\\\` \\\`$now UTC\\\`" >> $GITHUB_ENV
|
||||||
|
echo -e "$commit_message"
|
||||||
|
echo "COMMIT_MESSAGE=$(echo $commit_message)" >> $GITHUB_ENV
|
||||||
|
echo "NOW=$(echo $now)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# #
|
||||||
|
# History › Clean › Pre-Commit › Debug
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: >-
|
||||||
|
📦 Commit › Pre-commit › Debug
|
||||||
|
id: task_history_clean_commit_debug
|
||||||
|
run: |
|
||||||
|
echo -e "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――"
|
||||||
|
echo -e " Printing Values"
|
||||||
|
echo -e "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――"
|
||||||
|
echo -e " env.COMMIT_LABEL .................... ${{ env.COMMIT_LABEL }}"
|
||||||
|
echo -e " env.COMMIT_MESSAGE .................. ${{ env.COMMIT_MESSAGE }}"
|
||||||
|
echo -e " env.NOW ............................. ${{ env.NOW }}"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# History › Clean › Start
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: >-
|
||||||
|
🧹 Clean Repo History
|
||||||
|
id: task_history_clean_history
|
||||||
|
run: |
|
||||||
|
# Create a new orphan branch
|
||||||
|
git checkout --orphan temp-branch
|
||||||
|
|
||||||
|
# Add all files to the new branch
|
||||||
|
git add -A
|
||||||
|
|
||||||
|
# Commit the files to the new branch
|
||||||
|
git commit -m "${{ env.COMMIT_MESSAGE }}"
|
||||||
|
|
||||||
|
# Delete the old main branch
|
||||||
|
git branch -D ${{ env.BRANCH_MAIN }}
|
||||||
|
|
||||||
|
# Rename the new orphan branch to main
|
||||||
|
git branch -m ${{ env.BRANCH_MAIN }}
|
||||||
|
|
||||||
|
# Force push the new main branch to the remote repository
|
||||||
|
git push -f origin ${{ env.BRANCH_MAIN }}
|
||||||
|
|
||||||
|
# #
|
||||||
|
# History › Clean › References
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: >-
|
||||||
|
🗑️ Clean References
|
||||||
|
id: task_history_clean_references
|
||||||
|
run: |
|
||||||
|
# Remove remote-tracking references to deleted branches (optional)
|
||||||
|
git fetch origin --prune
|
||||||
|
|
||||||
|
git reflog expire --expire=now --all
|
||||||
|
git gc --prune=now --aggressive
|
||||||
|
|
||||||
|
# #
|
||||||
|
# History › Clean › Commit
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: >-
|
||||||
|
📦 Commit › Execute
|
||||||
|
id: task_history_clean_commit_execute
|
||||||
|
uses: stefanzweifel/git-auto-commit-action@v5
|
||||||
|
with:
|
||||||
|
commit_message: ${{ env.COMMIT_MESSAGE }}
|
||||||
779
.github/workflows/issues-new.yml
vendored
299
.github/workflows/issues-scan.yml
vendored
@@ -2,7 +2,7 @@
|
|||||||
# @type github workflow
|
# @type github workflow
|
||||||
# @author Aetherinox
|
# @author Aetherinox
|
||||||
# @url https://github.com/Aetherinox
|
# @url https://github.com/Aetherinox
|
||||||
# @desc pull request auto-scan
|
# @usage pull request auto-scan
|
||||||
# scans all of the files related to a particular pull request
|
# scans all of the files related to a particular pull request
|
||||||
# if the code in the files being submitted contains code that is forbidden,
|
# if the code in the files being submitted contains code that is forbidden,
|
||||||
# a report is generated and posted as a comment in the PR.
|
# a report is generated and posted as a comment in the PR.
|
||||||
@@ -16,15 +16,15 @@
|
|||||||
# secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/
|
# secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/
|
||||||
# secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/
|
# secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/
|
||||||
# secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token
|
# secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token
|
||||||
# secrets.ORG_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
# secrets.ORG_TOKEN org github personal access token (fine-grained)
|
||||||
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
# secrets.ORG_TOKEN_CL org github personal access token (classic)
|
||||||
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
# secrets.ORG_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
# secrets.ORG_BINARYNINJA_GITEA_TOKEN org gitea personal access token (classic) with package:write permission
|
# secrets.ORG_GITEA_TOKEN org gitea personal access token (classic) with package:write permission
|
||||||
# secrets.BINARYSERV_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK
|
# secrets.BOT_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK
|
||||||
# secrets.BINARYSERV_GPG_PASSPHRASE bot gpg private key passphrase
|
# secrets.BOT_GPG_PASSPHRASE bot gpg private key passphrase
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_RELEASES discord webhook to report release notifications from github to discord
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_RELEASES discord webhook to report release notifications from github to discord
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_WORKFLOWS discord webhook to report workflow notifications from github to discord
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_WORKFLOWS discord webhook to report workflow notifications from github to discord
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_UPDATES discord webhook to report activity notifications from github to discord
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_UPDATES discord webhook to report activity notifications from github to discord
|
||||||
#
|
#
|
||||||
# @local these workflows can be tested locally through the use of `act`
|
# @local these workflows can be tested locally through the use of `act`
|
||||||
# https://github.com/nektos/act
|
# https://github.com/nektos/act
|
||||||
@@ -36,8 +36,8 @@
|
|||||||
# act -W .github/workflows/issues-scan.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
# act -W .github/workflows/issues-scan.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "🎫 Issues › Scan"
|
name: '🎫 PR › Scan'
|
||||||
run-name: "🎫 Issues › Scan"
|
run-name: '🎫 PR › Scan'
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# triggers
|
# triggers
|
||||||
@@ -61,9 +61,9 @@ env:
|
|||||||
LABEL_CHECK_SECURITY_ERR: AC › Security Warning
|
LABEL_CHECK_SECURITY_ERR: AC › Security Warning
|
||||||
LABEL_CHECK_STATUS_CHGMADE: AC › Changes Made
|
LABEL_CHECK_STATUS_CHGMADE: AC › Changes Made
|
||||||
LABEL_CHECK_SCAN_SKIPPED: AC › Skipped Scan
|
LABEL_CHECK_SCAN_SKIPPED: AC › Skipped Scan
|
||||||
LABEL_TYPE_PR: Type ◦ Pull Request
|
LABEL_TYPE_PR: Type › Pull Request
|
||||||
LABEL_TYPE_DEPENDENCY: Type ◦ Dependency
|
LABEL_TYPE_DEPENDENCY: Type › Dependency
|
||||||
LABEL_TYPE_GITACTION: Type ◦ Git Action
|
LABEL_TYPE_GITACTION: Type › Git Action
|
||||||
|
|
||||||
ASSIGN_USER: Aetherinox
|
ASSIGN_USER: Aetherinox
|
||||||
BOT_NAME_1: EuropaServ
|
BOT_NAME_1: EuropaServ
|
||||||
@@ -73,64 +73,64 @@ env:
|
|||||||
|
|
||||||
LABELS_JSON: |
|
LABELS_JSON: |
|
||||||
[
|
[
|
||||||
{ "name": "AC › Changes Made", "color": "8F1784", "description": "Requested changes have been made and are pending a re-scan" },
|
{ "name": "AC › Changes Made", "color": "8F1784", "description": "Requested changes have been made and are pending a re-scan" },
|
||||||
{ "name": "AC › Changes Required", "color": "8F1784", "description": "Requires changes to be made to the package before being accepted" },
|
{ "name": "AC › Changes Required", "color": "8F1784", "description": "Requires changes to be made to the package before being accepted" },
|
||||||
{ "name": "AC › Failed", "color": "a61f2d", "description": "Autocheck failed to run through a complete cycle, requires investigation" },
|
{ "name": "AC › Failed", "color": "a61f2d", "description": "Autocheck failed to run through a complete cycle, requires investigation" },
|
||||||
{ "name": "AC › Needs Rebase", "color": "8F1784", "description": "Due to the permissions on the requesting repo, this pull request must be rebased by the author" },
|
{ "name": "AC › Needs Rebase", "color": "8F1784", "description": "Due to the permissions on the requesting repo, this pull request must be rebased by the author" },
|
||||||
{ "name": "AC › Passed", "color": "146b4a", "description": "Ready to be reviewed" },
|
{ "name": "AC › Passed", "color": "146b4a", "description": "Ready to be reviewed" },
|
||||||
{ "name": "AC › Review Required", "color": "8F1784", "description": "PR needs to be reviewed by another person, after the requested changes have been made" },
|
{ "name": "AC › Review Required", "color": "8F1784", "description": "PR needs to be reviewed by another person, after the requested changes have been made" },
|
||||||
{ "name": "AC › Security Warning", "color": "761620", "description": "Does not conform to developer policies, or includes potentially dangerous code" },
|
{ "name": "AC › Security Warning", "color": "761620", "description": "Does not conform to developer policies, or includes potentially dangerous code" },
|
||||||
{ "name": "AC › Skipped Scan", "color": "8F1784", "description": "Author has skipped code scan" },
|
{ "name": "AC › Skipped Scan", "color": "8F1784", "description": "Author has skipped code scan" },
|
||||||
{ "name": "Status 𐄂 Duplicate", "color": "75536b", "description": "Issue or pull request already exists" },
|
{ "name": "Status › Duplicate", "color": "75536b", "description": "Issue or pull request already exists" },
|
||||||
{ "name": "Status 𐄂 Accepted", "color": "2e7539", "description": "This pull request has been accepted" },
|
{ "name": "Status › Accepted", "color": "2e7539", "description": "This pull request has been accepted" },
|
||||||
{ "name": "Status 𐄂 Autoclosed", "color": "3E0915", "description": "Originally stale and was autoclosed for no activity" },
|
{ "name": "Status › Autoclosed", "color": "3E0915", "description": "Originally stale and was autoclosed for no activity" },
|
||||||
{ "name": "Status 𐄂 Denied", "color": "ba4058", "description": "Pull request has been denied" },
|
{ "name": "Status › Denied", "color": "ba4058", "description": "Pull request has been denied" },
|
||||||
{ "name": "Status 𐄂 Locked", "color": "550F45", "description": "Automatically locked by EuropaServ for a prolonged period of inactivity" },
|
{ "name": "Status › Locked", "color": "550F45", "description": "Automatically locked by AdminServ for a prolonged period of inactivity" },
|
||||||
{ "name": "Status 𐄂 Need Info", "color": "2E3C4C", "description": "Not enough information to resolve" },
|
{ "name": "Status › Need Info", "color": "2E3C4C", "description": "Not enough information to resolve" },
|
||||||
{ "name": "Status 𐄂 No Action", "color": "030406", "description": "Closed without any action being taken" },
|
{ "name": "Status › No Action", "color": "030406", "description": "Closed without any action being taken" },
|
||||||
{ "name": "Status 𐄂 Pending", "color": "984b12", "description": "Pending pull request" },
|
{ "name": "Status › Pending", "color": "984b12", "description": "Pending pull request" },
|
||||||
{ "name": "Status 𐄂 Released", "color": "1b6626", "description": "Issues or PR has been implemented and is now live" },
|
{ "name": "Status › Released", "color": "1b6626", "description": "Issues or PR has been implemented and is now live" },
|
||||||
{ "name": "Status 𐄂 Reopened", "color": "8a6f14", "description": "A previously closed PR which has been re-opened" },
|
{ "name": "Status › Reopened", "color": "8a6f14", "description": "A previously closed PR which has been re-opened" },
|
||||||
{ "name": "Status 𐄂 Review", "color": "9e1451", "description": "Currently pending review" },
|
{ "name": "Status › Review", "color": "9e1451", "description": "Currently pending review" },
|
||||||
{ "name": "Status 𐄂 Stale", "color": "928282", "description": "Has not had any activity in over 30 days" },
|
{ "name": "Status › Stale", "color": "928282", "description": "Has not had any activity in over 30 days" },
|
||||||
{ "name": "Type ◦ Bug", "color": "9a2c2c", "description": "Something isn't working" },
|
{ "name": "Type › Bug", "color": "9a2c2c", "description": "Something isn't working" },
|
||||||
{ "name": "Type ◦ Dependency", "color": "243759", "description": "Item is associated to dependency" },
|
{ "name": "Type › Dependency", "color": "243759", "description": "Item is associated to dependency" },
|
||||||
{ "name": "Type ◦ Docs", "color": "0e588d", "description": "Improvements or modifications to docs" },
|
{ "name": "Type › Docs", "color": "0e588d", "description": "Improvements or modifications to docs" },
|
||||||
{ "name": "Type ◦ Feature", "color": "3c4e93", "description": "Feature request" },
|
{ "name": "Type › Feature", "color": "3c4e93", "description": "Feature request" },
|
||||||
{ "name": "Type ◦ Git Action", "color": "030406", "description": "GitHub Action / workflow" },
|
{ "name": "Type › Git Action", "color": "030406", "description": "GitHub Action / workflow" },
|
||||||
{ "name": "Type ◦ Pull Request", "color": "8F1784", "description": "Normal pull request" },
|
{ "name": "Type › Pull Request", "color": "8F1784", "description": "Normal pull request" },
|
||||||
{ "name": "Type ◦ Roadmap", "color": "8F1784", "description": "Feature or bug currently planned for implementation" },
|
{ "name": "Type › Roadmap", "color": "8F1784", "description": "Feature or bug currently planned for implementation" },
|
||||||
{ "name": "Type ◦ Internal", "color": "A51994", "description": "Assigned items are for internal developer use" },
|
{ "name": "Type › Internal", "color": "A51994", "description": "Assigned items are for internal developer use" },
|
||||||
{ "name": "Build ◦ Desktop", "color": "c7ca4a", "description": "Specific to desktop" },
|
{ "name": "Build › Desktop", "color": "c7ca4a", "description": "Specific to desktop" },
|
||||||
{ "name": "Build ◦ Linux", "color": "c7ca4a", "description": "Specific to Linux" },
|
{ "name": "Build › Linux", "color": "c7ca4a", "description": "Specific to Linux" },
|
||||||
{ "name": "Build ◦ MacOS", "color": "c7ca4a", "description": "Specific to MacOS" },
|
{ "name": "Build › MacOS", "color": "c7ca4a", "description": "Specific to MacOS" },
|
||||||
{ "name": "Build ◦ Mobile", "color": "c7ca4a", "description": "Specific to mobile" },
|
{ "name": "Build › Mobile", "color": "c7ca4a", "description": "Specific to mobile" },
|
||||||
{ "name": "Build ◦ Web", "color": "c7ca4a", "description": "Specific to web" },
|
{ "name": "Build › Web", "color": "c7ca4a", "description": "Specific to web" },
|
||||||
{ "name": "Build ◦ Windows", "color": "c7ca4a", "description": "Specific to Windows" },
|
{ "name": "Build › Windows", "color": "c7ca4a", "description": "Specific to Windows" },
|
||||||
{ "name": "› API", "color": "F99B50", "description": "Plugin API, CLI, browser JS API" },
|
{ "name": "› API", "color": "F99B50", "description": "Plugin API, CLI, browser JS API" },
|
||||||
{ "name": "› Auto-type", "color": "9141E0", "description": "Auto-type functionality in desktop apps" },
|
{ "name": "› Auto-type", "color": "9141E0", "description": "Auto-type functionality in desktop apps" },
|
||||||
{ "name": "› Browser", "color": "9141E0", "description": "Browser plugins and passing data to <=> from app" },
|
{ "name": "› Browser", "color": "9141E0", "description": "Browser plugins and passing data to <=> from app" },
|
||||||
{ "name": "› Customization", "color": "E3F0FC", "description": "Customizations: plugins, themes, configs" },
|
{ "name": "› Customization", "color": "E3F0FC", "description": "Customizations: plugins, themes, configs" },
|
||||||
{ "name": "› Design", "color": "FA70DE", "description": "Design related queries" },
|
{ "name": "› Design", "color": "FA70DE", "description": "Design related queries" },
|
||||||
{ "name": "› Dist", "color": "FA70DE", "description": "Installers and other forms of software distribution" },
|
{ "name": "› Dist", "color": "FA70DE", "description": "Installers and other forms of software distribution" },
|
||||||
{ "name": "› Enterprise", "color": "11447a", "description": "Issues about collaboration, administration, and so on" },
|
{ "name": "› Enterprise", "color": "11447a", "description": "Issues about collaboration, administration, and so on" },
|
||||||
{ "name": "› Hardware", "color": "5a7503", "description": "YubiKey, other tokens, biometrics" },
|
{ "name": "› Hardware", "color": "5a7503", "description": "YubiKey, other tokens, biometrics" },
|
||||||
{ "name": "› Import/Export", "color": "F5FFCC", "description": "Import from and export to different file formats" },
|
{ "name": "› Import/Export", "color": "F5FFCC", "description": "Import from and export to different file formats" },
|
||||||
{ "name": "› Improvement", "color": "185c98", "description": "Enhance an existing feature" },
|
{ "name": "› Improvement", "color": "185c98", "description": "Enhance an existing feature" },
|
||||||
{ "name": "› Performance", "color": "006b75", "description": "Web and desktop performance issues" },
|
{ "name": "› Performance", "color": "006b75", "description": "Web and desktop performance issues" },
|
||||||
{ "name": "› Plugin Request", "color": "FCE9CA", "description": "Requested changes should be implemented as a plugin" },
|
{ "name": "› Plugin Request", "color": "FCE9CA", "description": "Requested changes should be implemented as a plugin" },
|
||||||
{ "name": "› Security", "color": "F75D39", "description": "Security issues" },
|
{ "name": "› Security", "color": "F75D39", "description": "Security issues" },
|
||||||
{ "name": "› Self-Hosting", "color": "fad8c7", "description": "Self-hosting installations and configs" },
|
{ "name": "› Self-Hosting", "color": "fad8c7", "description": "Self-hosting installations and configs" },
|
||||||
{ "name": "› Storage", "color": "5319e7", "description": "Storage providers: Dropbox, Google, WebDAV, etc." },
|
{ "name": "› Storage", "color": "5319e7", "description": "Storage providers: Dropbox, Google, WebDAV, etc." },
|
||||||
{ "name": "› Updater", "color": "1BADDE", "description": "Auto-updater issues" },
|
{ "name": "› Updater", "color": "1BADDE", "description": "Auto-updater issues" },
|
||||||
{ "name": "› UX", "color": "1BADDE", "description": "UX and usability" },
|
{ "name": "› UX", "color": "1BADDE", "description": "UX and usability" },
|
||||||
{ "name": "› Website", "color": "fef2c0", "description": "Website related issues" },
|
{ "name": "› Website", "color": "fef2c0", "description": "Website related issues" },
|
||||||
{ "name": "⚠ Urgent", "color": "a8740e", "description": "Requires urgent attention" },
|
{ "name": "⚠ Urgent", "color": "a8740e", "description": "Requires urgent attention" },
|
||||||
{ "name": "⚠ Announcement", "color": "DB4712", "description": "Announcements" },
|
{ "name": "⚠ Announcement", "color": "DB4712", "description": "Announcements" },
|
||||||
{ "name": "📰 Progress Report", "color": "392297", "description": "Development updates" },
|
{ "name": "📰 Progress Report", "color": "392297", "description": "Development updates" },
|
||||||
{ "name": "📦 Release", "color": "277542", "description": "Release announcements" },
|
{ "name": "📦 Release", "color": "277542", "description": "Release announcements" },
|
||||||
{ "name": "✔️ Poll", "color": "972255", "description": "Community polls" },
|
{ "name": "✔️ Poll", "color": "972255", "description": "Community polls" },
|
||||||
{ "name": "❔ Question", "color": "FFFFFF", "description": "All questions" }
|
{ "name": "❔ Question", "color": "FFFFFF", "description": "All questions" }
|
||||||
]
|
]
|
||||||
|
|
||||||
# #
|
# #
|
||||||
@@ -140,14 +140,17 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Job › Autoscan
|
# Job › PR Scan
|
||||||
|
#
|
||||||
|
# automatically scan a pull request once it is submitted
|
||||||
# #
|
# #
|
||||||
|
|
||||||
job-pr-autoscan:
|
job-pr-scan:
|
||||||
name: 🎫 Issues › Autoscan
|
name: >-
|
||||||
|
🎫 Issues › Autoscan
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
runs-on: apollo-x64
|
||||||
timeout-minutes: 7
|
timeout-minutes: 5
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
actions: read
|
actions: read
|
||||||
@@ -156,27 +159,32 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Cleanup › Set Env Variables
|
# PR Scan › Set Env Variables
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
🕛 Get Timestamp
|
🕛 Get Timestamp
|
||||||
id: task_autocheck_set_timestamp
|
id: task_prscan_set_timestamp
|
||||||
run: |
|
run: |
|
||||||
|
echo "YEAR=$(date +'%Y')" >> $GITHUB_ENV
|
||||||
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV
|
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV
|
||||||
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV
|
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV
|
||||||
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV
|
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV
|
||||||
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV
|
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV
|
||||||
|
|
||||||
# #
|
# #
|
||||||
|
# PR Scan › Labels › Verify Existing
|
||||||
|
#
|
||||||
|
# check if repo has all of the needed issue / pr labels; create label if not exists
|
||||||
|
#
|
||||||
# action needed if using 'pull_request' and 'issue_comment'
|
# action needed if using 'pull_request' and 'issue_comment'
|
||||||
# to get the pull request, you would normally use ${{ github.event.number }}
|
# to get the pull request, you would normally use ${{ github.event.number }}
|
||||||
# however this isnt available for 'issue_comment'
|
# however this isnt available for 'issue_comment'
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
🏷️ Verify Existing Labels
|
🎫 Labels › Verify Existing
|
||||||
id: task_autocheck_labels_verify
|
id: task_prscan_labels_verify
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.ADMINSERV_TOKEN_CL || github.token }}
|
github-token: ${{ secrets.ADMINSERV_TOKEN_CL || github.token }}
|
||||||
@@ -191,7 +199,7 @@ jobs:
|
|||||||
owner: context.repo.owner,
|
owner: context.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: context.repo.repo,
|
||||||
name: label.name,
|
name: label.name,
|
||||||
description: label.description || '',
|
description: label.description || 'No Description',
|
||||||
color: label.color
|
color: label.color
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -209,13 +217,15 @@ jobs:
|
|||||||
}
|
}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# set issue number
|
# PR Scan › Assign Pull Request ID to variable
|
||||||
|
#
|
||||||
|
# get id (number) for pr when submitted
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
#️⃣ Issue number › Set
|
#️⃣ Pull-Request ID › Set
|
||||||
|
id: task_prscan_issue_num_set
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
id: task_autocheck_issue_num_set
|
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.ADMINSERV_TOKEN_CL || github.token }}
|
github-token: ${{ secrets.ADMINSERV_TOKEN_CL || github.token }}
|
||||||
script: |
|
script: |
|
||||||
@@ -244,41 +254,43 @@ jobs:
|
|||||||
result-encoding: string
|
result-encoding: string
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# print issue number
|
# PR Scan › Pull-Request ID › Print
|
||||||
|
#
|
||||||
|
# prints the pr number detected
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
#️⃣ Issue number › Print
|
#️⃣ Pull-Request ID › Print
|
||||||
id: task_autocheck_issue_num_get
|
id: task_prscan_issue_num_get
|
||||||
run: |
|
run: |
|
||||||
echo '${{ steps.task_autocheck_issue_num_set.outputs.result }}'
|
echo '${{ steps.task_prscan_issue_num_set.outputs.result }}'
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# checkout
|
# PR Scan › Checkout
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
☑️ Checkout
|
☑️ Checkout
|
||||||
id: task_autoscan_checkout
|
id: task_prscan_checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
if: |
|
if: |
|
||||||
( github.event_name == 'pull_request_target' ) || ( github.event_name == 'pull_request' ) || ( github.event_name == 'issue_comment' && contains( github.event.comment.html_url, '/pull/' ) && contains( github.event.comment.body, '/rescan' ) )
|
( github.event_name == 'pull_request_target' ) || ( github.event_name == 'pull_request' ) || ( github.event_name == 'issue_comment' && contains( github.event.comment.html_url, '/pull/' ) && contains( github.event.comment.body, '/rescan' ) )
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.ADMINSERV_TOKEN_CL || github.token }}
|
token: ${{ secrets.ADMINSERV_TOKEN_CL || github.token }}
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
ref: "refs/pull/${{ steps.task_autocheck_issue_num_set.outputs.result }}/merge"
|
ref: "refs/pull/${{ steps.task_prscan_issue_num_set.outputs.result }}/merge"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# nodejs
|
# PR Scan › Setup NodeJS
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
⚙️ Setup Node
|
⚙️ Setup Node
|
||||||
id: task_autocheck_nodejs
|
id: task_prscan_nodejs
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# get list of changed files
|
# PR Scan › Get List of Changed Files
|
||||||
#
|
#
|
||||||
# Effortlessly track all changed files and directories relative to a target branch,
|
# Effortlessly track all changed files and directories relative to a target branch,
|
||||||
# the current branch (preceding commit or the last remote commit), multiple branches,
|
# the current branch (preceding commit or the last remote commit), multiple branches,
|
||||||
@@ -288,49 +300,49 @@ jobs:
|
|||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
📄 Get changed files
|
📄 Get changed files
|
||||||
id: task_autocheck_changed_files_get
|
id: task_prscan_changed_files_get
|
||||||
uses: tj-actions/changed-files@v46
|
uses: tj-actions/changed-files@v46
|
||||||
with:
|
with:
|
||||||
separator: ","
|
separator: ","
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# list of changed files
|
# PR Scan › List All Changed Files
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
📄 List all added files
|
📄 List all added files
|
||||||
id: task_autocheck_added_files_get
|
id: task_prscan_added_files_get
|
||||||
run: |
|
run: |
|
||||||
for file in ${CHANGED_FILES}; do
|
for file in ${CHANGED_FILES}; do
|
||||||
echo "$file was changed"
|
echo "$file was changed"
|
||||||
done
|
done
|
||||||
env:
|
env:
|
||||||
ADDED_FILES: ${{ steps.task_autocheck_changed_files_get.outputs.added_files }}
|
ADDED_FILES: ${{ steps.task_prscan_changed_files_get.outputs.added_files }}
|
||||||
MODIFIED_FILES: ${{ steps.task_autocheck_changed_files_get.outputs.modified_files }}
|
MODIFIED_FILES: ${{ steps.task_prscan_changed_files_get.outputs.modified_files }}
|
||||||
CHANGED_FILES: ${{ steps.task_autocheck_changed_files_get.outputs.all_changed_files }}
|
CHANGED_FILES: ${{ steps.task_prscan_changed_files_get.outputs.all_changed_files }}
|
||||||
COUNT_ADDED: ${{ steps.task_autocheck_changed_files_get.outputs.added_files_count }}
|
COUNT_ADDED: ${{ steps.task_prscan_changed_files_get.outputs.added_files_count }}
|
||||||
COUNT_MODIFIED: ${{ steps.task_autocheck_changed_files_get.outputs.modified_files_count }}
|
COUNT_MODIFIED: ${{ steps.task_prscan_changed_files_get.outputs.modified_files_count }}
|
||||||
COUNT_DELETED: ${{ steps.task_autocheck_changed_files_get.outputs.deleted_files_count }}
|
COUNT_DELETED: ${{ steps.task_prscan_changed_files_get.outputs.deleted_files_count }}
|
||||||
COUNT_RENAMED: ${{ steps.task_autocheck_changed_files_get.outputs.renamed_files_count }}
|
COUNT_RENAMED: ${{ steps.task_prscan_changed_files_get.outputs.renamed_files_count }}
|
||||||
COUNT_COPIED: ${{ steps.task_autocheck_changed_files_get.outputs.copied_files_count }}
|
COUNT_COPIED: ${{ steps.task_prscan_changed_files_get.outputs.copied_files_count }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# List directories
|
# PR Scan › List Directories / File Structure
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
📂 List Directories
|
📂 List Directories
|
||||||
id: task_autocheck_dirs_list
|
id: task_prscan_dirs_list
|
||||||
run: |
|
run: |
|
||||||
ls
|
ls
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Run autocheck
|
# PR Scan › Autocheck
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
☑️ Run Autocheck
|
☑️ Run Autocheck
|
||||||
id: task_autocheck_run
|
id: task_prscan_run
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
github-token: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
||||||
@@ -358,8 +370,8 @@ jobs:
|
|||||||
"number": 32
|
"number": 32
|
||||||
},
|
},
|
||||||
"repo": {
|
"repo": {
|
||||||
"owner": "TheBinaryNinja",
|
"owner": "Aetherinox",
|
||||||
"repo": "TVApp2"
|
"repo": "TheRepoName"
|
||||||
},
|
},
|
||||||
"payload": {
|
"payload": {
|
||||||
"action": "synchronize",
|
"action": "synchronize",
|
||||||
@@ -368,19 +380,19 @@ jobs:
|
|||||||
"number": 32,
|
"number": 32,
|
||||||
"organization": {
|
"organization": {
|
||||||
"avatar_url": "https://avatars.githubusercontent.com/u/200161462?v=4",
|
"avatar_url": "https://avatars.githubusercontent.com/u/200161462?v=4",
|
||||||
"events_url": "https://api.github.com/orgs/TheBinaryNinja/events",
|
"events_url": "https://api.github.com/orgs/Aetherinox/events",
|
||||||
"hooks_url": "https://api.github.com/orgs/TheBinaryNinja/hooks",
|
"hooks_url": "https://api.github.com/orgs/Aetherinox/hooks",
|
||||||
"issues_url": "https://api.github.com/orgs/TheBinaryNinja/issues",
|
"issues_url": "https://api.github.com/orgs/Aetherinox/issues",
|
||||||
"login": "TheBinaryNinja",
|
"login": "Aetherinox",
|
||||||
"members_url": "https://api.github.com/orgs/TheBinaryNinja/members{/member}",
|
"members_url": "https://api.github.com/orgs/Aetherinox/members{/member}",
|
||||||
"public_members_url": "https://api.github.com/orgs/TheBinaryNinja/public_members{/member}",
|
"public_members_url": "https://api.github.com/orgs/Aetherinox/public_members{/member}",
|
||||||
"repos_url": "https://api.github.com/orgs/TheBinaryNinja/repos",
|
"repos_url": "https://api.github.com/orgs/Aetherinox/repos",
|
||||||
"url": "https://api.github.com/orgs/TheBinaryNinja"
|
"url": "https://api.github.com/orgs/Aetherinox"
|
||||||
},
|
},
|
||||||
"pull_request": {
|
"pull_request": {
|
||||||
"created_at": "2025-03-17T23:32:22Z",
|
"created_at": "2025-03-17T23:32:22Z",
|
||||||
"updated_at": "2025-03-17T23:32:22Z",
|
"updated_at": "2025-03-17T23:32:22Z",
|
||||||
"url": "https://api.github.com/repos/TheBinaryNinja/tvapp2",
|
"url": "https://api.github.com/repos/Aetherinox/TheRepoName",
|
||||||
"title": "Test PR Workflow",
|
"title": "Test PR Workflow",
|
||||||
"head": {
|
"head": {
|
||||||
"ref": "main"
|
"ref": "main"
|
||||||
@@ -399,16 +411,16 @@ jobs:
|
|||||||
"id": 7821944832,
|
"id": 7821944832,
|
||||||
"name": "AC › Passed",
|
"name": "AC › Passed",
|
||||||
"node_id": "LA_kwDONW-GkM8AAAAB0jloAA",
|
"node_id": "LA_kwDONW-GkM8AAAAB0jloAA",
|
||||||
"url": "https://api.github.com/repos/TheBinaryNinja/tvapp2/labels/AC%20%E2%80%BA%20Passed"
|
"url": "https://api.github.com/repos/Aetherinox/TheRepoName/labels/AC%20%E2%80%BA%20Passed"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"color": "8F1784",
|
"color": "8F1784",
|
||||||
"default": false,
|
"default": false,
|
||||||
"description": "Normal pull request",
|
"description": "Normal pull request",
|
||||||
"id": 7821944963,
|
"id": 7821944963,
|
||||||
"name": "Type ◦ Pull Request",
|
"name": "Type › Pull Request",
|
||||||
"node_id": "LA_kwDONW-GkM8AAAAB0jlogw",
|
"node_id": "LA_kwDONW-GkM8AAAAB0jlogw",
|
||||||
"url": "https://api.github.com/repos/TheBinaryNinja/tvapp2/labels/Type%20%E2%97%A6%20Pull%20Request"
|
"url": "https://api.github.com/repos/Aetherinox/TheRepoName/labels/Type%20%E2%97%A6%20Pull%20Request"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -417,7 +429,7 @@ jobs:
|
|||||||
"sha": "c938f7a21247f69b29cf352d0c6890a63f260d47",
|
"sha": "c938f7a21247f69b29cf352d0c6890a63f260d47",
|
||||||
"ref": "refs/heads/main",
|
"ref": "refs/heads/main",
|
||||||
"workflow": "🎫 Issues › Scan",
|
"workflow": "🎫 Issues › Scan",
|
||||||
"action": "task_autocheck_run",
|
"action": "task_prscan_run",
|
||||||
"actor": "renovate[bot]",
|
"actor": "renovate[bot]",
|
||||||
"job": "job-pr-autoscan",
|
"job": "job-pr-autoscan",
|
||||||
"runNumber": 45,
|
"runNumber": 45,
|
||||||
@@ -454,7 +466,7 @@ jobs:
|
|||||||
labels.push(name);
|
labels.push(name);
|
||||||
});
|
});
|
||||||
|
|
||||||
const files_List = `${{ steps.task_autocheck_changed_files_get.outputs.all_changed_files }}` || ''
|
const files_List = `${{ steps.task_prscan_changed_files_get.outputs.all_changed_files }}` || ''
|
||||||
const files_Array = files_List.split(',')
|
const files_Array = files_List.split(',')
|
||||||
const branch_ref = `${ ct.payload.pull_request.head.ref }`
|
const branch_ref = `${ ct.payload.pull_request.head.ref }`
|
||||||
|
|
||||||
@@ -507,11 +519,11 @@ jobs:
|
|||||||
| Author | [ ` + ct.payload.pull_request.user.login + ` ](https://github.com/` + ct.repo.owner + `/) |
|
| Author | [ ` + ct.payload.pull_request.user.login + ` ](https://github.com/` + ct.repo.owner + `/) |
|
||||||
| Repo | [ ` + ct.repo.repo + ` ](https://github.com/` + ct.repo.owner + `/` + ct.repo.repo + `) |
|
| Repo | [ ` + ct.repo.repo + ` ](https://github.com/` + ct.repo.owner + `/` + ct.repo.repo + `) |
|
||||||
| Branch | [ ` + ct.payload.pull_request.head.ref + `](https://github.com/` + ct.repo.owner + `/` + ct.repo.repo + `/tree/` + ct.payload.pull_request.head.ref + `) ⇁ [ ` + ct.payload.pull_request.base.ref + `](https://github.com/` + ct.repo.owner + `/` + ct.repo.repo + `/tree/` + ct.payload.pull_request.base.ref + `) |
|
| Branch | [ ` + ct.payload.pull_request.head.ref + `](https://github.com/` + ct.repo.owner + `/` + ct.repo.repo + `/tree/` + ct.payload.pull_request.head.ref + `) ⇁ [ ` + ct.payload.pull_request.base.ref + `](https://github.com/` + ct.repo.owner + `/` + ct.repo.repo + `/tree/` + ct.payload.pull_request.base.ref + `) |
|
||||||
| Added Files | ${{ steps.task_autocheck_changed_files_get.outputs.added_files_count }} |
|
| Added Files | ${{ steps.task_prscan_changed_files_get.outputs.added_files_count }} |
|
||||||
| Modified Files | ${{ steps.task_autocheck_changed_files_get.outputs.all_modified_files_count }} |
|
| Modified Files | ${{ steps.task_prscan_changed_files_get.outputs.all_modified_files_count }} |
|
||||||
| Renamed Files | ${{ steps.task_autocheck_changed_files_get.outputs.renamed_files_count }} |
|
| Renamed Files | ${{ steps.task_prscan_changed_files_get.outputs.renamed_files_count }} |
|
||||||
| Copied Files | ${{ steps.task_autocheck_changed_files_get.outputs.deleted_files_count }} |
|
| Copied Files | ${{ steps.task_prscan_changed_files_get.outputs.deleted_files_count }} |
|
||||||
| Deleted Files | ${{ steps.task_autocheck_changed_files_get.outputs.deleted_files_count }} |
|
| Deleted Files | ${{ steps.task_prscan_changed_files_get.outputs.deleted_files_count }} |
|
||||||
`;
|
`;
|
||||||
|
|
||||||
message.push ( md_table );
|
message.push ( md_table );
|
||||||
@@ -960,12 +972,13 @@ jobs:
|
|||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
🕛 Get Weekly Commit List
|
🕛 Get Weekly Commit List
|
||||||
id: task_autocheck_set_weekly_commit_list
|
id: task_prscan_set_weekly_commit_list
|
||||||
run: |
|
run: |
|
||||||
echo 'WEEKLY_COMMITS<<EOF' >> $GITHUB_ENV
|
echo 'WEEKLY_COMMITS<<EOF' >> $GITHUB_ENV
|
||||||
git log --format="[\`%h\`](${{ github.server_url }}/${{ github.repository }}/commit/%H) %s - %an" --since=7.days >> $GITHUB_ENV
|
git log --format="[\`%h\`](${{ github.server_url }}/${{ github.repository }}/commit/%H) %s - %an" --since=7.days >> $GITHUB_ENV
|
||||||
echo 'EOF' >> $GITHUB_ENV
|
echo 'EOF' >> $GITHUB_ENV
|
||||||
|
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Autoscan › Notify Github › Success
|
# Autoscan › Notify Github › Success
|
||||||
# #
|
# #
|
||||||
@@ -1004,11 +1017,11 @@ jobs:
|
|||||||
- Status: `${{ github.event.pull_request.state }}`
|
- Status: `${{ github.event.pull_request.state }}`
|
||||||
|
|
||||||
### Scan Results
|
### Scan Results
|
||||||
- Added Files: ${{ steps.task_autocheck_changed_files_get.outputs.added_files_count }}
|
- Added Files: ${{ steps.task_prscan_added_files_get.outputs.added_files_count }}
|
||||||
- Modified Files: ${{ steps.task_autocheck_changed_files_get.outputs.all_modified_files_count }}
|
- Modified Files: ${{ steps.task_prscan_added_files_get.outputs.all_modified_files_count }}
|
||||||
- Renamed Files: ${{ steps.task_autocheck_changed_files_get.outputs.renamed_files_count }}
|
- Renamed Files: ${{ steps.task_prscan_added_files_get.outputs.renamed_files_count }}
|
||||||
- Copied Files: ${{ steps.task_autocheck_changed_files_get.outputs.copied_files_count }}
|
- Copied Files: ${{ steps.task_prscan_added_files_get.outputs.copied_files_count }}
|
||||||
- Deleted Files: ${{ steps.task_autocheck_changed_files_get.outputs.deleted_files_count }}
|
- Deleted Files: ${{ steps.task_prscan_added_files_get.outputs.deleted_files_count }}
|
||||||
|
|
||||||
embed-color: ${{ job.status == 'success' && '5763719' || '15418782' }}
|
embed-color: ${{ job.status == 'success' && '5763719' || '15418782' }}
|
||||||
embed-footer-text: "Completed at ${{ env.NOW }} UTC"
|
embed-footer-text: "Completed at ${{ env.NOW }} UTC"
|
||||||
@@ -1055,11 +1068,11 @@ jobs:
|
|||||||
- Status: `${{ github.event.pull_request.state }}`
|
- Status: `${{ github.event.pull_request.state }}`
|
||||||
|
|
||||||
### Scan Results
|
### Scan Results
|
||||||
- Added Files: ${{ steps.task_autocheck_changed_files_get.outputs.added_files_count }}
|
- Added Files: ${{ steps.task_prscan_added_files_get.outputs.added_files_count }}
|
||||||
- Modified Files: ${{ steps.task_autocheck_changed_files_get.outputs.all_modified_files_count }}
|
- Modified Files: ${{ steps.task_prscan_added_files_get.outputs.all_modified_files_count }}
|
||||||
- Renamed Files: ${{ steps.task_autocheck_changed_files_get.outputs.renamed_files_count }}
|
- Renamed Files: ${{ steps.task_prscan_added_files_get.outputs.renamed_files_count }}
|
||||||
- Copied Files: ${{ steps.task_autocheck_changed_files_get.outputs.copied_files_count }}
|
- Copied Files: ${{ steps.task_prscan_added_files_get.outputs.copied_files_count }}
|
||||||
- Deleted Files: ${{ steps.task_autocheck_changed_files_get.outputs.deleted_files_count }}
|
- Deleted Files: ${{ steps.task_prscan_added_files_get.outputs.deleted_files_count }}
|
||||||
|
|
||||||
embed-color: ${{ job.status == 'success' && '5763719' || '15418782' }}
|
embed-color: ${{ job.status == 'success' && '5763719' || '15418782' }}
|
||||||
embed-footer-text: "Completed at ${{ env.NOW }} UTC"
|
embed-footer-text: "Completed at ${{ env.NOW }} UTC"
|
||||||
|
|||||||
510
.github/workflows/issues-stale.yml
vendored
@@ -3,19 +3,18 @@
|
|||||||
# @author Aetherinox
|
# @author Aetherinox
|
||||||
# @url https://github.com/Aetherinox
|
# @url https://github.com/Aetherinox
|
||||||
# @usage creates repository labels if they are not yet installed
|
# @usage creates repository labels if they are not yet installed
|
||||||
# issues marked as stale after 30 days, given tag Status 𐄂 Stale
|
# issues marked as stale after 30 days, given tag Status › Stale
|
||||||
# inactive issues closed after 180 days, given tag Status 𐄂 Locked
|
# inactive issues closed after 180 days, given tag Status › Locked
|
||||||
# inactive pr closed after 365 days, given tag Status 𐄂 Locked
|
# inactive pr closed after 365 days, given tag Status › Locked
|
||||||
# issues marked stale after 30 days, given tag Status 𐄂 Stale
|
# issues marked stale after 30 days, given tag Status › Stale
|
||||||
# issues marked closed 7 days after being marked stale, given tag Status 𐄂 Autoclosed
|
# issues marked closed 7 days after being marked stale, given tag Status › Autoclosed
|
||||||
#
|
#
|
||||||
# @notes This Github action must be activated manually. This workflow script will do the following:
|
# @notes This Github action must be activated manually. This workflow script will do the following:
|
||||||
#
|
|
||||||
# - Scan issues / pull requests and make sure they have properly assigned labels:
|
# - Scan issues / pull requests and make sure they have properly assigned labels:
|
||||||
# - `Bug`
|
# - `Bug`
|
||||||
# - `Feature`
|
# - `Feature`
|
||||||
# - `Urgent`
|
# - `Urgent`
|
||||||
# - `Roadmap`
|
# - `Roadmap`
|
||||||
#
|
#
|
||||||
# - Workflow script will then scan each pr or issue and mark them as `Stale`
|
# - Workflow script will then scan each pr or issue and mark them as `Stale`
|
||||||
# if they haven't had any replies in 30 days.
|
# if they haven't had any replies in 30 days.
|
||||||
@@ -28,15 +27,15 @@
|
|||||||
# secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/
|
# secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/
|
||||||
# secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/
|
# secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/
|
||||||
# secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token
|
# secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token
|
||||||
# secrets.ORG_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
# secrets.ORG_TOKEN org github personal access token (fine-grained)
|
||||||
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
# secrets.ORG_TOKEN_CL org github personal access token (classic)
|
||||||
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
# secrets.ORG_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
# secrets.ORG_BINARYNINJA_GITEA_TOKEN org gitea personal access token (classic) with package:write permission
|
# secrets.ORG_GITEA_TOKEN org gitea personal access token (classic) with package:write permission
|
||||||
# secrets.BINARYSERV_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK
|
# secrets.BOT_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK
|
||||||
# secrets.BINARYSERV_GPG_PASSPHRASE bot gpg private key passphrase
|
# secrets.BOT_GPG_PASSPHRASE bot gpg private key passphrase
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_RELEASES discord webhook to report release notifications from github to discord
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_RELEASES discord webhook to report release notifications from github to discord
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_WORKFLOWS discord webhook to report workflow notifications from github to discord
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_WORKFLOWS discord webhook to report workflow notifications from github to discord
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_UPDATES discord webhook to report activity notifications from github to discord
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_UPDATES discord webhook to report activity notifications from github to discord
|
||||||
#
|
#
|
||||||
# @local these workflows can be tested locally through the use of `act`
|
# @local these workflows can be tested locally through the use of `act`
|
||||||
# https://github.com/nektos/act
|
# https://github.com/nektos/act
|
||||||
@@ -48,8 +47,8 @@
|
|||||||
# act -W .github/workflows/issues-stale.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
# act -W .github/workflows/issues-stale.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "🎫 Issues › Stale"
|
name: '🎫 Issues › Stale'
|
||||||
run-name: "🎫 Issues › Stale"
|
run-name: '🎫 Issues › Stale'
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# triggers
|
# triggers
|
||||||
@@ -65,68 +64,75 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PREFIX_BUG: "🐛 Bug"
|
PREFIX_BUG: "🐛 Bug"
|
||||||
PREFIX_DEPENDENCY: "Dependency"
|
PREFIX_DEPENDENCY: "Dependency"
|
||||||
PREFIX_DOCS: "Docs"
|
PREFIX_DOCS: "Docs"
|
||||||
PREFIX_FEATURE: "💡 Feature"
|
PREFIX_FEATURE: "💡 Feature"
|
||||||
PREFIX_GIT: "Git Action"
|
PREFIX_GIT: "Git Action"
|
||||||
PREFIX_PR: "PR"
|
PREFIX_PR: "PR"
|
||||||
PREFIX_ROADMAP: "🗺️ Roadmap"
|
PREFIX_ROADMAP: "🗺️ Roadmap"
|
||||||
PREFIX_INTERNAL: "Internal"
|
PREFIX_INTERNAL: "Internal"
|
||||||
PREFIX_URGENT: "⚠ Urgent"
|
PREFIX_URGENT: "⚠ Urgent"
|
||||||
|
|
||||||
LABEL_BUG: "Type ◦ Bug"
|
LABEL_BUG: "Type › Bug"
|
||||||
LABEL_DEPENDENCY: "Type ◦ Dependency"
|
LABEL_DEPENDENCY: "Type › Dependency"
|
||||||
LABEL_DOCS: "Type ◦ Docs"
|
LABEL_DOCS: "Type › Docs"
|
||||||
LABEL_FEATURE: "Type ◦ Feature"
|
LABEL_FEATURE: "Type › Feature"
|
||||||
LABEL_GIT: "Type ◦ Git Action"
|
LABEL_GIT: "Type › Git Action"
|
||||||
LABEL_PR: "Type ◦ Pull Request"
|
LABEL_PR: "Type › Pull Request"
|
||||||
LABEL_ROADMAP: "Type ◦ Roadmap"
|
LABEL_ROADMAP: "Type › Roadmap"
|
||||||
LABEL_INTERNAL: "Type ◦ Internal"
|
LABEL_INTERNAL: "Type › Internal"
|
||||||
LABEL_URGENT: "⚠ Urgent"
|
LABEL_LOCKED: "Status › Locked"
|
||||||
|
LABEL_STALE: "Status › Stale"
|
||||||
|
LABEL_AUTOCLOSE: "Status › Autoclosed"
|
||||||
|
LABEL_ACCEPTED: "Status › Accepted"
|
||||||
|
LABEL_REVIEW: "Status › Review"
|
||||||
|
LABEL_PENDING: "Status › Pending"
|
||||||
|
LABEL_AC_REVIEW: "AC › Review Required"
|
||||||
|
LABEL_URGENT: "⚠ Urgent"
|
||||||
|
|
||||||
ASSIGN_USER: Aetherinox
|
ASSIGN_USER: Aetherinox
|
||||||
BOT_NAME_1: EuropaServ
|
BOT_NAME_1: EuropaServ
|
||||||
BOT_NAME_2: BinaryServ
|
BOT_NAME_2: BinaryServ
|
||||||
BOT_NAME_DEPENDABOT: dependabot[bot]
|
BOT_NAME_DEPENDABOT: dependabot[bot]
|
||||||
BOT_NAME_RENOVATE: renovate[bot]
|
BOT_NAME_RENOVATE: renovate[bot]
|
||||||
|
|
||||||
LABELS_JSON: |
|
LABELS_JSON: |
|
||||||
[
|
[
|
||||||
{ "name": "AC › Changes Made", "color": "8F1784", "description": "Requested changes have been made and are pending a re-scan" },
|
{ "name": "AC › Changes Made", "color": "8F1784", "description": "Requested changes have been made and are pending a re-scan" },
|
||||||
{ "name": "AC › Changes Required", "color": "8F1784", "description": "Requires changes to be made to the package before being accepted" },
|
{ "name": "AC › Changes Required", "color": "8F1784", "description": "Requires changes to be made to the package before being accepted" },
|
||||||
{ "name": "AC › Failed", "color": "a61f2d", "description": "Autocheck failed to run through a complete cycle, requires investigation" },
|
{ "name": "AC › Failed", "color": "a61f2d", "description": "Autocheck failed to run through a complete cycle, requires investigation" },
|
||||||
{ "name": "AC › Needs Rebase", "color": "8F1784", "description": "Due to the permissions on the requesting repo, this pull request must be rebased by the author" },
|
{ "name": "AC › Needs Rebase", "color": "8F1784", "description": "Due to the permissions on the requesting repo, this pull request must be rebased by the author" },
|
||||||
{ "name": "AC › Passed", "color": "146b4a", "description": "Ready to be reviewed" },
|
{ "name": "AC › Passed", "color": "146b4a", "description": "Ready to be reviewed" },
|
||||||
{ "name": "AC › Review Required", "color": "8F1784", "description": "PR needs to be reviewed by another person, after the requested changes have been made" },
|
{ "name": "AC › Review Required", "color": "8F1784", "description": "PR needs to be reviewed by another person, after the requested changes have been made" },
|
||||||
{ "name": "AC › Security Warning", "color": "761620", "description": "Does not conform to developer policies, or includes potentially dangerous code" },
|
{ "name": "AC › Security Warning", "color": "761620", "description": "Does not conform to developer policies, or includes potentially dangerous code" },
|
||||||
{ "name": "AC › Skipped Scan", "color": "8F1784", "description": "Author has skipped code scan" },
|
{ "name": "AC › Skipped Scan", "color": "8F1784", "description": "Author has skipped code scan" },
|
||||||
{ "name": "Status 𐄂 Duplicate", "color": "75536b", "description": "Issue or pull request already exists" },
|
{ "name": "Status › Duplicate", "color": "75536b", "description": "Issue or pull request already exists" },
|
||||||
{ "name": "Status 𐄂 Accepted", "color": "2e7539", "description": "This pull request has been accepted" },
|
{ "name": "Status › Accepted", "color": "2e7539", "description": "This pull request has been accepted" },
|
||||||
{ "name": "Status 𐄂 Autoclosed", "color": "3E0915", "description": "Originally stale and was autoclosed for no activity" },
|
{ "name": "Status › Autoclosed", "color": "3E0915", "description": "Originally stale and was autoclosed for no activity" },
|
||||||
{ "name": "Status 𐄂 Denied", "color": "ba4058", "description": "Pull request has been denied" },
|
{ "name": "Status › Denied", "color": "ba4058", "description": "Pull request has been denied" },
|
||||||
{ "name": "Status 𐄂 Locked", "color": "550F45", "description": "Automatically locked by AdminServ for a prolonged period of inactivity" },
|
{ "name": "Status › Locked", "color": "550F45", "description": "Automatically locked by AdminServ for a prolonged period of inactivity" },
|
||||||
{ "name": "Status 𐄂 Need Info", "color": "2E3C4C", "description": "Not enough information to resolve" },
|
{ "name": "Status › Need Info", "color": "2E3C4C", "description": "Not enough information to resolve" },
|
||||||
{ "name": "Status 𐄂 No Action", "color": "030406", "description": "Closed without any action being taken" },
|
{ "name": "Status › No Action", "color": "030406", "description": "Closed without any action being taken" },
|
||||||
{ "name": "Status 𐄂 Pending", "color": "984b12", "description": "Pending pull request" },
|
{ "name": "Status › Pending", "color": "984b12", "description": "Pending pull request" },
|
||||||
{ "name": "Status 𐄂 Released", "color": "1b6626", "description": "Issues or PR has been implemented and is now live" },
|
{ "name": "Status › Released", "color": "1b6626", "description": "Issues or PR has been implemented and is now live" },
|
||||||
{ "name": "Status 𐄂 Reopened", "color": "8a6f14", "description": "A previously closed PR which has been re-opened" },
|
{ "name": "Status › Reopened", "color": "8a6f14", "description": "A previously closed PR which has been re-opened" },
|
||||||
{ "name": "Status 𐄂 Review", "color": "9e1451", "description": "Currently pending review" },
|
{ "name": "Status › Review", "color": "9e1451", "description": "Currently pending review" },
|
||||||
{ "name": "Status 𐄂 Stale", "color": "928282", "description": "Has not had any activity in over 30 days" },
|
{ "name": "Status › Stale", "color": "928282", "description": "Has not had any activity in over 30 days" },
|
||||||
{ "name": "Type ◦ Bug", "color": "9a2c2c", "description": "Something isn't working" },
|
{ "name": "Type › Bug", "color": "9a2c2c", "description": "Something isn't working" },
|
||||||
{ "name": "Type ◦ Dependency", "color": "243759", "description": "Item is associated to dependency" },
|
{ "name": "Type › Dependency", "color": "243759", "description": "Item is associated to dependency" },
|
||||||
{ "name": "Type ◦ Docs", "color": "0e588d", "description": "Improvements or modifications to docs" },
|
{ "name": "Type › Docs", "color": "0e588d", "description": "Improvements or modifications to docs" },
|
||||||
{ "name": "Type ◦ Feature", "color": "3c4e93", "description": "Feature request" },
|
{ "name": "Type › Feature", "color": "3c4e93", "description": "Feature request" },
|
||||||
{ "name": "Type ◦ Git Action", "color": "030406", "description": "GitHub Action / workflow" },
|
{ "name": "Type › Git Action", "color": "030406", "description": "GitHub Action / workflow" },
|
||||||
{ "name": "Type ◦ Pull Request", "color": "8F1784", "description": "Normal pull request" },
|
{ "name": "Type › Pull Request", "color": "8F1784", "description": "Normal pull request" },
|
||||||
{ "name": "Type ◦ Roadmap", "color": "8F1784", "description": "Feature or bug currently planned for implementation" },
|
{ "name": "Type › Roadmap", "color": "8F1784", "description": "Feature or bug currently planned for implementation" },
|
||||||
{ "name": "Type ◦ Internal", "color": "A51994", "description": "Assigned items are for internal developer use" },
|
{ "name": "Type › Internal", "color": "A51994", "description": "Assigned items are for internal developer use" },
|
||||||
{ "name": "Build ◦ Desktop", "color": "c7ca4a", "description": "Specific to desktop" },
|
{ "name": "Build › Desktop", "color": "c7ca4a", "description": "Specific to desktop" },
|
||||||
{ "name": "Build ◦ Linux", "color": "c7ca4a", "description": "Specific to Linux" },
|
{ "name": "Build › Linux", "color": "c7ca4a", "description": "Specific to Linux" },
|
||||||
{ "name": "Build ◦ MacOS", "color": "c7ca4a", "description": "Specific to MacOS" },
|
{ "name": "Build › MacOS", "color": "c7ca4a", "description": "Specific to MacOS" },
|
||||||
{ "name": "Build ◦ Mobile", "color": "c7ca4a", "description": "Specific to mobile" },
|
{ "name": "Build › Mobile", "color": "c7ca4a", "description": "Specific to mobile" },
|
||||||
{ "name": "Build ◦ Web", "color": "c7ca4a", "description": "Specific to web" },
|
{ "name": "Build › Web", "color": "c7ca4a", "description": "Specific to web" },
|
||||||
{ "name": "Build ◦ Windows", "color": "c7ca4a", "description": "Specific to Windows" },
|
{ "name": "Build › Windows", "color": "c7ca4a", "description": "Specific to Windows" },
|
||||||
{ "name": "› API", "color": "F99B50", "description": "Plugin API, CLI, browser JS API" },
|
{ "name": "› API", "color": "F99B50", "description": "Plugin API, CLI, browser JS API" },
|
||||||
{ "name": "› Auto-type", "color": "9141E0", "description": "Auto-type functionality in desktop apps" },
|
{ "name": "› Auto-type", "color": "9141E0", "description": "Auto-type functionality in desktop apps" },
|
||||||
{ "name": "› Browser", "color": "9141E0", "description": "Browser plugins and passing data to <=> from app" },
|
{ "name": "› Browser", "color": "9141E0", "description": "Browser plugins and passing data to <=> from app" },
|
||||||
@@ -169,41 +175,62 @@ jobs:
|
|||||||
job-labels-create:
|
job-labels-create:
|
||||||
name: >-
|
name: >-
|
||||||
🎫 Labels › Verify Existing
|
🎫 Labels › Verify Existing
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
timeout-minutes: 4
|
runs-on: apollo-x64
|
||||||
|
timeout-minutes: 5
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# [ Create Labels ] Start
|
# Issues (Stale) › Labels › Create › Start
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
✅ Start
|
✅ Start
|
||||||
id: task_label_create_start
|
id: task_labels_create_start
|
||||||
run: |
|
run: |
|
||||||
echo "Assigning labels and assignees"
|
echo "Assigning labels and assignees"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# [ Create Labels ] Checkout
|
# Issues (Stale) › Labels › Create › Set Env Variables
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: >-
|
||||||
|
🕛 Get Timestamp
|
||||||
|
id: task_labels_create_set_timestamp
|
||||||
|
run: |
|
||||||
|
echo "YEAR=$(date +'%Y')" >> $GITHUB_ENV
|
||||||
|
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV
|
||||||
|
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV
|
||||||
|
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV
|
||||||
|
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Issues (Stale) › Labels › Create › Checkout
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
☑️ Checkout
|
☑️ Checkout
|
||||||
id: task_label_create_checkout
|
id: task_labels_create_checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# [ Create Labels ] Verify Existing Labels
|
# Issues (Stale) › Labels › Create › Verify Existing
|
||||||
|
#
|
||||||
|
# check if repo has all of the needed issue / pr labels; create label if not exists
|
||||||
|
#
|
||||||
|
# action needed if using 'pull_request' and 'issue_comment'
|
||||||
|
# to get the pull request, you would normally use ${{ github.event.number }}
|
||||||
|
# however this isnt available for 'issue_comment'
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
🏷️ Verify Existing Labels
|
🎫 Labels › Verify Existing
|
||||||
id: task_label_create_verify
|
id: task_labels_create_verify
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
github-token: ${{ secrets.ADMINSERV_TOKEN_CL || github.token }}
|
||||||
script: |
|
script: |
|
||||||
const labels = JSON.parse( process.env.LABELS_JSON );
|
const labels = JSON.parse( process.env.LABELS_JSON );
|
||||||
for ( const label of labels )
|
for ( const label of labels )
|
||||||
@@ -215,7 +242,7 @@ jobs:
|
|||||||
owner: context.repo.owner,
|
owner: context.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: context.repo.repo,
|
||||||
name: label.name,
|
name: label.name,
|
||||||
description: label.description || '',
|
description: label.description || 'No Description',
|
||||||
color: label.color
|
color: label.color
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -233,7 +260,7 @@ jobs:
|
|||||||
}
|
}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Job [ Check Labels ]
|
# Issues (Stale) › Labels › Assign Missing
|
||||||
#
|
#
|
||||||
# Runs through all submissions to check for ones that have not been properly labeled
|
# Runs through all submissions to check for ones that have not been properly labeled
|
||||||
# - Bug
|
# - Bug
|
||||||
@@ -251,25 +278,29 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# [ Check Labels ] Checkout
|
# Issues (Stale) › Labels › Assign Missing › Checkout
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "☑️ Prepare"
|
|
||||||
|
- name: >-
|
||||||
|
☑️ Checkout
|
||||||
id: task_issues_nolabel_prepare
|
id: task_issues_nolabel_prepare
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# [ Check Labels ] Check
|
# Issues (Stale) › Labels › Assign Missing › Check
|
||||||
# Check if repo has labels currently added to issues
|
#
|
||||||
|
# Check if repo has labels to use
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: 🏷️ Checking Issues
|
- name: >-
|
||||||
|
🎫 Labels › Check
|
||||||
id: task_issues_nolabel_run
|
id: task_issues_nolabel_run
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
github-token: ${{ secrets.ADMINSERV_TOKEN_CL || github.token }}
|
||||||
script: |
|
script: |
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -278,19 +309,18 @@ jobs:
|
|||||||
|
|
||||||
const dateTimeformat = ( date ) =>
|
const dateTimeformat = ( date ) =>
|
||||||
{
|
{
|
||||||
let month = date.getMonth( ) + 1;
|
let month = date.getMonth( ) + 1;
|
||||||
month = month.toString( ).padStart( 2, '0' );
|
month = month.toString( ).padStart( 2, '0' );
|
||||||
let day = date.getDate( ).toString( ).padStart( 2, '0' );
|
let day = date.getDate( ).toString( ).padStart( 2, '0' );
|
||||||
let year = date.getFullYear( ).toString( ).padStart( 2, '0' );
|
let year = date.getFullYear( ).toString( ).padStart( 2, '0' );
|
||||||
|
|
||||||
let hours = date.getHours();
|
let hours = date.getHours();
|
||||||
let minutes = date.getMinutes();
|
let minutes = date.getMinutes();
|
||||||
let x = hours >= 12 ? 'PM' : 'AM';
|
let x = hours >= 12 ? 'PM' : 'AM';
|
||||||
hours = hours % 12;
|
hours = hours % 12;
|
||||||
hours = hours ? hours : 12;
|
hours = hours ? hours : 12;
|
||||||
minutes = minutes.toString( ).padStart( 2, '0' );
|
minutes = minutes.toString( ).padStart( 2, '0' );
|
||||||
|
let mergeTime = month + '.' + day + '.' + year + ' ' + hours + ':' + minutes + ' ' + x;
|
||||||
let mergeTime = month + '.' + day + '.' + year + ' ' + hours + ':' + minutes + ' ' + x;
|
|
||||||
|
|
||||||
return mergeTime;
|
return mergeTime;
|
||||||
}
|
}
|
||||||
@@ -315,7 +345,7 @@ jobs:
|
|||||||
let date_UpdateHuman = dateTimeformat( date_UpdateDate ) + " UTC"; // 03.26.2024 4:40 PM UTC
|
let date_UpdateHuman = dateTimeformat( date_UpdateDate ) + " UTC"; // 03.26.2024 4:40 PM UTC
|
||||||
const time_UpdateMs = new Date( issue.updated_at ).getTime( ); // 1711471241000
|
const time_UpdateMs = new Date( issue.updated_at ).getTime( ); // 1711471241000
|
||||||
|
|
||||||
//if ( curtime < time_UpdateMs + expireAfterMs ) continue;
|
// if ( curtime < time_UpdateMs + expireAfterMs ) continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Anything past this point is stale / to be closed
|
Anything past this point is stale / to be closed
|
||||||
@@ -336,8 +366,8 @@ jobs:
|
|||||||
let iss_body = `${ issue.body }`;
|
let iss_body = `${ issue.body }`;
|
||||||
const iss_body_lc = iss_body.toLowerCase( );
|
const iss_body_lc = iss_body.toLowerCase( );
|
||||||
|
|
||||||
console.log( ` └── 📁 ` + iss_title );
|
console.log( ` └── 📁 ` + iss_title + ` #${ issue.number }`);
|
||||||
console.log( ` └── 📄 Issue #${ issue.number } last updated on ${ date_UpdateHuman }` );
|
console.log( ` └── 📄 last updated on ${ date_UpdateHuman }` );
|
||||||
console.log( ` └── 📄 ${add_labels}` );
|
console.log( ` └── 📄 ${add_labels}` );
|
||||||
console.log( `\n\n` )
|
console.log( `\n\n` )
|
||||||
|
|
||||||
@@ -345,8 +375,8 @@ jobs:
|
|||||||
Keywords
|
Keywords
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const bug_words = [ "bug", "broke", "issue", "fail" ];
|
const bug_words = [ "bug", "broke", "issue", "fail", "wont work" ];
|
||||||
const feat_words = [ "feature", "request", "add support" ];
|
const feat_words = [ "feature", "request", "add", "addition", "enhance", "create" ];
|
||||||
const urgn_words = [ "urgent", "urgency", "emergency", "important", "critical" ];
|
const urgn_words = [ "urgent", "urgency", "emergency", "important", "critical" ];
|
||||||
const road_words = [ "roadmap", "road map", "planned" ];
|
const road_words = [ "roadmap", "road map", "planned" ];
|
||||||
|
|
||||||
@@ -365,17 +395,14 @@ jobs:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Label > Bugs
|
Label > Bugs
|
||||||
*/
|
|
||||||
|
|
||||||
const bug_bIncWordT = bug_words.some( s => s.includes( iss_title_lc ) || iss_title_lc.includes( s ) );
|
|
||||||
|
|
||||||
/*
|
|
||||||
Find regex based phrases
|
Find regex based phrases
|
||||||
|
|
||||||
Regex:
|
Regex:
|
||||||
https://regex101.com/r/Z99Gnq/2
|
https://regex101.com/r/Z99Gnq/2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const bug_bIncWordT = bug_words.some( s => s.includes( iss_title_lc ) || iss_title_lc.includes( s ) );
|
||||||
const bug_findWordList = /^\b(?:I?\s*have\s*(?:a|an)\s*(?:issue|problem|bug))|(?:will\s*not\s*work)|(?:it\s*is\s*(?:broken|broke|stuck))|(?:found\s*(?:an?|the)\s*(?:bug|issue))|(?:can\s*I\s*fix\s*the\s*(?:bug|issue))|(?:(?:does not|doesn'?t|don'?t|won'?t|can'?t|can\s?not|will\s*not)\s*(?:work|load|function))|(?:it\s*(?:will\s?not|won'?t|can\s?not|can'?t))\s*(?:get|find)\s*the\s*(?:website|site|webpage|page)|(?:the\s*(?:window|frame)\s*is\s*(?:blank|white|empty|missing))\b$/igm;
|
const bug_findWordList = /^\b(?:I?\s*have\s*(?:a|an)\s*(?:issue|problem|bug))|(?:will\s*not\s*work)|(?:it\s*is\s*(?:broken|broke|stuck))|(?:found\s*(?:an?|the)\s*(?:bug|issue))|(?:can\s*I\s*fix\s*the\s*(?:bug|issue))|(?:(?:does not|doesn'?t|don'?t|won'?t|can'?t|can\s?not|will\s*not)\s*(?:work|load|function))|(?:it\s*(?:will\s?not|won'?t|can\s?not|can'?t))\s*(?:get|find)\s*the\s*(?:website|site|webpage|page)|(?:the\s*(?:window|frame)\s*is\s*(?:blank|white|empty|missing))\b$/igm;
|
||||||
const bug_bFoundMatchTitle = Boolean( bug_findWordList.test( iss_title ) );
|
const bug_bFoundMatchTitle = Boolean( bug_findWordList.test( iss_title ) );
|
||||||
const bug_bFoundMatchBody = Boolean( bug_findWordList.test( iss_body ) );
|
const bug_bFoundMatchBody = Boolean( bug_findWordList.test( iss_body ) );
|
||||||
@@ -403,16 +430,49 @@ jobs:
|
|||||||
if ( author === `${{ env.BOT_NAME_DEPENDABOT }}` )
|
if ( author === `${{ env.BOT_NAME_DEPENDABOT }}` )
|
||||||
core.info( `Skipping: Detected ${ author }` )
|
core.info( `Skipping: Detected ${ author }` )
|
||||||
|
|
||||||
// Rename title to contain Bug:
|
if ( author === `${{ env.BOT_NAME_RENOVATE }}` )
|
||||||
|
core.info( `Skipping: Detected ${ author }` )
|
||||||
|
|
||||||
|
/*
|
||||||
|
Rename title to contain Bug:
|
||||||
|
if bug title or body contains keyword hinting at the issue being about a bug; change the title of the issue
|
||||||
|
|
||||||
|
@ref https://jsfiddle.net/aetherinox/wj17x8mp/2/
|
||||||
|
*/
|
||||||
|
|
||||||
if ( author !== `${{ env.BOT_NAME_DEPENDABOT }}` && !bug_bFoundPRTitle && !iss_title_lc.startsWith( bug_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( feat_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( urgn_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( road_tag.toLowerCase( ) ) )
|
if ( author !== `${{ env.BOT_NAME_DEPENDABOT }}` && !bug_bFoundPRTitle && !iss_title_lc.startsWith( bug_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( feat_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( urgn_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( road_tag.toLowerCase( ) ) )
|
||||||
{
|
{
|
||||||
const title = issue.title;
|
|
||||||
|
/*
|
||||||
|
If a user creates an issue starting with our tag; strip it and add ours with the emoji instead
|
||||||
|
original: Bug: CMD windows opens then closes, can't run the script.
|
||||||
|
new: 🐛 Bug: CMD windows opens then closes, can't run the script.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const removeBeginning1 = bug_tag.substring(3); // "Bug:"
|
||||||
|
let removeBeginning2 = bug_tag.substring(0); // "🐛 Bug:"
|
||||||
|
removeBeginning2 = removeBeginning2.replace(/\s/g, '') // "Bug:"
|
||||||
|
|
||||||
|
if ( iss_title.startsWith(removeBeginning1) )
|
||||||
|
{
|
||||||
|
iss_title = iss_title.slice(removeBeginning1.length);
|
||||||
|
iss_title = iss_title.trim();
|
||||||
|
}
|
||||||
|
else if ( iss_title.startsWith(removeBeginning2) )
|
||||||
|
{
|
||||||
|
iss_title = iss_title.slice(removeBeginning2.length);
|
||||||
|
iss_title = iss_title.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = iss_title;
|
||||||
let title_new = title.replace( /^\s?bug\s*(.*?)\b/gi, '' );
|
let title_new = title.replace( /^\s?bug\s*(.*?)\b/gi, '' );
|
||||||
title_new = title.replace( /^\s?fail\s*(.*?)\b/gi, '' );
|
title_new = title.replace( /^\s?fail\s*(.*?)\b/gi, '' );
|
||||||
title_new = title.replace( /^\s?issue\s*(.*?)\b/gi, '' );
|
title_new = title.replace( /^\s?issue\s*(.*?)\b/gi, '' );
|
||||||
iss_title = `${ bug_tag } ${ title_new }`;
|
iss_title = `${ bug_tag } ${ title_new }`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log( `New Title: ...................... ${ iss_title }` )
|
||||||
|
|
||||||
await github.rest.issues.update(
|
await github.rest.issues.update(
|
||||||
{
|
{
|
||||||
owner: context.repo.owner, repo: context.repo.repo, issue_number: issue.number,
|
owner: context.repo.owner, repo: context.repo.repo, issue_number: issue.number,
|
||||||
@@ -433,7 +493,7 @@ jobs:
|
|||||||
https://regex101.com/r/fR1Hm6/1
|
https://regex101.com/r/fR1Hm6/1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const feat_findWordList = /^(?:(?:request|include|see)\s*(?:an?|the?)\s*(?:feature|addon|addition|plugin))|(?:(?:add|see|get)\s*support\s*(?:for|with|of))|(?:can\s*we\s*get\s*(?:the|a)\s*(?:ability|feature))|(?:💡 Feature:)$/igm;
|
const feat_findWordList = /(?:(?:add|enjoy|would|like|can|request|include|see|could|have)\s*?(?:the|liked?|i|we|an?|the|you?)\s*?(?:to|have|an|get|ability|request|add|feature|functionality|addon|addition|plugin|create))|(?:(?:add|see|get)\s*?support\s*?(?:for|with|of))|(?:can\s*we\s*get\s*?(?:the|a)\s*?(?:ability|feature))|(?:💡 Feature:)$/igm;
|
||||||
const feat_bFoundMatchTitle = Boolean( feat_findWordList.test( iss_title ) );
|
const feat_bFoundMatchTitle = Boolean( feat_findWordList.test( iss_title ) );
|
||||||
const feat_bFoundMatchBody = Boolean( feat_findWordList.test( iss_body ) );
|
const feat_bFoundMatchBody = Boolean( feat_findWordList.test( iss_body ) );
|
||||||
|
|
||||||
@@ -460,17 +520,49 @@ jobs:
|
|||||||
if ( author === `${{ env.BOT_NAME_DEPENDABOT }}` )
|
if ( author === `${{ env.BOT_NAME_DEPENDABOT }}` )
|
||||||
core.info( `Skipping: Detected ${ author }` )
|
core.info( `Skipping: Detected ${ author }` )
|
||||||
|
|
||||||
// Rename title to contain Feature:
|
if ( author === `${{ env.BOT_NAME_RENOVATE }}` )
|
||||||
|
core.info( `Skipping: Detected ${ author }` )
|
||||||
|
|
||||||
|
/*
|
||||||
|
Rename title to contain Feature:
|
||||||
|
if feature title or body contains keyword hinting at the issue being about a feature; change the title of the issue
|
||||||
|
|
||||||
|
@ref https://jsfiddle.net/aetherinox/wj17x8mp/2/
|
||||||
|
*/
|
||||||
if ( author !== `${{ env.BOT_NAME_DEPENDABOT }}` && !feat_bFoundPRTitle && !iss_title_lc.startsWith( bug_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( feat_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( urgn_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( road_tag.toLowerCase( ) ) )
|
if ( author !== `${{ env.BOT_NAME_DEPENDABOT }}` && !feat_bFoundPRTitle && !iss_title_lc.startsWith( bug_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( feat_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( urgn_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( road_tag.toLowerCase( ) ) )
|
||||||
{
|
{
|
||||||
const title = issue.title;
|
|
||||||
|
/*
|
||||||
|
If a user creates an issue starting with our tag; strip it and add ours with the emoji instead
|
||||||
|
original: Feature: CMD windows opens then closes, can't run the script.
|
||||||
|
new: 💡 Feature: CMD windows opens then closes, can't run the script.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const removeBeginning1 = feat_tag.substring(3); // "Feature:"
|
||||||
|
let removeBeginning2 = feat_tag.substring(0); // "💡 Feature:"
|
||||||
|
removeBeginning2 = removeBeginning2.replace(/\s/g, '') // "Feature:"
|
||||||
|
|
||||||
|
if ( iss_title.startsWith(removeBeginning1) )
|
||||||
|
{
|
||||||
|
iss_title = iss_title.slice(removeBeginning1.length);
|
||||||
|
iss_title = iss_title.trim();
|
||||||
|
}
|
||||||
|
else if ( iss_title.startsWith(removeBeginning2) )
|
||||||
|
{
|
||||||
|
iss_title = iss_title.slice(removeBeginning2.length);
|
||||||
|
iss_title = iss_title.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = iss_title;
|
||||||
let title_new = title.replace( /^\s?feature\s*(.*?)\b/gi, '' );
|
let title_new = title.replace( /^\s?feature\s*(.*?)\b/gi, '' );
|
||||||
title_new = title.replace( /^\s?request\s*(.*?)\b/gi, '' );
|
title_new = title.replace( /^\s?request\s*(.*?)\b/gi, '' );
|
||||||
title_new = title.replace( /^\s?add(.*?)\s?feature\s*(.*?)\b/gi, '' );
|
title_new = title.replace( /^\s?add(.*?)\s?feature\s*(.*?)\b/gi, '' );
|
||||||
title_new = title.replace( /^\s?add(.*?)\s?support\s*(.*?)\b/gi, '' );
|
title_new = title.replace( /^\s?add(.*?)\s?support\s*(.*?)\b/gi, '' );
|
||||||
iss_title = `${ feat_tag } ${ title_new }`;
|
iss_title = `${ feat_tag } ${ title_new }`; // change TAG per category
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log( `New Title: ...................... ${ iss_title }` )
|
||||||
|
|
||||||
await github.rest.issues.update(
|
await github.rest.issues.update(
|
||||||
{
|
{
|
||||||
owner: context.repo.owner, repo: context.repo.repo, issue_number: issue.number,
|
owner: context.repo.owner, repo: context.repo.repo, issue_number: issue.number,
|
||||||
@@ -518,10 +610,40 @@ jobs:
|
|||||||
if ( author === `${{ env.BOT_NAME_DEPENDABOT }}` )
|
if ( author === `${{ env.BOT_NAME_DEPENDABOT }}` )
|
||||||
core.info( `Skipping: Detected ${ author }` )
|
core.info( `Skipping: Detected ${ author }` )
|
||||||
|
|
||||||
// Rename title to contain Urgent:
|
if ( author === `${{ env.BOT_NAME_RENOVATE }}` )
|
||||||
|
core.info( `Skipping: Detected ${ author }` )
|
||||||
|
|
||||||
|
/*
|
||||||
|
Rename title to contain Urgent:
|
||||||
|
if urgent title or body contains keyword hinting at the issue being about urgent; change the title of the issue
|
||||||
|
|
||||||
|
@ref https://jsfiddle.net/aetherinox/wj17x8mp/2/
|
||||||
|
*/
|
||||||
if ( author !== `${{ env.BOT_NAME_DEPENDABOT }}` && !urgn_bFoundPRTitle && !iss_title_lc.startsWith( bug_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( feat_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( urgn_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( road_tag.toLowerCase( ) ) )
|
if ( author !== `${{ env.BOT_NAME_DEPENDABOT }}` && !urgn_bFoundPRTitle && !iss_title_lc.startsWith( bug_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( feat_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( urgn_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( road_tag.toLowerCase( ) ) )
|
||||||
{
|
{
|
||||||
const title = issue.title;
|
|
||||||
|
/*
|
||||||
|
If a user creates an issue starting with our tag; strip it and add ours with the emoji instead
|
||||||
|
original: Urgent: CMD windows opens then closes, can't run the script.
|
||||||
|
new: ⚠ Urgent: CMD windows opens then closes, can't run the script.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const removeBeginning1 = urgn_tag.substring(3); // "Urgent:"
|
||||||
|
let removeBeginning2 = urgn_tag.substring(0); // "⚠ Urgent:"
|
||||||
|
removeBeginning2 = removeBeginning2.replace(/\s/g, '') // "Urgent:"
|
||||||
|
|
||||||
|
if ( iss_title.startsWith(removeBeginning1) )
|
||||||
|
{
|
||||||
|
iss_title = iss_title.slice(removeBeginning1.length);
|
||||||
|
iss_title = iss_title.trim();
|
||||||
|
}
|
||||||
|
else if ( iss_title.startsWith(removeBeginning2) )
|
||||||
|
{
|
||||||
|
iss_title = iss_title.slice(removeBeginning2.length);
|
||||||
|
iss_title = iss_title.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = iss_title;
|
||||||
let title_new = title.replace( /^\s?emergency\s*(.*?)\b/gi, '' );
|
let title_new = title.replace( /^\s?emergency\s*(.*?)\b/gi, '' );
|
||||||
title_new = title.replace( /^\s?urgent\s*(.*?)\b/gi, '' );
|
title_new = title.replace( /^\s?urgent\s*(.*?)\b/gi, '' );
|
||||||
title_new = title.replace( /^\s?urgency\s*(.*?)\b/gi, '' );
|
title_new = title.replace( /^\s?urgency\s*(.*?)\b/gi, '' );
|
||||||
@@ -530,6 +652,8 @@ jobs:
|
|||||||
iss_title = `${ urgn_tag } ${ title_new }`;
|
iss_title = `${ urgn_tag } ${ title_new }`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log( `New Title: ...................... ${ iss_title }` )
|
||||||
|
|
||||||
await github.rest.issues.update(
|
await github.rest.issues.update(
|
||||||
{
|
{
|
||||||
owner: context.repo.owner, repo: context.repo.repo, issue_number: issue.number,
|
owner: context.repo.owner, repo: context.repo.repo, issue_number: issue.number,
|
||||||
@@ -552,8 +676,8 @@ jobs:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const road_findWordList = /#\s*Summary[\S\s]+#\s*(?:Proposal|Objective)[^\]]+/igm;
|
const road_findWordList = /#\s*Summary[\S\s]+#\s*(?:Proposal|Objective)[^\]]+/igm;
|
||||||
const road_bFoundMatchTitle = Boolean( road_findWordList.test( iss_title ) );
|
const road_bFoundMatchTitle = Boolean( road_findWordList.test( iss_title ) );
|
||||||
const road_bFoundMatchBody = Boolean( road_findWordList.test( iss_body ) );
|
const road_bFoundMatchBody = Boolean( road_findWordList.test( iss_body ) );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Do not change a title if the item starts with a PR: #
|
Do not change a title if the item starts with a PR: #
|
||||||
@@ -562,8 +686,8 @@ jobs:
|
|||||||
https://regex101.com/r/JOrqbN/1
|
https://regex101.com/r/JOrqbN/1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const road_findPRTitle = /^PR\s?#?(?:[0-9]*:)/igm;
|
const road_findPRTitle = /^PR\s?#?(?:[0-9]*:)/igm;
|
||||||
const road_bFoundPRTitle = Boolean( road_findPRTitle.test( iss_title ) );
|
const road_bFoundPRTitle = Boolean( road_findPRTitle.test( iss_title ) );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
- Check if issue title matches the issue label "Roadmap:"
|
- Check if issue title matches the issue label "Roadmap:"
|
||||||
@@ -578,18 +702,48 @@ jobs:
|
|||||||
if ( author === `${{ env.BOT_NAME_DEPENDABOT }}` )
|
if ( author === `${{ env.BOT_NAME_DEPENDABOT }}` )
|
||||||
core.info( `Skipping: Detected ${ author }` )
|
core.info( `Skipping: Detected ${ author }` )
|
||||||
|
|
||||||
// Rename title to contain Roadmap:
|
if ( author === `${{ env.BOT_NAME_RENOVATE }}` )
|
||||||
|
core.info( `Skipping: Detected ${ author }` )
|
||||||
|
|
||||||
|
/*
|
||||||
|
Rename title to contain Roadmap:
|
||||||
|
if roadmap title or body contains keyword hinting at the issue being about roadmap; change the title of the issue
|
||||||
|
|
||||||
|
@ref https://jsfiddle.net/aetherinox/wj17x8mp/2/
|
||||||
|
*/
|
||||||
if ( author !== `${{ env.BOT_NAME_DEPENDABOT }}` && !road_bFoundPRTitle && !iss_title_lc.startsWith( bug_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( feat_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( urgn_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( road_tag.toLowerCase( ) ) )
|
if ( author !== `${{ env.BOT_NAME_DEPENDABOT }}` && !road_bFoundPRTitle && !iss_title_lc.startsWith( bug_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( feat_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( urgn_tag.toLowerCase( ) ) && !iss_title_lc.startsWith( road_tag.toLowerCase( ) ) )
|
||||||
{
|
{
|
||||||
const title = issue.title;
|
|
||||||
let title_new = title.replace( /^\s?emergency\s*(.*?)\b/gi, '' );
|
/*
|
||||||
title_new = title.replace( /^\s?urgent\s*(.*?)\b/gi, '' );
|
If a user creates an issue starting with our tag; strip it and add ours with the emoji instead
|
||||||
title_new = title.replace( /^\s?urgency\s*(.*?)\b/gi, '' );
|
original: Roadmap: CMD windows opens then closes, can't run the script.
|
||||||
title_new = title.replace( /^\s?important\s*(.*?)\b/gi, '' );
|
new: 🗺️ Roadmap: CMD windows opens then closes, can't run the script.
|
||||||
title_new = title.replace( /^\s?critical\s*(.*?)\b/gi, '' );
|
*/
|
||||||
iss_title = `${ road_tag } ${ title_new }`;
|
|
||||||
|
const removeBeginning1 = road_tag.substring(3); // "Roadmap:"
|
||||||
|
let removeBeginning2 = road_tag.substring(0); // "🗺️ Roadmap:"
|
||||||
|
removeBeginning2 = removeBeginning2.replace(/\s/g, '') // "Roadmap:"
|
||||||
|
|
||||||
|
if ( iss_title.startsWith(removeBeginning1) )
|
||||||
|
{
|
||||||
|
iss_title = iss_title.slice(removeBeginning1.length);
|
||||||
|
iss_title = iss_title.trim();
|
||||||
|
}
|
||||||
|
else if ( iss_title.startsWith(removeBeginning2) )
|
||||||
|
{
|
||||||
|
iss_title = iss_title.slice(removeBeginning2.length);
|
||||||
|
iss_title = iss_title.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = iss_title;
|
||||||
|
let title_new = title.replace( /^\s?broad(.*?)\s?map\s*(.*?)\b/gi, '' );
|
||||||
|
title_new = title.replace( /^\s?planned\s*(.*?)\b/gi, '' );
|
||||||
|
title_new = title.replace( /^\s?broadmap\s*(.*?)\b/gi, '' );
|
||||||
|
iss_title = `${ road_tag } ${ title_new }`; // change TAG per category
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log( `New Title: ...................... ${ iss_title }` )
|
||||||
|
|
||||||
await github.rest.issues.update(
|
await github.rest.issues.update(
|
||||||
{
|
{
|
||||||
owner: context.repo.owner, repo: context.repo.repo, issue_number: issue.number,
|
owner: context.repo.owner, repo: context.repo.repo, issue_number: issue.number,
|
||||||
@@ -607,14 +761,15 @@ jobs:
|
|||||||
}
|
}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Job [ Stale Issues ]
|
# Issues (Stale) › Stale
|
||||||
# #
|
# #
|
||||||
|
|
||||||
job-issues-stale:
|
job-issues-stale:
|
||||||
name: >-
|
name: >-
|
||||||
💤 Check › Stale
|
💤 Scan › Check Stale
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
timeout-minutes: 4
|
runs-on: apollo-x64
|
||||||
|
timeout-minutes: 5
|
||||||
needs:
|
needs:
|
||||||
- job-labels-create
|
- job-labels-create
|
||||||
- job-issues-nolabel
|
- job-issues-nolabel
|
||||||
@@ -624,57 +779,60 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# [ Stale Issues ] Check Condition
|
# Stale › Check Condition
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "💤 Stale › Check Condition"
|
- name: >-
|
||||||
uses: actions/stale@v9
|
💤 Stale › Check Condition
|
||||||
id: task_issues_stale_run
|
id: task_issues_inactive_stale
|
||||||
with:
|
uses: actions/stale@v9
|
||||||
repo-token: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
with:
|
||||||
stale-issue-message: |
|
repo-token: ${{ secrets.ADMINSERV_TOKEN_CL || github.token }}
|
||||||
⚠️ It looks like there hasn't been any recent updates on this issue. If you created this issue and no longer consider it open, then please login to github and close the issue.
|
stale-issue-message: |
|
||||||
|
⚠️ It looks like there hasn't been any recent updates on this issue. If you created this issue and no longer consider it open, then please login to github and close the issue.
|
||||||
|
|
||||||
If there is no further activity on this issue, it will be automatically closed in the next week.
|
If there is no further activity on this issue, it will be automatically closed in the next week.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<sub>I am a bot reaching out to you with an automated response.</sub>
|
<sub>I am a bot reaching out to you with an automated response.</sub>
|
||||||
stale-issue-label: 'Status 𐄂 Stale'
|
stale-issue-label: '${{ env.LABEL_STALE }}'
|
||||||
close-issue-label: 'Status 𐄂 Autoclosed'
|
close-issue-label: '${{ env.LABEL_AUTOCLOSE }}'
|
||||||
exempt-issue-labels: 'Status 𐄂 Accepted,Status 𐄂 Review,Status 𐄂 Pending,Type ◦ Bug,Type ◦ Dependency,Type ◦ Docs,Type ◦ Feature,Type ◦ Git Action,Type ◦ Pull Request,Type ◦ Roadmap'
|
exempt-issue-labels: '${{ env.LABEL_ACCEPTED }},${{ env.LABEL_REVIEW }},${{ env.LABEL_PENDING }},${{ env.LABEL_BUG }},${{ env.LABEL_DEPENDENCY }},${{ env.LABEL_DOCS }},${{ env.LABEL_FEATURE }},${{ env.LABEL_GIT }},${{ env.LABEL_PR }},${{ env.LABEL_ROADMAP }}'
|
||||||
days-before-stale: 60
|
days-before-stale: 120
|
||||||
days-before-close: 7
|
days-before-close: 7
|
||||||
days-before-pr-stale: -1
|
days-before-pr-stale: -1
|
||||||
days-before-pr-close: -1
|
days-before-pr-close: -1
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Job [ Lock Issues ]
|
# Issues (Stale) › Lock
|
||||||
# #
|
# #
|
||||||
|
|
||||||
job-issues-lock:
|
job-issues-lock:
|
||||||
name: >-
|
name: >-
|
||||||
🔒 Check › Inactive
|
🔒 Scan › Lock Inactive
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
timeout-minutes: 4
|
runs-on: apollo-x64
|
||||||
|
timeout-minutes: 5
|
||||||
needs:
|
needs:
|
||||||
- job-labels-create
|
- job-labels-create
|
||||||
- job-issues-nolabel
|
- job-issues-nolabel
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# [ Lock Issues ] Look for inactives
|
# Inactive › Lock
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "🔒 Lock › Inactives"
|
- name: >-
|
||||||
|
🔒 Inactive › Lock
|
||||||
|
id: task_issues_inactive_lock
|
||||||
uses: dessant/lock-threads@v5
|
uses: dessant/lock-threads@v5
|
||||||
id: task_issues_lock_run
|
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
github-token: ${{ secrets.ADMINSERV_TOKEN_CL || github.token }}
|
||||||
exclude-any-issue-labels: 'AC › Review Required,Status 𐄂 Accepted,Status 𐄂 Review,Status 𐄂 Pending,Type ◦ Bug,Type ◦ Dependency,Type ◦ Docs,Type ◦ Feature,Type ◦ Git Action,Type ◦ Roadmap,Type ◦ Internal'
|
exclude-any-issue-labels: '${{ env.LABEL_AC_REVIEW }},${{ env.LABEL_ACCEPTED }},${{ env.LABEL_REVIEW }},${{ env.LABEL_PENDING }},${{ env.LABEL_BUG }},${{ env.LABEL_DEPENDENCY }},${{ env.LABEL_DOCS }},${{ env.LABEL_FEATURE }},${{ env.LABEL_GIT }},${{ env.LABEL_ROADMAP }},${{ env.LABEL_INTERNAL }}'
|
||||||
add-issue-labels: 'Status 𐄂 Locked'
|
add-issue-labels: '${{ env.LABEL_LOCKED }}'
|
||||||
issue-inactive-days: '60'
|
issue-inactive-days: '120'
|
||||||
issue-lock-reason: 'resolved'
|
issue-lock-reason: 'resolved'
|
||||||
issue-comment: >
|
issue-comment: >
|
||||||
⚠️ This **issue** has been automatically locked since there has not been any recent activity after it was closed.
|
⚠️ This **issue** has been automatically locked since there has not been any recent activity after it was closed.
|
||||||
@@ -684,8 +842,8 @@ jobs:
|
|||||||
---
|
---
|
||||||
|
|
||||||
<sub>I am a bot reaching out to you with an automated response.</sub>
|
<sub>I am a bot reaching out to you with an automated response.</sub>
|
||||||
exclude-any-pr-labels: 'AC › Review Required,Status 𐄂 Accepted,Status 𐄂 Review,Status 𐄂 Pending,Type ◦ Bug,Type ◦ Dependency,Type ◦ Docs,Type ◦ Feature,Type ◦ Git Action,Type ◦ Roadmap,Type ◦ Internal'
|
exclude-any-pr-labels: '${{ env.LABEL_AC_REVIEW }},${{ env.LABEL_ACCEPTED }},${{ env.LABEL_REVIEW }},${{ env.LABEL_PENDING }},${{ env.LABEL_BUG }},${{ env.LABEL_DEPENDENCY }},${{ env.LABEL_DOCS }},${{ env.LABEL_FEATURE }},${{ env.LABEL_GIT }},${{ env.LABEL_ROADMAP }},${{ env.LABEL_INTERNAL }}'
|
||||||
add-pr-labels: 'Status 𐄂 Locked'
|
add-pr-labels: '${{ env.LABEL_LOCKED }}'
|
||||||
pr-inactive-days: '365'
|
pr-inactive-days: '365'
|
||||||
pr-lock-reason: 'resolved'
|
pr-lock-reason: 'resolved'
|
||||||
pr-comment: >
|
pr-comment: >
|
||||||
|
|||||||
171
.github/workflows/labels-clean.yml
vendored
@@ -13,15 +13,15 @@
|
|||||||
# secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/
|
# secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/
|
||||||
# secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/
|
# secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/
|
||||||
# secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token
|
# secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token
|
||||||
# secrets.ORG_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
# secrets.ORG_TOKEN org github personal access token (fine-grained)
|
||||||
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
# secrets.ORG_TOKEN_CL org github personal access token (classic)
|
||||||
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
# secrets.ORG_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
# secrets.ORG_BINARYNINJA_GITEA_TOKEN org gitea personal access token (classic) with package:write permission
|
# secrets.ORG_GITEA_TOKEN org gitea personal access token (classic) with package:write permission
|
||||||
# secrets.BINARYSERV_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK
|
# secrets.BOT_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK
|
||||||
# secrets.BINARYSERV_GPG_PASSPHRASE bot gpg private key passphrase
|
# secrets.BOT_GPG_PASSPHRASE bot gpg private key passphrase
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_RELEASES discord webhook to report release notifications from github to discord
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_RELEASES discord webhook to report release notifications from github to discord
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_WORKFLOWS discord webhook to report workflow notifications from github to discord
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_WORKFLOWS discord webhook to report workflow notifications from github to discord
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_UPDATES discord webhook to report activity notifications from github to discord
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_UPDATES discord webhook to report activity notifications from github to discord
|
||||||
#
|
#
|
||||||
# @local these workflows can be tested locally through the use of `act`
|
# @local these workflows can be tested locally through the use of `act`
|
||||||
# https://github.com/nektos/act
|
# https://github.com/nektos/act
|
||||||
@@ -33,8 +33,8 @@
|
|||||||
# act -W .github/workflows/labels-clean.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
# act -W .github/workflows/labels-clean.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "🎫 Labels › Remove"
|
name: '🧹 Labels › Clean'
|
||||||
run-name: "🎫 Labels › Remove"
|
run-name: '🧹 Labels › Clean'
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# triggers
|
# triggers
|
||||||
@@ -65,40 +65,40 @@ env:
|
|||||||
{ "name": "invalid", "color": "8F1784", "description": "Default github label" },
|
{ "name": "invalid", "color": "8F1784", "description": "Default github label" },
|
||||||
{ "name": "question", "color": "8F1784", "description": "Default github label" },
|
{ "name": "question", "color": "8F1784", "description": "Default github label" },
|
||||||
{ "name": "wontfix", "color": "8F1784", "description": "Default github label" },
|
{ "name": "wontfix", "color": "8F1784", "description": "Default github label" },
|
||||||
{ "name": "AC › Changes Made", "color": "8F1784", "description": "Requested changes have been made and are pending a re-scan" },
|
{ "name": "AC › Changes Made", "color": "8F1784", "description": "Requested changes have been made and are pending a re-scan" },
|
||||||
{ "name": "AC › Changes Required", "color": "8F1784", "description": "Requires changes to be made to the package before being accepted" },
|
{ "name": "AC › Changes Required", "color": "8F1784", "description": "Requires changes to be made to the package before being accepted" },
|
||||||
{ "name": "AC › Failed", "color": "a61f2d", "description": "Autocheck failed to run through a complete cycle, requires investigation" },
|
{ "name": "AC › Failed", "color": "a61f2d", "description": "Autocheck failed to run through a complete cycle, requires investigation" },
|
||||||
{ "name": "AC › Needs Rebase", "color": "8F1784", "description": "Due to the permissions on the requesting repo, this pull request must be rebased by the author" },
|
{ "name": "AC › Needs Rebase", "color": "8F1784", "description": "Due to the permissions on the requesting repo, this pull request must be rebased by the author" },
|
||||||
{ "name": "AC › Passed", "color": "146b4a", "description": "Ready to be reviewed" },
|
{ "name": "AC › Passed", "color": "146b4a", "description": "Ready to be reviewed" },
|
||||||
{ "name": "AC › Review Required", "color": "8F1784", "description": "PR needs to be reviewed by another person, after the requested changes have been made" },
|
{ "name": "AC › Review Required", "color": "8F1784", "description": "PR needs to be reviewed by another person, after the requested changes have been made" },
|
||||||
{ "name": "AC › Security Warning", "color": "761620", "description": "Does not conform to developer policies, or includes potentially dangerous code" },
|
{ "name": "AC › Security Warning", "color": "761620", "description": "Does not conform to developer policies, or includes potentially dangerous code" },
|
||||||
{ "name": "AC › Skipped Scan", "color": "8F1784", "description": "Author has skipped code scan" },
|
{ "name": "AC › Skipped Scan", "color": "8F1784", "description": "Author has skipped code scan" },
|
||||||
{ "name": "Status 𐄂 Duplicate", "color": "75536b", "description": "Issue or pull request already exists" },
|
{ "name": "Status › Duplicate", "color": "75536b", "description": "Issue or pull request already exists" },
|
||||||
{ "name": "Status 𐄂 Accepted", "color": "2e7539", "description": "This pull request has been accepted" },
|
{ "name": "Status › Accepted", "color": "2e7539", "description": "This pull request has been accepted" },
|
||||||
{ "name": "Status 𐄂 Autoclosed", "color": "3E0915", "description": "Originally stale and was autoclosed for no activity" },
|
{ "name": "Status › Autoclosed", "color": "3E0915", "description": "Originally stale and was autoclosed for no activity" },
|
||||||
{ "name": "Status 𐄂 Denied", "color": "ba4058", "description": "Pull request has been denied" },
|
{ "name": "Status › Denied", "color": "ba4058", "description": "Pull request has been denied" },
|
||||||
{ "name": "Status 𐄂 Locked", "color": "550F45", "description": "Automatically locked by AdminServ for a prolonged period of inactivity" },
|
{ "name": "Status › Locked", "color": "550F45", "description": "Automatically locked by AdminServ for a prolonged period of inactivity" },
|
||||||
{ "name": "Status 𐄂 Need Info", "color": "2E3C4C", "description": "Not enough information to resolve" },
|
{ "name": "Status › Need Info", "color": "2E3C4C", "description": "Not enough information to resolve" },
|
||||||
{ "name": "Status 𐄂 No Action", "color": "030406", "description": "Closed without any action being taken" },
|
{ "name": "Status › No Action", "color": "030406", "description": "Closed without any action being taken" },
|
||||||
{ "name": "Status 𐄂 Pending", "color": "984b12", "description": "Pending pull request" },
|
{ "name": "Status › Pending", "color": "984b12", "description": "Pending pull request" },
|
||||||
{ "name": "Status 𐄂 Released", "color": "1b6626", "description": "Issues or PR has been implemented and is now live" },
|
{ "name": "Status › Released", "color": "1b6626", "description": "Issues or PR has been implemented and is now live" },
|
||||||
{ "name": "Status 𐄂 Reopened", "color": "8a6f14", "description": "A previously closed PR which has been re-opened" },
|
{ "name": "Status › Reopened", "color": "8a6f14", "description": "A previously closed PR which has been re-opened" },
|
||||||
{ "name": "Status 𐄂 Review", "color": "9e1451", "description": "Currently pending review" },
|
{ "name": "Status › Review", "color": "9e1451", "description": "Currently pending review" },
|
||||||
{ "name": "Status 𐄂 Stale", "color": "928282", "description": "Has not had any activity in over 30 days" },
|
{ "name": "Status › Stale", "color": "928282", "description": "Has not had any activity in over 30 days" },
|
||||||
{ "name": "Type ◦ Bug", "color": "9a2c2c", "description": "Something isn't working" },
|
{ "name": "Type › Bug", "color": "9a2c2c", "description": "Something isn't working" },
|
||||||
{ "name": "Type ◦ Dependency", "color": "243759", "description": "Item is associated to dependency" },
|
{ "name": "Type › Dependency", "color": "243759", "description": "Item is associated to dependency" },
|
||||||
{ "name": "Type ◦ Docs", "color": "0e588d", "description": "Improvements or modifications to docs" },
|
{ "name": "Type › Docs", "color": "0e588d", "description": "Improvements or modifications to docs" },
|
||||||
{ "name": "Type ◦ Feature", "color": "3c4e93", "description": "Feature request" },
|
{ "name": "Type › Feature", "color": "3c4e93", "description": "Feature request" },
|
||||||
{ "name": "Type ◦ Git Action", "color": "030406", "description": "GitHub Action / workflow" },
|
{ "name": "Type › Git Action", "color": "030406", "description": "GitHub Action / workflow" },
|
||||||
{ "name": "Type ◦ Pull Request", "color": "8F1784", "description": "Normal pull request" },
|
{ "name": "Type › Pull Request", "color": "8F1784", "description": "Normal pull request" },
|
||||||
{ "name": "Type ◦ Roadmap", "color": "8F1784", "description": "Feature or bug currently planned for implementation" },
|
{ "name": "Type › Roadmap", "color": "8F1784", "description": "Feature or bug currently planned for implementation" },
|
||||||
{ "name": "Type ◦ Internal", "color": "A51994", "description": "Assigned items are for internal developer use" },
|
{ "name": "Type › Internal", "color": "A51994", "description": "Assigned items are for internal developer use" },
|
||||||
{ "name": "Build ◦ Desktop", "color": "c7ca4a", "description": "Specific to desktop" },
|
{ "name": "Build › Desktop", "color": "c7ca4a", "description": "Specific to desktop" },
|
||||||
{ "name": "Build ◦ Linux", "color": "c7ca4a", "description": "Specific to Linux" },
|
{ "name": "Build › Linux", "color": "c7ca4a", "description": "Specific to Linux" },
|
||||||
{ "name": "Build ◦ MacOS", "color": "c7ca4a", "description": "Specific to MacOS" },
|
{ "name": "Build › MacOS", "color": "c7ca4a", "description": "Specific to MacOS" },
|
||||||
{ "name": "Build ◦ Mobile", "color": "c7ca4a", "description": "Specific to mobile" },
|
{ "name": "Build › Mobile", "color": "c7ca4a", "description": "Specific to mobile" },
|
||||||
{ "name": "Build ◦ Web", "color": "c7ca4a", "description": "Specific to web" },
|
{ "name": "Build › Web", "color": "c7ca4a", "description": "Specific to web" },
|
||||||
{ "name": "Build ◦ Windows", "color": "c7ca4a", "description": "Specific to Windows" },
|
{ "name": "Build › Windows", "color": "c7ca4a", "description": "Specific to Windows" },
|
||||||
{ "name": "› API", "color": "F99B50", "description": "Plugin API, CLI, browser JS API" },
|
{ "name": "› API", "color": "F99B50", "description": "Plugin API, CLI, browser JS API" },
|
||||||
{ "name": "› Auto-type", "color": "9141E0", "description": "Auto-type functionality in desktop apps" },
|
{ "name": "› Auto-type", "color": "9141E0", "description": "Auto-type functionality in desktop apps" },
|
||||||
{ "name": "› Browser", "color": "9141E0", "description": "Browser plugins and passing data to <=> from app" },
|
{ "name": "› Browser", "color": "9141E0", "description": "Browser plugins and passing data to <=> from app" },
|
||||||
@@ -137,12 +137,12 @@ jobs:
|
|||||||
# This job removes all existing labels
|
# This job removes all existing labels
|
||||||
# #
|
# #
|
||||||
|
|
||||||
issues-labels-remove:
|
issues-labels-clean:
|
||||||
name: >-
|
name: >-
|
||||||
🎫 Labels › Remove
|
🧹 Labels › Clean
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
runs-on: apollo-x64
|
||||||
timeout-minutes: 4
|
timeout-minutes: 3
|
||||||
permissions:
|
permissions:
|
||||||
contents: 'read'
|
contents: 'read'
|
||||||
id-token: 'write'
|
id-token: 'write'
|
||||||
@@ -164,9 +164,10 @@ jobs:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
🕛 Get Timestamp
|
🕛 Get Timestamp
|
||||||
id: task_label_set_timestamp
|
id: task_label_set_timestamp
|
||||||
run: |
|
run: |
|
||||||
|
echo "YEAR=$(date +'%Y')" >> $GITHUB_ENV
|
||||||
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV
|
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV
|
||||||
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV
|
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV
|
||||||
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV
|
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV
|
||||||
@@ -192,7 +193,7 @@ jobs:
|
|||||||
id: task_label_remove_run
|
id: task_label_remove_run
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
github-token: ${{ secrets.ADMINSERV_TOKEN_CL || github.token }}
|
||||||
script: |
|
script: |
|
||||||
const targetOwner = context.repo.owner;
|
const targetOwner = context.repo.owner;
|
||||||
const targetRepo = context.repo.repo;
|
const targetRepo = context.repo.repo;
|
||||||
@@ -249,73 +250,3 @@ jobs:
|
|||||||
echo 'WEEKLY_COMMITS<<EOF' >> $GITHUB_ENV
|
echo 'WEEKLY_COMMITS<<EOF' >> $GITHUB_ENV
|
||||||
git log --format="[\`%h\`](${{ github.server_url }}/${{ github.repository }}/commit/%H) %s - %an" --since=7.days >> $GITHUB_ENV
|
git log --format="[\`%h\`](${{ github.server_url }}/${{ github.repository }}/commit/%H) %s - %an" --since=7.days >> $GITHUB_ENV
|
||||||
echo 'EOF' >> $GITHUB_ENV
|
echo 'EOF' >> $GITHUB_ENV
|
||||||
|
|
||||||
# #
|
|
||||||
# Labels › Notify Github › Success
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: >-
|
|
||||||
🔔 Send Discord Webhook Message (Success)
|
|
||||||
id: task_label_notify_discord_success
|
|
||||||
uses: tsickert/discord-webhook@v7.0.0
|
|
||||||
if: success()
|
|
||||||
with:
|
|
||||||
username: 'Io'
|
|
||||||
avatar-url: 'https://i.imgur.com/8BVDkla.jpg'
|
|
||||||
webhook-url: ${{ secrets.DISCORD_WEBHOOK_CHAN_TVAPP2_WORKFLOWS }}
|
|
||||||
embed-title: "⚙️ ${{ github.workflow_ref }}"
|
|
||||||
embed-url: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
|
||||||
embed-thumbnail-url: 'https://i.imgur.com/zDIzE8T.jpg'
|
|
||||||
embed-description: |
|
|
||||||
## 🎫 Labels › Clean ${{ job.status == 'success' && '✅' || '❌' }}
|
|
||||||
|
|
||||||
A **successful** workflow has been ran to wipe all labels from your repository.
|
|
||||||
|
|
||||||
**${{ steps.task_label_remove_run.outputs.result }}** labels have been removed.
|
|
||||||
|
|
||||||
- Labels: `${{ steps.task_label_remove_run.outputs.result }} created`
|
|
||||||
- Workflow: `${{ github.workflow }} (#${{github.run_number}})`
|
|
||||||
- Runner: `${{ runner.name }}`
|
|
||||||
- Triggered By: `${{ github.actor }}`
|
|
||||||
- Status: `${{ job.status == 'success' && '✅ Successful' || '❌ Failed' }}`
|
|
||||||
|
|
||||||
embed-color: ${{ job.status == 'success' && '5763719' || '15418782' }}
|
|
||||||
embed-footer-text: "Completed at ${{ env.NOW }} UTC"
|
|
||||||
embed-timestamp: "${{ env.NOW_LONG }}"
|
|
||||||
embed-author-name: "${{ github.repository_owner }}"
|
|
||||||
embed-author-url: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
|
||||||
embed-author-icon-url: "https://avatars.githubusercontent.com/u/200161462"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Labels › Notify Github › Failure
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: >-
|
|
||||||
🔔 Send Discord Webhook Message (Failure)
|
|
||||||
id: task_label_notify_discord_failure
|
|
||||||
uses: tsickert/discord-webhook@v7.0.0
|
|
||||||
if: failure()
|
|
||||||
with:
|
|
||||||
username: 'Io'
|
|
||||||
avatar-url: 'https://i.imgur.com/8BVDkla.jpg'
|
|
||||||
webhook-url: ${{ secrets.DISCORD_WEBHOOK_CHAN_TVAPP2_WORKFLOWS }}
|
|
||||||
embed-title: "⚙️ ${{ github.workflow_ref }}"
|
|
||||||
embed-url: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
|
||||||
embed-thumbnail-url: 'https://i.imgur.com/zDIzE8T.jpg'
|
|
||||||
embed-description: |
|
|
||||||
## 🎫 Labels › Clean ${{ job.status == 'success' && '✅' || '❌' }}
|
|
||||||
|
|
||||||
A **failed** attempt was made to run this workflow. No new labels have been added to your repository.
|
|
||||||
|
|
||||||
- Labels: `${{ steps.task_label_remove_run.outputs.result }} created`
|
|
||||||
- Workflow: `${{ github.workflow }} (#${{github.run_number}})`
|
|
||||||
- Runner: `${{ runner.name }}`
|
|
||||||
- Triggered By: `${{ github.actor }}`
|
|
||||||
- Status: `${{ job.status == 'success' && '✅ Successful' || '❌ Failed' }}`
|
|
||||||
|
|
||||||
embed-color: ${{ job.status == 'success' && '5763719' || '15418782' }}
|
|
||||||
embed-footer-text: "Completed at ${{ env.NOW }} UTC"
|
|
||||||
embed-timestamp: "${{ env.NOW_LONG }}"
|
|
||||||
embed-author-name: "${{ github.repository_owner }}"
|
|
||||||
embed-author-url: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
|
||||||
embed-author-icon-url: "https://avatars.githubusercontent.com/u/200161462"
|
|
||||||
|
|||||||
114
.github/workflows/labels-create.yml
vendored
@@ -4,34 +4,21 @@
|
|||||||
# @url https://github.com/Aetherinox
|
# @url https://github.com/Aetherinox
|
||||||
# @usage manually activated workflow to create issue labels
|
# @usage manually activated workflow to create issue labels
|
||||||
#
|
#
|
||||||
# @notes This Github action must be activated manually. This workflow script will do the following:
|
|
||||||
#
|
|
||||||
# - Scan issues / pull requests and make sure they have properly assigned labels:
|
|
||||||
# - `Bug`
|
|
||||||
# - `Feature`
|
|
||||||
# - `Urgent`
|
|
||||||
# - `Roadmap`
|
|
||||||
#
|
|
||||||
# - Workflow script will then scan each pr or issue and mark them as `Stale`
|
|
||||||
# if they haven't had any replies in 30 days.
|
|
||||||
#
|
|
||||||
# - Workflow will `autoclose` pr or issues which haven't had action in `365 days`.
|
|
||||||
#
|
|
||||||
# @secrets secrets.SELF_TOKEN self github personal access token (fine-grained)
|
# @secrets secrets.SELF_TOKEN self github personal access token (fine-grained)
|
||||||
# secrets.SELF_TOKEN_CL self github personal access token (classic)
|
# secrets.SELF_TOKEN_CL self github personal access token (classic)
|
||||||
# secrets.NPM_TOKEN self npmjs access token
|
# secrets.NPM_TOKEN self npmjs access token
|
||||||
# secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/
|
# secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/
|
||||||
# secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/
|
# secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/
|
||||||
# secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token
|
# secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token
|
||||||
# secrets.ORG_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
# secrets.ORG_TOKEN org github personal access token (fine-grained)
|
||||||
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
# secrets.ORG_TOKEN_CL org github personal access token (classic)
|
||||||
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
# secrets.ORG_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
# secrets.ORG_BINARYNINJA_GITEA_TOKEN org gitea personal access token (classic) with package:write permission
|
# secrets.ORG_GITEA_TOKEN org gitea personal access token (classic) with package:write permission
|
||||||
# secrets.BINARYSERV_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK
|
# secrets.BOT_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK
|
||||||
# secrets.BINARYSERV_GPG_PASSPHRASE bot gpg private key passphrase
|
# secrets.BOT_GPG_PASSPHRASE bot gpg private key passphrase
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_RELEASES discord webhook to report release notifications from github to discord
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_RELEASES discord webhook to report release notifications from github to discord
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_WORKFLOWS discord webhook to report workflow notifications from github to discord
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_WORKFLOWS discord webhook to report workflow notifications from github to discord
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_UPDATES discord webhook to report activity notifications from github to discord
|
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_UPDATES discord webhook to report activity notifications from github to discord
|
||||||
#
|
#
|
||||||
# @local these workflows can be tested locally through the use of `act`
|
# @local these workflows can be tested locally through the use of `act`
|
||||||
# https://github.com/nektos/act
|
# https://github.com/nektos/act
|
||||||
@@ -43,8 +30,8 @@
|
|||||||
# act -W .github/workflows/labels-create.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
# act -W .github/workflows/labels-create.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "🎫 Labels › Create"
|
name: '🎫 Labels › Create'
|
||||||
run-name: "🎫 Labels › Create"
|
run-name: '🎫 Labels › Create'
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# triggers
|
# triggers
|
||||||
@@ -66,40 +53,40 @@ env:
|
|||||||
|
|
||||||
LABELS_JSON: |
|
LABELS_JSON: |
|
||||||
[
|
[
|
||||||
{ "name": "AC › Changes Made", "color": "8F1784", "description": "Requested changes have been made and are pending a re-scan" },
|
{ "name": "AC › Changes Made", "color": "8F1784", "description": "Requested changes have been made and are pending a re-scan" },
|
||||||
{ "name": "AC › Changes Required", "color": "8F1784", "description": "Requires changes to be made to the package before being accepted" },
|
{ "name": "AC › Changes Required", "color": "8F1784", "description": "Requires changes to be made to the package before being accepted" },
|
||||||
{ "name": "AC › Failed", "color": "a61f2d", "description": "Autocheck failed to run through a complete cycle, requires investigation" },
|
{ "name": "AC › Failed", "color": "a61f2d", "description": "Autocheck failed to run through a complete cycle, requires investigation" },
|
||||||
{ "name": "AC › Needs Rebase", "color": "8F1784", "description": "Due to the permissions on the requesting repo, this pull request must be rebased by the author" },
|
{ "name": "AC › Needs Rebase", "color": "8F1784", "description": "Due to the permissions on the requesting repo, this pull request must be rebased by the author" },
|
||||||
{ "name": "AC › Passed", "color": "146b4a", "description": "Ready to be reviewed" },
|
{ "name": "AC › Passed", "color": "146b4a", "description": "Ready to be reviewed" },
|
||||||
{ "name": "AC › Review Required", "color": "8F1784", "description": "PR needs to be reviewed by another person, after the requested changes have been made" },
|
{ "name": "AC › Review Required", "color": "8F1784", "description": "PR needs to be reviewed by another person, after the requested changes have been made" },
|
||||||
{ "name": "AC › Security Warning", "color": "761620", "description": "Does not conform to developer policies, or includes potentially dangerous code" },
|
{ "name": "AC › Security Warning", "color": "761620", "description": "Does not conform to developer policies, or includes potentially dangerous code" },
|
||||||
{ "name": "AC › Skipped Scan", "color": "8F1784", "description": "Author has skipped code scan" },
|
{ "name": "AC › Skipped Scan", "color": "8F1784", "description": "Author has skipped code scan" },
|
||||||
{ "name": "Status 𐄂 Duplicate", "color": "75536b", "description": "Issue or pull request already exists" },
|
{ "name": "Status › Duplicate", "color": "75536b", "description": "Issue or pull request already exists" },
|
||||||
{ "name": "Status 𐄂 Accepted", "color": "2e7539", "description": "This pull request has been accepted" },
|
{ "name": "Status › Accepted", "color": "2e7539", "description": "This pull request has been accepted" },
|
||||||
{ "name": "Status 𐄂 Autoclosed", "color": "3E0915", "description": "Originally stale and was autoclosed for no activity" },
|
{ "name": "Status › Autoclosed", "color": "3E0915", "description": "Originally stale and was autoclosed for no activity" },
|
||||||
{ "name": "Status 𐄂 Denied", "color": "ba4058", "description": "Pull request has been denied" },
|
{ "name": "Status › Denied", "color": "ba4058", "description": "Pull request has been denied" },
|
||||||
{ "name": "Status 𐄂 Locked", "color": "550F45", "description": "Automatically locked by AdminServ for a prolonged period of inactivity" },
|
{ "name": "Status › Locked", "color": "550F45", "description": "Automatically locked by AdminServ for a prolonged period of inactivity" },
|
||||||
{ "name": "Status 𐄂 Need Info", "color": "2E3C4C", "description": "Not enough information to resolve" },
|
{ "name": "Status › Need Info", "color": "2E3C4C", "description": "Not enough information to resolve" },
|
||||||
{ "name": "Status 𐄂 No Action", "color": "030406", "description": "Closed without any action being taken" },
|
{ "name": "Status › No Action", "color": "030406", "description": "Closed without any action being taken" },
|
||||||
{ "name": "Status 𐄂 Pending", "color": "984b12", "description": "Pending pull request" },
|
{ "name": "Status › Pending", "color": "984b12", "description": "Pending pull request" },
|
||||||
{ "name": "Status 𐄂 Released", "color": "1b6626", "description": "Issues or PR has been implemented and is now live" },
|
{ "name": "Status › Released", "color": "1b6626", "description": "Issues or PR has been implemented and is now live" },
|
||||||
{ "name": "Status 𐄂 Reopened", "color": "8a6f14", "description": "A previously closed PR which has been re-opened" },
|
{ "name": "Status › Reopened", "color": "8a6f14", "description": "A previously closed PR which has been re-opened" },
|
||||||
{ "name": "Status 𐄂 Review", "color": "9e1451", "description": "Currently pending review" },
|
{ "name": "Status › Review", "color": "9e1451", "description": "Currently pending review" },
|
||||||
{ "name": "Status 𐄂 Stale", "color": "928282", "description": "Has not had any activity in over 30 days" },
|
{ "name": "Status › Stale", "color": "928282", "description": "Has not had any activity in over 30 days" },
|
||||||
{ "name": "Type ◦ Bug", "color": "9a2c2c", "description": "Something isn't working" },
|
{ "name": "Type › Bug", "color": "9a2c2c", "description": "Something isn't working" },
|
||||||
{ "name": "Type ◦ Dependency", "color": "243759", "description": "Item is associated to dependency" },
|
{ "name": "Type › Dependency", "color": "243759", "description": "Item is associated to dependency" },
|
||||||
{ "name": "Type ◦ Docs", "color": "0e588d", "description": "Improvements or modifications to docs" },
|
{ "name": "Type › Docs", "color": "0e588d", "description": "Improvements or modifications to docs" },
|
||||||
{ "name": "Type ◦ Feature", "color": "3c4e93", "description": "Feature request" },
|
{ "name": "Type › Feature", "color": "3c4e93", "description": "Feature request" },
|
||||||
{ "name": "Type ◦ Git Action", "color": "030406", "description": "GitHub Action / workflow" },
|
{ "name": "Type › Git Action", "color": "030406", "description": "GitHub Action / workflow" },
|
||||||
{ "name": "Type ◦ Pull Request", "color": "8F1784", "description": "Normal pull request" },
|
{ "name": "Type › Pull Request", "color": "8F1784", "description": "Normal pull request" },
|
||||||
{ "name": "Type ◦ Roadmap", "color": "8F1784", "description": "Feature or bug currently planned for implementation" },
|
{ "name": "Type › Roadmap", "color": "8F1784", "description": "Feature or bug currently planned for implementation" },
|
||||||
{ "name": "Type ◦ Internal", "color": "A51994", "description": "Assigned items are for internal developer use" },
|
{ "name": "Type › Internal", "color": "A51994", "description": "Assigned items are for internal developer use" },
|
||||||
{ "name": "Build ◦ Desktop", "color": "c7ca4a", "description": "Specific to desktop" },
|
{ "name": "Build › Desktop", "color": "c7ca4a", "description": "Specific to desktop" },
|
||||||
{ "name": "Build ◦ Linux", "color": "c7ca4a", "description": "Specific to Linux" },
|
{ "name": "Build › Linux", "color": "c7ca4a", "description": "Specific to Linux" },
|
||||||
{ "name": "Build ◦ MacOS", "color": "c7ca4a", "description": "Specific to MacOS" },
|
{ "name": "Build › MacOS", "color": "c7ca4a", "description": "Specific to MacOS" },
|
||||||
{ "name": "Build ◦ Mobile", "color": "c7ca4a", "description": "Specific to mobile" },
|
{ "name": "Build › Mobile", "color": "c7ca4a", "description": "Specific to mobile" },
|
||||||
{ "name": "Build ◦ Web", "color": "c7ca4a", "description": "Specific to web" },
|
{ "name": "Build › Web", "color": "c7ca4a", "description": "Specific to web" },
|
||||||
{ "name": "Build ◦ Windows", "color": "c7ca4a", "description": "Specific to Windows" },
|
{ "name": "Build › Windows", "color": "c7ca4a", "description": "Specific to Windows" },
|
||||||
{ "name": "› API", "color": "F99B50", "description": "Plugin API, CLI, browser JS API" },
|
{ "name": "› API", "color": "F99B50", "description": "Plugin API, CLI, browser JS API" },
|
||||||
{ "name": "› Auto-type", "color": "9141E0", "description": "Auto-type functionality in desktop apps" },
|
{ "name": "› Auto-type", "color": "9141E0", "description": "Auto-type functionality in desktop apps" },
|
||||||
{ "name": "› Browser", "color": "9141E0", "description": "Browser plugins and passing data to <=> from app" },
|
{ "name": "› Browser", "color": "9141E0", "description": "Browser plugins and passing data to <=> from app" },
|
||||||
@@ -142,7 +129,9 @@ jobs:
|
|||||||
issues-labels-create:
|
issues-labels-create:
|
||||||
name: >-
|
name: >-
|
||||||
🎫 Labels › Create
|
🎫 Labels › Create
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
|
runs-on: apollo-x64
|
||||||
|
timeout-minutes: 3
|
||||||
permissions:
|
permissions:
|
||||||
contents: 'read'
|
contents: 'read'
|
||||||
id-token: 'write'
|
id-token: 'write'
|
||||||
@@ -167,6 +156,7 @@ jobs:
|
|||||||
🕛 Get Timestamp
|
🕛 Get Timestamp
|
||||||
id: task_label_set_timestamp
|
id: task_label_set_timestamp
|
||||||
run: |
|
run: |
|
||||||
|
echo "YEAR=$(date +'%Y')" >> $GITHUB_ENV
|
||||||
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV
|
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV
|
||||||
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV
|
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV
|
||||||
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV
|
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV
|
||||||
@@ -192,7 +182,7 @@ jobs:
|
|||||||
id: task_label_verify_existing
|
id: task_label_verify_existing
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
github-token: ${{ secrets.ADMINSERV_TOKEN_CL || github.token }}
|
||||||
script: |
|
script: |
|
||||||
const labels = JSON.parse( process.env.LABELS_JSON );
|
const labels = JSON.parse( process.env.LABELS_JSON );
|
||||||
let result = Object.keys(labels).length;
|
let result = Object.keys(labels).length;
|
||||||
@@ -250,7 +240,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
username: 'Io'
|
username: 'Io'
|
||||||
avatar-url: 'https://i.imgur.com/8BVDkla.jpg'
|
avatar-url: 'https://i.imgur.com/8BVDkla.jpg'
|
||||||
webhook-url: ${{ secrets.DISCORD_WEBHOOK_CHAN_TVAPP2_WORKFLOWS }}
|
webhook-url: ${{ secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_WORKfLOWS }}
|
||||||
embed-title: "⚙️ ${{ github.workflow_ref }}"
|
embed-title: "⚙️ ${{ github.workflow_ref }}"
|
||||||
embed-url: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
embed-url: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||||
embed-thumbnail-url: 'https://i.imgur.com/zDIzE8T.jpg'
|
embed-thumbnail-url: 'https://i.imgur.com/zDIzE8T.jpg'
|
||||||
@@ -286,7 +276,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
username: 'Io'
|
username: 'Io'
|
||||||
avatar-url: 'https://i.imgur.com/8BVDkla.jpg'
|
avatar-url: 'https://i.imgur.com/8BVDkla.jpg'
|
||||||
webhook-url: ${{ secrets.DISCORD_WEBHOOK_CHAN_TVAPP2_WORKFLOWS }}
|
webhook-url: ${{ secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_WORKfLOWS }}
|
||||||
embed-title: "⚙️ ${{ github.workflow_ref }}"
|
embed-title: "⚙️ ${{ github.workflow_ref }}"
|
||||||
embed-url: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
embed-url: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||||
embed-thumbnail-url: 'https://i.imgur.com/zDIzE8T.jpg'
|
embed-thumbnail-url: 'https://i.imgur.com/zDIzE8T.jpg'
|
||||||
|
|||||||
295
.github/workflows/release.yml
vendored
@@ -77,23 +77,23 @@ on:
|
|||||||
type: boolean
|
type: boolean
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# ENABLE: released version will be marked as pre-release
|
# true released version will be marked as a development build and will have the v1.x.x-development tag instead of -latest
|
||||||
# DISABLE: release version will be marked as stable / normal release
|
# false release version will be marked with -latest docker tag
|
||||||
# #
|
# #
|
||||||
|
|
||||||
PRERELEASE:
|
RC_RELEASE:
|
||||||
description: '🧪 Build RC (Pre-release)'
|
description: '🧪 Build RC (Pre-release)'
|
||||||
required: true
|
required: true
|
||||||
default: false
|
default: false
|
||||||
type: boolean
|
type: boolean
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release Candidate version number
|
# only needed if env variable `RC_ONLY` = true
|
||||||
# this will be added to the end of your released app in the releases page.
|
# sets the version number for the release candidate
|
||||||
# e.g: tvapp2-v1.0.0-rc.1
|
# e.g: noxenv-v1.0.0-rc.1
|
||||||
# #
|
# #
|
||||||
|
|
||||||
VERSION_RC:
|
RC_VERSION:
|
||||||
description: '🧪 RC (Pre-release) Ver (tvapp2-rc.v1)'
|
description: '🧪 RC (Pre-release) Ver (tvapp2-rc.v1)'
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
@@ -105,15 +105,17 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
PROJECT_NAME: ${{ github.event.inputs.PROJECT_NAME || 'tvapp2' }}
|
PROJECT_NAME: ${{ github.event.inputs.PROJECT_NAME || 'tvapp2' }}
|
||||||
CHANGELOG_MODE_COMMIT: true
|
CHANGELOG_MODE_COMMIT: ${{ github.event.inputs.CHANGELOG_MODE_COMMIT || true }}
|
||||||
SHOW_UNCATEGORIZED: false
|
SHOW_UNCATEGORIZED: ${{ github.event.inputs.SHOW_UNCATEGORIZED || false }}
|
||||||
PRERELEASE: false
|
RC_RELEASE: ${{ github.event.inputs.RC_RELEASE || false }}
|
||||||
VERSION_RC: '1'
|
RC_VERSION: ${{ github.event.inputs.RC_VERSION || '1' }}
|
||||||
ASSIGN_USER: Aetherinox
|
ASSIGN_USER: Aetherinox
|
||||||
BOT_NAME_1: EuropaServ
|
BOT_NAME_1: EuropaServ
|
||||||
BOT_NAME_2: BinaryServ
|
BOT_NAME_2: BinaryServ
|
||||||
BOT_NAME_DEPENDABOT: dependabot[bot]
|
BOT_NAME_DEPENDABOT: dependabot[bot]
|
||||||
BOT_NAME_RENOVATE: renovate[bot]
|
BOT_NAME_RENOVATE: renovate[bot]
|
||||||
|
GPG_KEY_BASE64: ${{ secrets.ADMINSERV_GPG_KEY_B64 }}
|
||||||
|
GPG_KEY_PASSPHRASE: ${{ secrets.ADMINSERV_GPG_PASSPHRASE }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Jobs
|
# Jobs
|
||||||
@@ -207,6 +209,20 @@ jobs:
|
|||||||
packages: write
|
packages: write
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Set Env Variables
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: >-
|
||||||
|
🕛 Get Timestamp
|
||||||
|
id: task_release_label_set_timestamp
|
||||||
|
run: |
|
||||||
|
echo "YEAR=$(date +'%Y')" >> $GITHUB_ENV
|
||||||
|
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV
|
||||||
|
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV
|
||||||
|
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV
|
||||||
|
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Checkout
|
# Release › Checkout
|
||||||
# #
|
# #
|
||||||
@@ -218,17 +234,22 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Set Env Variables
|
# Release › Start
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
🕛 Get Timestamp
|
✅ Start
|
||||||
id: task_release_label_set_timestamp
|
id: task_release_start
|
||||||
run: |
|
run: |
|
||||||
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV
|
echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――"
|
||||||
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV
|
echo " Starting Documentation Build script"
|
||||||
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV
|
echo " Runner .............. ${{ runner.name }}"
|
||||||
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV
|
echo " Workflow ............ ${{ github.workflow }} (#${{ github.workflow_ref }})"
|
||||||
|
echo " Run Number .......... #${{ github.run_number }}"
|
||||||
|
echo " Run ID .............. https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||||
|
echo " Triggered By ........ ${{ github.actor }}"
|
||||||
|
echo " Time ................ ${{ env.NOW_LONG }}"
|
||||||
|
echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Print Version Debug
|
# Release › Print Version Debug
|
||||||
@@ -243,11 +264,12 @@ jobs:
|
|||||||
# Release › Install package via NPM
|
# Release › Install package via NPM
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '🪪 NPM › Install'
|
- name: '🪪 NPM › Install & Lint'
|
||||||
id: task_release_npm_install
|
id: task_release_npm_install
|
||||||
working-directory: ./tvapp2
|
working-directory: ./tvapp2
|
||||||
run: |
|
run: |
|
||||||
npm ci
|
npm ci
|
||||||
|
npm run lint
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.SELF_TOKEN_CL }}
|
NODE_AUTH_TOKEN: ${{ secrets.SELF_TOKEN_CL }}
|
||||||
|
|
||||||
@@ -287,15 +309,17 @@ jobs:
|
|||||||
# Release › Build › Stable
|
# Release › Build › Stable
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '🔨 Build › Stable ( ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip )'
|
- name: '🔨 Build › Stable › ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip'
|
||||||
id: task_release_build_st
|
id: task_release_build_st
|
||||||
if: ${{ startsWith( inputs.PRERELEASE, false ) }}
|
if: |
|
||||||
|
startsWith( inputs.RC_RELEASE, false ) ||
|
||||||
|
startsWith( env.RC_RELEASE, false )
|
||||||
run: |
|
run: |
|
||||||
echo Building STABLE Package ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip
|
echo Building STABLE Package ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip
|
||||||
zip -r ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip Dockerfile Dockerfile.aarch64 docker-compose.yml docker-entrypoint.sh root/ tvapp2/package.json README.md LICENSE
|
zip -r ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip Dockerfile Dockerfile.aarch64 docker-compose.yml docker-entrypoint.sh root/ tvapp2/package.json README.md LICENSE
|
||||||
|
|
||||||
echo Building STABLE Package ${{ env.PROJECT_NAME }}-v${{ env.PACKAGE_VERSION }}-docker-compose.zip
|
echo Building STABLE Package ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-docker-compose.zip
|
||||||
zip -r ${{ env.PROJECT_NAME }}-v${{ env.PACKAGE_VERSION }}-docker-compose.zip docker-compose.yml README.md LICENSE
|
zip -r ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-docker-compose.zip docker-compose.yml README.md LICENSE
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
NODE_AUTH_TOKEN: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
||||||
|
|
||||||
@@ -303,15 +327,17 @@ jobs:
|
|||||||
# Release › Build › Release Candidate
|
# Release › Build › Release Candidate
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '🔨 Build › RC ( ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.VERSION_RC }}.zip )'
|
- name: '🔨 Build › Release Candidate › ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.RC_VERSION }}.zip'
|
||||||
id: task_release_build_rc
|
id: task_release_build_rc
|
||||||
if: ${{ startsWith( inputs.PRERELEASE, true ) }}
|
if: |
|
||||||
|
startsWith( inputs.RC_RELEASE, true ) ||
|
||||||
|
startsWith( env.RC_RELEASE, true )
|
||||||
run: |
|
run: |
|
||||||
echo Building PRE-RELEASE Package ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.VERSION_RC }}.zip
|
echo Building PRE-RELEASE Package ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.RC_VERSION }}.zip
|
||||||
zip -r ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.VERSION_RC }}.zip Dockerfile Dockerfile.aarch64 docker-compose.yml docker-entrypoint.sh root/ tvapp2/package.json README.md LICENSE
|
zip -r ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.RC_VERSION }}.zip Dockerfile Dockerfile.aarch64 docker-compose.yml docker-entrypoint.sh root/ tvapp2/package.json README.md LICENSE
|
||||||
|
|
||||||
echo Building PRE-RELEASE Package ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.VERSION_RC }}-docker-compose.zip
|
echo Building PRE-RELEASE Package ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.RC_VERSION }}-docker-compose.zip
|
||||||
zip -r ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.VERSION_RC }}-docker-compose.zip docker-compose.yml README.md LICENSE
|
zip -r ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.RC_VERSION }}-docker-compose.zip docker-compose.yml README.md LICENSE
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
NODE_AUTH_TOKEN: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
||||||
|
|
||||||
@@ -345,39 +371,93 @@ jobs:
|
|||||||
echo "Tag already present: ${{ env.TAG_EXISTS }}"
|
echo "Tag already present: ${{ env.TAG_EXISTS }}"
|
||||||
echo "Tag already present: ${{ steps.task_release_tag_create.outputs.tag_exists }}"
|
echo "Tag already present: ${{ steps.task_release_tag_create.outputs.tag_exists }}"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › GPG › Import Key (No Passphrase)
|
||||||
|
#
|
||||||
|
# requires your GPG private key, converted to base64 binary .gpg (not armored .asc)
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🪪 GPG › Import Signing Key › W/o Passphrase'
|
||||||
|
id: task_release_gpg_import_nopass
|
||||||
|
if: env.GPG_KEY_BASE64 != '' && env.GPG_KEY_PASSPHRASE == ''
|
||||||
|
run: |
|
||||||
|
echo $GPG_KEY_BASE64 | base64 -di | gpg --import
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › GPG › Import Key (With Passphrase)
|
||||||
|
#
|
||||||
|
# requires your GPG private key, converted to base64 binary .gpg (not armored .asc)
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🪪 GPG › Import Signing Key › w/ Passphrase'
|
||||||
|
id: task_release_gpg_import_withpass
|
||||||
|
if: env.GPG_KEY_BASE64 != '' && env.GPG_KEY_PASSPHRASE != ''
|
||||||
|
run: |
|
||||||
|
echo "$GPG_KEY_BASE64" | base64 -di > /tmp/signing-key.gpg
|
||||||
|
echo "$GPG_KEY_PASSPHRASE" | gpg --pinentry-mode loopback --passphrase-fd 0 --import /tmp/signing-key.gpg
|
||||||
|
(echo "$GPG_KEY_PASSPHRASE"; echo; echo) | gpg --command-fd 0 --pinentry-mode loopback --change-passphrase $(gpg --list-secret-keys --with-colons 2> /dev/null | grep '^sec:' | cut --delimiter ':' --fields 5 | tail -n 1)
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Checksum › Stable
|
# Release › Checksum › Stable
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '🆔 Checksum › Stable'
|
- name: '🆔 Checksum › Stable'
|
||||||
id: task_release_checksum_st_set
|
id: task_release_checksum_st_set
|
||||||
if: ${{ startsWith( inputs.PRERELEASE, false ) }}
|
if: |
|
||||||
|
startsWith( inputs.RC_RELEASE, false ) ||
|
||||||
|
startsWith( env.RC_RELEASE, false )
|
||||||
run: |
|
run: |
|
||||||
filename_zip="${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip"
|
filename_zip="${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip"
|
||||||
sha256="$(shasum --algorithm 256 ${filename_zip} | awk '{ print $1 }')"
|
|
||||||
shasum --algorithm 256 ${filename_zip} > SHA256SUMS.txt
|
# get sha1 and sha256 for .zip and .gz files
|
||||||
|
find . -maxdepth 1 \( -name '*.zip' -o -name '*.gz' \) -printf '%P\n' | xargs -r sha1sum | gpg --digest-algo sha256 --clearsign > sha1sum.txt.asc
|
||||||
|
find . -maxdepth 1 \( -name '*.zip' -o -name '*.gz' \) -printf '%P\n' | xargs -r sha256sum | gpg --digest-algo sha256 --clearsign > sha256sum.txt.asc
|
||||||
|
|
||||||
|
# get sha1sum; assign to variable
|
||||||
|
sha1sum="$(shasum --algorithm 1 ${filename_zip} | awk '{ print $1 }')"
|
||||||
|
echo "SHA1SUM=${sha1sum}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# get sha256sum; assign to variable
|
||||||
|
sha256sum="$(shasum --algorithm 256 ${filename_zip} | awk '{ print $1 }')"
|
||||||
|
echo "SHA256SUM=${sha256sum}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# no longer needed, replaced by find . command
|
||||||
|
# shasum --algorithm 256 ${filename_zip} > SHA256SUMS.txt
|
||||||
echo "FILE_ZIP=${filename_zip}" >> $GITHUB_ENV
|
echo "FILE_ZIP=${filename_zip}" >> $GITHUB_ENV
|
||||||
echo "SHA256SUM=${sha256}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
filename_compose_zip="${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-docker-compose.zip"
|
filename_compose_zip="${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-docker-compose.zip"
|
||||||
sha256_compose="$(shasum --algorithm 256 ${filename_compose_zip} | awk '{ print $1 }')"
|
sha256sum_compose="$(shasum --algorithm 256 ${filename_compose_zip} | awk '{ print $1 }')"
|
||||||
echo "FILE_COMPOSE_ZIP=${filename_compose_zip}" >> $GITHUB_ENV
|
echo "FILE_COMPOSE_ZIP=${filename_compose_zip}" >> $GITHUB_ENV
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Checksum › Release Candidate
|
# Release › Checksum › Release Candidate
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '🆔 Checksum › RC'
|
- name: '🆔 Checksum › Release Candidate'
|
||||||
id: task_release_checksum_rc_set
|
id: task_release_checksum_rc_set
|
||||||
if: ${{ startsWith( inputs.PRERELEASE, true ) }}
|
if: |
|
||||||
|
startsWith( inputs.RC_RELEASE, true ) ||
|
||||||
|
startsWith( env.RC_RELEASE, true )
|
||||||
run: |
|
run: |
|
||||||
filename_zip="${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.VERSION_RC }}.zip"
|
filename_zip="${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.RC_VERSION }}.zip"
|
||||||
sha256="$(shasum --algorithm 256 ${filename_zip} | awk '{ print $1 }')"
|
|
||||||
shasum --algorithm 256 ${filename_zip} > SHA256SUMS.txt
|
|
||||||
echo "FILE_ZIP=${filename_zip}" >> $GITHUB_ENV
|
|
||||||
echo "SHA256SUM=${sha256}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
filename_compose_zip="${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.VERSION_RC }}-docker-compose.zip"
|
# get sha1 and sha256 for .zip and .gz files
|
||||||
|
find . -maxdepth 1 \( -name '*.zip' -o -name '*.gz' \) -printf '%P\n' | xargs -r sha1sum | gpg --digest-algo sha256 --clearsign > sha1sum.txt.asc
|
||||||
|
find . -maxdepth 1 \( -name '*.zip' -o -name '*.gz' \) -printf '%P\n' | xargs -r sha256sum | gpg --digest-algo sha256 --clearsign > sha256sum.txt.asc
|
||||||
|
|
||||||
|
# get sha1sum; assign to variable
|
||||||
|
sha1sum="$(shasum --algorithm 1 ${filename_zip} | awk '{ print $1 }')"
|
||||||
|
echo "SHA1SUM=${sha1sum}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# get sha256sum; assign to variable
|
||||||
|
sha256sum="$(shasum --algorithm 256 ${filename_zip} | awk '{ print $1 }')"
|
||||||
|
echo "SHA256SUM=${sha256sum}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# no longer needed, replaced by find . command
|
||||||
|
# shasum --algorithm 256 ${filename_zip} > SHA256SUMS.txt
|
||||||
|
echo "FILE_ZIP=${filename_zip}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
filename_compose_zip="${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.RC_VERSION }}-docker-compose.zip"
|
||||||
sha256_compose="$(shasum --algorithm 256 ${filename_compose_zip} | awk '{ print $1 }')"
|
sha256_compose="$(shasum --algorithm 256 ${filename_compose_zip} | awk '{ print $1 }')"
|
||||||
echo "FILE_COMPOSE_ZIP=${filename_compose_zip}" >> $GITHUB_ENV
|
echo "FILE_COMPOSE_ZIP=${filename_compose_zip}" >> $GITHUB_ENV
|
||||||
|
|
||||||
@@ -403,30 +483,15 @@ jobs:
|
|||||||
avatarSize: 42
|
avatarSize: 42
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Checksum › Add (Stable)
|
# Release › Changelog › Generate Tags
|
||||||
|
#
|
||||||
|
# generates a changelog from the github api. requires a PREVIOUS_TAG in order to figure
|
||||||
|
# out the changes made between the two versions.
|
||||||
|
#
|
||||||
|
# outputs:
|
||||||
|
# ${{ steps.changelog.outputs.changelog }}
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '📦 Zip › Add Checksum › Stable'
|
|
||||||
id: task_release_zip_st
|
|
||||||
if: ${{ startsWith( inputs.PRERELEASE, false ) }}
|
|
||||||
run: |
|
|
||||||
echo Zipping STABLE Package .zip ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip
|
|
||||||
zip -jr ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip SHA256SUMS.txt
|
|
||||||
ls
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Checksum › Add (Release Candidate)
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '📦 Zip › Add Checksum › RC'
|
|
||||||
id: task_release_zip_rc
|
|
||||||
if: ${{ startsWith( inputs.PRERELEASE, true ) }}
|
|
||||||
run: |
|
|
||||||
echo Zipping PRE-RELEASE Package .zip ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.VERSION_RC }}.zip
|
|
||||||
zip -jr ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.VERSION_RC }}.zip SHA256SUMS.txt
|
|
||||||
ls
|
|
||||||
|
|
||||||
|
|
||||||
- name: '📝 Changelog › Pre Setup (Categorized Commits)'
|
- name: '📝 Changelog › Pre Setup (Categorized Commits)'
|
||||||
id: task_release_changelog_categorized_sha_set
|
id: task_release_changelog_categorized_sha_set
|
||||||
run: |
|
run: |
|
||||||
@@ -539,14 +604,56 @@ jobs:
|
|||||||
echo "$CHANGELOG_UNCATEGORIZED"
|
echo "$CHANGELOG_UNCATEGORIZED"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › List Tree
|
# Release › Verbose › List Tree
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '⚙️ Debug › Clean Dist Folder'
|
- name: '⚙️ Verbose › Tree Listing'
|
||||||
id: task_release_debug_tree
|
id: task_release_verbose_tree
|
||||||
run: |
|
run: |
|
||||||
tree
|
tree
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Verbose › Changelog › Print Categorized
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '⚙️ Verbose › Changelog › Categorized'
|
||||||
|
id: task_release_changelog_verbose_categorized
|
||||||
|
if: |
|
||||||
|
startsWith( inputs.SHOW_UNCATEGORIZED, false ) ||
|
||||||
|
startsWith( env.SHOW_UNCATEGORIZED, false )
|
||||||
|
env:
|
||||||
|
CHANGELOG_CATEGORIZED: ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
|
CHANGELOG_UNCATEGORIZED: ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
|
run: |
|
||||||
|
echo
|
||||||
|
echo "---- CHANGELOG [ Categorized ] -----------------------------------------------"
|
||||||
|
echo
|
||||||
|
echo "$CHANGELOG_CATEGORIZED"
|
||||||
|
echo
|
||||||
|
echo "---- CHANGELOG ---------------------------------------------------------------"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Verbose › Changelog › Print Uncategorized
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '⚙️ Verbose › Changelog › Uncategorized'
|
||||||
|
id: task_release_changelog_verbose_uncategorized
|
||||||
|
if: |
|
||||||
|
startsWith( inputs.SHOW_UNCATEGORIZED, true ) ||
|
||||||
|
startsWith( env.SHOW_UNCATEGORIZED, true )
|
||||||
|
env:
|
||||||
|
CHANGELOG_CATEGORIZED: ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
|
CHANGELOG_UNCATEGORIZED: ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
|
run: |
|
||||||
|
echo
|
||||||
|
echo "---- CHANGELOG [ Uncategorized ] ---------------------------------------------"
|
||||||
|
echo
|
||||||
|
echo "$CHANGELOG_UNCATEGORIZED"
|
||||||
|
echo
|
||||||
|
echo "---- CHANGELOG ---------------------------------------------------------------"
|
||||||
|
echo
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Post Release (Stable)
|
# Release › Post Release (Stable)
|
||||||
#
|
#
|
||||||
@@ -559,10 +666,12 @@ jobs:
|
|||||||
- name: '🏳️ Post › Stable'
|
- name: '🏳️ Post › Stable'
|
||||||
id: task_release_bundle_st
|
id: task_release_bundle_st
|
||||||
if: |
|
if: |
|
||||||
startsWith( inputs.PRERELEASE, false ) ||
|
startsWith( inputs.RC_RELEASE, false ) ||
|
||||||
startsWith( env.PRERELEASE, false )
|
startsWith( env.RC_RELEASE, false )
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
env:
|
env:
|
||||||
|
CHANGELOG_CATEGORIZED: ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
|
CHANGELOG_UNCATEGORIZED: ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
GITHUB_TOKEN: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
GITHUB_TOKEN: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
token: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
||||||
@@ -572,9 +681,10 @@ jobs:
|
|||||||
draft: false
|
draft: false
|
||||||
generate_release_notes: false
|
generate_release_notes: false
|
||||||
files: |
|
files: |
|
||||||
${{ env.PROJECT_NAME }}-v${{ env.PACKAGE_VERSION }}-docker-compose.zip
|
${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-docker-compose.zip
|
||||||
${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip
|
${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip
|
||||||
SHA256SUMS.txt
|
sha1sum.txt.asc
|
||||||
|
sha256sum.txt.asc
|
||||||
prerelease: false
|
prerelease: false
|
||||||
body: |
|
body: |
|
||||||
${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
@@ -589,14 +699,16 @@ jobs:
|
|||||||
# ${{ steps.task_release_bundle_st.outputs.id
|
# ${{ steps.task_release_bundle_st.outputs.id
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "🏳️ Post › Release Candidate"
|
- name: '🏳️ Post › Release Candidate'
|
||||||
id: task_release_bundle_rc
|
id: task_release_bundle_rc
|
||||||
if: |
|
if: |
|
||||||
startsWith( inputs.PRERELEASE, true ) ||
|
startsWith( inputs.RC_RELEASE, true ) ||
|
||||||
startsWith( env.PRERELEASE, true )
|
startsWith( env.RC_RELEASE, true )
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.ADMINSERV_TOKEN }}
|
CHANGELOG_CATEGORIZED: ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
|
CHANGELOG_UNCATEGORIZED: ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.ADMINSERV_TOKEN }}
|
token: ${{ secrets.ADMINSERV_TOKEN }}
|
||||||
name: v${{ env.PACKAGE_VERSION }}
|
name: v${{ env.PACKAGE_VERSION }}
|
||||||
@@ -605,9 +717,10 @@ jobs:
|
|||||||
draft: false
|
draft: false
|
||||||
generate_release_notes: false
|
generate_release_notes: false
|
||||||
files: |
|
files: |
|
||||||
${{ env.PROJECT_NAME }}-v${{ env.PACKAGE_VERSION }}-rc.${{ inputs.VERSION_RC }}-docker-compose.zip
|
${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.RC_VERSION }}-docker-compose.zip
|
||||||
${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.VERSION_RC }}.zip
|
${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.RC_VERSION }}.zip
|
||||||
SHA256SUMS.txt
|
sha1sum.txt.asc
|
||||||
|
sha256sum.txt.asc
|
||||||
prerelease: false
|
prerelease: false
|
||||||
body: |
|
body: |
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
@@ -651,19 +764,37 @@ jobs:
|
|||||||
echo "---- CHANGELOG ---------------------------------------------------------------"
|
echo "---- CHANGELOG ---------------------------------------------------------------"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Upload Artifacts › Release Files
|
# Release › Upload Artifacts › Release Files › Stable
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
📋 Upload Artifacts › ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip
|
📋 Upload Artifacts › Stable › ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip
|
||||||
id: task_release_artifact
|
id: task_release_artifact_stable
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
if: always()
|
if: |
|
||||||
|
startsWith( inputs.RC_RELEASE, false ) ||
|
||||||
|
startsWith( env.RC_RELEASE, false )
|
||||||
with:
|
with:
|
||||||
name: "${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}"
|
name: "${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}"
|
||||||
path: ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip
|
path: ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Upload Artifacts › Release Files › Release Candidate
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: >-
|
||||||
|
📋 Upload Artifacts › RC › ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip
|
||||||
|
id: task_release_artifact_rc
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: |
|
||||||
|
startsWith( inputs.RC_RELEASE, true ) ||
|
||||||
|
startsWith( env.RC_RELEASE, true )
|
||||||
|
with:
|
||||||
|
name: "${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.RC_VERSION }}"
|
||||||
|
path: ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.RC_VERSION }}.zip
|
||||||
|
retention-days: 30
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Job › Complete
|
# Job › Complete
|
||||||
# #
|
# #
|
||||||
|
|||||||
58
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment include:
|
||||||
|
|
||||||
|
- Using welcoming and inclusive language
|
||||||
|
- Being respectful of differing viewpoints and experiences
|
||||||
|
- Gracefully accepting constructive criticism
|
||||||
|
- Focusing on what is best for the community
|
||||||
|
- Showing empathy towards other community members
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
- The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||||
|
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
|
- Public or private harassment
|
||||||
|
- Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||||
|
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Our Responsibilities
|
||||||
|
|
||||||
|
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at `thebinaryninja [at] proton [dot] me`. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
|
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [📄 Contributor Covenant][homepage], version 2.1, available at [https://contributor-covenant.org/version/2/1/][version]
|
||||||
|
|
||||||
|
[homepage]: http://contributor-covenant.org
|
||||||
|
[version]: https://www.contributor-covenant.org/version/2/1/
|
||||||
643
CONTRIBUTING.md
Normal file
@@ -0,0 +1,643 @@
|
|||||||
|
<div align="center">
|
||||||
|
<h6>Contribution Guidelines for BinaryNinja Applications</h6>
|
||||||
|
<h1>♾️ Contributing ♾️</h1>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
[![Version][github-version-img]][github-version-uri]
|
||||||
|
[![Downloads][github-downloads-img]][github-downloads-uri]
|
||||||
|
[![Size][github-size-img]][github-size-img]
|
||||||
|
[![Last Commit][github-commit-img]][github-commit-img]
|
||||||
|
[![Contributors][contribs-all-img]](#contributors-)
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
Below are a list of ways that you can help contribute to this project, as well as policies and guides that explain how to get started.
|
||||||
|
|
||||||
|
Please review everything on this page before you submit your contribution.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
- [About](#about)
|
||||||
|
- [Issues, Bugs, Ideas](#issues-bugs-ideas)
|
||||||
|
- [Contributing](#contributing)
|
||||||
|
- [Before Submitting Pull Requests](#before-submitting-pull-requests)
|
||||||
|
- [Conventional Commit Specification](#conventional-commit-specification)
|
||||||
|
- [Types](#types)
|
||||||
|
- [Example 1:](#example-1)
|
||||||
|
- [Example 2:](#example-2)
|
||||||
|
- [Committing](#committing)
|
||||||
|
- [Languages](#languages)
|
||||||
|
- [Python](#python)
|
||||||
|
- [Indentation](#indentation)
|
||||||
|
- [Line Length](#line-length)
|
||||||
|
- [Blank Lines](#blank-lines)
|
||||||
|
- [Imports](#imports)
|
||||||
|
- [Commenting](#commenting)
|
||||||
|
- [Casing](#casing)
|
||||||
|
- [NodeJS](#nodejs)
|
||||||
|
- [Prettier](#prettier)
|
||||||
|
- [ESLint](#eslint)
|
||||||
|
- [v9 \& Newer (Config)](#v9--newer-config)
|
||||||
|
- [v8 \& Older (Config)](#v8--older-config)
|
||||||
|
- [Packages](#packages)
|
||||||
|
- [Indentation](#indentation-1)
|
||||||
|
- [Style](#style)
|
||||||
|
- [Line Length](#line-length-1)
|
||||||
|
- [Commenting](#commenting-1)
|
||||||
|
- [Casing](#casing-1)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Issues, Bugs, Ideas
|
||||||
|
|
||||||
|
Stuff happens, and sometimes as best as we try, there may be issues within this project that we are unaware of. That is the great thing about open-source; anyone can use the program and contribute to making it better.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
If you have found a bug, have an issue, or maybe even a cool idea; you can let us know by [submitting it](https://github.com/thebinaryninja/tvapp2/issues). However, before you submit your new issue, bug report, or feature request; head over to the [Issues Section](https://github.com/thebinaryninja/tvapp2/issues) and ensure nobody else has already submitted it.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Once you are sure that your issue has not already being dealt with; you may submit a new issue at [here](https://github.com/thebinaryninja/tvapp2/issues/new/choose). You'll be asked to specify exactly what your new submission targets, such as:
|
||||||
|
- Bug report
|
||||||
|
- Feature Suggestion
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
When writing a new submission; ensure you fill out any of the questions asked of you. If you do not provide enough information, we cannot help. Be as detailed as possible, and provide any logs or screenshots you may have to help us better understand what you mean. Failure to fill out the submission properly may result in it being closed without a response.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
If you are submitting a bug report:
|
||||||
|
|
||||||
|
- Explain the issue
|
||||||
|
- Describe how you expect for a feature to work, and what you're seeing instead of what you expected.
|
||||||
|
- List possible options for a resolution or insight
|
||||||
|
- Provide screenshots, logs, or anything else that can visually help track down the issue.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
[![Submit Issue][btn-github-submit-img]][btn-github-submit-uri]
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
**[`^ back to top ^`](#about)**
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
If you are looking to contribute to this project by actually submit your own code; please review this section completely. There is important information and policies provided below that you must follow for your pull request to get accepted.
|
||||||
|
|
||||||
|
The source is here for everyone to collectively share and collaborate on. If you think you have a possible solution to a problem; don't be afraid to get your hands dirty.
|
||||||
|
|
||||||
|
All contributions are made via pull requests. To create a pull request, you need a GitHub account. If you are unclear on this process, see [GitHub's documentation on forking and pull requests](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork). Pull requests should be targeted at the master branch.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### Before Submitting Pull Requests
|
||||||
|
|
||||||
|
- Follow the repository's code formatting conventions (see below);
|
||||||
|
- Include tests that prove that the change works as intended and does not add regressions;
|
||||||
|
- Document the changes in the code and/or the project's documentation;
|
||||||
|
- Your PR must pass the CI pipeline;
|
||||||
|
- When submitting your Pull Request, use one of the following branches:
|
||||||
|
- For bug fixes: `main` branch
|
||||||
|
- For features & functionality: `development` branch
|
||||||
|
- Include a proper git commit message following the [Conventional Commit Specification](https://conventionalcommits.org/en/v1.0.0/#specification).
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
If you have completed the above tasks, the pull request is ready to be reviewed and your pull request's label will be changed to "Ready for Review". At this point, a human will need to step in and manually verify your submission.
|
||||||
|
|
||||||
|
Reviewers will approve the pull request once they are satisfied with the patch it will be merged.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### Conventional Commit Specification
|
||||||
|
|
||||||
|
When committing your changes, we require you to follow the [Conventional Commit Specification](https://conventionalcommits.org/en/v1.0.0/#specification). The **Conventional Commits** is a specification for the format and content of a commit message. The concept behind Conventional Commits is to provide a rich commit history that can be read and understood by both humans and automated tools. Conventional Commits have the following format:
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
```
|
||||||
|
<type>[(optional <scope>)]: <description>
|
||||||
|
|
||||||
|
[optional <body>]
|
||||||
|
|
||||||
|
[optional <footer(s)>]
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
#### Types
|
||||||
|
|
||||||
|
Our repositories make use of the following commit tags:
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
| Type | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| `feat` | Introduce new feature |
|
||||||
|
| `fix` | Bug fix |
|
||||||
|
| `chore` | Includes technical or preventative maintenance task that is necessary for managing the app or repo, such as updating grunt tasks, but is not tied to any specific feature. Usually done for maintenance purposes.<br/>E.g: Edit .gitignore, .prettierrc, .prettierignore, .gitignore, eslint.config.js file |
|
||||||
|
| `revert` | Revert a previous commit |
|
||||||
|
| `style` | Update / reformat style of source code. Does not change the way app is implemented. Changes that do not affect the meaning of the code<br />E.g: white-space, formatting, missing semi-colons, change tabs to spaces, etc) |
|
||||||
|
| `docs` | Change website or markdown documents. Does not mean changes to the documentation generator script itself, only the documents created from the generator. <br/>E.g: documentation, readme.md or markdown |
|
||||||
|
| `build` | Changes to the build / compilation / packaging process or auxiliary tools such as doc generation<br />E.g: create new build tasks, update release script, etc. |
|
||||||
|
| `refactor` | Change to production code that leads to no behavior difference,<br/>E.g: split files, rename variables, rename package, improve code style, etc. |
|
||||||
|
| `test` | Add or refactor tests, no production code change. Changes the suite of automated tests for the app. |
|
||||||
|
| `ci` | Changes related to Continuous Integration (usually `yml` and other configuration files). |
|
||||||
|
| `perf` | Performance improvement of algorithms or execution time of the app. Does not change an existing feature. |
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Example 1:
|
||||||
|
|
||||||
|
```
|
||||||
|
feat(core): bug affecting menu [#22]
|
||||||
|
^───^────^ ^────────────────^ ^───^
|
||||||
|
| | | |
|
||||||
|
| | | └───⫸ (ISSUE): Reference issue ID
|
||||||
|
│ │ │
|
||||||
|
│ │ └──────────────────────⫸ (DESC): Summary in present tense. Use lower case not title case!
|
||||||
|
│ │
|
||||||
|
│ └──────────────────────────────⫸ (SCOPE): The package(s) that this change affects
|
||||||
|
│
|
||||||
|
└──────────────────────────────────⫸ (TYPE): See list above
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Example 2:
|
||||||
|
|
||||||
|
```
|
||||||
|
<type>(<scope>): <short summary> [issue]
|
||||||
|
| | | |
|
||||||
|
| | | └─⫸ Reference issue id (optional)
|
||||||
|
│ │ │
|
||||||
|
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
||||||
|
│ │
|
||||||
|
│ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
||||||
|
│ elements|forms|http|language-service|localize|platform-browser|
|
||||||
|
│ platform-browser-dynamic|platform-server|router|service-worker|
|
||||||
|
│ upgrade|zone.js|packaging|changelog|docs-infra|migrations|ngcc|ve|
|
||||||
|
│ devtools....
|
||||||
|
│
|
||||||
|
└─⫸ Commit Type: build|ci|doc|docs|feat|fix|perf|refactor|test
|
||||||
|
website|chore|style|type|revert|deprecate
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### Committing
|
||||||
|
|
||||||
|
If you are pushing a commit which addresses a submitted issue, reference your issue at the end of the commit message. You may also optionally add the major issue to the end of your commit body.
|
||||||
|
|
||||||
|
References should be on their own line, following the word `Ref` or `Refs`
|
||||||
|
|
||||||
|
```
|
||||||
|
Title: fix(core): fix error message displayed to users. [#22]
|
||||||
|
Description: The description of your commit
|
||||||
|
|
||||||
|
Ref: #22, #34, #37
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### Languages
|
||||||
|
|
||||||
|
The formatting of code greatly depends on the language being used for this repository. We provide various different languages below as this guide is utilized across multiple repositories.
|
||||||
|
|
||||||
|
- [Python](#python)
|
||||||
|
- [Javascript / Typescript / NodeJS](#nodejs)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
#### Python
|
||||||
|
|
||||||
|
The following guidelines apply to any projects written with Python:
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Indentation
|
||||||
|
|
||||||
|
Use `4 spaces` per indentation level.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> ✅ Correct
|
||||||
|
> ```python
|
||||||
|
> def Encrypt( key : int, bytestr : bytes ):
|
||||||
|
> res = b''
|
||||||
|
> i_blk, left_bytes = divmod( len(bytestr), 3 )
|
||||||
|
> ```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> ❌ Wrong
|
||||||
|
> ```python
|
||||||
|
> def encrypt( key : int, byteStr : bytes ):
|
||||||
|
> Res = b''
|
||||||
|
> iBlk, leftBytes = divmod( len(byteStr), 3 )
|
||||||
|
> ```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Line Length
|
||||||
|
|
||||||
|
Keep the maximum character count to `100 characters per line`. If you are revising old code which doesn't follow this guideline; please rewrite it to conform.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Blank Lines
|
||||||
|
|
||||||
|
Surround top-level functions and class definitions with a blank in-between.
|
||||||
|
|
||||||
|
Method definitions inside a class are surrounded by a single blank line.
|
||||||
|
|
||||||
|
Extra blank lines may be used (sparingly) to separate groups of functions related to one another. Blank lines may be omitted between a bunch of related one-liners (e.g: set of dummy implementations).
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Imports
|
||||||
|
|
||||||
|
Imports should usually be on separate lines:
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> ✅ Correct
|
||||||
|
> ```python
|
||||||
|
> import os
|
||||||
|
> import sys
|
||||||
|
> ```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> ❌ Wrong
|
||||||
|
> ```python
|
||||||
|
> import sys, os
|
||||||
|
> ```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
The following is acceptable:
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> ✅ Correct
|
||||||
|
> ```python
|
||||||
|
> from mypkg import siblingA, siblingB, siblingC
|
||||||
|
> ```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Commenting
|
||||||
|
|
||||||
|
Comment your code. It helps novice readers to better understand the process. It doesn't have to be painfully obvious explanations, but it helps to give an idea of what something does.
|
||||||
|
|
||||||
|
Please append `#` to the beginning of each line.
|
||||||
|
|
||||||
|
```python
|
||||||
|
# #
|
||||||
|
# byteString : b'1#Aetherx|232#1#233262#0#0#0#'
|
||||||
|
# #
|
||||||
|
|
||||||
|
def Encrypt( key : int, byteString : bytes ):
|
||||||
|
res = bytearray( )
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Casing
|
||||||
|
|
||||||
|
- Stick to `camelCase`; unless:
|
||||||
|
- naming functions, capitalize the first letter
|
||||||
|
- Capitalize enums
|
||||||
|
- If you see code not conforming with this, please revise it in your pull request.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> ✅ Correct
|
||||||
|
> ```python
|
||||||
|
> def Encrypt( key : int, byteStr : bytes ):
|
||||||
|
> res = b''
|
||||||
|
> iBlock, leftBytes = divmod( len(byteStr), 3 )
|
||||||
|
> ```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> ❌ Wrong
|
||||||
|
> ```python
|
||||||
|
> def encrypt( key : int, bytestr : bytes ):
|
||||||
|
> res = b''
|
||||||
|
> i_blk, left_bytes = divmod( len(bytestr), 3 )
|
||||||
|
> ```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
**[`^ back to top ^`](#about)**
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
#### NodeJS
|
||||||
|
|
||||||
|
The following allows you to configure ESLint and Prettier.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Prettier
|
||||||
|
|
||||||
|
We have opted to make use of [ESLint](#eslint) over Prettier. We provide a detailed ESLint flag config file with very specific linting rules. Please review that section for more information.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### ESLint
|
||||||
|
|
||||||
|
Within the root folder of the repo, there are several configuration files which you should be using within the project. These files dictate how prettier and eslint will behave and what is acceptable / not acceptable.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Pick the config file below depending on which version of ESLint you are using. The v8 and older `.eslint` may not be there if we have migrated over to an Eslint v9 flat config file:
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
###### v9 & Newer (Config)
|
||||||
|
|
||||||
|
Our NodeJS applications require that you utilize ESLint v9 or newer which makes use of a flat config structure. You may find a copy of our flat config at the link below:
|
||||||
|
|
||||||
|
- [📄 eslint.config.mjs](https://github.com/thebinaryninja/tvapp2/blob/main/tvapp2/eslint.config.mjs)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
###### v8 & Older (Config)
|
||||||
|
|
||||||
|
- We no longer utilize any version of ESLint older than version 9.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> When submitting your pull request, these linting and style rules will be verified with all of your files. If you did not follow these rules; the linter tests on your pull request will fail; and you'll be expected to correct these issues before your submission will be transferred over for human review.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Packages
|
||||||
|
|
||||||
|
We use the following packages for linting and prettier.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
| Package | Repo File | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| [@stylistic/eslint-plugin-js](https://npmjs.com/package/@stylistic/eslint-plugin-js) | [package.json](./package.json) | JavaScript stylistic rules for ESLint, migrated from eslint core. |
|
||||||
|
| [@stylistic/eslint-plugin-ts](https://npmjs.com/package/@stylistic/eslint-plugin-ts) | [package.json](./package.json) | TypeScript stylistic rules for ESLint, migrated from typescript-eslint. |
|
||||||
|
| [@stylistic/eslint-plugin-plus](https://npmjs.com/package/@stylistic/eslint-plugin-plus) | [package.json](./package.json) | Supplementary rules introduced by ESLint Stylistic. |
|
||||||
|
| [eslint-plugin-prettier](https://npmjs.com/package/eslint-plugin-prettier) | [package.json](./package.json) | Runs Prettier as an ESLint rule and reports differences as individual ESLint issues. |
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
You can add the following to your `package.json` file:
|
||||||
|
|
||||||
|
https://github.com/TheBinaryNinja/tvapp2/blob/1c75f11e9f0506ad3dd05133fdafc3aeb87686ca/tvapp2/package.json#L81-L92
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Indentation
|
||||||
|
|
||||||
|
Use `4 spaces` per indentation level.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Style
|
||||||
|
|
||||||
|
For files that are not controlled by [Prettier](#prettier) or [ESLint](#eslint); use `Allman Style`. Braces should be on their own lines, and any code inside the braces should be indented 4 spaces.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return {
|
||||||
|
status: "failure",
|
||||||
|
user:
|
||||||
|
{
|
||||||
|
id: "1aaa35aa-fb3a-62ae-ffec-a14g7fc401ac",
|
||||||
|
label: "Test String",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
while (x == y)
|
||||||
|
{
|
||||||
|
foo();
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Line Length
|
||||||
|
|
||||||
|
Keep the maximum character count to `100 characters per line`. The configs on this page have prettier automatically set up to detect more than 100 characters per line.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Commenting
|
||||||
|
|
||||||
|
Comment your code. It helps novice readers to better understand the process. You may use block style commenting, or single lines:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
/*
|
||||||
|
tests to decide if the end-user is running on Darwin or another platform.
|
||||||
|
*/
|
||||||
|
|
||||||
|
test(`Return true if platform is Darwin`, () => {
|
||||||
|
process.platform = 'darwin';
|
||||||
|
expect(bIsDarwin()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(`Return false if platform is not Darwin`, () => {
|
||||||
|
process.platform = 'linux';
|
||||||
|
expect(bIsDarwin()).toBe(false);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Casing
|
||||||
|
|
||||||
|
Stick to `camelCase` as much as possible.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
let myVar = 'one';
|
||||||
|
let secondVar = 'two';
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
If you are defining a new environment variable; it must be in ALL CAPS in the `Dockerfile`:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
ENV DIR_BUILD=/usr/src/app
|
||||||
|
ENV DIR_RUN=/usr/bin/app
|
||||||
|
ENV URL_REPO="https://git.binaryninja.net/binaryninja/"
|
||||||
|
ENV WEB_IP="0.0.0.0"
|
||||||
|
ENV WEB_PORT=4124
|
||||||
|
ENV STREAM_QUALITY="hd"
|
||||||
|
ENV FILE_PLAYLIST="playlist.m3u8"
|
||||||
|
ENV FILE_EPG="xmltv.xml"
|
||||||
|
ENV LOG_LEVEL=4
|
||||||
|
ENV TZ="Etc/UTC"
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Then you may call your new environment variable within the Javascript code; and ensure you define a default value to correct any user misconfigurations:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const envUrlRepo = process.env.URL_REPO || 'https://git.binaryninja.net/binaryninja';
|
||||||
|
const envStreamQuality = process.env.STREAM_QUALITY || 'hd';
|
||||||
|
const envFileM3U = process.env.FILE_PLAYLIST || 'playlist.m3u8';
|
||||||
|
const envFileXML = process.env.FILE_EPG || 'xmltv.xml';
|
||||||
|
const envFileTAR = process.env.FILE_TAR || 'xmltv.xml.gz';
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
**[`^ back to top ^`](#about)**
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
<!-- markdownlint-disable -->
|
||||||
|
|
||||||
|
<!-- BADGE > GENERAL -->
|
||||||
|
[general-npmjs-uri]: https://npmjs.com
|
||||||
|
[general-nodejs-uri]: https://nodejs.org
|
||||||
|
[general-npmtrends-uri]: http://npmtrends.com/tvapp2
|
||||||
|
|
||||||
|
<!-- BADGE > VERSION > GITHUB -->
|
||||||
|
[github-version-img]: https://img.shields.io/github/v/tag/thebinaryninja/tvapp2?logo=GitHub&label=Version&color=ba5225
|
||||||
|
[github-version-uri]: https://github.com/thebinaryninja/tvapp2/releases
|
||||||
|
|
||||||
|
<!-- BADGE > LICENSE > MIT -->
|
||||||
|
[license-mit-img]: https://img.shields.io/badge/MIT-FFF?logo=creativecommons&logoColor=FFFFFF&label=License&color=9d29a0
|
||||||
|
[license-mit-uri]: https://github.com/thebinaryninja/tvapp2/blob/main/LICENSE
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > DOWNLOAD COUNT -->
|
||||||
|
[github-downloads-img]: https://img.shields.io/github/downloads/thebinaryninja/tvapp2/total?logo=github&logoColor=FFFFFF&label=Downloads&color=376892
|
||||||
|
[github-downloads-uri]: https://github.com/thebinaryninja/tvapp2/releases
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > DOWNLOAD SIZE -->
|
||||||
|
[github-size-img]: https://img.shields.io/github/repo-size/thebinaryninja/tvapp2?logo=github&label=Size&color=59702a
|
||||||
|
[github-size-uri]: https://github.com/thebinaryninja/tvapp2/releases
|
||||||
|
|
||||||
|
<!-- BADGE > ALL CONTRIBUTORS -->
|
||||||
|
[contribs-all-img]: https://img.shields.io/github/all-contributors/thebinaryninja/tvapp2?logo=contributorcovenant&color=de1f6f&label=contributors
|
||||||
|
[contribs-all-uri]: https://github.com/all-contributors/all-contributors
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > BUILD > NPM -->
|
||||||
|
[github-build-img]: https://img.shields.io/github/actions/workflow/status/thebinaryninja/tvapp2/npm-release.yml?logo=github&logoColor=FFFFFF&label=Build&color=%23278b30
|
||||||
|
[github-build-uri]: https://github.com/thebinaryninja/tvapp2/actions/workflows/npm-release.yml
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > BUILD > Pypi -->
|
||||||
|
[github-build-pypi-img]: https://img.shields.io/github/actions/workflow/status/thebinaryninja/tvapp2/release-pypi.yml?logo=github&logoColor=FFFFFF&label=Build&color=%23278b30
|
||||||
|
[github-build-pypi-uri]: https://github.com/thebinaryninja/tvapp2/actions/workflows/pypi-release.yml
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > TESTS -->
|
||||||
|
[github-tests-img]: https://img.shields.io/github/actions/workflow/status/thebinaryninja/tvapp2/npm-tests.yml?logo=github&label=Tests&color=2c6488
|
||||||
|
[github-tests-uri]: https://github.com/thebinaryninja/tvapp2/actions/workflows/npm-tests.yml
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > COMMIT -->
|
||||||
|
[github-commit-img]: https://img.shields.io/github/last-commit/thebinaryninja/tvapp2?logo=conventionalcommits&logoColor=FFFFFF&label=Last%20Commit&color=313131
|
||||||
|
[github-commit-uri]: https://github.com/thebinaryninja/tvapp2/commits/main/
|
||||||
|
|
||||||
|
<!-- BADGE > Github > Docker Image > SELFHOSTED BADGES -->
|
||||||
|
[github-docker-version-img]: https://badges-ghcr.onrender.com/thebinaryninja/tvapp2/latest_tag?color=%233d9e18&ignore=development-amd64%2Cdevelopment%2Cdevelopment-arm64%2Clatest&label=version&trim=
|
||||||
|
[github-docker-version-uri]: https://github.com/thebinaryninja/tvapp2/pkgs/container/tvapp2
|
||||||
|
|
||||||
|
<!-- BADGE > Dockerhub > Docker Image -->
|
||||||
|
[dockerhub-docker-version-img]: https://img.shields.io/docker/v/thebinaryninja/tvapp2?sort=semver&arch=arm64
|
||||||
|
[dockerhub-docker-version-uri]: https://hub.docker.com/repository/docker/thebinaryninja/tvapp2/general
|
||||||
|
|
||||||
|
<!-- BADGE > Gitea > Docker Image > SELFHOSTED BADGES -->
|
||||||
|
[gitea-docker-version-img]: https://badges-ghcr.onrender.com/thebinaryninja/tvapp2/latest_tag?color=%233d9e18&ignore=latest&label=version&trim=
|
||||||
|
[gitea-docker-version-uri]: https://git.binaryninja.net/BinaryNinja/tvapp2
|
||||||
|
|
||||||
|
<!-- BADGE > Gitea 2 > Docker Image -->
|
||||||
|
[gitea2-docker-version-img]: https://img.shields.io/gitea/v/release/binaryninja/tvapp2?gitea_url=https%3A%2F%2Fgit.binaryninja.net
|
||||||
|
[gitea2-docker-version-uri]: https://git.binaryninja.net/BinaryNinja/-/packages/container/tvapp2/latest
|
||||||
|
|
||||||
|
<!-- BADGE > BUTTON > SUBMIT ISSUES -->
|
||||||
|
[btn-github-submit-img]: https://img.shields.io/badge/submit%20new%20issue-de1f5c?style=for-the-badge&logo=github&logoColor=FFFFFF
|
||||||
|
[btn-github-submit-uri]: https://github.com/thebinaryninja/tvapp2/issues
|
||||||
|
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
<!-- markdownlint-restore -->
|
||||||
54
Dockerfile
@@ -9,14 +9,31 @@
|
|||||||
# https://git.binaryninja.net/BinaryNinja/tvapp2
|
# https://git.binaryninja.net/BinaryNinja/tvapp2
|
||||||
# https://github.com/aetherinox/docker-base-alpine
|
# https://github.com/aetherinox/docker-base-alpine
|
||||||
#
|
#
|
||||||
# you can build your own image by running
|
# build your own image by running
|
||||||
# amd64 docker build --build-arg VERSION=1.0.0 --build-arg BUILDDATE=20250218 -t tvapp2:latest -t tvapp2:1.0.0 -t tvapp2:1.0.0-amd64 -f Dockerfile .
|
# amd64 docker build --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 -t tvapp2:latest -t tvapp2:1.5.0 -t tvapp2:1.5.0-amd64 -f Dockerfile .
|
||||||
# arm64 docker build --build-arg VERSION=1.0.0 --build-arg BUILDDATE=20250218 -t tvapp2:1.0.0-arm64 -f Dockerfile.aarch64 .
|
# arm64 docker build --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 -t tvapp2:1.5.0-arm64 -f Dockerfile.aarch64 .
|
||||||
#
|
#
|
||||||
# if you prefer to use `docker buildx`
|
# OR; build using `docker buildx`
|
||||||
# create docker buildx create --driver docker-container --name container --bootstrap --use
|
# create docker buildx create --driver docker-container --name container --bootstrap --use
|
||||||
# amd64 docker buildx build --no-cache --pull --build-arg VERSION=1.0.0 --build-arg BUILDDATE=20250218 -t tvapp2:latest -t tvapp2:1.0.0 --platform=linux/amd64 --output type=docker --output type=docker .
|
# amd64 docker buildx build --build-arg ARCH=amd64 --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 --build-arg RELEASE=stable --tag ghcr.io/thebinaryninja/tvapp2:1.5.0-amd64 --attest type=provenance,disabled=true --attest type=sbom,disabled=true --file Dockerfile --platform linux/amd64 --output type=docker --allow network.host --network host --no-cache --pull --push .
|
||||||
# arm64 docker buildx build --no-cache --pull --build-arg VERSION=1.0.0 --build-arg BUILDDATE=20250218 -t tvapp2:latest -t tvapp2:1.0.0 --platform=linux/arm64 --output type=docker --output type=docker .
|
# arm64 docker buildx build --build-arg ARCH=arm64 --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 --build-arg RELEASE=stable --tag ghcr.io/thebinaryninja/tvapp2:1.5.0-arm64 --attest type=provenance,disabled=true --attest type=sbom,disabled=true --file Dockerfile --platform linux/arm64 --output type=docker --allow network.host --network host --no-cache --pull --push .
|
||||||
|
#
|
||||||
|
# OR; build single amd64 image
|
||||||
|
# create docker buildx create --driver docker-container --name container --bootstrap --use
|
||||||
|
# amd64 docker buildx build --build-arg ARCH=amd64 --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 --build-arg RELEASE=stable --tag ghcr.io/thebinaryninja/tvapp2:1.5.0 --tag ghcr.io/thebinaryninja/tvapp2:1.5 --tag ghcr.io/thebinaryninja/tvapp2:1 --tag ghcr.io/thebinaryninja/tvapp2:latest --attest type=provenance,disabled=true --attest type=sbom,disabled=true --file Dockerfile --platform linux/amd64 --output type=docker --allow network.host --network host --no-cache --push .
|
||||||
|
#
|
||||||
|
# OR; build official image (publish)
|
||||||
|
# create docker buildx create --driver docker-container --name container --bootstrap --use
|
||||||
|
# amd64-stable docker buildx build --build-arg ARCH=amd64 --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 --build-arg RELEASE=stable --tag ghcr.io/thebinaryninja/tvapp2:1.5.0-amd64 --attest type=provenance,disabled=true --attest type=sbom,disabled=true --file Dockerfile --platform linux/amd64 --output type=docker --allow network.host --network host --no-cache --pull --push .
|
||||||
|
# arm64-stable docker buildx build --build-arg ARCH=arm64 --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 --build-arg RELEASE=stable --tag ghcr.io/thebinaryninja/tvapp2:1.5.0-arm64 --attest type=provenance,disabled=true --attest type=sbom,disabled=true --file Dockerfile --platform linux/arm64 --output type=docker --allow network.host --network host --no-cache --pull --push .
|
||||||
|
# amd64-dev docker buildx build --build-arg ARCH=amd64 --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 --build-arg RELEASE=development --tag ghcr.io/thebinaryninja/tvapp2:development-amd64 --attest type=provenance,disabled=true --attest type=sbom,disabled=true --file Dockerfile --platform linux/amd64 --output type=docker --allow network.host --network host --no-cache --pull --push .
|
||||||
|
# arm64-dev docker buildx build --build-arg ARCH=arm64 --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 --build-arg RELEASE=development --tag ghcr.io/thebinaryninja/tvapp2:development-arm64 --attest type=provenance,disabled=true --attest type=sbom,disabled=true --file Dockerfile --platform linux/arm64 --output type=docker --allow network.host --network host --no-cache --pull --push .
|
||||||
|
# amd64-stable-hash docker buildx imagetools inspect ghcr.io/thebinaryninja/tvapp2:1.5.0-amd64
|
||||||
|
# arm64-stable-hash docker buildx imagetools inspect ghcr.io/thebinaryninja/tvapp2:1.5.0-arm64
|
||||||
|
# amd64-dev-hash docker buildx imagetools inspect ghcr.io/thebinaryninja/tvapp2:development-amd64
|
||||||
|
# arm64-dev-hash docker buildx imagetools inspect ghcr.io/thebinaryninja/tvapp2:development-arm64
|
||||||
|
# merge-stable docker buildx imagetools create --tag ghcr.io/thebinaryninja/tvapp2:1.5.0 --tag ghcr.io/thebinaryninja/tvapp2:1.5 --tag ghcr.io/thebinaryninja/tvapp2:1 --tag ghcr.io/thebinaryninja/tvapp2:latest sha256:0abe1b1c119959b3b1ccc23c56a7ee2c4c908c6aaef290d4ab2993859d807a3b sha256:e68b9de8669eac64d4e4d2a8343c56705e05e9a907cf0b542343f9b536d9c473
|
||||||
|
# merge-dev docker buildx imagetools create --tag ghcr.io/thebinaryninja/tvapp2:development sha256:8f36385a28c8f6eb7394d903c9a7a2765b06f94266b32628389ee9e3e3d7e69d sha256:c719ccb034946e3f0625003f25026d001768794e38a1ba8aafc9146291d548c5
|
||||||
# #
|
# #
|
||||||
|
|
||||||
# #
|
# #
|
||||||
@@ -28,15 +45,19 @@
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
ARG ARCH=amd64
|
ARG ARCH=amd64
|
||||||
FROM --platform=linux/${ARCH} ghcr.io/aetherinox/alpine-base:3.21
|
ARG ALPINE_VERSION=3.21
|
||||||
|
FROM --platform=linux/${ARCH} ghcr.io/aetherinox/alpine-base:${ALPINE_VERSION}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Set Args
|
# Set Args
|
||||||
# #
|
# #
|
||||||
|
|
||||||
ARG ARCH=amd64
|
ARG ARCH=amd64
|
||||||
|
ARG ALPINE_VERSION=3.21
|
||||||
ARG BUILDDATE
|
ARG BUILDDATE
|
||||||
ARG VERSION
|
ARG VERSION
|
||||||
|
ARG RELEASE
|
||||||
|
ARG GIT_SHA1=0000000000000000000000000000000000000000
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Set Labels
|
# Set Labels
|
||||||
@@ -56,8 +77,13 @@ LABEL org.opencontainers.image.licenses="MIT"
|
|||||||
LABEL org.opencontainers.image.architecture="${ARCH}"
|
LABEL org.opencontainers.image.architecture="${ARCH}"
|
||||||
LABEL org.opencontainers.image.ref.name="main"
|
LABEL org.opencontainers.image.ref.name="main"
|
||||||
LABEL org.opencontainers.image.registry="local"
|
LABEL org.opencontainers.image.registry="local"
|
||||||
|
LABEL org.opencontainers.image.release="${RELEASE}"
|
||||||
LABEL org.tvapp2.image.maintainers="Aetherinox, iFlip721, Optx"
|
LABEL org.tvapp2.image.maintainers="Aetherinox, iFlip721, Optx"
|
||||||
LABEL org.tvapp2.image.build-version="Version:- ${VERSION} Date:- ${BUILDDATE}"
|
LABEL org.tvapp2.image.build-version="Version:- ${VERSION} Date:- ${BUILDDATE}"
|
||||||
|
LABEL org.tvapp2.image.build-version-alpine="${ALPINE_VERSION}"
|
||||||
|
LABEL org.tvapp2.image.build-architecture="${ARCH}"
|
||||||
|
LABEL org.tvapp2.image.build-release="${RELEASE}"
|
||||||
|
LABEL org.tvapp2.image.build-sha1="${GIT_SHA1}"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Set Env Var
|
# Set Env Var
|
||||||
@@ -65,16 +91,24 @@ LABEL org.tvapp2.image.build-version="Version:- ${VERSION} Date:- ${BUILDDATE}"
|
|||||||
|
|
||||||
ENV NODE_VERSION=22.8.0
|
ENV NODE_VERSION=22.8.0
|
||||||
ENV YARN_VERSION=1.22.22
|
ENV YARN_VERSION=1.22.22
|
||||||
|
ENV RELEASE="${RELEASE}"
|
||||||
ENV DIR_BUILD=/usr/src/app
|
ENV DIR_BUILD=/usr/src/app
|
||||||
ENV DIR_RUN=/usr/bin/app
|
ENV DIR_RUN=/usr/bin/app
|
||||||
ENV URL_REPO="https://git.binaryninja.net/binaryninja/"
|
ENV URL_REPO="https://git.binaryninja.net/binaryninja/"
|
||||||
ENV WEB_IP="0.0.0.0"
|
ENV WEB_IP="0.0.0.0"
|
||||||
ENV WEB_PORT=4124
|
ENV WEB_PORT=4124
|
||||||
|
ENV WEB_ENCODING="deflate, br"
|
||||||
|
ENV WEB_PROXY_HEADER="x-forwarded-for"
|
||||||
ENV STREAM_QUALITY="hd"
|
ENV STREAM_QUALITY="hd"
|
||||||
ENV FILE_PLAYLIST="playlist.m3u8"
|
ENV FILE_URL="urls.txt"
|
||||||
|
ENV FILE_M3U="playlist.m3u8"
|
||||||
ENV FILE_EPG="xmltv.xml"
|
ENV FILE_EPG="xmltv.xml"
|
||||||
|
ENV FILE_TAR="xmltv.xml.gz"
|
||||||
|
ENV HEALTH_TIMER=600000
|
||||||
|
ENV TASK_CRON_SYNC="0 0 */3 * *"
|
||||||
ENV LOG_LEVEL=4
|
ENV LOG_LEVEL=4
|
||||||
ENV TZ="Etc/UTC"
|
ENV TZ="Etc/UTC"
|
||||||
|
ENV GIT_SHA1=${GIT_SHA1:-0000000000000000000000000000000000000000}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Install
|
# Install
|
||||||
@@ -83,8 +117,10 @@ ENV TZ="Etc/UTC"
|
|||||||
RUN \
|
RUN \
|
||||||
apk add --no-cache \
|
apk add --no-cache \
|
||||||
wget \
|
wget \
|
||||||
|
curl \
|
||||||
bash \
|
bash \
|
||||||
nano \
|
nano \
|
||||||
|
git \
|
||||||
npm \
|
npm \
|
||||||
openssl
|
openssl
|
||||||
|
|
||||||
|
|||||||
@@ -6,21 +6,197 @@ tags:
|
|||||||
|
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
This section outlines all releases of TVApp2, including the version of the release, and the changes made for that release.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
<p align="center" markdown="1">
|
<p align="center" markdown="1">
|
||||||
|
|
||||||

|
<!-- prettier-ignore-start -->
|
||||||

|
[![Version][github-version-img]][github-version-uri]
|
||||||

|
[![Downloads][github-downloads-img]][github-downloads-uri]
|
||||||

|
[![Size][github-size-img]][github-size-img]
|
||||||
|
[![Last Commit][github-commit-img]][github-commit-img]
|
||||||
|
[![Contributors][contribs-all-img]](#contributors)
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
### <!-- md:version stable- --> 1.0.0 <small>Feb 24, 2025</small> { id="1.0.0" }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
### <!-- md:version stable- --> 1.4.0 <small>Apr 10, 2025</small> { id="1.4.0" }
|
||||||
|
|
||||||
|
- `feat`: add new environment variable `HEALTH_TIMER` _(See feature below)_
|
||||||
|
- `feat`: new health check icon in top right; triggers every `10 minutes` and reports back to the web interface as a toast notification
|
||||||
|
- health check shows timer until next health check is performed.
|
||||||
|
- `feat`: added bootstramp toast notifications and modals
|
||||||
|
- `feat`: new modal dialog when when user triggers a re-sync of the m3u and epg data
|
||||||
|
- `feat`: footer of web interface how discloses which build is being ran; `stable` or `development`
|
||||||
|
- `refactor`: console logging system overhauled with new syntax for how logs are displayed
|
||||||
|
- `refactor`: additional logs added for `LOG_LEVEL=5` or higher
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### <!-- md:version stable- --> 1.3.0 <small>Apr 9, 2025</small> { id="1.3.0" }
|
||||||
|
|
||||||
|
- `feat`: new button to upper-right side of header which allows you to **force re-sync** your m3u and xml data.
|
||||||
|
- `feat`: new api endpoint `/api/resync`; utilized to resync M3U and EPG data
|
||||||
|
- `feat`: new api endpoint `/api/health`; utilized in your `docker-compose.yml` health check
|
||||||
|
- `feat`: new env variable `WEB_ENCODING`; allows you to customize the HTTP `Accept-Encoding` request and response header
|
||||||
|
- `feat`: new env variable `IP_GATEWAY`; stores assigned container gateway ip
|
||||||
|
- `feat`: new env variable `IP_CONTAINER`; stores assigned container ip
|
||||||
|
- `refactor`: env variables re-named
|
||||||
|
- `FILE_TAR` → `FILE_GZP`
|
||||||
|
- `refactor`: errors and success messages now use api endpoint; lists timestamp, error code, etc.
|
||||||
|
- `build`: bump bootstrap from `v4` to `v5`
|
||||||
|
- `fix`: bug in Jellyfin which caused EPG data syncing to error out for hosts which cannot support gzip compression
|
||||||
|
- Error: _[ERR] [27] Jellyfin.LiveTv.Guide.GuideManager: Error getting programs for channel XXXXXXXXXXXXXXX (Source 2) System.Xml.XmlException: '', hexadecimal value 0x1F, is an invalid character. Line 1, position 1._
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### <!-- md:version stable- --> 1.2.0 <small>Apr 5, 2025</small> { id="1.2.0" }
|
||||||
|
|
||||||
|
- `feat`: add support for additional mime types and default file type
|
||||||
|
- `style`: rename env variable `FILE_PLAYLIST` to `FILE_M3U`
|
||||||
|
- `build`: add new env vars to `Dockerfile`
|
||||||
|
- `FILE_TAR`
|
||||||
|
- `FILE_URL`
|
||||||
|
- `refactor`: m3u and epg files now stored in `www` folder
|
||||||
|
- `fix`: html template links pointing to old repo
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### <!-- md:version stable- --> 1.1.0 <small>Mar 25, 2025</small> { id="1.1.0" }
|
||||||
|
|
||||||
|
- `feat`: new interface & theme for web ui
|
||||||
|
- integrated bootstrap 4.x
|
||||||
|
- new dark theme
|
||||||
|
- all hosted files now display `date`, `download url`, `size`, and `description`
|
||||||
|
- automatic viewport resizing depending on the device used
|
||||||
|
- new favicon
|
||||||
|
- localized css, js, and image support instead of relying on externally hosted resources
|
||||||
|
- `feat`: app now offers a compressed `gzip` for EPG guide data
|
||||||
|
- `feat`: add multiple url paths to download each asset
|
||||||
|
- `/guide`, `/epg`, `xml`
|
||||||
|
- `/playlist`, `/m3u`, `/m3u8`
|
||||||
|
- `/gzip`, `/gz`
|
||||||
|
- `feat`: add mew environment variables
|
||||||
|
- `LOG_LEVEL`: specifies what level of logs you will see in console
|
||||||
|
- `STREAM_QUALITY`: specifies the quality of the stream; options: `hd` and `sd`
|
||||||
|
- `FILE_PLAYLIST`: filename that M3U playlist data will be stored to
|
||||||
|
- `FILE_EPG`: filename that EPG / XML guide data will be stored to
|
||||||
|
- `FILE_GZIP`: filename that compressed gzip guide data will be stored to
|
||||||
|
- `build`: app migrated from CommonJS to ES Modules
|
||||||
|
- `build`: bump alpine base image from v3.20 to v3.21
|
||||||
|
- `build`: migrated html template to independent file in `www` folder; utilizes `ejs` module
|
||||||
|
- `build`: **amd64** and **arm64** docker images merged into one image with architecture support
|
||||||
|
- `fix`: resolved bug where local server could not be started using nodejs; related to ip address variable
|
||||||
|
- `build(deps)`: add package `ejs` 3.1.10
|
||||||
|
- `build(deps)`: add package `chalk` 5.3.0
|
||||||
|
- `build(deps)`: add package `moment` 2.30.1
|
||||||
|
- `build(deps-dev)`: add package `eslint` 9.17.0
|
||||||
|
- `build(deps-dev)`: add package `eslint-plugin-chai-friendly` 1.0.1
|
||||||
|
- `build(deps-dev)`: add package `eslint-plugin-import` 2.31.0
|
||||||
|
- `build(deps-dev)`: add package `eslint-plugin-n` 17.15.0
|
||||||
|
- `build(deps-dev)`: add package `eslint-plugin-promise` 7.2.1
|
||||||
|
- `build(deps-dev)`: add package `@stylistic/eslint-plugin-js` 3.1.0
|
||||||
|
- `remove`: tvapp2.fonts.min.js
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### <!-- md:version stable- --> 1.0.0 <small>Feb 24, 2025</small> { id="1.0.0" }
|
||||||
|
|
||||||
|
- Initial release
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
<!-- markdownlint-disable -->
|
||||||
|
|
||||||
|
<!-- BADGE > GENERAL -->
|
||||||
|
[general-npmjs-uri]: https://npmjs.com
|
||||||
|
[general-nodejs-uri]: https://nodejs.org
|
||||||
|
[general-npmtrends-uri]: http://npmtrends.com/csf-firewall
|
||||||
|
|
||||||
|
<!-- BADGE > VERSION > GITHUB -->
|
||||||
|
[github-version-img]: https://img.shields.io/github/v/tag/TheBinaryNinja/tvapp2?logo=GitHub&label=Version&color=ba5225
|
||||||
|
[github-version-uri]: https://github.com/TheBinaryNinja/tvapp2/releases
|
||||||
|
|
||||||
|
<!-- BADGE > LICENSE > MIT -->
|
||||||
|
[license-mit-img]: https://img.shields.io/badge/MIT-FFF?logo=creativecommons&logoColor=FFFFFF&label=License&color=9d29a0
|
||||||
|
[license-mit-uri]: https://github.com/TheBinaryNinja/tvapp2/blob/main/LICENSE
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > DOWNLOAD COUNT -->
|
||||||
|
[github-downloads-img]: https://img.shields.io/github/downloads/TheBinaryNinja/tvapp2/total?logo=github&logoColor=FFFFFF&label=Downloads&color=376892
|
||||||
|
[github-downloads-uri]: https://github.com/TheBinaryNinja/tvapp2/releases
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > DOWNLOAD SIZE -->
|
||||||
|
[github-size-img]: https://img.shields.io/github/repo-size/TheBinaryNinja/tvapp2?logo=github&label=Size&color=59702a
|
||||||
|
[github-size-uri]: https://github.com/TheBinaryNinja/tvapp2/releases
|
||||||
|
|
||||||
|
<!-- BADGE > ALL CONTRIBUTORS -->
|
||||||
|
[contribs-all-img]: https://img.shields.io/github/all-contributors/TheBinaryNinja/tvapp2?logo=contributorcovenant&color=de1f6f&label=contributors
|
||||||
|
[contribs-all-uri]: https://github.com/all-contributors/all-contributors
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > BUILD > NPM -->
|
||||||
|
[github-build-img]: https://img.shields.io/github/actions/workflow/status/TheBinaryNinja/tvapp2/npm-release.yml?logo=github&logoColor=FFFFFF&label=Build&color=%23278b30
|
||||||
|
[github-build-uri]: https://github.com/TheBinaryNinja/tvapp2/actions/workflows/npm-release.yml
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > BUILD > Pypi -->
|
||||||
|
[github-build-pypi-img]: https://img.shields.io/github/actions/workflow/status/TheBinaryNinja/tvapp2/release-pypi.yml?logo=github&logoColor=FFFFFF&label=Build&color=%23278b30
|
||||||
|
[github-build-pypi-uri]: https://github.com/TheBinaryNinja/tvapp2/actions/workflows/pypi-release.yml
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > TESTS -->
|
||||||
|
[github-tests-img]: https://img.shields.io/github/actions/workflow/status/TheBinaryNinja/tvapp2/npm-tests.yml?logo=github&label=Tests&color=2c6488
|
||||||
|
[github-tests-uri]: https://github.com/TheBinaryNinja/tvapp2/actions/workflows/npm-tests.yml
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > COMMIT -->
|
||||||
|
[github-commit-img]: https://img.shields.io/github/last-commit/TheBinaryNinja/tvapp2?logo=conventionalcommits&logoColor=FFFFFF&label=Last%20Commit&color=313131
|
||||||
|
[github-commit-uri]: https://github.com/TheBinaryNinja/tvapp2/commits/main/
|
||||||
|
|
||||||
|
<!-- BADGE > Github > Docker Image > SELFHOSTED BADGES -->
|
||||||
|
[github-docker-version-img]: https://badges-ghcr.onrender.com/thebinaryninja/tvapp2/latest_tag?color=%233d9e18&ignore=development-amd64%2Cdevelopment%2Cdevelopment-arm64%2Clatest&label=version&trim=
|
||||||
|
[github-docker-version-uri]: https://github.com/TheBinaryNinja/tvapp2/pkgs/container/tvapp2
|
||||||
|
|
||||||
|
<!-- BADGE > Dockerhub > Docker Image -->
|
||||||
|
[dockerhub-docker-version-img]: https://img.shields.io/docker/v/thebinaryninja/tvapp2?sort=semver&arch=arm64
|
||||||
|
[dockerhub-docker-version-uri]: https://hub.docker.com/repository/docker/thebinaryninja/tvapp2/general
|
||||||
|
|
||||||
|
<!-- BADGE > Gitea > Docker Image > SELFHOSTED BADGES -->
|
||||||
|
[gitea-docker-version-img]: https://badges-ghcr.onrender.com/thebinaryninja/tvapp2/latest_tag?color=%233d9e18&ignore=latest&label=version&trim=
|
||||||
|
[gitea-docker-version-uri]: https://git.binaryninja.net/BinaryNinja/tvapp2
|
||||||
|
|
||||||
|
<!-- BADGE > Gitea 2 > Docker Image -->
|
||||||
|
[gitea2-docker-version-img]: https://img.shields.io/gitea/v/release/binaryninja/tvapp2?gitea_url=https%3A%2F%2Fgit.binaryninja.net
|
||||||
|
[gitea2-docker-version-uri]: https://git.binaryninja.net/BinaryNinja/-/packages/container/tvapp2/latest
|
||||||
|
|
||||||
|
<!-- BADGE > BUTTON > SUBMIT ISSUES -->
|
||||||
|
[btn-github-submit-img]: https://img.shields.io/badge/submit%20new%20issue-de1f5c?style=for-the-badge&logo=github&logoColor=FFFFFF
|
||||||
|
[btn-github-submit-uri]: https://github.com/TheBinaryNinja/tvapp2/issues
|
||||||
|
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
<!-- markdownlint-restore -->
|
||||||
|
|||||||
652
docs/docs/about/contributing.md
Normal file
@@ -0,0 +1,652 @@
|
|||||||
|
---
|
||||||
|
title: Contributing to TVApp2
|
||||||
|
tags:
|
||||||
|
- info
|
||||||
|
---
|
||||||
|
|
||||||
|
<div align="center" markdown="1">
|
||||||
|
<h1>♾️ Contributing ♾️</h1>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<p align="center" markdown="1">
|
||||||
|
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
[![Version][github-version-img]][github-version-uri]
|
||||||
|
[![Downloads][github-downloads-img]][github-downloads-uri]
|
||||||
|
[![Size][github-size-img]][github-size-img]
|
||||||
|
[![Last Commit][github-commit-img]][github-commit-img]
|
||||||
|
[![Contributors][contribs-all-img]](#contributors)
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
Below are a list of ways that you can help contribute to this project, as well as policies and guides that explain how to get started.
|
||||||
|
|
||||||
|
Please review everything on this page before you submit your contribution.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
- [About](#about)
|
||||||
|
- [Issues, Bugs, Ideas](#issues-bugs-ideas)
|
||||||
|
- [Contributing](#contributing)
|
||||||
|
- [Before Submitting Pull Requests](#before-submitting-pull-requests)
|
||||||
|
- [Conventional Commit Specification](#conventional-commit-specification)
|
||||||
|
- [Types](#types)
|
||||||
|
- [Example 1:](#example-1)
|
||||||
|
- [Example 2:](#example-2)
|
||||||
|
- [Committing](#committing)
|
||||||
|
- [Languages](#languages)
|
||||||
|
- [Python](#python)
|
||||||
|
- [Indentation](#indentation)
|
||||||
|
- [Line Length](#line-length)
|
||||||
|
- [Blank Lines](#blank-lines)
|
||||||
|
- [Imports](#imports)
|
||||||
|
- [Commenting](#commenting)
|
||||||
|
- [Casing](#casing)
|
||||||
|
- [NodeJS](#nodejs)
|
||||||
|
- [Prettier](#prettier)
|
||||||
|
- [ESLint](#eslint)
|
||||||
|
- [v9 \& Newer (Config)](#v9--newer-config)
|
||||||
|
- [v8 \& Older (Config)](#v8--older-config)
|
||||||
|
- [Packages](#packages)
|
||||||
|
- [Indentation](#indentation-1)
|
||||||
|
- [Style](#style)
|
||||||
|
- [Line Length](#line-length-1)
|
||||||
|
- [Commenting](#commenting-1)
|
||||||
|
- [Casing](#casing-1)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Issues, Bugs, Ideas
|
||||||
|
|
||||||
|
Stuff happens, and sometimes as best as we try, there may be issues within this project that we are unaware of. That is the great thing about open-source; anyone can use the program and contribute to making it better.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
If you have found a bug, have an issue, or maybe even a cool idea; you can let us know by [submitting it](https://github.com/thebinaryninja/tvapp2/issues). However, before you submit your new issue, bug report, or feature request; head over to the [Issues Section](https://github.com/thebinaryninja/tvapp2/issues) and ensure nobody else has already submitted it.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Once you are sure that your issue has not already being dealt with; you may submit a new issue at [here](https://github.com/thebinaryninja/tvapp2/issues/new/choose). You'll be asked to specify exactly what your new submission targets, such as:
|
||||||
|
- Bug report
|
||||||
|
- Feature Suggestion
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
When writing a new submission; ensure you fill out any of the questions asked of you. If you do not provide enough information, we cannot help. Be as detailed as possible, and provide any logs or screenshots you may have to help us better understand what you mean. Failure to fill out the submission properly may result in it being closed without a response.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
If you are submitting a bug report:
|
||||||
|
|
||||||
|
- Explain the issue
|
||||||
|
- Describe how you expect for a feature to work, and what you're seeing instead of what you expected.
|
||||||
|
- List possible options for a resolution or insight
|
||||||
|
- Provide screenshots, logs, or anything else that can visually help track down the issue.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
[![Submit Issue][btn-github-submit-img]][btn-github-submit-uri]
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
**[`^ back to top ^`](#about)**
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
If you are looking to contribute to this project by actually submit your own code; please review this section completely. There is important information and policies provided below that you must follow for your pull request to get accepted.
|
||||||
|
|
||||||
|
The source is here for everyone to collectively share and collaborate on. If you think you have a possible solution to a problem; don't be afraid to get your hands dirty.
|
||||||
|
|
||||||
|
All contributions are made via pull requests. To create a pull request, you need a GitHub account. If you are unclear on this process, see [GitHub's documentation on forking and pull requests](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork). Pull requests should be targeted at the master branch.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### Before Submitting Pull Requests
|
||||||
|
|
||||||
|
- Follow the repository's code formatting conventions (see below);
|
||||||
|
- Include tests that prove that the change works as intended and does not add regressions;
|
||||||
|
- Document the changes in the code and/or the project's documentation;
|
||||||
|
- Your PR must pass the CI pipeline;
|
||||||
|
- When submitting your Pull Request, use one of the following branches:
|
||||||
|
- For bug fixes: `main` branch
|
||||||
|
- For features & functionality: `development` branch
|
||||||
|
- Include a proper git commit message following the [Conventional Commit Specification](https://conventionalcommits.org/en/v1.0.0/#specification).
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
If you have completed the above tasks, the pull request is ready to be reviewed and your pull request's label will be changed to "Ready for Review". At this point, a human will need to step in and manually verify your submission.
|
||||||
|
|
||||||
|
Reviewers will approve the pull request once they are satisfied with the patch it will be merged.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### Conventional Commit Specification
|
||||||
|
|
||||||
|
When committing your changes, we require you to follow the [Conventional Commit Specification](https://conventionalcommits.org/en/v1.0.0/#specification). The **Conventional Commits** is a specification for the format and content of a commit message. The concept behind Conventional Commits is to provide a rich commit history that can be read and understood by both humans and automated tools. Conventional Commits have the following format:
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
```
|
||||||
|
<type>[(optional <scope>)]: <description>
|
||||||
|
|
||||||
|
[optional <body>]
|
||||||
|
|
||||||
|
[optional <footer(s)>]
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
#### Types
|
||||||
|
|
||||||
|
Our repositories make use of the following commit tags:
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
| Type | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| `feat` | <sup><sub>Introduce new feature</sub></sup> |
|
||||||
|
| `fix` | <sup><sub>Bug fix</sub></sup> |
|
||||||
|
| `chore` | <sup><sub>Includes technical or preventative maintenance task that is necessary for managing the app or repo, such as updating grunt tasks, but is not tied to any specific feature. Usually done for maintenance purposes.<br/>E.g: Edit .gitignore, .prettierrc, .prettierignore, .gitignore, eslint.config.js file</sub></sup> |
|
||||||
|
| `revert` | <sup><sub>Revert a previous commit</sub></sup> |
|
||||||
|
| `style` | <sup><sub>Update / reformat style of source code. Does not change the way app is implemented. Changes that do not affect the meaning of the code<br />E.g: white-space, formatting, missing semi-colons, change tabs to spaces, etc)</sub></sup> |
|
||||||
|
| `docs` | <sup><sub>Change website or markdown documents. Does not mean changes to the documentation generator script itself, only the documents created from the generator. <br/>E.g: documentation, readme.md or markdown |
|
||||||
|
| `build` | <sup><sub>Changes to the build / compilation / packaging process or auxiliary tools such as doc generation<br />E.g: create new build tasks, update release script, etc.</sub></sup> |
|
||||||
|
| `refactor` | <sup><sub>Change to production code that leads to no behavior difference,<br/>E.g: split files, rename variables, rename package, improve code style, etc.</sub></sup> |
|
||||||
|
| `test` | <sup><sub>Add or refactor tests, no production code change. Changes the suite of automated tests for the app.</sub></sup> |
|
||||||
|
| `ci` | <sup><sub>Changes related to Continuous Integration (usually `yml` and other configuration files).</sub></sup> |
|
||||||
|
| `perf` | <sup><sub>Performance improvement of algorithms or execution time of the app. Does not change an existing feature.</sub></sup> |
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Example 1:
|
||||||
|
|
||||||
|
```
|
||||||
|
feat(core): bug affecting menu [#22]
|
||||||
|
^───^────^ ^────────────────^ ^───^
|
||||||
|
| | | |
|
||||||
|
| | | └───⫸ (ISSUE): Reference issue ID
|
||||||
|
│ │ │
|
||||||
|
│ │ └──────────────────────⫸ (DESC): Summary in present tense. Use lower case not title case!
|
||||||
|
│ │
|
||||||
|
│ └──────────────────────────────⫸ (SCOPE): The package(s) that this change affects
|
||||||
|
│
|
||||||
|
└──────────────────────────────────⫸ (TYPE): See list above
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Example 2:
|
||||||
|
|
||||||
|
```
|
||||||
|
<type>(<scope>): <short summary> [issue]
|
||||||
|
| | | |
|
||||||
|
| | | └─⫸ Reference issue id (optional)
|
||||||
|
│ │ │
|
||||||
|
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
||||||
|
│ │
|
||||||
|
│ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
||||||
|
│ elements|forms|http|language-service|localize|platform-browser|
|
||||||
|
│ platform-browser-dynamic|platform-server|router|service-worker|
|
||||||
|
│ upgrade|zone.js|packaging|changelog|docs-infra|migrations|ngcc|ve|
|
||||||
|
│ devtools....
|
||||||
|
│
|
||||||
|
└─⫸ Commit Type: build|ci|doc|docs|feat|fix|perf|refactor|test
|
||||||
|
website|chore|style|type|revert|deprecate
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### Committing
|
||||||
|
|
||||||
|
If you are pushing a commit which addresses a submitted issue, reference your issue at the end of the commit message. You may also optionally add the major issue to the end of your commit body.
|
||||||
|
|
||||||
|
References should be on their own line, following the word `Ref` or `Refs`
|
||||||
|
|
||||||
|
```
|
||||||
|
Title: fix(core): fix error message displayed to users. [#22]
|
||||||
|
Description: The description of your commit
|
||||||
|
|
||||||
|
Ref: #22, #34, #37
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### Languages
|
||||||
|
|
||||||
|
The formatting of code greatly depends on the language being used for this repository. We provide various different languages below as this guide is utilized across multiple repositories.
|
||||||
|
|
||||||
|
- [Python](#python)
|
||||||
|
- [Javascript / Typescript / NodeJS](#nodejs)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
#### Python
|
||||||
|
|
||||||
|
The following guidelines apply to any projects written with Python:
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Indentation
|
||||||
|
|
||||||
|
Use `4 spaces` per indentation level.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> ✅ Correct
|
||||||
|
> ```python
|
||||||
|
> def Encrypt( key : int, bytestr : bytes ):
|
||||||
|
> res = b''
|
||||||
|
> i_blk, left_bytes = divmod( len(bytestr), 3 )
|
||||||
|
> ```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> ❌ Wrong
|
||||||
|
> ```python
|
||||||
|
> def encrypt( key : int, byteStr : bytes ):
|
||||||
|
> Res = b''
|
||||||
|
> iBlk, leftBytes = divmod( len(byteStr), 3 )
|
||||||
|
> ```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Line Length
|
||||||
|
|
||||||
|
Keep the maximum character count to `100 characters per line`. If you are revising old code which doesn't follow this guideline; please rewrite it to conform.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Blank Lines
|
||||||
|
|
||||||
|
Surround top-level functions and class definitions with a blank in-between.
|
||||||
|
|
||||||
|
Method definitions inside a class are surrounded by a single blank line.
|
||||||
|
|
||||||
|
Extra blank lines may be used (sparingly) to separate groups of functions related to one another. Blank lines may be omitted between a bunch of related one-liners (e.g: set of dummy implementations).
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Imports
|
||||||
|
|
||||||
|
Imports should usually be on separate lines:
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> ✅ Correct
|
||||||
|
> ```python
|
||||||
|
> import os
|
||||||
|
> import sys
|
||||||
|
> ```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> ❌ Wrong
|
||||||
|
> ```python
|
||||||
|
> import sys, os
|
||||||
|
> ```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
The following is acceptable:
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> ✅ Correct
|
||||||
|
> ```python
|
||||||
|
> from mypkg import siblingA, siblingB, siblingC
|
||||||
|
> ```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Commenting
|
||||||
|
|
||||||
|
Comment your code. It helps novice readers to better understand the process. It doesn't have to be painfully obvious explanations, but it helps to give an idea of what something does.
|
||||||
|
|
||||||
|
Please append `#` to the beginning of each line.
|
||||||
|
|
||||||
|
```python
|
||||||
|
# #
|
||||||
|
# byteString : b'1#Aetherx|232#1#233262#0#0#0#'
|
||||||
|
# #
|
||||||
|
|
||||||
|
def Encrypt( key : int, byteString : bytes ):
|
||||||
|
res = bytearray( )
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Casing
|
||||||
|
|
||||||
|
- Stick to `camelCase`; unless:
|
||||||
|
- naming functions, capitalize the first letter
|
||||||
|
- Capitalize enums
|
||||||
|
- If you see code not conforming with this, please revise it in your pull request.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> ✅ Correct
|
||||||
|
> ```python
|
||||||
|
> def Encrypt( key : int, byteStr : bytes ):
|
||||||
|
> res = b''
|
||||||
|
> iBlock, leftBytes = divmod( len(byteStr), 3 )
|
||||||
|
> ```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> ❌ Wrong
|
||||||
|
> ```python
|
||||||
|
> def encrypt( key : int, bytestr : bytes ):
|
||||||
|
> res = b''
|
||||||
|
> i_blk, left_bytes = divmod( len(bytestr), 3 )
|
||||||
|
> ```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
**[`^ back to top ^`](#about)**
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
#### NodeJS
|
||||||
|
|
||||||
|
The following allows you to configure ESLint and Prettier.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Prettier
|
||||||
|
|
||||||
|
We have opted to make use of [ESLint](#eslint) over Prettier. We provide a detailed ESLint flag config file with very specific linting rules. Please review that section for more information.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### ESLint
|
||||||
|
|
||||||
|
Within the root folder of the repo, there are several configuration files which you should be using within the project. These files dictate how prettier and eslint will behave and what is acceptable / not acceptable.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Pick the config file below depending on which version of ESLint you are using. The v8 and older `.eslint` may not be there if we have migrated over to an Eslint v9 flat config file:
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
###### v9 & Newer (Config)
|
||||||
|
|
||||||
|
Our NodeJS applications require that you utilize ESLint v9 or newer which makes use of a flat config structure. You may find a copy of our flat config at the link below:
|
||||||
|
|
||||||
|
- [📄 eslint.config.mjs](https://github.com/thebinaryninja/tvapp2/blob/main/tvapp2/eslint.config.mjs)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
###### v8 & Older (Config)
|
||||||
|
|
||||||
|
- We no longer utilize any version of ESLint older than version 9.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> When submitting your pull request, these linting and style rules will be verified with all of your files. If you did not follow these rules; the linter tests on your pull request will fail; and you'll be expected to correct these issues before your submission will be transferred over for human review.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Packages
|
||||||
|
|
||||||
|
We use the following packages for linting and prettier.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
| Package | Repo File | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| [@stylistic/eslint-plugin-js](https://npmjs.com/package/@stylistic/eslint-plugin-js) | [package.json](./package.json) | JavaScript stylistic rules for ESLint, migrated from eslint core. |
|
||||||
|
| [@stylistic/eslint-plugin-ts](https://npmjs.com/package/@stylistic/eslint-plugin-ts) | [package.json](./package.json) | TypeScript stylistic rules for ESLint, migrated from typescript-eslint. |
|
||||||
|
| [@stylistic/eslint-plugin-plus](https://npmjs.com/package/@stylistic/eslint-plugin-plus) | [package.json](./package.json) | Supplementary rules introduced by ESLint Stylistic. |
|
||||||
|
| [eslint-plugin-prettier](https://npmjs.com/package/eslint-plugin-prettier) | [package.json](./package.json) | Runs Prettier as an ESLint rule and reports differences as individual ESLint issues. |
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
You can add the following to your `package.json` file:
|
||||||
|
|
||||||
|
https://github.com/TheBinaryNinja/tvapp2/blob/1c75f11e9f0506ad3dd05133fdafc3aeb87686ca/tvapp2/package.json#L81-L92
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Indentation
|
||||||
|
|
||||||
|
Use `4 spaces` per indentation level.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Style
|
||||||
|
|
||||||
|
For files that are not controlled by [Prettier](#prettier) or [ESLint](#eslint); use `Allman Style`. Braces should be on their own lines, and any code inside the braces should be indented 4 spaces.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return {
|
||||||
|
status: "failure",
|
||||||
|
user:
|
||||||
|
{
|
||||||
|
id: "1aaa35aa-fb3a-62ae-ffec-a14g7fc401ac",
|
||||||
|
label: "Test String",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
while (x == y)
|
||||||
|
{
|
||||||
|
foo();
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Line Length
|
||||||
|
|
||||||
|
Keep the maximum character count to `100 characters per line`. The configs on this page have prettier automatically set up to detect more than 100 characters per line.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Commenting
|
||||||
|
|
||||||
|
Comment your code. It helps novice readers to better understand the process. You may use block style commenting, or single lines:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
/*
|
||||||
|
tests to decide if the end-user is running on Darwin or another platform.
|
||||||
|
*/
|
||||||
|
|
||||||
|
test(`Return true if platform is Darwin`, () => {
|
||||||
|
process.platform = 'darwin';
|
||||||
|
expect(bIsDarwin()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(`Return false if platform is not Darwin`, () => {
|
||||||
|
process.platform = 'linux';
|
||||||
|
expect(bIsDarwin()).toBe(false);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
##### Casing
|
||||||
|
|
||||||
|
Stick to `camelCase` as much as possible.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
let myVar = 'one';
|
||||||
|
let secondVar = 'two';
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
If you are defining a new environment variable; it must be in ALL CAPS in the `Dockerfile`:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
ENV DIR_BUILD=/usr/src/app
|
||||||
|
ENV DIR_RUN=/usr/bin/app
|
||||||
|
ENV URL_REPO="https://git.binaryninja.net/binaryninja/"
|
||||||
|
ENV WEB_IP="0.0.0.0"
|
||||||
|
ENV WEB_PORT=4124
|
||||||
|
ENV STREAM_QUALITY="hd"
|
||||||
|
ENV FILE_PLAYLIST="playlist.m3u8"
|
||||||
|
ENV FILE_EPG="xmltv.xml"
|
||||||
|
ENV LOG_LEVEL=4
|
||||||
|
ENV TZ="Etc/UTC"
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Then you may call your new environment variable within the Javascript code; and ensure you define a default value to correct any user misconfigurations:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const envUrlRepo = process.env.URL_REPO || 'https://git.binaryninja.net/binaryninja';
|
||||||
|
const envStreamQuality = process.env.STREAM_QUALITY || 'hd';
|
||||||
|
const envFileM3U = process.env.FILE_PLAYLIST || 'playlist.m3u8';
|
||||||
|
const envFileXML = process.env.FILE_EPG || 'xmltv.xml';
|
||||||
|
const envFileTAR = process.env.FILE_TAR || 'xmltv.xml.gz';
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
**[`^ back to top ^`](#about)**
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
<!-- markdownlint-disable -->
|
||||||
|
|
||||||
|
<!-- BADGE > GENERAL -->
|
||||||
|
[general-npmjs-uri]: https://npmjs.com
|
||||||
|
[general-nodejs-uri]: https://nodejs.org
|
||||||
|
[general-npmtrends-uri]: http://npmtrends.com/tvapp2
|
||||||
|
|
||||||
|
<!-- BADGE > VERSION > GITHUB -->
|
||||||
|
[github-version-img]: https://img.shields.io/github/v/tag/thebinaryninja/tvapp2?logo=GitHub&label=Version&color=ba5225
|
||||||
|
[github-version-uri]: https://github.com/thebinaryninja/tvapp2/releases
|
||||||
|
|
||||||
|
<!-- BADGE > LICENSE > MIT -->
|
||||||
|
[license-mit-img]: https://img.shields.io/badge/MIT-FFF?logo=creativecommons&logoColor=FFFFFF&label=License&color=9d29a0
|
||||||
|
[license-mit-uri]: https://github.com/thebinaryninja/tvapp2/blob/main/LICENSE
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > DOWNLOAD COUNT -->
|
||||||
|
[github-downloads-img]: https://img.shields.io/github/downloads/thebinaryninja/tvapp2/total?logo=github&logoColor=FFFFFF&label=Downloads&color=376892
|
||||||
|
[github-downloads-uri]: https://github.com/thebinaryninja/tvapp2/releases
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > DOWNLOAD SIZE -->
|
||||||
|
[github-size-img]: https://img.shields.io/github/repo-size/thebinaryninja/tvapp2?logo=github&label=Size&color=59702a
|
||||||
|
[github-size-uri]: https://github.com/thebinaryninja/tvapp2/releases
|
||||||
|
|
||||||
|
<!-- BADGE > ALL CONTRIBUTORS -->
|
||||||
|
[contribs-all-img]: https://img.shields.io/github/all-contributors/thebinaryninja/tvapp2?logo=contributorcovenant&color=de1f6f&label=contributors
|
||||||
|
[contribs-all-uri]: https://github.com/all-contributors/all-contributors
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > BUILD > NPM -->
|
||||||
|
[github-build-img]: https://img.shields.io/github/actions/workflow/status/thebinaryninja/tvapp2/npm-release.yml?logo=github&logoColor=FFFFFF&label=Build&color=%23278b30
|
||||||
|
[github-build-uri]: https://github.com/thebinaryninja/tvapp2/actions/workflows/npm-release.yml
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > BUILD > Pypi -->
|
||||||
|
[github-build-pypi-img]: https://img.shields.io/github/actions/workflow/status/thebinaryninja/tvapp2/release-pypi.yml?logo=github&logoColor=FFFFFF&label=Build&color=%23278b30
|
||||||
|
[github-build-pypi-uri]: https://github.com/thebinaryninja/tvapp2/actions/workflows/pypi-release.yml
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > TESTS -->
|
||||||
|
[github-tests-img]: https://img.shields.io/github/actions/workflow/status/thebinaryninja/tvapp2/npm-tests.yml?logo=github&label=Tests&color=2c6488
|
||||||
|
[github-tests-uri]: https://github.com/thebinaryninja/tvapp2/actions/workflows/npm-tests.yml
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > COMMIT -->
|
||||||
|
[github-commit-img]: https://img.shields.io/github/last-commit/thebinaryninja/tvapp2?logo=conventionalcommits&logoColor=FFFFFF&label=Last%20Commit&color=313131
|
||||||
|
[github-commit-uri]: https://github.com/thebinaryninja/tvapp2/commits/main/
|
||||||
|
|
||||||
|
<!-- BADGE > Github > Docker Image > SELFHOSTED BADGES -->
|
||||||
|
[github-docker-version-img]: https://badges-ghcr.onrender.com/thebinaryninja/tvapp2/latest_tag?color=%233d9e18&ignore=development-amd64%2Cdevelopment%2Cdevelopment-arm64%2Clatest&label=version&trim=
|
||||||
|
[github-docker-version-uri]: https://github.com/thebinaryninja/tvapp2/pkgs/container/tvapp2
|
||||||
|
|
||||||
|
<!-- BADGE > Dockerhub > Docker Image -->
|
||||||
|
[dockerhub-docker-version-img]: https://img.shields.io/docker/v/thebinaryninja/tvapp2?sort=semver&arch=arm64
|
||||||
|
[dockerhub-docker-version-uri]: https://hub.docker.com/repository/docker/thebinaryninja/tvapp2/general
|
||||||
|
|
||||||
|
<!-- BADGE > Gitea > Docker Image > SELFHOSTED BADGES -->
|
||||||
|
[gitea-docker-version-img]: https://badges-ghcr.onrender.com/thebinaryninja/tvapp2/latest_tag?color=%233d9e18&ignore=latest&label=version&trim=
|
||||||
|
[gitea-docker-version-uri]: https://git.binaryninja.net/BinaryNinja/tvapp2
|
||||||
|
|
||||||
|
<!-- BADGE > Gitea 2 > Docker Image -->
|
||||||
|
[gitea2-docker-version-img]: https://img.shields.io/gitea/v/release/binaryninja/tvapp2?gitea_url=https%3A%2F%2Fgit.binaryninja.net
|
||||||
|
[gitea2-docker-version-uri]: https://git.binaryninja.net/BinaryNinja/-/packages/container/tvapp2/latest
|
||||||
|
|
||||||
|
<!-- BADGE > BUTTON > SUBMIT ISSUES -->
|
||||||
|
[btn-github-submit-img]: https://img.shields.io/badge/submit%20new%20issue-de1f5c?style=for-the-badge&logo=github&logoColor=FFFFFF
|
||||||
|
[btn-github-submit-uri]: https://github.com/thebinaryninja/tvapp2/issues
|
||||||
|
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
<!-- markdownlint-restore -->
|
||||||
@@ -9,8 +9,9 @@ conventions:
|
|||||||
|
|
||||||
The tag symbol in conjunction with a version number denotes when a specific feature or behavior was added. Make sure you're at least on this version if you want to use it.
|
The tag symbol in conjunction with a version number denotes when a specific feature or behavior was added. Make sure you're at least on this version if you want to use it.
|
||||||
|
|
||||||
|
: <!-- md:version --> default
|
||||||
: <!-- md:version stable- --> stable
|
: <!-- md:version stable- --> stable
|
||||||
: <!-- md:version beta- --> beta
|
: <!-- md:version development- --> development
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
@@ -19,11 +20,13 @@ The tag symbol in conjunction with a version number denotes when a specific feat
|
|||||||
These icons define what type of control a specified setting uses.
|
These icons define what type of control a specified setting uses.
|
||||||
|
|
||||||
: <!-- md:control toggle --> toggle
|
: <!-- md:control toggle --> toggle
|
||||||
|
: <!-- md:control toggle_on --> toggle on
|
||||||
|
: <!-- md:control toggle_off --> toggle off
|
||||||
: <!-- md:control textbox --> textbox
|
: <!-- md:control textbox --> textbox
|
||||||
: <!-- md:control dropdown --> dropdown
|
: <!-- md:control dropdown --> dropdown
|
||||||
: <!-- md:control button --> button
|
: <!-- md:control button --> button
|
||||||
: <!-- md:control slider --> slider
|
: <!-- md:control slider --> slider
|
||||||
: <!-- md:control color --> color wheel
|
: <!-- md:control color #E5E5E5 #121315 --> color wheel
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
@@ -45,40 +48,42 @@ This defines a command
|
|||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
### <!-- md:flag experimental --> – Experimental { data-toc-label="Experimental" }
|
### <!-- md:flag --> – Flags { #flags data-toc-label="Flags" }
|
||||||
|
|
||||||
|
: <!-- md:flag --> Default
|
||||||
|
: <!-- md:flag experimental --> Experimental
|
||||||
|
: <!-- md:flag required --> Required
|
||||||
|
: <!-- md:flag customization --> Customization
|
||||||
|
: <!-- md:flag metadata --> Metadata
|
||||||
|
: <!-- md:flag dangerous --> Dangerous
|
||||||
|
: <!-- md:flag multiple --> Multiple
|
||||||
|
: <!-- md:flag setting --> Setting
|
||||||
|
|
||||||
Anything listed with this icon are features or functionality that are still in development and may change in future versions.
|
Anything listed with this icon are features or functionality that are still in development and may change in future versions.
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
### <!-- md:flag required --> – Required value { #required data-toc-label="Required value" }
|
|
||||||
|
|
||||||
Items listed with this symbol indicate that they are required to be set.
|
|
||||||
|
|
||||||
<br />
|
|
||||||
|
|
||||||
### <!-- md:flag customization --> – Customization { #customization data-toc-label="Customization" }
|
|
||||||
|
|
||||||
This symbol denotes that the item described is a customization which affects the overall look of the app.
|
|
||||||
|
|
||||||
<br />
|
|
||||||
|
|
||||||
### <!-- md:3rdparty --> – 3rd Party { data-toc-label="3rd Party" }
|
### <!-- md:3rdparty --> – 3rd Party { data-toc-label="3rd Party" }
|
||||||
|
|
||||||
This symbol denotes that the item described is classified as something that changes the overall functionality of the plugin.
|
This symbol denotes that the item described is classified as something that changes the overall functionality of the plugin.
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
### <!-- md:flag metadata --> – Metadata property { #metadata data-toc-label="Metadata property" }
|
### <!-- md:flag setting --> – Configurable Settings { #setting data-toc-label="Configurable Setting" }
|
||||||
|
|
||||||
This symbol denotes that the item described is a metadata property, which can
|
The following denotes a configurable setting. These can also be broken up into individual settings as shown below:
|
||||||
be used in Markdown documents as part of the front matter definition.
|
|
||||||
|
|
||||||
<br />
|
#### <!-- md:setting example.setting.enabled -->
|
||||||
|
<!-- md:version 1.0.0 -->
|
||||||
|
<!-- md:default `true` -->
|
||||||
|
|
||||||
### <!-- md:flag setting --> – Configurable Setting { #setting data-toc-label="Configurable Setting" }
|
This is an example setting
|
||||||
|
|
||||||
This symbol denotes that an item is configurable by the user
|
#### <!-- md:setting example.setting.other -->
|
||||||
|
<!-- md:version 1.0.0 -->
|
||||||
|
<!-- md:default `true` -->
|
||||||
|
|
||||||
|
This is another example setting
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
@@ -91,9 +96,23 @@ can be used multiple times in the `plugins` setting in `mkdocs.yml`.
|
|||||||
|
|
||||||
### <!-- md:feature --> – Optional feature { #feature data-toc-label="Optional feature" }
|
### <!-- md:feature --> – Optional feature { #feature data-toc-label="Optional feature" }
|
||||||
|
|
||||||
Most of the features are hidden behind feature flags, which means they must
|
Some features may be hidden behind feature flags, which means they must
|
||||||
be explicitly enabled via `mkdocs.yml`. This allows for the existence of
|
be explicitly enabled first before they can be configured. This allows
|
||||||
potentially orthogonal features.
|
for the existence of potentially orthogonal features.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### <!-- md:markdown --> – Markdown extension { data-toc-label="Markdown extension" #extension }
|
||||||
|
|
||||||
|
This symbol denotes that the thing described is a Markdown element.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### <!-- md:flag dangerous --> – Dangerous { #danger data-toc-label="Dangerous Property" }
|
||||||
|
|
||||||
|
This symbol denotes that the item described is a metadata property, which can
|
||||||
|
be used in Markdown documents as part of the front matter definition.
|
||||||
|
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
@@ -107,3 +126,58 @@ available to backers. Normal users will not have access to this particular item.
|
|||||||
---
|
---
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
## Other Tags
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### Example Download { #example data-toc-label="Dangerous Property" }
|
||||||
|
<!-- md:example my-example-file -->
|
||||||
|
|
||||||
|
The following denotes a downloadable file.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
<!-- md:command `-s, --start` -->
|
||||||
|
|
||||||
|
The above denotes a command which can be executed in a terminal / command prompt.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
Options are another form of setting which lists what the option does, and then examples of how it works.
|
||||||
|
|
||||||
|
<!-- md:option rss.enabled -->
|
||||||
|
|
||||||
|
: <!-- md:default `true` --> This option specifies whether
|
||||||
|
the plugin is enabled when building your project. If you want to speed up
|
||||||
|
local builds, you can use an [environment variable][mkdocs.env]:
|
||||||
|
|
||||||
|
``` yaml
|
||||||
|
plugins:
|
||||||
|
- rss:
|
||||||
|
enabled: !ENV [CI, false]
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- md:option rss.match_path -->
|
||||||
|
|
||||||
|
: <!-- md:default `.*` --> This option specifies which
|
||||||
|
pages should be included in the feed. For example, to only include blog
|
||||||
|
posts in the feed, use the following regular expression:
|
||||||
|
|
||||||
|
``` yaml
|
||||||
|
plugins:
|
||||||
|
- rss:
|
||||||
|
match_path: blog/posts/.*
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|||||||
236
docs/docs/about/what_is_tvapp.md
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
---
|
||||||
|
title: About TVApp2
|
||||||
|
tags:
|
||||||
|
- info
|
||||||
|
---
|
||||||
|
|
||||||
|
# About
|
||||||
|
|
||||||
|
<figure markdown="span">
|
||||||
|
{ width="60%" }
|
||||||
|
<figcaption>TVApp2 Main Interface</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<h1 align="center"><b>TVApp2: M3U Playlist & Data Guides</b></h1>
|
||||||
|
|
||||||
|
<p align="center" markdown="1">
|
||||||
|
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
[![Version][github-version-img]][github-version-uri]
|
||||||
|
[![Downloads][github-downloads-img]][github-downloads-uri]
|
||||||
|
[![Size][github-size-img]][github-size-img]
|
||||||
|
[![Last Commit][github-commit-img]][github-commit-img]
|
||||||
|
[![Contributors][contribs-all-img]](#contributors)
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
## What is TVApp2?
|
||||||
|
|
||||||
|
**TVApp2** is a docker image which allows you to download M3U playlists and EPG guide data from various online IPTV services such as **TheTVApp**, **TVPass**, and **MoveOnJoy**. The playlist and guide data files can be imported into your favorite IPTV applications such as Jellyfin, Plex, and Emby.
|
||||||
|
|
||||||
|
Once the docker container is started; a fresh copy of the channel list and TV guide data will be downloaded and generated within your docker container. You can then visit the website URL associated with your docker container; which will give you direct links to the files that you can utilize with the above listed IPTV apps.
|
||||||
|
|
||||||
|
All channels contain multiple sources so that you have a reliable streaming experience, and helps you combat moments when one channel source goes offline.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Image Sources
|
||||||
|
|
||||||
|
This project contains several repositories which all share the same code; use them as backups:
|
||||||
|
|
||||||
|
- [🔀 dockerhub:thebinaryninja/tvapp2](https://hub.docker.com/r/thebinaryninja/tvapp2)
|
||||||
|
- [🔀 github:thebinaryninja/tvapp2](https://github.com/thebinaryninja/tvapp2)
|
||||||
|
- [🔀 gitea:git.binaryninja.net/binaryninja/tvapp2](https://git.binaryninja.net/binaryninja/tvapp2)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
| Pull URL | Registry | Arch | Version |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `ghcr.io/thebinaryninja/tvapp2:latest`<br />`ghcr.io/thebinaryninja/tvapp2:development` | Github | amd64<br/>arm64 | [![Github][github-docker-version-img]][github-docker-version-uri] |
|
||||||
|
| `thebinaryninja/tvapp2:latest`<br />`thebinaryninja/tvapp2:development` | Dockerhub | amd64<br/>arm64 | [![Dockerhub][dockerhub-docker-version-img]][dockerhub-docker-version-uri] |
|
||||||
|
| `git.binaryninja.net/binaryninja/tvapp2:latest`<br />`git.binaryninja.net/binaryninja/tvapp2:development` | Gitea | amd64<br/>arm64 | [![Gitea][gitea-docker-version-img]][gitea-docker-version-uri] |
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
The following is a small list of the features available with the TVApp2 container:
|
||||||
|
|
||||||
|
- Multiple IPTV service sources:
|
||||||
|
- TheTVApp
|
||||||
|
- TVPass
|
||||||
|
- MoveOnJoy
|
||||||
|
- Channel playlists can be downloaded as a `.m38u` or a compressed `.gzip` archive.
|
||||||
|
- Compressed gzip compatible with 3rd party apps like Cabernet and Jellyfin.
|
||||||
|
- Tracking statistics which show the last update time, size, and a description for each file's purpose.
|
||||||
|
- API endpoints:
|
||||||
|
- **Resync All Files**
|
||||||
|
- http://127.0.0.1:4124/api/resync
|
||||||
|
- http://127.0.0.1:4124/api/restart
|
||||||
|
- **Health check**
|
||||||
|
- http://127.0.0.1:4124/api/health
|
||||||
|
- http://127.0.0.1:4124/api/status
|
||||||
|
- Direct access to download each of the generated files, including multiple easy-to-remember URLs for each file type.
|
||||||
|
- **M3U Playlist**:
|
||||||
|
- http://127.0.0.1:4124/playlist
|
||||||
|
- http://127.0.0.1:4124/m3u
|
||||||
|
- http://127.0.0.1:4124/m38u
|
||||||
|
- **EPG Guide Data (Uncompressed)**:
|
||||||
|
- http://127.0.0.1:4124/guide
|
||||||
|
- http://127.0.0.1:4124/epg
|
||||||
|
- http://127.0.0.1:4124/xml
|
||||||
|
- **EPG Guide Data (Compressed)**:
|
||||||
|
- http://127.0.0.1:4124/gzip
|
||||||
|
- http://127.0.0.1:4124/gz
|
||||||
|
- Video sources include both quality options `hd` and `sd`.
|
||||||
|
- Easily mountable docker volumes to access the generated files quickly.
|
||||||
|
- Wide variety of docker environment variables to change the binding IP, port, app root directory, quality, timezone, etc.
|
||||||
|
- Small docker image size; based on Alpine 3.x which averages `40MB`.
|
||||||
|
- Compatible with architectures `amd64` and `arm64/aarm64`.
|
||||||
|
- Example configurations for 3rd party apps such as Traefik and Authentik.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## ✨ Contributors
|
||||||
|
|
||||||
|
We are always looking for contributors. If you feel that you can provide something useful to Gistr, then we'd love to review your suggestion. Before submitting your contribution, please review the following resources:
|
||||||
|
|
||||||
|
- [Pull Request Procedure](https://github.com/TheBinaryNinja/tvapp2/blob/main/.github/PULL_REQUEST_TEMPLATE.md)
|
||||||
|
- [Contributor Policy](https://github.com/TheBinaryNinja/tvapp2/blob/main/CONTRIBUTING.md)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Want to help but can't write code?
|
||||||
|
- Review [active questions by our community](https://github.com/TheBinaryNinja/tvapp2/labels/help%20wanted) and answer the ones you know.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div align="center" markdown="1">
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
The following people have helped get this project going:
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div align="center" markdown="1">
|
||||||
|
|
||||||
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||||
|
[![Contributors][contribs-all-img]](#contributors)
|
||||||
|
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||||
|
|
||||||
|
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
<!-- markdownlint-disable -->
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top"><a href="https://github.com/Aetherinox">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/118329232?v=4?s=40" width="80px;" alt="Aetherinox"/><br /><sub><b>Aetherinox</b></sub></a><br /><a href="https://github.com/TheBinaryNinja/tvapp2/commits?author=Aetherinox" title="Code">💻</a>
|
||||||
|
</td>
|
||||||
|
<td align="center" valign="top"><a href="https://github.com/iFlip721">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/28721588?v=4" width="80px;" alt="iFlip721"/><br /><sub><b>iFlip721</b></sub></a><br /><a href="https://github.com/TheBinaryNinja/tvapp2/commits?author=iFlip721" title="Code">💻</a>
|
||||||
|
</td>
|
||||||
|
<td align="center" valign="top"><a href="https://github.com/Nvmdfth">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/32874812?v=4" width="80px;" alt="Nvmdfth"/><br /><sub><b>Optx</b></sub></a><br /><a href="https://github.com/TheBinaryNinja/tvapp2/commits?author=Nvmdfth" title="Code">💻</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!-- markdownlint-restore -->
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
<!-- markdownlint-disable -->
|
||||||
|
|
||||||
|
<!-- BADGE > GENERAL -->
|
||||||
|
[general-npmjs-uri]: https://npmjs.com
|
||||||
|
[general-nodejs-uri]: https://nodejs.org
|
||||||
|
[general-npmtrends-uri]: http://npmtrends.com/csf-firewall
|
||||||
|
|
||||||
|
<!-- BADGE > VERSION > GITHUB -->
|
||||||
|
[github-version-img]: https://img.shields.io/github/v/tag/TheBinaryNinja/tvapp2?logo=GitHub&label=Version&color=ba5225
|
||||||
|
[github-version-uri]: https://github.com/TheBinaryNinja/tvapp2/releases
|
||||||
|
|
||||||
|
<!-- BADGE > LICENSE > MIT -->
|
||||||
|
[license-mit-img]: https://img.shields.io/badge/MIT-FFF?logo=creativecommons&logoColor=FFFFFF&label=License&color=9d29a0
|
||||||
|
[license-mit-uri]: https://github.com/TheBinaryNinja/tvapp2/blob/main/LICENSE
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > DOWNLOAD COUNT -->
|
||||||
|
[github-downloads-img]: https://img.shields.io/github/downloads/TheBinaryNinja/tvapp2/total?logo=github&logoColor=FFFFFF&label=Downloads&color=376892
|
||||||
|
[github-downloads-uri]: https://github.com/TheBinaryNinja/tvapp2/releases
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > DOWNLOAD SIZE -->
|
||||||
|
[github-size-img]: https://img.shields.io/github/repo-size/TheBinaryNinja/tvapp2?logo=github&label=Size&color=59702a
|
||||||
|
[github-size-uri]: https://github.com/TheBinaryNinja/tvapp2/releases
|
||||||
|
|
||||||
|
<!-- BADGE > ALL CONTRIBUTORS -->
|
||||||
|
[contribs-all-img]: https://img.shields.io/github/all-contributors/TheBinaryNinja/tvapp2?logo=contributorcovenant&color=de1f6f&label=contributors
|
||||||
|
[contribs-all-uri]: https://github.com/all-contributors/all-contributors
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > BUILD > NPM -->
|
||||||
|
[github-build-img]: https://img.shields.io/github/actions/workflow/status/TheBinaryNinja/tvapp2/npm-release.yml?logo=github&logoColor=FFFFFF&label=Build&color=%23278b30
|
||||||
|
[github-build-uri]: https://github.com/TheBinaryNinja/tvapp2/actions/workflows/npm-release.yml
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > BUILD > Pypi -->
|
||||||
|
[github-build-pypi-img]: https://img.shields.io/github/actions/workflow/status/TheBinaryNinja/tvapp2/release-pypi.yml?logo=github&logoColor=FFFFFF&label=Build&color=%23278b30
|
||||||
|
[github-build-pypi-uri]: https://github.com/TheBinaryNinja/tvapp2/actions/workflows/pypi-release.yml
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > TESTS -->
|
||||||
|
[github-tests-img]: https://img.shields.io/github/actions/workflow/status/TheBinaryNinja/tvapp2/npm-tests.yml?logo=github&label=Tests&color=2c6488
|
||||||
|
[github-tests-uri]: https://github.com/TheBinaryNinja/tvapp2/actions/workflows/npm-tests.yml
|
||||||
|
|
||||||
|
<!-- BADGE > GITHUB > COMMIT -->
|
||||||
|
[github-commit-img]: https://img.shields.io/github/last-commit/TheBinaryNinja/tvapp2?logo=conventionalcommits&logoColor=FFFFFF&label=Last%20Commit&color=313131
|
||||||
|
[github-commit-uri]: https://github.com/TheBinaryNinja/tvapp2/commits/main/
|
||||||
|
|
||||||
|
<!-- BADGE > Github > Docker Image > SELFHOSTED BADGES -->
|
||||||
|
[github-docker-version-img]: https://badges-ghcr.onrender.com/thebinaryninja/tvapp2/latest_tag?color=%233d9e18&ignore=development-amd64%2Cdevelopment%2Cdevelopment-arm64%2Clatest&label=version&trim=
|
||||||
|
[github-docker-version-uri]: https://github.com/TheBinaryNinja/tvapp2/pkgs/container/tvapp2
|
||||||
|
|
||||||
|
<!-- BADGE > Dockerhub > Docker Image -->
|
||||||
|
[dockerhub-docker-version-img]: https://img.shields.io/docker/v/thebinaryninja/tvapp2?sort=semver&arch=arm64
|
||||||
|
[dockerhub-docker-version-uri]: https://hub.docker.com/repository/docker/thebinaryninja/tvapp2/general
|
||||||
|
|
||||||
|
<!-- BADGE > Gitea > Docker Image > SELFHOSTED BADGES -->
|
||||||
|
[gitea-docker-version-img]: https://badges-ghcr.onrender.com/thebinaryninja/tvapp2/latest_tag?color=%233d9e18&ignore=latest&label=version&trim=
|
||||||
|
[gitea-docker-version-uri]: https://git.binaryninja.net/BinaryNinja/tvapp2
|
||||||
|
|
||||||
|
<!-- BADGE > Gitea 2 > Docker Image -->
|
||||||
|
[gitea2-docker-version-img]: https://img.shields.io/gitea/v/release/binaryninja/tvapp2?gitea_url=https%3A%2F%2Fgit.binaryninja.net
|
||||||
|
[gitea2-docker-version-uri]: https://git.binaryninja.net/BinaryNinja/-/packages/container/tvapp2/latest
|
||||||
|
|
||||||
|
<!-- BADGE > BUTTON > SUBMIT ISSUES -->
|
||||||
|
[btn-github-submit-img]: https://img.shields.io/badge/submit%20new%20issue-de1f5c?style=for-the-badge&logo=github&logoColor=FFFFFF
|
||||||
|
[btn-github-submit-uri]: https://github.com/TheBinaryNinja/tvapp2/issues
|
||||||
|
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
<!-- markdownlint-restore -->
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
title: About TVApp2
|
|
||||||
tags:
|
|
||||||
- info
|
|
||||||
---
|
|
||||||
|
|
||||||
# About TVApp2
|
|
||||||
|
|
||||||
<br />
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<br />
|
|
||||||
BIN
docs/docs/assets/images/health-toast.gif
Normal file
|
After Width: | Height: | Size: 16 KiB |
521
docs/docs/config/env.md
Normal file
@@ -0,0 +1,521 @@
|
|||||||
|
---
|
||||||
|
title: Environment Variables
|
||||||
|
tags:
|
||||||
|
- config
|
||||||
|
---
|
||||||
|
|
||||||
|
# Environment Variables
|
||||||
|
|
||||||
|
Environment variables allow you to modify how TVApp2 functions within a docker container. Ensure that
|
||||||
|
you understand the setting you are changing before you modify these values, otherwise, TVApp2 may fail to
|
||||||
|
start due to misconfigurations.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## TZ
|
||||||
|
<!-- md:control env -->
|
||||||
|
<!-- md:version stable-1.0.0 -->
|
||||||
|
<!-- md:default `Etc/UTC` -->
|
||||||
|
|
||||||
|
The `TZ` environment variable specifies the timezone that your docker container will
|
||||||
|
utilize. This is useful for syncing your local time with console outputs such as
|
||||||
|
our logging system.
|
||||||
|
|
||||||
|
=== "Example"
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="13" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- TZ=Etc/UTC # (1)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :information: Changing this env variable will change the time for anything
|
||||||
|
related to the TVApp2 docker container.
|
||||||
|
|
||||||
|
=== "Timezones"
|
||||||
|
|
||||||
|
``` yaml
|
||||||
|
Etc/UTC
|
||||||
|
Africa/Cairo
|
||||||
|
Africa/Johannesburg
|
||||||
|
Africa/Lagos
|
||||||
|
America/Argentina/Buenos_Aires
|
||||||
|
America/Bogota
|
||||||
|
America/Caracas
|
||||||
|
America/Chicago
|
||||||
|
America/El_Salvador
|
||||||
|
America/Juneau
|
||||||
|
America/Lima
|
||||||
|
America/Los_Angeles
|
||||||
|
America/Mexico_City
|
||||||
|
America/New_York
|
||||||
|
America/Phoenix
|
||||||
|
America/Santiago
|
||||||
|
America/Sao_Paulo
|
||||||
|
America/Toronto
|
||||||
|
America/Vancouver
|
||||||
|
Asia/Almaty
|
||||||
|
Asia/Ashkhabad
|
||||||
|
Asia/Bahrain
|
||||||
|
Asia/Bangkok
|
||||||
|
Asia/Chongqing
|
||||||
|
Asia/Dubai
|
||||||
|
Asia/Ho_Chi_Minh
|
||||||
|
Asia/Hong_Kong
|
||||||
|
Asia/Jakarta
|
||||||
|
Asia/Jerusalem
|
||||||
|
Asia/Kathmandu
|
||||||
|
Asia/Kolkata
|
||||||
|
Asia/Kuwait
|
||||||
|
Asia/Muscat
|
||||||
|
Asia/Qatar
|
||||||
|
Asia/Riyadh
|
||||||
|
Asia/Seoul
|
||||||
|
Asia/Shanghai
|
||||||
|
Asia/Singapore
|
||||||
|
Asia/Taipei
|
||||||
|
Asia/Tehran
|
||||||
|
Asia/Tokyo
|
||||||
|
Atlantic/Reykjavik
|
||||||
|
Australia/ACT
|
||||||
|
Australia/Adelaide
|
||||||
|
Australia/Brisbane
|
||||||
|
Australia/Sydney
|
||||||
|
Europe/Athens
|
||||||
|
Europe/Belgrade
|
||||||
|
Europe/Berlin
|
||||||
|
Europe/Copenhagen
|
||||||
|
Europe/Helsinki
|
||||||
|
Europe/Istanbul
|
||||||
|
Europe/London
|
||||||
|
Europe/Luxembourg
|
||||||
|
Europe/Madrid
|
||||||
|
Europe/Moscow
|
||||||
|
Europe/Paris
|
||||||
|
Europe/Riga
|
||||||
|
Europe/Rome
|
||||||
|
Europe/Stockholm
|
||||||
|
Europe/Tallinn
|
||||||
|
Europe/Vilnius
|
||||||
|
Europe/Warsaw
|
||||||
|
Europe/Zurich
|
||||||
|
Pacific/Auckland
|
||||||
|
Pacific/Chatham
|
||||||
|
Pacific/Fakaofo
|
||||||
|
Pacific/Honolulu
|
||||||
|
Pacific/Norfolk
|
||||||
|
US/Mountain
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## WEB_IP
|
||||||
|
<!-- md:control env -->
|
||||||
|
<!-- md:version stable-1.0.0 -->
|
||||||
|
<!-- md:default `0.0.0.0` -->
|
||||||
|
|
||||||
|
The `WEB_IP` environment variable allows you to define what IP address will be
|
||||||
|
bound to the TVApp2 docker image.
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="13" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- WEB_IP=0.0.0.0 # (1)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :information: Specify `0.0.0.0` to bind to all local IP addresses.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## WEB_PORT
|
||||||
|
<!-- md:control env -->
|
||||||
|
<!-- md:version stable-1.0.0 -->
|
||||||
|
<!-- md:default `4124` -->
|
||||||
|
|
||||||
|
The `WEB_PORT` environment variable allows you to define what port the TVApp2
|
||||||
|
docker container will listen to.
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="13" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- WEB_IP=4124 # (1)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :information: The default port is `4124`
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## WEB_ENCODING
|
||||||
|
<!-- md:control env -->
|
||||||
|
<!-- md:version stable-1.3.0 -->
|
||||||
|
<!-- md:default `deflate, br` -->
|
||||||
|
|
||||||
|
The `WEB_ENCODING` environment variable allows you to customize the HTTP `Accept-Encoding` request and response header. This value specifies what content encoding the sender can understand when sending these requests.
|
||||||
|
|
||||||
|
Most users will not need to modify this value unless you are running Jellyfin and receive the following error when attempting to sync EPG data between Jellyfin and the TVApp2 container:
|
||||||
|
|
||||||
|
!!! warning "Jellyfin Error"
|
||||||
|
|
||||||
|
```
|
||||||
|
[ERR] [27] Jellyfin.LiveTv.Guide.GuideManager: Error getting programs for channel
|
||||||
|
XXXXXXXXXXXXXXX (Source 2) System.Xml.XmlException: '', hexadecimal value 0x1F,
|
||||||
|
is an invalid character. Line 1, position 1.
|
||||||
|
```
|
||||||
|
|
||||||
|
If you receive the above error and you have already customized this environment variable to include `gzip`, you must remove it from your accepted encoders string to fix the error.
|
||||||
|
|
||||||
|
=== "Old"
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="13" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- WEB_ENCODING: 'gzip, deflate, br'
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "New"
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="13" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- WEB_ENCODING: 'deflate, br'
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## URL_REPO
|
||||||
|
<!-- md:control env -->
|
||||||
|
<!-- md:version stable-1.0.0 -->
|
||||||
|
<!-- md:default `https://git.binaryninja.net/binaryninja` -->
|
||||||
|
<!-- md:flag dangerous -->
|
||||||
|
|
||||||
|
The `URL_REPO` environment variable allows you to specify what Github repo is used to communicate
|
||||||
|
with in order to fetch IPTV data. This is used as an internal environment variable by the developers
|
||||||
|
and should not be changed by the end-user; otherwise you will be unable to fetch IPTV data.
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="13" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- URL_REPO=https://git.binaryninja.net/binaryninja # (1)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :warning: It is highly recommended that you do not change this value
|
||||||
|
otherwise you will not be able to download the latest M3U playlists
|
||||||
|
and EPG guide data.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## FILE_URL
|
||||||
|
<!-- md:control env -->
|
||||||
|
<!-- md:version stable-1.2.0 -->
|
||||||
|
<!-- md:default `urls.txt` -->
|
||||||
|
|
||||||
|
The `FILE_URL` environment variable allows you to specify what the name of the downloaded `urls.txt` cache file. This file is downloaded when you first spin up the TVApp2 container.
|
||||||
|
|
||||||
|
There should be no need to utilize this environment variable unless you have a specific reason.
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="13" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- FILE_URL=urls.txt # (1)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :warning: There is really no reason to modify this environment variable
|
||||||
|
unless you have a specific purpose.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## FILE_M3U
|
||||||
|
<!-- md:control env -->
|
||||||
|
<!-- md:version stable-1.1.0 -->
|
||||||
|
<!-- md:default `playlist.m3u8` -->
|
||||||
|
|
||||||
|
The `FILE_M3U` environment variable allows you to specify what the name of the downloaded `playlist.m3u8` file will be. This file is downloaded when you first spin up the TVApp2 container, and contains a list of what channels you can pick from.
|
||||||
|
|
||||||
|
There should be no need to utilize this environment variable unless you have a specific reason.
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="13" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- FILE_M3U=playlist.m3u8 # (1)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :warning: There is really no reason to modify this environment variable
|
||||||
|
unless you have a specific purpose.
|
||||||
|
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## FILE_EPG
|
||||||
|
<!-- md:control env -->
|
||||||
|
<!-- md:version stable-1.1.0 -->
|
||||||
|
<!-- md:default `xmltv.xml` -->
|
||||||
|
|
||||||
|
The `FILE_EPG` environment variable specifies the filename that will be utilized when
|
||||||
|
your .xml EPG playlist file is generated.
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="13" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- FILE_EPG=xmltv.xml # (1)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :information: Changing this file only changes the filename locally; it does
|
||||||
|
not affect the server-side fetching mechanism.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## FILE_GZIP
|
||||||
|
<!-- md:control env -->
|
||||||
|
<!-- md:version stable-1.1.0 -->
|
||||||
|
<!-- md:default `xmltv.xml.gz` -->
|
||||||
|
|
||||||
|
The `FILE_GZIP` environment variable specifies the filename that will be utilized when
|
||||||
|
a compressed `.gzip` is generated and when you download the file.
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="13" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- FILE_GZIP=xmltv.xml.gz # (1)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :information: Changing this file only changes the filename locally for
|
||||||
|
generation and downloading. It does not affect the server-side fetching
|
||||||
|
mechanism.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## STREAM_QUALITY
|
||||||
|
<!-- md:control env -->
|
||||||
|
<!-- md:version stable-1.1.0 -->
|
||||||
|
<!-- md:default `hd` -->
|
||||||
|
|
||||||
|
The `STREAM_QUALITY` environment variable specifies the default stream quality that will
|
||||||
|
be used when you initiate a new channel to view.
|
||||||
|
|
||||||
|
Available Options:
|
||||||
|
|
||||||
|
* `hd` High Definition
|
||||||
|
* `sd` Standard Definition
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="13" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- STREAM_QUALITY=hd # (1)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :information: This environment variable has the following options:
|
||||||
|
- hd
|
||||||
|
- sd
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## DIR_BUILD
|
||||||
|
<!-- md:control env -->
|
||||||
|
<!-- md:version stable-1.0.0 -->
|
||||||
|
<!-- md:default `/usr/src/app` -->
|
||||||
|
<!-- md:flag dangerous -->
|
||||||
|
|
||||||
|
The `DIR_BUILD` environment variable specifies what local folder will be utilized
|
||||||
|
by the TVApp2 docker container when the container builds the app.
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="13" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- DIR_BUILD=/usr/src/app # (1)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :warning: You should not change this unless you are an advanced user.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## DIR_RUN
|
||||||
|
<!-- md:control env -->
|
||||||
|
<!-- md:version stable-1.0.0 -->
|
||||||
|
<!-- md:default `/usr/src/app` -->
|
||||||
|
<!-- md:flag dangerous -->
|
||||||
|
|
||||||
|
The `DIR_RUN` environment variable specifies what local folder will be utilized
|
||||||
|
by the TVApp2 docker container when the container has built the app and placed it
|
||||||
|
into a production folder.
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="13" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- DIR_RUN=/usr/bin/app # (1)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :warning: You should not change this unless you are an advanced user.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## LOG_LEVEL
|
||||||
|
<!-- md:control env -->
|
||||||
|
<!-- md:version stable-1.1.0 -->
|
||||||
|
<!-- md:default `4` -->
|
||||||
|
|
||||||
|
The `LOG_LEVEL` environment variable allows you specify how deep logs should go
|
||||||
|
when being output to your console.
|
||||||
|
|
||||||
|
=== "Example"
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="13" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- LOG_LEVEL=4 # (1)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :information: The default log level is `4` (info).
|
||||||
|
|
||||||
|
=== "Log Levels"
|
||||||
|
|
||||||
|
| Log Level | Name | Description |
|
||||||
|
| --------------- | ----------- | ------------------------------------------------------------------------------- |
|
||||||
|
| `6` | :material-checkbox-blank-circle:{ style="color: var(--md-loglevel-trace-color) " } Trace | Displays all possible logs in console, along with anything below this line. |
|
||||||
|
| `5` | :material-checkbox-blank-circle:{ style="color: var(--md-loglevel-debug-color) " } Debug | Displays debug / developer logs, along with anything below this line. |
|
||||||
|
| `4` | :material-checkbox-blank-circle:{ style="color: var(--md-loglevel-info-color) " } Info | Displays informative logs, along with anything below this line. |
|
||||||
|
| `3` | :material-checkbox-blank-circle:{ style="color: var(--md-loglevel-notice-color) " } Notice | Displays important notices, along with anything below this line. |
|
||||||
|
| `2` | :material-checkbox-blank-circle:{ style="color: var(--md-loglevel-warn-color) " } Warn | Displays warnings, along with anything below this line. |
|
||||||
|
| `1` | :material-checkbox-blank-circle:{ style="color: var(--md-loglevel-error-color) " } Error | Displays only errors, none of the log levels above this line will be shown |
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
109
docs/docs/config/volumes.md
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
---
|
||||||
|
title: Environment Variables
|
||||||
|
tags:
|
||||||
|
- config
|
||||||
|
---
|
||||||
|
|
||||||
|
# Mountable Volumes
|
||||||
|
|
||||||
|
Mountable volumes in Docker allow you to share folders within a docker container with your host machine. This allows you to access these specific files without having to bash into the container and using the terminal to navigate around.
|
||||||
|
|
||||||
|
The TVApp2 docker image provides a few different paths that you can mount to your host machine; as outlined below.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## 📁 /usr/bin/app
|
||||||
|
|
||||||
|
<!-- md:control volume -->
|
||||||
|
<!-- md:version stable-1.0.0 -->
|
||||||
|
|
||||||
|
The mountable volume `/usr/bin/app` is where TVApp2 files will be placed once the app has been built when your docker container spins up. The files in this folder include:
|
||||||
|
|
||||||
|
| File | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| `📁 node_modules` | List of all NodeJS packages utilized by TVApp2 |
|
||||||
|
| `📁 www` | Main storage folder for TVApp2. Contains website files and M3U / EPG synced files |
|
||||||
|
| `📄 package.json` | NodeJS package file |
|
||||||
|
| `📄 playlist.m3u8` | Generated playlist containing channels |
|
||||||
|
| `📄 urls.txt` | List containing cached URLs utilized by TVApp2 |
|
||||||
|
| `📄 xmltv.xml` | EPG guide data in uncompressed XML format |
|
||||||
|
| `📄 xmltv.xml.gz` | EPG guide data in compressed GZ archive |
|
||||||
|
| `📄 index.js` | Main source code file for TVApp2 |
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
=== "Example"
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="7" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./app:/usr/bin/app # (1)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :information: Changing this env variable will change the time for anything
|
||||||
|
related to the TVApp2 docker container.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
This folder path can be changed by specifying a new path with the environment variable `DIR_RUN`
|
||||||
|
|
||||||
|
=== "Example"
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="7" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./app:/usr/bin/app # (1) (2)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :information: Changing this env variable will change the folder within the docker container which stores the fully built TVApp2 files.
|
||||||
|
|
||||||
|
2. This should not be used unless you know what you're doing
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## 📁 /config
|
||||||
|
|
||||||
|
<!-- md:control volume -->
|
||||||
|
<!-- md:version stable-1.0.0 -->
|
||||||
|
|
||||||
|
The mountable volume `/config` defines where the TVApp2 application will store SSL certificates related to the TVApp2 web interface being ran using https instead of http. The files in this folder include:
|
||||||
|
|
||||||
|
| File | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| `📁 keys` | Folder which stores the SSL cert and keys |
|
||||||
|
| `📄 keys/cert.crt` | SSL public certificate |
|
||||||
|
| `📄 keys/key.crt` | SSL private key |
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
|
||||||
|
=== "Example"
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="7" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./config:/config # (1) (2)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :information: Changing this env variable will change the folder within the docker container which stores the fully built TVApp2 files.
|
||||||
|
|
||||||
|
2. This should not be used unless you know what you're doing
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
13
docs/docs/includes/abbreviations.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[mkdocs]: https://www.mkdocs.org
|
||||||
|
[mkdocs.dotfiles]: https://www.mkdocs.org/dev-guide/themes/#dot-files
|
||||||
|
[mkdocs.metadata]: https://www.mkdocs.org/user-guide/writing-your-docs/#yaml-style-meta-data
|
||||||
|
[mkdocs.env]: https://www.mkdocs.org/user-guide/configuration/#environment-variables
|
||||||
|
[mkdocs.docs_dir]: https://www.mkdocs.org/user-guide/configuration/#docs_dir
|
||||||
|
[mkdocs.extra_templates]: https://www.mkdocs.org/user-guide/configuration/#extra_templates
|
||||||
|
[mkdocs.site_dir]: https://www.mkdocs.org/user-guide/configuration/#site_dir
|
||||||
|
[mkdocs.site_url]: https://www.mkdocs.org/user-guide/configuration/#site_url
|
||||||
|
[mkdocs.site_description]: https://www.mkdocs.org/user-guide/configuration/#site_description
|
||||||
|
[mkdocs.nav]: https://www.mkdocs.org/user-guide/configuration/#nav
|
||||||
|
[mkdocs.plugins]: https://www.mkdocs.org/user-guide/configuration/#plugins
|
||||||
|
[mkdocs.strict]: https://www.mkdocs.org/user-guide/configuration/#strict
|
||||||
|
[mkdocs.use_directory_urls]: https://www.mkdocs.org/user-guide/configuration/#use_directory_urls
|
||||||
125
docs/docs/install/docker-run.md
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
---
|
||||||
|
title: "Install: docker-run"
|
||||||
|
tags:
|
||||||
|
- install
|
||||||
|
---
|
||||||
|
|
||||||
|
# docker run
|
||||||
|
|
||||||
|
Our documentation provides two ways that you may start up a TVApp2 docker container:
|
||||||
|
|
||||||
|
<div class="grid cards" markdown>
|
||||||
|
|
||||||
|
- :material-circle: [docker run](docker-run.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Spin up the TVApp2 container using the `docker run` command.
|
||||||
|
This is useful for quick launches, but is not time efficient
|
||||||
|
if you plan to use this container long-term.
|
||||||
|
|
||||||
|
This requires a longer command that must be used each time
|
||||||
|
you wish to bring the container up.
|
||||||
|
|
||||||
|
- :material-circle: [docker compose](docker-compose.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Spin up the TVApp2 container by creating a `📄 docker-compose.yml`
|
||||||
|
file which will store all of your options such as env variables,
|
||||||
|
mounted volumes, and labels.
|
||||||
|
|
||||||
|
To bring the container up, `cd` into the folder with the
|
||||||
|
`📄 docker-compose.yml` file, and run the
|
||||||
|
command `docker compose up -d`.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
The `🗔 docker run` command allows you to start up a docker container by providing a set of [options](#command-options) which define how the container should operate, including the environment variables, mounted volumes, assigned IP address, etc.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Start TVApp2
|
||||||
|
|
||||||
|
Pulling the image if needed and starting the container. To spin up a TVApp2 container using this method; run a command similar to the below example. See the section [Options](#options) below for a list of what you can specify.
|
||||||
|
|
||||||
|
=== "Terminal"
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker run -d \
|
||||||
|
--restart=unless-stopped \ # (1)!
|
||||||
|
--name tvapp2 \ # (2)!
|
||||||
|
-p 4124:4124 \ # (3)!
|
||||||
|
-e "TZ=Etc/UTC" \ # (4)!
|
||||||
|
-v ${PWD}/app:/usr/bin/app \ # (5)!
|
||||||
|
ghcr.io/thebinaryninja/tvapp2:latest # (6)!
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Specifies what happens if the container becomes unresponsive or goes down.
|
||||||
|
2. Name to assign the container; otherwise, a random id will be given.
|
||||||
|
3. Port that will be used for the container
|
||||||
|
4. Environment variable which specifies the timezone to use for the container.
|
||||||
|
5. Mount the container volume `/usr/bin/app` to your host machine in the subfolder `./app`
|
||||||
|
6. Specifies what docker image to spin up.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
To confirm that the container has been brought up, run the command `docker ps | grep tvapp2`. If you have the app [Portainer](https://portainer.io/), you can sign into your admin interface and view your TVApp2 container details, instead of using a command-line.
|
||||||
|
|
||||||
|
```
|
||||||
|
e95236c42b43 binaryninja/tvapp2:1.4.0 "/init" 3 seconds ago Up 3 seconds 4124/tcp tvapp2
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
Review the list of docker run options below. These allow you to define how a docker container will start up.
|
||||||
|
|
||||||
|
???- note "Official Docker Documentation"
|
||||||
|
To view a full list of the available docker parameters, view the official docker documentation at:
|
||||||
|
|
||||||
|
- https://docs.docker.com/reference/cli/docker/container/run/
|
||||||
|
|
||||||
|
| Parameter / Flag | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| `-d, --detach` | Run container in background and print container ID |
|
||||||
|
| `-e, --env` | Set environment variable |
|
||||||
|
| `--env-file` | Read in a file of environment variables |
|
||||||
|
| `--expose` | Expose a port or a range of ports |
|
||||||
|
| `--health-cmd` | Command to run to check health |
|
||||||
|
| `--health-interval` | Time between running the check<br/>`ms|s|m|h` (default 0s) |
|
||||||
|
| `--health-retries` | Consecutive failures needed to report unhealthy |
|
||||||
|
| `--health-start-interval` | Time between running the check during the start period<br/>`ms|s|m|h` (default 0s) |
|
||||||
|
| `--health-start-period` | Start period for the container to initialize before starting health-retries countdown<br/>`ms|s|m|h` (default 0s) |
|
||||||
|
| `--health-timeout` | Maximum time to allow one check to run<br/>`ms|s|m|h` (default 0s) |
|
||||||
|
| `-h, --hostname` | Container host name |
|
||||||
|
| `--ip` | IPv4 address (e.g., 172.30.100.104) |
|
||||||
|
| `--ip6` | IPv6 address (e.g., 2001:db8::33) |
|
||||||
|
| `-l, --label` | Set meta data on a container |
|
||||||
|
| `--mount` | Attach a filesystem mount to the container |
|
||||||
|
| `--name` | Assign a name to the container |
|
||||||
|
| `--network` | Connect a container to a network |
|
||||||
|
| `--privileged` | Give extended privileges to this container |
|
||||||
|
| `-p, --publish` | Publish a container's port(s) to the host |
|
||||||
|
| `--pull` | Pull image before running<br/>`always`, `missing`, `never` |
|
||||||
|
| `--restart` | Restart policy to apply when a container exits <br/> `on-failure[:max-retries]`, `always`, `unless-stopped` |
|
||||||
|
| `-u, --user` | Username or UID <br/>`<name|uid>[:<group|gid>]` |
|
||||||
|
| `-v, --volume` | Bind mount a volume |
|
||||||
|
| `-w, --workdir` | Working directory inside the container |
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
47
docs/docs/install/index.md
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
---
|
||||||
|
title: Install
|
||||||
|
tags:
|
||||||
|
- install
|
||||||
|
---
|
||||||
|
|
||||||
|
# Installing TVApp2
|
||||||
|
|
||||||
|
To install TVApp2 using docker; you will need to use either the `🗔 docker run` command, or create a `📄 docker-compose.yml` file which contains information about how to pull the latest image and spin the container up. We have provided instructions for both.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
{==
|
||||||
|
|
||||||
|
Select your desired option to bring up the TVApp2 container with:
|
||||||
|
|
||||||
|
==}
|
||||||
|
|
||||||
|
<div class="grid cards" markdown>
|
||||||
|
|
||||||
|
- :material-circle: [docker run](docker-run.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Spin up the TVApp2 container using the `docker run` command.
|
||||||
|
This is useful for quick launches, but is not time efficient
|
||||||
|
if you plan to use this container long-term.
|
||||||
|
|
||||||
|
This requires a longer command that must be used each time
|
||||||
|
you wish to bring the container up.
|
||||||
|
|
||||||
|
- :material-circle: [docker compose](docker-compose.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Spin up the TVApp2 container by creating a `📄 docker-compose.yml`
|
||||||
|
file which will store all of your options such as env variables,
|
||||||
|
mounted volumes, and labels.
|
||||||
|
|
||||||
|
To bring the container up, `cd` into the folder with the
|
||||||
|
`📄 docker-compose.yml` file, and run the
|
||||||
|
command `docker compose up -d`.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
6
docs/docs/javascripts/tablesort.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
document$.subscribe(function() {
|
||||||
|
var tables = document.querySelectorAll("article table:not([class])")
|
||||||
|
tables.forEach(function(table) {
|
||||||
|
new Tablesort(table)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -5,6 +5,16 @@
|
|||||||
[ data-md-color-scheme="default" ]
|
[ data-md-color-scheme="default" ]
|
||||||
{
|
{
|
||||||
|
|
||||||
|
--md-accent-fg-color--transparent: #1b1b1b2f;
|
||||||
|
--md-typeset-a-color: #568afa;
|
||||||
|
--md-badge-icon-color: #2b2b2b;
|
||||||
|
--md-badge-icon-hover-color: #568afa;
|
||||||
|
--md-badge-bg-color--transparent: #1b1b1b2f;
|
||||||
|
--md-badge-bg-hover-color: #1b1b1b2f;
|
||||||
|
--md-table-head-bg-color: #597dd2;
|
||||||
|
--md-table-body-bg-color: rgb(221, 221, 221);
|
||||||
|
--md-table-body-text-color: rgb(20, 20, 20);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Tag > Background Color
|
Tag > Background Color
|
||||||
*/
|
*/
|
||||||
@@ -24,15 +34,6 @@
|
|||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Badge > Left Box (Icon
|
|
||||||
*/
|
|
||||||
|
|
||||||
.md-typeset .mdx-badge__icon
|
|
||||||
{
|
|
||||||
background-color: var(--md-accent-fg-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Badges > Right Box
|
Badges > Right Box
|
||||||
*/
|
*/
|
||||||
@@ -52,15 +53,6 @@
|
|||||||
color: #FFF;
|
color: #FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Badge > Icon Color
|
|
||||||
*/
|
|
||||||
|
|
||||||
.md-typeset .mdx-badge svg
|
|
||||||
{
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Make <small>text</small> opaque. used for changelog to show date
|
Make <small>text</small> opaque. used for changelog to show date
|
||||||
*/
|
*/
|
||||||
@@ -84,16 +76,10 @@
|
|||||||
margin-inline-end: 5px;
|
margin-inline-end: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 .mdx-badge svg
|
|
||||||
{
|
|
||||||
padding-left: 2px;
|
|
||||||
padding-top: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.color-box {
|
.color-box {
|
||||||
float: left;
|
float: left;
|
||||||
height: 24px;
|
height: 21px;
|
||||||
width: 24px;
|
width: 21px;
|
||||||
border: 1px solid rgba( 255, 255, 255, 0.2 );
|
border: 1px solid rgba( 255, 255, 255, 0.2 );
|
||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
@@ -111,11 +97,6 @@
|
|||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.md-typeset table:not([class]) tbody tr
|
|
||||||
{
|
|
||||||
background-color: rgb(255, 255, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Table > Outter Border / Background
|
Table > Outter Border / Background
|
||||||
*/
|
*/
|
||||||
@@ -125,6 +106,17 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.md-typeset table:not([class]) td
|
||||||
|
{
|
||||||
|
border-top: 2px solid var(--md-typeset-table-color);
|
||||||
|
padding: .9375em 1.25em;
|
||||||
|
padding-top: 0.9375em;
|
||||||
|
padding-bottom: 0.9375em;
|
||||||
|
padding-left: 1.25em;
|
||||||
|
vertical-align: top;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Table > Outter Border / Background
|
Table > Outter Border / Background
|
||||||
*/
|
*/
|
||||||
@@ -156,15 +148,6 @@
|
|||||||
{
|
{
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
/*background-color: var(--md-code-bg-color);*/
|
/*background-color: var(--md-code-bg-color);*/
|
||||||
min-width: 25%;
|
|
||||||
border-right: 1px solid rgba( 255, 255, 255, 0.14);
|
|
||||||
background-color: rgba(194, 194, 194, 0.28);
|
|
||||||
}
|
|
||||||
|
|
||||||
.md-typeset__table thead
|
|
||||||
{
|
|
||||||
background-color: var(--md-accent-fg-color);
|
|
||||||
color: #FFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -196,6 +179,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[dir="ltr"] .md-typeset table th[role="columnheader"]::after
|
||||||
|
{
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Theme > Main
|
Theme > Main
|
||||||
*/
|
*/
|
||||||
@@ -208,6 +196,13 @@
|
|||||||
--md-tooltip-width: 400px;
|
--md-tooltip-width: 400px;
|
||||||
--glow-color: hsl(186 100% 69%);
|
--glow-color: hsl(186 100% 69%);
|
||||||
|
|
||||||
|
--md-loglevel-error-color: #f06090;
|
||||||
|
--md-loglevel-warn-color: #e6695b;
|
||||||
|
--md-loglevel-notice-color: #e2d55e;
|
||||||
|
--md-loglevel-info-color: #6791e0;
|
||||||
|
--md-loglevel-debug-color: #c973d9;
|
||||||
|
--md-loglevel-trace-color: hsla(225deg,15%,90%,0.56);
|
||||||
|
|
||||||
--md-default-fg-color: hsla(var(--md-hue),15%,90%,0.82);
|
--md-default-fg-color: hsla(var(--md-hue),15%,90%,0.82);
|
||||||
--md-default-fg-color--light: hsla(var(--md-hue),15%,90%,0.56);
|
--md-default-fg-color--light: hsla(var(--md-hue),15%,90%,0.56);
|
||||||
--md-default-fg-color--lighter: hsla(var(--md-hue),15%,90%,0.32);
|
--md-default-fg-color--lighter: hsla(var(--md-hue),15%,90%,0.32);
|
||||||
@@ -233,29 +228,42 @@
|
|||||||
--md-code-hl-generic-color: var(--md-default-fg-color--light);
|
--md-code-hl-generic-color: var(--md-default-fg-color--light);
|
||||||
--md-code-hl-variable-color: var(--md-default-fg-color--light);
|
--md-code-hl-variable-color: var(--md-default-fg-color--light);
|
||||||
--md-typeset-color: var(--md-default-fg-color);
|
--md-typeset-color: var(--md-default-fg-color);
|
||||||
--md-typeset-a-color: #568afa;
|
--md-typeset-a-color: #f91d5b;
|
||||||
|
--md-badge-icon-color: #d0d0d0;
|
||||||
|
--md-badge-icon-hover-color: #568afa;
|
||||||
|
--md-badge-bg-color--transparent: #ffffff1c;
|
||||||
|
--md-badge-bg-hover-color: #FFFFFF2E;
|
||||||
--md-typeset-kbd-color: hsla(var(--md-hue),15%,90%,0.12);
|
--md-typeset-kbd-color: hsla(var(--md-hue),15%,90%,0.12);
|
||||||
--md-typeset-kbd-accent-color: hsla(var(--md-hue),15%,90%,0.2);
|
--md-typeset-kbd-accent-color: hsla(var(--md-hue),15%,90%,0.2);
|
||||||
--md-typeset-kbd-border-color: hsla(var(--md-hue),15%,14%,1);
|
--md-typeset-kbd-border-color: hsla(var(--md-hue),15%,14%,1);
|
||||||
--md-typeset-mark-color: #4287ff4d;
|
--md-typeset-mark-color: #4287ff4d;
|
||||||
--md-typeset-table-color: hsla(var(--md-hue),15%,95%,0.12);
|
--md-typeset-table-color: hsla(0%, 0%, 40%, 0.12);
|
||||||
--md-typeset-table-color--light: hsla(var(--md-hue),15%,95%,0.035);
|
--md-typeset-table-color--light: hsla(var(--md-hue),15%,95%,0.035);
|
||||||
--md-admonition-fg-color: var(--md-default-fg-color);
|
--md-admonition-fg-color: var(--md-default-fg-color);
|
||||||
--md-admonition-bg-color: var(--md-default-bg-color);
|
--md-admonition-bg-color: var(--md-default-bg-color);
|
||||||
--md-footer-bg-color: rgba( 34, 34, 34, 1 );
|
--md-footer-bg-color: rgba( 17, 17, 17, 1 );
|
||||||
--md-footer-bg-color--dark: rgba( 15, 15, 15, 1 );
|
--md-footer-bg-color--dark: rgba( 13, 13, 13, 1 );
|
||||||
--md-shadow-z1: 0 0.2rem 0.5rem #0000000d,0 0 0.05rem #0000001a;
|
--md-shadow-z1: 0 0.2rem 0.5rem #0000000d,0 0 0.05rem #0000001a;
|
||||||
--md-shadow-z2: 0 0.2rem 0.5rem #00000040,0 0 0.05rem #00000040;
|
--md-shadow-z2: 0 0.2rem 0.5rem #00000040,0 0 0.05rem #00000040;
|
||||||
--md-shadow-z3: 0 0.2rem 0.5rem #0006,0 0 0.05rem #00000059;
|
--md-shadow-z3: 0 0.2rem 0.5rem #0006,0 0 0.05rem #00000059;
|
||||||
|
--md-table-head-bg-color: #860038;
|
||||||
|
--md-table-body-text-color: rgb(231, 231, 231);
|
||||||
|
--md-accent-fg-color--transparent: #FFFFFF2E;
|
||||||
--md-admonition-icon--pied-piper: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M244 246c-3.2-2-6.3-2.9-10.1-2.9-6.6 0-12.6 3.2-19.3 3.7l1.7 4.9zm135.9 197.9c-19 0-64.1 9.5-79.9 19.8l6.9 45.1c35.7 6.1 70.1 3.6 106-9.8-4.8-10-23.5-55.1-33-55.1zM340.8 177c6.6 2.8 11.5 9.2 22.7 22.1 2-1.4 7.5-5.2 7.5-8.6 0-4.9-11.8-13.2-13.2-23 11.2-5.7 25.2-6 37.6-8.9 68.1-16.4 116.3-52.9 146.8-116.7C548.3 29.3 554 16.1 554.6 2l-2 2.6c-28.4 50-33 63.2-81.3 100-31.9 24.4-69.2 40.2-106.6 54.6l-6.3-.3v-21.8c-19.6 1.6-19.7-14.6-31.6-23-18.7 20.6-31.6 40.8-58.9 51.1-12.7 4.8-19.6 10-25.9 21.8 34.9-16.4 91.2-13.5 98.8-10zM555.5 0l-.6 1.1-.3.9.6-.6zm-59.2 382.1c-33.9-56.9-75.3-118.4-150-115.5l-.3-6c-1.1-13.5 32.8 3.2 35.1-31l-14.4 7.2c-19.8-45.7-8.6-54.3-65.5-54.3-14.7 0-26.7 1.7-41.4 4.6 2.9 18.6 2.2 36.7-10.9 50.3l19.5 5.5c-1.7 3.2-2.9 6.3-2.9 9.8 0 21 42.8 2.9 42.8 33.6 0 18.4-36.8 60.1-54.9 60.1-8 0-53.7-50-53.4-60.1l.3-4.6 52.3-11.5c13-2.6 12.3-22.7-2.9-22.7-3.7 0-43.1 9.2-49.4 10.6-2-5.2-7.5-14.1-13.8-14.1-3.2 0-6.3 3.2-9.5 4-9.2 2.6-31 2.9-21.5 20.1L15.9 298.5c-5.5 1.1-8.9 6.3-8.9 11.8 0 6 5.5 10.9 11.5 10.9 8 0 131.3-28.4 147.4-32.2 2.6 3.2 4.6 6.3 7.8 8.6 20.1 14.4 59.8 85.9 76.4 85.9 24.1 0 58-22.4 71.3-41.9 3.2-4.3 6.9-7.5 12.4-6.9.6 13.8-31.6 34.2-33 43.7-1.4 10.2-1 35.2-.3 41.1 26.7 8.1 52-3.6 77.9-2.9 4.3-21 10.6-41.9 9.8-63.5l-.3-9.5c-1.4-34.2-10.9-38.5-34.8-58.6-1.1-1.1-2.6-2.6-3.7-4 2.2-1.4 1.1-1 4.6-1.7 88.5 0 56.3 183.6 111.5 229.9 33.1-15 72.5-27.9 103.5-47.2-29-25.6-52.6-45.7-72.7-79.9zm-196.2 46.1v27.2l11.8-3.4-2.9-23.8zm-68.7-150.4l24.1 61.2 21-13.8-31.3-50.9zm84.4 154.9l2 12.4c9-1.5 58.4-6.6 58.4-14.1 0-1.4-.6-3.2-.9-4.6-26.8 0-36.9 3.8-59.5 6.3z"/></svg>');
|
--md-admonition-icon--pied-piper: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M244 246c-3.2-2-6.3-2.9-10.1-2.9-6.6 0-12.6 3.2-19.3 3.7l1.7 4.9zm135.9 197.9c-19 0-64.1 9.5-79.9 19.8l6.9 45.1c35.7 6.1 70.1 3.6 106-9.8-4.8-10-23.5-55.1-33-55.1zM340.8 177c6.6 2.8 11.5 9.2 22.7 22.1 2-1.4 7.5-5.2 7.5-8.6 0-4.9-11.8-13.2-13.2-23 11.2-5.7 25.2-6 37.6-8.9 68.1-16.4 116.3-52.9 146.8-116.7C548.3 29.3 554 16.1 554.6 2l-2 2.6c-28.4 50-33 63.2-81.3 100-31.9 24.4-69.2 40.2-106.6 54.6l-6.3-.3v-21.8c-19.6 1.6-19.7-14.6-31.6-23-18.7 20.6-31.6 40.8-58.9 51.1-12.7 4.8-19.6 10-25.9 21.8 34.9-16.4 91.2-13.5 98.8-10zM555.5 0l-.6 1.1-.3.9.6-.6zm-59.2 382.1c-33.9-56.9-75.3-118.4-150-115.5l-.3-6c-1.1-13.5 32.8 3.2 35.1-31l-14.4 7.2c-19.8-45.7-8.6-54.3-65.5-54.3-14.7 0-26.7 1.7-41.4 4.6 2.9 18.6 2.2 36.7-10.9 50.3l19.5 5.5c-1.7 3.2-2.9 6.3-2.9 9.8 0 21 42.8 2.9 42.8 33.6 0 18.4-36.8 60.1-54.9 60.1-8 0-53.7-50-53.4-60.1l.3-4.6 52.3-11.5c13-2.6 12.3-22.7-2.9-22.7-3.7 0-43.1 9.2-49.4 10.6-2-5.2-7.5-14.1-13.8-14.1-3.2 0-6.3 3.2-9.5 4-9.2 2.6-31 2.9-21.5 20.1L15.9 298.5c-5.5 1.1-8.9 6.3-8.9 11.8 0 6 5.5 10.9 11.5 10.9 8 0 131.3-28.4 147.4-32.2 2.6 3.2 4.6 6.3 7.8 8.6 20.1 14.4 59.8 85.9 76.4 85.9 24.1 0 58-22.4 71.3-41.9 3.2-4.3 6.9-7.5 12.4-6.9.6 13.8-31.6 34.2-33 43.7-1.4 10.2-1 35.2-.3 41.1 26.7 8.1 52-3.6 77.9-2.9 4.3-21 10.6-41.9 9.8-63.5l-.3-9.5c-1.4-34.2-10.9-38.5-34.8-58.6-1.1-1.1-2.6-2.6-3.7-4 2.2-1.4 1.1-1 4.6-1.7 88.5 0 56.3 183.6 111.5 229.9 33.1-15 72.5-27.9 103.5-47.2-29-25.6-52.6-45.7-72.7-79.9zm-196.2 46.1v27.2l11.8-3.4-2.9-23.8zm-68.7-150.4l24.1 61.2 21-13.8-31.3-50.9zm84.4 154.9l2 12.4c9-1.5 58.4-6.6 58.4-14.1 0-1.4-.6-3.2-.9-4.6-26.8 0-36.9 3.8-59.5 6.3z"/></svg>');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Tag > Background Color
|
Navigation > Tabs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.md-typeset .md-tag
|
.md-tabs
|
||||||
{
|
{
|
||||||
background-color: var(--md-primary-fg-color);
|
background-color: #860038;
|
||||||
|
color: var(--md-primary-bg-color);
|
||||||
|
display: block;
|
||||||
|
line-height: 1.3;
|
||||||
|
overflow: auto;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -264,8 +272,8 @@
|
|||||||
|
|
||||||
.md-nav
|
.md-nav
|
||||||
{
|
{
|
||||||
font-size: .6rem;
|
font-size: .7rem;
|
||||||
line-height: 1.3;
|
line-height: 1.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mdx-container
|
.mdx-container
|
||||||
@@ -276,12 +284,18 @@
|
|||||||
|
|
||||||
.md-main
|
.md-main
|
||||||
{
|
{
|
||||||
background-color: hsla(140, 0%, 5%, 1) !important;
|
background-color: #161618 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-main__inner
|
||||||
|
{
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.md-typeset table:not([ class ] ) tbody tr
|
.md-typeset table:not([ class ] ) tbody tr
|
||||||
{
|
{
|
||||||
background-color: rgb( 17, 15, 15 );
|
background-color: rgb( 15, 15, 15 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -315,14 +329,6 @@
|
|||||||
{
|
{
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
/*background-color: var(--md-code-bg-color);*/
|
/*background-color: var(--md-code-bg-color);*/
|
||||||
min-width: 25%;
|
|
||||||
border-right: 1px solid rgba( 255, 255, 255, 0.14);
|
|
||||||
background-color: rgba(70, 65, 77, 0.36);
|
|
||||||
}
|
|
||||||
|
|
||||||
.md-typeset__table thead
|
|
||||||
{
|
|
||||||
background-color: #b10f52;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -417,16 +423,28 @@
|
|||||||
|
|
||||||
.md-typeset .tabbed-labels
|
.md-typeset .tabbed-labels
|
||||||
{
|
{
|
||||||
background-color: #090909;
|
background-color: #0b0b0b;
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
border-left: 1px solid #242735;
|
||||||
|
border-top: 1px solid #242735;
|
||||||
|
border-right: 1px solid #242735;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
.tabbed-labels::before
|
||||||
Badge > Left Box (Icon
|
|
||||||
*/
|
|
||||||
|
|
||||||
.md-typeset .mdx-badge__icon
|
|
||||||
{
|
{
|
||||||
background-color: #3f4faa;
|
background: hsla(343.1, 87.9%, 51.6%, 0.82);
|
||||||
|
bottom: 0;
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
height: 2px;
|
||||||
|
left: 0;
|
||||||
|
position: absolute;
|
||||||
|
transform: translateX(var(--md-indicator-x));
|
||||||
|
transition: width 225ms,background-color .25s,transform .25s;
|
||||||
|
transition-timing-function: ease, ease, ease;
|
||||||
|
transition-timing-function: cubic-bezier(.4,0,.2,1);
|
||||||
|
width: var(--md-indicator-width);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -453,8 +471,7 @@
|
|||||||
|
|
||||||
h3 .mdx-badge svg
|
h3 .mdx-badge svg
|
||||||
{
|
{
|
||||||
padding-left: 2px;
|
padding-left: 0px;
|
||||||
padding-top: 1px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -476,15 +493,6 @@
|
|||||||
color: #FFF;
|
color: #FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Badge > Icon Color
|
|
||||||
*/
|
|
||||||
|
|
||||||
.md-typeset .mdx-badge svg
|
|
||||||
{
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -509,6 +517,14 @@ h4:has(.twemoji) .twemoji
|
|||||||
margin-left: -7px;
|
margin-left: -7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.md-typeset .emojione, .md-typeset .gemoji, .md-typeset .twemoji
|
||||||
|
{
|
||||||
|
--md-icon-size: 1.125em;
|
||||||
|
display: inline-flex;
|
||||||
|
height: var(--md-icon-size);
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Badge > Header Padding
|
Badge > Header Padding
|
||||||
if a badge is used in a header, add padding between the badge and text
|
if a badge is used in a header, add padding between the badge and text
|
||||||
@@ -523,12 +539,18 @@ h4:has(.twemoji) .twemoji
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
.md-nav--primary .md-nav__title
|
||||||
|
{
|
||||||
|
background: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Navigation > Spacer
|
Navigation > Spacer
|
||||||
Add a gap between the last "File" item in nav menu, and the folders under.
|
Add a gap between the last "File" item in nav menu, and the folders under.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
li:has(a[href*="about_patcher"])
|
.md-sidebar--primary li:has(a[href*="about_tvapp2"])
|
||||||
{
|
{
|
||||||
margin-bottom: 28px !important;
|
margin-bottom: 28px !important;
|
||||||
}
|
}
|
||||||
@@ -563,6 +585,53 @@ li:has(a[href*="about_patcher"])
|
|||||||
transition: none !important;
|
transition: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.md-typeset .mdx-badge--dangerous
|
||||||
|
{
|
||||||
|
--md-badge-icon-color: #fff;
|
||||||
|
--md-badge-icon-hover-color: #ff1058;
|
||||||
|
--md-badge-bg-color--transparent: #7B1532 !important;
|
||||||
|
color: #f9f9f9;
|
||||||
|
--md-typeset-bg-color: #111;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes health
|
||||||
|
{
|
||||||
|
0%, 40%, 80%, 100% {
|
||||||
|
transform: scale(1);
|
||||||
|
color: #FFF;
|
||||||
|
fill: #FFF !important;
|
||||||
|
}
|
||||||
|
20%, 60% {
|
||||||
|
transform: scale(1.15);
|
||||||
|
color: #FF6593;
|
||||||
|
fill: #FF6593 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.heart
|
||||||
|
{
|
||||||
|
animation: health 1000ms infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset .mdx-badge--heart {
|
||||||
|
--md-badge-icon-color: #e92063;
|
||||||
|
--md-badge-icon-hover-color: #FFFFFF;
|
||||||
|
--md-accent-fg-color: #ff4281;
|
||||||
|
--md-accent-fg-color--transparent: #e920631a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset .mdx-badge--heart .twemoji {
|
||||||
|
animation: heart 1s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset .mdx-badge--command
|
||||||
|
{
|
||||||
|
--md-typeset-a-color: #ff2d72;
|
||||||
|
--md-accent-fg-color: #fff;
|
||||||
|
--md-accent-fg-color--transparent: #ffffff1a;
|
||||||
|
color: #e91e63;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Badge > Header Positioning
|
Badge > Header Positioning
|
||||||
This is mainly for the conventions page
|
This is mainly for the conventions page
|
||||||
@@ -584,7 +653,6 @@ h2:has(.mdx-badge) > .mdx-badge svg
|
|||||||
|
|
||||||
:is(h1, h2, h3, h4, h5, h6) .mdx-badge__icon svg
|
:is(h1, h2, h3, h4, h5, h6) .mdx-badge__icon svg
|
||||||
{
|
{
|
||||||
padding-top: 3px !important;
|
|
||||||
padding-right: 1px;
|
padding-right: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,6 +666,22 @@ h2:has(.mdx-badge) > .mdx-badge svg
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Table > Header
|
||||||
|
*/
|
||||||
|
|
||||||
|
.md-typeset__table table thead, .md-typeset__table > table
|
||||||
|
{
|
||||||
|
background-color: var(--md-table-head-bg-color);
|
||||||
|
color: #FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table:not([class]) tbody tr
|
||||||
|
{
|
||||||
|
background-color: var(--md-table-body-bg-color);
|
||||||
|
color: var(--md-table-body-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
.mdx-badge__text a
|
.mdx-badge__text a
|
||||||
{
|
{
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
@@ -614,20 +698,40 @@ small
|
|||||||
font-size: 60%;
|
font-size: 60%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Navigation > Category Gap
|
||||||
|
|
||||||
|
if you have multiple sub-folders for a group of pages, add a gap between categories on left-side navigation
|
||||||
|
*/
|
||||||
|
|
||||||
|
.md-nav__item--section
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
margin: 2.00em 0;
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Menu Navigation > FontAwesome Folder Icons (for folders)
|
Menu Navigation > FontAwesome Folder Icons (for folders)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
label.md-nav__link
|
||||||
|
{
|
||||||
|
color: #ffffff59 !important;
|
||||||
|
}
|
||||||
|
|
||||||
label.md-nav__link::before
|
label.md-nav__link::before
|
||||||
{
|
{
|
||||||
content: ".";
|
opacity: 0.6;
|
||||||
|
content: "";
|
||||||
background-color: currentColor;
|
background-color: currentColor;
|
||||||
padding-right: 0.6rem;
|
padding-right: 0.6rem;
|
||||||
margin-right: 0.1rem;
|
margin-right: 0.1rem;
|
||||||
mask-repeat: no-repeat;
|
mask-repeat: no-repeat;
|
||||||
mask-size: contain;
|
mask-size: 20px;
|
||||||
|
padding-inline: 4px;
|
||||||
|
mask-position: center;
|
||||||
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512' fill='currentColor' width='16px' height='16px'%3E%3C!-- --%3E%3Cdefs%3E%3Cstyle%3E.fa-secondary%7Bopacity:.4%7D%3C/style%3E%3C/defs%3E%3Cpath class='fa-primary' d='M160 384H512c35.3 0 64-28.7 64-64V160c0-35.3-28.7-64-64-64H394.5c-17 0-33.3-6.7-45.3-18.7L322.7 50.7c-12-12-28.3-18.7-45.3-18.7H160c-35.3 0-64 28.7-64 64V320c0 35.3 28.7 64 64 64z'%3E%3C/path%3E%3Cpath class='fa-secondary' d='M24 96c13.3 0 24 10.7 24 24V344c0 48.6 39.4 88 88 88H456c13.3 0 24 10.7 24 24s-10.7 24-24 24H136C60.9 480 0 419.1 0 344V120c0-13.3 10.7-24 24-24z'%3E%3C/path%3E%3C/svg%3E");
|
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512' fill='currentColor' width='16px' height='16px'%3E%3C!-- --%3E%3Cdefs%3E%3Cstyle%3E.fa-secondary%7Bopacity:.4%7D%3C/style%3E%3C/defs%3E%3Cpath class='fa-primary' d='M160 384H512c35.3 0 64-28.7 64-64V160c0-35.3-28.7-64-64-64H394.5c-17 0-33.3-6.7-45.3-18.7L322.7 50.7c-12-12-28.3-18.7-45.3-18.7H160c-35.3 0-64 28.7-64 64V320c0 35.3 28.7 64 64 64z'%3E%3C/path%3E%3Cpath class='fa-secondary' d='M24 96c13.3 0 24 10.7 24 24V344c0 48.6 39.4 88 88 88H456c13.3 0 24 10.7 24 24s-10.7 24-24 24H136C60.9 480 0 419.1 0 344V120c0-13.3 10.7-24 24-24z'%3E%3C/path%3E%3C/svg%3E");
|
||||||
opacity: 0.6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
li.md-nav__item--nested > a > span::before
|
li.md-nav__item--nested > a > span::before
|
||||||
@@ -652,10 +756,56 @@ nav.md-nav > ul.md-nav__list > li.md-nav__item > a.md-nav__link > span::before
|
|||||||
padding-right: 0.6rem;
|
padding-right: 0.6rem;
|
||||||
margin-right: 0.1rem;
|
margin-right: 0.1rem;
|
||||||
mask-repeat: no-repeat;
|
mask-repeat: no-repeat;
|
||||||
mask-size: contain;
|
mask-size: 9px;
|
||||||
|
padding-inline: 4px;
|
||||||
|
mask-position: center;
|
||||||
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512' fill='currentColor' width='16px' height='16px'%3E%3C!-- --%3E%3Cdefs%3E%3Cstyle%3E.fa-secondary%7Bopacity:.4%7D%3C/style%3E%3C/defs%3E%3Cpath class='fa-primary' d=''%3E%3C/path%3E%3Cpath class='fa-secondary' d='M0 256a160 160 0 1 1 320 0A160 160 0 1 1 0 256z'%3E%3C/path%3E%3C/svg%3E");
|
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512' fill='currentColor' width='16px' height='16px'%3E%3C!-- --%3E%3Cdefs%3E%3Cstyle%3E.fa-secondary%7Bopacity:.4%7D%3C/style%3E%3C/defs%3E%3Cpath class='fa-primary' d=''%3E%3C/path%3E%3Cpath class='fa-secondary' d='M0 256a160 160 0 1 1 320 0A160 160 0 1 1 0 256z'%3E%3C/path%3E%3C/svg%3E");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Menu Navigation > Secondary > Text Size
|
||||||
|
*/
|
||||||
|
|
||||||
|
nav.md-nav--secondary li
|
||||||
|
{
|
||||||
|
font-size: 0.6rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Badge > Override Icon Color
|
||||||
|
*/
|
||||||
|
|
||||||
|
.mdx-badge a
|
||||||
|
{
|
||||||
|
color: var(--md-badge-icon-color);
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mdx-badge a:hover
|
||||||
|
{
|
||||||
|
color: var(--md-badge-icon-hover-color);
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mdx-badge .mdx-badge__icon
|
||||||
|
{
|
||||||
|
background-color: var(--md-badge-bg-color--transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mdx-badge .mdx-badge__icon:hover
|
||||||
|
{
|
||||||
|
background-color: var(--md-badge-bg-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Tag > Background Color
|
||||||
|
*/
|
||||||
|
|
||||||
|
.md-typeset .md-tag
|
||||||
|
{
|
||||||
|
background-color: var(--md-primary-fg-color);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Lightbox border
|
Lightbox border
|
||||||
*/
|
*/
|
||||||
@@ -727,6 +877,12 @@ figure img
|
|||||||
transition: border .25s,box-shadow .25s;
|
transition: border .25s,box-shadow .25s;
|
||||||
border: 2px solid rgba( 255, 255, 255, 0.1 );
|
border: 2px solid rgba( 255, 255, 255, 0.1 );
|
||||||
background-color: var(--md-default-fg-color--lightest);
|
background-color: var(--md-default-fg-color--lightest);
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin: 0 auto;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
margin-top: 5px;
|
||||||
|
width: clamp(200px, 100%, 75%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mkde-embed-container:hover
|
.mkde-embed-container:hover
|
||||||
@@ -815,14 +971,14 @@ figure img
|
|||||||
|
|
||||||
.mkde-right
|
.mkde-right
|
||||||
{
|
{
|
||||||
padding: 8px 10px;
|
padding: 0px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media ( min-width: 360px )
|
@media ( min-width: 360px )
|
||||||
{
|
{
|
||||||
.mkde-right
|
.mkde-right
|
||||||
{
|
{
|
||||||
padding: 12px 15px;
|
padding: 0px 15px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -830,7 +986,7 @@ figure img
|
|||||||
{
|
{
|
||||||
.mkde-right
|
.mkde-right
|
||||||
{
|
{
|
||||||
padding: 12px 12px;
|
padding: 0px 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -840,10 +996,12 @@ figure img
|
|||||||
|
|
||||||
._lc._sm:not( .xd ) .mkde-left
|
._lc._sm:not( .xd ) .mkde-left
|
||||||
{
|
{
|
||||||
min-width: 100px;
|
min-width: 70px;
|
||||||
width: 100px;
|
width: 70px;
|
||||||
min-height: 100px;
|
min-height: 70px;
|
||||||
padding: 10px;
|
height: 70px;
|
||||||
|
padding: 5px;
|
||||||
|
align-self: center;
|
||||||
background: rgba( 255, 255, 255, 0.10 );
|
background: rgba( 255, 255, 255, 0.10 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -851,9 +1009,11 @@ figure img
|
|||||||
{
|
{
|
||||||
._lc._sm:not( .xd ) .mkde-left
|
._lc._sm:not( .xd ) .mkde-left
|
||||||
{
|
{
|
||||||
min-width: 110px;
|
min-width: 80px;
|
||||||
width: 110px;
|
width: 80px;
|
||||||
min-height: 110px;
|
min-height: 80px;
|
||||||
|
height: 80px;
|
||||||
|
align-self: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -861,9 +1021,11 @@ figure img
|
|||||||
{
|
{
|
||||||
._lc._sm:not( .xd ) .mkde-left
|
._lc._sm:not( .xd ) .mkde-left
|
||||||
{
|
{
|
||||||
min-width: 140px;
|
min-width: 110px;
|
||||||
width: 140px;
|
width: 110px;
|
||||||
min-height: 140px;
|
min-height: 110px;
|
||||||
|
height: 110px;
|
||||||
|
align-self: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -871,9 +1033,11 @@ figure img
|
|||||||
{
|
{
|
||||||
._lc._sm:not( .xd ) .mkde-left
|
._lc._sm:not( .xd ) .mkde-left
|
||||||
{
|
{
|
||||||
min-width: 160px;
|
min-width: 110px;
|
||||||
width: 160px;
|
width: 110px;
|
||||||
min-height: 160px;
|
min-height: 110px;
|
||||||
|
height: 110px;
|
||||||
|
align-self: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1049,24 +1213,24 @@ figure img
|
|||||||
._fs-x,
|
._fs-x,
|
||||||
._fs-m
|
._fs-m
|
||||||
{
|
{
|
||||||
font-size: 12px;
|
font-size: clamp(7px, 2.0vw, 12px);
|
||||||
}
|
}
|
||||||
|
|
||||||
._f1p
|
._f1p
|
||||||
{
|
{
|
||||||
font-size: 13px;
|
font-size: clamp(10px, 2.5vw, 13px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media ( min-width: 360px )
|
@media ( min-width: 360px )
|
||||||
{
|
{
|
||||||
._fs-x
|
._fs-x
|
||||||
{
|
{
|
||||||
font-size: 13px;
|
font-size: clamp(10px, 2.5vw, 13px);
|
||||||
}
|
}
|
||||||
|
|
||||||
._f1p
|
._f1p
|
||||||
{
|
{
|
||||||
font-size: 14px;
|
font-size: clamp(10px, 2.5vw, 14px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1074,17 +1238,17 @@ figure img
|
|||||||
{
|
{
|
||||||
._fs-m
|
._fs-m
|
||||||
{
|
{
|
||||||
font-size: 13px;
|
font-size: clamp(10px, 2.5vw, 13px);
|
||||||
}
|
}
|
||||||
|
|
||||||
._fs-x
|
._fs-x
|
||||||
{
|
{
|
||||||
font-size: 14px;
|
font-size: clamp(10px, 2.5vw, 14px);
|
||||||
}
|
}
|
||||||
|
|
||||||
._f1p
|
._f1p
|
||||||
{
|
{
|
||||||
font-size: 15px;
|
font-size: clamp(10px, 2.5vw, 15px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1092,17 +1256,17 @@ figure img
|
|||||||
{
|
{
|
||||||
._fs-m
|
._fs-m
|
||||||
{
|
{
|
||||||
font-size: 14px;
|
font-size: clamp(10px, 2.5vw, 13px);
|
||||||
}
|
}
|
||||||
|
|
||||||
._fs-x
|
._fs-x
|
||||||
{
|
{
|
||||||
font-size: 15px;
|
font-size: clamp(10px, 2.5vw, 14px);
|
||||||
}
|
}
|
||||||
|
|
||||||
._f1p
|
._f1p
|
||||||
{
|
{
|
||||||
font-size: 17px;
|
font-size: clamp(10px, 2.5vw, 15px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1216,13 +1380,12 @@ figure img
|
|||||||
.item-link
|
.item-link
|
||||||
{
|
{
|
||||||
color: var( --md-typeset-a-color );
|
color: var( --md-typeset-a-color );
|
||||||
font-size: 12px;
|
font-size: clamp(8px, 2.5vw, 12px);
|
||||||
padding-bottom: 6px;
|
padding-bottom: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-footer
|
.item-footer
|
||||||
{
|
{
|
||||||
padding-block-start: 12px;
|
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1255,14 +1418,14 @@ figure img
|
|||||||
{
|
{
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
margin-block-end: -5px;
|
margin-block-end: -7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-box
|
.color-box
|
||||||
{
|
{
|
||||||
float: left;
|
float: left;
|
||||||
height: 20px;
|
height: 21px;
|
||||||
width: 20px;
|
width: 21px;
|
||||||
border: 1px solid rgba( 255, 255, 255, 0.2 );
|
border: 1px solid rgba( 255, 255, 255, 0.2 );
|
||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
@@ -1276,3 +1439,187 @@ figure img
|
|||||||
clear: both;
|
clear: both;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Tools > Icon Search
|
||||||
|
*/
|
||||||
|
|
||||||
|
.md-typeset .mdx-iconsearch {
|
||||||
|
background-color:var(--md-default-bg-color);
|
||||||
|
border-radius:.1rem;
|
||||||
|
box-shadow:var(--md-shadow-z1);
|
||||||
|
position:relative;
|
||||||
|
transition:box-shadow 125ms
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-iconsearch:focus-within,
|
||||||
|
.md-typeset .mdx-iconsearch:hover {
|
||||||
|
box-shadow:var(--md-shadow-z2)
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-iconsearch .md-input {
|
||||||
|
background:var(--md-default-bg-color);
|
||||||
|
box-shadow:none
|
||||||
|
}
|
||||||
|
[data-md-color-scheme=slate] .md-typeset .mdx-iconsearch .md-input {
|
||||||
|
background:var(--md-code-bg-color)
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-iconsearch-result {
|
||||||
|
-webkit-backface-visibility:hidden;
|
||||||
|
backface-visibility:hidden;
|
||||||
|
max-height:50vh;
|
||||||
|
overflow-y:auto;
|
||||||
|
scrollbar-color:var(--md-default-fg-color--lighter) #0000;
|
||||||
|
scrollbar-width:thin;
|
||||||
|
touch-action:pan-y
|
||||||
|
}
|
||||||
|
.md-tooltip .md-typeset .mdx-iconsearch-result {
|
||||||
|
max-height:10.25rem
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-iconsearch-result::-webkit-scrollbar {
|
||||||
|
height:.2rem;
|
||||||
|
width:.2rem
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-iconsearch-result::-webkit-scrollbar-thumb {
|
||||||
|
background-color:var(--md-default-fg-color--lighter)
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-iconsearch-result::-webkit-scrollbar-thumb:hover {
|
||||||
|
background-color:var(--md-accent-fg-color)
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-iconsearch-result__meta {
|
||||||
|
color:var(--md-default-fg-color--lighter);
|
||||||
|
font-size:.64rem;
|
||||||
|
position:absolute;
|
||||||
|
right:.6rem;
|
||||||
|
top:.4rem
|
||||||
|
}
|
||||||
|
@media screen and (max-width:29.984375em) {
|
||||||
|
.md-typeset .mdx-iconsearch-result__meta {
|
||||||
|
display:none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-iconsearch-result__select {
|
||||||
|
background-color:var(--md-default-fg-color--lightest);
|
||||||
|
border:none;
|
||||||
|
border-radius:.1rem;
|
||||||
|
color:var(--md-default-fg-color--light);
|
||||||
|
font-size:.64rem;
|
||||||
|
padding-bottom:.15em;
|
||||||
|
padding-top:.15em;
|
||||||
|
position:absolute;
|
||||||
|
right:.6rem;
|
||||||
|
top:.4rem;
|
||||||
|
transition:color 125ms,background-color 125ms
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-iconsearch-result__select:focus,
|
||||||
|
.md-typeset .mdx-iconsearch-result__select:hover {
|
||||||
|
background-color:var(--md-accent-fg-color);
|
||||||
|
color:var(--md-accent-bg-color);
|
||||||
|
outline:none
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-iconsearch-result__select+.mdx-iconsearch-result__meta {
|
||||||
|
right:4.1rem
|
||||||
|
}
|
||||||
|
[dir=ltr] .md-typeset .mdx-iconsearch-result__list {
|
||||||
|
margin-left:0
|
||||||
|
}
|
||||||
|
[dir=rtl] .md-typeset .mdx-iconsearch-result__list {
|
||||||
|
margin-right:0
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-iconsearch-result__list {
|
||||||
|
list-style:none;
|
||||||
|
margin:0;
|
||||||
|
padding:0
|
||||||
|
}
|
||||||
|
[dir=ltr] .md-typeset .mdx-iconsearch-result__item {
|
||||||
|
margin-left:0
|
||||||
|
}
|
||||||
|
[dir=rtl] .md-typeset .mdx-iconsearch-result__item {
|
||||||
|
margin-right:0
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-iconsearch-result__item {
|
||||||
|
border-bottom:.05rem solid var(--md-default-fg-color--lightest);
|
||||||
|
margin:0;
|
||||||
|
padding:.2rem .6rem
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-iconsearch-result__item:last-child {
|
||||||
|
border-bottom:none
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-iconsearch-result__item>* {
|
||||||
|
margin-right:.6rem
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-iconsearch-result__item img {
|
||||||
|
height:.9rem;
|
||||||
|
width:.9rem
|
||||||
|
}
|
||||||
|
[data-md-color-scheme=slate] .md-typeset .mdx-iconsearch-result__item img[src*=squidfunk] {
|
||||||
|
filter:invert(1)
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-premium p {
|
||||||
|
margin:2em 0;
|
||||||
|
text-align:center
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-premium img {
|
||||||
|
height:3.25rem
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-premium p:last-child {
|
||||||
|
display:flex;
|
||||||
|
flex-wrap:wrap;
|
||||||
|
justify-content:center
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-premium p:last-child>a {
|
||||||
|
display:block;
|
||||||
|
flex-shrink:0
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-sponsorship__list {
|
||||||
|
margin:2em 0
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-sponsorship__list:after {
|
||||||
|
clear:both;
|
||||||
|
content:"";
|
||||||
|
display:block
|
||||||
|
}
|
||||||
|
[dir=ltr] .md-typeset .mdx-sponsorship__item {
|
||||||
|
float:left
|
||||||
|
}
|
||||||
|
[dir=rtl] .md-typeset .mdx-sponsorship__item {
|
||||||
|
float:right
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-sponsorship__item {
|
||||||
|
border-radius:100%;
|
||||||
|
display:block;
|
||||||
|
height:1.6rem;
|
||||||
|
margin:.2rem;
|
||||||
|
overflow:hidden;
|
||||||
|
transform:scale(1);
|
||||||
|
transition:color 125ms,transform 125ms;
|
||||||
|
width:1.6rem
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-sponsorship__item:focus,
|
||||||
|
.md-typeset .mdx-sponsorship__item:hover {
|
||||||
|
transform:scale(1.1)
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-sponsorship__item:focus img,
|
||||||
|
.md-typeset .mdx-sponsorship__item:hover img {
|
||||||
|
filter:grayscale(0)
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-sponsorship__item--private {
|
||||||
|
background:var(--md-default-fg-color--lightest);
|
||||||
|
color:var(--md-default-fg-color--lighter);
|
||||||
|
font-size:.6rem;
|
||||||
|
font-weight:700;
|
||||||
|
line-height:1.6rem;
|
||||||
|
text-align:center
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-sponsorship__item img {
|
||||||
|
display:block;
|
||||||
|
filter:grayscale(100%) opacity(75%);
|
||||||
|
height:auto;
|
||||||
|
transition:filter 125ms;
|
||||||
|
width:100%
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-sponsorship-button {
|
||||||
|
font-weight:400
|
||||||
|
}
|
||||||
|
.md-typeset .mdx-sponsorship-count,
|
||||||
|
.md-typeset .mdx-sponsorship-total {
|
||||||
|
font-weight:700
|
||||||
|
}
|
||||||
|
|||||||
164
docs/docs/usage/healthcheck.md
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
---
|
||||||
|
title: Healthcheck
|
||||||
|
tags:
|
||||||
|
- usage
|
||||||
|
---
|
||||||
|
|
||||||
|
# Healthcheck
|
||||||
|
|
||||||
|
This docker container includes the ability to run health checks between the container api and outside services such as Portainer, or any other app that has the ability to query the endpoint `api/health`.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## API
|
||||||
|
<!-- md:version stable-1.4.0 -->
|
||||||
|
|
||||||
|
This container includes the ability to run health checks utilizing the built-in API. You can directly access the health check and view a json formatted result with the url `https://tvapp2.domain.lan/api/health`
|
||||||
|
|
||||||
|
=== "Example"
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="/api/health" linenums="1" }
|
||||||
|
{
|
||||||
|
"ip": "172.18.2.1",
|
||||||
|
"gateway": "172.18.0.1",
|
||||||
|
"uptime": 5903.549082501,
|
||||||
|
"message": "healthy",
|
||||||
|
"status": "healthy",
|
||||||
|
"ref": "/api/health",
|
||||||
|
"method": "GET",
|
||||||
|
"code": 200,
|
||||||
|
"timestamp": 1744386346242
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Numerous aliases have been added; you can use any of the following URLs to access the same health check results as they go to the same endpoint:
|
||||||
|
|
||||||
|
- https://tvapp2.domain.lan/api/health
|
||||||
|
- https://tvapp2.domain.lan/api/status
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Portainer
|
||||||
|
<!-- md:version stable-1.3.0 -->
|
||||||
|
|
||||||
|
To run a health check between TVApp2 and Portainer, apply the following lines of code to your TVApp2 `docker-compose.yml`. Two examples have been provided, you can use either one; `wget` or `curl`:
|
||||||
|
|
||||||
|
=== "Using CURL"
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="14-18" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- TZ=Etc/UTC
|
||||||
|
health check:
|
||||||
|
test: "curl --fail --silent http://127.0.0.1:4124/api/health | grep -i healthy || exit 1"
|
||||||
|
interval: 15s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Using WGET"
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="14-18" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- TZ=Etc/UTC
|
||||||
|
health check:
|
||||||
|
test: "wget -qO- http://127.0.0.1:4124/api/health | grep -i healthy || exit 1"
|
||||||
|
interval: 15s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## Web Interface
|
||||||
|
<!-- md:version stable-1.4.0 -->
|
||||||
|
|
||||||
|
The TVApp2 web interface is equip with its own health check which is ran every `10 minutes` by default. Users will notice a health indicator in the top right of the header navigation bar which is represented by the :octicons-heart-fill-24:{ .heart } icon.
|
||||||
|
|
||||||
|
When the health check is ran every 10 minutes; a toast notification will appear in the lower-right side of the page:
|
||||||
|
|
||||||
|
<figure markdown="span">
|
||||||
|
{ width="80%" }
|
||||||
|
<figcaption>Health check toast notification</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
### Health Check Duration
|
||||||
|
<!-- md:control env -->
|
||||||
|
<!-- md:version stable-1.4.0 -->
|
||||||
|
<!-- md:default `600000` -->
|
||||||
|
|
||||||
|
By default, a health check between the TVApp2 container and the web interface is done every `10 minutes`, but you can change this duration to something less or more. Be aware that if you set the time too low, you will constantly be spammed with toast notifications.
|
||||||
|
|
||||||
|
To change the health check delay, add the environment variable `HEALTH_TIMER` to your TVApp2 `docker-compose.yml`. Duration is in milliseconds.
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
=== "Example"
|
||||||
|
|
||||||
|
``` { .yaml .copy .select title="docker-compose.yml" linenums="1" hl_lines="13" }
|
||||||
|
services:
|
||||||
|
tvapp2:
|
||||||
|
container_name: tvapp2
|
||||||
|
image: ghcr.io/thebinaryninja/tvapp2:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config:/config
|
||||||
|
- ./app:/usr/bin/app
|
||||||
|
environment:
|
||||||
|
- HEALTH_TIMER=600000 # (1)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :information: Defines how often to perform health checks between the container and the web interface. Time is in milliseconds. <br /><br />Default value is `600000` (10 minutes)
|
||||||
|
|
||||||
|
=== "Time Chart"
|
||||||
|
|
||||||
|
| HEALTH_TIMER Value | Delay Between Checks |
|
||||||
|
| --- | --- |
|
||||||
|
| `HEALTH_TIMER=300000` | 5 minutes |
|
||||||
|
| `HEALTH_TIMER=600000` | 10 minutes |
|
||||||
|
| `HEALTH_TIMER=1200000` | 20 minutes |
|
||||||
|
| `HEALTH_TIMER=1800000` | 30 minutes |
|
||||||
|
| `HEALTH_TIMER=3600000` | 1 hour |
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
BIN
docs/img/core/01.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
docs/img/core/02.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
docs/img/core/03.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
docs/img/core/04.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
docs/img/screenshots/01.gif
Normal file
|
After Width: | Height: | Size: 970 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 60 KiB |
1
docs/material/overrides/.icons/aetherx/axd/ballot.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc. --><defs><style>.fa-secondary{opacity:.4}</style></defs><path class="fa-secondary" d="M0 64L0 448c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-384c0-35.3-28.7-64-64-64L64 0C28.7 0 0 28.7 0 64zm64 48c0-8.8 7.2-16 16-16l32 0c8.8 0 16 7.2 16 16l0 32c0 8.8-7.2 16-16 16l-32 0c-8.8 0-16-7.2-16-16l0-32zm0 128c0-8.8 7.2-16 16-16l32 0c8.8 0 16 7.2 16 16l0 32c0 8.8-7.2 16-16 16l-32 0c-8.8 0-16-7.2-16-16l0-32zm0 128c0-8.8 7.2-16 16-16l32 0c8.8 0 16 7.2 16 16l0 32c0 8.8-7.2 16-16 16l-32 0c-8.8 0-16-7.2-16-16l0-32zM192 128c0-8.8 7.2-16 16-16l160 0c8.8 0 16 7.2 16 16s-7.2 16-16 16l-160 0c-8.8 0-16-7.2-16-16zm0 128c0-8.8 7.2-16 16-16l160 0c8.8 0 16 7.2 16 16s-7.2 16-16 16l-160 0c-8.8 0-16-7.2-16-16zm0 128c0-8.8 7.2-16 16-16l160 0c8.8 0 16 7.2 16 16s-7.2 16-16 16l-160 0c-8.8 0-16-7.2-16-16z"/><path class="fa-primary" d="M64 112c0-8.8 7.2-16 16-16l32 0c8.8 0 16 7.2 16 16l0 32c0 8.8-7.2 16-16 16l-32 0c-8.8 0-16-7.2-16-16l0-32zm0 128c0-8.8 7.2-16 16-16l32 0c8.8 0 16 7.2 16 16l0 32c0 8.8-7.2 16-16 16l-32 0c-8.8 0-16-7.2-16-16l0-32zM80 352l32 0c8.8 0 16 7.2 16 16l0 32c0 8.8-7.2 16-16 16l-32 0c-8.8 0-16-7.2-16-16l0-32c0-8.8 7.2-16 16-16z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc. --><defs><style>.fa-secondary{opacity:.4}</style></defs><path class="fa-secondary" d="M264.8 64C277.6 64 288 74.4 288 87.2c0 9.2-5.8 17.3-13.2 22.8c-11.6 8.7-18.8 20.7-18.8 34c0 26.5 28.7 48 64 48s64-21.5 64-48c0-13.3-7.2-25.3-18.8-34c-7.4-5.5-13.2-13.6-13.2-22.8C352 74.4 362.4 64 375.2 64L464 64c26.5 0 48 21.5 48 48l0 88.8c0 12.8 10.4 23.2 23.2 23.2c9.2 0 17.3-5.8 22.8-13.2c8.7-11.6 20.7-18.8 34-18.8c26.5 0 48 28.7 48 64s-21.5 64-48 64c-13.3 0-25.3-7.2-34-18.8c-5.5-7.4-13.6-13.2-22.8-13.2c-12.8 0-23.2 10.4-23.2 23.2l0 88.8c0 26.5-21.5 48-48 48l-88.8 0c-12.8 0-23.2-10.4-23.2-23.2c0-9.2 5.8-17.3 13.2-22.8c11.6-8.7 18.8-20.7 18.8-34c0-26.5-28.7-48-64-48s-64 21.5-64 48c0 13.3 7.2 25.3 18.8 34c7.4 5.5 13.2 13.6 13.2 22.8c0 12.8-10.4 23.2-23.2 23.2L176 448c-26.5 0-48-21.5-48-48l0-88.8c0-12.8-10.4-23.2-23.2-23.2c-9.2 0-17.3 5.8-22.8 13.2C73.3 312.8 61.3 320 48 320c-26.5 0-48-28.7-48-64s21.5-64 48-64c13.3 0 25.3 7.2 34 18.8c5.5 7.4 13.6 13.2 22.8 13.2c12.8 0 23.2-10.4 23.2-23.2l0-88.8c0-26.5 21.5-48 48-48l88.8 0z"/><path class="fa-primary" d=""/></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc. --><defs><style>.fa-secondary{opacity:.4}</style></defs><path class="fa-secondary" d="M192 104.8c0-9.2-5.8-17.3-13.2-22.8C167.2 73.3 160 61.3 160 48c0-26.5 28.7-48 64-48s64 21.5 64 48c0 13.3-7.2 25.3-18.8 34c-7.4 5.5-13.2 13.6-13.2 22.8c0 12.8 10.4 23.2 23.2 23.2l56.8 0c26.5 0 48 21.5 48 48l0 56.8c0 12.8 10.4 23.2 23.2 23.2c9.2 0 17.3-5.8 22.8-13.2c8.7-11.6 20.7-18.8 34-18.8c26.5 0 48 28.7 48 64s-21.5 64-48 64c-13.3 0-25.3-7.2-34-18.8c-5.5-7.4-13.6-13.2-22.8-13.2c-12.8 0-23.2 10.4-23.2 23.2L384 464c0 26.5-21.5 48-48 48l-56.8 0c-12.8 0-23.2-10.4-23.2-23.2c0-9.2 5.8-17.3 13.2-22.8c11.6-8.7 18.8-20.7 18.8-34c0-26.5-28.7-48-64-48s-64 21.5-64 48c0 13.3 7.2 25.3 18.8 34c7.4 5.5 13.2 13.6 13.2 22.8c0 12.8-10.4 23.2-23.2 23.2L48 512c-26.5 0-48-21.5-48-48L0 343.2C0 330.4 10.4 320 23.2 320c9.2 0 17.3 5.8 22.8 13.2C54.7 344.8 66.7 352 80 352c26.5 0 48-28.7 48-64s-21.5-64-48-64c-13.3 0-25.3 7.2-34 18.8C40.5 250.2 32.4 256 23.2 256C10.4 256 0 245.6 0 232.8L0 176c0-26.5 21.5-48 48-48l120.8 0c12.8 0 23.2-10.4 23.2-23.2z"/><path class="fa-primary" d=""/></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
1
docs/material/overrides/.icons/aetherx/axd/puzzle.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc. --><defs><style>.fa-secondary{opacity:.4}</style></defs><path class="fa-secondary" d="M0 288L0 448c0 35.3 28.7 64 64 64l160 0 0-64c0-8.8-7.2-16-16-16l-16 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l16 0c8.8 0 16-7.2 16-16l0-64-64 0c-8.8 0-16-7.2-16-16l0-16c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 16c0 8.8-7.2 16-16 16L0 288zM304 16l0 48c0 8.8 7.2 16 16 16l16 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-16 0c-8.8 0-16 7.2-16 16l0 32c0 8.8 7.2 16 16 16l36 0c6.6 0 12 5.4 12 12l0 4c0 17.7 14.3 32 32 32s32-14.3 32-32l0-4c0-6.6 5.4-12 12-12l52 0c8.8 0 16-7.2 16-16l0-128c0-35.3-28.7-64-64-64L320 0c-8.8 0-16 7.2-16 16z"/><path class="fa-primary" d="M0 288l64 0c8.8 0 16-7.2 16-16l0-16c0-17.7 14.3-32 32-32s32 14.3 32 32l0 16c0 8.8 7.2 16 16 16l64 0 0-68c0-6.6 5.4-12 12-12l4 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-4 0c-6.6 0-12-5.4-12-12l0-52c0-8.8-7.2-16-16-16L64 64C28.7 64 0 92.7 0 128L0 288zm224 0l0 64c0 8.8-7.2 16-16 16l-16 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l16 0c8.8 0 16 7.2 16 16l0 64 160 0c35.3 0 64-28.7 64-64l0-144c0-8.8-7.2-16-16-16l-48 0c-8.8 0-16 7.2-16 16l0 16c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-16c0-8.8-7.2-16-16-16l-64 0z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc. --><defs><style>.fa-secondary{opacity:.4}</style></defs><path class="fa-secondary" d="M3.4 273.7c-7.9 15.8-1.5 35 14.3 42.9L152.4 384 17.7 451.4C1.9 459.3-4.5 478.5 3.4 494.3C9 505.5 20.3 512 32 512c4.8 0 9.7-1.1 14.3-3.4L224 419.8l177.7 88.8c4.6 2.3 9.5 3.4 14.3 3.4c11.7 0 23-6.5 28.6-17.7c7.9-15.8 1.5-35-14.3-42.9L295.6 384l134.8-67.4c15.8-7.9 22.2-27.1 14.3-42.9C439 262.5 427.7 256 416 256c-4.8 0-9.7 1.1-14.3 3.4L224 348.2 46.3 259.4c-4.6-2.3-9.5-3.4-14.3-3.4c-11.7 0-23 6.5-28.6 17.7z"/><path class="fa-primary" d="M304 234.4c38.6-23 64-62.1 64-106.4C368 57.3 303.5 0 224 0S80 57.3 80 128c0 44.4 25.4 83.5 64 106.4l0 21.6c0 17.7 14.3 32 32 32l96 0c17.7 0 32-14.3 32-32l0-21.6zM136 144a32 32 0 1 1 64 0 32 32 0 1 1 -64 0zm144-32a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1006 B |
1
docs/material/overrides/.icons/aetherx/axd/tv.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc. --><defs><style>.fa-secondary{opacity:.4}</style></defs><path class="fa-secondary" d="M0 64C0 28.7 28.7 0 64 0L576 0c35.3 0 64 28.7 64 64l0 288c0 35.3-28.7 64-64 64L64 416c-35.3 0-64-28.7-64-64L0 64zm64 0l0 288 512 0 0-288L64 64zM96 480c0-17.7 14.3-32 32-32l384 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-384 0c-17.7 0-32-14.3-32-32z"/><path class="fa-primary" d="M64 64H576V352H64V64z"/></svg>
|
||||||
|
After Width: | Height: | Size: 617 B |
1
docs/material/overrides/.icons/aetherx/axd/volume.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc. --><defs><style>.fa-secondary{opacity:.4}</style></defs><path class="fa-secondary" d="M0 96C0 60.7 28.7 32 64 32l384 0c35.3 0 64 28.7 64 64l0 224c0 5.5-.7 10.8-2 16c-3.6-13.8-11.6-25.8-22.5-34.4c-5.4-4.3-11.6-7.7-18.2-10c-3.3-1.2-6.8-2.1-10.3-2.7c-1.8-.3-3.6-.5-5.4-.7c-.9-.1-1.8-.1-2.8-.2s-1.8-.1-2.8-.1L64 288c-29.8 0-54.9 20.4-62 48c-1.3-5.1-2-10.5-2-16L0 96zM352 384a32 32 0 1 1 -64 0 32 32 0 1 1 64 0z"/><path class="fa-primary" d="M0 352c0-35.3 28.7-64 64-64l384 0c35.3 0 64 28.7 64 64l0 64c0 35.3-28.7 64-64 64L64 480c-35.3 0-64-28.7-64-64l0-64zm352 32a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zm64 32a32 32 0 1 0 0-64 32 32 0 1 0 0 64z"/></svg>
|
||||||
|
After Width: | Height: | Size: 872 B |
1
docs/material/overrides/.icons/aetherx/axs/clock.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc. --><defs><style>.fa-secondary{opacity:.4}</style></defs><path class="fa-secondary" d="M0 256a256 256 0 1 0 512 0A256 256 0 1 0 0 256zM232 120c.1-13.4 10.8-24 24-24c6.6 0 12.6 2.7 17 7c2.2 2.2 3.9 4.8 5.1 7.6c.6 1.4 1.1 2.9 1.4 4.5c.2 .8 .3 1.6 .4 2.4s.1 1.6 .1 2.5c0 41 0 82.1 0 123.2L365.3 300c6.9 4.6 10.7 12.2 10.7 20c0 4.6-1.3 9.2-4 13.3c-4.6 6.9-12.2 10.7-20 10.7c-4.6 0-9.2-1.3-13.3-4c-32-21.3-64-42.7-96-64C236 271.5 232 264 232 256c0-45.3 0-90.7 0-136z"/><path class="fa-primary" d="M256 96c-13.3 0-24 10.7-24 24l0 136c0 8 4 15.5 10.7 20l96 64c11 7.4 25.9 4.4 33.3-6.7s4.4-25.9-6.7-33.3L280 243.2 280 120c0-13.3-10.7-24-24-24z"/></svg>
|
||||||
|
After Width: | Height: | Size: 870 B |
1
docs/material/overrides/.icons/aetherx/axs/code.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc. --><defs><style>.fa-secondary{opacity:.4}</style></defs><path class="fa-secondary" d="M225.2 471.2c-4.9 17 5 34.7 22 39.6c2.9 .8 5.9 1.2 8.8 1.2c13.9 0 26.7-9.2 30.7-23.2l128-448c.8-2.9 1.2-5.9 1.2-8.8c0-13.9-9.2-26.7-23.2-30.8c-17-4.9-34.7 5-39.6 22l-128 448z"/><path class="fa-primary" d="M473.4 121.4c-12.5 12.5-12.5 32.8 0 45.3L562.7 256l-89.4 89.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l112-112c12.5-12.5 12.5-32.8 0-45.3l-112-112c-12.5-12.5-32.8-12.5-45.3 0zm-306.7 0c-12.5-12.5-32.8-12.5-45.3 0l-112 112c-12.5 12.5-12.5 32.8 0 45.3l112 112c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256l89.4-89.4c12.5-12.5 12.5-32.8 0-45.3z"/></svg>
|
||||||
|
After Width: | Height: | Size: 879 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc. --><defs><style>.fa-secondary{opacity:.4}</style></defs><path class="fa-secondary" d="M192 104.8c0-9.2-5.8-17.3-13.2-22.8C167.2 73.3 160 61.3 160 48c0-26.5 28.7-48 64-48s64 21.5 64 48c0 13.3-7.2 25.3-18.8 34c-7.4 5.5-13.2 13.6-13.2 22.8c0 12.8 10.4 23.2 23.2 23.2l56.8 0c26.5 0 48 21.5 48 48l0 56.8c0 12.8 10.4 23.2 23.2 23.2c9.2 0 17.3-5.8 22.8-13.2c8.7-11.6 20.7-18.8 34-18.8c26.5 0 48 28.7 48 64s-21.5 64-48 64c-13.3 0-25.3-7.2-34-18.8c-5.5-7.4-13.6-13.2-22.8-13.2c-12.8 0-23.2 10.4-23.2 23.2L384 464c0 26.5-21.5 48-48 48l-56.8 0c-12.8 0-23.2-10.4-23.2-23.2c0-9.2 5.8-17.3 13.2-22.8c11.6-8.7 18.8-20.7 18.8-34c0-26.5-28.7-48-64-48s-64 21.5-64 48c0 13.3 7.2 25.3 18.8 34c7.4 5.5 13.2 13.6 13.2 22.8c0 12.8-10.4 23.2-23.2 23.2L48 512c-26.5 0-48-21.5-48-48L0 343.2C0 330.4 10.4 320 23.2 320c9.2 0 17.3 5.8 22.8 13.2C54.7 344.8 66.7 352 80 352c26.5 0 48-28.7 48-64s-21.5-64-48-64c-13.3 0-25.3 7.2-34 18.8C40.5 250.2 32.4 256 23.2 256C10.4 256 0 245.6 0 232.8L0 176c0-26.5 21.5-48 48-48l120.8 0c12.8 0 23.2-10.4 23.2-23.2z"/><path class="fa-primary" d=""/></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -71,9 +71,9 @@ class clr():
|
|||||||
MAGENTA = '\033[35m'
|
MAGENTA = '\033[35m'
|
||||||
CYAN = '\033[36m'
|
CYAN = '\033[36m'
|
||||||
WHITE = '\033[37m'
|
WHITE = '\033[37m'
|
||||||
|
GREY = '\033[90m'
|
||||||
UNDERLINE = '\033[4m'
|
UNDERLINE = '\033[4m'
|
||||||
RESET = '\033[0m'
|
RESET = '\033[0m'
|
||||||
GREY = '\033[90m'
|
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Pages
|
# Pages
|
||||||
@@ -87,6 +87,8 @@ PAGE_CONVENTIONS = "about/conventions.md"
|
|||||||
|
|
||||||
# #
|
# #
|
||||||
# Hooks > on_page_markdown
|
# Hooks > on_page_markdown
|
||||||
|
#
|
||||||
|
# do not change this function name
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def on_page_markdown(markdown: str, *, page: Page, config: MkDocsConfig, files: Files):
|
def on_page_markdown(markdown: str, *, page: Page, config: MkDocsConfig, files: Files):
|
||||||
@@ -99,28 +101,28 @@ def on_page_markdown(markdown: str, *, page: Page, config: MkDocsConfig, files:
|
|||||||
args = args.strip()
|
args = args.strip()
|
||||||
|
|
||||||
if type == "version":
|
if type == "version":
|
||||||
if args.startswith( "beta-" ):
|
if args.startswith( "development-" ):
|
||||||
return Version_Beta(args, page, files)
|
return Version_Development(args, page, files)
|
||||||
elif args.startswith( "stable-" ):
|
elif args.startswith( "stable-" ):
|
||||||
return Version_Stable( args, page, files )
|
return Version_Stable( args, page, files )
|
||||||
else:
|
else:
|
||||||
return Version( args, page, files )
|
return Version( args, page, files )
|
||||||
|
|
||||||
elif type == "backers": return Badge_Backers(page, files)
|
elif type == "control": return badgeControl(args, page, files)
|
||||||
elif type == "control": return Create_Control(args, page, files)
|
elif type == "flag": return badgeFlag(args, page, files)
|
||||||
elif type == "flag": return Create_Flag(args, page, files)
|
elif type == "option": return badgeOption(args)
|
||||||
elif type == "option": return Create_Option(args)
|
elif type == "setting": return badgeSetting(args)
|
||||||
elif type == "setting": return Create_Setting(args)
|
elif type == "backers": return badgeBackers(page, files)
|
||||||
elif type == "command": return Badge_Command(args, page, files)
|
elif type == "command": return badgeCommand(args, page, files)
|
||||||
elif type == "feature": return Badge_Feature(args, page, files)
|
elif type == "feature": return badgeFeature(args, page, files)
|
||||||
elif type == "plugin": return Badge_Plugin(args, page, files)
|
elif type == "plugin": return badgePlugin(args, page, files)
|
||||||
elif type == "extension": return Badge_Extension(args, page, files)
|
elif type == "markdown": return badgeMarkdown(args, page, files)
|
||||||
elif type == "3rdparty": return Badge_3rdparty(args, page, files)
|
elif type == "3rdparty": return badge3rdParty(args, page, files)
|
||||||
elif type == "example": return Badge_Example(args, page, files)
|
elif type == "example": return badgeExample(args, page, files)
|
||||||
elif type == "default":
|
elif type == "default":
|
||||||
if args == "none": return Badge_DefaultValue_None(page, files)
|
if args == "none": return badgeDefaultNone(page, files)
|
||||||
elif args == "computed": return Badge_DefaultValue_Computed(page, files)
|
elif args == "computed": return badgeDefaultVal(page, files)
|
||||||
else: return Badge_DefaultValue_Custom(args, page, files)
|
else: return badgeDefaultCustom(args, page, files)
|
||||||
|
|
||||||
# Otherwise, raise an error
|
# Otherwise, raise an error
|
||||||
raise RuntimeError( f"Error in shortcodes.yp - Specified an unknown shortcode: {type}" )
|
raise RuntimeError( f"Error in shortcodes.yp - Specified an unknown shortcode: {type}" )
|
||||||
@@ -135,31 +137,36 @@ def on_page_markdown(markdown: str, *, page: Page, config: MkDocsConfig, files:
|
|||||||
# Create > Flag
|
# Create > Flag
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Create_Flag(args: str, page: Page, files: Files):
|
def badgeFlag(args: str, page: Page, files: Files):
|
||||||
type, *_ = args.split(" ", 1)
|
type, *_ = args.split(" ", 1)
|
||||||
if type == "experimental": return Badge_Flag_Experimental(page, files)
|
if type == "experimental": return badgeFlagExperimental(page, files)
|
||||||
elif type == "required": return Badge_Flag_Required(page, files)
|
elif type == "required": return badgeFlagRequired(page, files)
|
||||||
elif type == "customization": return Badge_Flag_Customization(page, files)
|
elif type == "customization": return badgeFlagCustomization(page, files)
|
||||||
elif type == "metadata": return Badge_Flag_Metadata(page, files)
|
elif type == "metadata": return badgeFlagMetadata(page, files)
|
||||||
elif type == "multiple": return Badge_Flag_Multiple_Instances(page, files)
|
elif type == "dangerous": return badgeFlagDangerous(page, files)
|
||||||
elif type == "setting": return Badge_Flag_Setting(page, files)
|
elif type == "multiple": return badgeFlagMultiInstances(page, files)
|
||||||
|
elif type == "setting": return badgeFlagSetting(page, files)
|
||||||
|
else: return badgeFlagDefault( page, files )
|
||||||
|
|
||||||
raise RuntimeError(f"Unknown type: {type}")
|
raise RuntimeError(f"Unknown type: {type}")
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Create > Controls
|
# Create > Controls
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Create_Control( args: str, page: Page, files: Files ):
|
def badgeControl( args: str, page: Page, files: Files ):
|
||||||
type, *_ = args.split( " ", 2 )
|
type, *_ = args.split( " ", 2 )
|
||||||
if type == "toggle": return icon_control_toggle( page, files )
|
if type == "toggle": return newControlToggle( page, files )
|
||||||
elif type == "toggle_on": return icon_control_toggle_on( page, files )
|
elif type == "toggle_on": return newControlToggleOn( page, files )
|
||||||
elif type == "toggle_off": return icon_control_toggle_off( page, files )
|
elif type == "toggle_off": return newControlToggleOff( page, files )
|
||||||
elif type == "textbox": return icon_control_textbox( page, files )
|
elif type == "textbox": return newControlTextbox( page, files )
|
||||||
elif type == "dropdown": return icon_control_dropdown( page, files )
|
elif type == "dropdown": return newControlDropdown( page, files )
|
||||||
elif type == "button": return icon_control_button( page, files )
|
elif type == "button": return newControlButton( page, files )
|
||||||
elif type == "slider": return icon_control_slider( page, files )
|
elif type == "slider": return newControlSlider( page, files )
|
||||||
elif type == "color": return icon_control_color( args, page, files )
|
elif type == "env": return newControlEnvVar( page, files )
|
||||||
else: return icon_control_default( page, files )
|
elif type == "volume": return newControlVolume( page, files )
|
||||||
|
elif type == "color": return newControlColor( args, page, files )
|
||||||
|
else: return newControlDefault( page, files )
|
||||||
|
|
||||||
raise RuntimeError(f"Unknown type: {type}")
|
raise RuntimeError(f"Unknown type: {type}")
|
||||||
|
|
||||||
@@ -167,15 +174,19 @@ def Create_Control( args: str, page: Page, files: Files ):
|
|||||||
# Create > Option
|
# Create > Option
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Create_Option(type: str):
|
def badgeOption(type: str):
|
||||||
_, *_, name = re.split(r"[.:]", type)
|
_, *_, name = re.split(r"[.:]", type)
|
||||||
return f"[`{name}`](#+{type}){{ #+{type} }}\n\n"
|
return f"[`{name}`](#+{type}){{ #+{type} }}\n\n"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Create > Setting
|
# Create > Setting
|
||||||
|
#
|
||||||
|
# #### <!-- md:setting example.setting.enabled -->
|
||||||
|
# <!-- md:version 1.0.0 -->
|
||||||
|
# <!-- md:default `true` -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Create_Setting(type: str):
|
def badgeSetting(type: str):
|
||||||
_, *_, name = re.split(r"[.*]", type)
|
_, *_, name = re.split(r"[.*]", type)
|
||||||
return f"`{name}` {{ #{type} }}\n\n[{type}]: #{type}\n\n"
|
return f"`{name}` {{ #{type} }}\n\n[{type}]: #{type}\n\n"
|
||||||
|
|
||||||
@@ -202,7 +213,7 @@ def _resolve(file: File, page: Page):
|
|||||||
# Create > Badge
|
# Create > Badge
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Create_Badge(icon: str, text: str = "", type: str = ""):
|
def badgeCreate(icon: str, text: str = "", type: str = ""):
|
||||||
classes = f"mdx-badge mdx-badge--{type}" if type else "mdx-badge"
|
classes = f"mdx-badge mdx-badge--{type}" if type else "mdx-badge"
|
||||||
return "".join([
|
return "".join([
|
||||||
f"<span class=\"{classes}\">",
|
f"<span class=\"{classes}\">",
|
||||||
@@ -215,7 +226,7 @@ def Create_Badge(icon: str, text: str = "", type: str = ""):
|
|||||||
# Badge > Color Palette
|
# Badge > Color Palette
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_ColorPalette(icon: str, text: str = "", type: str = ""):
|
def badgeColorPalette(icon: str, text: str = "", type: str = ""):
|
||||||
args = type.split( " " )
|
args = type.split( " " )
|
||||||
|
|
||||||
bg1_clr = "#000000"
|
bg1_clr = "#000000"
|
||||||
@@ -252,10 +263,10 @@ def Badge_ColorPalette(icon: str, text: str = "", type: str = ""):
|
|||||||
# <!-- md:sponsors -->
|
# <!-- md:sponsors -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_Backers(page: Page, files: Files):
|
def badgeBackers(page: Page, files: Files):
|
||||||
icon = "material-heart"
|
icon = "material-heart"
|
||||||
href = _resolve_path(PAGE_BACKERS, page, files)
|
href = _resolve_path(PAGE_BACKERS, page, files)
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Backers only')",
|
icon = f"[:{icon}:]({href} 'Backers only')",
|
||||||
type = "heart"
|
type = "heart"
|
||||||
)
|
)
|
||||||
@@ -280,8 +291,8 @@ def Version( text: str, page: Page, files: Files ):
|
|||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Mkdocs Release')",
|
icon = f"[:{icon}:]({href} 'TVApp2 Release')",
|
||||||
text = f"[{text}]({_resolve_path(path, page, files)})" if spec else ""
|
text = f"[{text}]({_resolve_path(path, page, files)})" if spec else ""
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -294,8 +305,8 @@ def Version_Stable( text: str, page: Page, files: Files ):
|
|||||||
path = f"{PAGE_CHANGELOG}#{spec}"
|
path = f"{PAGE_CHANGELOG}#{spec}"
|
||||||
|
|
||||||
# Return badge
|
# Return badge
|
||||||
icon = "aetherx-axs-tag"
|
icon = "aetherx-axs-tag"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#version-beta", page, files )
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#version-stable", page, files )
|
||||||
output = ""
|
output = ""
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
@@ -306,22 +317,22 @@ def Version_Stable( text: str, page: Page, files: Files ):
|
|||||||
else:
|
else:
|
||||||
output = f"Stable Release"
|
output = f"Stable Release"
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} '{output}' )",
|
icon = f"[:{icon}:]({href} '{output}' )",
|
||||||
text = f"[{spec}]({_resolve_path(path, page, files)})" if spec else ""
|
text = f"[{spec}]({_resolve_path(path, page, files)})" if spec else ""
|
||||||
)
|
)
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Badge > Version > Beta
|
# Badge > Version > Development
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Version_Beta( text: str, page: Page, files: Files ):
|
def Version_Development( text: str, page: Page, files: Files ):
|
||||||
spec = text.replace( "beta-", "" )
|
spec = text.replace( "development-", "" )
|
||||||
path = f"{PAGE_CHANGELOG}#{spec}"
|
path = f"{PAGE_CHANGELOG}#{spec}"
|
||||||
|
|
||||||
# Return badge
|
# Return badge
|
||||||
icon = "aetherx-axs-b"
|
icon = "aetherx-axs-code"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#version-beta", page, files )
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#version-development", page, files )
|
||||||
output = ""
|
output = ""
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
@@ -330,9 +341,9 @@ def Version_Beta( text: str, page: Page, files: Files ):
|
|||||||
if spec:
|
if spec:
|
||||||
output = f"Requires version {spec}"
|
output = f"Requires version {spec}"
|
||||||
else:
|
else:
|
||||||
output = f"Beta Release"
|
output = f"Development Release"
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} '{output}' )",
|
icon = f"[:{icon}:]({href} '{output}' )",
|
||||||
text = f"[{text}]({_resolve_path(path, page, files)})" if spec else ""
|
text = f"[{text}]({_resolve_path(path, page, files)})" if spec else ""
|
||||||
)
|
)
|
||||||
@@ -344,13 +355,13 @@ def Version_Beta( text: str, page: Page, files: Files ):
|
|||||||
# <!-- md:feature -->
|
# <!-- md:feature -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_Feature(text: str, page: Page, files: Files):
|
def badgeFeature(text: str, page: Page, files: Files):
|
||||||
icon = "material-toggle-switch"
|
icon = "material-toggle-switch"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#feature", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#feature", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Optional feature')",
|
icon = f"[:{icon}:]({href} 'Optional feature')",
|
||||||
text = text
|
text = text
|
||||||
)
|
)
|
||||||
@@ -364,32 +375,32 @@ def Badge_Feature(text: str, page: Page, files: Files):
|
|||||||
# <!-- md:plugin [typeset] – built-in -->
|
# <!-- md:plugin [typeset] – built-in -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_Plugin(text: str, page: Page, files: Files):
|
def badgePlugin(text: str, page: Page, files: Files):
|
||||||
icon = "material-floppy"
|
icon = "material-floppy"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#plugin", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#plugin", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Plugin')",
|
icon = f"[:{icon}:]({href} 'Plugin')",
|
||||||
text = text
|
text = text
|
||||||
)
|
)
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Create badge for extension
|
# Create badge for Markdown
|
||||||
#
|
#
|
||||||
# use the following tag in your md file:
|
# use the following tag in your md file:
|
||||||
# <!-- md:extension [admonition][Admonition] -->
|
# <!-- md:markdown [admonition][Admonition] -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_Extension(text: str, page: Page, files: Files):
|
def badgeMarkdown(text: str, page: Page, files: Files):
|
||||||
icon = "material-language-markdown"
|
icon = "material-language-markdown"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#extension", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#markdown", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Markdown extension')",
|
icon = f"[:{icon}:]({href} 'Markdown functionality')",
|
||||||
text = text
|
text = text
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -403,13 +414,13 @@ def Badge_Extension(text: str, page: Page, files: Files):
|
|||||||
# <!-- md:3rdparty [mike] -->
|
# <!-- md:3rdparty [mike] -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_3rdparty(text: str, page: Page, files: Files):
|
def badge3rdParty(text: str, page: Page, files: Files):
|
||||||
icon = "material-package-variant"
|
icon = "material-package-variant"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#3rdparty", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#3rdparty", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Third-party utility')",
|
icon = f"[:{icon}:]({href} 'Third-party utility')",
|
||||||
text = text
|
text = text
|
||||||
)
|
)
|
||||||
@@ -433,30 +444,30 @@ def Badge_3rdparty(text: str, page: Page, files: Files):
|
|||||||
# <!-- md:example my-example-file -->
|
# <!-- md:example my-example-file -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_Example(text: str, page: Page, files: Files):
|
def badgeExample(text: str, page: Page, files: Files):
|
||||||
return "\n".join([
|
return "\n".join([
|
||||||
Badge_Example_Download_Zip(text, page, files),
|
badgeExampleDownloadZip(text, page, files),
|
||||||
Badge_Example_View(text, page, files)
|
badgeExampleView(text, page, files)
|
||||||
])
|
])
|
||||||
|
|
||||||
def Badge_Example_View(text: str, page: Page, files: Files):
|
def badgeExampleView(text: str, page: Page, files: Files):
|
||||||
icon = "material-folder-eye"
|
icon = "material-folder-eye"
|
||||||
href = f"https://github.com/TheBinaryNinja/tvapp2/{text}/"
|
href = f"https://github.com/TheBinaryNinja/tvapp2/{text}/"
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'View example')",
|
icon = f"[:{icon}:]({href} 'View example')",
|
||||||
type = "right"
|
type = "right"
|
||||||
)
|
)
|
||||||
|
|
||||||
def Badge_Example_Download_Zip(text: str, page: Page, files: Files):
|
def badgeExampleDownloadZip(text: str, page: Page, files: Files):
|
||||||
icon = "material-folder-download"
|
icon = "material-folder-download"
|
||||||
href = f"https://github.com/TheBinaryNinja/tvapp2/{text}.zip"
|
href = f"https://github.com/TheBinaryNinja/tvapp2/{text}.zip"
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Download example')",
|
icon = f"[:{icon}:]({href} 'Download example')",
|
||||||
text = f"[`.zip`]({href})",
|
text = f"[`.zip`]({href})",
|
||||||
type = "right"
|
type = "right"
|
||||||
@@ -471,15 +482,16 @@ def Badge_Example_Download_Zip(text: str, page: Page, files: Files):
|
|||||||
# <!-- md:command `-s, --start` -->
|
# <!-- md:command `-s, --start` -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_Command(text: str, page: Page, files: Files):
|
def badgeCommand(text: str, page: Page, files: Files):
|
||||||
icon = "material-console-line"
|
icon = "material-console-line"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#command", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#command", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Terminal / Console Command')",
|
icon = f"[:{icon}:]({href} 'Terminal / Console Command')",
|
||||||
text = text
|
text = text,
|
||||||
|
type = "command"
|
||||||
)
|
)
|
||||||
|
|
||||||
# #
|
# #
|
||||||
@@ -494,13 +506,13 @@ def Badge_Command(text: str, page: Page, files: Files):
|
|||||||
# <!-- md:default none -->
|
# <!-- md:default none -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_DefaultValue_Custom(text: str, page: Page, files: Files):
|
def badgeDefaultCustom(text: str, page: Page, files: Files):
|
||||||
icon = "material-water"
|
icon = "material-water"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#default", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#default", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Default value')",
|
icon = f"[:{icon}:]({href} 'Default value')",
|
||||||
text = text
|
text = text
|
||||||
)
|
)
|
||||||
@@ -517,13 +529,13 @@ def Badge_DefaultValue_Custom(text: str, page: Page, files: Files):
|
|||||||
# <!-- md:default none -->
|
# <!-- md:default none -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_DefaultValue_None(page: Page, files: Files):
|
def badgeDefaultNone(page: Page, files: Files):
|
||||||
icon = "material-water-outline"
|
icon = "material-water-outline"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#default", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#default", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Default value is empty')"
|
icon = f"[:{icon}:]({href} 'Default value is empty')"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -539,53 +551,127 @@ def Badge_DefaultValue_None(page: Page, files: Files):
|
|||||||
# <!-- md:default none -->
|
# <!-- md:default none -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_DefaultValue_Computed(page: Page, files: Files):
|
def badgeDefaultVal(page: Page, files: Files):
|
||||||
icon = "material-water-check"
|
icon = "material-water-check"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#default", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#default", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Default value is computed')"
|
icon = f"[:{icon}:]({href} 'Default value is computed')"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Badge > Flag > Default
|
||||||
|
#
|
||||||
|
# This symbol denotes that the specified item is a customizable setting
|
||||||
|
#
|
||||||
|
# MUST add an entry in conventions.md
|
||||||
|
#
|
||||||
|
# use the following tag in your md file:
|
||||||
|
# : <!-- md:flag --> Default
|
||||||
|
# : <!-- md:flag experimental --> Experimental
|
||||||
|
# : <!-- md:flag required --> Required
|
||||||
|
# : <!-- md:flag customization --> Customization
|
||||||
|
# : <!-- md:flag metadata --> Metadata
|
||||||
|
# : <!-- md:flag dangerous --> Dangerous
|
||||||
|
# : <!-- md:flag multiple --> Multiple
|
||||||
|
# : <!-- md:flag setting --> Setting
|
||||||
|
# #
|
||||||
|
|
||||||
|
def badgeFlagDefault(page: Page, files: Files):
|
||||||
|
icon = "material-flag"
|
||||||
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#setting", page, files)
|
||||||
|
|
||||||
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
|
return badgeCreate(
|
||||||
|
icon = f"[:{icon}:]({href} 'Configurable Setting')"
|
||||||
|
)
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Badge > Flag > Metadata Property
|
# Badge > Flag > Metadata Property
|
||||||
#
|
#
|
||||||
# This symbol denotes that the item described is a metadata property, which can
|
# This symbol denotes that the item described is a metadata property, which can
|
||||||
# be used in Markdown documents as part of the front matter definition.
|
# be used in Markdown documents as part of the front matter definition.
|
||||||
#
|
#
|
||||||
|
# MUST add an entry in conventions.md
|
||||||
|
#
|
||||||
# use the following tag in your md file:
|
# use the following tag in your md file:
|
||||||
# <!-- md:flag metadata -->
|
# : <!-- md:flag --> Default
|
||||||
|
# : <!-- md:flag experimental --> Experimental
|
||||||
|
# : <!-- md:flag required --> Required
|
||||||
|
# : <!-- md:flag customization --> Customization
|
||||||
|
# : <!-- md:flag metadata --> Metadata
|
||||||
|
# : <!-- md:flag dangerous --> Dangerous
|
||||||
|
# : <!-- md:flag multiple --> Multiple
|
||||||
|
# : <!-- md:flag setting --> Setting
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_Flag_Metadata(page: Page, files: Files):
|
def badgeFlagMetadata(page: Page, files: Files):
|
||||||
icon = "material-list-box-outline"
|
icon = "material-list-box-outline"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#metadata", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#metadata", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Metadata property')"
|
icon = f"[:{icon}:]({href} 'Metadata property')"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Badge > Flag > Dangerous
|
||||||
|
#
|
||||||
|
# This symbol denotes that the item or setting specified may be dangerous to change.
|
||||||
|
#
|
||||||
|
# MUST add an entry in conventions.md
|
||||||
|
#
|
||||||
|
# use the following tag in your md file:
|
||||||
|
# : <!-- md:flag --> Default
|
||||||
|
# : <!-- md:flag experimental --> Experimental
|
||||||
|
# : <!-- md:flag required --> Required
|
||||||
|
# : <!-- md:flag customization --> Customization
|
||||||
|
# : <!-- md:flag metadata --> Metadata
|
||||||
|
# : <!-- md:flag dangerous --> Dangerous
|
||||||
|
# : <!-- md:flag multiple --> Multiple
|
||||||
|
# : <!-- md:flag setting --> Setting
|
||||||
|
# #
|
||||||
|
|
||||||
|
def badgeFlagDangerous(page: Page, files: Files):
|
||||||
|
icon = "aetherx-axd-skull-crossbones"
|
||||||
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#dangerous", page, files)
|
||||||
|
|
||||||
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
|
return badgeCreate(
|
||||||
|
icon = f"[:{icon}:]({href} 'This setting is dangerous to change')",
|
||||||
|
type = "dangerous"
|
||||||
|
)
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Badge > Flag > Required
|
# Badge > Flag > Required
|
||||||
#
|
#
|
||||||
# Specifies that a value is required.
|
# Specifies that a value is required.
|
||||||
#
|
#
|
||||||
|
# MUST add an entry in conventions.md
|
||||||
|
#
|
||||||
# use the following tag in your md file:
|
# use the following tag in your md file:
|
||||||
# <!-- md:flag required -->
|
# : <!-- md:flag --> Default
|
||||||
# <!-- md:flag required --> This option enables the content tabs
|
# : <!-- md:flag experimental --> Experimental
|
||||||
|
# : <!-- md:flag required --> Required
|
||||||
|
# : <!-- md:flag customization --> Customization
|
||||||
|
# : <!-- md:flag metadata --> Metadata
|
||||||
|
# : <!-- md:flag dangerous --> Dangerous
|
||||||
|
# : <!-- md:flag multiple --> Multiple
|
||||||
|
# : <!-- md:flag setting --> Setting
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_Flag_Required(page: Page, files: Files):
|
def badgeFlagRequired(page: Page, files: Files):
|
||||||
icon = "material-alert"
|
icon = "material-alert"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#required", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#required", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Required value')"
|
icon = f"[:{icon}:]({href} 'Required value')"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -594,17 +680,26 @@ def Badge_Flag_Required(page: Page, files: Files):
|
|||||||
#
|
#
|
||||||
# This symbol denotes that the item described is a customization which affects the overall look of the app.
|
# This symbol denotes that the item described is a customization which affects the overall look of the app.
|
||||||
#
|
#
|
||||||
|
# MUST add an entry in conventions.md
|
||||||
|
#
|
||||||
# use the following tag in your md file:
|
# use the following tag in your md file:
|
||||||
# <!-- md:flag customization -->
|
# : <!-- md:flag --> Default
|
||||||
|
# : <!-- md:flag experimental --> Experimental
|
||||||
|
# : <!-- md:flag required --> Required
|
||||||
|
# : <!-- md:flag customization --> Customization
|
||||||
|
# : <!-- md:flag metadata --> Metadata
|
||||||
|
# : <!-- md:flag dangerous --> Dangerous
|
||||||
|
# : <!-- md:flag multiple --> Multiple
|
||||||
|
# : <!-- md:flag setting --> Setting
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_Flag_Customization(page: Page, files: Files):
|
def badgeFlagCustomization(page: Page, files: Files):
|
||||||
icon = "material-brush-variant"
|
icon = "material-brush-variant"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#customization", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#customization", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Customization')"
|
icon = f"[:{icon}:]({href} 'Customization')"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -616,16 +711,23 @@ def Badge_Flag_Customization(page: Page, files: Files):
|
|||||||
# MUST add an entry in conventions.md
|
# MUST add an entry in conventions.md
|
||||||
#
|
#
|
||||||
# use the following tag in your md file:
|
# use the following tag in your md file:
|
||||||
# <!-- md:flag experimental -->
|
# : <!-- md:flag --> Default
|
||||||
|
# : <!-- md:flag experimental --> Experimental
|
||||||
|
# : <!-- md:flag required --> Required
|
||||||
|
# : <!-- md:flag customization --> Customization
|
||||||
|
# : <!-- md:flag metadata --> Metadata
|
||||||
|
# : <!-- md:flag dangerous --> Dangerous
|
||||||
|
# : <!-- md:flag multiple --> Multiple
|
||||||
|
# : <!-- md:flag setting --> Setting
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_Flag_Experimental(page: Page, files: Files):
|
def badgeFlagExperimental(page: Page, files: Files):
|
||||||
icon = "material-flask-outline"
|
icon = "material-flask-outline"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#experimental", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#experimental", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Experimental')"
|
icon = f"[:{icon}:]({href} 'Experimental')"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -638,16 +740,23 @@ def Badge_Flag_Experimental(page: Page, files: Files):
|
|||||||
# MUST add an entry in conventions.md
|
# MUST add an entry in conventions.md
|
||||||
#
|
#
|
||||||
# use the following tag in your md file:
|
# use the following tag in your md file:
|
||||||
# <!-- md:flag multiple -->
|
# : <!-- md:flag --> Default
|
||||||
|
# : <!-- md:flag experimental --> Experimental
|
||||||
|
# : <!-- md:flag required --> Required
|
||||||
|
# : <!-- md:flag customization --> Customization
|
||||||
|
# : <!-- md:flag metadata --> Metadata
|
||||||
|
# : <!-- md:flag dangerous --> Dangerous
|
||||||
|
# : <!-- md:flag multiple --> Multiple
|
||||||
|
# : <!-- md:flag setting --> Setting
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_Flag_Multiple_Instances(page: Page, files: Files):
|
def badgeFlagMultiInstances(page: Page, files: Files):
|
||||||
icon = "material-inbox-multiple"
|
icon = "material-inbox-multiple"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#multiple-instances", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#multiple-instances", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Multiple instances')"
|
icon = f"[:{icon}:]({href} 'Multiple instances')"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -659,16 +768,23 @@ def Badge_Flag_Multiple_Instances(page: Page, files: Files):
|
|||||||
# MUST add an entry in conventions.md
|
# MUST add an entry in conventions.md
|
||||||
#
|
#
|
||||||
# use the following tag in your md file:
|
# use the following tag in your md file:
|
||||||
# <!-- md:flag setting -->
|
# : <!-- md:flag --> Default
|
||||||
|
# : <!-- md:flag experimental --> Experimental
|
||||||
|
# : <!-- md:flag required --> Required
|
||||||
|
# : <!-- md:flag customization --> Customization
|
||||||
|
# : <!-- md:flag metadata --> Metadata
|
||||||
|
# : <!-- md:flag dangerous --> Dangerous
|
||||||
|
# : <!-- md:flag multiple --> Multiple
|
||||||
|
# : <!-- md:flag setting --> Setting
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def Badge_Flag_Setting(page: Page, files: Files):
|
def badgeFlagSetting(page: Page, files: Files):
|
||||||
icon = "material-cog"
|
icon = "material-cog"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#setting", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#setting", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Configurable Setting')"
|
icon = f"[:{icon}:]({href} 'Configurable Setting')"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -681,13 +797,13 @@ def Badge_Flag_Setting(page: Page, files: Files):
|
|||||||
# <!-- md:control -->
|
# <!-- md:control -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def icon_control_default( page: Page, files: Files ):
|
def newControlDefault( page: Page, files: Files ):
|
||||||
icon = "aetherx-axs-hand-pointer"
|
icon = "aetherx-axs-hand-pointer"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Type: Textbox')"
|
icon = f"[:{icon}:]({href} 'Type: Textbox')"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -698,13 +814,13 @@ def icon_control_default( page: Page, files: Files ):
|
|||||||
# <!-- md:control textbox -->
|
# <!-- md:control textbox -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def icon_control_textbox( page: Page, files: Files ):
|
def newControlTextbox( page: Page, files: Files ):
|
||||||
icon = "aetherx-axs-input-text"
|
icon = "aetherx-axs-input-text"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Type: Textbox')"
|
icon = f"[:{icon}:]({href} 'Type: Textbox')"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -717,33 +833,33 @@ def icon_control_textbox( page: Page, files: Files ):
|
|||||||
# <!-- md:control toggle_off --> `Disabled`
|
# <!-- md:control toggle_off --> `Disabled`
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def icon_control_toggle( page: Page, files: Files ):
|
def newControlToggle( page: Page, files: Files ):
|
||||||
icon = "aetherx-axs-toggle-large-on"
|
icon = "aetherx-axs-toggle-large-on"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Type: Toggle Switch')"
|
icon = f"[:{icon}:]({href} 'Type: Toggle Switch')"
|
||||||
)
|
)
|
||||||
|
|
||||||
def icon_control_toggle_on( page: Page, files: Files ):
|
def newControlToggleOn( page: Page, files: Files ):
|
||||||
icon = "aetherx-axd-toggle-on"
|
icon = "aetherx-axd-toggle-on"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Toggle: Enabled')"
|
icon = f"[:{icon}:]({href} 'Toggle: Enabled')"
|
||||||
)
|
)
|
||||||
|
|
||||||
def icon_control_toggle_off( page: Page, files: Files ):
|
def newControlToggleOff( page: Page, files: Files ):
|
||||||
icon = "aetherx-axd-toggle-off"
|
icon = "aetherx-axd-toggle-off"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Toggle: Disabled')"
|
icon = f"[:{icon}:]({href} 'Toggle: Disabled')"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -754,13 +870,13 @@ def icon_control_toggle_off( page: Page, files: Files ):
|
|||||||
# <!-- md:control dropdown -->
|
# <!-- md:control dropdown -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def icon_control_dropdown( page: Page, files: Files ):
|
def newControlDropdown( page: Page, files: Files ):
|
||||||
icon = "aetherx-axs-square-caret-down"
|
icon = "aetherx-axs-square-caret-down"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files)
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files)
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Type: Dropdown')"
|
icon = f"[:{icon}:]({href} 'Type: Dropdown')"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -771,13 +887,13 @@ def icon_control_dropdown( page: Page, files: Files ):
|
|||||||
# <!-- md:control button -->
|
# <!-- md:control button -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def icon_control_button( page: Page, files: Files ):
|
def newControlButton( page: Page, files: Files ):
|
||||||
icon = "material-button-pointer"
|
icon = "material-button-pointer"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Type: Button')"
|
icon = f"[:{icon}:]({href} 'Type: Button')"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -788,13 +904,13 @@ def icon_control_button( page: Page, files: Files ):
|
|||||||
# <!-- md:control slider -->
|
# <!-- md:control slider -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def icon_control_slider( page: Page, files: Files ):
|
def newControlSlider( page: Page, files: Files ):
|
||||||
icon = "aetherx-axd-sliders-simple"
|
icon = "aetherx-axd-sliders-simple"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Create_Badge(
|
return badgeCreate(
|
||||||
icon = f"[:{icon}:]({href} 'Type: Slider')"
|
icon = f"[:{icon}:]({href} 'Type: Slider')"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -805,13 +921,49 @@ def icon_control_slider( page: Page, files: Files ):
|
|||||||
# <!-- md:control color #E5E5E5 #121315 -->
|
# <!-- md:control color #E5E5E5 #121315 -->
|
||||||
# #
|
# #
|
||||||
|
|
||||||
def icon_control_color( text: str, page: Page, files: Files ):
|
def newControlColor( text: str, page: Page, files: Files ):
|
||||||
icon = "aetherx-axs-palette"
|
icon = "aetherx-axs-palette"
|
||||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
||||||
|
|
||||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
return Badge_ColorPalette(
|
return badgeColorPalette(
|
||||||
icon = f"[:{icon}:]({href} 'Type: Color Wheel')",
|
icon = f"[:{icon}:]({href} 'Type: Color Wheel')",
|
||||||
type = text
|
type = text
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Icon : Control : Env Variable
|
||||||
|
#
|
||||||
|
# use the following tag in your md file:
|
||||||
|
# <!-- md:control env -->
|
||||||
|
# #
|
||||||
|
|
||||||
|
def newControlEnvVar( page: Page, files: Files ):
|
||||||
|
icon = "aetherx-axd-puzzle-piece"
|
||||||
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
||||||
|
|
||||||
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
|
return badgeCreate(
|
||||||
|
icon = f"[:{icon}:]({href} 'Type: Environment Variable')",
|
||||||
|
type = "env"
|
||||||
|
)
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Icon : Control : Volume
|
||||||
|
#
|
||||||
|
# use the following tag in your md file:
|
||||||
|
# <!-- md:control volume -->
|
||||||
|
# #
|
||||||
|
|
||||||
|
def newControlVolume( page: Page, files: Files ):
|
||||||
|
icon = "aetherx-axd-volume"
|
||||||
|
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
||||||
|
|
||||||
|
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||||
|
|
||||||
|
return badgeCreate(
|
||||||
|
icon = f"[:{icon}:]({href} 'Type: Mountable Volume')",
|
||||||
|
type = "volume"
|
||||||
|
)
|
||||||
|
|||||||
557
docs/mkdocs.yml
@@ -1,262 +1,339 @@
|
|||||||
|
# #
|
||||||
|
# Mkdocs Config
|
||||||
|
#
|
||||||
|
# @notes this documentation requires the following plugins to be installed:
|
||||||
|
# pip install mkdocs
|
||||||
|
# pip install mkdocs-material
|
||||||
|
# pip install mike
|
||||||
|
# pip install mkdocs-git-committers-plugin-2
|
||||||
|
# pip install mkdocs-encryptcontent-plugin
|
||||||
|
# pip install mkdocs-embed-external-markdown
|
||||||
|
# pip install mkdocs-redirects mkdocs-glightbox pymdown-extensions mkdocs-git-revision-date-localized-plugin mkdocs-git-authors-plugin mkdocs-link-embeds-plugin
|
||||||
|
# cd docs
|
||||||
|
# mkdocs build
|
||||||
|
#
|
||||||
|
# @update use the following commands to update mkdocs and the mkdocs-material theme:
|
||||||
|
# pip install --upgrade mkdocs
|
||||||
|
# pip install --upgrade --force-reinstall mkdocs-material
|
||||||
|
# #
|
||||||
|
|
||||||
site_name: !!python/object/apply:os.getenv ["DOCS_NAME", "TVApp2"]
|
site_name: !!python/object/apply:os.getenv ["DOCS_NAME", "TVApp2"]
|
||||||
repo_url: https://github.com/TheBinaryNinja/tvapp2
|
repo_url: https://github.com/TheBinaryNinja/tvapp2
|
||||||
repo_name: TheBinaryNinja/tvapp2
|
repo_name: TheBinaryNinja/tvapp2
|
||||||
edit_uri: edit/main/docs/docs/
|
edit_uri: edit/main/docs/docs/
|
||||||
site_author: TheBinaryNinja
|
site_author: TheBinaryNinja
|
||||||
|
site_url: 'https://thebinaryninja.github.io/tvapp2/'
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Section › Markdown Extensions
|
||||||
|
# #
|
||||||
|
|
||||||
markdown_extensions:
|
markdown_extensions:
|
||||||
- markdown.extensions.extra
|
- pymdownx.critic
|
||||||
- toc:
|
- markdown.extensions.extra
|
||||||
permalink: true
|
- toc:
|
||||||
- abbr
|
permalink: true
|
||||||
- admonition
|
- abbr
|
||||||
- attr_list
|
- admonition
|
||||||
- pymdownx.magiclink:
|
- attr_list
|
||||||
normalize_issue_symbols: true
|
- pymdownx.magiclink:
|
||||||
repo_url_shorthand: true
|
normalize_issue_symbols: true
|
||||||
user: TheBinaryNinja
|
repo_url_shorthand: true
|
||||||
repo: tvapp2
|
user: TheBinaryNinja
|
||||||
- pymdownx.emoji:
|
repo: tvapp2
|
||||||
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
- pymdownx.emoji:
|
||||||
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
||||||
options:
|
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
||||||
custom_icons:
|
options:
|
||||||
- material/overrides/.icons
|
custom_icons:
|
||||||
- md_in_html
|
- material/overrides/.icons
|
||||||
- def_list
|
- md_in_html
|
||||||
- footnotes
|
- def_list
|
||||||
- tables
|
- footnotes
|
||||||
- pymdownx.inlinehilite
|
- tables
|
||||||
- pymdownx.betterem:
|
- pymdownx.inlinehilite
|
||||||
smart_enable: all
|
- pymdownx.betterem:
|
||||||
- pymdownx.tasklist:
|
smart_enable: all
|
||||||
custom_checkbox: true
|
- pymdownx.tasklist:
|
||||||
- pymdownx.highlight:
|
custom_checkbox: true
|
||||||
use_pygments: true
|
- pymdownx.highlight:
|
||||||
anchor_linenums: true
|
use_pygments: true
|
||||||
line_spans: __span
|
anchor_linenums: true
|
||||||
pygments_lang_class: true
|
line_spans: __span
|
||||||
- pymdownx.superfences:
|
pygments_lang_class: true
|
||||||
custom_fences:
|
- pymdownx.superfences:
|
||||||
- name: mermaid
|
custom_fences:
|
||||||
class: mermaid
|
- name: mermaid
|
||||||
format: !!python/name:pymdownx.superfences.fence_code_format
|
class: mermaid
|
||||||
- pymdownx.tabbed:
|
format: !!python/name:pymdownx.superfences.fence_code_format
|
||||||
alternate_style: true
|
- pymdownx.tabbed:
|
||||||
combine_header_slug: true
|
alternate_style: true
|
||||||
slugify: !!python/object/apply:pymdownx.slugs.slugify
|
combine_header_slug: true
|
||||||
kwds:
|
slugify: !!python/object/apply:pymdownx.slugs.slugify
|
||||||
case: lower
|
kwds:
|
||||||
- pymdownx.tabbed
|
case: lower
|
||||||
- pymdownx.caret
|
- pymdownx.tabbed
|
||||||
- pymdownx.mark
|
- pymdownx.caret
|
||||||
- pymdownx.smartsymbols
|
- pymdownx.mark
|
||||||
- pymdownx.tilde
|
- pymdownx.smartsymbols
|
||||||
- pymdownx.blocks.html
|
- pymdownx.tilde
|
||||||
- pymdownx.details
|
- pymdownx.blocks.html
|
||||||
- pymdownx.magiclink:
|
- pymdownx.details
|
||||||
normalize_issue_symbols: true
|
- pymdownx.magiclink:
|
||||||
repo_url_shorthand: true
|
normalize_issue_symbols: true
|
||||||
user: TheBinaryNinja
|
repo_url_shorthand: true
|
||||||
repo: tvapp2
|
user: TheBinaryNinja
|
||||||
- pymdownx.keys
|
repo: tvapp2
|
||||||
- pymdownx.snippets:
|
- pymdownx.keys
|
||||||
auto_append:
|
- pymdownx.snippets:
|
||||||
- includes/abbreviations.md
|
auto_append:
|
||||||
url_download: true
|
- docs/includes/abbreviations.md
|
||||||
- pymdownx.arithmatex:
|
url_download: true
|
||||||
generic: true
|
- pymdownx.arithmatex:
|
||||||
|
generic: true
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Section › Theme
|
||||||
|
# #
|
||||||
|
|
||||||
theme:
|
theme:
|
||||||
highlightjs: true
|
highlightjs: true
|
||||||
hljs_languages:
|
hljs_languages:
|
||||||
- yaml
|
- yaml
|
||||||
- yml
|
- yml
|
||||||
- rust
|
- rust
|
||||||
- markdown
|
- markdown
|
||||||
icon:
|
- json
|
||||||
note: fontawesome/solid/note-sticky
|
- batch
|
||||||
abstract: fontawesome/solid/book
|
- typescript
|
||||||
info: fontawesome/solid/circle-info
|
- javascript
|
||||||
tip: fontawesome/solid/bullhorn
|
- lua
|
||||||
success: fontawesome/solid/check
|
- python
|
||||||
question: fontawesome/solid/circle-question
|
icon:
|
||||||
warning: fontawesome/solid/triangle-exclamation
|
note: fontawesome/solid/note-sticky
|
||||||
failure: fontawesome/solid/bomb
|
abstract: fontawesome/solid/book
|
||||||
danger: fontawesome/solid/skull
|
info: fontawesome/solid/circle-info
|
||||||
bug: fontawesome/solid/robot
|
tip: fontawesome/solid/bullhorn
|
||||||
example: fontawesome/solid/flask
|
success: fontawesome/solid/check
|
||||||
quote: fontawesome/solid/quote-left
|
question: fontawesome/solid/circle-question
|
||||||
annotation: material/arrow-right-circle
|
warning: fontawesome/solid/triangle-exclamation
|
||||||
tag:
|
failure: fontawesome/solid/bomb
|
||||||
html: fontawesome/brands/html5
|
danger: fontawesome/solid/skull
|
||||||
js: fontawesome/brands/js
|
bug: fontawesome/solid/robot
|
||||||
css: fontawesome/brands/css3
|
example: fontawesome/solid/flask
|
||||||
repo: fontawesome/brands/git-alt
|
quote: fontawesome/solid/quote-left
|
||||||
name: material
|
annotation: material/arrow-right-circle
|
||||||
custom_dir: material/overrides
|
hi: aetherx/axs/clock
|
||||||
palette:
|
tag:
|
||||||
# Palette toggle for light mode
|
html: fontawesome/brands/html5
|
||||||
- scheme: default
|
js: fontawesome/brands/js
|
||||||
primary: custom
|
css: fontawesome/brands/css3
|
||||||
accent: indigo
|
repo: fontawesome/brands/git-alt
|
||||||
toggle:
|
name: material
|
||||||
icon: material/brightness-7
|
custom_dir: material/overrides
|
||||||
name: Switch to dark mode
|
palette:
|
||||||
|
# Palette toggle for light mode
|
||||||
|
- scheme: default
|
||||||
|
primary: custom
|
||||||
|
accent: indigo
|
||||||
|
toggle:
|
||||||
|
icon: material/brightness-7
|
||||||
|
name: Switch to dark mode
|
||||||
|
|
||||||
# Palette toggle for dark mode
|
# Palette toggle for dark mode
|
||||||
- scheme: main
|
- scheme: main
|
||||||
primary: custom
|
primary: custom
|
||||||
accent: custom
|
accent: custom
|
||||||
toggle:
|
toggle:
|
||||||
icon: material/brightness-4
|
icon: material/brightness-4
|
||||||
name: Switch to light mode
|
name: Switch to light mode
|
||||||
font:
|
font:
|
||||||
text: Roboto
|
text: Roboto
|
||||||
code: Roboto Mono
|
code: Roboto Mono
|
||||||
favicon: assets/favicon.png
|
favicon: assets/favicon.png
|
||||||
icon:
|
icon:
|
||||||
logo: logo
|
logo: /aetherx/axd/tv
|
||||||
features:
|
features:
|
||||||
- announce.dismiss
|
- navigation.tabs
|
||||||
- toc.follow
|
- navigation.sections
|
||||||
- content.action.edit
|
- announce.dismiss
|
||||||
- content.action.view
|
- toc.follow
|
||||||
- content.tooltips
|
- content.action.edit
|
||||||
- search.highlight
|
- content.action.view
|
||||||
- search.share
|
- content.tooltips
|
||||||
- search.suggest
|
- search.highlight
|
||||||
- content.code.annotate
|
- search.share
|
||||||
- content.code.select
|
- search.suggest
|
||||||
- content.code.copy
|
- content.code.annotate
|
||||||
- navigation.footer
|
- content.code.select
|
||||||
- navigation.indexes
|
- content.code.copy
|
||||||
- navigation.instant
|
- navigation.footer
|
||||||
- navigation.instant.progress
|
- navigation.indexes
|
||||||
- navigation.instant.prefetch
|
- navigation.instant
|
||||||
- navigation.instant.preview
|
- navigation.instant.progress
|
||||||
- navigation.tracking
|
- navigation.instant.prefetch
|
||||||
- navigation.path
|
- navigation.instant.preview
|
||||||
- navigation.top
|
- navigation.tracking
|
||||||
|
- navigation.path
|
||||||
|
- navigation.top
|
||||||
|
# #
|
||||||
|
# Section › Hooks
|
||||||
|
# #
|
||||||
|
|
||||||
# Hooks
|
|
||||||
hooks:
|
hooks:
|
||||||
- material/overrides/hooks/shortcodes.py
|
- material/overrides/hooks/shortcodes.py
|
||||||
- material/overrides/hooks/translations.py
|
- material/overrides/hooks/translations.py
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Section › Extra › CSS
|
||||||
|
# #
|
||||||
|
|
||||||
extra_css:
|
extra_css:
|
||||||
- stylesheets/extra.css?v1.000
|
- stylesheets/extra.css?v1.000
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Section › Extra › Javascript
|
||||||
|
# #
|
||||||
|
|
||||||
extra_javascript:
|
extra_javascript:
|
||||||
- https://unpkg.com/tablesort@5.3.0/dist/tablesort.min.js
|
- https://unpkg.com/tablesort@5.3.0/dist/tablesort.min.js
|
||||||
- javascripts/tablesort.js
|
- javascripts/tablesort.js
|
||||||
nav:
|
|
||||||
- Home: 'home.md'
|
|
||||||
- About TVApp2: 'about_tvapp2.md'
|
|
||||||
- About:
|
|
||||||
- License: 'about/license.md'
|
|
||||||
- Conventions: 'about/conventions.md'
|
|
||||||
- Tags: 'about/tags.md'
|
|
||||||
- Changelog: 'about/changelog.md'
|
|
||||||
- Backers: 'backers/index.md'
|
|
||||||
|
|
||||||
plugins:
|
# #
|
||||||
- search:
|
# Section › Extras
|
||||||
separator: '[\s\u200b\-_,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])'
|
# #
|
||||||
- tags:
|
|
||||||
tags_file: about/tags.md
|
|
||||||
- group:
|
|
||||||
plugins:
|
|
||||||
- optimize
|
|
||||||
- minify
|
|
||||||
- git-committers:
|
|
||||||
repository: TheBinaryNinja/tvapp2
|
|
||||||
docs_path: docs/docs/
|
|
||||||
branch: main
|
|
||||||
token: !!python/object/apply:os.getenv [GH_TOKEN, "NULL"]
|
|
||||||
- blog:
|
|
||||||
authors: true
|
|
||||||
authors_file: .authors.yml
|
|
||||||
- encryptcontent:
|
|
||||||
title_prefix: '[🔒]'
|
|
||||||
summary: 'Access Restricted'
|
|
||||||
placeholder: 'Authentication Code'
|
|
||||||
placeholder_user: User
|
|
||||||
password_button: True
|
|
||||||
password_button_text: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" fill="currentColor" width="16px" height="16px"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><defs><style>.fa-secondary{opacity:.4}</style></defs><path class="fa-primary" d="M384 160L224 0V128c0 17.7 14.3 32 32 32H384zm80 80c17.7 0 32 14.3 32 32v48H432V272c0-17.7 14.3-32 32-32zm-80 32v48c-17.7 0-32 14.3-32 32V480c0 17.7 14.3 32 32 32H544c17.7 0 32-14.3 32-32V352c0-17.7-14.3-32-32-32V272c0-44.2-35.8-80-80-80s-80 35.8-80 80z"></path><path class="fa-secondary" d="M0 64C0 28.7 28.7 0 64 0H224V128c0 17.7 14.3 32 32 32H384v33.6c-19.8 20.2-32 47.9-32 78.4v24.6c-19.1 11.1-32 31.7-32 55.4V480c0 11.4 3 22.2 8.3 31.5c-2.7 .3-5.5 .5-8.3 .5H64c-35.3 0-64-28.7-64-64V64z"></path></svg>'
|
|
||||||
# input_class: 'w3-input' # CSS class used for input username and password
|
|
||||||
# button_class: 'w3-button w3-theme-l1 w3-hover-theme' # CSS class for password_button
|
|
||||||
decryption_failure_message: 'Authentication code not correct.'
|
|
||||||
encryption_info_message: "This information is restricted to certain users with access."
|
|
||||||
password_inventory:
|
|
||||||
classified:
|
|
||||||
- !!python/object/apply:os.getenv [DOCS_SECRET_L1, "NULL"]
|
|
||||||
confidential:
|
|
||||||
- !!python/object/apply:os.getenv [DOCS_SECRET_L2, "NULL"]
|
|
||||||
- git-revision-date-localized:
|
|
||||||
type: timeago
|
|
||||||
enabled: true
|
|
||||||
- git-authors:
|
|
||||||
show_contribution: true
|
|
||||||
sort_authors_by: name
|
|
||||||
exclude:
|
|
||||||
- index.md
|
|
||||||
enabled: true
|
|
||||||
- glightbox:
|
|
||||||
touchNavigation: true
|
|
||||||
loop: false
|
|
||||||
effect: zoom
|
|
||||||
slide_effect: slide
|
|
||||||
width: 100%
|
|
||||||
height: auto
|
|
||||||
zoomable: true
|
|
||||||
draggable: false
|
|
||||||
skip_classes:
|
|
||||||
- custom-skip-class-name
|
|
||||||
auto_caption: false
|
|
||||||
caption_position: bottom
|
|
||||||
background: black
|
|
||||||
shadow: false
|
|
||||||
- mike:
|
|
||||||
alias_type: symlink
|
|
||||||
redirect_template: null
|
|
||||||
deploy_prefix: ''
|
|
||||||
canonical_version: null
|
|
||||||
version_selector: true
|
|
||||||
css_dir: css
|
|
||||||
javascript_dir: js
|
|
||||||
- redirects:
|
|
||||||
redirect_maps:
|
|
||||||
docs/settings/summary.md: settings/summary.md
|
|
||||||
- link-embeds:
|
|
||||||
enabled: true
|
|
||||||
name_default: "Untitled Link"
|
|
||||||
desc_default: "No description found"
|
|
||||||
image_default: "https://github.com/Aetherinox/mkdocs-link-embeds/assets/118329232/c0298d98-0910-4235-a88f-0c3e2f704ba7"
|
|
||||||
image_disabled: false
|
|
||||||
favicon_default: "https://github.com/Aetherinox/mkdocs-link-embeds/assets/118329232/b37da9c6-6f17-4c3f-9c94-c346a6f31bfa"
|
|
||||||
favicon_disabled: true
|
|
||||||
favicon_size: 25
|
|
||||||
target: "blank"
|
|
||||||
accent: "FFFFFF1A"
|
|
||||||
verbose: true
|
|
||||||
|
|
||||||
extra:
|
extra:
|
||||||
tags:
|
social:
|
||||||
HTML5: html
|
- icon: fontawesome/brands/github
|
||||||
JavaScript: js
|
link: https://github.com/TheBinaryNinja/tvapp2
|
||||||
CSS: css
|
- icon: fontawesome/brands/discord
|
||||||
generator: false
|
link: https://discord.gg/gTze6hRe
|
||||||
version:
|
tags:
|
||||||
default: stable
|
HTML5: html
|
||||||
provider: mike
|
JavaScript: js
|
||||||
consent:
|
CSS: css
|
||||||
title: Cookie Consent
|
generator: false
|
||||||
description: >-
|
version:
|
||||||
We use cookies to recognize your repeated visits and preferences, as well
|
default: latest
|
||||||
as to measure the effectiveness of our documentation and whether users
|
provider: mike
|
||||||
find what they're searching for. With your consent, you're helping us to
|
alias: true
|
||||||
make our documentation better.
|
consent:
|
||||||
|
title: Cookie Consent
|
||||||
|
description: >-
|
||||||
|
We use cookies to recognize your repeated visits and preferences, as well
|
||||||
|
as to measure the effectiveness of our documentation and whether users
|
||||||
|
find what they're searching for. With your consent, you're helping us to
|
||||||
|
make our documentation better.
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Section › Navigation
|
||||||
|
# #
|
||||||
|
|
||||||
|
nav:
|
||||||
|
- Home: 'home.md'
|
||||||
|
- About:
|
||||||
|
- What Is TVApp2: 'about/what_is_tvapp.md'
|
||||||
|
- Contributing: 'about/contributing.md'
|
||||||
|
- License: 'about/license.md'
|
||||||
|
- Wiki:
|
||||||
|
- Conventions: 'about/conventions.md'
|
||||||
|
- Tags: 'about/tags.md'
|
||||||
|
- Install:
|
||||||
|
- Getting Started: 'install/index.md'
|
||||||
|
- docker run: 'install/docker-run.md'
|
||||||
|
- docker compose: 'install/docker-compose.md'
|
||||||
|
- Config:
|
||||||
|
- Environment Variables: 'config/env.md'
|
||||||
|
- Volumes: 'config/volumes.md'
|
||||||
|
- Usage:
|
||||||
|
- Healthcheck: 'usage/healthcheck.md'
|
||||||
|
- Changelog: 'about/changelog.md'
|
||||||
|
- Discord: 'https://discord.gg/gTze6hRe'
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Section › Plugins
|
||||||
|
# #
|
||||||
|
|
||||||
|
plugins:
|
||||||
|
- search:
|
||||||
|
separator: '[\s\u200b\-_,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])'
|
||||||
|
- group:
|
||||||
|
plugins:
|
||||||
|
- optimize
|
||||||
|
- minify
|
||||||
|
- git-committers:
|
||||||
|
repository: TheBinaryNinja/tvapp2
|
||||||
|
docs_path: docs/docs/
|
||||||
|
branch: main
|
||||||
|
token: !!python/object/apply:os.getenv [GH_TOKEN, "NULL"]
|
||||||
|
- blog:
|
||||||
|
authors: true
|
||||||
|
authors_file: .authors.yml
|
||||||
|
- encryptcontent:
|
||||||
|
title_prefix: '[🔒]'
|
||||||
|
summary: 'Access Restricted'
|
||||||
|
placeholder: 'Authentication Code'
|
||||||
|
placeholder_user: User
|
||||||
|
password_button: True
|
||||||
|
password_button_text: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" fill="currentColor" width="16px" height="16px"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><defs><style>.fa-secondary{opacity:.4}</style></defs><path class="fa-primary" d="M384 160L224 0V128c0 17.7 14.3 32 32 32H384zm80 80c17.7 0 32 14.3 32 32v48H432V272c0-17.7 14.3-32 32-32zm-80 32v48c-17.7 0-32 14.3-32 32V480c0 17.7 14.3 32 32 32H544c17.7 0 32-14.3 32-32V352c0-17.7-14.3-32-32-32V272c0-44.2-35.8-80-80-80s-80 35.8-80 80z"></path><path class="fa-secondary" d="M0 64C0 28.7 28.7 0 64 0H224V128c0 17.7 14.3 32 32 32H384v33.6c-19.8 20.2-32 47.9-32 78.4v24.6c-19.1 11.1-32 31.7-32 55.4V480c0 11.4 3 22.2 8.3 31.5c-2.7 .3-5.5 .5-8.3 .5H64c-35.3 0-64-28.7-64-64V64z"></path></svg>'
|
||||||
|
# input_class: 'w3-input' # CSS class used for input username and password
|
||||||
|
# button_class: 'w3-button w3-theme-l1 w3-hover-theme' # CSS class for password_button
|
||||||
|
decryption_failure_message: 'Authentication code not correct.'
|
||||||
|
encryption_info_message: "This information is restricted to certain users with access."
|
||||||
|
password_inventory:
|
||||||
|
classified:
|
||||||
|
- !!python/object/apply:os.getenv [DOCS_SECRET_L1, "NULL"]
|
||||||
|
confidential:
|
||||||
|
- !!python/object/apply:os.getenv [DOCS_SECRET_L2, "NULL"]
|
||||||
|
- git-revision-date-localized:
|
||||||
|
type: timeago
|
||||||
|
enabled: true
|
||||||
|
- git-authors:
|
||||||
|
show_contribution: true
|
||||||
|
sort_authors_by: name
|
||||||
|
exclude:
|
||||||
|
- index.md
|
||||||
|
enabled: true
|
||||||
|
- glightbox:
|
||||||
|
touchNavigation: true
|
||||||
|
loop: false
|
||||||
|
effect: zoom
|
||||||
|
slide_effect: slide
|
||||||
|
width: 100%
|
||||||
|
height: auto
|
||||||
|
zoomable: true
|
||||||
|
draggable: false
|
||||||
|
skip_classes:
|
||||||
|
- custom-skip-class-name
|
||||||
|
auto_caption: false
|
||||||
|
caption_position: bottom
|
||||||
|
background: black
|
||||||
|
shadow: false
|
||||||
|
- mike:
|
||||||
|
alias_type: symlink
|
||||||
|
redirect_template: null
|
||||||
|
deploy_prefix: ''
|
||||||
|
canonical_version: null
|
||||||
|
version_selector: true
|
||||||
|
css_dir: css
|
||||||
|
javascript_dir: js
|
||||||
|
- redirects:
|
||||||
|
redirect_maps:
|
||||||
|
docs/settings/summary.md: settings/summary.md
|
||||||
|
- link-embeds:
|
||||||
|
enabled: true
|
||||||
|
name_default: "Untitled Link"
|
||||||
|
desc_default: "No description found"
|
||||||
|
image_default: "https://github.com/Aetherinox/mkdocs-link-embeds/assets/118329232/c0298d98-0910-4235-a88f-0c3e2f704ba7"
|
||||||
|
image_disabled: false
|
||||||
|
favicon_default: "https://github.com/Aetherinox/mkdocs-link-embeds/assets/118329232/b37da9c6-6f17-4c3f-9c94-c346a6f31bfa"
|
||||||
|
favicon_disabled: false
|
||||||
|
favicon_size: 25
|
||||||
|
target: "blank"
|
||||||
|
accent: "FFFFFF1A"
|
||||||
|
verbose: true
|
||||||
|
- external-markdown
|
||||||
|
|
||||||
copyright: >
|
copyright: >
|
||||||
Copyright © 2025 - BinaryNinja
|
Copyright © 2025 - BinaryNinja
|
||||||
|
|||||||
@@ -6,15 +6,19 @@ MODE con:cols=125 lines=120
|
|||||||
MODE 125,40
|
MODE 125,40
|
||||||
GOTO comment_end
|
GOTO comment_end
|
||||||
|
|
||||||
Starts up mkdocs from a windows system.
|
@usage Starts up mkdocs from a windows system.
|
||||||
Ensure you have defined `GH_TOKEN` or the git-committers plugin will rate limit you.
|
Ensure you have defined `GH_TOKEN` or the git-committers plugin will rate limit you.
|
||||||
|
|
||||||
setx /m GH_TOKEN "github_pat_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
setx /m GH_TOKEN "github_pat_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||||
|
|
||||||
If using a Github Workflow, create a new secret in the repo settings named `GH_TOKEN`
|
If using a Github Workflow, create a new secret in the repo settings named `GH_TOKEN`
|
||||||
and give it your Github fine-grained personal access token.
|
and give it your Github fine-grained personal access token.
|
||||||
|
|
||||||
The token variable is defined in mkdocs.yml
|
The token variable is defined in mkdocs.yml
|
||||||
|
|
||||||
|
@update use the following commands to update mkdocs and the mkdocs-material theme:
|
||||||
|
pip install --upgrade mkdocs
|
||||||
|
pip install --upgrade --force-reinstall mkdocs-material
|
||||||
|
|
||||||
:comment_end
|
:comment_end
|
||||||
|
|
||||||
@@ -30,28 +34,33 @@ set dir_home=%~dp0
|
|||||||
:: define: env variable
|
:: define: env variable
|
||||||
:: #
|
:: #
|
||||||
|
|
||||||
set TOKEN=%GH_TOKEN2%
|
echo ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
echo --------------------------------------------------------------------------------
|
|
||||||
echo Mkdocs Launcher
|
echo Mkdocs Launcher
|
||||||
echo --------------------------------------------------------------------------------
|
echo ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
IF [!TOKEN!]==[] (
|
|
||||||
echo --------------------------------------------------------------------------------
|
|
||||||
echo GH_TOKEN not defined. Open %0%
|
|
||||||
echo Create a new one at https://github.com/settings/personal-access-tokens
|
|
||||||
echo --------------------------------------------------------------------------------
|
|
||||||
set /P TOKEN= Enter Github Personal Access Token (fine-grained):
|
|
||||||
|
|
||||||
|
IF "!GH_TOKEN!"=="" (
|
||||||
|
echo GH_TOKEN not defined.
|
||||||
|
echo Open %0%
|
||||||
|
echo Create a new one at:
|
||||||
|
echo https://github.com/settings/personal-access-tokens
|
||||||
|
echo ------------------------------------------------------------------------------------------------
|
||||||
|
set /p TOKEN=" Enter Github Personal Access Token (fine-grained): "
|
||||||
)
|
)
|
||||||
|
|
||||||
echo GH_TOKEN: !TOKEN!
|
echo GH_TOKEN: !GH_TOKEN!
|
||||||
echo.
|
echo.
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
|
echo Creating environment variable GH_TOKEN
|
||||||
|
setx GH_TOKEN "!GH_TOKEN!"
|
||||||
|
|
||||||
|
timeout 2 > NUL
|
||||||
|
|
||||||
:: #
|
:: #
|
||||||
:: start mkdocs
|
:: start mkdocs
|
||||||
:: #
|
:: #
|
||||||
|
|
||||||
echo Starting mkdocs ...
|
echo Starting mkdocs ...
|
||||||
start cmd /k "mkdocs serve --clean"
|
start cmd /k "mkdocs serve --clean"
|
||||||
|
|
||||||
|
timeout 5 > NUL
|
||||||
|
|||||||
@@ -9,10 +9,80 @@
|
|||||||
# @repo.3 https://github.com/aetherinox/docker-base-alpine
|
# @repo.3 https://github.com/aetherinox/docker-base-alpine
|
||||||
# #
|
# #
|
||||||
|
|
||||||
|
# #
|
||||||
|
# define > colors
|
||||||
|
#
|
||||||
|
# Use the color table at:
|
||||||
|
# - https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
|
||||||
|
# #
|
||||||
|
|
||||||
|
declare -A c=(
|
||||||
|
[end]=$'\e[0m'
|
||||||
|
[white]=$'\e[97m'
|
||||||
|
[bold]=$'\e[1m'
|
||||||
|
[dim]=$'\e[2m'
|
||||||
|
[underline]=$'\e[4m'
|
||||||
|
[strike]=$'\e[9m'
|
||||||
|
[blink]=$'\e[5m'
|
||||||
|
[inverted]=$'\e[7m'
|
||||||
|
[hidden]=$'\e[8m'
|
||||||
|
[black]=$'\e[0;30m'
|
||||||
|
[redl]=$'\e[0;91m'
|
||||||
|
[redd]=$'\e[0;31m'
|
||||||
|
[magental]=$'\e[0;95m'
|
||||||
|
[magentad]=$'\e[0;35mm'
|
||||||
|
[bluel]=$'\e[0;94m'
|
||||||
|
[blued]=$'\e[0;34m'
|
||||||
|
[cyanl]=$'\e[0;96m'
|
||||||
|
[cyand]=$'\e[0;36m'
|
||||||
|
[greenl]=$'\e[0;92m'
|
||||||
|
[greend]=$'\e[0;32m'
|
||||||
|
[yellowl]=$'\e[0;93m'
|
||||||
|
[yellowd]=$'\e[0;33m'
|
||||||
|
[greyl]=$'\e[0;37m'
|
||||||
|
[greyd]=$'\e[0;90m'
|
||||||
|
[navy]=$'\e[38;5;62m'
|
||||||
|
[olive]=$'\e[38;5;144m'
|
||||||
|
[peach]=$'\e[38;5;210m'
|
||||||
|
)
|
||||||
|
|
||||||
|
# #
|
||||||
|
# unicode for emojis
|
||||||
|
# https://apps.timwhitlock.info/emoji/tables/unicode
|
||||||
|
# #
|
||||||
|
|
||||||
|
declare -A icon=(
|
||||||
|
["symbolic link"]=$'\xF0\x9F\x94\x97' # 🔗
|
||||||
|
["regular file"]=$'\xF0\x9F\x93\x84' # 📄
|
||||||
|
["directory"]=$'\xF0\x9F\x93\x81' # 📁
|
||||||
|
["regular empty file"]=$'\xe2\xad\x95' # ⭕
|
||||||
|
["log"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["1"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["2"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["3"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["4"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["5"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["pem"]=$'\xF0\x9F\x94\x92' # 🔑
|
||||||
|
["pub"]=$'\xF0\x9F\x94\x91' # 🔒
|
||||||
|
["pfx"]=$'\xF0\x9F\x94\x92' # 🔑
|
||||||
|
["p12"]=$'\xF0\x9F\x94\x92' # 🔑
|
||||||
|
["key"]=$'\xF0\x9F\x94\x91' # 🔒
|
||||||
|
["crt"]=$'\xF0\x9F\xAA\xAA ' # 🪪
|
||||||
|
["gz"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["zip"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["gzip"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["deb"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["sh"]=$'\xF0\x9F\x97\x94' # 🗔
|
||||||
|
)
|
||||||
|
|
||||||
|
# #
|
||||||
|
# define > general
|
||||||
|
# #
|
||||||
|
|
||||||
PLUGINS_PATH="/config/www/plugins"
|
PLUGINS_PATH="/config/www/plugins"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Plugins > Start
|
# Plugins > Start
|
||||||
# #
|
# #
|
||||||
|
|
||||||
echo -e " Loader : Checking tvapp2-plugins"
|
printf '%-29s %-65s\n' " ${c[bluel]}Loader${c[end]}" "${c[end]}Checking tvapp2-plugins${c[end]}"
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
echo -e " Core : Completed loading container"
|
echo -e " Completed loading container"
|
||||||
|
|||||||
@@ -1,35 +1,160 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
#!/usr/bin/with-contenv bash
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
# #
|
||||||
|
# defaults
|
||||||
|
# #
|
||||||
|
|
||||||
PUID=${PUID:-911}
|
PUID=${PUID:-911}
|
||||||
PGID=${PGID:-911}
|
PGID=${PGID:-911}
|
||||||
|
DIR_BUILD=${DIR_BUILD:-/usr/src/app}
|
||||||
|
DIR_RUN=${DIR_RUN:-/usr/bin/app}
|
||||||
|
bHasError=false
|
||||||
|
|
||||||
|
# #
|
||||||
|
# define > colors
|
||||||
|
#
|
||||||
|
# Use the color table at:
|
||||||
|
# - https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
|
||||||
|
# #
|
||||||
|
|
||||||
|
declare -A c=(
|
||||||
|
[end]=$'\e[0m'
|
||||||
|
[white]=$'\e[97m'
|
||||||
|
[bold]=$'\e[1m'
|
||||||
|
[dim]=$'\e[2m'
|
||||||
|
[underline]=$'\e[4m'
|
||||||
|
[strike]=$'\e[9m'
|
||||||
|
[blink]=$'\e[5m'
|
||||||
|
[inverted]=$'\e[7m'
|
||||||
|
[hidden]=$'\e[8m'
|
||||||
|
[black]=$'\e[0;30m'
|
||||||
|
[redl]=$'\e[0;91m'
|
||||||
|
[redd]=$'\e[0;31m'
|
||||||
|
[magental]=$'\e[0;95m'
|
||||||
|
[magentad]=$'\e[0;35mm'
|
||||||
|
[bluel]=$'\e[0;94m'
|
||||||
|
[blued]=$'\e[0;34m'
|
||||||
|
[cyanl]=$'\e[0;96m'
|
||||||
|
[cyand]=$'\e[0;36m'
|
||||||
|
[greenl]=$'\e[0;92m'
|
||||||
|
[greend]=$'\e[0;32m'
|
||||||
|
[yellowl]=$'\e[0;93m'
|
||||||
|
[yellowd]=$'\e[0;33m'
|
||||||
|
[greyl]=$'\e[0;37m'
|
||||||
|
[greyd]=$'\e[0;90m'
|
||||||
|
[navy]=$'\e[38;5;62m'
|
||||||
|
[olive]=$'\e[38;5;144m'
|
||||||
|
[peach]=$'\e[38;5;210m'
|
||||||
|
)
|
||||||
|
|
||||||
|
# #
|
||||||
|
# unicode for emojis
|
||||||
|
# https://apps.timwhitlock.info/emoji/tables/unicode
|
||||||
|
# #
|
||||||
|
|
||||||
|
declare -A icon=(
|
||||||
|
["symbolic link"]=$'\xF0\x9F\x94\x97' # 🔗
|
||||||
|
["regular file"]=$'\xF0\x9F\x93\x84' # 📄
|
||||||
|
["directory"]=$'\xF0\x9F\x93\x81' # 📁
|
||||||
|
["regular empty file"]=$'\xe2\xad\x95' # ⭕
|
||||||
|
["log"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["1"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["2"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["3"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["4"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["5"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["pem"]=$'\xF0\x9F\x94\x92' # 🔑
|
||||||
|
["pub"]=$'\xF0\x9F\x94\x91' # 🔒
|
||||||
|
["pfx"]=$'\xF0\x9F\x94\x92' # 🔑
|
||||||
|
["p12"]=$'\xF0\x9F\x94\x92' # 🔑
|
||||||
|
["key"]=$'\xF0\x9F\x94\x91' # 🔒
|
||||||
|
["crt"]=$'\xF0\x9F\xAA\xAA ' # 🪪
|
||||||
|
["gz"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["zip"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["gzip"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["deb"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["sh"]=$'\xF0\x9F\x97\x94' # 🗔
|
||||||
|
)
|
||||||
|
|
||||||
|
# #
|
||||||
|
# get container ips
|
||||||
|
# #
|
||||||
|
|
||||||
IP_GATEWAY=$(/sbin/ip route|awk '/default/ { print $3 }')
|
IP_GATEWAY=$(/sbin/ip route|awk '/default/ { print $3 }')
|
||||||
IP_CONTAINER=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1')
|
IP_CONTAINER=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1')
|
||||||
|
|
||||||
|
# #
|
||||||
|
# usermod
|
||||||
|
# -o, --non-unique allow using duplicate (non-unique) UID
|
||||||
|
# -g, --gid GROUP force use GROUP as new primary group
|
||||||
|
# -G, --groups GROUPS new list of supplementary GROUPS
|
||||||
|
# -u, --uid UID new UID for the user account
|
||||||
|
# -U, --unlock unlock the user account
|
||||||
|
#
|
||||||
|
# groupmod
|
||||||
|
# -g, --gid GID change the group ID to GID
|
||||||
|
# -o, --non-unique allow to use a duplicate (non-unique) GID
|
||||||
|
# #
|
||||||
|
|
||||||
if [[ -z ${TVAPP_READ_ONLY_FS} ]] && [[ -z ${TVAPP_NON_ROOT_USER} ]]; then
|
if [[ -z ${TVAPP_READ_ONLY_FS} ]] && [[ -z ${TVAPP_NON_ROOT_USER} ]]; then
|
||||||
groupmod -o -g "$PGID" dockerx
|
groupmod -o -g "$PGID" dockerx
|
||||||
usermod -o -u "$PUID" dockerx
|
usermod -o -u "$PUID" dockerx
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if { [[ -z ${TVAPP_READ_ONLY_FS} ]] && [[ -z ${TVAPP_NON_ROOT_USER} ]]; } || [[ ! ${TVAPP_FIRST_PARTY} = "true" ]]; then
|
# #
|
||||||
cat /etc/s6-overlay/s6-rc.d/init-adduser/branding
|
# s6 > branding
|
||||||
else
|
# #
|
||||||
cat /run/branding
|
|
||||||
fi
|
printf '%-1s\n' " ${c[greyd]}──────────────────────────────────────────────────────────────────────────────────────────${c[end]}"
|
||||||
|
printf '%-1s\n' " ${c[greyd]} TVApp2 Docker Image${c[end]}"
|
||||||
|
printf '%-1s\n' " ${c[greyd]}──────────────────────────────────────────────────────────────────────────────────────────${c[end]}"
|
||||||
|
|
||||||
|
printf '%-2s\n' " ${c[greyd]}The TvApp2 image allows you to fetch M3U playlist and EPG data for numerous IPTV ${c[end]}"
|
||||||
|
printf '%-2s\n' " ${c[greyd]}services online. ${c[end]}"
|
||||||
|
echo -e
|
||||||
|
printf '%-2s\n' " ${c[greyd]}Once the files are fetched by the image, you can visit the self-hosted webpage, copy ${c[end]}"
|
||||||
|
printf '%-2s\n' " ${c[greyd]}the links to the M3U and EPG files; and add them to your favorite IPTV app such as ${c[end]}"
|
||||||
|
printf '%-2s\n' " ${c[greyd]}Jellyfin, Plex, or Emby. ${c[end]}"
|
||||||
|
echo -e
|
||||||
|
printf '%-2s\n' " ${c[greyd]}For more information about this project; visit the links below. This app is served on ${c[end]}"
|
||||||
|
printf '%-2s\n' " ${c[greyd]}multiple repositories as backup. Use any of the repo links below: ${c[end]}"
|
||||||
|
echo -e
|
||||||
|
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}TVApp2 Repo 1${c[end]}" "${c[end]}https://github.com/TheBinaryNinja/tvapp2 ${c[end]}"
|
||||||
|
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}TVApp2 Repo 2${c[end]}" "${c[end]}https://git.binaryninja.net/BinaryNinja/tvapp2 ${c[end]}"
|
||||||
|
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}Base Alpine Image${c[end]}" "${c[end]}https://github.com/Aetherinox/docker-base-alpine ${c[end]}"
|
||||||
|
echo -e
|
||||||
|
|
||||||
|
printf '%-2s\n' " ${c[greyd]}If you are making this container available on a public-facing domain, please consider ${c[end]}"
|
||||||
|
printf '%-2s\n' " ${c[greyd]}using Traefik and Authentik to protect this container from outside access. Your M3U ${c[end]}"
|
||||||
|
printf '%-2s\n' " ${c[greyd]}and EPG files will be available for the public to download and use. ${c[end]}"
|
||||||
|
|
||||||
|
# if { [[ -z ${TVAPP_READ_ONLY_FS} ]] && [[ -z ${TVAPP_NON_ROOT_USER} ]]; } || [[ ! ${TVAPP_FIRST_PARTY} = "true" ]]; then
|
||||||
|
# cat /etc/s6-overlay/s6-rc.d/init-adduser/branding
|
||||||
|
# else
|
||||||
|
# cat /run/branding
|
||||||
|
# fi
|
||||||
|
|
||||||
|
# #
|
||||||
|
# branding > non-root user
|
||||||
|
# #
|
||||||
|
|
||||||
if [[ -z ${TVAPP_NON_ROOT_USER} ]]; then
|
if [[ -z ${TVAPP_NON_ROOT_USER} ]]; then
|
||||||
echo ""
|
echo -e
|
||||||
echo " User:Group $(id -u dockerx):$(id -g dockerx)"
|
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}User:Group${c[end]}" "${c[end]}$(id -u dockerx):$(id -g dockerx)${c[end]}"
|
||||||
else
|
else
|
||||||
echo " User:Group $(stat /run -c %u):$(stat /run -c %g)"
|
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}User:Group${c[end]}" "${c[end]}$(stat /run -c %u):$(stat /run -c %g)${c[end]}"
|
||||||
fi
|
fi
|
||||||
echo " Port(s) $(echo $WEB_PORT)"
|
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}Port(s)${c[end]}" "${c[end]}$(echo $WEB_PORT)${c[end]}"
|
||||||
echo " Gateway $(echo $IP_GATEWAY)"
|
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}Gateway${c[end]}" "${c[end]}$(echo $IP_GATEWAY)${c[end]}"
|
||||||
echo " Web Server $(echo $IP_CONTAINER:$WEB_PORT)"
|
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}Web Server${c[end]}" "${c[end]}$(echo $IP_CONTAINER:$WEB_PORT)${c[end]}"
|
||||||
echo " App Folder $(echo $DIR_RUN)"
|
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}App Folder${c[end]}" "${c[end]}$(echo $DIR_RUN)${c[end]}"
|
||||||
echo ""
|
echo -e
|
||||||
echo '──────────────────────────────────────────────────────────────────────────────────────────'
|
printf '%-1s\n' " ${c[greyd]}──────────────────────────────────────────────────────────────────────────────────────────${c[end]}"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# set permissions
|
||||||
|
# #
|
||||||
|
|
||||||
if [[ -z ${TVAPP_READ_ONLY_FS} ]] && [[ -z ${TVAPP_NON_ROOT_USER} ]]; then
|
if [[ -z ${TVAPP_READ_ONLY_FS} ]] && [[ -z ${TVAPP_NON_ROOT_USER} ]]; then
|
||||||
aetherxown dockerx:dockerx /app
|
aetherxown dockerx:dockerx /app
|
||||||
|
|||||||
@@ -1,22 +1,88 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
#!/usr/bin/with-contenv bash
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
# #
|
||||||
|
# define > colors
|
||||||
|
#
|
||||||
|
# Use the color table at:
|
||||||
|
# - https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
|
||||||
|
# #
|
||||||
|
|
||||||
|
declare -A c=(
|
||||||
|
[end]=$'\e[0m'
|
||||||
|
[white]=$'\e[97m'
|
||||||
|
[bold]=$'\e[1m'
|
||||||
|
[dim]=$'\e[2m'
|
||||||
|
[underline]=$'\e[4m'
|
||||||
|
[strike]=$'\e[9m'
|
||||||
|
[blink]=$'\e[5m'
|
||||||
|
[inverted]=$'\e[7m'
|
||||||
|
[hidden]=$'\e[8m'
|
||||||
|
[black]=$'\e[0;30m'
|
||||||
|
[redl]=$'\e[0;91m'
|
||||||
|
[redd]=$'\e[0;31m'
|
||||||
|
[magental]=$'\e[0;95m'
|
||||||
|
[magentad]=$'\e[0;35mm'
|
||||||
|
[bluel]=$'\e[0;94m'
|
||||||
|
[blued]=$'\e[0;34m'
|
||||||
|
[cyanl]=$'\e[0;96m'
|
||||||
|
[cyand]=$'\e[0;36m'
|
||||||
|
[greenl]=$'\e[0;92m'
|
||||||
|
[greend]=$'\e[0;32m'
|
||||||
|
[yellowl]=$'\e[0;93m'
|
||||||
|
[yellowd]=$'\e[0;33m'
|
||||||
|
[greyl]=$'\e[0;37m'
|
||||||
|
[greyd]=$'\e[0;90m'
|
||||||
|
[navy]=$'\e[38;5;62m'
|
||||||
|
[olive]=$'\e[38;5;144m'
|
||||||
|
[peach]=$'\e[38;5;210m'
|
||||||
|
)
|
||||||
|
|
||||||
|
# #
|
||||||
|
# unicode for emojis
|
||||||
|
# https://apps.timwhitlock.info/emoji/tables/unicode
|
||||||
|
# #
|
||||||
|
|
||||||
|
declare -A icon=(
|
||||||
|
["symbolic link"]=$'\xF0\x9F\x94\x97' # 🔗
|
||||||
|
["regular file"]=$'\xF0\x9F\x93\x84' # 📄
|
||||||
|
["directory"]=$'\xF0\x9F\x93\x81' # 📁
|
||||||
|
["regular empty file"]=$'\xe2\xad\x95' # ⭕
|
||||||
|
["log"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["1"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["2"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["3"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["4"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["5"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["pem"]=$'\xF0\x9F\x94\x92' # 🔑
|
||||||
|
["pub"]=$'\xF0\x9F\x94\x91' # 🔒
|
||||||
|
["pfx"]=$'\xF0\x9F\x94\x92' # 🔑
|
||||||
|
["p12"]=$'\xF0\x9F\x94\x92' # 🔑
|
||||||
|
["key"]=$'\xF0\x9F\x94\x91' # 🔒
|
||||||
|
["crt"]=$'\xF0\x9F\xAA\xAA ' # 🪪
|
||||||
|
["gz"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["zip"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["gzip"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["deb"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["sh"]=$'\xF0\x9F\x97\x94' # 🗔
|
||||||
|
)
|
||||||
|
|
||||||
# Directories
|
# Directories
|
||||||
SCRIPTS_DIR="/custom-cont-init.d"
|
SCRIPTS_DIR="/custom-cont-init.d"
|
||||||
|
|
||||||
# Make sure custom init directory exists and has files in it
|
# Make sure custom init directory exists and has files in it
|
||||||
if [[ -e "${SCRIPTS_DIR}" ]] && [[ -n "$(/bin/ls -A ${SCRIPTS_DIR} 2>/dev/null)" ]]; then
|
if [[ -e "${SCRIPTS_DIR}" ]] && [[ -n "$(/bin/ls -A ${SCRIPTS_DIR} 2>/dev/null)" ]]; then
|
||||||
echo -e " Loader : Plugins found, loading them ..."
|
printf '%-29s %-65s\n' " ${c[bluel]}Loader${c[end]}" "${c[end]}Loading any found plugins${c[end]}"
|
||||||
for SCRIPT in "${SCRIPTS_DIR}"/*; do
|
for SCRIPT in "${SCRIPTS_DIR}"/*; do
|
||||||
NAME="$(basename "${SCRIPT}")"
|
NAME="$(basename "${SCRIPT}")"
|
||||||
if [[ -f "${SCRIPT}" ]]; then
|
if [[ -f "${SCRIPT}" ]]; then
|
||||||
echo -e " Loader : Executing ..."
|
printf '%-29s %-65s\n' " ${c[bluel]}Loader${c[end]}" "${c[end]}Executing${c[end]}"
|
||||||
/bin/bash "${SCRIPT}"
|
/bin/bash "${SCRIPT}"
|
||||||
echo -e " Loader : ${NAME}: Ran Successfully with code [$?]"
|
printf '%-29s %-65s\n' " ${c[bluel]}Loader${c[end]}" "${c[end]}Successfully ran with code ${c[bluel]}[$?]${c[end]}"
|
||||||
elif [[ ! -f "${SCRIPT}" ]]; then
|
elif [[ ! -f "${SCRIPT}" ]]; then
|
||||||
echo -e " Loader : ${NAME}: Not a valid file"
|
printf '%-29s %-65s\n' " ${c[bluel]}Loader${c[end]}" "${c[end]}${c[bluel]}${NAME}${c[end]} is not a valid file${c[end]}"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
echo -e " Loader : No Plugins found, skipping..."
|
printf '%-29s %-65s\n' " ${c[bluel]}Loader${c[end]}" "${c[end]}No plugins found; skipping${c[end]}"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,12 +1,190 @@
|
|||||||
#!/usr/bin/with-contenv sh
|
#!/usr/bin/with-contenv bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
# #
|
||||||
|
# defaults
|
||||||
|
# #
|
||||||
|
|
||||||
|
PUID=${PUID:-911}
|
||||||
|
PGID=${PGID:-911}
|
||||||
|
DIR_BUILD=${DIR_BUILD:-/usr/src/app}
|
||||||
|
DIR_RUN=${DIR_RUN:-/usr/bin/app}
|
||||||
|
bHasError=false
|
||||||
|
|
||||||
|
# #
|
||||||
|
# define > colors
|
||||||
|
#
|
||||||
|
# Use the color table at:
|
||||||
|
# - https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
|
||||||
|
# #
|
||||||
|
|
||||||
|
declare -A c=(
|
||||||
|
[end]=$'\e[0m'
|
||||||
|
[white]=$'\e[97m'
|
||||||
|
[bold]=$'\e[1m'
|
||||||
|
[dim]=$'\e[2m'
|
||||||
|
[underline]=$'\e[4m'
|
||||||
|
[strike]=$'\e[9m'
|
||||||
|
[blink]=$'\e[5m'
|
||||||
|
[inverted]=$'\e[7m'
|
||||||
|
[hidden]=$'\e[8m'
|
||||||
|
[black]=$'\e[0;30m'
|
||||||
|
[redl]=$'\e[0;91m'
|
||||||
|
[redd]=$'\e[0;31m'
|
||||||
|
[magental]=$'\e[0;95m'
|
||||||
|
[magentad]=$'\e[0;35mm'
|
||||||
|
[bluel]=$'\e[0;94m'
|
||||||
|
[blued]=$'\e[0;34m'
|
||||||
|
[cyanl]=$'\e[0;96m'
|
||||||
|
[cyand]=$'\e[0;36m'
|
||||||
|
[greenl]=$'\e[0;92m'
|
||||||
|
[greend]=$'\e[0;32m'
|
||||||
|
[yellowl]=$'\e[0;93m'
|
||||||
|
[yellowd]=$'\e[0;33m'
|
||||||
|
[greyl]=$'\e[0;37m'
|
||||||
|
[greyd]=$'\e[0;90m'
|
||||||
|
[navy]=$'\e[38;5;62m'
|
||||||
|
[olive]=$'\e[38;5;144m'
|
||||||
|
[peach]=$'\e[38;5;210m'
|
||||||
|
)
|
||||||
|
|
||||||
|
# #
|
||||||
|
# unicode for emojis
|
||||||
|
# https://apps.timwhitlock.info/emoji/tables/unicode
|
||||||
|
# #
|
||||||
|
|
||||||
|
declare -A icon=(
|
||||||
|
["symbolic link"]=$'\xF0\x9F\x94\x97' # 🔗
|
||||||
|
["regular file"]=$'\xF0\x9F\x93\x84' # 📄
|
||||||
|
["directory"]=$'\xF0\x9F\x93\x81' # 📁
|
||||||
|
["regular empty file"]=$'\xe2\xad\x95' # ⭕
|
||||||
|
["log"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["1"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["2"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["3"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["4"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["5"]=$'\xF0\x9F\x93\x9C' # 📜
|
||||||
|
["pem"]=$'\xF0\x9F\x94\x92' # 🔑
|
||||||
|
["pub"]=$'\xF0\x9F\x94\x91' # 🔒
|
||||||
|
["pfx"]=$'\xF0\x9F\x94\x92' # 🔑
|
||||||
|
["p12"]=$'\xF0\x9F\x94\x92' # 🔑
|
||||||
|
["key"]=$'\xF0\x9F\x94\x91' # 🔒
|
||||||
|
["crt"]=$'\xF0\x9F\xAA\xAA ' # 🪪
|
||||||
|
["gz"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["zip"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["gzip"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["deb"]=$'\xF0\x9F\x93\xA6' # 📦
|
||||||
|
["sh"]=$'\xF0\x9F\x97\x94' # 🗔
|
||||||
|
)
|
||||||
|
|
||||||
|
# #
|
||||||
|
# define > system
|
||||||
|
# #
|
||||||
|
|
||||||
|
sys_os_ver="1.0.0"
|
||||||
|
sys_os_name="Unknown"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# s6 > store env variables
|
||||||
|
# #
|
||||||
|
|
||||||
|
printf '%-29s %-65s\n' " ${c[bluel]}STATUS${c[end]}" "${c[end]}Fetching docker container and gateway addresses${c[end]}"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# get container ips
|
||||||
|
# #
|
||||||
|
|
||||||
|
ip_gateway=$(/sbin/ip route|awk '/default/ { print $3 }')
|
||||||
|
ip_container=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1')
|
||||||
|
|
||||||
|
if [ -d "/var/run/s6/container_environment/" ]; then
|
||||||
|
printf "$ip_gateway" > /var/run/s6/container_environment/IP_GATEWAY
|
||||||
|
printf "$ip_container" > /var/run/s6/container_environment/IP_CONTAINER
|
||||||
|
else
|
||||||
|
printf '%-29s %-65s\n' " ${c[redl]}ERROR${c[end]}" "${c[end]}Cannot generate s6-overlay env files; folder ${c[redl]}/var/run/s6/container_environment/${c[end]} does not exist${c[end]}"
|
||||||
|
bHasError=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# #
|
||||||
|
# s6 > export env vars
|
||||||
|
# #
|
||||||
|
|
||||||
|
export IP_GATEWAY=$ip_gateway
|
||||||
|
export IP_GATEWAY=$ip_container
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# install and startup for tvapp2
|
# install and startup for tvapp2
|
||||||
# #
|
# #
|
||||||
|
|
||||||
cp -r ${DIR_BUILD}/* ${DIR_RUN}
|
printf '%-29s %-65s\n' " ${c[bluel]}STATUS${c[end]}" "${c[end]}Copying ${c[bluel]}${DIR_BUILD}${c[end]} to ${c[bluel]}${DIR_RUN}${c[end]}"
|
||||||
rm -rf ${DIR_BUILD}/*
|
if [ -z "${DIR_BUILD}" ]; then
|
||||||
cd ${DIR_RUN}
|
printf '%-29s %-65s\n' " ${c[redl]}ERROR${c[end]}" "${c[end]}Cannot copy; env var ${c[redl]}\${DIR_BUILD}${c[end]} missing${c[end]}"
|
||||||
npm install --omit=dev
|
bHasError=true
|
||||||
npm start
|
else
|
||||||
|
if [ -d "${DIR_BUILD}/" ]; then
|
||||||
|
cp -r ${DIR_BUILD}/* ${DIR_RUN}
|
||||||
|
else
|
||||||
|
printf '%-29s %-65s\n' " ${c[redl]}ERROR${c[end]}" "${c[end]}Cannot copy folder ${c[redl]}${DIR_BUILD}${c[end]} to ${c[redl]}${DIR_RUN}${c[end]}; build folder ${c[redl]}${DIR_BUILD}${c[end]} does not exist${c[end]}"
|
||||||
|
bHasError=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# #
|
||||||
|
# remove build directory
|
||||||
|
# #
|
||||||
|
|
||||||
|
printf '%-29s %-65s\n' " ${c[bluel]}STATUS${c[end]}" "${c[end]}Remove ${c[bluel]}${DIR_BUILD}/${c[end]}"
|
||||||
|
if [ -z "${DIR_BUILD}" ]; then
|
||||||
|
printf '%-29s %-65s\n' " ${c[redl]}ERROR${c[end]}" "${c[end]}Cannot remove; env var ${c[redl]}\${DIR_BUILD}${c[end]} missing${c[end]}"
|
||||||
|
else
|
||||||
|
if [ -d "${DIR_BUILD}" ]; then
|
||||||
|
rm -rf "${DIR_BUILD}/"
|
||||||
|
else
|
||||||
|
printf '%-29s %-65s\n' " ${c[redl]}ERROR${c[end]}" "${c[end]}Cannot remove; build folder ${c[redl]}${DIR_BUILD}${c[end]} does not exist. Restart the container to re-initialize build folder.${c[end]}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# #
|
||||||
|
# cd to BUILD_RUN directory
|
||||||
|
# #
|
||||||
|
|
||||||
|
printf '%-29s %-65s\n' " ${c[bluel]}STATUS${c[end]}" "${c[end]}Changing to run directory ${c[bluel]}${DIR_RUN}/${c[end]}"
|
||||||
|
if [ -z "${DIR_RUN}" ]; then
|
||||||
|
printf '%-29s %-65s\n' " ${c[redl]}ERROR${c[end]}" "${c[end]}Cannot cd; env var ${c[redl]}\${DIR_RUN}${c[end]} missing${c[end]}"
|
||||||
|
bHasError=true
|
||||||
|
else
|
||||||
|
if [ -d "${DIR_RUN}" ]; then
|
||||||
|
cd ${DIR_RUN}
|
||||||
|
else
|
||||||
|
printf '%-29s %-65s\n' " ${c[redl]}ERROR${c[end]}" "${c[end]}Cannot cd; run folder ${c[redl]}${DIR_RUN}${c[end]} does not exist${c[end]}"
|
||||||
|
bHasError=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# #
|
||||||
|
# install tvapp2 via npm
|
||||||
|
# #
|
||||||
|
|
||||||
|
printf '%-29s %-65s\n' " ${c[bluel]}STATUS${c[end]}" "${c[end]}Running command ${c[bluel]}npm install --omit=dev${c[end]}"
|
||||||
|
if ! command -v npm; then
|
||||||
|
printf '%-29s %-65s\n' " ${c[redl]}ERROR${c[end]}" "${c[end]}Cannot install TVApp2 with npm because package ${c[redl]}npm${c[end]} not installed${c[end]}"
|
||||||
|
bHasError=true
|
||||||
|
else
|
||||||
|
npm install --omit=dev
|
||||||
|
|
||||||
|
printf '%-29s %-65s\n' " ${c[bluel]}STATUS${c[end]}" "${c[end]}Running command ${c[bluel]}npm start${c[end]}"
|
||||||
|
npm start
|
||||||
|
fi
|
||||||
|
|
||||||
|
# #
|
||||||
|
# finished run script
|
||||||
|
# #
|
||||||
|
|
||||||
|
printf '%-29s %-65s\n' " ${c[greenl]}OK${c[end]}" "${c[end]}Finished initializing script${c[end]}"
|
||||||
|
if [ "$bHasError" = true ] ; then
|
||||||
|
printf '%-29s %-65s\n' "" ""
|
||||||
|
printf '%-29s %-65s\n' " ${c[redl]}ERROR${c[end]}" "${c[end]}Fatal errors were detected${c[end]}"
|
||||||
|
printf '%-29s %-65s\n' " ${c[redl]}${c[end]}" "${c[end]}The run script detected that certain steps failed. This app may not${c[end]}"
|
||||||
|
printf '%-29s %-65s\n' " ${c[redl]}${c[end]}" "${c[end]}work properly. Try restarting the container.${c[end]}"
|
||||||
|
printf '%-29s %-65s\n' "" ""
|
||||||
|
fi
|
||||||
|
|||||||
@@ -58,17 +58,20 @@ const compat = new FlatCompat({
|
|||||||
|
|
||||||
export default
|
export default
|
||||||
[
|
[
|
||||||
...compat.extends('eslint:recommended'),
|
|
||||||
{
|
{
|
||||||
ignores: [
|
ignores: [
|
||||||
'coverage/**',
|
'coverage/**',
|
||||||
'node_modules/**',
|
'node_modules/**',
|
||||||
'**/node_modules/**',
|
|
||||||
'**/dist/**/*',
|
'**/dist/**/*',
|
||||||
'**/__tmp__/**/*',
|
'**/__tmp__/**/*',
|
||||||
'eslint.config.cjs'
|
'eslint.config.mjs',
|
||||||
],
|
'eslint.config.cjs',
|
||||||
files: ['index.js'],
|
"root.js",
|
||||||
|
"www/**/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...compat.extends('eslint:recommended'),
|
||||||
|
{
|
||||||
plugins: {
|
plugins: {
|
||||||
'n': pluginNode,
|
'n': pluginNode,
|
||||||
'import': pluginImport,
|
'import': pluginImport,
|
||||||
@@ -266,17 +269,5 @@ export default
|
|||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
},
|
|
||||||
{
|
|
||||||
files: ['root.js'],
|
|
||||||
languageOptions: {
|
|
||||||
sourceType: 'module',
|
|
||||||
ecmaVersion: 'latest',
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
'no-console': 'off',
|
|
||||||
'no-undef': 'off',
|
|
||||||
'no-var': 'off'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
1632
tvapp2/index.js
3837
tvapp2/node_modules/.package-lock.json
generated
vendored
34
tvapp2/node_modules/playwright-core/browsers.json
generated
vendored
@@ -3,31 +3,43 @@
|
|||||||
"browsers": [
|
"browsers": [
|
||||||
{
|
{
|
||||||
"name": "chromium",
|
"name": "chromium",
|
||||||
"revision": "1155",
|
"revision": "1169",
|
||||||
"installByDefault": true,
|
"installByDefault": true,
|
||||||
"browserVersion": "133.0.6943.16"
|
"browserVersion": "136.0.7103.25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "chromium-headless-shell",
|
||||||
|
"revision": "1169",
|
||||||
|
"installByDefault": true,
|
||||||
|
"browserVersion": "136.0.7103.25"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "chromium-tip-of-tree",
|
"name": "chromium-tip-of-tree",
|
||||||
"revision": "1293",
|
"revision": "1320",
|
||||||
"installByDefault": false,
|
"installByDefault": false,
|
||||||
"browserVersion": "133.0.6943.0"
|
"browserVersion": "137.0.7105.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "chromium-tip-of-tree-headless-shell",
|
||||||
|
"revision": "1320",
|
||||||
|
"installByDefault": false,
|
||||||
|
"browserVersion": "137.0.7105.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "firefox",
|
"name": "firefox",
|
||||||
"revision": "1471",
|
"revision": "1482",
|
||||||
"installByDefault": true,
|
"installByDefault": true,
|
||||||
"browserVersion": "134.0"
|
"browserVersion": "137.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "firefox-beta",
|
"name": "firefox-beta",
|
||||||
"revision": "1467",
|
"revision": "1477",
|
||||||
"installByDefault": false,
|
"installByDefault": false,
|
||||||
"browserVersion": "133.0b9"
|
"browserVersion": "137.0b2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "webkit",
|
"name": "webkit",
|
||||||
"revision": "2123",
|
"revision": "2158",
|
||||||
"installByDefault": true,
|
"installByDefault": true,
|
||||||
"revisionOverrides": {
|
"revisionOverrides": {
|
||||||
"debian11-x64": "2105",
|
"debian11-x64": "2105",
|
||||||
@@ -38,10 +50,12 @@
|
|||||||
"mac11-arm64": "1816",
|
"mac11-arm64": "1816",
|
||||||
"mac12": "2009",
|
"mac12": "2009",
|
||||||
"mac12-arm64": "2009",
|
"mac12-arm64": "2009",
|
||||||
|
"mac13": "2140",
|
||||||
|
"mac13-arm64": "2140",
|
||||||
"ubuntu20.04-x64": "2092",
|
"ubuntu20.04-x64": "2092",
|
||||||
"ubuntu20.04-arm64": "2092"
|
"ubuntu20.04-arm64": "2092"
|
||||||
},
|
},
|
||||||
"browserVersion": "18.2"
|
"browserVersion": "18.4"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ffmpeg",
|
"name": "ffmpeg",
|
||||||
|
|||||||
1
tvapp2/node_modules/playwright-core/index.js
generated
vendored
@@ -19,7 +19,6 @@ const semver = currentNodeVersion.split('.');
|
|||||||
const [major] = [+semver[0]];
|
const [major] = [+semver[0]];
|
||||||
|
|
||||||
if (major < minimumMajorNodeVersion) {
|
if (major < minimumMajorNodeVersion) {
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error(
|
console.error(
|
||||||
'You are running Node.js ' +
|
'You are running Node.js ' +
|
||||||
currentNodeVersion +
|
currentNodeVersion +
|
||||||
|
|||||||
90
tvapp2/node_modules/playwright-core/lib/androidServerImpl.js
generated
vendored
@@ -1,69 +1,63 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var androidServerImpl_exports = {};
|
||||||
|
__export(androidServerImpl_exports, {
|
||||||
|
AndroidServerLauncherImpl: () => AndroidServerLauncherImpl
|
||||||
});
|
});
|
||||||
exports.AndroidServerLauncherImpl = void 0;
|
module.exports = __toCommonJS(androidServerImpl_exports);
|
||||||
var _utilsBundle = require("./utilsBundle");
|
var import_playwrightServer = require("./remote/playwrightServer");
|
||||||
var _utils = require("./utils");
|
var import_playwright = require("./server/playwright");
|
||||||
var _playwright = require("./server/playwright");
|
var import_crypto = require("./server/utils/crypto");
|
||||||
var _playwrightServer = require("./remote/playwrightServer");
|
var import_utilsBundle = require("./utilsBundle");
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class AndroidServerLauncherImpl {
|
class AndroidServerLauncherImpl {
|
||||||
async launchServer(options = {}) {
|
async launchServer(options = {}) {
|
||||||
const playwright = (0, _playwright.createPlaywright)({
|
const playwright = (0, import_playwright.createPlaywright)({ sdkLanguage: "javascript", isServer: true });
|
||||||
sdkLanguage: 'javascript',
|
|
||||||
isServer: true
|
|
||||||
});
|
|
||||||
// 1. Pre-connect to the device
|
|
||||||
let devices = await playwright.android.devices({
|
let devices = await playwright.android.devices({
|
||||||
host: options.adbHost,
|
host: options.adbHost,
|
||||||
port: options.adbPort,
|
port: options.adbPort,
|
||||||
omitDriverInstall: options.omitDriverInstall
|
omitDriverInstall: options.omitDriverInstall
|
||||||
});
|
});
|
||||||
if (devices.length === 0) throw new Error('No devices found');
|
if (devices.length === 0)
|
||||||
|
throw new Error("No devices found");
|
||||||
if (options.deviceSerialNumber) {
|
if (options.deviceSerialNumber) {
|
||||||
devices = devices.filter(d => d.serial === options.deviceSerialNumber);
|
devices = devices.filter((d) => d.serial === options.deviceSerialNumber);
|
||||||
if (devices.length === 0) throw new Error(`No device with serial number '${options.deviceSerialNumber}' was found`);
|
if (devices.length === 0)
|
||||||
|
throw new Error(`No device with serial number '${options.deviceSerialNumber}' was found`);
|
||||||
}
|
}
|
||||||
if (devices.length > 1) throw new Error(`More than one device found. Please specify deviceSerialNumber`);
|
if (devices.length > 1)
|
||||||
|
throw new Error(`More than one device found. Please specify deviceSerialNumber`);
|
||||||
const device = devices[0];
|
const device = devices[0];
|
||||||
const path = options.wsPath ? options.wsPath.startsWith('/') ? options.wsPath : `/${options.wsPath}` : `/${(0, _utils.createGuid)()}`;
|
const path = options.wsPath ? options.wsPath.startsWith("/") ? options.wsPath : `/${options.wsPath}` : `/${(0, import_crypto.createGuid)()}`;
|
||||||
|
const server = new import_playwrightServer.PlaywrightServer({ mode: "launchServer", path, maxConnections: 1, preLaunchedAndroidDevice: device });
|
||||||
// 2. Start the server
|
|
||||||
const server = new _playwrightServer.PlaywrightServer({
|
|
||||||
mode: 'launchServer',
|
|
||||||
path,
|
|
||||||
maxConnections: 1,
|
|
||||||
preLaunchedAndroidDevice: device
|
|
||||||
});
|
|
||||||
const wsEndpoint = await server.listen(options.port, options.host);
|
const wsEndpoint = await server.listen(options.port, options.host);
|
||||||
|
const browserServer = new import_utilsBundle.ws.EventEmitter();
|
||||||
// 3. Return the BrowserServer interface
|
|
||||||
const browserServer = new _utilsBundle.ws.EventEmitter();
|
|
||||||
browserServer.wsEndpoint = () => wsEndpoint;
|
browserServer.wsEndpoint = () => wsEndpoint;
|
||||||
browserServer.close = () => device.close();
|
browserServer.close = () => device.close();
|
||||||
browserServer.kill = () => device.close();
|
browserServer.kill = () => device.close();
|
||||||
device.on('close', () => {
|
device.on("close", () => {
|
||||||
server.close();
|
server.close();
|
||||||
browserServer.emit('close');
|
browserServer.emit("close");
|
||||||
});
|
});
|
||||||
return browserServer;
|
return browserServer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.AndroidServerLauncherImpl = AndroidServerLauncherImpl;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
AndroidServerLauncherImpl
|
||||||
|
});
|
||||||
|
|||||||
122
tvapp2/node_modules/playwright-core/lib/browserServerImpl.js
generated
vendored
@@ -1,74 +1,57 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var browserServerImpl_exports = {};
|
||||||
|
__export(browserServerImpl_exports, {
|
||||||
|
BrowserServerLauncherImpl: () => BrowserServerLauncherImpl
|
||||||
});
|
});
|
||||||
exports.BrowserServerLauncherImpl = void 0;
|
module.exports = __toCommonJS(browserServerImpl_exports);
|
||||||
var _utilsBundle = require("./utilsBundle");
|
var import_socksProxy = require("./server/utils/socksProxy");
|
||||||
var _clientHelper = require("./client/clientHelper");
|
var import_playwrightServer = require("./remote/playwrightServer");
|
||||||
var _utils = require("./utils");
|
var import_helper = require("./server/helper");
|
||||||
var _instrumentation = require("./server/instrumentation");
|
var import_instrumentation = require("./server/instrumentation");
|
||||||
var _playwright = require("./server/playwright");
|
var import_playwright = require("./server/playwright");
|
||||||
var _playwrightServer = require("./remote/playwrightServer");
|
var import_crypto = require("./server/utils/crypto");
|
||||||
var _helper = require("./server/helper");
|
var import_stackTrace = require("./utils/isomorphic/stackTrace");
|
||||||
var _stackTrace = require("./utils/stackTrace");
|
var import_utilsBundle = require("./utilsBundle");
|
||||||
var _socksProxy = require("./common/socksProxy");
|
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class BrowserServerLauncherImpl {
|
class BrowserServerLauncherImpl {
|
||||||
constructor(browserName) {
|
constructor(browserName) {
|
||||||
this._browserName = void 0;
|
|
||||||
this._browserName = browserName;
|
this._browserName = browserName;
|
||||||
}
|
}
|
||||||
async launchServer(options = {}) {
|
async launchServer(options = {}) {
|
||||||
const playwright = (0, _playwright.createPlaywright)({
|
const playwright = (0, import_playwright.createPlaywright)({ sdkLanguage: "javascript", isServer: true });
|
||||||
sdkLanguage: 'javascript',
|
const socksProxy = false ? new SocksProxy() : void 0;
|
||||||
isServer: true
|
playwright.options.socksProxyPort = await socksProxy?.listen(0);
|
||||||
});
|
const metadata = (0, import_instrumentation.serverSideCallMetadata)();
|
||||||
// TODO: enable socks proxy once ipv6 is supported.
|
|
||||||
const socksProxy = false ? new _socksProxy.SocksProxy() : undefined;
|
|
||||||
playwright.options.socksProxyPort = await (socksProxy === null || socksProxy === void 0 ? void 0 : socksProxy.listen(0));
|
|
||||||
|
|
||||||
// 1. Pre-launch the browser
|
|
||||||
const metadata = (0, _instrumentation.serverSideCallMetadata)();
|
|
||||||
const browser = await playwright[this._browserName].launch(metadata, {
|
const browser = await playwright[this._browserName].launch(metadata, {
|
||||||
...options,
|
...options,
|
||||||
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
|
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : void 0,
|
||||||
ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
|
ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
|
||||||
env: options.env ? (0, _clientHelper.envObjectToArray)(options.env) : undefined
|
env: options.env ? envObjectToArray(options.env) : void 0
|
||||||
}, toProtocolLogger(options.logger)).catch(e => {
|
}, toProtocolLogger(options.logger)).catch((e) => {
|
||||||
const log = _helper.helper.formatBrowserLogs(metadata.log);
|
const log = import_helper.helper.formatBrowserLogs(metadata.log);
|
||||||
(0, _stackTrace.rewriteErrorMessage)(e, `${e.message} Failed to launch browser.${log}`);
|
(0, import_stackTrace.rewriteErrorMessage)(e, `${e.message} Failed to launch browser.${log}`);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
const path = options.wsPath ? options.wsPath.startsWith('/') ? options.wsPath : `/${options.wsPath}` : `/${(0, _utils.createGuid)()}`;
|
const path = options.wsPath ? options.wsPath.startsWith("/") ? options.wsPath : `/${options.wsPath}` : `/${(0, import_crypto.createGuid)()}`;
|
||||||
|
const server = new import_playwrightServer.PlaywrightServer({ mode: "launchServer", path, maxConnections: Infinity, preLaunchedBrowser: browser, preLaunchedSocksProxy: socksProxy });
|
||||||
// 2. Start the server
|
|
||||||
const server = new _playwrightServer.PlaywrightServer({
|
|
||||||
mode: 'launchServer',
|
|
||||||
path,
|
|
||||||
maxConnections: Infinity,
|
|
||||||
preLaunchedBrowser: browser,
|
|
||||||
preLaunchedSocksProxy: socksProxy
|
|
||||||
});
|
|
||||||
const wsEndpoint = await server.listen(options.port, options.host);
|
const wsEndpoint = await server.listen(options.port, options.host);
|
||||||
|
const browserServer = new import_utilsBundle.ws.EventEmitter();
|
||||||
// 3. Return the BrowserServer interface
|
|
||||||
const browserServer = new _utilsBundle.ws.EventEmitter();
|
|
||||||
browserServer.process = () => browser.options.browserProcess.process;
|
browserServer.process = () => browser.options.browserProcess.process;
|
||||||
browserServer.wsEndpoint = () => wsEndpoint;
|
browserServer.wsEndpoint = () => wsEndpoint;
|
||||||
browserServer.close = () => browser.options.browserProcess.close();
|
browserServer.close = () => browser.options.browserProcess.close();
|
||||||
@@ -77,16 +60,29 @@ class BrowserServerLauncherImpl {
|
|||||||
browserServer._disconnectForTest = () => server.close();
|
browserServer._disconnectForTest = () => server.close();
|
||||||
browserServer._userDataDirForTest = browser._userDataDirForTest;
|
browserServer._userDataDirForTest = browser._userDataDirForTest;
|
||||||
browser.options.browserProcess.onclose = (exitCode, signal) => {
|
browser.options.browserProcess.onclose = (exitCode, signal) => {
|
||||||
socksProxy === null || socksProxy === void 0 || socksProxy.close().catch(() => {});
|
socksProxy?.close().catch(() => {
|
||||||
|
});
|
||||||
server.close();
|
server.close();
|
||||||
browserServer.emit('close', exitCode, signal);
|
browserServer.emit("close", exitCode, signal);
|
||||||
};
|
};
|
||||||
return browserServer;
|
return browserServer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.BrowserServerLauncherImpl = BrowserServerLauncherImpl;
|
|
||||||
function toProtocolLogger(logger) {
|
function toProtocolLogger(logger) {
|
||||||
return logger ? (direction, message) => {
|
return logger ? (direction, message) => {
|
||||||
if (logger.isEnabled('protocol', 'verbose')) logger.log('protocol', 'verbose', (direction === 'send' ? 'SEND ► ' : '◀ RECV ') + JSON.stringify(message), [], {});
|
if (logger.isEnabled("protocol", "verbose"))
|
||||||
} : undefined;
|
logger.log("protocol", "verbose", (direction === "send" ? "SEND \u25BA " : "\u25C0 RECV ") + JSON.stringify(message), [], {});
|
||||||
|
} : void 0;
|
||||||
}
|
}
|
||||||
|
function envObjectToArray(env) {
|
||||||
|
const result = [];
|
||||||
|
for (const name in env) {
|
||||||
|
if (!Object.is(env[name], void 0))
|
||||||
|
result.push({ name, value: String(env[name]) });
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
BrowserServerLauncherImpl
|
||||||
|
});
|
||||||
|
|||||||
138
tvapp2/node_modules/playwright-core/lib/cli/driver.js
generated
vendored
@@ -1,95 +1,97 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __create = Object.create;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __defProp = Object.defineProperty;
|
||||||
value: true
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __getProtoOf = Object.getPrototypeOf;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||||
|
// If the importer is in node compatibility mode or this is not an ESM
|
||||||
|
// file that has been converted to a CommonJS file using a Babel-
|
||||||
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||||
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||||
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||||
|
mod
|
||||||
|
));
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var driver_exports = {};
|
||||||
|
__export(driver_exports, {
|
||||||
|
launchBrowserServer: () => launchBrowserServer,
|
||||||
|
printApiJson: () => printApiJson,
|
||||||
|
runDriver: () => runDriver,
|
||||||
|
runServer: () => runServer
|
||||||
});
|
});
|
||||||
exports.launchBrowserServer = launchBrowserServer;
|
module.exports = __toCommonJS(driver_exports);
|
||||||
exports.printApiJson = printApiJson;
|
var import_fs = __toESM(require("fs"));
|
||||||
exports.runDriver = runDriver;
|
var playwright = __toESM(require("../.."));
|
||||||
exports.runServer = runServer;
|
var import_pipeTransport = require("../server/utils/pipeTransport");
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
var import_playwrightServer = require("../remote/playwrightServer");
|
||||||
var playwright = _interopRequireWildcard(require("../.."));
|
var import_server = require("../server");
|
||||||
var _server = require("../server");
|
var import_processLauncher = require("../server/utils/processLauncher");
|
||||||
var _transport = require("../protocol/transport");
|
|
||||||
var _playwrightServer = require("../remote/playwrightServer");
|
|
||||||
var _processLauncher = require("../utils/processLauncher");
|
|
||||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
||||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* eslint-disable no-console */
|
|
||||||
|
|
||||||
function printApiJson() {
|
function printApiJson() {
|
||||||
// Note: this file is generated by build-playwright-driver.sh
|
console.log(JSON.stringify(require("../../api.json")));
|
||||||
console.log(JSON.stringify(require('../../api.json')));
|
|
||||||
}
|
}
|
||||||
function runDriver() {
|
function runDriver() {
|
||||||
const dispatcherConnection = new _server.DispatcherConnection();
|
const dispatcherConnection = new import_server.DispatcherConnection();
|
||||||
new _server.RootDispatcher(dispatcherConnection, async (rootScope, {
|
new import_server.RootDispatcher(dispatcherConnection, async (rootScope, { sdkLanguage }) => {
|
||||||
sdkLanguage
|
const playwright2 = (0, import_server.createPlaywright)({ sdkLanguage });
|
||||||
}) => {
|
return new import_server.PlaywrightDispatcher(rootScope, playwright2);
|
||||||
const playwright = (0, _server.createPlaywright)({
|
|
||||||
sdkLanguage
|
|
||||||
});
|
|
||||||
return new _server.PlaywrightDispatcher(rootScope, playwright);
|
|
||||||
});
|
});
|
||||||
const transport = new _transport.PipeTransport(process.stdout, process.stdin);
|
const transport = new import_pipeTransport.PipeTransport(process.stdout, process.stdin);
|
||||||
transport.onmessage = message => dispatcherConnection.dispatch(JSON.parse(message));
|
transport.onmessage = (message) => dispatcherConnection.dispatch(JSON.parse(message));
|
||||||
// Certain Language Binding JSON parsers (e.g. .NET) do not like strings with lone surrogates.
|
const isJavaScriptLanguageBinding = !process.env.PW_LANG_NAME || process.env.PW_LANG_NAME === "javascript";
|
||||||
const isJavaScriptLanguageBinding = !process.env.PW_LANG_NAME || process.env.PW_LANG_NAME === 'javascript';
|
|
||||||
const replacer = !isJavaScriptLanguageBinding && String.prototype.toWellFormed ? (key, value) => {
|
const replacer = !isJavaScriptLanguageBinding && String.prototype.toWellFormed ? (key, value) => {
|
||||||
if (typeof value === 'string') return value.toWellFormed();
|
if (typeof value === "string")
|
||||||
|
return value.toWellFormed();
|
||||||
return value;
|
return value;
|
||||||
} : undefined;
|
} : void 0;
|
||||||
dispatcherConnection.onmessage = message => transport.send(JSON.stringify(message, replacer));
|
dispatcherConnection.onmessage = (message) => transport.send(JSON.stringify(message, replacer));
|
||||||
transport.onclose = () => {
|
transport.onclose = () => {
|
||||||
// Drop any messages during shutdown on the floor.
|
dispatcherConnection.onmessage = () => {
|
||||||
dispatcherConnection.onmessage = () => {};
|
};
|
||||||
(0, _processLauncher.gracefullyProcessExitDoNotHang)(0);
|
(0, import_processLauncher.gracefullyProcessExitDoNotHang)(0);
|
||||||
};
|
};
|
||||||
// Ignore the SIGINT signal in the driver process so the parent can gracefully close the connection.
|
process.on("SIGINT", () => {
|
||||||
// We still will destruct everything (close browsers and exit) when the transport pipe closes.
|
|
||||||
process.on('SIGINT', () => {
|
|
||||||
// Keep the process running.
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async function runServer(options) {
|
async function runServer(options) {
|
||||||
const {
|
const {
|
||||||
port,
|
port,
|
||||||
host,
|
host,
|
||||||
path = '/',
|
path = "/",
|
||||||
maxConnections = Infinity,
|
maxConnections = Infinity,
|
||||||
extension
|
extension
|
||||||
} = options;
|
} = options;
|
||||||
const server = new _playwrightServer.PlaywrightServer({
|
const server = new import_playwrightServer.PlaywrightServer({ mode: extension ? "extension" : "default", path, maxConnections });
|
||||||
mode: extension ? 'extension' : 'default',
|
|
||||||
path,
|
|
||||||
maxConnections
|
|
||||||
});
|
|
||||||
const wsEndpoint = await server.listen(port, host);
|
const wsEndpoint = await server.listen(port, host);
|
||||||
process.on('exit', () => server.close().catch(console.error));
|
process.on("exit", () => server.close().catch(console.error));
|
||||||
console.log('Listening on ' + wsEndpoint);
|
console.log("Listening on " + wsEndpoint);
|
||||||
process.stdin.on('close', () => (0, _processLauncher.gracefullyProcessExitDoNotHang)(0));
|
process.stdin.on("close", () => (0, import_processLauncher.gracefullyProcessExitDoNotHang)(0));
|
||||||
}
|
}
|
||||||
async function launchBrowserServer(browserName, configFile) {
|
async function launchBrowserServer(browserName, configFile) {
|
||||||
let options = {};
|
let options = {};
|
||||||
if (configFile) options = JSON.parse(_fs.default.readFileSync(configFile).toString());
|
if (configFile)
|
||||||
|
options = JSON.parse(import_fs.default.readFileSync(configFile).toString());
|
||||||
const browserType = playwright[browserName];
|
const browserType = playwright[browserName];
|
||||||
const server = await browserType.launchServer(options);
|
const server = await browserType.launchServer(options);
|
||||||
console.log(server.wsEndpoint());
|
console.log(server.wsEndpoint());
|
||||||
}
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
launchBrowserServer,
|
||||||
|
printApiJson,
|
||||||
|
runDriver,
|
||||||
|
runServer
|
||||||
|
});
|
||||||
|
|||||||
640
tvapp2/node_modules/playwright-core/lib/cli/program.js
generated
vendored
@@ -1,134 +1,173 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __create = Object.create;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __defProp = Object.defineProperty;
|
||||||
value: true
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
});
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
Object.defineProperty(exports, "program", {
|
var __getProtoOf = Object.getPrototypeOf;
|
||||||
enumerable: true,
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
get: function () {
|
var __export = (target, all) => {
|
||||||
return _utilsBundle.program;
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
}
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||||
|
// If the importer is in node compatibility mode or this is not an ESM
|
||||||
|
// file that has been converted to a CommonJS file using a Babel-
|
||||||
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||||
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||||
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||||
|
mod
|
||||||
|
));
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var program_exports = {};
|
||||||
|
__export(program_exports, {
|
||||||
|
program: () => import_utilsBundle2.program
|
||||||
});
|
});
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
module.exports = __toCommonJS(program_exports);
|
||||||
var _os = _interopRequireDefault(require("os"));
|
var import_fs = __toESM(require("fs"));
|
||||||
var _path = _interopRequireDefault(require("path"));
|
var import_os = __toESM(require("os"));
|
||||||
var _utilsBundle = require("../utilsBundle");
|
var import_path = __toESM(require("path"));
|
||||||
var _driver = require("./driver");
|
var playwright = __toESM(require("../.."));
|
||||||
var _traceViewer = require("../server/trace/viewer/traceViewer");
|
var import_driver = require("./driver");
|
||||||
var playwright = _interopRequireWildcard(require("../.."));
|
var import_server = require("../server");
|
||||||
var _utils = require("../utils");
|
var import_utils = require("../utils");
|
||||||
var _server = require("../server");
|
var import_traceViewer = require("../server/trace/viewer/traceViewer");
|
||||||
var _errors = require("../client/errors");
|
var import_utils2 = require("../utils");
|
||||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
var import_ascii = require("../server/utils/ascii");
|
||||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
var import_utilsBundle = require("../utilsBundle");
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
var import_utilsBundle2 = require("../utilsBundle");
|
||||||
/**
|
const packageJSON = require("../../package.json");
|
||||||
* Copyright (c) Microsoft Corporation.
|
import_utilsBundle.program.version("Version " + (process.env.PW_CLI_DISPLAY_VERSION || packageJSON.version)).name(buildBasePlaywrightCLICommand(process.env.PW_LANG_NAME));
|
||||||
*
|
import_utilsBundle.program.command("mark-docker-image [dockerImageNameTemplate]", { hidden: true }).description("mark docker image").allowUnknownOption(true).action(function(dockerImageNameTemplate) {
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
(0, import_utils2.assert)(dockerImageNameTemplate, "dockerImageNameTemplate is required");
|
||||||
* you may not use this file except in compliance with the License.
|
(0, import_server.writeDockerVersion)(dockerImageNameTemplate).catch(logErrorAndExit);
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* eslint-disable no-console */
|
|
||||||
|
|
||||||
const packageJSON = require('../../package.json');
|
|
||||||
_utilsBundle.program.version('Version ' + (process.env.PW_CLI_DISPLAY_VERSION || packageJSON.version)).name(buildBasePlaywrightCLICommand(process.env.PW_LANG_NAME));
|
|
||||||
_utilsBundle.program.command('mark-docker-image [dockerImageNameTemplate]', {
|
|
||||||
hidden: true
|
|
||||||
}).description('mark docker image').allowUnknownOption(true).action(function (dockerImageNameTemplate) {
|
|
||||||
(0, _utils.assert)(dockerImageNameTemplate, 'dockerImageNameTemplate is required');
|
|
||||||
(0, _server.writeDockerVersion)(dockerImageNameTemplate).catch(logErrorAndExit);
|
|
||||||
});
|
});
|
||||||
commandWithOpenOptions('open [url]', 'open page in browser specified via -b, --browser', []).action(function (url, options) {
|
commandWithOpenOptions("open [url]", "open page in browser specified via -b, --browser", []).action(function(url, options) {
|
||||||
open(options, url, codegenId()).catch(logErrorAndExit);
|
open(options, url, codegenId()).catch(logErrorAndExit);
|
||||||
}).addHelpText('afterAll', `
|
}).addHelpText("afterAll", `
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
$ open
|
$ open
|
||||||
$ open -b webkit https://example.com`);
|
$ open -b webkit https://example.com`);
|
||||||
commandWithOpenOptions('codegen [url]', 'open page and generate code for user actions', [['-o, --output <file name>', 'saves the generated script to a file'], ['--target <language>', `language to generate, one of javascript, playwright-test, python, python-async, python-pytest, csharp, csharp-mstest, csharp-nunit, java, java-junit`, codegenId()], ['--test-id-attribute <attributeName>', 'use the specified attribute to generate data test ID selectors']]).action(function (url, options) {
|
commandWithOpenOptions(
|
||||||
|
"codegen [url]",
|
||||||
|
"open page and generate code for user actions",
|
||||||
|
[
|
||||||
|
["-o, --output <file name>", "saves the generated script to a file"],
|
||||||
|
["--target <language>", `language to generate, one of javascript, playwright-test, python, python-async, python-pytest, csharp, csharp-mstest, csharp-nunit, java, java-junit`, codegenId()],
|
||||||
|
["--test-id-attribute <attributeName>", "use the specified attribute to generate data test ID selectors"]
|
||||||
|
]
|
||||||
|
).action(function(url, options) {
|
||||||
codegen(options, url).catch(logErrorAndExit);
|
codegen(options, url).catch(logErrorAndExit);
|
||||||
}).addHelpText('afterAll', `
|
}).addHelpText("afterAll", `
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
$ codegen
|
$ codegen
|
||||||
$ codegen --target=python
|
$ codegen --target=python
|
||||||
$ codegen -b webkit https://example.com`);
|
$ codegen -b webkit https://example.com`);
|
||||||
function suggestedBrowsersToInstall() {
|
function suggestedBrowsersToInstall() {
|
||||||
return _server.registry.executables().filter(e => e.installType !== 'none' && e.type !== 'tool').map(e => e.name).join(', ');
|
return import_server.registry.executables().filter((e) => e.installType !== "none" && e.type !== "tool").map((e) => e.name).join(", ");
|
||||||
}
|
}
|
||||||
function defaultBrowsersToInstall(options) {
|
function defaultBrowsersToInstall(options) {
|
||||||
let executables = _server.registry.defaultExecutables();
|
let executables = import_server.registry.defaultExecutables();
|
||||||
if (options.noShell) executables = executables.filter(e => e.name !== 'chromium-headless-shell');
|
if (options.noShell)
|
||||||
if (options.onlyShell) executables = executables.filter(e => e.name !== 'chromium');
|
executables = executables.filter((e) => e.name !== "chromium-headless-shell");
|
||||||
|
if (options.onlyShell)
|
||||||
|
executables = executables.filter((e) => e.name !== "chromium");
|
||||||
return executables;
|
return executables;
|
||||||
}
|
}
|
||||||
function checkBrowsersToInstall(args, options) {
|
function checkBrowsersToInstall(args, options) {
|
||||||
if (options.noShell && options.onlyShell) throw new Error(`Only one of --no-shell and --only-shell can be specified`);
|
if (options.noShell && options.onlyShell)
|
||||||
|
throw new Error(`Only one of --no-shell and --only-shell can be specified`);
|
||||||
const faultyArguments = [];
|
const faultyArguments = [];
|
||||||
const executables = [];
|
const executables = [];
|
||||||
const handleArgument = arg => {
|
const handleArgument = (arg) => {
|
||||||
const executable = _server.registry.findExecutable(arg);
|
const executable = import_server.registry.findExecutable(arg);
|
||||||
if (!executable || executable.installType === 'none') faultyArguments.push(arg);else executables.push(executable);
|
if (!executable || executable.installType === "none")
|
||||||
if ((executable === null || executable === void 0 ? void 0 : executable.browserName) === 'chromium') executables.push(_server.registry.findExecutable('ffmpeg'));
|
faultyArguments.push(arg);
|
||||||
|
else
|
||||||
|
executables.push(executable);
|
||||||
|
if (executable?.browserName === "chromium")
|
||||||
|
executables.push(import_server.registry.findExecutable("ffmpeg"));
|
||||||
};
|
};
|
||||||
for (const arg of args) {
|
for (const arg of args) {
|
||||||
if (arg === 'chromium') {
|
if (arg === "chromium") {
|
||||||
if (!options.onlyShell) handleArgument('chromium');
|
if (!options.onlyShell)
|
||||||
if (!options.noShell) handleArgument('chromium-headless-shell');
|
handleArgument("chromium");
|
||||||
|
if (!options.noShell)
|
||||||
|
handleArgument("chromium-headless-shell");
|
||||||
} else {
|
} else {
|
||||||
handleArgument(arg);
|
handleArgument(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (process.platform === 'win32') executables.push(_server.registry.findExecutable('winldd'));
|
if (process.platform === "win32")
|
||||||
if (faultyArguments.length) throw new Error(`Invalid installation targets: ${faultyArguments.map(name => `'${name}'`).join(', ')}. Expecting one of: ${suggestedBrowsersToInstall()}`);
|
executables.push(import_server.registry.findExecutable("winldd"));
|
||||||
|
if (faultyArguments.length)
|
||||||
|
throw new Error(`Invalid installation targets: ${faultyArguments.map((name) => `'${name}'`).join(", ")}. Expecting one of: ${suggestedBrowsersToInstall()}`);
|
||||||
return executables;
|
return executables;
|
||||||
}
|
}
|
||||||
_utilsBundle.program.command('install [browser...]').description('ensure browsers necessary for this version of Playwright are installed').option('--with-deps', 'install system dependencies for browsers').option('--dry-run', 'do not execute installation, only print information').option('--force', 'force reinstall of stable browser channels').option('--only-shell', 'only install headless shell when installing chromium').option('--no-shell', 'do not install chromium headless shell').action(async function (args, options) {
|
import_utilsBundle.program.command("install [browser...]").description("ensure browsers necessary for this version of Playwright are installed").option("--with-deps", "install system dependencies for browsers").option("--dry-run", "do not execute installation, only print information").option("--force", "force reinstall of stable browser channels").option("--only-shell", "only install headless shell when installing chromium").option("--no-shell", "do not install chromium headless shell").action(async function(args, options) {
|
||||||
// For '--no-shell' option, commander sets `shell: false` instead.
|
if (options.shell === false)
|
||||||
if (options.shell === false) options.noShell = true;
|
options.noShell = true;
|
||||||
if ((0, _utils.isLikelyNpxGlobal)()) {
|
if ((0, import_utils.isLikelyNpxGlobal)()) {
|
||||||
console.error((0, _utils.wrapInASCIIBox)([`WARNING: It looks like you are running 'npx playwright install' without first`, `installing your project's dependencies.`, ``, `To avoid unexpected behavior, please install your dependencies first, and`, `then run Playwright's install command:`, ``, ` npm install`, ` npx playwright install`, ``, `If your project does not yet depend on Playwright, first install the`, `applicable npm package (most commonly @playwright/test), and`, `then run Playwright's install command to download the browsers:`, ``, ` npm install @playwright/test`, ` npx playwright install`, ``].join('\n'), 1));
|
console.error((0, import_ascii.wrapInASCIIBox)([
|
||||||
|
`WARNING: It looks like you are running 'npx playwright install' without first`,
|
||||||
|
`installing your project's dependencies.`,
|
||||||
|
``,
|
||||||
|
`To avoid unexpected behavior, please install your dependencies first, and`,
|
||||||
|
`then run Playwright's install command:`,
|
||||||
|
``,
|
||||||
|
` npm install`,
|
||||||
|
` npx playwright install`,
|
||||||
|
``,
|
||||||
|
`If your project does not yet depend on Playwright, first install the`,
|
||||||
|
`applicable npm package (most commonly @playwright/test), and`,
|
||||||
|
`then run Playwright's install command to download the browsers:`,
|
||||||
|
``,
|
||||||
|
` npm install @playwright/test`,
|
||||||
|
` npx playwright install`,
|
||||||
|
``
|
||||||
|
].join("\n"), 1));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const hasNoArguments = !args.length;
|
const hasNoArguments = !args.length;
|
||||||
const executables = hasNoArguments ? defaultBrowsersToInstall(options) : checkBrowsersToInstall(args, options);
|
const executables = hasNoArguments ? defaultBrowsersToInstall(options) : checkBrowsersToInstall(args, options);
|
||||||
if (options.withDeps) await _server.registry.installDeps(executables, !!options.dryRun);
|
if (options.withDeps)
|
||||||
|
await import_server.registry.installDeps(executables, !!options.dryRun);
|
||||||
if (options.dryRun) {
|
if (options.dryRun) {
|
||||||
for (const executable of executables) {
|
for (const executable of executables) {
|
||||||
var _executable$directory, _executable$downloadU;
|
const version = executable.browserVersion ? `version ` + executable.browserVersion : "";
|
||||||
const version = executable.browserVersion ? `version ` + executable.browserVersion : '';
|
console.log(`browser: ${executable.name}${version ? " " + version : ""}`);
|
||||||
console.log(`browser: ${executable.name}${version ? ' ' + version : ''}`);
|
console.log(` Install location: ${executable.directory ?? "<system>"}`);
|
||||||
console.log(` Install location: ${(_executable$directory = executable.directory) !== null && _executable$directory !== void 0 ? _executable$directory : '<system>'}`);
|
if (executable.downloadURLs?.length) {
|
||||||
if ((_executable$downloadU = executable.downloadURLs) !== null && _executable$downloadU !== void 0 && _executable$downloadU.length) {
|
|
||||||
const [url, ...fallbacks] = executable.downloadURLs;
|
const [url, ...fallbacks] = executable.downloadURLs;
|
||||||
console.log(` Download url: ${url}`);
|
console.log(` Download url: ${url}`);
|
||||||
for (let i = 0; i < fallbacks.length; ++i) console.log(` Download fallback ${i + 1}: ${fallbacks[i]}`);
|
for (let i = 0; i < fallbacks.length; ++i)
|
||||||
|
console.log(` Download fallback ${i + 1}: ${fallbacks[i]}`);
|
||||||
}
|
}
|
||||||
console.log(``);
|
console.log(``);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const forceReinstall = hasNoArguments ? false : !!options.force;
|
const forceReinstall = hasNoArguments ? false : !!options.force;
|
||||||
await _server.registry.install(executables, forceReinstall);
|
await import_server.registry.install(executables, forceReinstall);
|
||||||
await _server.registry.validateHostRequirementsForExecutablesIfNeeded(executables, process.env.PW_LANG_NAME || 'javascript').catch(e => {
|
await import_server.registry.validateHostRequirementsForExecutablesIfNeeded(executables, process.env.PW_LANG_NAME || "javascript").catch((e) => {
|
||||||
e.name = 'Playwright Host validation warning';
|
e.name = "Playwright Host validation warning";
|
||||||
console.error(e);
|
console.error(e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(`Failed to install browsers\n${e}`);
|
console.log(`Failed to install browsers
|
||||||
(0, _utils.gracefullyProcessExitDoNotHang)(1);
|
${e}`);
|
||||||
|
(0, import_utils.gracefullyProcessExitDoNotHang)(1);
|
||||||
}
|
}
|
||||||
}).addHelpText('afterAll', `
|
}).addHelpText("afterAll", `
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
- $ install
|
- $ install
|
||||||
@@ -136,106 +175,110 @@ Examples:
|
|||||||
|
|
||||||
- $ install chrome firefox
|
- $ install chrome firefox
|
||||||
Install custom browsers, supports ${suggestedBrowsersToInstall()}.`);
|
Install custom browsers, supports ${suggestedBrowsersToInstall()}.`);
|
||||||
_utilsBundle.program.command('uninstall').description('Removes browsers used by this installation of Playwright from the system (chromium, firefox, webkit, ffmpeg). This does not include branded channels.').option('--all', 'Removes all browsers used by any Playwright installation from the system.').action(async options => {
|
import_utilsBundle.program.command("uninstall").description("Removes browsers used by this installation of Playwright from the system (chromium, firefox, webkit, ffmpeg). This does not include branded channels.").option("--all", "Removes all browsers used by any Playwright installation from the system.").action(async (options) => {
|
||||||
delete process.env.PLAYWRIGHT_SKIP_BROWSER_GC;
|
delete process.env.PLAYWRIGHT_SKIP_BROWSER_GC;
|
||||||
await _server.registry.uninstall(!!options.all).then(({
|
await import_server.registry.uninstall(!!options.all).then(({ numberOfBrowsersLeft }) => {
|
||||||
numberOfBrowsersLeft
|
|
||||||
}) => {
|
|
||||||
if (!options.all && numberOfBrowsersLeft > 0) {
|
if (!options.all && numberOfBrowsersLeft > 0) {
|
||||||
console.log('Successfully uninstalled Playwright browsers for the current Playwright installation.');
|
console.log("Successfully uninstalled Playwright browsers for the current Playwright installation.");
|
||||||
console.log(`There are still ${numberOfBrowsersLeft} browsers left, used by other Playwright installations.\nTo uninstall Playwright browsers for all installations, re-run with --all flag.`);
|
console.log(`There are still ${numberOfBrowsersLeft} browsers left, used by other Playwright installations.
|
||||||
|
To uninstall Playwright browsers for all installations, re-run with --all flag.`);
|
||||||
}
|
}
|
||||||
}).catch(logErrorAndExit);
|
}).catch(logErrorAndExit);
|
||||||
});
|
});
|
||||||
_utilsBundle.program.command('install-deps [browser...]').description('install dependencies necessary to run browsers (will ask for sudo permissions)').option('--dry-run', 'Do not execute installation commands, only print them').action(async function (args, options) {
|
import_utilsBundle.program.command("install-deps [browser...]").description("install dependencies necessary to run browsers (will ask for sudo permissions)").option("--dry-run", "Do not execute installation commands, only print them").action(async function(args, options) {
|
||||||
try {
|
try {
|
||||||
if (!args.length) await _server.registry.installDeps(defaultBrowsersToInstall({}), !!options.dryRun);else await _server.registry.installDeps(checkBrowsersToInstall(args, {}), !!options.dryRun);
|
if (!args.length)
|
||||||
|
await import_server.registry.installDeps(defaultBrowsersToInstall({}), !!options.dryRun);
|
||||||
|
else
|
||||||
|
await import_server.registry.installDeps(checkBrowsersToInstall(args, {}), !!options.dryRun);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(`Failed to install browser dependencies\n${e}`);
|
console.log(`Failed to install browser dependencies
|
||||||
(0, _utils.gracefullyProcessExitDoNotHang)(1);
|
${e}`);
|
||||||
|
(0, import_utils.gracefullyProcessExitDoNotHang)(1);
|
||||||
}
|
}
|
||||||
}).addHelpText('afterAll', `
|
}).addHelpText("afterAll", `
|
||||||
Examples:
|
Examples:
|
||||||
- $ install-deps
|
- $ install-deps
|
||||||
Install dependencies for default browsers.
|
Install dependencies for default browsers.
|
||||||
|
|
||||||
- $ install-deps chrome firefox
|
- $ install-deps chrome firefox
|
||||||
Install dependencies for specific browsers, supports ${suggestedBrowsersToInstall()}.`);
|
Install dependencies for specific browsers, supports ${suggestedBrowsersToInstall()}.`);
|
||||||
const browsers = [{
|
const browsers = [
|
||||||
alias: 'cr',
|
{ alias: "cr", name: "Chromium", type: "chromium" },
|
||||||
name: 'Chromium',
|
{ alias: "ff", name: "Firefox", type: "firefox" },
|
||||||
type: 'chromium'
|
{ alias: "wk", name: "WebKit", type: "webkit" }
|
||||||
}, {
|
];
|
||||||
alias: 'ff',
|
for (const { alias, name, type } of browsers) {
|
||||||
name: 'Firefox',
|
commandWithOpenOptions(`${alias} [url]`, `open page in ${name}`, []).action(function(url, options) {
|
||||||
type: 'firefox'
|
open({ ...options, browser: type }, url, options.target).catch(logErrorAndExit);
|
||||||
}, {
|
}).addHelpText("afterAll", `
|
||||||
alias: 'wk',
|
|
||||||
name: 'WebKit',
|
|
||||||
type: 'webkit'
|
|
||||||
}];
|
|
||||||
for (const {
|
|
||||||
alias,
|
|
||||||
name,
|
|
||||||
type
|
|
||||||
} of browsers) {
|
|
||||||
commandWithOpenOptions(`${alias} [url]`, `open page in ${name}`, []).action(function (url, options) {
|
|
||||||
open({
|
|
||||||
...options,
|
|
||||||
browser: type
|
|
||||||
}, url, options.target).catch(logErrorAndExit);
|
|
||||||
}).addHelpText('afterAll', `
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
$ ${alias} https://example.com`);
|
$ ${alias} https://example.com`);
|
||||||
}
|
}
|
||||||
commandWithOpenOptions('screenshot <url> <filename>', 'capture a page screenshot', [['--wait-for-selector <selector>', 'wait for selector before taking a screenshot'], ['--wait-for-timeout <timeout>', 'wait for timeout in milliseconds before taking a screenshot'], ['--full-page', 'whether to take a full page screenshot (entire scrollable area)']]).action(function (url, filename, command) {
|
commandWithOpenOptions(
|
||||||
|
"screenshot <url> <filename>",
|
||||||
|
"capture a page screenshot",
|
||||||
|
[
|
||||||
|
["--wait-for-selector <selector>", "wait for selector before taking a screenshot"],
|
||||||
|
["--wait-for-timeout <timeout>", "wait for timeout in milliseconds before taking a screenshot"],
|
||||||
|
["--full-page", "whether to take a full page screenshot (entire scrollable area)"]
|
||||||
|
]
|
||||||
|
).action(function(url, filename, command) {
|
||||||
screenshot(command, command, url, filename).catch(logErrorAndExit);
|
screenshot(command, command, url, filename).catch(logErrorAndExit);
|
||||||
}).addHelpText('afterAll', `
|
}).addHelpText("afterAll", `
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
$ screenshot -b webkit https://example.com example.png`);
|
$ screenshot -b webkit https://example.com example.png`);
|
||||||
commandWithOpenOptions('pdf <url> <filename>', 'save page as pdf', [['--wait-for-selector <selector>', 'wait for given selector before saving as pdf'], ['--wait-for-timeout <timeout>', 'wait for given timeout in milliseconds before saving as pdf']]).action(function (url, filename, options) {
|
commandWithOpenOptions(
|
||||||
|
"pdf <url> <filename>",
|
||||||
|
"save page as pdf",
|
||||||
|
[
|
||||||
|
["--paper-format <format>", "paper format: Letter, Legal, Tabloid, Ledger, A0, A1, A2, A3, A4, A5, A6"],
|
||||||
|
["--wait-for-selector <selector>", "wait for given selector before saving as pdf"],
|
||||||
|
["--wait-for-timeout <timeout>", "wait for given timeout in milliseconds before saving as pdf"]
|
||||||
|
]
|
||||||
|
).action(function(url, filename, options) {
|
||||||
pdf(options, options, url, filename).catch(logErrorAndExit);
|
pdf(options, options, url, filename).catch(logErrorAndExit);
|
||||||
}).addHelpText('afterAll', `
|
}).addHelpText("afterAll", `
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
$ pdf https://example.com example.pdf`);
|
$ pdf https://example.com example.pdf`);
|
||||||
_utilsBundle.program.command('run-driver', {
|
import_utilsBundle.program.command("run-driver", { hidden: true }).action(function(options) {
|
||||||
hidden: true
|
(0, import_driver.runDriver)();
|
||||||
}).action(function (options) {
|
|
||||||
(0, _driver.runDriver)();
|
|
||||||
});
|
});
|
||||||
_utilsBundle.program.command('run-server').option('--port <port>', 'Server port').option('--host <host>', 'Server host').option('--path <path>', 'Endpoint Path', '/').option('--max-clients <maxClients>', 'Maximum clients').option('--mode <mode>', 'Server mode, either "default" or "extension"').action(function (options) {
|
import_utilsBundle.program.command("run-server").option("--port <port>", "Server port").option("--host <host>", "Server host").option("--path <path>", "Endpoint Path", "/").option("--max-clients <maxClients>", "Maximum clients").option("--mode <mode>", 'Server mode, either "default" or "extension"').action(function(options) {
|
||||||
(0, _driver.runServer)({
|
(0, import_driver.runServer)({
|
||||||
port: options.port ? +options.port : undefined,
|
port: options.port ? +options.port : void 0,
|
||||||
host: options.host,
|
host: options.host,
|
||||||
path: options.path,
|
path: options.path,
|
||||||
maxConnections: options.maxClients ? +options.maxClients : Infinity,
|
maxConnections: options.maxClients ? +options.maxClients : Infinity,
|
||||||
extension: options.mode === 'extension' || !!process.env.PW_EXTENSION_MODE
|
extension: options.mode === "extension" || !!process.env.PW_EXTENSION_MODE
|
||||||
}).catch(logErrorAndExit);
|
}).catch(logErrorAndExit);
|
||||||
});
|
});
|
||||||
_utilsBundle.program.command('print-api-json', {
|
import_utilsBundle.program.command("print-api-json", { hidden: true }).action(function(options) {
|
||||||
hidden: true
|
(0, import_driver.printApiJson)();
|
||||||
}).action(function (options) {
|
|
||||||
(0, _driver.printApiJson)();
|
|
||||||
});
|
});
|
||||||
_utilsBundle.program.command('launch-server', {
|
import_utilsBundle.program.command("launch-server", { hidden: true }).requiredOption("--browser <browserName>", 'Browser name, one of "chromium", "firefox" or "webkit"').option("--config <path-to-config-file>", "JSON file with launchServer options").action(function(options) {
|
||||||
hidden: true
|
(0, import_driver.launchBrowserServer)(options.browser, options.config);
|
||||||
}).requiredOption('--browser <browserName>', 'Browser name, one of "chromium", "firefox" or "webkit"').option('--config <path-to-config-file>', 'JSON file with launchServer options').action(function (options) {
|
|
||||||
(0, _driver.launchBrowserServer)(options.browser, options.config);
|
|
||||||
});
|
});
|
||||||
_utilsBundle.program.command('show-trace [trace...]').option('-b, --browser <browserType>', 'browser to use, one of cr, chromium, ff, firefox, wk, webkit', 'chromium').option('-h, --host <host>', 'Host to serve trace on; specifying this option opens trace in a browser tab').option('-p, --port <port>', 'Port to serve trace on, 0 for any free port; specifying this option opens trace in a browser tab').option('--stdin', 'Accept trace URLs over stdin to update the viewer').description('show trace viewer').action(function (traces, options) {
|
import_utilsBundle.program.command("show-trace [trace...]").option("-b, --browser <browserType>", "browser to use, one of cr, chromium, ff, firefox, wk, webkit", "chromium").option("-h, --host <host>", "Host to serve trace on; specifying this option opens trace in a browser tab").option("-p, --port <port>", "Port to serve trace on, 0 for any free port; specifying this option opens trace in a browser tab").option("--stdin", "Accept trace URLs over stdin to update the viewer").description("show trace viewer").action(function(traces, options) {
|
||||||
if (options.browser === 'cr') options.browser = 'chromium';
|
if (options.browser === "cr")
|
||||||
if (options.browser === 'ff') options.browser = 'firefox';
|
options.browser = "chromium";
|
||||||
if (options.browser === 'wk') options.browser = 'webkit';
|
if (options.browser === "ff")
|
||||||
|
options.browser = "firefox";
|
||||||
|
if (options.browser === "wk")
|
||||||
|
options.browser = "webkit";
|
||||||
const openOptions = {
|
const openOptions = {
|
||||||
host: options.host,
|
host: options.host,
|
||||||
port: +options.port,
|
port: +options.port,
|
||||||
isServer: !!options.stdin
|
isServer: !!options.stdin
|
||||||
};
|
};
|
||||||
if (options.port !== undefined || options.host !== undefined) (0, _traceViewer.runTraceInBrowser)(traces, openOptions).catch(logErrorAndExit);else (0, _traceViewer.runTraceViewerApp)(traces, options.browser, openOptions, true).catch(logErrorAndExit);
|
if (options.port !== void 0 || options.host !== void 0)
|
||||||
}).addHelpText('afterAll', `
|
(0, import_traceViewer.runTraceInBrowser)(traces, openOptions).catch(logErrorAndExit);
|
||||||
|
else
|
||||||
|
(0, import_traceViewer.runTraceViewerApp)(traces, options.browser, openOptions, true).catch(logErrorAndExit);
|
||||||
|
}).addHelpText("afterAll", `
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
$ show-trace https://example.com/trace.zip`);
|
$ show-trace https://example.com/trace.zip`);
|
||||||
@@ -243,79 +286,67 @@ async function launchContext(options, extraOptions) {
|
|||||||
validateOptions(options);
|
validateOptions(options);
|
||||||
const browserType = lookupBrowserType(options);
|
const browserType = lookupBrowserType(options);
|
||||||
const launchOptions = extraOptions;
|
const launchOptions = extraOptions;
|
||||||
if (options.channel) launchOptions.channel = options.channel;
|
if (options.channel)
|
||||||
|
launchOptions.channel = options.channel;
|
||||||
launchOptions.handleSIGINT = false;
|
launchOptions.handleSIGINT = false;
|
||||||
const contextOptions =
|
const contextOptions = (
|
||||||
// Copy the device descriptor since we have to compare and modify the options.
|
// Copy the device descriptor since we have to compare and modify the options.
|
||||||
options.device ? {
|
options.device ? { ...playwright.devices[options.device] } : {}
|
||||||
...playwright.devices[options.device]
|
);
|
||||||
} : {};
|
if (!extraOptions.headless)
|
||||||
|
contextOptions.deviceScaleFactor = import_os.default.platform() === "darwin" ? 2 : 1;
|
||||||
// In headful mode, use host device scale factor for things to look nice.
|
if (browserType.name() === "webkit" && process.platform === "linux") {
|
||||||
// In headless, keep things the way it works in Playwright by default.
|
|
||||||
// Assume high-dpi on MacOS. TODO: this is not perfect.
|
|
||||||
if (!extraOptions.headless) contextOptions.deviceScaleFactor = _os.default.platform() === 'darwin' ? 2 : 1;
|
|
||||||
|
|
||||||
// Work around the WebKit GTK scrolling issue.
|
|
||||||
if (browserType.name() === 'webkit' && process.platform === 'linux') {
|
|
||||||
delete contextOptions.hasTouch;
|
delete contextOptions.hasTouch;
|
||||||
delete contextOptions.isMobile;
|
delete contextOptions.isMobile;
|
||||||
}
|
}
|
||||||
if (contextOptions.isMobile && browserType.name() === 'firefox') contextOptions.isMobile = undefined;
|
if (contextOptions.isMobile && browserType.name() === "firefox")
|
||||||
if (options.blockServiceWorkers) contextOptions.serviceWorkers = 'block';
|
contextOptions.isMobile = void 0;
|
||||||
|
if (options.blockServiceWorkers)
|
||||||
// Proxy
|
contextOptions.serviceWorkers = "block";
|
||||||
|
|
||||||
if (options.proxyServer) {
|
if (options.proxyServer) {
|
||||||
launchOptions.proxy = {
|
launchOptions.proxy = {
|
||||||
server: options.proxyServer
|
server: options.proxyServer
|
||||||
};
|
};
|
||||||
if (options.proxyBypass) launchOptions.proxy.bypass = options.proxyBypass;
|
if (options.proxyBypass)
|
||||||
|
launchOptions.proxy.bypass = options.proxyBypass;
|
||||||
}
|
}
|
||||||
const browser = await browserType.launch(launchOptions);
|
const browser = await browserType.launch(launchOptions);
|
||||||
if (process.env.PWTEST_CLI_IS_UNDER_TEST) {
|
if (process.env.PWTEST_CLI_IS_UNDER_TEST) {
|
||||||
process._didSetSourcesForTest = text => {
|
process._didSetSourcesForTest = (text) => {
|
||||||
process.stdout.write('\n-------------8<-------------\n');
|
process.stdout.write("\n-------------8<-------------\n");
|
||||||
process.stdout.write(text);
|
process.stdout.write(text);
|
||||||
process.stdout.write('\n-------------8<-------------\n');
|
process.stdout.write("\n-------------8<-------------\n");
|
||||||
const autoExitCondition = process.env.PWTEST_CLI_AUTO_EXIT_WHEN;
|
const autoExitCondition = process.env.PWTEST_CLI_AUTO_EXIT_WHEN;
|
||||||
if (autoExitCondition && text.includes(autoExitCondition)) closeBrowser();
|
if (autoExitCondition && text.includes(autoExitCondition))
|
||||||
|
closeBrowser();
|
||||||
};
|
};
|
||||||
// Make sure we exit abnormally when browser crashes.
|
|
||||||
const logs = [];
|
const logs = [];
|
||||||
require('playwright-core/lib/utilsBundle').debug.log = (...args) => {
|
require("playwright-core/lib/utilsBundle").debug.log = (...args) => {
|
||||||
const line = require('util').format(...args) + '\n';
|
const line = require("util").format(...args) + "\n";
|
||||||
logs.push(line);
|
logs.push(line);
|
||||||
process.stderr.write(line);
|
process.stderr.write(line);
|
||||||
};
|
};
|
||||||
browser.on('disconnected', () => {
|
browser.on("disconnected", () => {
|
||||||
const hasCrashLine = logs.some(line => line.includes('process did exit:') && !line.includes('process did exit: exitCode=0, signal=null'));
|
const hasCrashLine = logs.some((line) => line.includes("process did exit:") && !line.includes("process did exit: exitCode=0, signal=null"));
|
||||||
if (hasCrashLine) {
|
if (hasCrashLine) {
|
||||||
process.stderr.write('Detected browser crash.\n');
|
process.stderr.write("Detected browser crash.\n");
|
||||||
(0, _utils.gracefullyProcessExitDoNotHang)(1);
|
(0, import_utils.gracefullyProcessExitDoNotHang)(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Viewport size
|
|
||||||
if (options.viewportSize) {
|
if (options.viewportSize) {
|
||||||
try {
|
try {
|
||||||
const [width, height] = options.viewportSize.split(',').map(n => +n);
|
const [width, height] = options.viewportSize.split(",").map((n) => +n);
|
||||||
if (isNaN(width) || isNaN(height)) throw new Error('bad values');
|
if (isNaN(width) || isNaN(height))
|
||||||
contextOptions.viewport = {
|
throw new Error("bad values");
|
||||||
width,
|
contextOptions.viewport = { width, height };
|
||||||
height
|
|
||||||
};
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error('Invalid viewport size format: use "width,height", for example --viewport-size="800,600"');
|
throw new Error('Invalid viewport size format: use "width,height", for example --viewport-size="800,600"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Geolocation
|
|
||||||
|
|
||||||
if (options.geolocation) {
|
if (options.geolocation) {
|
||||||
try {
|
try {
|
||||||
const [latitude, longitude] = options.geolocation.split(',').map(n => parseFloat(n.trim()));
|
const [latitude, longitude] = options.geolocation.split(",").map((n) => parseFloat(n.trim()));
|
||||||
contextOptions.geolocation = {
|
contextOptions.geolocation = {
|
||||||
latitude,
|
latitude,
|
||||||
longitude
|
longitude
|
||||||
@@ -323,94 +354,71 @@ async function launchContext(options, extraOptions) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error('Invalid geolocation format, should be "lat,long". For example --geolocation="37.819722,-122.478611"');
|
throw new Error('Invalid geolocation format, should be "lat,long". For example --geolocation="37.819722,-122.478611"');
|
||||||
}
|
}
|
||||||
contextOptions.permissions = ['geolocation'];
|
contextOptions.permissions = ["geolocation"];
|
||||||
}
|
}
|
||||||
|
if (options.userAgent)
|
||||||
// User agent
|
contextOptions.userAgent = options.userAgent;
|
||||||
|
if (options.lang)
|
||||||
if (options.userAgent) contextOptions.userAgent = options.userAgent;
|
contextOptions.locale = options.lang;
|
||||||
|
if (options.colorScheme)
|
||||||
// Lang
|
contextOptions.colorScheme = options.colorScheme;
|
||||||
|
if (options.timezone)
|
||||||
if (options.lang) contextOptions.locale = options.lang;
|
contextOptions.timezoneId = options.timezone;
|
||||||
|
if (options.loadStorage)
|
||||||
// Color scheme
|
contextOptions.storageState = options.loadStorage;
|
||||||
|
if (options.ignoreHttpsErrors)
|
||||||
if (options.colorScheme) contextOptions.colorScheme = options.colorScheme;
|
contextOptions.ignoreHTTPSErrors = true;
|
||||||
|
|
||||||
// Timezone
|
|
||||||
|
|
||||||
if (options.timezone) contextOptions.timezoneId = options.timezone;
|
|
||||||
|
|
||||||
// Storage
|
|
||||||
|
|
||||||
if (options.loadStorage) contextOptions.storageState = options.loadStorage;
|
|
||||||
if (options.ignoreHttpsErrors) contextOptions.ignoreHTTPSErrors = true;
|
|
||||||
|
|
||||||
// HAR
|
|
||||||
|
|
||||||
if (options.saveHar) {
|
if (options.saveHar) {
|
||||||
contextOptions.recordHar = {
|
contextOptions.recordHar = { path: import_path.default.resolve(process.cwd(), options.saveHar), mode: "minimal" };
|
||||||
path: _path.default.resolve(process.cwd(), options.saveHar),
|
if (options.saveHarGlob)
|
||||||
mode: 'minimal'
|
contextOptions.recordHar.urlFilter = options.saveHarGlob;
|
||||||
};
|
contextOptions.serviceWorkers = "block";
|
||||||
if (options.saveHarGlob) contextOptions.recordHar.urlFilter = options.saveHarGlob;
|
|
||||||
contextOptions.serviceWorkers = 'block';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close app when the last window closes.
|
|
||||||
|
|
||||||
const context = await browser.newContext(contextOptions);
|
const context = await browser.newContext(contextOptions);
|
||||||
let closingBrowser = false;
|
let closingBrowser = false;
|
||||||
async function closeBrowser() {
|
async function closeBrowser() {
|
||||||
// We can come here multiple times. For example, saving storage creates
|
if (closingBrowser)
|
||||||
// a temporary page and we call closeBrowser again when that page closes.
|
return;
|
||||||
if (closingBrowser) return;
|
|
||||||
closingBrowser = true;
|
closingBrowser = true;
|
||||||
if (options.saveStorage) await context.storageState({
|
if (options.saveStorage)
|
||||||
path: options.saveStorage
|
await context.storageState({ path: options.saveStorage }).catch((e) => null);
|
||||||
}).catch(e => null);
|
if (options.saveHar)
|
||||||
if (options.saveHar) await context.close();
|
await context.close();
|
||||||
await browser.close();
|
await browser.close();
|
||||||
}
|
}
|
||||||
context.on('page', page => {
|
context.on("page", (page) => {
|
||||||
page.on('dialog', () => {}); // Prevent dialogs from being automatically dismissed.
|
page.on("dialog", () => {
|
||||||
page.on('close', () => {
|
});
|
||||||
const hasPage = browser.contexts().some(context => context.pages().length > 0);
|
page.on("close", () => {
|
||||||
if (hasPage) return;
|
const hasPage = browser.contexts().some((context2) => context2.pages().length > 0);
|
||||||
// Avoid the error when the last page is closed because the browser has been closed.
|
if (hasPage)
|
||||||
closeBrowser().catch(() => {});
|
return;
|
||||||
|
closeBrowser().catch(() => {
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
process.on('SIGINT', async () => {
|
process.on("SIGINT", async () => {
|
||||||
await closeBrowser();
|
await closeBrowser();
|
||||||
(0, _utils.gracefullyProcessExitDoNotHang)(130);
|
(0, import_utils.gracefullyProcessExitDoNotHang)(130);
|
||||||
});
|
});
|
||||||
const timeout = options.timeout ? parseInt(options.timeout, 10) : 0;
|
const timeout = options.timeout ? parseInt(options.timeout, 10) : 0;
|
||||||
context.setDefaultTimeout(timeout);
|
context.setDefaultTimeout(timeout);
|
||||||
context.setDefaultNavigationTimeout(timeout);
|
context.setDefaultNavigationTimeout(timeout);
|
||||||
|
|
||||||
// Omit options that we add automatically for presentation purpose.
|
|
||||||
delete launchOptions.headless;
|
delete launchOptions.headless;
|
||||||
delete launchOptions.executablePath;
|
delete launchOptions.executablePath;
|
||||||
delete launchOptions.handleSIGINT;
|
delete launchOptions.handleSIGINT;
|
||||||
delete contextOptions.deviceScaleFactor;
|
delete contextOptions.deviceScaleFactor;
|
||||||
return {
|
return { browser, browserName: browserType.name(), context, contextOptions, launchOptions };
|
||||||
browser,
|
|
||||||
browserName: browserType.name(),
|
|
||||||
context,
|
|
||||||
contextOptions,
|
|
||||||
launchOptions
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
async function openPage(context, url) {
|
async function openPage(context, url) {
|
||||||
const page = await context.newPage();
|
const page = await context.newPage();
|
||||||
if (url) {
|
if (url) {
|
||||||
if (_fs.default.existsSync(url)) url = 'file://' + _path.default.resolve(url);else if (!url.startsWith('http') && !url.startsWith('file://') && !url.startsWith('about:') && !url.startsWith('data:')) url = 'http://' + url;
|
if (import_fs.default.existsSync(url))
|
||||||
await page.goto(url).catch(error => {
|
url = "file://" + import_path.default.resolve(url);
|
||||||
if (process.env.PWTEST_CLI_AUTO_EXIT_WHEN && (0, _errors.isTargetClosedError)(error)) {
|
else if (!url.startsWith("http") && !url.startsWith("file://") && !url.startsWith("about:") && !url.startsWith("data:"))
|
||||||
// Tests with PWTEST_CLI_AUTO_EXIT_WHEN might close page too fast, resulting
|
url = "http://" + url;
|
||||||
// in a stray navigation aborted error. We should ignore it.
|
await page.goto(url).catch((error) => {
|
||||||
|
if (process.env.PWTEST_CLI_AUTO_EXIT_WHEN) {
|
||||||
} else {
|
} else {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
@@ -419,14 +427,7 @@ async function openPage(context, url) {
|
|||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
async function open(options, url, language) {
|
async function open(options, url, language) {
|
||||||
const {
|
const { context, launchOptions, contextOptions } = await launchContext(options, { headless: !!process.env.PWTEST_CLI_HEADLESS, executablePath: process.env.PWTEST_CLI_EXECUTABLE_PATH });
|
||||||
context,
|
|
||||||
launchOptions,
|
|
||||||
contextOptions
|
|
||||||
} = await launchContext(options, {
|
|
||||||
headless: !!process.env.PWTEST_CLI_HEADLESS,
|
|
||||||
executablePath: process.env.PWTEST_CLI_EXECUTABLE_PATH
|
|
||||||
});
|
|
||||||
await context._enableRecorder({
|
await context._enableRecorder({
|
||||||
language,
|
language,
|
||||||
launchOptions,
|
launchOptions,
|
||||||
@@ -438,33 +439,23 @@ async function open(options, url, language) {
|
|||||||
await openPage(context, url);
|
await openPage(context, url);
|
||||||
}
|
}
|
||||||
async function codegen(options, url) {
|
async function codegen(options, url) {
|
||||||
const {
|
const { target: language, output: outputFile, testIdAttribute: testIdAttributeName } = options;
|
||||||
target: language,
|
const tracesDir = import_path.default.join(import_os.default.tmpdir(), `playwright-recorder-trace-${Date.now()}`);
|
||||||
output: outputFile,
|
const { context, launchOptions, contextOptions } = await launchContext(options, {
|
||||||
testIdAttribute: testIdAttributeName
|
|
||||||
} = options;
|
|
||||||
const tracesDir = _path.default.join(_os.default.tmpdir(), `playwright-recorder-trace-${Date.now()}`);
|
|
||||||
const {
|
|
||||||
context,
|
|
||||||
launchOptions,
|
|
||||||
contextOptions
|
|
||||||
} = await launchContext(options, {
|
|
||||||
headless: !!process.env.PWTEST_CLI_HEADLESS,
|
headless: !!process.env.PWTEST_CLI_HEADLESS,
|
||||||
executablePath: process.env.PWTEST_CLI_EXECUTABLE_PATH,
|
executablePath: process.env.PWTEST_CLI_EXECUTABLE_PATH,
|
||||||
tracesDir
|
tracesDir
|
||||||
});
|
});
|
||||||
_utilsBundle.dotenv.config({
|
import_utilsBundle.dotenv.config({ path: "playwright.env" });
|
||||||
path: 'playwright.env'
|
|
||||||
});
|
|
||||||
await context._enableRecorder({
|
await context._enableRecorder({
|
||||||
language,
|
language,
|
||||||
launchOptions,
|
launchOptions,
|
||||||
contextOptions,
|
contextOptions,
|
||||||
device: options.device,
|
device: options.device,
|
||||||
saveStorage: options.saveStorage,
|
saveStorage: options.saveStorage,
|
||||||
mode: 'recording',
|
mode: "recording",
|
||||||
testIdAttributeName,
|
testIdAttributeName,
|
||||||
outputFile: outputFile ? _path.default.resolve(outputFile) : undefined,
|
outputFile: outputFile ? import_path.default.resolve(outputFile) : void 0,
|
||||||
handleSIGINT: false
|
handleSIGINT: false
|
||||||
});
|
});
|
||||||
await openPage(context, url);
|
await openPage(context, url);
|
||||||
@@ -479,41 +470,24 @@ async function waitForPage(page, captureOptions) {
|
|||||||
await page.waitForTimeout(parseInt(captureOptions.waitForTimeout, 10));
|
await page.waitForTimeout(parseInt(captureOptions.waitForTimeout, 10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function screenshot(options, captureOptions, url, path) {
|
async function screenshot(options, captureOptions, url, path2) {
|
||||||
const {
|
const { context } = await launchContext(options, { headless: true });
|
||||||
context
|
console.log("Navigating to " + url);
|
||||||
} = await launchContext(options, {
|
|
||||||
headless: true
|
|
||||||
});
|
|
||||||
console.log('Navigating to ' + url);
|
|
||||||
const page = await openPage(context, url);
|
const page = await openPage(context, url);
|
||||||
await waitForPage(page, captureOptions);
|
await waitForPage(page, captureOptions);
|
||||||
console.log('Capturing screenshot into ' + path);
|
console.log("Capturing screenshot into " + path2);
|
||||||
await page.screenshot({
|
await page.screenshot({ path: path2, fullPage: !!captureOptions.fullPage });
|
||||||
path,
|
|
||||||
fullPage: !!captureOptions.fullPage
|
|
||||||
});
|
|
||||||
// launchContext takes care of closing the browser.
|
|
||||||
await page.close();
|
await page.close();
|
||||||
}
|
}
|
||||||
async function pdf(options, captureOptions, url, path) {
|
async function pdf(options, captureOptions, url, path2) {
|
||||||
if (options.browser !== 'chromium') throw new Error('PDF creation is only working with Chromium');
|
if (options.browser !== "chromium")
|
||||||
const {
|
throw new Error("PDF creation is only working with Chromium");
|
||||||
context
|
const { context } = await launchContext({ ...options, browser: "chromium" }, { headless: true });
|
||||||
} = await launchContext({
|
console.log("Navigating to " + url);
|
||||||
...options,
|
|
||||||
browser: 'chromium'
|
|
||||||
}, {
|
|
||||||
headless: true
|
|
||||||
});
|
|
||||||
console.log('Navigating to ' + url);
|
|
||||||
const page = await openPage(context, url);
|
const page = await openPage(context, url);
|
||||||
await waitForPage(page, captureOptions);
|
await waitForPage(page, captureOptions);
|
||||||
console.log('Saving as pdf into ' + path);
|
console.log("Saving as pdf into " + path2);
|
||||||
await page.pdf({
|
await page.pdf({ path: path2, format: captureOptions.paperFormat });
|
||||||
path
|
|
||||||
});
|
|
||||||
// launchContext takes care of closing the browser.
|
|
||||||
await page.close();
|
await page.close();
|
||||||
}
|
}
|
||||||
function lookupBrowserType(options) {
|
function lookupBrowserType(options) {
|
||||||
@@ -524,60 +498,70 @@ function lookupBrowserType(options) {
|
|||||||
}
|
}
|
||||||
let browserType;
|
let browserType;
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'chromium':
|
case "chromium":
|
||||||
browserType = playwright.chromium;
|
browserType = playwright.chromium;
|
||||||
break;
|
break;
|
||||||
case 'webkit':
|
case "webkit":
|
||||||
browserType = playwright.webkit;
|
browserType = playwright.webkit;
|
||||||
break;
|
break;
|
||||||
case 'firefox':
|
case "firefox":
|
||||||
browserType = playwright.firefox;
|
browserType = playwright.firefox;
|
||||||
break;
|
break;
|
||||||
case 'cr':
|
case "cr":
|
||||||
browserType = playwright.chromium;
|
browserType = playwright.chromium;
|
||||||
break;
|
break;
|
||||||
case 'wk':
|
case "wk":
|
||||||
browserType = playwright.webkit;
|
browserType = playwright.webkit;
|
||||||
break;
|
break;
|
||||||
case 'ff':
|
case "ff":
|
||||||
browserType = playwright.firefox;
|
browserType = playwright.firefox;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (browserType) return browserType;
|
if (browserType)
|
||||||
_utilsBundle.program.help();
|
return browserType;
|
||||||
|
import_utilsBundle.program.help();
|
||||||
}
|
}
|
||||||
function validateOptions(options) {
|
function validateOptions(options) {
|
||||||
if (options.device && !(options.device in playwright.devices)) {
|
if (options.device && !(options.device in playwright.devices)) {
|
||||||
const lines = [`Device descriptor not found: '${options.device}', available devices are:`];
|
const lines = [`Device descriptor not found: '${options.device}', available devices are:`];
|
||||||
for (const name in playwright.devices) lines.push(` "${name}"`);
|
for (const name in playwright.devices)
|
||||||
throw new Error(lines.join('\n'));
|
lines.push(` "${name}"`);
|
||||||
|
throw new Error(lines.join("\n"));
|
||||||
}
|
}
|
||||||
if (options.colorScheme && !['light', 'dark'].includes(options.colorScheme)) throw new Error('Invalid color scheme, should be one of "light", "dark"');
|
if (options.colorScheme && !["light", "dark"].includes(options.colorScheme))
|
||||||
|
throw new Error('Invalid color scheme, should be one of "light", "dark"');
|
||||||
}
|
}
|
||||||
function logErrorAndExit(e) {
|
function logErrorAndExit(e) {
|
||||||
if (process.env.PWDEBUGIMPL) console.error(e);else console.error(e.name + ': ' + e.message);
|
if (process.env.PWDEBUGIMPL)
|
||||||
(0, _utils.gracefullyProcessExitDoNotHang)(1);
|
console.error(e);
|
||||||
|
else
|
||||||
|
console.error(e.name + ": " + e.message);
|
||||||
|
(0, import_utils.gracefullyProcessExitDoNotHang)(1);
|
||||||
}
|
}
|
||||||
function codegenId() {
|
function codegenId() {
|
||||||
return process.env.PW_LANG_NAME || 'playwright-test';
|
return process.env.PW_LANG_NAME || "playwright-test";
|
||||||
}
|
}
|
||||||
function commandWithOpenOptions(command, description, options) {
|
function commandWithOpenOptions(command, description, options) {
|
||||||
let result = _utilsBundle.program.command(command).description(description);
|
let result = import_utilsBundle.program.command(command).description(description);
|
||||||
for (const option of options) result = result.option(option[0], ...option.slice(1));
|
for (const option of options)
|
||||||
return result.option('-b, --browser <browserType>', 'browser to use, one of cr, chromium, ff, firefox, wk, webkit', 'chromium').option('--block-service-workers', 'block service workers').option('--channel <channel>', 'Chromium distribution channel, "chrome", "chrome-beta", "msedge-dev", etc').option('--color-scheme <scheme>', 'emulate preferred color scheme, "light" or "dark"').option('--device <deviceName>', 'emulate device, for example "iPhone 11"').option('--geolocation <coordinates>', 'specify geolocation coordinates, for example "37.819722,-122.478611"').option('--ignore-https-errors', 'ignore https errors').option('--load-storage <filename>', 'load context storage state from the file, previously saved with --save-storage').option('--lang <language>', 'specify language / locale, for example "en-GB"').option('--proxy-server <proxy>', 'specify proxy server, for example "http://myproxy:3128" or "socks5://myproxy:8080"').option('--proxy-bypass <bypass>', 'comma-separated domains to bypass proxy, for example ".com,chromium.org,.domain.com"').option('--save-har <filename>', 'save HAR file with all network activity at the end').option('--save-har-glob <glob pattern>', 'filter entries in the HAR by matching url against this glob pattern').option('--save-storage <filename>', 'save context storage state at the end, for later use with --load-storage').option('--timezone <time zone>', 'time zone to emulate, for example "Europe/Rome"').option('--timeout <timeout>', 'timeout for Playwright actions in milliseconds, no timeout by default').option('--user-agent <ua string>', 'specify user agent string').option('--viewport-size <size>', 'specify browser viewport size in pixels, for example "1280, 720"');
|
result = result.option(option[0], ...option.slice(1));
|
||||||
|
return result.option("-b, --browser <browserType>", "browser to use, one of cr, chromium, ff, firefox, wk, webkit", "chromium").option("--block-service-workers", "block service workers").option("--channel <channel>", 'Chromium distribution channel, "chrome", "chrome-beta", "msedge-dev", etc').option("--color-scheme <scheme>", 'emulate preferred color scheme, "light" or "dark"').option("--device <deviceName>", 'emulate device, for example "iPhone 11"').option("--geolocation <coordinates>", 'specify geolocation coordinates, for example "37.819722,-122.478611"').option("--ignore-https-errors", "ignore https errors").option("--load-storage <filename>", "load context storage state from the file, previously saved with --save-storage").option("--lang <language>", 'specify language / locale, for example "en-GB"').option("--proxy-server <proxy>", 'specify proxy server, for example "http://myproxy:3128" or "socks5://myproxy:8080"').option("--proxy-bypass <bypass>", 'comma-separated domains to bypass proxy, for example ".com,chromium.org,.domain.com"').option("--save-har <filename>", "save HAR file with all network activity at the end").option("--save-har-glob <glob pattern>", "filter entries in the HAR by matching url against this glob pattern").option("--save-storage <filename>", "save context storage state at the end, for later use with --load-storage").option("--timezone <time zone>", 'time zone to emulate, for example "Europe/Rome"').option("--timeout <timeout>", "timeout for Playwright actions in milliseconds, no timeout by default").option("--user-agent <ua string>", "specify user agent string").option("--viewport-size <size>", 'specify browser viewport size in pixels, for example "1280, 720"');
|
||||||
}
|
}
|
||||||
function buildBasePlaywrightCLICommand(cliTargetLang) {
|
function buildBasePlaywrightCLICommand(cliTargetLang) {
|
||||||
switch (cliTargetLang) {
|
switch (cliTargetLang) {
|
||||||
case 'python':
|
case "python":
|
||||||
return `playwright`;
|
return `playwright`;
|
||||||
case 'java':
|
case "java":
|
||||||
return `mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="...options.."`;
|
return `mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="...options.."`;
|
||||||
case 'csharp':
|
case "csharp":
|
||||||
return `pwsh bin/Debug/netX/playwright.ps1`;
|
return `pwsh bin/Debug/netX/playwright.ps1`;
|
||||||
default:
|
default: {
|
||||||
{
|
const packageManagerCommand = (0, import_utils2.getPackageManagerExecCommand)();
|
||||||
const packageManagerCommand = (0, _utils.getPackageManagerExecCommand)();
|
return `${packageManagerCommand} playwright`;
|
||||||
return `${packageManagerCommand} playwright`;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
program
|
||||||
|
});
|
||||||
|
|||||||
95
tvapp2/node_modules/playwright-core/lib/cli/programWithTestStub.js
generated
vendored
@@ -1,67 +1,74 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
});
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
Object.defineProperty(exports, "program", {
|
var __export = (target, all) => {
|
||||||
enumerable: true,
|
for (var name in all)
|
||||||
get: function () {
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
return _program.program;
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
}
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var programWithTestStub_exports = {};
|
||||||
|
__export(programWithTestStub_exports, {
|
||||||
|
program: () => import_program2.program
|
||||||
});
|
});
|
||||||
var _utils = require("../utils");
|
module.exports = __toCommonJS(programWithTestStub_exports);
|
||||||
var _program = require("./program");
|
var import_processLauncher = require("../server/utils/processLauncher");
|
||||||
/**
|
var import_utils = require("../utils");
|
||||||
* Copyright (c) Microsoft Corporation.
|
var import_program = require("./program");
|
||||||
*
|
var import_program2 = require("./program");
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* eslint-disable no-console */
|
|
||||||
|
|
||||||
function printPlaywrightTestError(command) {
|
function printPlaywrightTestError(command) {
|
||||||
const packages = [];
|
const packages = [];
|
||||||
for (const pkg of ['playwright', 'playwright-chromium', 'playwright-firefox', 'playwright-webkit']) {
|
for (const pkg of ["playwright", "playwright-chromium", "playwright-firefox", "playwright-webkit"]) {
|
||||||
try {
|
try {
|
||||||
require.resolve(pkg);
|
require.resolve(pkg);
|
||||||
packages.push(pkg);
|
packages.push(pkg);
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!packages.length) packages.push('playwright');
|
if (!packages.length)
|
||||||
const packageManager = (0, _utils.getPackageManager)();
|
packages.push("playwright");
|
||||||
if (packageManager === 'yarn') {
|
const packageManager = (0, import_utils.getPackageManager)();
|
||||||
|
if (packageManager === "yarn") {
|
||||||
console.error(`Please install @playwright/test package before running "yarn playwright ${command}"`);
|
console.error(`Please install @playwright/test package before running "yarn playwright ${command}"`);
|
||||||
console.error(` yarn remove ${packages.join(' ')}`);
|
console.error(` yarn remove ${packages.join(" ")}`);
|
||||||
console.error(' yarn add -D @playwright/test');
|
console.error(" yarn add -D @playwright/test");
|
||||||
} else if (packageManager === 'pnpm') {
|
} else if (packageManager === "pnpm") {
|
||||||
console.error(`Please install @playwright/test package before running "pnpm exec playwright ${command}"`);
|
console.error(`Please install @playwright/test package before running "pnpm exec playwright ${command}"`);
|
||||||
console.error(` pnpm remove ${packages.join(' ')}`);
|
console.error(` pnpm remove ${packages.join(" ")}`);
|
||||||
console.error(' pnpm add -D @playwright/test');
|
console.error(" pnpm add -D @playwright/test");
|
||||||
} else {
|
} else {
|
||||||
console.error(`Please install @playwright/test package before running "npx playwright ${command}"`);
|
console.error(`Please install @playwright/test package before running "npx playwright ${command}"`);
|
||||||
console.error(` npm uninstall ${packages.join(' ')}`);
|
console.error(` npm uninstall ${packages.join(" ")}`);
|
||||||
console.error(' npm install -D @playwright/test');
|
console.error(" npm install -D @playwright/test");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const kExternalPlaywrightTestCommands = [['test', 'Run tests with Playwright Test.'], ['show-report', 'Show Playwright Test HTML report.'], ['merge-reports', 'Merge Playwright Test Blob reports']];
|
const kExternalPlaywrightTestCommands = [
|
||||||
|
["test", "Run tests with Playwright Test."],
|
||||||
|
["show-report", "Show Playwright Test HTML report."],
|
||||||
|
["merge-reports", "Merge Playwright Test Blob reports"]
|
||||||
|
];
|
||||||
function addExternalPlaywrightTestCommands() {
|
function addExternalPlaywrightTestCommands() {
|
||||||
for (const [command, description] of kExternalPlaywrightTestCommands) {
|
for (const [command, description] of kExternalPlaywrightTestCommands) {
|
||||||
const playwrightTest = _program.program.command(command).allowUnknownOption(true);
|
const playwrightTest = import_program.program.command(command).allowUnknownOption(true);
|
||||||
playwrightTest.description(`${description} Available in @playwright/test package.`);
|
playwrightTest.description(`${description} Available in @playwright/test package.`);
|
||||||
playwrightTest.action(async () => {
|
playwrightTest.action(async () => {
|
||||||
printPlaywrightTestError(command);
|
printPlaywrightTestError(command);
|
||||||
(0, _utils.gracefullyProcessExitDoNotHang)(1);
|
(0, import_processLauncher.gracefullyProcessExitDoNotHang)(1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!process.env.PW_LANG_NAME) addExternalPlaywrightTestCommands();
|
if (!process.env.PW_LANG_NAME)
|
||||||
|
addExternalPlaywrightTestCommands();
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
program
|
||||||
|
});
|
||||||
|
|||||||
63
tvapp2/node_modules/playwright-core/lib/client/accessibility.js
generated
vendored
@@ -1,33 +1,33 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var accessibility_exports = {};
|
||||||
|
__export(accessibility_exports, {
|
||||||
|
Accessibility: () => Accessibility
|
||||||
});
|
});
|
||||||
exports.Accessibility = void 0;
|
module.exports = __toCommonJS(accessibility_exports);
|
||||||
/**
|
|
||||||
* Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
* Modifications copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function axNodeFromProtocol(axNode) {
|
function axNodeFromProtocol(axNode) {
|
||||||
const result = {
|
const result = {
|
||||||
...axNode,
|
...axNode,
|
||||||
value: axNode.valueNumber !== undefined ? axNode.valueNumber : axNode.valueString,
|
value: axNode.valueNumber !== void 0 ? axNode.valueNumber : axNode.valueString,
|
||||||
checked: axNode.checked === 'checked' ? true : axNode.checked === 'unchecked' ? false : axNode.checked,
|
checked: axNode.checked === "checked" ? true : axNode.checked === "unchecked" ? false : axNode.checked,
|
||||||
pressed: axNode.pressed === 'pressed' ? true : axNode.pressed === 'released' ? false : axNode.pressed,
|
pressed: axNode.pressed === "pressed" ? true : axNode.pressed === "released" ? false : axNode.pressed,
|
||||||
children: axNode.children ? axNode.children.map(axNodeFromProtocol) : undefined
|
children: axNode.children ? axNode.children.map(axNodeFromProtocol) : void 0
|
||||||
};
|
};
|
||||||
delete result.valueNumber;
|
delete result.valueNumber;
|
||||||
delete result.valueString;
|
delete result.valueString;
|
||||||
@@ -35,16 +35,15 @@ function axNodeFromProtocol(axNode) {
|
|||||||
}
|
}
|
||||||
class Accessibility {
|
class Accessibility {
|
||||||
constructor(channel) {
|
constructor(channel) {
|
||||||
this._channel = void 0;
|
|
||||||
this._channel = channel;
|
this._channel = channel;
|
||||||
}
|
}
|
||||||
async snapshot(options = {}) {
|
async snapshot(options = {}) {
|
||||||
const root = options.root ? options.root._elementChannel : undefined;
|
const root = options.root ? options.root._elementChannel : void 0;
|
||||||
const result = await this._channel.accessibilitySnapshot({
|
const result = await this._channel.accessibilitySnapshot({ interestingOnly: options.interestingOnly, root });
|
||||||
interestingOnly: options.interestingOnly,
|
|
||||||
root
|
|
||||||
});
|
|
||||||
return result.rootAXNode ? axNodeFromProtocol(result.rootAXNode) : null;
|
return result.rootAXNode ? axNodeFromProtocol(result.rootAXNode) : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Accessibility = Accessibility;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
Accessibility
|
||||||
|
});
|
||||||
|
|||||||
400
tvapp2/node_modules/playwright-core/lib/client/android.js
generated
vendored
@@ -1,161 +1,125 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var android_exports = {};
|
||||||
|
__export(android_exports, {
|
||||||
|
Android: () => Android,
|
||||||
|
AndroidDevice: () => AndroidDevice,
|
||||||
|
AndroidInput: () => AndroidInput,
|
||||||
|
AndroidSocket: () => AndroidSocket,
|
||||||
|
AndroidWebView: () => AndroidWebView
|
||||||
});
|
});
|
||||||
exports.AndroidWebView = exports.AndroidSocket = exports.AndroidInput = exports.AndroidDevice = exports.Android = void 0;
|
module.exports = __toCommonJS(android_exports);
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
var import_eventEmitter = require("./eventEmitter");
|
||||||
var _utils = require("../utils");
|
var import_browserContext = require("./browserContext");
|
||||||
var _events = require("./events");
|
var import_channelOwner = require("./channelOwner");
|
||||||
var _browserContext = require("./browserContext");
|
var import_errors = require("./errors");
|
||||||
var _channelOwner = require("./channelOwner");
|
var import_events = require("./events");
|
||||||
var _timeoutSettings = require("../common/timeoutSettings");
|
var import_waiter = require("./waiter");
|
||||||
var _waiter = require("./waiter");
|
var import_timeoutSettings = require("./timeoutSettings");
|
||||||
var _events2 = require("events");
|
var import_rtti = require("../utils/isomorphic/rtti");
|
||||||
var _connection = require("./connection");
|
var import_time = require("../utils/isomorphic/time");
|
||||||
var _errors = require("./errors");
|
var import_timeoutRunner = require("../utils/isomorphic/timeoutRunner");
|
||||||
var _timeoutRunner = require("../utils/timeoutRunner");
|
var import_webSocket = require("./webSocket");
|
||||||
let _Symbol$asyncDispose;
|
class Android extends import_channelOwner.ChannelOwner {
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
class Android extends _channelOwner.ChannelOwner {
|
|
||||||
static from(android) {
|
static from(android) {
|
||||||
return android._object;
|
return android._object;
|
||||||
}
|
}
|
||||||
constructor(parent, type, guid, initializer) {
|
constructor(parent, type, guid, initializer) {
|
||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
this._timeoutSettings = void 0;
|
this._timeoutSettings = new import_timeoutSettings.TimeoutSettings(this._platform);
|
||||||
this._serverLauncher = void 0;
|
|
||||||
this._timeoutSettings = new _timeoutSettings.TimeoutSettings();
|
|
||||||
}
|
}
|
||||||
setDefaultTimeout(timeout) {
|
setDefaultTimeout(timeout) {
|
||||||
this._timeoutSettings.setDefaultTimeout(timeout);
|
this._timeoutSettings.setDefaultTimeout(timeout);
|
||||||
this._channel.setDefaultTimeoutNoReply({
|
this._wrapApiCall(async () => {
|
||||||
timeout
|
await this._channel.setDefaultTimeoutNoReply({ timeout });
|
||||||
|
}, true).catch(() => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async devices(options = {}) {
|
async devices(options = {}) {
|
||||||
const {
|
const { devices } = await this._channel.devices(options);
|
||||||
devices
|
return devices.map((d) => AndroidDevice.from(d));
|
||||||
} = await this._channel.devices(options);
|
|
||||||
return devices.map(d => AndroidDevice.from(d));
|
|
||||||
}
|
}
|
||||||
async launchServer(options = {}) {
|
async launchServer(options = {}) {
|
||||||
if (!this._serverLauncher) throw new Error('Launching server is not supported');
|
if (!this._serverLauncher)
|
||||||
|
throw new Error("Launching server is not supported");
|
||||||
return await this._serverLauncher.launchServer(options);
|
return await this._serverLauncher.launchServer(options);
|
||||||
}
|
}
|
||||||
async connect(wsEndpoint, options = {}) {
|
async connect(wsEndpoint, options = {}) {
|
||||||
return await this._wrapApiCall(async () => {
|
return await this._wrapApiCall(async () => {
|
||||||
const deadline = options.timeout ? (0, _utils.monotonicTime)() + options.timeout : 0;
|
const deadline = options.timeout ? (0, import_time.monotonicTime)() + options.timeout : 0;
|
||||||
const headers = {
|
const headers = { "x-playwright-browser": "android", ...options.headers };
|
||||||
'x-playwright-browser': 'android',
|
const connectParams = { wsEndpoint, headers, slowMo: options.slowMo, timeout: options.timeout };
|
||||||
...options.headers
|
const connection = await (0, import_webSocket.connectOverWebSocket)(this._connection, connectParams);
|
||||||
};
|
|
||||||
const localUtils = this._connection.localUtils();
|
|
||||||
const connectParams = {
|
|
||||||
wsEndpoint,
|
|
||||||
headers,
|
|
||||||
slowMo: options.slowMo,
|
|
||||||
timeout: options.timeout
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
pipe
|
|
||||||
} = await localUtils._channel.connect(connectParams);
|
|
||||||
const closePipe = () => pipe.close().catch(() => {});
|
|
||||||
const connection = new _connection.Connection(localUtils, this._instrumentation);
|
|
||||||
connection.markAsRemote();
|
|
||||||
connection.on('close', closePipe);
|
|
||||||
let device;
|
let device;
|
||||||
let closeError;
|
connection.on("close", () => {
|
||||||
const onPipeClosed = () => {
|
device?._didClose();
|
||||||
var _device;
|
|
||||||
(_device = device) === null || _device === void 0 || _device._didClose();
|
|
||||||
connection.close(closeError);
|
|
||||||
};
|
|
||||||
pipe.on('closed', onPipeClosed);
|
|
||||||
connection.onmessage = message => pipe.send({
|
|
||||||
message
|
|
||||||
}).catch(onPipeClosed);
|
|
||||||
pipe.on('message', ({
|
|
||||||
message
|
|
||||||
}) => {
|
|
||||||
try {
|
|
||||||
connection.dispatch(message);
|
|
||||||
} catch (e) {
|
|
||||||
closeError = String(e);
|
|
||||||
closePipe();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
const result = await (0, _timeoutRunner.raceAgainstDeadline)(async () => {
|
const result = await (0, import_timeoutRunner.raceAgainstDeadline)(async () => {
|
||||||
const playwright = await connection.initializePlaywright();
|
const playwright = await connection.initializePlaywright();
|
||||||
if (!playwright._initializer.preConnectedAndroidDevice) {
|
if (!playwright._initializer.preConnectedAndroidDevice) {
|
||||||
closePipe();
|
connection.close();
|
||||||
throw new Error('Malformed endpoint. Did you use Android.launchServer method?');
|
throw new Error("Malformed endpoint. Did you use Android.launchServer method?");
|
||||||
}
|
}
|
||||||
device = AndroidDevice.from(playwright._initializer.preConnectedAndroidDevice);
|
device = AndroidDevice.from(playwright._initializer.preConnectedAndroidDevice);
|
||||||
device._shouldCloseConnectionOnClose = true;
|
device._shouldCloseConnectionOnClose = true;
|
||||||
device.on(_events.Events.AndroidDevice.Close, closePipe);
|
device.on(import_events.Events.AndroidDevice.Close, () => connection.close());
|
||||||
return device;
|
return device;
|
||||||
}, deadline);
|
}, deadline);
|
||||||
if (!result.timedOut) {
|
if (!result.timedOut) {
|
||||||
return result.result;
|
return result.result;
|
||||||
} else {
|
} else {
|
||||||
closePipe();
|
connection.close();
|
||||||
throw new Error(`Timeout ${options.timeout}ms exceeded`);
|
throw new Error(`Timeout ${options.timeout}ms exceeded`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Android = Android;
|
class AndroidDevice extends import_channelOwner.ChannelOwner {
|
||||||
_Symbol$asyncDispose = Symbol.asyncDispose;
|
|
||||||
class AndroidDevice extends _channelOwner.ChannelOwner {
|
|
||||||
static from(androidDevice) {
|
|
||||||
return androidDevice._object;
|
|
||||||
}
|
|
||||||
constructor(parent, type, guid, initializer) {
|
constructor(parent, type, guid, initializer) {
|
||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
this._timeoutSettings = void 0;
|
this._webViews = /* @__PURE__ */ new Map();
|
||||||
this._webViews = new Map();
|
|
||||||
this._shouldCloseConnectionOnClose = false;
|
this._shouldCloseConnectionOnClose = false;
|
||||||
this.input = void 0;
|
|
||||||
this.input = new AndroidInput(this);
|
this.input = new AndroidInput(this);
|
||||||
this._timeoutSettings = new _timeoutSettings.TimeoutSettings(parent._timeoutSettings);
|
this._timeoutSettings = new import_timeoutSettings.TimeoutSettings(this._platform, parent._timeoutSettings);
|
||||||
this._channel.on('webViewAdded', ({
|
this._channel.on("webViewAdded", ({ webView }) => this._onWebViewAdded(webView));
|
||||||
webView
|
this._channel.on("webViewRemoved", ({ socketName }) => this._onWebViewRemoved(socketName));
|
||||||
}) => this._onWebViewAdded(webView));
|
this._channel.on("close", () => this._didClose());
|
||||||
this._channel.on('webViewRemoved', ({
|
}
|
||||||
socketName
|
static from(androidDevice) {
|
||||||
}) => this._onWebViewRemoved(socketName));
|
return androidDevice._object;
|
||||||
this._channel.on('close', () => this._didClose());
|
|
||||||
}
|
}
|
||||||
_onWebViewAdded(webView) {
|
_onWebViewAdded(webView) {
|
||||||
const view = new AndroidWebView(this, webView);
|
const view = new AndroidWebView(this, webView);
|
||||||
this._webViews.set(webView.socketName, view);
|
this._webViews.set(webView.socketName, view);
|
||||||
this.emit(_events.Events.AndroidDevice.WebView, view);
|
this.emit(import_events.Events.AndroidDevice.WebView, view);
|
||||||
}
|
}
|
||||||
_onWebViewRemoved(socketName) {
|
_onWebViewRemoved(socketName) {
|
||||||
const view = this._webViews.get(socketName);
|
const view = this._webViews.get(socketName);
|
||||||
this._webViews.delete(socketName);
|
this._webViews.delete(socketName);
|
||||||
if (view) view.emit(_events.Events.AndroidWebView.Close);
|
if (view)
|
||||||
|
view.emit(import_events.Events.AndroidWebView.Close);
|
||||||
}
|
}
|
||||||
setDefaultTimeout(timeout) {
|
setDefaultTimeout(timeout) {
|
||||||
this._timeoutSettings.setDefaultTimeout(timeout);
|
this._timeoutSettings.setDefaultTimeout(timeout);
|
||||||
this._channel.setDefaultTimeoutNoReply({
|
this._wrapApiCall(async () => {
|
||||||
timeout
|
await this._channel.setDefaultTimeoutNoReply({ timeout });
|
||||||
|
}, true).catch(() => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
serial() {
|
serial() {
|
||||||
@@ -168,179 +132,124 @@ class AndroidDevice extends _channelOwner.ChannelOwner {
|
|||||||
return [...this._webViews.values()];
|
return [...this._webViews.values()];
|
||||||
}
|
}
|
||||||
async webView(selector, options) {
|
async webView(selector, options) {
|
||||||
const predicate = v => {
|
const predicate = (v) => {
|
||||||
if (selector.pkg) return v.pkg() === selector.pkg;
|
if (selector.pkg)
|
||||||
if (selector.socketName) return v._socketName() === selector.socketName;
|
return v.pkg() === selector.pkg;
|
||||||
|
if (selector.socketName)
|
||||||
|
return v._socketName() === selector.socketName;
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
const webView = [...this._webViews.values()].find(predicate);
|
const webView = [...this._webViews.values()].find(predicate);
|
||||||
if (webView) return webView;
|
if (webView)
|
||||||
return await this.waitForEvent('webview', {
|
return webView;
|
||||||
...options,
|
return await this.waitForEvent("webview", { ...options, predicate });
|
||||||
predicate
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async wait(selector, options) {
|
async wait(selector, options) {
|
||||||
await this._channel.wait({
|
await this._channel.wait({ selector: toSelectorChannel(selector), ...options });
|
||||||
selector: toSelectorChannel(selector),
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async fill(selector, text, options) {
|
async fill(selector, text, options) {
|
||||||
await this._channel.fill({
|
await this._channel.fill({ selector: toSelectorChannel(selector), text, ...options });
|
||||||
selector: toSelectorChannel(selector),
|
|
||||||
text,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async press(selector, key, options) {
|
async press(selector, key, options) {
|
||||||
await this.tap(selector, options);
|
await this.tap(selector, options);
|
||||||
await this.input.press(key);
|
await this.input.press(key);
|
||||||
}
|
}
|
||||||
async tap(selector, options) {
|
async tap(selector, options) {
|
||||||
await this._channel.tap({
|
await this._channel.tap({ selector: toSelectorChannel(selector), ...options });
|
||||||
selector: toSelectorChannel(selector),
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async drag(selector, dest, options) {
|
async drag(selector, dest, options) {
|
||||||
await this._channel.drag({
|
await this._channel.drag({ selector: toSelectorChannel(selector), dest, ...options });
|
||||||
selector: toSelectorChannel(selector),
|
|
||||||
dest,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async fling(selector, direction, options) {
|
async fling(selector, direction, options) {
|
||||||
await this._channel.fling({
|
await this._channel.fling({ selector: toSelectorChannel(selector), direction, ...options });
|
||||||
selector: toSelectorChannel(selector),
|
|
||||||
direction,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async longTap(selector, options) {
|
async longTap(selector, options) {
|
||||||
await this._channel.longTap({
|
await this._channel.longTap({ selector: toSelectorChannel(selector), ...options });
|
||||||
selector: toSelectorChannel(selector),
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async pinchClose(selector, percent, options) {
|
async pinchClose(selector, percent, options) {
|
||||||
await this._channel.pinchClose({
|
await this._channel.pinchClose({ selector: toSelectorChannel(selector), percent, ...options });
|
||||||
selector: toSelectorChannel(selector),
|
|
||||||
percent,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async pinchOpen(selector, percent, options) {
|
async pinchOpen(selector, percent, options) {
|
||||||
await this._channel.pinchOpen({
|
await this._channel.pinchOpen({ selector: toSelectorChannel(selector), percent, ...options });
|
||||||
selector: toSelectorChannel(selector),
|
|
||||||
percent,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async scroll(selector, direction, percent, options) {
|
async scroll(selector, direction, percent, options) {
|
||||||
await this._channel.scroll({
|
await this._channel.scroll({ selector: toSelectorChannel(selector), direction, percent, ...options });
|
||||||
selector: toSelectorChannel(selector),
|
|
||||||
direction,
|
|
||||||
percent,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async swipe(selector, direction, percent, options) {
|
async swipe(selector, direction, percent, options) {
|
||||||
await this._channel.swipe({
|
await this._channel.swipe({ selector: toSelectorChannel(selector), direction, percent, ...options });
|
||||||
selector: toSelectorChannel(selector),
|
|
||||||
direction,
|
|
||||||
percent,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async info(selector) {
|
async info(selector) {
|
||||||
return (await this._channel.info({
|
return (await this._channel.info({ selector: toSelectorChannel(selector) })).info;
|
||||||
selector: toSelectorChannel(selector)
|
|
||||||
})).info;
|
|
||||||
}
|
}
|
||||||
async screenshot(options = {}) {
|
async screenshot(options = {}) {
|
||||||
const {
|
const { binary } = await this._channel.screenshot();
|
||||||
binary
|
if (options.path)
|
||||||
} = await this._channel.screenshot();
|
await this._platform.fs().promises.writeFile(options.path, binary);
|
||||||
if (options.path) await _fs.default.promises.writeFile(options.path, binary);
|
|
||||||
return binary;
|
return binary;
|
||||||
}
|
}
|
||||||
async [_Symbol$asyncDispose]() {
|
async [Symbol.asyncDispose]() {
|
||||||
await this.close();
|
await this.close();
|
||||||
}
|
}
|
||||||
async close() {
|
async close() {
|
||||||
try {
|
try {
|
||||||
if (this._shouldCloseConnectionOnClose) this._connection.close();else await this._channel.close();
|
if (this._shouldCloseConnectionOnClose)
|
||||||
|
this._connection.close();
|
||||||
|
else
|
||||||
|
await this._channel.close();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if ((0, _errors.isTargetClosedError)(e)) return;
|
if ((0, import_errors.isTargetClosedError)(e))
|
||||||
|
return;
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_didClose() {
|
_didClose() {
|
||||||
this.emit(_events.Events.AndroidDevice.Close, this);
|
this.emit(import_events.Events.AndroidDevice.Close, this);
|
||||||
}
|
}
|
||||||
async shell(command) {
|
async shell(command) {
|
||||||
const {
|
const { result } = await this._channel.shell({ command });
|
||||||
result
|
|
||||||
} = await this._channel.shell({
|
|
||||||
command
|
|
||||||
});
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
async open(command) {
|
async open(command) {
|
||||||
return AndroidSocket.from((await this._channel.open({
|
return AndroidSocket.from((await this._channel.open({ command })).socket);
|
||||||
command
|
|
||||||
})).socket);
|
|
||||||
}
|
}
|
||||||
async installApk(file, options) {
|
async installApk(file, options) {
|
||||||
await this._channel.installApk({
|
await this._channel.installApk({ file: await loadFile(this._platform, file), args: options && options.args });
|
||||||
file: await loadFile(file),
|
|
||||||
args: options && options.args
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async push(file, path, options) {
|
async push(file, path, options) {
|
||||||
await this._channel.push({
|
await this._channel.push({ file: await loadFile(this._platform, file), path, mode: options ? options.mode : void 0 });
|
||||||
file: await loadFile(file),
|
|
||||||
path,
|
|
||||||
mode: options ? options.mode : undefined
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async launchBrowser(options = {}) {
|
async launchBrowser(options = {}) {
|
||||||
const contextOptions = await (0, _browserContext.prepareBrowserContextParams)(options);
|
const contextOptions = await (0, import_browserContext.prepareBrowserContextParams)(this._platform, options);
|
||||||
const result = await this._channel.launchBrowser(contextOptions);
|
const result = await this._channel.launchBrowser(contextOptions);
|
||||||
const context = _browserContext.BrowserContext.from(result.context);
|
const context = import_browserContext.BrowserContext.from(result.context);
|
||||||
context._setOptions(contextOptions, {});
|
context._setOptions(contextOptions, {});
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
async waitForEvent(event, optionsOrPredicate = {}) {
|
async waitForEvent(event, optionsOrPredicate = {}) {
|
||||||
return await this._wrapApiCall(async () => {
|
return await this._wrapApiCall(async () => {
|
||||||
const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate);
|
const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === "function" ? {} : optionsOrPredicate);
|
||||||
const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate;
|
const predicate = typeof optionsOrPredicate === "function" ? optionsOrPredicate : optionsOrPredicate.predicate;
|
||||||
const waiter = _waiter.Waiter.createForEvent(this, event);
|
const waiter = import_waiter.Waiter.createForEvent(this, event);
|
||||||
waiter.rejectOnTimeout(timeout, `Timeout ${timeout}ms exceeded while waiting for event "${event}"`);
|
waiter.rejectOnTimeout(timeout, `Timeout ${timeout}ms exceeded while waiting for event "${event}"`);
|
||||||
if (event !== _events.Events.AndroidDevice.Close) waiter.rejectOnEvent(this, _events.Events.AndroidDevice.Close, () => new _errors.TargetClosedError());
|
if (event !== import_events.Events.AndroidDevice.Close)
|
||||||
|
waiter.rejectOnEvent(this, import_events.Events.AndroidDevice.Close, () => new import_errors.TargetClosedError());
|
||||||
const result = await waiter.waitForEvent(this, event, predicate);
|
const result = await waiter.waitForEvent(this, event, predicate);
|
||||||
waiter.dispose();
|
waiter.dispose();
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.AndroidDevice = AndroidDevice;
|
class AndroidSocket extends import_channelOwner.ChannelOwner {
|
||||||
class AndroidSocket extends _channelOwner.ChannelOwner {
|
|
||||||
static from(androidDevice) {
|
static from(androidDevice) {
|
||||||
return androidDevice._object;
|
return androidDevice._object;
|
||||||
}
|
}
|
||||||
constructor(parent, type, guid, initializer) {
|
constructor(parent, type, guid, initializer) {
|
||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
this._channel.on('data', ({
|
this._channel.on("data", ({ data }) => this.emit(import_events.Events.AndroidSocket.Data, data));
|
||||||
data
|
this._channel.on("close", () => this.emit(import_events.Events.AndroidSocket.Close));
|
||||||
}) => this.emit(_events.Events.AndroidSocket.Data, data));
|
|
||||||
this._channel.on('close', () => this.emit(_events.Events.AndroidSocket.Close));
|
|
||||||
}
|
}
|
||||||
async write(data) {
|
async write(data) {
|
||||||
await this._channel.write({
|
await this._channel.write({ data });
|
||||||
data
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async close() {
|
async close() {
|
||||||
await this._channel.close();
|
await this._channel.close();
|
||||||
@@ -349,46 +258,31 @@ class AndroidSocket extends _channelOwner.ChannelOwner {
|
|||||||
await this.close();
|
await this.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.AndroidSocket = AndroidSocket;
|
async function loadFile(platform, file) {
|
||||||
async function loadFile(file) {
|
if ((0, import_rtti.isString)(file))
|
||||||
if ((0, _utils.isString)(file)) return await _fs.default.promises.readFile(file);
|
return await platform.fs().promises.readFile(file);
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
class AndroidInput {
|
class AndroidInput {
|
||||||
constructor(device) {
|
constructor(device) {
|
||||||
this._device = void 0;
|
|
||||||
this._device = device;
|
this._device = device;
|
||||||
}
|
}
|
||||||
async type(text) {
|
async type(text) {
|
||||||
await this._device._channel.inputType({
|
await this._device._channel.inputType({ text });
|
||||||
text
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async press(key) {
|
async press(key) {
|
||||||
await this._device._channel.inputPress({
|
await this._device._channel.inputPress({ key });
|
||||||
key
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async tap(point) {
|
async tap(point) {
|
||||||
await this._device._channel.inputTap({
|
await this._device._channel.inputTap({ point });
|
||||||
point
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async swipe(from, segments, steps) {
|
async swipe(from, segments, steps) {
|
||||||
await this._device._channel.inputSwipe({
|
await this._device._channel.inputSwipe({ segments, steps });
|
||||||
segments,
|
|
||||||
steps
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async drag(from, to, steps) {
|
async drag(from, to, steps) {
|
||||||
await this._device._channel.inputDrag({
|
await this._device._channel.inputDrag({ from, to, steps });
|
||||||
from,
|
|
||||||
to,
|
|
||||||
steps
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.AndroidInput = AndroidInput;
|
|
||||||
function toSelectorChannel(selector) {
|
function toSelectorChannel(selector) {
|
||||||
const {
|
const {
|
||||||
checkable,
|
checkable,
|
||||||
@@ -409,10 +303,12 @@ function toSelectorChannel(selector) {
|
|||||||
selected,
|
selected,
|
||||||
text
|
text
|
||||||
} = selector;
|
} = selector;
|
||||||
const toRegex = value => {
|
const toRegex = (value) => {
|
||||||
if (value === undefined) return undefined;
|
if (value === void 0)
|
||||||
if ((0, _utils.isRegExp)(value)) return value.source;
|
return void 0;
|
||||||
return '^' + value.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d') + '$';
|
if ((0, import_rtti.isRegExp)(value))
|
||||||
|
return value.source;
|
||||||
|
return "^" + value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d") + "$";
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
checkable,
|
checkable,
|
||||||
@@ -427,24 +323,16 @@ function toSelectorChannel(selector) {
|
|||||||
enabled,
|
enabled,
|
||||||
focusable,
|
focusable,
|
||||||
focused,
|
focused,
|
||||||
hasChild: hasChild ? {
|
hasChild: hasChild ? { selector: toSelectorChannel(hasChild.selector) } : void 0,
|
||||||
selector: toSelectorChannel(hasChild.selector)
|
hasDescendant: hasDescendant ? { selector: toSelectorChannel(hasDescendant.selector), maxDepth: hasDescendant.maxDepth } : void 0,
|
||||||
} : undefined,
|
|
||||||
hasDescendant: hasDescendant ? {
|
|
||||||
selector: toSelectorChannel(hasDescendant.selector),
|
|
||||||
maxDepth: hasDescendant.maxDepth
|
|
||||||
} : undefined,
|
|
||||||
longClickable,
|
longClickable,
|
||||||
scrollable,
|
scrollable,
|
||||||
selected
|
selected
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
class AndroidWebView extends _events2.EventEmitter {
|
class AndroidWebView extends import_eventEmitter.EventEmitter {
|
||||||
constructor(device, data) {
|
constructor(device, data) {
|
||||||
super();
|
super(device._platform);
|
||||||
this._device = void 0;
|
|
||||||
this._data = void 0;
|
|
||||||
this._pagePromise = void 0;
|
|
||||||
this._device = device;
|
this._device = device;
|
||||||
this._data = data;
|
this._data = data;
|
||||||
}
|
}
|
||||||
@@ -458,16 +346,20 @@ class AndroidWebView extends _events2.EventEmitter {
|
|||||||
return this._data.socketName;
|
return this._data.socketName;
|
||||||
}
|
}
|
||||||
async page() {
|
async page() {
|
||||||
if (!this._pagePromise) this._pagePromise = this._fetchPage();
|
if (!this._pagePromise)
|
||||||
|
this._pagePromise = this._fetchPage();
|
||||||
return await this._pagePromise;
|
return await this._pagePromise;
|
||||||
}
|
}
|
||||||
async _fetchPage() {
|
async _fetchPage() {
|
||||||
const {
|
const { context } = await this._device._channel.connectToWebView({ socketName: this._data.socketName });
|
||||||
context
|
return import_browserContext.BrowserContext.from(context).pages()[0];
|
||||||
} = await this._device._channel.connectToWebView({
|
|
||||||
socketName: this._data.socketName
|
|
||||||
});
|
|
||||||
return _browserContext.BrowserContext.from(context).pages()[0];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.AndroidWebView = AndroidWebView;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
Android,
|
||||||
|
AndroidDevice,
|
||||||
|
AndroidInput,
|
||||||
|
AndroidSocket,
|
||||||
|
AndroidWebView
|
||||||
|
});
|
||||||
|
|||||||
414
tvapp2/node_modules/playwright-core/lib/client/api.js
generated
vendored
@@ -1,285 +1,137 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
});
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
Object.defineProperty(exports, "APIRequest", {
|
var __export = (target, all) => {
|
||||||
enumerable: true,
|
for (var name in all)
|
||||||
get: function () {
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
return _fetch.APIRequest;
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
}
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var api_exports = {};
|
||||||
|
__export(api_exports, {
|
||||||
|
APIRequest: () => import_fetch.APIRequest,
|
||||||
|
APIRequestContext: () => import_fetch.APIRequestContext,
|
||||||
|
APIResponse: () => import_fetch.APIResponse,
|
||||||
|
Accessibility: () => import_accessibility.Accessibility,
|
||||||
|
Android: () => import_android.Android,
|
||||||
|
AndroidDevice: () => import_android.AndroidDevice,
|
||||||
|
AndroidInput: () => import_android.AndroidInput,
|
||||||
|
AndroidSocket: () => import_android.AndroidSocket,
|
||||||
|
AndroidWebView: () => import_android.AndroidWebView,
|
||||||
|
Browser: () => import_browser.Browser,
|
||||||
|
BrowserContext: () => import_browserContext.BrowserContext,
|
||||||
|
BrowserType: () => import_browserType.BrowserType,
|
||||||
|
CDPSession: () => import_cdpSession.CDPSession,
|
||||||
|
Clock: () => import_clock.Clock,
|
||||||
|
ConsoleMessage: () => import_consoleMessage.ConsoleMessage,
|
||||||
|
Coverage: () => import_coverage.Coverage,
|
||||||
|
Dialog: () => import_dialog.Dialog,
|
||||||
|
Download: () => import_download.Download,
|
||||||
|
Electron: () => import_electron.Electron,
|
||||||
|
ElectronApplication: () => import_electron.ElectronApplication,
|
||||||
|
ElementHandle: () => import_elementHandle.ElementHandle,
|
||||||
|
FileChooser: () => import_fileChooser.FileChooser,
|
||||||
|
Frame: () => import_frame.Frame,
|
||||||
|
FrameLocator: () => import_locator.FrameLocator,
|
||||||
|
JSHandle: () => import_jsHandle.JSHandle,
|
||||||
|
Keyboard: () => import_input.Keyboard,
|
||||||
|
Locator: () => import_locator.Locator,
|
||||||
|
Mouse: () => import_input.Mouse,
|
||||||
|
Page: () => import_page.Page,
|
||||||
|
Playwright: () => import_playwright.Playwright,
|
||||||
|
Request: () => import_network.Request,
|
||||||
|
Response: () => import_network.Response,
|
||||||
|
Route: () => import_network.Route,
|
||||||
|
Selectors: () => import_selectors.Selectors,
|
||||||
|
TimeoutError: () => import_errors.TimeoutError,
|
||||||
|
Touchscreen: () => import_input.Touchscreen,
|
||||||
|
Tracing: () => import_tracing.Tracing,
|
||||||
|
Video: () => import_video.Video,
|
||||||
|
WebError: () => import_webError.WebError,
|
||||||
|
WebSocket: () => import_network.WebSocket,
|
||||||
|
WebSocketRoute: () => import_network.WebSocketRoute,
|
||||||
|
Worker: () => import_worker.Worker
|
||||||
});
|
});
|
||||||
Object.defineProperty(exports, "APIRequestContext", {
|
module.exports = __toCommonJS(api_exports);
|
||||||
enumerable: true,
|
var import_accessibility = require("./accessibility");
|
||||||
get: function () {
|
var import_android = require("./android");
|
||||||
return _fetch.APIRequestContext;
|
var import_browser = require("./browser");
|
||||||
}
|
var import_browserContext = require("./browserContext");
|
||||||
|
var import_browserType = require("./browserType");
|
||||||
|
var import_clock = require("./clock");
|
||||||
|
var import_consoleMessage = require("./consoleMessage");
|
||||||
|
var import_coverage = require("./coverage");
|
||||||
|
var import_dialog = require("./dialog");
|
||||||
|
var import_download = require("./download");
|
||||||
|
var import_electron = require("./electron");
|
||||||
|
var import_locator = require("./locator");
|
||||||
|
var import_elementHandle = require("./elementHandle");
|
||||||
|
var import_fileChooser = require("./fileChooser");
|
||||||
|
var import_errors = require("./errors");
|
||||||
|
var import_frame = require("./frame");
|
||||||
|
var import_input = require("./input");
|
||||||
|
var import_jsHandle = require("./jsHandle");
|
||||||
|
var import_network = require("./network");
|
||||||
|
var import_fetch = require("./fetch");
|
||||||
|
var import_page = require("./page");
|
||||||
|
var import_selectors = require("./selectors");
|
||||||
|
var import_tracing = require("./tracing");
|
||||||
|
var import_video = require("./video");
|
||||||
|
var import_worker = require("./worker");
|
||||||
|
var import_cdpSession = require("./cdpSession");
|
||||||
|
var import_playwright = require("./playwright");
|
||||||
|
var import_webError = require("./webError");
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
APIRequest,
|
||||||
|
APIRequestContext,
|
||||||
|
APIResponse,
|
||||||
|
Accessibility,
|
||||||
|
Android,
|
||||||
|
AndroidDevice,
|
||||||
|
AndroidInput,
|
||||||
|
AndroidSocket,
|
||||||
|
AndroidWebView,
|
||||||
|
Browser,
|
||||||
|
BrowserContext,
|
||||||
|
BrowserType,
|
||||||
|
CDPSession,
|
||||||
|
Clock,
|
||||||
|
ConsoleMessage,
|
||||||
|
Coverage,
|
||||||
|
Dialog,
|
||||||
|
Download,
|
||||||
|
Electron,
|
||||||
|
ElectronApplication,
|
||||||
|
ElementHandle,
|
||||||
|
FileChooser,
|
||||||
|
Frame,
|
||||||
|
FrameLocator,
|
||||||
|
JSHandle,
|
||||||
|
Keyboard,
|
||||||
|
Locator,
|
||||||
|
Mouse,
|
||||||
|
Page,
|
||||||
|
Playwright,
|
||||||
|
Request,
|
||||||
|
Response,
|
||||||
|
Route,
|
||||||
|
Selectors,
|
||||||
|
TimeoutError,
|
||||||
|
Touchscreen,
|
||||||
|
Tracing,
|
||||||
|
Video,
|
||||||
|
WebError,
|
||||||
|
WebSocket,
|
||||||
|
WebSocketRoute,
|
||||||
|
Worker
|
||||||
});
|
});
|
||||||
Object.defineProperty(exports, "APIResponse", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _fetch.APIResponse;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Accessibility", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _accessibility.Accessibility;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Android", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _android.Android;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "AndroidDevice", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _android.AndroidDevice;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "AndroidInput", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _android.AndroidInput;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "AndroidSocket", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _android.AndroidSocket;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "AndroidWebView", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _android.AndroidWebView;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Browser", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _browser.Browser;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "BrowserContext", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _browserContext.BrowserContext;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "BrowserType", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _browserType.BrowserType;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "CDPSession", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _cdpSession.CDPSession;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Clock", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _clock.Clock;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "ConsoleMessage", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _consoleMessage.ConsoleMessage;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Coverage", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _coverage.Coverage;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Dialog", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _dialog.Dialog;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Download", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _download.Download;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Electron", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _electron.Electron;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "ElectronApplication", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _electron.ElectronApplication;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "ElementHandle", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _elementHandle.ElementHandle;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "FileChooser", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _fileChooser.FileChooser;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Frame", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _frame.Frame;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "FrameLocator", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _locator.FrameLocator;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "JSHandle", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _jsHandle.JSHandle;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Keyboard", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _input.Keyboard;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Locator", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _locator.Locator;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Mouse", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _input.Mouse;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Page", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _page.Page;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Playwright", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _playwright.Playwright;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Request", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _network.Request;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Response", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _network.Response;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Route", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _network.Route;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Selectors", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _selectors.Selectors;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "TimeoutError", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _errors.TimeoutError;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Touchscreen", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _input.Touchscreen;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Tracing", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _tracing.Tracing;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Video", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _video.Video;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "WebError", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _webError.WebError;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "WebSocket", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _network.WebSocket;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "WebSocketRoute", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _network.WebSocketRoute;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "Worker", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _worker.Worker;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var _accessibility = require("./accessibility");
|
|
||||||
var _android = require("./android");
|
|
||||||
var _browser = require("./browser");
|
|
||||||
var _browserContext = require("./browserContext");
|
|
||||||
var _browserType = require("./browserType");
|
|
||||||
var _clock = require("./clock");
|
|
||||||
var _consoleMessage = require("./consoleMessage");
|
|
||||||
var _coverage = require("./coverage");
|
|
||||||
var _dialog = require("./dialog");
|
|
||||||
var _download = require("./download");
|
|
||||||
var _electron = require("./electron");
|
|
||||||
var _locator = require("./locator");
|
|
||||||
var _elementHandle = require("./elementHandle");
|
|
||||||
var _fileChooser = require("./fileChooser");
|
|
||||||
var _errors = require("./errors");
|
|
||||||
var _frame = require("./frame");
|
|
||||||
var _input = require("./input");
|
|
||||||
var _jsHandle = require("./jsHandle");
|
|
||||||
var _network = require("./network");
|
|
||||||
var _fetch = require("./fetch");
|
|
||||||
var _page = require("./page");
|
|
||||||
var _selectors = require("./selectors");
|
|
||||||
var _tracing = require("./tracing");
|
|
||||||
var _video = require("./video");
|
|
||||||
var _worker = require("./worker");
|
|
||||||
var _cdpSession = require("./cdpSession");
|
|
||||||
var _playwright = require("./playwright");
|
|
||||||
var _webError = require("./webError");
|
|
||||||
78
tvapp2/node_modules/playwright-core/lib/client/artifact.js
generated
vendored
@@ -1,51 +1,48 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var artifact_exports = {};
|
||||||
|
__export(artifact_exports, {
|
||||||
|
Artifact: () => Artifact
|
||||||
});
|
});
|
||||||
exports.Artifact = void 0;
|
module.exports = __toCommonJS(artifact_exports);
|
||||||
var fs = _interopRequireWildcard(require("fs"));
|
var import_channelOwner = require("./channelOwner");
|
||||||
var _stream = require("./stream");
|
var import_stream = require("./stream");
|
||||||
var _fileUtils = require("../utils/fileUtils");
|
var import_fileUtils = require("./fileUtils");
|
||||||
var _channelOwner = require("./channelOwner");
|
class Artifact extends import_channelOwner.ChannelOwner {
|
||||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
||||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Artifact extends _channelOwner.ChannelOwner {
|
|
||||||
static from(channel) {
|
static from(channel) {
|
||||||
return channel._object;
|
return channel._object;
|
||||||
}
|
}
|
||||||
async pathAfterFinished() {
|
async pathAfterFinished() {
|
||||||
if (this._connection.isRemote()) throw new Error(`Path is not available when connecting remotely. Use saveAs() to save a local copy.`);
|
if (this._connection.isRemote())
|
||||||
|
throw new Error(`Path is not available when connecting remotely. Use saveAs() to save a local copy.`);
|
||||||
return (await this._channel.pathAfterFinished()).value;
|
return (await this._channel.pathAfterFinished()).value;
|
||||||
}
|
}
|
||||||
async saveAs(path) {
|
async saveAs(path) {
|
||||||
if (!this._connection.isRemote()) {
|
if (!this._connection.isRemote()) {
|
||||||
await this._channel.saveAs({
|
await this._channel.saveAs({ path });
|
||||||
path
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const result = await this._channel.saveAsStream();
|
const result = await this._channel.saveAsStream();
|
||||||
const stream = _stream.Stream.from(result.stream);
|
const stream = import_stream.Stream.from(result.stream);
|
||||||
await (0, _fileUtils.mkdirIfNeeded)(path);
|
await (0, import_fileUtils.mkdirIfNeeded)(this._platform, path);
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
stream.stream().pipe(fs.createWriteStream(path)).on('finish', resolve).on('error', reject);
|
stream.stream().pipe(this._platform.fs().createWriteStream(path)).on("finish", resolve).on("error", reject);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async failure() {
|
async failure() {
|
||||||
@@ -53,20 +50,20 @@ class Artifact extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
async createReadStream() {
|
async createReadStream() {
|
||||||
const result = await this._channel.stream();
|
const result = await this._channel.stream();
|
||||||
const stream = _stream.Stream.from(result.stream);
|
const stream = import_stream.Stream.from(result.stream);
|
||||||
return stream.stream();
|
return stream.stream();
|
||||||
}
|
}
|
||||||
async readIntoBuffer() {
|
async readIntoBuffer() {
|
||||||
const stream = await this.createReadStream();
|
const stream = await this.createReadStream();
|
||||||
return await new Promise((resolve, reject) => {
|
return await new Promise((resolve, reject) => {
|
||||||
const chunks = [];
|
const chunks = [];
|
||||||
stream.on('data', chunk => {
|
stream.on("data", (chunk) => {
|
||||||
chunks.push(chunk);
|
chunks.push(chunk);
|
||||||
});
|
});
|
||||||
stream.on('end', () => {
|
stream.on("end", () => {
|
||||||
resolve(Buffer.concat(chunks));
|
resolve(Buffer.concat(chunks));
|
||||||
});
|
});
|
||||||
stream.on('error', reject);
|
stream.on("error", reject);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async cancel() {
|
async cancel() {
|
||||||
@@ -76,4 +73,7 @@ class Artifact extends _channelOwner.ChannelOwner {
|
|||||||
return await this._channel.delete();
|
return await this._channel.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Artifact = Artifact;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
Artifact
|
||||||
|
});
|
||||||
|
|||||||
127
tvapp2/node_modules/playwright-core/lib/client/browser.js
generated
vendored
@@ -1,55 +1,46 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
});
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
exports.Browser = void 0;
|
var __export = (target, all) => {
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
for (var name in all)
|
||||||
var _browserContext = require("./browserContext");
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
var _channelOwner = require("./channelOwner");
|
};
|
||||||
var _events = require("./events");
|
var __copyProps = (to, from, except, desc) => {
|
||||||
var _errors = require("./errors");
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
var _cdpSession = require("./cdpSession");
|
for (let key of __getOwnPropNames(from))
|
||||||
var _artifact = require("./artifact");
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
var _utils = require("../utils");
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
let _Symbol$asyncDispose;
|
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
_Symbol$asyncDispose = Symbol.asyncDispose;
|
|
||||||
class Browser extends _channelOwner.ChannelOwner {
|
|
||||||
static from(browser) {
|
|
||||||
return browser._object;
|
|
||||||
}
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var browser_exports = {};
|
||||||
|
__export(browser_exports, {
|
||||||
|
Browser: () => Browser
|
||||||
|
});
|
||||||
|
module.exports = __toCommonJS(browser_exports);
|
||||||
|
var import_artifact = require("./artifact");
|
||||||
|
var import_browserContext = require("./browserContext");
|
||||||
|
var import_cdpSession = require("./cdpSession");
|
||||||
|
var import_channelOwner = require("./channelOwner");
|
||||||
|
var import_errors = require("./errors");
|
||||||
|
var import_events = require("./events");
|
||||||
|
var import_fileUtils = require("./fileUtils");
|
||||||
|
class Browser extends import_channelOwner.ChannelOwner {
|
||||||
constructor(parent, type, guid, initializer) {
|
constructor(parent, type, guid, initializer) {
|
||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
this._contexts = new Set();
|
this._contexts = /* @__PURE__ */ new Set();
|
||||||
this._isConnected = true;
|
this._isConnected = true;
|
||||||
this._closedPromise = void 0;
|
|
||||||
this._shouldCloseConnectionOnClose = false;
|
this._shouldCloseConnectionOnClose = false;
|
||||||
this._browserType = void 0;
|
|
||||||
this._options = {};
|
this._options = {};
|
||||||
this._name = void 0;
|
|
||||||
this._path = void 0;
|
|
||||||
// Used from @playwright/test fixtures.
|
|
||||||
this._connectHeaders = void 0;
|
|
||||||
this._closeReason = void 0;
|
|
||||||
this._name = initializer.name;
|
this._name = initializer.name;
|
||||||
this._channel.on('close', () => this._didClose());
|
this._channel.on("close", () => this._didClose());
|
||||||
this._closedPromise = new Promise(f => this.once(_events.Events.Browser.Disconnected, f));
|
this._closedPromise = new Promise((f) => this.once(import_events.Events.Browser.Disconnected, f));
|
||||||
|
}
|
||||||
|
static from(browser) {
|
||||||
|
return browser._object;
|
||||||
}
|
}
|
||||||
browserType() {
|
browserType() {
|
||||||
return this._browserType;
|
return this._browserType;
|
||||||
@@ -61,7 +52,8 @@ class Browser extends _channelOwner.ChannelOwner {
|
|||||||
return await this._wrapApiCall(async () => {
|
return await this._wrapApiCall(async () => {
|
||||||
for (const context of this._contexts) {
|
for (const context of this._contexts) {
|
||||||
await this._browserType._willCloseContext(context);
|
await this._browserType._willCloseContext(context);
|
||||||
for (const page of context.pages()) page._onClose();
|
for (const page of context.pages())
|
||||||
|
page._onClose();
|
||||||
context._onClose();
|
context._onClose();
|
||||||
}
|
}
|
||||||
return await this._innerNewContext(options, true);
|
return await this._innerNewContext(options, true);
|
||||||
@@ -69,19 +61,14 @@ class Browser extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
async _stopPendingOperations(reason) {
|
async _stopPendingOperations(reason) {
|
||||||
return await this._wrapApiCall(async () => {
|
return await this._wrapApiCall(async () => {
|
||||||
await this._channel.stopPendingOperations({
|
await this._channel.stopPendingOperations({ reason });
|
||||||
reason
|
|
||||||
});
|
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
async _innerNewContext(options = {}, forReuse) {
|
async _innerNewContext(options = {}, forReuse) {
|
||||||
options = {
|
options = { ...this._browserType._playwright._defaultContextOptions, ...options };
|
||||||
...this._browserType._defaultContextOptions,
|
const contextOptions = await (0, import_browserContext.prepareBrowserContextParams)(this._platform, options);
|
||||||
...options
|
|
||||||
};
|
|
||||||
const contextOptions = await (0, _browserContext.prepareBrowserContextParams)(options);
|
|
||||||
const response = forReuse ? await this._channel.newContextForReuse(contextOptions) : await this._channel.newContext(contextOptions);
|
const response = forReuse ? await this._channel.newContextForReuse(contextOptions) : await this._channel.newContext(contextOptions);
|
||||||
const context = _browserContext.BrowserContext.from(response.context);
|
const context = import_browserContext.BrowserContext.from(response.context);
|
||||||
await this._browserType._didCreateContext(context, contextOptions, this._options, options.logger || this._logger);
|
await this._browserType._didCreateContext(context, contextOptions, this._options, options.logger || this._logger);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
@@ -104,42 +91,46 @@ class Browser extends _channelOwner.ChannelOwner {
|
|||||||
return this._isConnected;
|
return this._isConnected;
|
||||||
}
|
}
|
||||||
async newBrowserCDPSession() {
|
async newBrowserCDPSession() {
|
||||||
return _cdpSession.CDPSession.from((await this._channel.newBrowserCDPSession()).session);
|
return import_cdpSession.CDPSession.from((await this._channel.newBrowserCDPSession()).session);
|
||||||
}
|
}
|
||||||
async startTracing(page, options = {}) {
|
async startTracing(page, options = {}) {
|
||||||
this._path = options.path;
|
this._path = options.path;
|
||||||
await this._channel.startTracing({
|
await this._channel.startTracing({ ...options, page: page ? page._channel : void 0 });
|
||||||
...options,
|
|
||||||
page: page ? page._channel : undefined
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async stopTracing() {
|
async stopTracing() {
|
||||||
const artifact = _artifact.Artifact.from((await this._channel.stopTracing()).artifact);
|
const artifact = import_artifact.Artifact.from((await this._channel.stopTracing()).artifact);
|
||||||
const buffer = await artifact.readIntoBuffer();
|
const buffer = await artifact.readIntoBuffer();
|
||||||
await artifact.delete();
|
await artifact.delete();
|
||||||
if (this._path) {
|
if (this._path) {
|
||||||
await (0, _utils.mkdirIfNeeded)(this._path);
|
await (0, import_fileUtils.mkdirIfNeeded)(this._platform, this._path);
|
||||||
await _fs.default.promises.writeFile(this._path, buffer);
|
await this._platform.fs().promises.writeFile(this._path, buffer);
|
||||||
this._path = undefined;
|
this._path = void 0;
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
async [_Symbol$asyncDispose]() {
|
async [Symbol.asyncDispose]() {
|
||||||
await this.close();
|
await this.close();
|
||||||
}
|
}
|
||||||
async close(options = {}) {
|
async close(options = {}) {
|
||||||
this._closeReason = options.reason;
|
this._closeReason = options.reason;
|
||||||
try {
|
try {
|
||||||
if (this._shouldCloseConnectionOnClose) this._connection.close();else await this._channel.close(options);
|
if (this._shouldCloseConnectionOnClose)
|
||||||
|
this._connection.close();
|
||||||
|
else
|
||||||
|
await this._channel.close(options);
|
||||||
await this._closedPromise;
|
await this._closedPromise;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if ((0, _errors.isTargetClosedError)(e)) return;
|
if ((0, import_errors.isTargetClosedError)(e))
|
||||||
|
return;
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_didClose() {
|
_didClose() {
|
||||||
this._isConnected = false;
|
this._isConnected = false;
|
||||||
this.emit(_events.Events.Browser.Disconnected, this);
|
this.emit(import_events.Events.Browser.Disconnected, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Browser = Browser;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
Browser
|
||||||
|
});
|
||||||
|
|||||||
652
tvapp2/node_modules/playwright-core/lib/client/browserContext.js
generated
vendored
@@ -1,250 +1,244 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __create = Object.create;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __defProp = Object.defineProperty;
|
||||||
value: true
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __getProtoOf = Object.getPrototypeOf;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||||
|
// If the importer is in node compatibility mode or this is not an ESM
|
||||||
|
// file that has been converted to a CommonJS file using a Babel-
|
||||||
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||||
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||||
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||||
|
mod
|
||||||
|
));
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var browserContext_exports = {};
|
||||||
|
__export(browserContext_exports, {
|
||||||
|
BrowserContext: () => BrowserContext,
|
||||||
|
prepareBrowserContextParams: () => prepareBrowserContextParams,
|
||||||
|
toClientCertificatesProtocol: () => toClientCertificatesProtocol
|
||||||
});
|
});
|
||||||
exports.BrowserContext = void 0;
|
module.exports = __toCommonJS(browserContext_exports);
|
||||||
exports.prepareBrowserContextParams = prepareBrowserContextParams;
|
var import_artifact = require("./artifact");
|
||||||
exports.toClientCertificatesProtocol = toClientCertificatesProtocol;
|
var import_browser = require("./browser");
|
||||||
var _page = require("./page");
|
var import_cdpSession = require("./cdpSession");
|
||||||
var _frame = require("./frame");
|
var import_channelOwner = require("./channelOwner");
|
||||||
var network = _interopRequireWildcard(require("./network"));
|
var import_clientHelper = require("./clientHelper");
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
var import_clock = require("./clock");
|
||||||
var _path = _interopRequireDefault(require("path"));
|
var import_consoleMessage = require("./consoleMessage");
|
||||||
var _channelOwner = require("./channelOwner");
|
var import_dialog = require("./dialog");
|
||||||
var _clientHelper = require("./clientHelper");
|
var import_errors = require("./errors");
|
||||||
var _browser = require("./browser");
|
var import_events = require("./events");
|
||||||
var _worker = require("./worker");
|
var import_fetch = require("./fetch");
|
||||||
var _events = require("./events");
|
var import_frame = require("./frame");
|
||||||
var _timeoutSettings = require("../common/timeoutSettings");
|
var import_harRouter = require("./harRouter");
|
||||||
var _waiter = require("./waiter");
|
var network = __toESM(require("./network"));
|
||||||
var _utils = require("../utils");
|
var import_page = require("./page");
|
||||||
var _cdpSession = require("./cdpSession");
|
var import_tracing = require("./tracing");
|
||||||
var _tracing = require("./tracing");
|
var import_waiter = require("./waiter");
|
||||||
var _artifact = require("./artifact");
|
var import_webError = require("./webError");
|
||||||
var _fetch = require("./fetch");
|
var import_worker = require("./worker");
|
||||||
var _stackTrace = require("../utils/stackTrace");
|
var import_timeoutSettings = require("./timeoutSettings");
|
||||||
var _harRouter = require("./harRouter");
|
var import_fileUtils = require("./fileUtils");
|
||||||
var _consoleMessage = require("./consoleMessage");
|
var import_headers = require("../utils/isomorphic/headers");
|
||||||
var _dialog = require("./dialog");
|
var import_urlMatch = require("../utils/isomorphic/urlMatch");
|
||||||
var _webError = require("./webError");
|
var import_rtti = require("../utils/isomorphic/rtti");
|
||||||
var _errors = require("./errors");
|
var import_stackTrace = require("../utils/isomorphic/stackTrace");
|
||||||
var _clock = require("./clock");
|
class BrowserContext extends import_channelOwner.ChannelOwner {
|
||||||
let _Symbol$asyncDispose;
|
constructor(parent, type, guid, initializer) {
|
||||||
/**
|
super(parent, type, guid, initializer);
|
||||||
* Copyright 2017 Google Inc. All rights reserved.
|
this._pages = /* @__PURE__ */ new Set();
|
||||||
* Modifications copyright (c) Microsoft Corporation.
|
this._routes = [];
|
||||||
*
|
this._webSocketRoutes = [];
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
this._browser = null;
|
||||||
* you may not use this file except in compliance with the License.
|
this._bindings = /* @__PURE__ */ new Map();
|
||||||
* You may obtain a copy of the License at
|
this._options = {};
|
||||||
*
|
this._backgroundPages = /* @__PURE__ */ new Set();
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
this._serviceWorkers = /* @__PURE__ */ new Set();
|
||||||
*
|
this._harRecorders = /* @__PURE__ */ new Map();
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
this._closeWasCalled = false;
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
this._harRouters = [];
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
this._timeoutSettings = new import_timeoutSettings.TimeoutSettings(this._platform);
|
||||||
* See the License for the specific language governing permissions and
|
if (parent instanceof import_browser.Browser)
|
||||||
* limitations under the License.
|
this._browser = parent;
|
||||||
*/
|
this._browser?._contexts.add(this);
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
this._isChromium = this._browser?._name === "chromium";
|
||||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
this.tracing = import_tracing.Tracing.from(initializer.tracing);
|
||||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
this.request = import_fetch.APIRequestContext.from(initializer.requestContext);
|
||||||
_Symbol$asyncDispose = Symbol.asyncDispose;
|
this.clock = new import_clock.Clock(this);
|
||||||
class BrowserContext extends _channelOwner.ChannelOwner {
|
this._channel.on("bindingCall", ({ binding }) => this._onBinding(import_page.BindingCall.from(binding)));
|
||||||
|
this._channel.on("close", () => this._onClose());
|
||||||
|
this._channel.on("page", ({ page }) => this._onPage(import_page.Page.from(page)));
|
||||||
|
this._channel.on("route", ({ route }) => this._onRoute(network.Route.from(route)));
|
||||||
|
this._channel.on("webSocketRoute", ({ webSocketRoute }) => this._onWebSocketRoute(network.WebSocketRoute.from(webSocketRoute)));
|
||||||
|
this._channel.on("backgroundPage", ({ page }) => {
|
||||||
|
const backgroundPage = import_page.Page.from(page);
|
||||||
|
this._backgroundPages.add(backgroundPage);
|
||||||
|
this.emit(import_events.Events.BrowserContext.BackgroundPage, backgroundPage);
|
||||||
|
});
|
||||||
|
this._channel.on("serviceWorker", ({ worker }) => {
|
||||||
|
const serviceWorker = import_worker.Worker.from(worker);
|
||||||
|
serviceWorker._context = this;
|
||||||
|
this._serviceWorkers.add(serviceWorker);
|
||||||
|
this.emit(import_events.Events.BrowserContext.ServiceWorker, serviceWorker);
|
||||||
|
});
|
||||||
|
this._channel.on("console", (event) => {
|
||||||
|
const consoleMessage = new import_consoleMessage.ConsoleMessage(this._platform, event);
|
||||||
|
this.emit(import_events.Events.BrowserContext.Console, consoleMessage);
|
||||||
|
const page = consoleMessage.page();
|
||||||
|
if (page)
|
||||||
|
page.emit(import_events.Events.Page.Console, consoleMessage);
|
||||||
|
});
|
||||||
|
this._channel.on("pageError", ({ error, page }) => {
|
||||||
|
const pageObject = import_page.Page.from(page);
|
||||||
|
const parsedError = (0, import_errors.parseError)(error);
|
||||||
|
this.emit(import_events.Events.BrowserContext.WebError, new import_webError.WebError(pageObject, parsedError));
|
||||||
|
if (pageObject)
|
||||||
|
pageObject.emit(import_events.Events.Page.PageError, parsedError);
|
||||||
|
});
|
||||||
|
this._channel.on("dialog", ({ dialog }) => {
|
||||||
|
const dialogObject = import_dialog.Dialog.from(dialog);
|
||||||
|
let hasListeners = this.emit(import_events.Events.BrowserContext.Dialog, dialogObject);
|
||||||
|
const page = dialogObject.page();
|
||||||
|
if (page)
|
||||||
|
hasListeners = page.emit(import_events.Events.Page.Dialog, dialogObject) || hasListeners;
|
||||||
|
if (!hasListeners) {
|
||||||
|
if (dialogObject.type() === "beforeunload")
|
||||||
|
dialog.accept({}).catch(() => {
|
||||||
|
});
|
||||||
|
else
|
||||||
|
dialog.dismiss().catch(() => {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._channel.on("request", ({ request, page }) => this._onRequest(network.Request.from(request), import_page.Page.fromNullable(page)));
|
||||||
|
this._channel.on("requestFailed", ({ request, failureText, responseEndTiming, page }) => this._onRequestFailed(network.Request.from(request), responseEndTiming, failureText, import_page.Page.fromNullable(page)));
|
||||||
|
this._channel.on("requestFinished", (params) => this._onRequestFinished(params));
|
||||||
|
this._channel.on("response", ({ response, page }) => this._onResponse(network.Response.from(response), import_page.Page.fromNullable(page)));
|
||||||
|
this._closedPromise = new Promise((f) => this.once(import_events.Events.BrowserContext.Close, f));
|
||||||
|
this._setEventToSubscriptionMapping(/* @__PURE__ */ new Map([
|
||||||
|
[import_events.Events.BrowserContext.Console, "console"],
|
||||||
|
[import_events.Events.BrowserContext.Dialog, "dialog"],
|
||||||
|
[import_events.Events.BrowserContext.Request, "request"],
|
||||||
|
[import_events.Events.BrowserContext.Response, "response"],
|
||||||
|
[import_events.Events.BrowserContext.RequestFinished, "requestFinished"],
|
||||||
|
[import_events.Events.BrowserContext.RequestFailed, "requestFailed"]
|
||||||
|
]));
|
||||||
|
}
|
||||||
static from(context) {
|
static from(context) {
|
||||||
return context._object;
|
return context._object;
|
||||||
}
|
}
|
||||||
static fromNullable(context) {
|
static fromNullable(context) {
|
||||||
return context ? BrowserContext.from(context) : null;
|
return context ? BrowserContext.from(context) : null;
|
||||||
}
|
}
|
||||||
constructor(parent, type, guid, initializer) {
|
|
||||||
var _this$_browser, _this$_browser2;
|
|
||||||
super(parent, type, guid, initializer);
|
|
||||||
this._pages = new Set();
|
|
||||||
this._routes = [];
|
|
||||||
this._webSocketRoutes = [];
|
|
||||||
this._browser = null;
|
|
||||||
this._browserType = void 0;
|
|
||||||
this._bindings = new Map();
|
|
||||||
this._timeoutSettings = new _timeoutSettings.TimeoutSettings();
|
|
||||||
this._ownerPage = void 0;
|
|
||||||
this._closedPromise = void 0;
|
|
||||||
this._options = {};
|
|
||||||
this.request = void 0;
|
|
||||||
this.tracing = void 0;
|
|
||||||
this.clock = void 0;
|
|
||||||
this._backgroundPages = new Set();
|
|
||||||
this._serviceWorkers = new Set();
|
|
||||||
this._isChromium = void 0;
|
|
||||||
this._harRecorders = new Map();
|
|
||||||
this._closeWasCalled = false;
|
|
||||||
this._closeReason = void 0;
|
|
||||||
this._harRouters = [];
|
|
||||||
if (parent instanceof _browser.Browser) this._browser = parent;
|
|
||||||
(_this$_browser = this._browser) === null || _this$_browser === void 0 || _this$_browser._contexts.add(this);
|
|
||||||
this._isChromium = ((_this$_browser2 = this._browser) === null || _this$_browser2 === void 0 ? void 0 : _this$_browser2._name) === 'chromium';
|
|
||||||
this.tracing = _tracing.Tracing.from(initializer.tracing);
|
|
||||||
this.request = _fetch.APIRequestContext.from(initializer.requestContext);
|
|
||||||
this.clock = new _clock.Clock(this);
|
|
||||||
this._channel.on('bindingCall', ({
|
|
||||||
binding
|
|
||||||
}) => this._onBinding(_page.BindingCall.from(binding)));
|
|
||||||
this._channel.on('close', () => this._onClose());
|
|
||||||
this._channel.on('page', ({
|
|
||||||
page
|
|
||||||
}) => this._onPage(_page.Page.from(page)));
|
|
||||||
this._channel.on('route', ({
|
|
||||||
route
|
|
||||||
}) => this._onRoute(network.Route.from(route)));
|
|
||||||
this._channel.on('webSocketRoute', ({
|
|
||||||
webSocketRoute
|
|
||||||
}) => this._onWebSocketRoute(network.WebSocketRoute.from(webSocketRoute)));
|
|
||||||
this._channel.on('backgroundPage', ({
|
|
||||||
page
|
|
||||||
}) => {
|
|
||||||
const backgroundPage = _page.Page.from(page);
|
|
||||||
this._backgroundPages.add(backgroundPage);
|
|
||||||
this.emit(_events.Events.BrowserContext.BackgroundPage, backgroundPage);
|
|
||||||
});
|
|
||||||
this._channel.on('serviceWorker', ({
|
|
||||||
worker
|
|
||||||
}) => {
|
|
||||||
const serviceWorker = _worker.Worker.from(worker);
|
|
||||||
serviceWorker._context = this;
|
|
||||||
this._serviceWorkers.add(serviceWorker);
|
|
||||||
this.emit(_events.Events.BrowserContext.ServiceWorker, serviceWorker);
|
|
||||||
});
|
|
||||||
this._channel.on('console', event => {
|
|
||||||
const consoleMessage = new _consoleMessage.ConsoleMessage(event);
|
|
||||||
this.emit(_events.Events.BrowserContext.Console, consoleMessage);
|
|
||||||
const page = consoleMessage.page();
|
|
||||||
if (page) page.emit(_events.Events.Page.Console, consoleMessage);
|
|
||||||
});
|
|
||||||
this._channel.on('pageError', ({
|
|
||||||
error,
|
|
||||||
page
|
|
||||||
}) => {
|
|
||||||
const pageObject = _page.Page.from(page);
|
|
||||||
const parsedError = (0, _errors.parseError)(error);
|
|
||||||
this.emit(_events.Events.BrowserContext.WebError, new _webError.WebError(pageObject, parsedError));
|
|
||||||
if (pageObject) pageObject.emit(_events.Events.Page.PageError, parsedError);
|
|
||||||
});
|
|
||||||
this._channel.on('dialog', ({
|
|
||||||
dialog
|
|
||||||
}) => {
|
|
||||||
const dialogObject = _dialog.Dialog.from(dialog);
|
|
||||||
let hasListeners = this.emit(_events.Events.BrowserContext.Dialog, dialogObject);
|
|
||||||
const page = dialogObject.page();
|
|
||||||
if (page) hasListeners = page.emit(_events.Events.Page.Dialog, dialogObject) || hasListeners;
|
|
||||||
if (!hasListeners) {
|
|
||||||
// Although we do similar handling on the server side, we still need this logic
|
|
||||||
// on the client side due to a possible race condition between two async calls:
|
|
||||||
// a) removing "dialog" listener subscription (client->server)
|
|
||||||
// b) actual "dialog" event (server->client)
|
|
||||||
if (dialogObject.type() === 'beforeunload') dialog.accept({}).catch(() => {});else dialog.dismiss().catch(() => {});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this._channel.on('request', ({
|
|
||||||
request,
|
|
||||||
page
|
|
||||||
}) => this._onRequest(network.Request.from(request), _page.Page.fromNullable(page)));
|
|
||||||
this._channel.on('requestFailed', ({
|
|
||||||
request,
|
|
||||||
failureText,
|
|
||||||
responseEndTiming,
|
|
||||||
page
|
|
||||||
}) => this._onRequestFailed(network.Request.from(request), responseEndTiming, failureText, _page.Page.fromNullable(page)));
|
|
||||||
this._channel.on('requestFinished', params => this._onRequestFinished(params));
|
|
||||||
this._channel.on('response', ({
|
|
||||||
response,
|
|
||||||
page
|
|
||||||
}) => this._onResponse(network.Response.from(response), _page.Page.fromNullable(page)));
|
|
||||||
this._closedPromise = new Promise(f => this.once(_events.Events.BrowserContext.Close, f));
|
|
||||||
this._setEventToSubscriptionMapping(new Map([[_events.Events.BrowserContext.Console, 'console'], [_events.Events.BrowserContext.Dialog, 'dialog'], [_events.Events.BrowserContext.Request, 'request'], [_events.Events.BrowserContext.Response, 'response'], [_events.Events.BrowserContext.RequestFinished, 'requestFinished'], [_events.Events.BrowserContext.RequestFailed, 'requestFailed']]));
|
|
||||||
}
|
|
||||||
_setOptions(contextOptions, browserOptions) {
|
_setOptions(contextOptions, browserOptions) {
|
||||||
this._options = contextOptions;
|
this._options = contextOptions;
|
||||||
if (this._options.recordHar) this._harRecorders.set('', {
|
if (this._options.recordHar)
|
||||||
path: this._options.recordHar.path,
|
this._harRecorders.set("", { path: this._options.recordHar.path, content: this._options.recordHar.content });
|
||||||
content: this._options.recordHar.content
|
|
||||||
});
|
|
||||||
this.tracing._tracesDir = browserOptions.tracesDir;
|
this.tracing._tracesDir = browserOptions.tracesDir;
|
||||||
}
|
}
|
||||||
_onPage(page) {
|
_onPage(page) {
|
||||||
this._pages.add(page);
|
this._pages.add(page);
|
||||||
this.emit(_events.Events.BrowserContext.Page, page);
|
this.emit(import_events.Events.BrowserContext.Page, page);
|
||||||
if (page._opener && !page._opener.isClosed()) page._opener.emit(_events.Events.Page.Popup, page);
|
if (page._opener && !page._opener.isClosed())
|
||||||
|
page._opener.emit(import_events.Events.Page.Popup, page);
|
||||||
}
|
}
|
||||||
_onRequest(request, page) {
|
_onRequest(request, page) {
|
||||||
this.emit(_events.Events.BrowserContext.Request, request);
|
this.emit(import_events.Events.BrowserContext.Request, request);
|
||||||
if (page) page.emit(_events.Events.Page.Request, request);
|
if (page)
|
||||||
|
page.emit(import_events.Events.Page.Request, request);
|
||||||
}
|
}
|
||||||
_onResponse(response, page) {
|
_onResponse(response, page) {
|
||||||
this.emit(_events.Events.BrowserContext.Response, response);
|
this.emit(import_events.Events.BrowserContext.Response, response);
|
||||||
if (page) page.emit(_events.Events.Page.Response, response);
|
if (page)
|
||||||
|
page.emit(import_events.Events.Page.Response, response);
|
||||||
}
|
}
|
||||||
_onRequestFailed(request, responseEndTiming, failureText, page) {
|
_onRequestFailed(request, responseEndTiming, failureText, page) {
|
||||||
request._failureText = failureText || null;
|
request._failureText = failureText || null;
|
||||||
request._setResponseEndTiming(responseEndTiming);
|
request._setResponseEndTiming(responseEndTiming);
|
||||||
this.emit(_events.Events.BrowserContext.RequestFailed, request);
|
this.emit(import_events.Events.BrowserContext.RequestFailed, request);
|
||||||
if (page) page.emit(_events.Events.Page.RequestFailed, request);
|
if (page)
|
||||||
|
page.emit(import_events.Events.Page.RequestFailed, request);
|
||||||
}
|
}
|
||||||
_onRequestFinished(params) {
|
_onRequestFinished(params) {
|
||||||
const {
|
const { responseEndTiming } = params;
|
||||||
responseEndTiming
|
|
||||||
} = params;
|
|
||||||
const request = network.Request.from(params.request);
|
const request = network.Request.from(params.request);
|
||||||
const response = network.Response.fromNullable(params.response);
|
const response = network.Response.fromNullable(params.response);
|
||||||
const page = _page.Page.fromNullable(params.page);
|
const page = import_page.Page.fromNullable(params.page);
|
||||||
request._setResponseEndTiming(responseEndTiming);
|
request._setResponseEndTiming(responseEndTiming);
|
||||||
this.emit(_events.Events.BrowserContext.RequestFinished, request);
|
this.emit(import_events.Events.BrowserContext.RequestFinished, request);
|
||||||
if (page) page.emit(_events.Events.Page.RequestFinished, request);
|
if (page)
|
||||||
if (response) response._finishedPromise.resolve(null);
|
page.emit(import_events.Events.Page.RequestFinished, request);
|
||||||
|
if (response)
|
||||||
|
response._finishedPromise.resolve(null);
|
||||||
}
|
}
|
||||||
async _onRoute(route) {
|
async _onRoute(route) {
|
||||||
route._context = this;
|
route._context = this;
|
||||||
const page = route.request()._safePage();
|
const page = route.request()._safePage();
|
||||||
const routeHandlers = this._routes.slice();
|
const routeHandlers = this._routes.slice();
|
||||||
for (const routeHandler of routeHandlers) {
|
for (const routeHandler of routeHandlers) {
|
||||||
// If the page or the context was closed we stall all requests right away.
|
if (page?._closeWasCalled || this._closeWasCalled)
|
||||||
if (page !== null && page !== void 0 && page._closeWasCalled || this._closeWasCalled) return;
|
return;
|
||||||
if (!routeHandler.matches(route.request().url())) continue;
|
if (!routeHandler.matches(route.request().url()))
|
||||||
|
continue;
|
||||||
const index = this._routes.indexOf(routeHandler);
|
const index = this._routes.indexOf(routeHandler);
|
||||||
if (index === -1) continue;
|
if (index === -1)
|
||||||
if (routeHandler.willExpire()) this._routes.splice(index, 1);
|
continue;
|
||||||
|
if (routeHandler.willExpire())
|
||||||
|
this._routes.splice(index, 1);
|
||||||
const handled = await routeHandler.handle(route);
|
const handled = await routeHandler.handle(route);
|
||||||
if (!this._routes.length) this._wrapApiCall(() => this._updateInterceptionPatterns(), true).catch(() => {});
|
if (!this._routes.length)
|
||||||
if (handled) return;
|
this._wrapApiCall(() => this._updateInterceptionPatterns(), true).catch(() => {
|
||||||
|
});
|
||||||
|
if (handled)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// If the page is closed or unrouteAll() was called without waiting and interception disabled,
|
await route._innerContinue(
|
||||||
// the method will throw an error - silence it.
|
true
|
||||||
await route._innerContinue(true /* isFallback */).catch(() => {});
|
/* isFallback */
|
||||||
|
).catch(() => {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
async _onWebSocketRoute(webSocketRoute) {
|
async _onWebSocketRoute(webSocketRoute) {
|
||||||
const routeHandler = this._webSocketRoutes.find(route => route.matches(webSocketRoute.url()));
|
const routeHandler = this._webSocketRoutes.find((route) => route.matches(webSocketRoute.url()));
|
||||||
if (routeHandler) await routeHandler.handle(webSocketRoute);else webSocketRoute.connectToServer();
|
if (routeHandler)
|
||||||
|
await routeHandler.handle(webSocketRoute);
|
||||||
|
else
|
||||||
|
webSocketRoute.connectToServer();
|
||||||
}
|
}
|
||||||
async _onBinding(bindingCall) {
|
async _onBinding(bindingCall) {
|
||||||
const func = this._bindings.get(bindingCall._initializer.name);
|
const func = this._bindings.get(bindingCall._initializer.name);
|
||||||
if (!func) return;
|
if (!func)
|
||||||
|
return;
|
||||||
await bindingCall.call(func);
|
await bindingCall.call(func);
|
||||||
}
|
}
|
||||||
setDefaultNavigationTimeout(timeout) {
|
setDefaultNavigationTimeout(timeout) {
|
||||||
this._timeoutSettings.setDefaultNavigationTimeout(timeout);
|
this._timeoutSettings.setDefaultNavigationTimeout(timeout);
|
||||||
this._wrapApiCall(async () => {
|
this._wrapApiCall(async () => {
|
||||||
this._channel.setDefaultNavigationTimeoutNoReply({
|
await this._channel.setDefaultNavigationTimeoutNoReply({ timeout });
|
||||||
timeout
|
}, true).catch(() => {
|
||||||
}).catch(() => {});
|
});
|
||||||
}, true);
|
|
||||||
}
|
}
|
||||||
setDefaultTimeout(timeout) {
|
setDefaultTimeout(timeout) {
|
||||||
this._timeoutSettings.setDefaultTimeout(timeout);
|
this._timeoutSettings.setDefaultTimeout(timeout);
|
||||||
this._wrapApiCall(async () => {
|
this._wrapApiCall(async () => {
|
||||||
this._channel.setDefaultTimeoutNoReply({
|
await this._channel.setDefaultTimeoutNoReply({ timeout });
|
||||||
timeout
|
}, true).catch(() => {
|
||||||
}).catch(() => {});
|
});
|
||||||
}, true);
|
|
||||||
}
|
}
|
||||||
browser() {
|
browser() {
|
||||||
return this._browser;
|
return this._browser;
|
||||||
@@ -253,86 +247,67 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
return [...this._pages];
|
return [...this._pages];
|
||||||
}
|
}
|
||||||
async newPage() {
|
async newPage() {
|
||||||
if (this._ownerPage) throw new Error('Please use browser.newContext()');
|
if (this._ownerPage)
|
||||||
return _page.Page.from((await this._channel.newPage()).page);
|
throw new Error("Please use browser.newContext()");
|
||||||
|
return import_page.Page.from((await this._channel.newPage()).page);
|
||||||
}
|
}
|
||||||
async cookies(urls) {
|
async cookies(urls) {
|
||||||
if (!urls) urls = [];
|
if (!urls)
|
||||||
if (urls && typeof urls === 'string') urls = [urls];
|
urls = [];
|
||||||
return (await this._channel.cookies({
|
if (urls && typeof urls === "string")
|
||||||
urls: urls
|
urls = [urls];
|
||||||
})).cookies;
|
return (await this._channel.cookies({ urls })).cookies;
|
||||||
}
|
}
|
||||||
async addCookies(cookies) {
|
async addCookies(cookies) {
|
||||||
await this._channel.addCookies({
|
await this._channel.addCookies({ cookies });
|
||||||
cookies
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async clearCookies(options = {}) {
|
async clearCookies(options = {}) {
|
||||||
await this._channel.clearCookies({
|
await this._channel.clearCookies({
|
||||||
name: (0, _utils.isString)(options.name) ? options.name : undefined,
|
name: (0, import_rtti.isString)(options.name) ? options.name : void 0,
|
||||||
nameRegexSource: (0, _utils.isRegExp)(options.name) ? options.name.source : undefined,
|
nameRegexSource: (0, import_rtti.isRegExp)(options.name) ? options.name.source : void 0,
|
||||||
nameRegexFlags: (0, _utils.isRegExp)(options.name) ? options.name.flags : undefined,
|
nameRegexFlags: (0, import_rtti.isRegExp)(options.name) ? options.name.flags : void 0,
|
||||||
domain: (0, _utils.isString)(options.domain) ? options.domain : undefined,
|
domain: (0, import_rtti.isString)(options.domain) ? options.domain : void 0,
|
||||||
domainRegexSource: (0, _utils.isRegExp)(options.domain) ? options.domain.source : undefined,
|
domainRegexSource: (0, import_rtti.isRegExp)(options.domain) ? options.domain.source : void 0,
|
||||||
domainRegexFlags: (0, _utils.isRegExp)(options.domain) ? options.domain.flags : undefined,
|
domainRegexFlags: (0, import_rtti.isRegExp)(options.domain) ? options.domain.flags : void 0,
|
||||||
path: (0, _utils.isString)(options.path) ? options.path : undefined,
|
path: (0, import_rtti.isString)(options.path) ? options.path : void 0,
|
||||||
pathRegexSource: (0, _utils.isRegExp)(options.path) ? options.path.source : undefined,
|
pathRegexSource: (0, import_rtti.isRegExp)(options.path) ? options.path.source : void 0,
|
||||||
pathRegexFlags: (0, _utils.isRegExp)(options.path) ? options.path.flags : undefined
|
pathRegexFlags: (0, import_rtti.isRegExp)(options.path) ? options.path.flags : void 0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async grantPermissions(permissions, options) {
|
async grantPermissions(permissions, options) {
|
||||||
await this._channel.grantPermissions({
|
await this._channel.grantPermissions({ permissions, ...options });
|
||||||
permissions,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async clearPermissions() {
|
async clearPermissions() {
|
||||||
await this._channel.clearPermissions();
|
await this._channel.clearPermissions();
|
||||||
}
|
}
|
||||||
async setGeolocation(geolocation) {
|
async setGeolocation(geolocation) {
|
||||||
await this._channel.setGeolocation({
|
await this._channel.setGeolocation({ geolocation: geolocation || void 0 });
|
||||||
geolocation: geolocation || undefined
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async setExtraHTTPHeaders(headers) {
|
async setExtraHTTPHeaders(headers) {
|
||||||
network.validateHeaders(headers);
|
network.validateHeaders(headers);
|
||||||
await this._channel.setExtraHTTPHeaders({
|
await this._channel.setExtraHTTPHeaders({ headers: (0, import_headers.headersObjectToArray)(headers) });
|
||||||
headers: (0, _utils.headersObjectToArray)(headers)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async setOffline(offline) {
|
async setOffline(offline) {
|
||||||
await this._channel.setOffline({
|
await this._channel.setOffline({ offline });
|
||||||
offline
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async setHTTPCredentials(httpCredentials) {
|
async setHTTPCredentials(httpCredentials) {
|
||||||
await this._channel.setHTTPCredentials({
|
await this._channel.setHTTPCredentials({ httpCredentials: httpCredentials || void 0 });
|
||||||
httpCredentials: httpCredentials || undefined
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async addInitScript(script, arg) {
|
async addInitScript(script, arg) {
|
||||||
const source = await (0, _clientHelper.evaluationScript)(script, arg);
|
const source = await (0, import_clientHelper.evaluationScript)(this._platform, script, arg);
|
||||||
await this._channel.addInitScript({
|
await this._channel.addInitScript({ source });
|
||||||
source
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async exposeBinding(name, callback, options = {}) {
|
async exposeBinding(name, callback, options = {}) {
|
||||||
await this._channel.exposeBinding({
|
await this._channel.exposeBinding({ name, needsHandle: options.handle });
|
||||||
name,
|
|
||||||
needsHandle: options.handle
|
|
||||||
});
|
|
||||||
this._bindings.set(name, callback);
|
this._bindings.set(name, callback);
|
||||||
}
|
}
|
||||||
async exposeFunction(name, callback) {
|
async exposeFunction(name, callback) {
|
||||||
await this._channel.exposeBinding({
|
await this._channel.exposeBinding({ name });
|
||||||
name
|
|
||||||
});
|
|
||||||
const binding = (source, ...args) => callback(...args);
|
const binding = (source, ...args) => callback(...args);
|
||||||
this._bindings.set(name, binding);
|
this._bindings.set(name, binding);
|
||||||
}
|
}
|
||||||
async route(url, handler, options = {}) {
|
async route(url, handler, options = {}) {
|
||||||
this._routes.unshift(new network.RouteHandler(this._options.baseURL, url, handler, options.times));
|
this._routes.unshift(new network.RouteHandler(this._platform, this._options.baseURL, url, handler, options.times));
|
||||||
await this._updateInterceptionPatterns();
|
await this._updateInterceptionPatterns();
|
||||||
}
|
}
|
||||||
async routeWebSocket(url, handler) {
|
async routeWebSocket(url, handler) {
|
||||||
@@ -340,90 +315,85 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
await this._updateWebSocketInterceptionPatterns();
|
await this._updateWebSocketInterceptionPatterns();
|
||||||
}
|
}
|
||||||
async _recordIntoHAR(har, page, options = {}) {
|
async _recordIntoHAR(har, page, options = {}) {
|
||||||
var _options$updateConten, _options$updateMode, _options$updateConten2;
|
const { harId } = await this._channel.harStart({
|
||||||
const {
|
page: page?._channel,
|
||||||
harId
|
|
||||||
} = await this._channel.harStart({
|
|
||||||
page: page === null || page === void 0 ? void 0 : page._channel,
|
|
||||||
options: prepareRecordHarOptions({
|
options: prepareRecordHarOptions({
|
||||||
path: har,
|
path: har,
|
||||||
content: (_options$updateConten = options.updateContent) !== null && _options$updateConten !== void 0 ? _options$updateConten : 'attach',
|
content: options.updateContent ?? "attach",
|
||||||
mode: (_options$updateMode = options.updateMode) !== null && _options$updateMode !== void 0 ? _options$updateMode : 'minimal',
|
mode: options.updateMode ?? "minimal",
|
||||||
urlFilter: options.url
|
urlFilter: options.url
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
this._harRecorders.set(harId, {
|
this._harRecorders.set(harId, { path: har, content: options.updateContent ?? "attach" });
|
||||||
path: har,
|
|
||||||
content: (_options$updateConten2 = options.updateContent) !== null && _options$updateConten2 !== void 0 ? _options$updateConten2 : 'attach'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async routeFromHAR(har, options = {}) {
|
async routeFromHAR(har, options = {}) {
|
||||||
|
const localUtils = this._connection.localUtils();
|
||||||
|
if (!localUtils)
|
||||||
|
throw new Error("Route from har is not supported in thin clients");
|
||||||
if (options.update) {
|
if (options.update) {
|
||||||
await this._recordIntoHAR(har, null, options);
|
await this._recordIntoHAR(har, null, options);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const harRouter = await _harRouter.HarRouter.create(this._connection.localUtils(), har, options.notFound || 'abort', {
|
const harRouter = await import_harRouter.HarRouter.create(localUtils, har, options.notFound || "abort", { urlMatch: options.url });
|
||||||
urlMatch: options.url
|
|
||||||
});
|
|
||||||
this._harRouters.push(harRouter);
|
this._harRouters.push(harRouter);
|
||||||
await harRouter.addContextRoute(this);
|
await harRouter.addContextRoute(this);
|
||||||
}
|
}
|
||||||
_disposeHarRouters() {
|
_disposeHarRouters() {
|
||||||
this._harRouters.forEach(router => router.dispose());
|
this._harRouters.forEach((router) => router.dispose());
|
||||||
this._harRouters = [];
|
this._harRouters = [];
|
||||||
}
|
}
|
||||||
async unrouteAll(options) {
|
async unrouteAll(options) {
|
||||||
await this._unrouteInternal(this._routes, [], options === null || options === void 0 ? void 0 : options.behavior);
|
await this._unrouteInternal(this._routes, [], options?.behavior);
|
||||||
this._disposeHarRouters();
|
this._disposeHarRouters();
|
||||||
}
|
}
|
||||||
async unroute(url, handler) {
|
async unroute(url, handler) {
|
||||||
const removed = [];
|
const removed = [];
|
||||||
const remaining = [];
|
const remaining = [];
|
||||||
for (const route of this._routes) {
|
for (const route of this._routes) {
|
||||||
if ((0, _utils.urlMatchesEqual)(route.url, url) && (!handler || route.handler === handler)) removed.push(route);else remaining.push(route);
|
if ((0, import_urlMatch.urlMatchesEqual)(route.url, url) && (!handler || route.handler === handler))
|
||||||
|
removed.push(route);
|
||||||
|
else
|
||||||
|
remaining.push(route);
|
||||||
}
|
}
|
||||||
await this._unrouteInternal(removed, remaining, 'default');
|
await this._unrouteInternal(removed, remaining, "default");
|
||||||
}
|
}
|
||||||
async _unrouteInternal(removed, remaining, behavior) {
|
async _unrouteInternal(removed, remaining, behavior) {
|
||||||
this._routes = remaining;
|
this._routes = remaining;
|
||||||
await this._updateInterceptionPatterns();
|
await this._updateInterceptionPatterns();
|
||||||
if (!behavior || behavior === 'default') return;
|
if (!behavior || behavior === "default")
|
||||||
const promises = removed.map(routeHandler => routeHandler.stop(behavior));
|
return;
|
||||||
|
const promises = removed.map((routeHandler) => routeHandler.stop(behavior));
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
}
|
}
|
||||||
async _updateInterceptionPatterns() {
|
async _updateInterceptionPatterns() {
|
||||||
const patterns = network.RouteHandler.prepareInterceptionPatterns(this._routes);
|
const patterns = network.RouteHandler.prepareInterceptionPatterns(this._routes);
|
||||||
await this._channel.setNetworkInterceptionPatterns({
|
await this._channel.setNetworkInterceptionPatterns({ patterns });
|
||||||
patterns
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async _updateWebSocketInterceptionPatterns() {
|
async _updateWebSocketInterceptionPatterns() {
|
||||||
const patterns = network.WebSocketRouteHandler.prepareInterceptionPatterns(this._webSocketRoutes);
|
const patterns = network.WebSocketRouteHandler.prepareInterceptionPatterns(this._webSocketRoutes);
|
||||||
await this._channel.setWebSocketInterceptionPatterns({
|
await this._channel.setWebSocketInterceptionPatterns({ patterns });
|
||||||
patterns
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
_effectiveCloseReason() {
|
_effectiveCloseReason() {
|
||||||
var _this$_browser3;
|
return this._closeReason || this._browser?._closeReason;
|
||||||
return this._closeReason || ((_this$_browser3 = this._browser) === null || _this$_browser3 === void 0 ? void 0 : _this$_browser3._closeReason);
|
|
||||||
}
|
}
|
||||||
async waitForEvent(event, optionsOrPredicate = {}) {
|
async waitForEvent(event, optionsOrPredicate = {}) {
|
||||||
return await this._wrapApiCall(async () => {
|
return await this._wrapApiCall(async () => {
|
||||||
const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate);
|
const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === "function" ? {} : optionsOrPredicate);
|
||||||
const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate;
|
const predicate = typeof optionsOrPredicate === "function" ? optionsOrPredicate : optionsOrPredicate.predicate;
|
||||||
const waiter = _waiter.Waiter.createForEvent(this, event);
|
const waiter = import_waiter.Waiter.createForEvent(this, event);
|
||||||
waiter.rejectOnTimeout(timeout, `Timeout ${timeout}ms exceeded while waiting for event "${event}"`);
|
waiter.rejectOnTimeout(timeout, `Timeout ${timeout}ms exceeded while waiting for event "${event}"`);
|
||||||
if (event !== _events.Events.BrowserContext.Close) waiter.rejectOnEvent(this, _events.Events.BrowserContext.Close, () => new _errors.TargetClosedError(this._effectiveCloseReason()));
|
if (event !== import_events.Events.BrowserContext.Close)
|
||||||
|
waiter.rejectOnEvent(this, import_events.Events.BrowserContext.Close, () => new import_errors.TargetClosedError(this._effectiveCloseReason()));
|
||||||
const result = await waiter.waitForEvent(this, event, predicate);
|
const result = await waiter.waitForEvent(this, event, predicate);
|
||||||
waiter.dispose();
|
waiter.dispose();
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async storageState(options = {}) {
|
async storageState(options = {}) {
|
||||||
const state = await this._channel.storageState();
|
const state = await this._channel.storageState({ indexedDB: options.indexedDB });
|
||||||
if (options.path) {
|
if (options.path) {
|
||||||
await (0, _utils.mkdirIfNeeded)(options.path);
|
await (0, import_fileUtils.mkdirIfNeeded)(this._platform, options.path);
|
||||||
await _fs.default.promises.writeFile(options.path, JSON.stringify(state, undefined, 2), 'utf8');
|
await this._platform.fs().promises.writeFile(options.path, JSON.stringify(state, void 0, 2), "utf8");
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@@ -434,50 +404,43 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
return [...this._serviceWorkers];
|
return [...this._serviceWorkers];
|
||||||
}
|
}
|
||||||
async newCDPSession(page) {
|
async newCDPSession(page) {
|
||||||
// channelOwner.ts's validation messages don't handle the pseudo-union type, so we're explicit here
|
if (!(page instanceof import_page.Page) && !(page instanceof import_frame.Frame))
|
||||||
if (!(page instanceof _page.Page) && !(page instanceof _frame.Frame)) throw new Error('page: expected Page or Frame');
|
throw new Error("page: expected Page or Frame");
|
||||||
const result = await this._channel.newCDPSession(page instanceof _page.Page ? {
|
const result = await this._channel.newCDPSession(page instanceof import_page.Page ? { page: page._channel } : { frame: page._channel });
|
||||||
page: page._channel
|
return import_cdpSession.CDPSession.from(result.session);
|
||||||
} : {
|
|
||||||
frame: page._channel
|
|
||||||
});
|
|
||||||
return _cdpSession.CDPSession.from(result.session);
|
|
||||||
}
|
}
|
||||||
_onClose() {
|
_onClose() {
|
||||||
var _this$_browserType;
|
if (this._browser)
|
||||||
if (this._browser) this._browser._contexts.delete(this);
|
this._browser._contexts.delete(this);
|
||||||
(_this$_browserType = this._browserType) === null || _this$_browserType === void 0 || (_this$_browserType = _this$_browserType._contexts) === null || _this$_browserType === void 0 || _this$_browserType.delete(this);
|
this._browserType?._contexts?.delete(this);
|
||||||
this._disposeHarRouters();
|
this._disposeHarRouters();
|
||||||
this.tracing._resetStackCounter();
|
this.tracing._resetStackCounter();
|
||||||
this.emit(_events.Events.BrowserContext.Close, this);
|
this.emit(import_events.Events.BrowserContext.Close, this);
|
||||||
}
|
}
|
||||||
async [_Symbol$asyncDispose]() {
|
async [Symbol.asyncDispose]() {
|
||||||
await this.close();
|
await this.close();
|
||||||
}
|
}
|
||||||
async close(options = {}) {
|
async close(options = {}) {
|
||||||
if (this._closeWasCalled) return;
|
if (this._closeWasCalled)
|
||||||
|
return;
|
||||||
this._closeReason = options.reason;
|
this._closeReason = options.reason;
|
||||||
this._closeWasCalled = true;
|
this._closeWasCalled = true;
|
||||||
await this._wrapApiCall(async () => {
|
await this._wrapApiCall(async () => {
|
||||||
await this.request.dispose(options);
|
await this.request.dispose(options);
|
||||||
}, true);
|
}, true);
|
||||||
await this._wrapApiCall(async () => {
|
await this._wrapApiCall(async () => {
|
||||||
var _this$_browserType2;
|
await this._browserType?._willCloseContext(this);
|
||||||
await ((_this$_browserType2 = this._browserType) === null || _this$_browserType2 === void 0 ? void 0 : _this$_browserType2._willCloseContext(this));
|
|
||||||
for (const [harId, harParams] of this._harRecorders) {
|
for (const [harId, harParams] of this._harRecorders) {
|
||||||
const har = await this._channel.harExport({
|
const har = await this._channel.harExport({ harId });
|
||||||
harId
|
const artifact = import_artifact.Artifact.from(har.artifact);
|
||||||
});
|
const isCompressed = harParams.content === "attach" || harParams.path.endsWith(".zip");
|
||||||
const artifact = _artifact.Artifact.from(har.artifact);
|
const needCompressed = harParams.path.endsWith(".zip");
|
||||||
// Server side will compress artifact if content is attach or if file is .zip.
|
|
||||||
const isCompressed = harParams.content === 'attach' || harParams.path.endsWith('.zip');
|
|
||||||
const needCompressed = harParams.path.endsWith('.zip');
|
|
||||||
if (isCompressed && !needCompressed) {
|
if (isCompressed && !needCompressed) {
|
||||||
await artifact.saveAs(harParams.path + '.tmp');
|
const localUtils = this._connection.localUtils();
|
||||||
await this._connection.localUtils()._channel.harUnzip({
|
if (!localUtils)
|
||||||
zipFile: harParams.path + '.tmp',
|
throw new Error("Uncompressed har is not supported in thin clients");
|
||||||
harFile: harParams.path
|
await artifact.saveAs(harParams.path + ".tmp");
|
||||||
});
|
await localUtils.harUnzip({ zipFile: harParams.path + ".tmp", harFile: harParams.path });
|
||||||
} else {
|
} else {
|
||||||
await artifact.saveAs(harParams.path);
|
await artifact.saveAs(harParams.path);
|
||||||
}
|
}
|
||||||
@@ -491,43 +454,48 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
await this._channel.enableRecorder(params);
|
await this._channel.enableRecorder(params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.BrowserContext = BrowserContext;
|
async function prepareStorageState(platform, options) {
|
||||||
async function prepareStorageState(options) {
|
if (typeof options.storageState !== "string")
|
||||||
if (typeof options.storageState !== 'string') return options.storageState;
|
return options.storageState;
|
||||||
try {
|
try {
|
||||||
return JSON.parse(await _fs.default.promises.readFile(options.storageState, 'utf8'));
|
return JSON.parse(await platform.fs().promises.readFile(options.storageState, "utf8"));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
(0, _stackTrace.rewriteErrorMessage)(e, `Error reading storage state from ${options.storageState}:\n` + e.message);
|
(0, import_stackTrace.rewriteErrorMessage)(e, `Error reading storage state from ${options.storageState}:
|
||||||
|
` + e.message);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function prepareRecordHarOptions(options) {
|
function prepareRecordHarOptions(options) {
|
||||||
if (!options) return;
|
if (!options)
|
||||||
|
return;
|
||||||
return {
|
return {
|
||||||
path: options.path,
|
path: options.path,
|
||||||
content: options.content || (options.omitContent ? 'omit' : undefined),
|
content: options.content || (options.omitContent ? "omit" : void 0),
|
||||||
urlGlob: (0, _utils.isString)(options.urlFilter) ? options.urlFilter : undefined,
|
urlGlob: (0, import_rtti.isString)(options.urlFilter) ? options.urlFilter : void 0,
|
||||||
urlRegexSource: (0, _utils.isRegExp)(options.urlFilter) ? options.urlFilter.source : undefined,
|
urlRegexSource: (0, import_rtti.isRegExp)(options.urlFilter) ? options.urlFilter.source : void 0,
|
||||||
urlRegexFlags: (0, _utils.isRegExp)(options.urlFilter) ? options.urlFilter.flags : undefined,
|
urlRegexFlags: (0, import_rtti.isRegExp)(options.urlFilter) ? options.urlFilter.flags : void 0,
|
||||||
mode: options.mode
|
mode: options.mode
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async function prepareBrowserContextParams(options) {
|
async function prepareBrowserContextParams(platform, options) {
|
||||||
if (options.videoSize && !options.videosPath) throw new Error(`"videoSize" option requires "videosPath" to be specified`);
|
if (options.videoSize && !options.videosPath)
|
||||||
if (options.extraHTTPHeaders) network.validateHeaders(options.extraHTTPHeaders);
|
throw new Error(`"videoSize" option requires "videosPath" to be specified`);
|
||||||
|
if (options.extraHTTPHeaders)
|
||||||
|
network.validateHeaders(options.extraHTTPHeaders);
|
||||||
const contextParams = {
|
const contextParams = {
|
||||||
...options,
|
...options,
|
||||||
viewport: options.viewport === null ? undefined : options.viewport,
|
viewport: options.viewport === null ? void 0 : options.viewport,
|
||||||
noDefaultViewport: options.viewport === null,
|
noDefaultViewport: options.viewport === null,
|
||||||
extraHTTPHeaders: options.extraHTTPHeaders ? (0, _utils.headersObjectToArray)(options.extraHTTPHeaders) : undefined,
|
extraHTTPHeaders: options.extraHTTPHeaders ? (0, import_headers.headersObjectToArray)(options.extraHTTPHeaders) : void 0,
|
||||||
storageState: await prepareStorageState(options),
|
storageState: await prepareStorageState(platform, options),
|
||||||
serviceWorkers: options.serviceWorkers,
|
serviceWorkers: options.serviceWorkers,
|
||||||
recordHar: prepareRecordHarOptions(options.recordHar),
|
recordHar: prepareRecordHarOptions(options.recordHar),
|
||||||
colorScheme: options.colorScheme === null ? 'no-override' : options.colorScheme,
|
colorScheme: options.colorScheme === null ? "no-override" : options.colorScheme,
|
||||||
reducedMotion: options.reducedMotion === null ? 'no-override' : options.reducedMotion,
|
reducedMotion: options.reducedMotion === null ? "no-override" : options.reducedMotion,
|
||||||
forcedColors: options.forcedColors === null ? 'no-override' : options.forcedColors,
|
forcedColors: options.forcedColors === null ? "no-override" : options.forcedColors,
|
||||||
|
contrast: options.contrast === null ? "no-override" : options.contrast,
|
||||||
acceptDownloads: toAcceptDownloadsProtocol(options.acceptDownloads),
|
acceptDownloads: toAcceptDownloadsProtocol(options.acceptDownloads),
|
||||||
clientCertificates: await toClientCertificatesProtocol(options.clientCertificates)
|
clientCertificates: await toClientCertificatesProtocol(platform, options.clientCertificates)
|
||||||
};
|
};
|
||||||
if (!contextParams.recordVideo && options.videosPath) {
|
if (!contextParams.recordVideo && options.videosPath) {
|
||||||
contextParams.recordVideo = {
|
contextParams.recordVideo = {
|
||||||
@@ -535,21 +503,27 @@ async function prepareBrowserContextParams(options) {
|
|||||||
size: options.videoSize
|
size: options.videoSize
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (contextParams.recordVideo && contextParams.recordVideo.dir) contextParams.recordVideo.dir = _path.default.resolve(process.cwd(), contextParams.recordVideo.dir);
|
if (contextParams.recordVideo && contextParams.recordVideo.dir)
|
||||||
|
contextParams.recordVideo.dir = platform.path().resolve(contextParams.recordVideo.dir);
|
||||||
return contextParams;
|
return contextParams;
|
||||||
}
|
}
|
||||||
function toAcceptDownloadsProtocol(acceptDownloads) {
|
function toAcceptDownloadsProtocol(acceptDownloads) {
|
||||||
if (acceptDownloads === undefined) return undefined;
|
if (acceptDownloads === void 0)
|
||||||
if (acceptDownloads) return 'accept';
|
return void 0;
|
||||||
return 'deny';
|
if (acceptDownloads)
|
||||||
|
return "accept";
|
||||||
|
return "deny";
|
||||||
}
|
}
|
||||||
async function toClientCertificatesProtocol(certs) {
|
async function toClientCertificatesProtocol(platform, certs) {
|
||||||
if (!certs) return undefined;
|
if (!certs)
|
||||||
|
return void 0;
|
||||||
const bufferizeContent = async (value, path) => {
|
const bufferizeContent = async (value, path) => {
|
||||||
if (value) return value;
|
if (value)
|
||||||
if (path) return await _fs.default.promises.readFile(path);
|
return value;
|
||||||
|
if (path)
|
||||||
|
return await platform.fs().promises.readFile(path);
|
||||||
};
|
};
|
||||||
return await Promise.all(certs.map(async cert => ({
|
return await Promise.all(certs.map(async (cert) => ({
|
||||||
origin: cert.origin,
|
origin: cert.origin,
|
||||||
cert: await bufferizeContent(cert.cert, cert.certPath),
|
cert: await bufferizeContent(cert.cert, cert.certPath),
|
||||||
key: await bufferizeContent(cert.key, cert.keyPath),
|
key: await bufferizeContent(cert.key, cert.keyPath),
|
||||||
@@ -557,3 +531,9 @@ async function toClientCertificatesProtocol(certs) {
|
|||||||
passphrase: cert.passphrase
|
passphrase: cert.passphrase
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
BrowserContext,
|
||||||
|
prepareBrowserContextParams,
|
||||||
|
toClientCertificatesProtocol
|
||||||
|
});
|
||||||
|
|||||||
238
tvapp2/node_modules/playwright-core/lib/client/browserType.js
generated
vendored
@@ -1,222 +1,169 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var browserType_exports = {};
|
||||||
|
__export(browserType_exports, {
|
||||||
|
BrowserType: () => BrowserType
|
||||||
});
|
});
|
||||||
exports.BrowserType = void 0;
|
module.exports = __toCommonJS(browserType_exports);
|
||||||
var _browser3 = require("./browser");
|
var import_browser = require("./browser");
|
||||||
var _browserContext = require("./browserContext");
|
var import_browserContext = require("./browserContext");
|
||||||
var _channelOwner = require("./channelOwner");
|
var import_channelOwner = require("./channelOwner");
|
||||||
var _connection = require("./connection");
|
var import_clientHelper = require("./clientHelper");
|
||||||
var _events = require("./events");
|
var import_events = require("./events");
|
||||||
var _clientHelper = require("./clientHelper");
|
var import_assert = require("../utils/isomorphic/assert");
|
||||||
var _utils = require("../utils");
|
var import_headers = require("../utils/isomorphic/headers");
|
||||||
var _timeoutRunner = require("../utils/timeoutRunner");
|
var import_time = require("../utils/isomorphic/time");
|
||||||
/**
|
var import_timeoutRunner = require("../utils/isomorphic/timeoutRunner");
|
||||||
* Copyright (c) Microsoft Corporation.
|
var import_webSocket = require("./webSocket");
|
||||||
*
|
class BrowserType extends import_channelOwner.ChannelOwner {
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
constructor() {
|
||||||
* you may not use this file except in compliance with the License.
|
super(...arguments);
|
||||||
* You may obtain a copy of the License at
|
this._contexts = /* @__PURE__ */ new Set();
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This is here just for api generation and checking.
|
|
||||||
|
|
||||||
class BrowserType extends _channelOwner.ChannelOwner {
|
|
||||||
constructor(...args) {
|
|
||||||
super(...args);
|
|
||||||
this._serverLauncher = void 0;
|
|
||||||
this._contexts = new Set();
|
|
||||||
this._playwright = void 0;
|
|
||||||
// Instrumentation.
|
|
||||||
this._defaultContextOptions = void 0;
|
|
||||||
this._defaultContextTimeout = void 0;
|
|
||||||
this._defaultContextNavigationTimeout = void 0;
|
|
||||||
this._defaultLaunchOptions = void 0;
|
|
||||||
}
|
}
|
||||||
static from(browserType) {
|
static from(browserType) {
|
||||||
return browserType._object;
|
return browserType._object;
|
||||||
}
|
}
|
||||||
executablePath() {
|
executablePath() {
|
||||||
if (!this._initializer.executablePath) throw new Error('Browser is not supported on current platform');
|
if (!this._initializer.executablePath)
|
||||||
|
throw new Error("Browser is not supported on current platform");
|
||||||
return this._initializer.executablePath;
|
return this._initializer.executablePath;
|
||||||
}
|
}
|
||||||
name() {
|
name() {
|
||||||
return this._initializer.name;
|
return this._initializer.name;
|
||||||
}
|
}
|
||||||
async launch(options = {}) {
|
async launch(options = {}) {
|
||||||
var _this$_defaultLaunchO;
|
(0, import_assert.assert)(!options.userDataDir, "userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead");
|
||||||
(0, _utils.assert)(!options.userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
|
(0, import_assert.assert)(!options.port, "Cannot specify a port without launching as a server.");
|
||||||
(0, _utils.assert)(!options.port, 'Cannot specify a port without launching as a server.');
|
const logger = options.logger || this._playwright._defaultLaunchOptions?.logger;
|
||||||
const logger = options.logger || ((_this$_defaultLaunchO = this._defaultLaunchOptions) === null || _this$_defaultLaunchO === void 0 ? void 0 : _this$_defaultLaunchO.logger);
|
options = { ...this._playwright._defaultLaunchOptions, ...options };
|
||||||
options = {
|
|
||||||
...this._defaultLaunchOptions,
|
|
||||||
...options
|
|
||||||
};
|
|
||||||
const launchOptions = {
|
const launchOptions = {
|
||||||
...options,
|
...options,
|
||||||
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
|
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : void 0,
|
||||||
ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
|
ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
|
||||||
env: options.env ? (0, _clientHelper.envObjectToArray)(options.env) : undefined
|
env: options.env ? (0, import_clientHelper.envObjectToArray)(options.env) : void 0
|
||||||
};
|
};
|
||||||
return await this._wrapApiCall(async () => {
|
return await this._wrapApiCall(async () => {
|
||||||
const browser = _browser3.Browser.from((await this._channel.launch(launchOptions)).browser);
|
const browser = import_browser.Browser.from((await this._channel.launch(launchOptions)).browser);
|
||||||
this._didLaunchBrowser(browser, options, logger);
|
this._didLaunchBrowser(browser, options, logger);
|
||||||
return browser;
|
return browser;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async launchServer(options = {}) {
|
async launchServer(options = {}) {
|
||||||
if (!this._serverLauncher) throw new Error('Launching server is not supported');
|
if (!this._serverLauncher)
|
||||||
options = {
|
throw new Error("Launching server is not supported");
|
||||||
...this._defaultLaunchOptions,
|
options = { ...this._playwright._defaultLaunchOptions, ...options };
|
||||||
...options
|
|
||||||
};
|
|
||||||
return await this._serverLauncher.launchServer(options);
|
return await this._serverLauncher.launchServer(options);
|
||||||
}
|
}
|
||||||
async launchPersistentContext(userDataDir, options = {}) {
|
async launchPersistentContext(userDataDir, options = {}) {
|
||||||
var _this$_defaultLaunchO2;
|
const logger = options.logger || this._playwright._defaultLaunchOptions?.logger;
|
||||||
const logger = options.logger || ((_this$_defaultLaunchO2 = this._defaultLaunchOptions) === null || _this$_defaultLaunchO2 === void 0 ? void 0 : _this$_defaultLaunchO2.logger);
|
(0, import_assert.assert)(!options.port, "Cannot specify a port without launching as a server.");
|
||||||
(0, _utils.assert)(!options.port, 'Cannot specify a port without launching as a server.');
|
options = { ...this._playwright._defaultLaunchOptions, ...this._playwright._defaultContextOptions, ...options };
|
||||||
options = {
|
const contextParams = await (0, import_browserContext.prepareBrowserContextParams)(this._platform, options);
|
||||||
...this._defaultLaunchOptions,
|
|
||||||
...this._defaultContextOptions,
|
|
||||||
...options
|
|
||||||
};
|
|
||||||
const contextParams = await (0, _browserContext.prepareBrowserContextParams)(options);
|
|
||||||
const persistentParams = {
|
const persistentParams = {
|
||||||
...contextParams,
|
...contextParams,
|
||||||
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
|
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : void 0,
|
||||||
ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
|
ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
|
||||||
env: options.env ? (0, _clientHelper.envObjectToArray)(options.env) : undefined,
|
env: options.env ? (0, import_clientHelper.envObjectToArray)(options.env) : void 0,
|
||||||
channel: options.channel,
|
channel: options.channel,
|
||||||
userDataDir
|
userDataDir: this._platform.path().isAbsolute(userDataDir) || !userDataDir ? userDataDir : this._platform.path().resolve(userDataDir)
|
||||||
};
|
};
|
||||||
return await this._wrapApiCall(async () => {
|
return await this._wrapApiCall(async () => {
|
||||||
const result = await this._channel.launchPersistentContext(persistentParams);
|
const result = await this._channel.launchPersistentContext(persistentParams);
|
||||||
const context = _browserContext.BrowserContext.from(result.context);
|
const context = import_browserContext.BrowserContext.from(result.context);
|
||||||
await this._didCreateContext(context, contextParams, options, logger);
|
await this._didCreateContext(context, contextParams, options, logger);
|
||||||
return context;
|
return context;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async connect(optionsOrWsEndpoint, options) {
|
async connect(optionsOrWsEndpoint, options) {
|
||||||
if (typeof optionsOrWsEndpoint === 'string') return await this._connect({
|
if (typeof optionsOrWsEndpoint === "string")
|
||||||
...options,
|
return await this._connect({ ...options, wsEndpoint: optionsOrWsEndpoint });
|
||||||
wsEndpoint: optionsOrWsEndpoint
|
(0, import_assert.assert)(optionsOrWsEndpoint.wsEndpoint, "options.wsEndpoint is required");
|
||||||
});
|
|
||||||
(0, _utils.assert)(optionsOrWsEndpoint.wsEndpoint, 'options.wsEndpoint is required');
|
|
||||||
return await this._connect(optionsOrWsEndpoint);
|
return await this._connect(optionsOrWsEndpoint);
|
||||||
}
|
}
|
||||||
async _connect(params) {
|
async _connect(params) {
|
||||||
const logger = params.logger;
|
const logger = params.logger;
|
||||||
return await this._wrapApiCall(async () => {
|
return await this._wrapApiCall(async () => {
|
||||||
var _params$exposeNetwork;
|
const deadline = params.timeout ? (0, import_time.monotonicTime)() + params.timeout : 0;
|
||||||
const deadline = params.timeout ? (0, _utils.monotonicTime)() + params.timeout : 0;
|
const headers = { "x-playwright-browser": this.name(), ...params.headers };
|
||||||
const headers = {
|
|
||||||
'x-playwright-browser': this.name(),
|
|
||||||
...params.headers
|
|
||||||
};
|
|
||||||
const localUtils = this._connection.localUtils();
|
|
||||||
const connectParams = {
|
const connectParams = {
|
||||||
wsEndpoint: params.wsEndpoint,
|
wsEndpoint: params.wsEndpoint,
|
||||||
headers,
|
headers,
|
||||||
exposeNetwork: (_params$exposeNetwork = params.exposeNetwork) !== null && _params$exposeNetwork !== void 0 ? _params$exposeNetwork : params._exposeNetwork,
|
exposeNetwork: params.exposeNetwork ?? params._exposeNetwork,
|
||||||
slowMo: params.slowMo,
|
slowMo: params.slowMo,
|
||||||
timeout: params.timeout
|
timeout: params.timeout
|
||||||
};
|
};
|
||||||
if (params.__testHookRedirectPortForwarding) connectParams.socksProxyRedirectPortForTest = params.__testHookRedirectPortForwarding;
|
if (params.__testHookRedirectPortForwarding)
|
||||||
const {
|
connectParams.socksProxyRedirectPortForTest = params.__testHookRedirectPortForwarding;
|
||||||
pipe,
|
const connection = await (0, import_webSocket.connectOverWebSocket)(this._connection, connectParams);
|
||||||
headers: connectHeaders
|
|
||||||
} = await localUtils._channel.connect(connectParams);
|
|
||||||
const closePipe = () => pipe.close().catch(() => {});
|
|
||||||
const connection = new _connection.Connection(localUtils, this._instrumentation);
|
|
||||||
connection.markAsRemote();
|
|
||||||
connection.on('close', closePipe);
|
|
||||||
let browser;
|
let browser;
|
||||||
let closeError;
|
connection.on("close", () => {
|
||||||
const onPipeClosed = reason => {
|
for (const context of browser?.contexts() || []) {
|
||||||
// Emulate all pages, contexts and the browser closing upon disconnect.
|
for (const page of context.pages())
|
||||||
for (const context of ((_browser = browser) === null || _browser === void 0 ? void 0 : _browser.contexts()) || []) {
|
page._onClose();
|
||||||
var _browser;
|
|
||||||
for (const page of context.pages()) page._onClose();
|
|
||||||
context._onClose();
|
context._onClose();
|
||||||
}
|
}
|
||||||
connection.close(reason || closeError);
|
setTimeout(() => browser?._didClose(), 0);
|
||||||
// Give a chance to any API call promises to reject upon page/context closure.
|
|
||||||
// This happens naturally when we receive page.onClose and browser.onClose from the server
|
|
||||||
// in separate tasks. However, upon pipe closure we used to dispatch them all synchronously
|
|
||||||
// here and promises did not have a chance to reject.
|
|
||||||
// The order of rejects vs closure is a part of the API contract and our test runner
|
|
||||||
// relies on it to attribute rejections to the right test.
|
|
||||||
setTimeout(() => {
|
|
||||||
var _browser2;
|
|
||||||
return (_browser2 = browser) === null || _browser2 === void 0 ? void 0 : _browser2._didClose();
|
|
||||||
}, 0);
|
|
||||||
};
|
|
||||||
pipe.on('closed', params => onPipeClosed(params.reason));
|
|
||||||
connection.onmessage = message => this._wrapApiCall(() => pipe.send({
|
|
||||||
message
|
|
||||||
}).catch(() => onPipeClosed()), /* isInternal */true);
|
|
||||||
pipe.on('message', ({
|
|
||||||
message
|
|
||||||
}) => {
|
|
||||||
try {
|
|
||||||
connection.dispatch(message);
|
|
||||||
} catch (e) {
|
|
||||||
closeError = String(e);
|
|
||||||
closePipe();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
const result = await (0, _timeoutRunner.raceAgainstDeadline)(async () => {
|
const result = await (0, import_timeoutRunner.raceAgainstDeadline)(async () => {
|
||||||
// For tests.
|
if (params.__testHookBeforeCreateBrowser)
|
||||||
if (params.__testHookBeforeCreateBrowser) await params.__testHookBeforeCreateBrowser();
|
await params.__testHookBeforeCreateBrowser();
|
||||||
const playwright = await connection.initializePlaywright();
|
const playwright = await connection.initializePlaywright();
|
||||||
if (!playwright._initializer.preLaunchedBrowser) {
|
if (!playwright._initializer.preLaunchedBrowser) {
|
||||||
closePipe();
|
connection.close();
|
||||||
throw new Error('Malformed endpoint. Did you use BrowserType.launchServer method?');
|
throw new Error("Malformed endpoint. Did you use BrowserType.launchServer method?");
|
||||||
}
|
}
|
||||||
playwright._setSelectors(this._playwright.selectors);
|
playwright._setSelectors(this._playwright.selectors);
|
||||||
browser = _browser3.Browser.from(playwright._initializer.preLaunchedBrowser);
|
browser = import_browser.Browser.from(playwright._initializer.preLaunchedBrowser);
|
||||||
this._didLaunchBrowser(browser, {}, logger);
|
this._didLaunchBrowser(browser, {}, logger);
|
||||||
browser._shouldCloseConnectionOnClose = true;
|
browser._shouldCloseConnectionOnClose = true;
|
||||||
browser._connectHeaders = connectHeaders;
|
browser.on(import_events.Events.Browser.Disconnected, () => connection.close());
|
||||||
browser.on(_events.Events.Browser.Disconnected, () => this._wrapApiCall(() => closePipe(), /* isInternal */true));
|
|
||||||
return browser;
|
return browser;
|
||||||
}, deadline);
|
}, deadline);
|
||||||
if (!result.timedOut) {
|
if (!result.timedOut) {
|
||||||
return result.result;
|
return result.result;
|
||||||
} else {
|
} else {
|
||||||
closePipe();
|
connection.close();
|
||||||
throw new Error(`Timeout ${params.timeout}ms exceeded`);
|
throw new Error(`Timeout ${params.timeout}ms exceeded`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async connectOverCDP(endpointURLOrOptions, options) {
|
async connectOverCDP(endpointURLOrOptions, options) {
|
||||||
if (typeof endpointURLOrOptions === 'string') return await this._connectOverCDP(endpointURLOrOptions, options);
|
if (typeof endpointURLOrOptions === "string")
|
||||||
const endpointURL = 'endpointURL' in endpointURLOrOptions ? endpointURLOrOptions.endpointURL : endpointURLOrOptions.wsEndpoint;
|
return await this._connectOverCDP(endpointURLOrOptions, options);
|
||||||
(0, _utils.assert)(endpointURL, 'Cannot connect over CDP without wsEndpoint.');
|
const endpointURL = "endpointURL" in endpointURLOrOptions ? endpointURLOrOptions.endpointURL : endpointURLOrOptions.wsEndpoint;
|
||||||
|
(0, import_assert.assert)(endpointURL, "Cannot connect over CDP without wsEndpoint.");
|
||||||
return await this.connectOverCDP(endpointURL, endpointURLOrOptions);
|
return await this.connectOverCDP(endpointURL, endpointURLOrOptions);
|
||||||
}
|
}
|
||||||
async _connectOverCDP(endpointURL, params = {}) {
|
async _connectOverCDP(endpointURL, params = {}) {
|
||||||
if (this.name() !== 'chromium') throw new Error('Connecting over CDP is only supported in Chromium.');
|
if (this.name() !== "chromium")
|
||||||
const headers = params.headers ? (0, _utils.headersObjectToArray)(params.headers) : undefined;
|
throw new Error("Connecting over CDP is only supported in Chromium.");
|
||||||
|
const headers = params.headers ? (0, import_headers.headersObjectToArray)(params.headers) : void 0;
|
||||||
const result = await this._channel.connectOverCDP({
|
const result = await this._channel.connectOverCDP({
|
||||||
endpointURL,
|
endpointURL,
|
||||||
headers,
|
headers,
|
||||||
slowMo: params.slowMo,
|
slowMo: params.slowMo,
|
||||||
timeout: params.timeout
|
timeout: params.timeout
|
||||||
});
|
});
|
||||||
const browser = _browser3.Browser.from(result.browser);
|
const browser = import_browser.Browser.from(result.browser);
|
||||||
this._didLaunchBrowser(browser, {}, params.logger);
|
this._didLaunchBrowser(browser, {}, params.logger);
|
||||||
if (result.defaultContext) await this._didCreateContext(_browserContext.BrowserContext.from(result.defaultContext), {}, {}, params.logger);
|
if (result.defaultContext)
|
||||||
|
await this._didCreateContext(import_browserContext.BrowserContext.from(result.defaultContext), {}, {}, params.logger);
|
||||||
return browser;
|
return browser;
|
||||||
}
|
}
|
||||||
_didLaunchBrowser(browser, browserOptions, logger) {
|
_didLaunchBrowser(browser, browserOptions, logger) {
|
||||||
@@ -229,8 +176,10 @@ class BrowserType extends _channelOwner.ChannelOwner {
|
|||||||
context._browserType = this;
|
context._browserType = this;
|
||||||
this._contexts.add(context);
|
this._contexts.add(context);
|
||||||
context._setOptions(contextOptions, browserOptions);
|
context._setOptions(contextOptions, browserOptions);
|
||||||
if (this._defaultContextTimeout !== undefined) context.setDefaultTimeout(this._defaultContextTimeout);
|
if (this._playwright._defaultContextTimeout !== void 0)
|
||||||
if (this._defaultContextNavigationTimeout !== undefined) context.setDefaultNavigationTimeout(this._defaultContextNavigationTimeout);
|
context.setDefaultTimeout(this._playwright._defaultContextTimeout);
|
||||||
|
if (this._playwright._defaultContextNavigationTimeout !== void 0)
|
||||||
|
context.setDefaultNavigationTimeout(this._playwright._defaultContextNavigationTimeout);
|
||||||
await this._instrumentation.runAfterCreateBrowserContext(context);
|
await this._instrumentation.runAfterCreateBrowserContext(context);
|
||||||
}
|
}
|
||||||
async _willCloseContext(context) {
|
async _willCloseContext(context) {
|
||||||
@@ -238,4 +187,7 @@ class BrowserType extends _channelOwner.ChannelOwner {
|
|||||||
await this._instrumentation.runBeforeCloseBrowserContext(context);
|
await this._instrumentation.runBeforeCloseBrowserContext(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.BrowserType = BrowserType;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
BrowserType
|
||||||
|
});
|
||||||
|
|||||||
60
tvapp2/node_modules/playwright-core/lib/client/cdpSession.js
generated
vendored
@@ -1,36 +1,34 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var cdpSession_exports = {};
|
||||||
|
__export(cdpSession_exports, {
|
||||||
|
CDPSession: () => CDPSession
|
||||||
});
|
});
|
||||||
exports.CDPSession = void 0;
|
module.exports = __toCommonJS(cdpSession_exports);
|
||||||
var _channelOwner = require("./channelOwner");
|
var import_channelOwner = require("./channelOwner");
|
||||||
/**
|
class CDPSession extends import_channelOwner.ChannelOwner {
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class CDPSession extends _channelOwner.ChannelOwner {
|
|
||||||
static from(cdpSession) {
|
static from(cdpSession) {
|
||||||
return cdpSession._object;
|
return cdpSession._object;
|
||||||
}
|
}
|
||||||
constructor(parent, type, guid, initializer) {
|
constructor(parent, type, guid, initializer) {
|
||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
this._channel.on('event', ({
|
this._channel.on("event", ({ method, params }) => {
|
||||||
method,
|
|
||||||
params
|
|
||||||
}) => {
|
|
||||||
this.emit(method, params);
|
this.emit(method, params);
|
||||||
});
|
});
|
||||||
this.on = super.on;
|
this.on = super.on;
|
||||||
@@ -40,14 +38,14 @@ class CDPSession extends _channelOwner.ChannelOwner {
|
|||||||
this.once = super.once;
|
this.once = super.once;
|
||||||
}
|
}
|
||||||
async send(method, params) {
|
async send(method, params) {
|
||||||
const result = await this._channel.send({
|
const result = await this._channel.send({ method, params });
|
||||||
method,
|
|
||||||
params
|
|
||||||
});
|
|
||||||
return result.result;
|
return result.result;
|
||||||
}
|
}
|
||||||
async detach() {
|
async detach() {
|
||||||
return await this._channel.detach();
|
return await this._channel.detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.CDPSession = CDPSession;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
CDPSession
|
||||||
|
});
|
||||||
|
|||||||
202
tvapp2/node_modules/playwright-core/lib/client/channelOwner.js
generated
vendored
@@ -1,58 +1,50 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var channelOwner_exports = {};
|
||||||
|
__export(channelOwner_exports, {
|
||||||
|
ChannelOwner: () => ChannelOwner
|
||||||
});
|
});
|
||||||
exports.ChannelOwner = void 0;
|
module.exports = __toCommonJS(channelOwner_exports);
|
||||||
var _eventEmitter = require("./eventEmitter");
|
var import_eventEmitter = require("./eventEmitter");
|
||||||
var _validator = require("../protocol/validator");
|
var import_validator = require("../protocol/validator");
|
||||||
var _debugLogger = require("../utils/debugLogger");
|
var import_clientStackTrace = require("./clientStackTrace");
|
||||||
var _stackTrace = require("../utils/stackTrace");
|
var import_stackTrace = require("../utils/isomorphic/stackTrace");
|
||||||
var _utils = require("../utils");
|
class ChannelOwner extends import_eventEmitter.EventEmitter {
|
||||||
var _zones = require("../utils/zones");
|
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class ChannelOwner extends _eventEmitter.EventEmitter {
|
|
||||||
constructor(parent, type, guid, initializer) {
|
constructor(parent, type, guid, initializer) {
|
||||||
super();
|
const connection = parent instanceof ChannelOwner ? parent._connection : parent;
|
||||||
this._connection = void 0;
|
super(connection._platform);
|
||||||
this._parent = void 0;
|
this._objects = /* @__PURE__ */ new Map();
|
||||||
this._objects = new Map();
|
this._eventToSubscriptionMapping = /* @__PURE__ */ new Map();
|
||||||
this._type = void 0;
|
|
||||||
this._guid = void 0;
|
|
||||||
this._channel = void 0;
|
|
||||||
this._initializer = void 0;
|
|
||||||
this._logger = void 0;
|
|
||||||
this._instrumentation = void 0;
|
|
||||||
this._eventToSubscriptionMapping = new Map();
|
|
||||||
this._isInternalType = false;
|
this._isInternalType = false;
|
||||||
this._wasCollected = false;
|
this._wasCollected = false;
|
||||||
this.setMaxListeners(0);
|
this.setMaxListeners(0);
|
||||||
this._connection = parent instanceof ChannelOwner ? parent._connection : parent;
|
this._connection = connection;
|
||||||
this._type = type;
|
this._type = type;
|
||||||
this._guid = guid;
|
this._guid = guid;
|
||||||
this._parent = parent instanceof ChannelOwner ? parent : undefined;
|
this._parent = parent instanceof ChannelOwner ? parent : void 0;
|
||||||
this._instrumentation = this._connection._instrumentation;
|
this._instrumentation = this._connection._instrumentation;
|
||||||
this._connection._objects.set(guid, this);
|
this._connection._objects.set(guid, this);
|
||||||
if (this._parent) {
|
if (this._parent) {
|
||||||
this._parent._objects.set(guid, this);
|
this._parent._objects.set(guid, this);
|
||||||
this._logger = this._parent._logger;
|
this._logger = this._parent._logger;
|
||||||
}
|
}
|
||||||
this._channel = this._createChannel(new _eventEmitter.EventEmitter());
|
this._channel = this._createChannel(new import_eventEmitter.EventEmitter(connection._platform));
|
||||||
this._initializer = initializer;
|
this._initializer = initializer;
|
||||||
}
|
}
|
||||||
markAsInternalType() {
|
markAsInternalType() {
|
||||||
@@ -65,36 +57,39 @@ class ChannelOwner extends _eventEmitter.EventEmitter {
|
|||||||
const protocolEvent = this._eventToSubscriptionMapping.get(String(event));
|
const protocolEvent = this._eventToSubscriptionMapping.get(String(event));
|
||||||
if (protocolEvent) {
|
if (protocolEvent) {
|
||||||
this._wrapApiCall(async () => {
|
this._wrapApiCall(async () => {
|
||||||
await this._channel.updateSubscription({
|
await this._channel.updateSubscription({ event: protocolEvent, enabled });
|
||||||
event: protocolEvent,
|
}, true).catch(() => {
|
||||||
enabled
|
});
|
||||||
});
|
|
||||||
}, true).catch(() => {});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
on(event, listener) {
|
on(event, listener) {
|
||||||
if (!this.listenerCount(event)) this._updateSubscription(event, true);
|
if (!this.listenerCount(event))
|
||||||
|
this._updateSubscription(event, true);
|
||||||
super.on(event, listener);
|
super.on(event, listener);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
addListener(event, listener) {
|
addListener(event, listener) {
|
||||||
if (!this.listenerCount(event)) this._updateSubscription(event, true);
|
if (!this.listenerCount(event))
|
||||||
|
this._updateSubscription(event, true);
|
||||||
super.addListener(event, listener);
|
super.addListener(event, listener);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
prependListener(event, listener) {
|
prependListener(event, listener) {
|
||||||
if (!this.listenerCount(event)) this._updateSubscription(event, true);
|
if (!this.listenerCount(event))
|
||||||
|
this._updateSubscription(event, true);
|
||||||
super.prependListener(event, listener);
|
super.prependListener(event, listener);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
off(event, listener) {
|
off(event, listener) {
|
||||||
super.off(event, listener);
|
super.off(event, listener);
|
||||||
if (!this.listenerCount(event)) this._updateSubscription(event, false);
|
if (!this.listenerCount(event))
|
||||||
|
this._updateSubscription(event, false);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
removeListener(event, listener) {
|
removeListener(event, listener) {
|
||||||
super.removeListener(event, listener);
|
super.removeListener(event, listener);
|
||||||
if (!this.listenerCount(event)) this._updateSubscription(event, false);
|
if (!this.listenerCount(event))
|
||||||
|
this._updateSubscription(event, false);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
_adopt(child) {
|
_adopt(child) {
|
||||||
@@ -103,44 +98,44 @@ class ChannelOwner extends _eventEmitter.EventEmitter {
|
|||||||
child._parent = this;
|
child._parent = this;
|
||||||
}
|
}
|
||||||
_dispose(reason) {
|
_dispose(reason) {
|
||||||
// Clean up from parent and connection.
|
if (this._parent)
|
||||||
if (this._parent) this._parent._objects.delete(this._guid);
|
this._parent._objects.delete(this._guid);
|
||||||
this._connection._objects.delete(this._guid);
|
this._connection._objects.delete(this._guid);
|
||||||
this._wasCollected = reason === 'gc';
|
this._wasCollected = reason === "gc";
|
||||||
|
for (const object of [...this._objects.values()])
|
||||||
// Dispose all children.
|
object._dispose(reason);
|
||||||
for (const object of [...this._objects.values()]) object._dispose(reason);
|
|
||||||
this._objects.clear();
|
this._objects.clear();
|
||||||
}
|
}
|
||||||
_debugScopeState() {
|
_debugScopeState() {
|
||||||
return {
|
return {
|
||||||
_guid: this._guid,
|
_guid: this._guid,
|
||||||
objects: Array.from(this._objects.values()).map(o => o._debugScopeState())
|
objects: Array.from(this._objects.values()).map((o) => o._debugScopeState())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
_validatorToWireContext() {
|
||||||
|
return {
|
||||||
|
tChannelImpl: tChannelImplToWire,
|
||||||
|
binary: this._connection.rawBuffers() ? "buffer" : "toBase64",
|
||||||
|
isUnderTest: () => this._platform.isUnderTest()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
_createChannel(base) {
|
_createChannel(base) {
|
||||||
const channel = new Proxy(base, {
|
const channel = new Proxy(base, {
|
||||||
get: (obj, prop) => {
|
get: (obj, prop) => {
|
||||||
if (typeof prop === 'string') {
|
if (typeof prop === "string") {
|
||||||
const validator = (0, _validator.maybeFindValidator)(this._type, prop, 'Params');
|
const validator = (0, import_validator.maybeFindValidator)(this._type, prop, "Params");
|
||||||
if (validator) {
|
if (validator) {
|
||||||
return async params => {
|
return async (params) => {
|
||||||
return await this._wrapApiCall(async apiZone => {
|
return await this._wrapApiCall(async (apiZone) => {
|
||||||
const validatedParams = validator(params, '', {
|
const validatedParams = validator(params, "", this._validatorToWireContext());
|
||||||
tChannelImpl: tChannelImplToWire,
|
|
||||||
binary: this._connection.rawBuffers() ? 'buffer' : 'toBase64'
|
|
||||||
});
|
|
||||||
if (!apiZone.isInternal && !apiZone.reported) {
|
if (!apiZone.isInternal && !apiZone.reported) {
|
||||||
// Reporting/tracing/logging this api call for the first time.
|
|
||||||
apiZone.params = params;
|
apiZone.params = params;
|
||||||
apiZone.reported = true;
|
apiZone.reported = true;
|
||||||
this._instrumentation.onApiCallBegin(apiZone);
|
this._instrumentation.onApiCallBegin(apiZone);
|
||||||
logApiCall(this._logger, `=> ${apiZone.apiName} started`);
|
logApiCall(this._platform, this._logger, `=> ${apiZone.apiName} started`);
|
||||||
return await this._connection.sendMessageToServer(this, prop, validatedParams, apiZone.apiName, apiZone.frames, apiZone.stepId);
|
return await this._connection.sendMessageToServer(this, prop, validatedParams, apiZone.apiName, apiZone.frames, apiZone.stepId);
|
||||||
}
|
}
|
||||||
// Since this api call is either internal, or has already been reported/traced once,
|
return await this._connection.sendMessageToServer(this, prop, validatedParams, void 0, [], void 0);
|
||||||
// passing undefined apiName will avoid an extra unneeded tracing entry.
|
|
||||||
return await this._connection.sendMessageToServer(this, prop, validatedParams, undefined, [], undefined);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -153,63 +148,58 @@ class ChannelOwner extends _eventEmitter.EventEmitter {
|
|||||||
}
|
}
|
||||||
async _wrapApiCall(func, isInternal) {
|
async _wrapApiCall(func, isInternal) {
|
||||||
const logger = this._logger;
|
const logger = this._logger;
|
||||||
const existingApiZone = _zones.zones.zoneData('apiZone');
|
const existingApiZone = this._platform.zones.current().data();
|
||||||
if (existingApiZone) return await func(existingApiZone);
|
if (existingApiZone)
|
||||||
if (isInternal === undefined) isInternal = this._isInternalType;
|
return await func(existingApiZone);
|
||||||
const stackTrace = (0, _stackTrace.captureLibraryStackTrace)();
|
if (isInternal === void 0)
|
||||||
const apiZone = {
|
isInternal = this._isInternalType;
|
||||||
apiName: stackTrace.apiName,
|
const stackTrace = (0, import_clientStackTrace.captureLibraryStackTrace)(this._platform);
|
||||||
frames: stackTrace.frames,
|
const apiZone = { apiName: stackTrace.apiName, frames: stackTrace.frames, isInternal, reported: false, userData: void 0, stepId: void 0 };
|
||||||
isInternal,
|
|
||||||
reported: false,
|
|
||||||
userData: undefined,
|
|
||||||
stepId: undefined
|
|
||||||
};
|
|
||||||
try {
|
try {
|
||||||
const result = await _zones.zones.run('apiZone', apiZone, async () => await func(apiZone));
|
const result = await this._platform.zones.current().push(apiZone).run(async () => await func(apiZone));
|
||||||
if (!isInternal) {
|
if (!isInternal) {
|
||||||
logApiCall(logger, `<= ${apiZone.apiName} succeeded`);
|
logApiCall(this._platform, logger, `<= ${apiZone.apiName} succeeded`);
|
||||||
this._instrumentation.onApiCallEnd(apiZone);
|
this._instrumentation.onApiCallEnd(apiZone);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const innerError = (process.env.PWDEBUGIMPL || (0, _utils.isUnderTest)()) && e.stack ? '\n<inner error>\n' + e.stack : '';
|
const innerError = (this._platform.showInternalStackFrames() || this._platform.isUnderTest()) && e.stack ? "\n<inner error>\n" + e.stack : "";
|
||||||
if (apiZone.apiName && !apiZone.apiName.includes('<anonymous>')) e.message = apiZone.apiName + ': ' + e.message;
|
if (apiZone.apiName && !apiZone.apiName.includes("<anonymous>"))
|
||||||
const stackFrames = '\n' + (0, _stackTrace.stringifyStackFrames)(stackTrace.frames).join('\n') + innerError;
|
e.message = apiZone.apiName + ": " + e.message;
|
||||||
if (stackFrames.trim()) e.stack = e.message + stackFrames;else e.stack = '';
|
const stackFrames = "\n" + (0, import_stackTrace.stringifyStackFrames)(stackTrace.frames).join("\n") + innerError;
|
||||||
|
if (stackFrames.trim())
|
||||||
|
e.stack = e.message + stackFrames;
|
||||||
|
else
|
||||||
|
e.stack = "";
|
||||||
if (!isInternal) {
|
if (!isInternal) {
|
||||||
apiZone.error = e;
|
apiZone.error = e;
|
||||||
logApiCall(logger, `<= ${apiZone.apiName} failed`);
|
logApiCall(this._platform, logger, `<= ${apiZone.apiName} failed`);
|
||||||
this._instrumentation.onApiCallEnd(apiZone);
|
this._instrumentation.onApiCallEnd(apiZone);
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_toImpl() {
|
_toImpl() {
|
||||||
var _this$_connection$toI, _this$_connection;
|
return this._connection.toImpl?.(this);
|
||||||
return (_this$_connection$toI = (_this$_connection = this._connection).toImpl) === null || _this$_connection$toI === void 0 ? void 0 : _this$_connection$toI.call(_this$_connection, this);
|
|
||||||
}
|
}
|
||||||
toJSON() {
|
toJSON() {
|
||||||
// Jest's expect library tries to print objects sometimes.
|
|
||||||
// RPC objects can contain links to lots of other objects,
|
|
||||||
// which can cause jest to crash. Let's help it out
|
|
||||||
// by just returning the important values.
|
|
||||||
return {
|
return {
|
||||||
_type: this._type,
|
_type: this._type,
|
||||||
_guid: this._guid
|
_guid: this._guid
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.ChannelOwner = ChannelOwner;
|
function logApiCall(platform, logger, message) {
|
||||||
function logApiCall(logger, message) {
|
if (logger && logger.isEnabled("api", "info"))
|
||||||
if (logger && logger.isEnabled('api', 'info')) logger.log('api', 'info', message, [], {
|
logger.log("api", "info", message, [], { color: "cyan" });
|
||||||
color: 'cyan'
|
platform.log("api", message);
|
||||||
});
|
|
||||||
_debugLogger.debugLogger.log('api', message);
|
|
||||||
}
|
}
|
||||||
function tChannelImplToWire(names, arg, path, context) {
|
function tChannelImplToWire(names, arg, path, context) {
|
||||||
if (arg._object instanceof ChannelOwner && (names === '*' || names.includes(arg._object._type))) return {
|
if (arg._object instanceof ChannelOwner && (names === "*" || names.includes(arg._object._type)))
|
||||||
guid: arg._object._guid
|
return { guid: arg._object._guid };
|
||||||
};
|
throw new import_validator.ValidationError(`${path}: expected channel ${names.toString()}`);
|
||||||
throw new _validator.ValidationError(`${path}: expected channel ${names.toString()}`);
|
|
||||||
}
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
ChannelOwner
|
||||||
|
});
|
||||||
|
|||||||
89
tvapp2/node_modules/playwright-core/lib/client/clientHelper.js
generated
vendored
@@ -1,57 +1,64 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var clientHelper_exports = {};
|
||||||
|
__export(clientHelper_exports, {
|
||||||
|
addSourceUrlToScript: () => addSourceUrlToScript,
|
||||||
|
envObjectToArray: () => envObjectToArray,
|
||||||
|
evaluationScript: () => evaluationScript
|
||||||
});
|
});
|
||||||
exports.addSourceUrlToScript = addSourceUrlToScript;
|
module.exports = __toCommonJS(clientHelper_exports);
|
||||||
exports.envObjectToArray = envObjectToArray;
|
var import_rtti = require("../utils/isomorphic/rtti");
|
||||||
exports.evaluationScript = evaluationScript;
|
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
|
||||||
var _utils = require("../utils");
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
/**
|
|
||||||
* Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
* Modifications copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function envObjectToArray(env) {
|
function envObjectToArray(env) {
|
||||||
const result = [];
|
const result = [];
|
||||||
for (const name in env) {
|
for (const name in env) {
|
||||||
if (!Object.is(env[name], undefined)) result.push({
|
if (!Object.is(env[name], void 0))
|
||||||
name,
|
result.push({ name, value: String(env[name]) });
|
||||||
value: String(env[name])
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
async function evaluationScript(fun, arg, addSourceUrl = true) {
|
async function evaluationScript(platform, fun, arg, addSourceUrl = true) {
|
||||||
if (typeof fun === 'function') {
|
if (typeof fun === "function") {
|
||||||
const source = fun.toString();
|
const source = fun.toString();
|
||||||
const argString = Object.is(arg, undefined) ? 'undefined' : JSON.stringify(arg);
|
const argString = Object.is(arg, void 0) ? "undefined" : JSON.stringify(arg);
|
||||||
return `(${source})(${argString})`;
|
return `(${source})(${argString})`;
|
||||||
}
|
}
|
||||||
if (arg !== undefined) throw new Error('Cannot evaluate a string with arguments');
|
if (arg !== void 0)
|
||||||
if ((0, _utils.isString)(fun)) return fun;
|
throw new Error("Cannot evaluate a string with arguments");
|
||||||
if (fun.content !== undefined) return fun.content;
|
if ((0, import_rtti.isString)(fun))
|
||||||
if (fun.path !== undefined) {
|
return fun;
|
||||||
let source = await _fs.default.promises.readFile(fun.path, 'utf8');
|
if (fun.content !== void 0)
|
||||||
if (addSourceUrl) source = addSourceUrlToScript(source, fun.path);
|
return fun.content;
|
||||||
|
if (fun.path !== void 0) {
|
||||||
|
let source = await platform.fs().promises.readFile(fun.path, "utf8");
|
||||||
|
if (addSourceUrl)
|
||||||
|
source = addSourceUrlToScript(source, fun.path);
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
throw new Error('Either path or content property must be present');
|
throw new Error("Either path or content property must be present");
|
||||||
}
|
}
|
||||||
function addSourceUrlToScript(source, path) {
|
function addSourceUrlToScript(source, path) {
|
||||||
return `${source}\n//# sourceURL=${path.replace(/\n/g, '')}`;
|
return `${source}
|
||||||
|
//# sourceURL=${path.replace(/\n/g, "")}`;
|
||||||
}
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
addSourceUrlToScript,
|
||||||
|
envObjectToArray,
|
||||||
|
evaluationScript
|
||||||
|
});
|
||||||
|
|||||||
75
tvapp2/node_modules/playwright-core/lib/client/clientInstrumentation.js
generated
vendored
@@ -1,52 +1,55 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var clientInstrumentation_exports = {};
|
||||||
|
__export(clientInstrumentation_exports, {
|
||||||
|
createInstrumentation: () => createInstrumentation
|
||||||
});
|
});
|
||||||
exports.createInstrumentation = createInstrumentation;
|
module.exports = __toCommonJS(clientInstrumentation_exports);
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Instrumentation can mutate the data, for example change apiName or stepId.
|
|
||||||
|
|
||||||
function createInstrumentation() {
|
function createInstrumentation() {
|
||||||
const listeners = [];
|
const listeners = [];
|
||||||
return new Proxy({}, {
|
return new Proxy({}, {
|
||||||
get: (obj, prop) => {
|
get: (obj, prop) => {
|
||||||
if (typeof prop !== 'string') return obj[prop];
|
if (typeof prop !== "string")
|
||||||
if (prop === 'addListener') return listener => listeners.push(listener);
|
return obj[prop];
|
||||||
if (prop === 'removeListener') return listener => listeners.splice(listeners.indexOf(listener), 1);
|
if (prop === "addListener")
|
||||||
if (prop === 'removeAllListeners') return () => listeners.splice(0, listeners.length);
|
return (listener) => listeners.push(listener);
|
||||||
if (prop.startsWith('run')) {
|
if (prop === "removeListener")
|
||||||
|
return (listener) => listeners.splice(listeners.indexOf(listener), 1);
|
||||||
|
if (prop === "removeAllListeners")
|
||||||
|
return () => listeners.splice(0, listeners.length);
|
||||||
|
if (prop.startsWith("run")) {
|
||||||
return async (...params) => {
|
return async (...params) => {
|
||||||
for (const listener of listeners) {
|
for (const listener of listeners)
|
||||||
var _prop, _ref;
|
await listener[prop]?.(...params);
|
||||||
await ((_prop = (_ref = listener)[prop]) === null || _prop === void 0 ? void 0 : _prop.call(_ref, ...params));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (prop.startsWith('on')) {
|
if (prop.startsWith("on")) {
|
||||||
return (...params) => {
|
return (...params) => {
|
||||||
for (const listener of listeners) {
|
for (const listener of listeners)
|
||||||
var _prop2, _ref2;
|
listener[prop]?.(...params);
|
||||||
(_prop2 = (_ref2 = listener)[prop]) === null || _prop2 === void 0 || _prop2.call(_ref2, ...params);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return obj[prop];
|
return obj[prop];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
createInstrumentation
|
||||||
|
});
|
||||||
|
|||||||
70
tvapp2/node_modules/playwright-core/lib/client/clock.js
generated
vendored
@@ -1,32 +1,32 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var clock_exports = {};
|
||||||
|
__export(clock_exports, {
|
||||||
|
Clock: () => Clock
|
||||||
});
|
});
|
||||||
exports.Clock = void 0;
|
module.exports = __toCommonJS(clock_exports);
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Clock {
|
class Clock {
|
||||||
constructor(browserContext) {
|
constructor(browserContext) {
|
||||||
this._browserContext = void 0;
|
|
||||||
this._browserContext = browserContext;
|
this._browserContext = browserContext;
|
||||||
}
|
}
|
||||||
async install(options = {}) {
|
async install(options = {}) {
|
||||||
await this._browserContext._channel.clockInstall(options.time !== undefined ? parseTime(options.time) : {});
|
await this._browserContext._channel.clockInstall(options.time !== void 0 ? parseTime(options.time) : {});
|
||||||
}
|
}
|
||||||
async fastForward(ticks) {
|
async fastForward(ticks) {
|
||||||
await this._browserContext._channel.clockFastForward(parseTicks(ticks));
|
await this._browserContext._channel.clockFastForward(parseTicks(ticks));
|
||||||
@@ -47,22 +47,22 @@ class Clock {
|
|||||||
await this._browserContext._channel.clockSetSystemTime(parseTime(time));
|
await this._browserContext._channel.clockSetSystemTime(parseTime(time));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Clock = Clock;
|
|
||||||
function parseTime(time) {
|
function parseTime(time) {
|
||||||
if (typeof time === 'number') return {
|
if (typeof time === "number")
|
||||||
timeNumber: time
|
return { timeNumber: time };
|
||||||
};
|
if (typeof time === "string")
|
||||||
if (typeof time === 'string') return {
|
return { timeString: time };
|
||||||
timeString: time
|
if (!isFinite(time.getTime()))
|
||||||
};
|
throw new Error(`Invalid date: ${time}`);
|
||||||
if (!isFinite(time.getTime())) throw new Error(`Invalid date: ${time}`);
|
return { timeNumber: time.getTime() };
|
||||||
return {
|
|
||||||
timeNumber: time.getTime()
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
function parseTicks(ticks) {
|
function parseTicks(ticks) {
|
||||||
return {
|
return {
|
||||||
ticksNumber: typeof ticks === 'number' ? ticks : undefined,
|
ticksNumber: typeof ticks === "number" ? ticks : void 0,
|
||||||
ticksString: typeof ticks === 'string' ? ticks : undefined
|
ticksString: typeof ticks === "string" ? ticks : void 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
Clock
|
||||||
|
});
|
||||||
|
|||||||
419
tvapp2/node_modules/playwright-core/lib/client/connection.js
generated
vendored
@@ -1,84 +1,81 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var connection_exports = {};
|
||||||
|
__export(connection_exports, {
|
||||||
|
Connection: () => Connection
|
||||||
});
|
});
|
||||||
exports.Connection = void 0;
|
module.exports = __toCommonJS(connection_exports);
|
||||||
var _browser = require("./browser");
|
var import_eventEmitter = require("./eventEmitter");
|
||||||
var _browserContext = require("./browserContext");
|
var import_android = require("./android");
|
||||||
var _browserType = require("./browserType");
|
var import_artifact = require("./artifact");
|
||||||
var _channelOwner = require("./channelOwner");
|
var import_browser = require("./browser");
|
||||||
var _elementHandle = require("./elementHandle");
|
var import_browserContext = require("./browserContext");
|
||||||
var _frame = require("./frame");
|
var import_browserType = require("./browserType");
|
||||||
var _jsHandle = require("./jsHandle");
|
var import_cdpSession = require("./cdpSession");
|
||||||
var _network = require("./network");
|
var import_channelOwner = require("./channelOwner");
|
||||||
var _page = require("./page");
|
var import_clientInstrumentation = require("./clientInstrumentation");
|
||||||
var _worker = require("./worker");
|
var import_dialog = require("./dialog");
|
||||||
var _dialog = require("./dialog");
|
var import_electron = require("./electron");
|
||||||
var _errors = require("./errors");
|
var import_elementHandle = require("./elementHandle");
|
||||||
var _cdpSession = require("./cdpSession");
|
var import_errors = require("./errors");
|
||||||
var _playwright = require("./playwright");
|
var import_fetch = require("./fetch");
|
||||||
var _electron = require("./electron");
|
var import_frame = require("./frame");
|
||||||
var _stream = require("./stream");
|
var import_jsHandle = require("./jsHandle");
|
||||||
var _writableStream = require("./writableStream");
|
var import_jsonPipe = require("./jsonPipe");
|
||||||
var _debugLogger = require("../utils/debugLogger");
|
var import_localUtils = require("./localUtils");
|
||||||
var _selectors = require("./selectors");
|
var import_network = require("./network");
|
||||||
var _android = require("./android");
|
var import_page = require("./page");
|
||||||
var _artifact = require("./artifact");
|
var import_playwright = require("./playwright");
|
||||||
var _events = require("events");
|
var import_selectors = require("./selectors");
|
||||||
var _jsonPipe = require("./jsonPipe");
|
var import_stream = require("./stream");
|
||||||
var _fetch = require("./fetch");
|
var import_tracing = require("./tracing");
|
||||||
var _localUtils = require("./localUtils");
|
var import_worker = require("./worker");
|
||||||
var _tracing = require("./tracing");
|
var import_writableStream = require("./writableStream");
|
||||||
var _validator = require("../protocol/validator");
|
var import_validator = require("../protocol/validator");
|
||||||
var _clientInstrumentation = require("./clientInstrumentation");
|
var import_stackTrace = require("../utils/isomorphic/stackTrace");
|
||||||
var _utils = require("../utils");
|
class Root extends import_channelOwner.ChannelOwner {
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Root extends _channelOwner.ChannelOwner {
|
|
||||||
constructor(connection) {
|
constructor(connection) {
|
||||||
super(connection, 'Root', '', {});
|
super(connection, "Root", "", {});
|
||||||
}
|
}
|
||||||
async initialize() {
|
async initialize() {
|
||||||
return _playwright.Playwright.from((await this._channel.initialize({
|
return import_playwright.Playwright.from((await this._channel.initialize({
|
||||||
sdkLanguage: 'javascript'
|
sdkLanguage: "javascript"
|
||||||
})).playwright);
|
})).playwright);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class DummyChannelOwner extends _channelOwner.ChannelOwner {}
|
class DummyChannelOwner extends import_channelOwner.ChannelOwner {
|
||||||
class Connection extends _events.EventEmitter {
|
}
|
||||||
constructor(localUtils, instrumentation) {
|
class Connection extends import_eventEmitter.EventEmitter {
|
||||||
super();
|
constructor(platform, localUtils, instrumentation, headers = []) {
|
||||||
this._objects = new Map();
|
super(platform);
|
||||||
this.onmessage = message => {};
|
this._objects = /* @__PURE__ */ new Map();
|
||||||
|
this.onmessage = (message) => {
|
||||||
|
};
|
||||||
this._lastId = 0;
|
this._lastId = 0;
|
||||||
this._callbacks = new Map();
|
this._callbacks = /* @__PURE__ */ new Map();
|
||||||
this._rootObject = void 0;
|
|
||||||
this._closedError = void 0;
|
|
||||||
this._isRemote = false;
|
this._isRemote = false;
|
||||||
this._localUtils = void 0;
|
|
||||||
this._rawBuffers = false;
|
this._rawBuffers = false;
|
||||||
// Some connections allow resolving in-process dispatchers.
|
|
||||||
this.toImpl = void 0;
|
|
||||||
this._tracingCount = 0;
|
this._tracingCount = 0;
|
||||||
this._instrumentation = void 0;
|
this._instrumentation = instrumentation || (0, import_clientInstrumentation.createInstrumentation)();
|
||||||
this._instrumentation = instrumentation || (0, _clientInstrumentation.createInstrumentation)();
|
|
||||||
this._localUtils = localUtils;
|
this._localUtils = localUtils;
|
||||||
this._rootObject = new Root(this);
|
this._rootObject = new Root(this);
|
||||||
|
this.headers = headers;
|
||||||
}
|
}
|
||||||
markAsRemote() {
|
markAsRemote() {
|
||||||
this._isRemote = true;
|
this._isRemote = true;
|
||||||
@@ -102,232 +99,220 @@ class Connection extends _events.EventEmitter {
|
|||||||
return this._objects.get(guid);
|
return this._objects.get(guid);
|
||||||
}
|
}
|
||||||
setIsTracing(isTracing) {
|
setIsTracing(isTracing) {
|
||||||
if (isTracing) this._tracingCount++;else this._tracingCount--;
|
if (isTracing)
|
||||||
|
this._tracingCount++;
|
||||||
|
else
|
||||||
|
this._tracingCount--;
|
||||||
}
|
}
|
||||||
async sendMessageToServer(object, method, params, apiName, frames, stepId) {
|
async sendMessageToServer(object, method, params, apiName, frames, stepId) {
|
||||||
var _this$_localUtils;
|
if (this._closedError)
|
||||||
if (this._closedError) throw this._closedError;
|
throw this._closedError;
|
||||||
if (object._wasCollected) throw new Error('The object has been collected to prevent unbounded heap growth.');
|
if (object._wasCollected)
|
||||||
|
throw new Error("The object has been collected to prevent unbounded heap growth.");
|
||||||
const guid = object._guid;
|
const guid = object._guid;
|
||||||
const type = object._type;
|
const type = object._type;
|
||||||
const id = ++this._lastId;
|
const id = ++this._lastId;
|
||||||
const message = {
|
const message = { id, guid, method, params };
|
||||||
id,
|
if (this._platform.isLogEnabled("channel")) {
|
||||||
guid,
|
this._platform.log("channel", "SEND> " + JSON.stringify(message));
|
||||||
method,
|
|
||||||
params
|
|
||||||
};
|
|
||||||
if (_debugLogger.debugLogger.isEnabled('channel')) {
|
|
||||||
// Do not include metadata in debug logs to avoid noise.
|
|
||||||
_debugLogger.debugLogger.log('channel', 'SEND> ' + JSON.stringify(message));
|
|
||||||
}
|
}
|
||||||
const location = frames[0] ? {
|
const location = frames[0] ? { file: frames[0].file, line: frames[0].line, column: frames[0].column } : void 0;
|
||||||
file: frames[0].file,
|
const metadata = { apiName, location, internal: !apiName, stepId };
|
||||||
line: frames[0].line,
|
if (this._tracingCount && frames && type !== "LocalUtils")
|
||||||
column: frames[0].column
|
this._localUtils?.addStackToTracingNoReply({ callData: { stack: frames, id } }).catch(() => {
|
||||||
} : undefined;
|
});
|
||||||
const metadata = {
|
this._platform.zones.empty.run(() => this.onmessage({ ...message, metadata }));
|
||||||
apiName,
|
return await new Promise((resolve, reject) => this._callbacks.set(id, { resolve, reject, apiName, type, method }));
|
||||||
location,
|
}
|
||||||
internal: !apiName,
|
_validatorFromWireContext() {
|
||||||
stepId
|
return {
|
||||||
|
tChannelImpl: this._tChannelImplFromWire.bind(this),
|
||||||
|
binary: this._rawBuffers ? "buffer" : "fromBase64",
|
||||||
|
isUnderTest: () => this._platform.isUnderTest()
|
||||||
};
|
};
|
||||||
if (this._tracingCount && frames && type !== 'LocalUtils') (_this$_localUtils = this._localUtils) === null || _this$_localUtils === void 0 || _this$_localUtils._channel.addStackToTracingNoReply({
|
|
||||||
callData: {
|
|
||||||
stack: frames,
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}).catch(() => {});
|
|
||||||
// We need to exit zones before calling into the server, otherwise
|
|
||||||
// when we receive events from the server, we would be in an API zone.
|
|
||||||
_utils.zones.empty().run(() => this.onmessage({
|
|
||||||
...message,
|
|
||||||
metadata
|
|
||||||
}));
|
|
||||||
return await new Promise((resolve, reject) => this._callbacks.set(id, {
|
|
||||||
resolve,
|
|
||||||
reject,
|
|
||||||
apiName,
|
|
||||||
type,
|
|
||||||
method
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
dispatch(message) {
|
dispatch(message) {
|
||||||
if (this._closedError) return;
|
if (this._closedError)
|
||||||
const {
|
return;
|
||||||
id,
|
const { id, guid, method, params, result, error, log } = message;
|
||||||
guid,
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
result,
|
|
||||||
error,
|
|
||||||
log
|
|
||||||
} = message;
|
|
||||||
if (id) {
|
if (id) {
|
||||||
if (_debugLogger.debugLogger.isEnabled('channel')) _debugLogger.debugLogger.log('channel', '<RECV ' + JSON.stringify(message));
|
if (this._platform.isLogEnabled("channel"))
|
||||||
|
this._platform.log("channel", "<RECV " + JSON.stringify(message));
|
||||||
const callback = this._callbacks.get(id);
|
const callback = this._callbacks.get(id);
|
||||||
if (!callback) throw new Error(`Cannot find command to respond: ${id}`);
|
if (!callback)
|
||||||
|
throw new Error(`Cannot find command to respond: ${id}`);
|
||||||
this._callbacks.delete(id);
|
this._callbacks.delete(id);
|
||||||
if (error && !result) {
|
if (error && !result) {
|
||||||
const parsedError = (0, _errors.parseError)(error);
|
const parsedError = (0, import_errors.parseError)(error);
|
||||||
(0, _utils.rewriteErrorMessage)(parsedError, parsedError.message + (0, _utils.formatCallLog)(log));
|
(0, import_stackTrace.rewriteErrorMessage)(parsedError, parsedError.message + formatCallLog(this._platform, log));
|
||||||
callback.reject(parsedError);
|
callback.reject(parsedError);
|
||||||
} else {
|
} else {
|
||||||
const validator = (0, _validator.findValidator)(callback.type, callback.method, 'Result');
|
const validator2 = (0, import_validator.findValidator)(callback.type, callback.method, "Result");
|
||||||
callback.resolve(validator(result, '', {
|
callback.resolve(validator2(result, "", this._validatorFromWireContext()));
|
||||||
tChannelImpl: this._tChannelImplFromWire.bind(this),
|
|
||||||
binary: this._rawBuffers ? 'buffer' : 'fromBase64'
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_debugLogger.debugLogger.isEnabled('channel')) _debugLogger.debugLogger.log('channel', '<EVENT ' + JSON.stringify(message));
|
if (this._platform.isLogEnabled("channel"))
|
||||||
if (method === '__create__') {
|
this._platform.log("channel", "<EVENT " + JSON.stringify(message));
|
||||||
|
if (method === "__create__") {
|
||||||
this._createRemoteObject(guid, params.type, params.guid, params.initializer);
|
this._createRemoteObject(guid, params.type, params.guid, params.initializer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const object = this._objects.get(guid);
|
const object = this._objects.get(guid);
|
||||||
if (!object) throw new Error(`Cannot find object to "${method}": ${guid}`);
|
if (!object)
|
||||||
if (method === '__adopt__') {
|
throw new Error(`Cannot find object to "${method}": ${guid}`);
|
||||||
|
if (method === "__adopt__") {
|
||||||
const child = this._objects.get(params.guid);
|
const child = this._objects.get(params.guid);
|
||||||
if (!child) throw new Error(`Unknown new child: ${params.guid}`);
|
if (!child)
|
||||||
|
throw new Error(`Unknown new child: ${params.guid}`);
|
||||||
object._adopt(child);
|
object._adopt(child);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (method === '__dispose__') {
|
if (method === "__dispose__") {
|
||||||
object._dispose(params.reason);
|
object._dispose(params.reason);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const validator = (0, _validator.findValidator)(object._type, method, 'Event');
|
const validator = (0, import_validator.findValidator)(object._type, method, "Event");
|
||||||
object._channel.emit(method, validator(params, '', {
|
object._channel.emit(method, validator(params, "", this._validatorFromWireContext()));
|
||||||
tChannelImpl: this._tChannelImplFromWire.bind(this),
|
|
||||||
binary: this._rawBuffers ? 'buffer' : 'fromBase64'
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
close(cause) {
|
close(cause) {
|
||||||
if (this._closedError) return;
|
if (this._closedError)
|
||||||
this._closedError = new _errors.TargetClosedError(cause);
|
return;
|
||||||
for (const callback of this._callbacks.values()) callback.reject(this._closedError);
|
this._closedError = new import_errors.TargetClosedError(cause);
|
||||||
|
for (const callback of this._callbacks.values())
|
||||||
|
callback.reject(this._closedError);
|
||||||
this._callbacks.clear();
|
this._callbacks.clear();
|
||||||
this.emit('close');
|
this.emit("close");
|
||||||
}
|
}
|
||||||
_tChannelImplFromWire(names, arg, path, context) {
|
_tChannelImplFromWire(names, arg, path, context) {
|
||||||
if (arg && typeof arg === 'object' && typeof arg.guid === 'string') {
|
if (arg && typeof arg === "object" && typeof arg.guid === "string") {
|
||||||
const object = this._objects.get(arg.guid);
|
const object = this._objects.get(arg.guid);
|
||||||
if (!object) throw new Error(`Object with guid ${arg.guid} was not bound in the connection`);
|
if (!object)
|
||||||
if (names !== '*' && !names.includes(object._type)) throw new _validator.ValidationError(`${path}: expected channel ${names.toString()}`);
|
throw new Error(`Object with guid ${arg.guid} was not bound in the connection`);
|
||||||
|
if (names !== "*" && !names.includes(object._type))
|
||||||
|
throw new import_validator.ValidationError(`${path}: expected channel ${names.toString()}`);
|
||||||
return object._channel;
|
return object._channel;
|
||||||
}
|
}
|
||||||
throw new _validator.ValidationError(`${path}: expected channel ${names.toString()}`);
|
throw new import_validator.ValidationError(`${path}: expected channel ${names.toString()}`);
|
||||||
}
|
}
|
||||||
_createRemoteObject(parentGuid, type, guid, initializer) {
|
_createRemoteObject(parentGuid, type, guid, initializer) {
|
||||||
const parent = this._objects.get(parentGuid);
|
const parent = this._objects.get(parentGuid);
|
||||||
if (!parent) throw new Error(`Cannot find parent object ${parentGuid} to create ${guid}`);
|
if (!parent)
|
||||||
|
throw new Error(`Cannot find parent object ${parentGuid} to create ${guid}`);
|
||||||
let result;
|
let result;
|
||||||
const validator = (0, _validator.findValidator)(type, '', 'Initializer');
|
const validator = (0, import_validator.findValidator)(type, "", "Initializer");
|
||||||
initializer = validator(initializer, '', {
|
initializer = validator(initializer, "", this._validatorFromWireContext());
|
||||||
tChannelImpl: this._tChannelImplFromWire.bind(this),
|
|
||||||
binary: this._rawBuffers ? 'buffer' : 'fromBase64'
|
|
||||||
});
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'Android':
|
case "Android":
|
||||||
result = new _android.Android(parent, type, guid, initializer);
|
result = new import_android.Android(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'AndroidSocket':
|
case "AndroidSocket":
|
||||||
result = new _android.AndroidSocket(parent, type, guid, initializer);
|
result = new import_android.AndroidSocket(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'AndroidDevice':
|
case "AndroidDevice":
|
||||||
result = new _android.AndroidDevice(parent, type, guid, initializer);
|
result = new import_android.AndroidDevice(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'APIRequestContext':
|
case "APIRequestContext":
|
||||||
result = new _fetch.APIRequestContext(parent, type, guid, initializer);
|
result = new import_fetch.APIRequestContext(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'Artifact':
|
case "Artifact":
|
||||||
result = new _artifact.Artifact(parent, type, guid, initializer);
|
result = new import_artifact.Artifact(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'BindingCall':
|
case "BindingCall":
|
||||||
result = new _page.BindingCall(parent, type, guid, initializer);
|
result = new import_page.BindingCall(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'Browser':
|
case "Browser":
|
||||||
result = new _browser.Browser(parent, type, guid, initializer);
|
result = new import_browser.Browser(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'BrowserContext':
|
case "BrowserContext":
|
||||||
result = new _browserContext.BrowserContext(parent, type, guid, initializer);
|
result = new import_browserContext.BrowserContext(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'BrowserType':
|
case "BrowserType":
|
||||||
result = new _browserType.BrowserType(parent, type, guid, initializer);
|
result = new import_browserType.BrowserType(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'CDPSession':
|
case "CDPSession":
|
||||||
result = new _cdpSession.CDPSession(parent, type, guid, initializer);
|
result = new import_cdpSession.CDPSession(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'Dialog':
|
case "Dialog":
|
||||||
result = new _dialog.Dialog(parent, type, guid, initializer);
|
result = new import_dialog.Dialog(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'Electron':
|
case "Electron":
|
||||||
result = new _electron.Electron(parent, type, guid, initializer);
|
result = new import_electron.Electron(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'ElectronApplication':
|
case "ElectronApplication":
|
||||||
result = new _electron.ElectronApplication(parent, type, guid, initializer);
|
result = new import_electron.ElectronApplication(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'ElementHandle':
|
case "ElementHandle":
|
||||||
result = new _elementHandle.ElementHandle(parent, type, guid, initializer);
|
result = new import_elementHandle.ElementHandle(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'Frame':
|
case "Frame":
|
||||||
result = new _frame.Frame(parent, type, guid, initializer);
|
result = new import_frame.Frame(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'JSHandle':
|
case "JSHandle":
|
||||||
result = new _jsHandle.JSHandle(parent, type, guid, initializer);
|
result = new import_jsHandle.JSHandle(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'JsonPipe':
|
case "JsonPipe":
|
||||||
result = new _jsonPipe.JsonPipe(parent, type, guid, initializer);
|
result = new import_jsonPipe.JsonPipe(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'LocalUtils':
|
case "LocalUtils":
|
||||||
result = new _localUtils.LocalUtils(parent, type, guid, initializer);
|
result = new import_localUtils.LocalUtils(parent, type, guid, initializer);
|
||||||
if (!this._localUtils) this._localUtils = result;
|
if (!this._localUtils)
|
||||||
|
this._localUtils = result;
|
||||||
break;
|
break;
|
||||||
case 'Page':
|
case "Page":
|
||||||
result = new _page.Page(parent, type, guid, initializer);
|
result = new import_page.Page(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'Playwright':
|
case "Playwright":
|
||||||
result = new _playwright.Playwright(parent, type, guid, initializer);
|
result = new import_playwright.Playwright(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'Request':
|
case "Request":
|
||||||
result = new _network.Request(parent, type, guid, initializer);
|
result = new import_network.Request(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'Response':
|
case "Response":
|
||||||
result = new _network.Response(parent, type, guid, initializer);
|
result = new import_network.Response(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'Route':
|
case "Route":
|
||||||
result = new _network.Route(parent, type, guid, initializer);
|
result = new import_network.Route(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'Stream':
|
case "Stream":
|
||||||
result = new _stream.Stream(parent, type, guid, initializer);
|
result = new import_stream.Stream(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'Selectors':
|
case "Selectors":
|
||||||
result = new _selectors.SelectorsOwner(parent, type, guid, initializer);
|
result = new import_selectors.SelectorsOwner(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'SocksSupport':
|
case "SocksSupport":
|
||||||
result = new DummyChannelOwner(parent, type, guid, initializer);
|
result = new DummyChannelOwner(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'Tracing':
|
case "Tracing":
|
||||||
result = new _tracing.Tracing(parent, type, guid, initializer);
|
result = new import_tracing.Tracing(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'WebSocket':
|
case "WebSocket":
|
||||||
result = new _network.WebSocket(parent, type, guid, initializer);
|
result = new import_network.WebSocket(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'WebSocketRoute':
|
case "WebSocketRoute":
|
||||||
result = new _network.WebSocketRoute(parent, type, guid, initializer);
|
result = new import_network.WebSocketRoute(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'Worker':
|
case "Worker":
|
||||||
result = new _worker.Worker(parent, type, guid, initializer);
|
result = new import_worker.Worker(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
case 'WritableStream':
|
case "WritableStream":
|
||||||
result = new _writableStream.WritableStream(parent, type, guid, initializer);
|
result = new import_writableStream.WritableStream(parent, type, guid, initializer);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error('Missing type ' + type);
|
throw new Error("Missing type " + type);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Connection = Connection;
|
function formatCallLog(platform, log) {
|
||||||
|
if (!log || !log.some((l) => !!l))
|
||||||
|
return "";
|
||||||
|
return `
|
||||||
|
Call log:
|
||||||
|
${platform.colors.dim(log.join("\n"))}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
Connection
|
||||||
|
});
|
||||||
|
|||||||
66
tvapp2/node_modules/playwright-core/lib/client/consoleMessage.js
generated
vendored
@@ -1,37 +1,34 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var consoleMessage_exports = {};
|
||||||
|
__export(consoleMessage_exports, {
|
||||||
|
ConsoleMessage: () => ConsoleMessage
|
||||||
});
|
});
|
||||||
exports.ConsoleMessage = void 0;
|
module.exports = __toCommonJS(consoleMessage_exports);
|
||||||
var util = _interopRequireWildcard(require("util"));
|
var import_jsHandle = require("./jsHandle");
|
||||||
var _jsHandle = require("./jsHandle");
|
var import_page = require("./page");
|
||||||
var _page = require("./page");
|
|
||||||
let _util$inspect$custom;
|
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
||||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
||||||
_util$inspect$custom = util.inspect.custom;
|
|
||||||
class ConsoleMessage {
|
class ConsoleMessage {
|
||||||
constructor(event) {
|
constructor(platform, event) {
|
||||||
this._page = void 0;
|
this._page = "page" in event && event.page ? import_page.Page.from(event.page) : null;
|
||||||
this._event = void 0;
|
|
||||||
this._page = 'page' in event && event.page ? _page.Page.from(event.page) : null;
|
|
||||||
this._event = event;
|
this._event = event;
|
||||||
|
if (platform.inspectCustom)
|
||||||
|
this[platform.inspectCustom] = () => this._inspect();
|
||||||
}
|
}
|
||||||
page() {
|
page() {
|
||||||
return this._page;
|
return this._page;
|
||||||
@@ -43,13 +40,16 @@ class ConsoleMessage {
|
|||||||
return this._event.text;
|
return this._event.text;
|
||||||
}
|
}
|
||||||
args() {
|
args() {
|
||||||
return this._event.args.map(_jsHandle.JSHandle.from);
|
return this._event.args.map(import_jsHandle.JSHandle.from);
|
||||||
}
|
}
|
||||||
location() {
|
location() {
|
||||||
return this._event.location;
|
return this._event.location;
|
||||||
}
|
}
|
||||||
[_util$inspect$custom]() {
|
_inspect() {
|
||||||
return this.text();
|
return this.text();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.ConsoleMessage = ConsoleMessage;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
ConsoleMessage
|
||||||
|
});
|
||||||
|
|||||||
47
tvapp2/node_modules/playwright-core/lib/client/coverage.js
generated
vendored
@@ -1,28 +1,28 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var coverage_exports = {};
|
||||||
|
__export(coverage_exports, {
|
||||||
|
Coverage: () => Coverage
|
||||||
});
|
});
|
||||||
exports.Coverage = void 0;
|
module.exports = __toCommonJS(coverage_exports);
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Coverage {
|
class Coverage {
|
||||||
constructor(channel) {
|
constructor(channel) {
|
||||||
this._channel = void 0;
|
|
||||||
this._channel = channel;
|
this._channel = channel;
|
||||||
}
|
}
|
||||||
async startJSCoverage(options = {}) {
|
async startJSCoverage(options = {}) {
|
||||||
@@ -38,4 +38,7 @@ class Coverage {
|
|||||||
return (await this._channel.stopCSSCoverage()).entries;
|
return (await this._channel.stopCSSCoverage()).entries;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Coverage = Coverage;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
Coverage
|
||||||
|
});
|
||||||
|
|||||||
61
tvapp2/node_modules/playwright-core/lib/client/dialog.js
generated
vendored
@@ -1,37 +1,35 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var dialog_exports = {};
|
||||||
|
__export(dialog_exports, {
|
||||||
|
Dialog: () => Dialog
|
||||||
});
|
});
|
||||||
exports.Dialog = void 0;
|
module.exports = __toCommonJS(dialog_exports);
|
||||||
var _channelOwner = require("./channelOwner");
|
var import_channelOwner = require("./channelOwner");
|
||||||
var _page = require("./page");
|
var import_page = require("./page");
|
||||||
/**
|
class Dialog extends import_channelOwner.ChannelOwner {
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Dialog extends _channelOwner.ChannelOwner {
|
|
||||||
static from(dialog) {
|
static from(dialog) {
|
||||||
return dialog._object;
|
return dialog._object;
|
||||||
}
|
}
|
||||||
constructor(parent, type, guid, initializer) {
|
constructor(parent, type, guid, initializer) {
|
||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
// Note: dialogs that open early during page initialization block it.
|
this._page = import_page.Page.fromNullable(initializer.page);
|
||||||
// Therefore, we must report the dialog without a page to be able to handle it.
|
|
||||||
this._page = void 0;
|
|
||||||
this._page = _page.Page.fromNullable(initializer.page);
|
|
||||||
}
|
}
|
||||||
page() {
|
page() {
|
||||||
return this._page;
|
return this._page;
|
||||||
@@ -46,12 +44,13 @@ class Dialog extends _channelOwner.ChannelOwner {
|
|||||||
return this._initializer.defaultValue;
|
return this._initializer.defaultValue;
|
||||||
}
|
}
|
||||||
async accept(promptText) {
|
async accept(promptText) {
|
||||||
await this._channel.accept({
|
await this._channel.accept({ promptText });
|
||||||
promptText
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async dismiss() {
|
async dismiss() {
|
||||||
await this._channel.dismiss();
|
await this._channel.dismiss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Dialog = Dialog;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
Dialog
|
||||||
|
});
|
||||||
|
|||||||
50
tvapp2/node_modules/playwright-core/lib/client/download.js
generated
vendored
@@ -1,31 +1,28 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var download_exports = {};
|
||||||
|
__export(download_exports, {
|
||||||
|
Download: () => Download
|
||||||
});
|
});
|
||||||
exports.Download = void 0;
|
module.exports = __toCommonJS(download_exports);
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Download {
|
class Download {
|
||||||
constructor(page, url, suggestedFilename, artifact) {
|
constructor(page, url, suggestedFilename, artifact) {
|
||||||
this._page = void 0;
|
|
||||||
this._url = void 0;
|
|
||||||
this._suggestedFilename = void 0;
|
|
||||||
this._artifact = void 0;
|
|
||||||
this._page = page;
|
this._page = page;
|
||||||
this._url = url;
|
this._url = url;
|
||||||
this._suggestedFilename = suggestedFilename;
|
this._suggestedFilename = suggestedFilename;
|
||||||
@@ -59,4 +56,7 @@ class Download {
|
|||||||
return await this._artifact.delete();
|
return await this._artifact.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Download = Download;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
Download
|
||||||
|
});
|
||||||
|
|||||||
150
tvapp2/node_modules/playwright-core/lib/client/electron.js
generated
vendored
@@ -1,35 +1,37 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var electron_exports = {};
|
||||||
|
__export(electron_exports, {
|
||||||
|
Electron: () => Electron,
|
||||||
|
ElectronApplication: () => ElectronApplication
|
||||||
});
|
});
|
||||||
exports.ElectronApplication = exports.Electron = void 0;
|
module.exports = __toCommonJS(electron_exports);
|
||||||
var _timeoutSettings = require("../common/timeoutSettings");
|
var import_browserContext = require("./browserContext");
|
||||||
var _browserContext = require("./browserContext");
|
var import_channelOwner = require("./channelOwner");
|
||||||
var _channelOwner = require("./channelOwner");
|
var import_clientHelper = require("./clientHelper");
|
||||||
var _clientHelper = require("./clientHelper");
|
var import_consoleMessage = require("./consoleMessage");
|
||||||
var _events = require("./events");
|
var import_errors = require("./errors");
|
||||||
var _jsHandle = require("./jsHandle");
|
var import_events = require("./events");
|
||||||
var _consoleMessage = require("./consoleMessage");
|
var import_jsHandle = require("./jsHandle");
|
||||||
var _waiter = require("./waiter");
|
var import_waiter = require("./waiter");
|
||||||
var _errors = require("./errors");
|
var import_timeoutSettings = require("./timeoutSettings");
|
||||||
let _Symbol$asyncDispose;
|
class Electron extends import_channelOwner.ChannelOwner {
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
class Electron extends _channelOwner.ChannelOwner {
|
|
||||||
static from(electron) {
|
static from(electron) {
|
||||||
return electron._object;
|
return electron._object;
|
||||||
}
|
}
|
||||||
@@ -38,8 +40,8 @@ class Electron extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
async launch(options = {}) {
|
async launch(options = {}) {
|
||||||
const params = {
|
const params = {
|
||||||
...(await (0, _browserContext.prepareBrowserContextParams)(options)),
|
...await (0, import_browserContext.prepareBrowserContextParams)(this._platform, options),
|
||||||
env: (0, _clientHelper.envObjectToArray)(options.env ? options.env : process.env),
|
env: (0, import_clientHelper.envObjectToArray)(options.env ? options.env : this._platform.env),
|
||||||
tracesDir: options.tracesDir
|
tracesDir: options.tracesDir
|
||||||
};
|
};
|
||||||
const app = ElectronApplication.from((await this._channel.launch(params)).electronApplication);
|
const app = ElectronApplication.from((await this._channel.launch(params)).electronApplication);
|
||||||
@@ -47,89 +49,85 @@ class Electron extends _channelOwner.ChannelOwner {
|
|||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Electron = Electron;
|
class ElectronApplication extends import_channelOwner.ChannelOwner {
|
||||||
_Symbol$asyncDispose = Symbol.asyncDispose;
|
|
||||||
class ElectronApplication extends _channelOwner.ChannelOwner {
|
|
||||||
static from(electronApplication) {
|
|
||||||
return electronApplication._object;
|
|
||||||
}
|
|
||||||
constructor(parent, type, guid, initializer) {
|
constructor(parent, type, guid, initializer) {
|
||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
this._context = void 0;
|
this._windows = /* @__PURE__ */ new Set();
|
||||||
this._windows = new Set();
|
this._timeoutSettings = new import_timeoutSettings.TimeoutSettings(this._platform);
|
||||||
this._timeoutSettings = new _timeoutSettings.TimeoutSettings();
|
this._context = import_browserContext.BrowserContext.from(initializer.context);
|
||||||
this._context = _browserContext.BrowserContext.from(initializer.context);
|
for (const page of this._context._pages)
|
||||||
for (const page of this._context._pages) this._onPage(page);
|
this._onPage(page);
|
||||||
this._context.on(_events.Events.BrowserContext.Page, page => this._onPage(page));
|
this._context.on(import_events.Events.BrowserContext.Page, (page) => this._onPage(page));
|
||||||
this._channel.on('close', () => {
|
this._channel.on("close", () => {
|
||||||
this.emit(_events.Events.ElectronApplication.Close);
|
this.emit(import_events.Events.ElectronApplication.Close);
|
||||||
});
|
});
|
||||||
this._channel.on('console', event => this.emit(_events.Events.ElectronApplication.Console, new _consoleMessage.ConsoleMessage(event)));
|
this._channel.on("console", (event) => this.emit(import_events.Events.ElectronApplication.Console, new import_consoleMessage.ConsoleMessage(this._platform, event)));
|
||||||
this._setEventToSubscriptionMapping(new Map([[_events.Events.ElectronApplication.Console, 'console']]));
|
this._setEventToSubscriptionMapping(/* @__PURE__ */ new Map([
|
||||||
|
[import_events.Events.ElectronApplication.Console, "console"]
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
static from(electronApplication) {
|
||||||
|
return electronApplication._object;
|
||||||
}
|
}
|
||||||
process() {
|
process() {
|
||||||
return this._toImpl().process();
|
return this._toImpl().process();
|
||||||
}
|
}
|
||||||
_onPage(page) {
|
_onPage(page) {
|
||||||
this._windows.add(page);
|
this._windows.add(page);
|
||||||
this.emit(_events.Events.ElectronApplication.Window, page);
|
this.emit(import_events.Events.ElectronApplication.Window, page);
|
||||||
page.once(_events.Events.Page.Close, () => this._windows.delete(page));
|
page.once(import_events.Events.Page.Close, () => this._windows.delete(page));
|
||||||
}
|
}
|
||||||
windows() {
|
windows() {
|
||||||
// TODO: add ElectronPage class inheriting from Page.
|
|
||||||
return [...this._windows];
|
return [...this._windows];
|
||||||
}
|
}
|
||||||
async firstWindow(options) {
|
async firstWindow(options) {
|
||||||
if (this._windows.size) return this._windows.values().next().value;
|
if (this._windows.size)
|
||||||
return await this.waitForEvent('window', options);
|
return this._windows.values().next().value;
|
||||||
|
return await this.waitForEvent("window", options);
|
||||||
}
|
}
|
||||||
context() {
|
context() {
|
||||||
return this._context;
|
return this._context;
|
||||||
}
|
}
|
||||||
async [_Symbol$asyncDispose]() {
|
async [Symbol.asyncDispose]() {
|
||||||
await this.close();
|
await this.close();
|
||||||
}
|
}
|
||||||
async close() {
|
async close() {
|
||||||
try {
|
try {
|
||||||
await this._context.close();
|
await this._context.close();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if ((0, _errors.isTargetClosedError)(e)) return;
|
if ((0, import_errors.isTargetClosedError)(e))
|
||||||
|
return;
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async waitForEvent(event, optionsOrPredicate = {}) {
|
async waitForEvent(event, optionsOrPredicate = {}) {
|
||||||
return await this._wrapApiCall(async () => {
|
return await this._wrapApiCall(async () => {
|
||||||
const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate);
|
const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === "function" ? {} : optionsOrPredicate);
|
||||||
const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate;
|
const predicate = typeof optionsOrPredicate === "function" ? optionsOrPredicate : optionsOrPredicate.predicate;
|
||||||
const waiter = _waiter.Waiter.createForEvent(this, event);
|
const waiter = import_waiter.Waiter.createForEvent(this, event);
|
||||||
waiter.rejectOnTimeout(timeout, `Timeout ${timeout}ms exceeded while waiting for event "${event}"`);
|
waiter.rejectOnTimeout(timeout, `Timeout ${timeout}ms exceeded while waiting for event "${event}"`);
|
||||||
if (event !== _events.Events.ElectronApplication.Close) waiter.rejectOnEvent(this, _events.Events.ElectronApplication.Close, () => new _errors.TargetClosedError());
|
if (event !== import_events.Events.ElectronApplication.Close)
|
||||||
|
waiter.rejectOnEvent(this, import_events.Events.ElectronApplication.Close, () => new import_errors.TargetClosedError());
|
||||||
const result = await waiter.waitForEvent(this, event, predicate);
|
const result = await waiter.waitForEvent(this, event, predicate);
|
||||||
waiter.dispose();
|
waiter.dispose();
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async browserWindow(page) {
|
async browserWindow(page) {
|
||||||
const result = await this._channel.browserWindow({
|
const result = await this._channel.browserWindow({ page: page._channel });
|
||||||
page: page._channel
|
return import_jsHandle.JSHandle.from(result.handle);
|
||||||
});
|
|
||||||
return _jsHandle.JSHandle.from(result.handle);
|
|
||||||
}
|
}
|
||||||
async evaluate(pageFunction, arg) {
|
async evaluate(pageFunction, arg) {
|
||||||
const result = await this._channel.evaluateExpression({
|
const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
|
||||||
expression: String(pageFunction),
|
return (0, import_jsHandle.parseResult)(result.value);
|
||||||
isFunction: typeof pageFunction === 'function',
|
|
||||||
arg: (0, _jsHandle.serializeArgument)(arg)
|
|
||||||
});
|
|
||||||
return (0, _jsHandle.parseResult)(result.value);
|
|
||||||
}
|
}
|
||||||
async evaluateHandle(pageFunction, arg) {
|
async evaluateHandle(pageFunction, arg) {
|
||||||
const result = await this._channel.evaluateExpressionHandle({
|
const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
|
||||||
expression: String(pageFunction),
|
return import_jsHandle.JSHandle.from(result.handle);
|
||||||
isFunction: typeof pageFunction === 'function',
|
|
||||||
arg: (0, _jsHandle.serializeArgument)(arg)
|
|
||||||
});
|
|
||||||
return _jsHandle.JSHandle.from(result.handle);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.ElectronApplication = ElectronApplication;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
Electron,
|
||||||
|
ElectronApplication
|
||||||
|
});
|
||||||
|
|||||||
287
tvapp2/node_modules/playwright-core/lib/client/elementHandle.js
generated
vendored
@@ -1,41 +1,37 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var elementHandle_exports = {};
|
||||||
|
__export(elementHandle_exports, {
|
||||||
|
ElementHandle: () => ElementHandle,
|
||||||
|
convertInputFiles: () => convertInputFiles,
|
||||||
|
convertSelectOptionValues: () => convertSelectOptionValues,
|
||||||
|
determineScreenshotType: () => determineScreenshotType
|
||||||
});
|
});
|
||||||
exports.ElementHandle = void 0;
|
module.exports = __toCommonJS(elementHandle_exports);
|
||||||
exports.convertInputFiles = convertInputFiles;
|
var import_frame = require("./frame");
|
||||||
exports.convertSelectOptionValues = convertSelectOptionValues;
|
var import_jsHandle = require("./jsHandle");
|
||||||
exports.determineScreenshotType = determineScreenshotType;
|
var import_assert = require("../utils/isomorphic/assert");
|
||||||
var _frame = require("./frame");
|
var import_fileUtils = require("./fileUtils");
|
||||||
var _jsHandle = require("./jsHandle");
|
var import_rtti = require("../utils/isomorphic/rtti");
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
var import_writableStream = require("./writableStream");
|
||||||
var _utilsBundle = require("../utilsBundle");
|
var import_mimeType = require("../utils/isomorphic/mimeType");
|
||||||
var _path = _interopRequireDefault(require("path"));
|
class ElementHandle extends import_jsHandle.JSHandle {
|
||||||
var _utils = require("../utils");
|
|
||||||
var _fileUtils = require("../utils/fileUtils");
|
|
||||||
var _writableStream = require("./writableStream");
|
|
||||||
var _stream = require("stream");
|
|
||||||
var _util = require("util");
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const pipelineAsync = (0, _util.promisify)(_stream.pipeline);
|
|
||||||
class ElementHandle extends _jsHandle.JSHandle {
|
|
||||||
static from(handle) {
|
static from(handle) {
|
||||||
return handle._object;
|
return handle._object;
|
||||||
}
|
}
|
||||||
@@ -44,30 +40,31 @@ class ElementHandle extends _jsHandle.JSHandle {
|
|||||||
}
|
}
|
||||||
constructor(parent, type, guid, initializer) {
|
constructor(parent, type, guid, initializer) {
|
||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
this._elementChannel = void 0;
|
|
||||||
this._elementChannel = this._channel;
|
this._elementChannel = this._channel;
|
||||||
}
|
}
|
||||||
asElement() {
|
asElement() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
async ownerFrame() {
|
async ownerFrame() {
|
||||||
return _frame.Frame.fromNullable((await this._elementChannel.ownerFrame()).frame);
|
return import_frame.Frame.fromNullable((await this._elementChannel.ownerFrame()).frame);
|
||||||
}
|
}
|
||||||
async contentFrame() {
|
async contentFrame() {
|
||||||
return _frame.Frame.fromNullable((await this._elementChannel.contentFrame()).frame);
|
return import_frame.Frame.fromNullable((await this._elementChannel.contentFrame()).frame);
|
||||||
|
}
|
||||||
|
async _generateLocatorString() {
|
||||||
|
const value = (await this._elementChannel.generateLocatorString()).value;
|
||||||
|
return value === void 0 ? null : value;
|
||||||
}
|
}
|
||||||
async getAttribute(name) {
|
async getAttribute(name) {
|
||||||
const value = (await this._elementChannel.getAttribute({
|
const value = (await this._elementChannel.getAttribute({ name })).value;
|
||||||
name
|
return value === void 0 ? null : value;
|
||||||
})).value;
|
|
||||||
return value === undefined ? null : value;
|
|
||||||
}
|
}
|
||||||
async inputValue() {
|
async inputValue() {
|
||||||
return (await this._elementChannel.inputValue()).value;
|
return (await this._elementChannel.inputValue()).value;
|
||||||
}
|
}
|
||||||
async textContent() {
|
async textContent() {
|
||||||
const value = (await this._elementChannel.textContent()).value;
|
const value = (await this._elementChannel.textContent()).value;
|
||||||
return value === undefined ? null : value;
|
return value === void 0 ? null : value;
|
||||||
}
|
}
|
||||||
async innerText() {
|
async innerText() {
|
||||||
return (await this._elementChannel.innerText()).value;
|
return (await this._elementChannel.innerText()).value;
|
||||||
@@ -94,10 +91,7 @@ class ElementHandle extends _jsHandle.JSHandle {
|
|||||||
return (await this._elementChannel.isVisible()).value;
|
return (await this._elementChannel.isVisible()).value;
|
||||||
}
|
}
|
||||||
async dispatchEvent(type, eventInit = {}) {
|
async dispatchEvent(type, eventInit = {}) {
|
||||||
await this._elementChannel.dispatchEvent({
|
await this._elementChannel.dispatchEvent({ type, eventInit: (0, import_jsHandle.serializeArgument)(eventInit) });
|
||||||
type,
|
|
||||||
eventInit: (0, _jsHandle.serializeArgument)(eventInit)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async scrollIntoViewIfNeeded(options = {}) {
|
async scrollIntoViewIfNeeded(options = {}) {
|
||||||
await this._elementChannel.scrollIntoViewIfNeeded(options);
|
await this._elementChannel.scrollIntoViewIfNeeded(options);
|
||||||
@@ -115,44 +109,30 @@ class ElementHandle extends _jsHandle.JSHandle {
|
|||||||
return await this._elementChannel.tap(options);
|
return await this._elementChannel.tap(options);
|
||||||
}
|
}
|
||||||
async selectOption(values, options = {}) {
|
async selectOption(values, options = {}) {
|
||||||
const result = await this._elementChannel.selectOption({
|
const result = await this._elementChannel.selectOption({ ...convertSelectOptionValues(values), ...options });
|
||||||
...convertSelectOptionValues(values),
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
return result.values;
|
return result.values;
|
||||||
}
|
}
|
||||||
async fill(value, options = {}) {
|
async fill(value, options = {}) {
|
||||||
return await this._elementChannel.fill({
|
return await this._elementChannel.fill({ value, ...options });
|
||||||
value,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async selectText(options = {}) {
|
async selectText(options = {}) {
|
||||||
await this._elementChannel.selectText(options);
|
await this._elementChannel.selectText(options);
|
||||||
}
|
}
|
||||||
async setInputFiles(files, options = {}) {
|
async setInputFiles(files, options = {}) {
|
||||||
const frame = await this.ownerFrame();
|
const frame = await this.ownerFrame();
|
||||||
if (!frame) throw new Error('Cannot set input files to detached element');
|
if (!frame)
|
||||||
const converted = await convertInputFiles(files, frame.page().context());
|
throw new Error("Cannot set input files to detached element");
|
||||||
await this._elementChannel.setInputFiles({
|
const converted = await convertInputFiles(this._platform, files, frame.page().context());
|
||||||
...converted,
|
await this._elementChannel.setInputFiles({ ...converted, ...options });
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async focus() {
|
async focus() {
|
||||||
await this._elementChannel.focus();
|
await this._elementChannel.focus();
|
||||||
}
|
}
|
||||||
async type(text, options = {}) {
|
async type(text, options = {}) {
|
||||||
await this._elementChannel.type({
|
await this._elementChannel.type({ text, ...options });
|
||||||
text,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async press(key, options = {}) {
|
async press(key, options = {}) {
|
||||||
await this._elementChannel.press({
|
await this._elementChannel.press({ key, ...options });
|
||||||
key,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async check(options = {}) {
|
async check(options = {}) {
|
||||||
return await this._elementChannel.check(options);
|
return await this._elementChannel.check(options);
|
||||||
@@ -161,143 +141,117 @@ class ElementHandle extends _jsHandle.JSHandle {
|
|||||||
return await this._elementChannel.uncheck(options);
|
return await this._elementChannel.uncheck(options);
|
||||||
}
|
}
|
||||||
async setChecked(checked, options) {
|
async setChecked(checked, options) {
|
||||||
if (checked) await this.check(options);else await this.uncheck(options);
|
if (checked)
|
||||||
|
await this.check(options);
|
||||||
|
else
|
||||||
|
await this.uncheck(options);
|
||||||
}
|
}
|
||||||
async boundingBox() {
|
async boundingBox() {
|
||||||
const value = (await this._elementChannel.boundingBox()).value;
|
const value = (await this._elementChannel.boundingBox()).value;
|
||||||
return value === undefined ? null : value;
|
return value === void 0 ? null : value;
|
||||||
}
|
}
|
||||||
async screenshot(options = {}) {
|
async screenshot(options = {}) {
|
||||||
const copy = {
|
const mask = options.mask;
|
||||||
...options,
|
const copy = { ...options, mask: void 0 };
|
||||||
mask: undefined
|
if (!copy.type)
|
||||||
};
|
copy.type = determineScreenshotType(options);
|
||||||
if (!copy.type) copy.type = determineScreenshotType(options);
|
if (mask) {
|
||||||
if (options.mask) {
|
copy.mask = mask.map((locator) => ({
|
||||||
copy.mask = options.mask.map(locator => ({
|
|
||||||
frame: locator._frame._channel,
|
frame: locator._frame._channel,
|
||||||
selector: locator._selector
|
selector: locator._selector
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
const result = await this._elementChannel.screenshot(copy);
|
const result = await this._elementChannel.screenshot(copy);
|
||||||
if (options.path) {
|
if (options.path) {
|
||||||
await (0, _fileUtils.mkdirIfNeeded)(options.path);
|
await (0, import_fileUtils.mkdirIfNeeded)(this._platform, options.path);
|
||||||
await _fs.default.promises.writeFile(options.path, result.binary);
|
await this._platform.fs().promises.writeFile(options.path, result.binary);
|
||||||
}
|
}
|
||||||
return result.binary;
|
return result.binary;
|
||||||
}
|
}
|
||||||
async $(selector) {
|
async $(selector) {
|
||||||
return ElementHandle.fromNullable((await this._elementChannel.querySelector({
|
return ElementHandle.fromNullable((await this._elementChannel.querySelector({ selector })).element);
|
||||||
selector
|
|
||||||
})).element);
|
|
||||||
}
|
}
|
||||||
async $$(selector) {
|
async $$(selector) {
|
||||||
const result = await this._elementChannel.querySelectorAll({
|
const result = await this._elementChannel.querySelectorAll({ selector });
|
||||||
selector
|
return result.elements.map((h) => ElementHandle.from(h));
|
||||||
});
|
|
||||||
return result.elements.map(h => ElementHandle.from(h));
|
|
||||||
}
|
}
|
||||||
async $eval(selector, pageFunction, arg) {
|
async $eval(selector, pageFunction, arg) {
|
||||||
const result = await this._elementChannel.evalOnSelector({
|
const result = await this._elementChannel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
|
||||||
selector,
|
return (0, import_jsHandle.parseResult)(result.value);
|
||||||
expression: String(pageFunction),
|
|
||||||
isFunction: typeof pageFunction === 'function',
|
|
||||||
arg: (0, _jsHandle.serializeArgument)(arg)
|
|
||||||
});
|
|
||||||
return (0, _jsHandle.parseResult)(result.value);
|
|
||||||
}
|
}
|
||||||
async $$eval(selector, pageFunction, arg) {
|
async $$eval(selector, pageFunction, arg) {
|
||||||
const result = await this._elementChannel.evalOnSelectorAll({
|
const result = await this._elementChannel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
|
||||||
selector,
|
return (0, import_jsHandle.parseResult)(result.value);
|
||||||
expression: String(pageFunction),
|
|
||||||
isFunction: typeof pageFunction === 'function',
|
|
||||||
arg: (0, _jsHandle.serializeArgument)(arg)
|
|
||||||
});
|
|
||||||
return (0, _jsHandle.parseResult)(result.value);
|
|
||||||
}
|
}
|
||||||
async waitForElementState(state, options = {}) {
|
async waitForElementState(state, options = {}) {
|
||||||
return await this._elementChannel.waitForElementState({
|
return await this._elementChannel.waitForElementState({ state, ...options });
|
||||||
state,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async waitForSelector(selector, options = {}) {
|
async waitForSelector(selector, options = {}) {
|
||||||
const result = await this._elementChannel.waitForSelector({
|
const result = await this._elementChannel.waitForSelector({ selector, ...options });
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
return ElementHandle.fromNullable(result.element);
|
return ElementHandle.fromNullable(result.element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.ElementHandle = ElementHandle;
|
|
||||||
function convertSelectOptionValues(values) {
|
function convertSelectOptionValues(values) {
|
||||||
if (values === null) return {};
|
if (values === null)
|
||||||
if (!Array.isArray(values)) values = [values];
|
return {};
|
||||||
if (!values.length) return {};
|
if (!Array.isArray(values))
|
||||||
for (let i = 0; i < values.length; i++) (0, _utils.assert)(values[i] !== null, `options[${i}]: expected object, got null`);
|
values = [values];
|
||||||
if (values[0] instanceof ElementHandle) return {
|
if (!values.length)
|
||||||
elements: values.map(v => v._elementChannel)
|
return {};
|
||||||
};
|
for (let i = 0; i < values.length; i++)
|
||||||
if ((0, _utils.isString)(values[0])) return {
|
(0, import_assert.assert)(values[i] !== null, `options[${i}]: expected object, got null`);
|
||||||
options: values.map(valueOrLabel => ({
|
if (values[0] instanceof ElementHandle)
|
||||||
valueOrLabel
|
return { elements: values.map((v) => v._elementChannel) };
|
||||||
}))
|
if ((0, import_rtti.isString)(values[0]))
|
||||||
};
|
return { options: values.map((valueOrLabel) => ({ valueOrLabel })) };
|
||||||
return {
|
return { options: values };
|
||||||
options: values
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
function filePayloadExceedsSizeLimit(payloads) {
|
function filePayloadExceedsSizeLimit(payloads) {
|
||||||
return payloads.reduce((size, item) => size + (item.buffer ? item.buffer.byteLength : 0), 0) >= _fileUtils.fileUploadSizeLimit;
|
return payloads.reduce((size, item) => size + (item.buffer ? item.buffer.byteLength : 0), 0) >= import_fileUtils.fileUploadSizeLimit;
|
||||||
}
|
}
|
||||||
async function resolvePathsAndDirectoryForInputFiles(items) {
|
async function resolvePathsAndDirectoryForInputFiles(platform, items) {
|
||||||
var _localPaths2;
|
|
||||||
let localPaths;
|
let localPaths;
|
||||||
let localDirectory;
|
let localDirectory;
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const stat = await _fs.default.promises.stat(item);
|
const stat = await platform.fs().promises.stat(item);
|
||||||
if (stat.isDirectory()) {
|
if (stat.isDirectory()) {
|
||||||
if (localDirectory) throw new Error('Multiple directories are not supported');
|
if (localDirectory)
|
||||||
localDirectory = _path.default.resolve(item);
|
throw new Error("Multiple directories are not supported");
|
||||||
|
localDirectory = platform.path().resolve(item);
|
||||||
} else {
|
} else {
|
||||||
var _localPaths;
|
localPaths ??= [];
|
||||||
(_localPaths = localPaths) !== null && _localPaths !== void 0 ? _localPaths : localPaths = [];
|
localPaths.push(platform.path().resolve(item));
|
||||||
localPaths.push(_path.default.resolve(item));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((_localPaths2 = localPaths) !== null && _localPaths2 !== void 0 && _localPaths2.length && localDirectory) throw new Error('File paths must be all files or a single directory');
|
if (localPaths?.length && localDirectory)
|
||||||
|
throw new Error("File paths must be all files or a single directory");
|
||||||
return [localPaths, localDirectory];
|
return [localPaths, localDirectory];
|
||||||
}
|
}
|
||||||
async function convertInputFiles(files, context) {
|
async function convertInputFiles(platform, files, context) {
|
||||||
const items = Array.isArray(files) ? files.slice() : [files];
|
const items = Array.isArray(files) ? files.slice() : [files];
|
||||||
if (items.some(item => typeof item === 'string')) {
|
if (items.some((item) => typeof item === "string")) {
|
||||||
if (!items.every(item => typeof item === 'string')) throw new Error('File paths cannot be mixed with buffers');
|
if (!items.every((item) => typeof item === "string"))
|
||||||
const [localPaths, localDirectory] = await resolvePathsAndDirectoryForInputFiles(items);
|
throw new Error("File paths cannot be mixed with buffers");
|
||||||
|
const [localPaths, localDirectory] = await resolvePathsAndDirectoryForInputFiles(platform, items);
|
||||||
if (context._connection.isRemote()) {
|
if (context._connection.isRemote()) {
|
||||||
const files = localDirectory ? (await _fs.default.promises.readdir(localDirectory, {
|
const files2 = localDirectory ? (await platform.fs().promises.readdir(localDirectory, { withFileTypes: true, recursive: true })).filter((f) => f.isFile()).map((f) => platform.path().join(f.path, f.name)) : localPaths;
|
||||||
withFileTypes: true,
|
const { writableStreams, rootDir } = await context._wrapApiCall(async () => context._channel.createTempFiles({
|
||||||
recursive: true
|
rootDirName: localDirectory ? platform.path().basename(localDirectory) : void 0,
|
||||||
})).filter(f => f.isFile()).map(f => _path.default.join(f.path, f.name)) : localPaths;
|
items: await Promise.all(files2.map(async (file) => {
|
||||||
const {
|
const lastModifiedMs = (await platform.fs().promises.stat(file)).mtimeMs;
|
||||||
writableStreams,
|
|
||||||
rootDir
|
|
||||||
} = await context._wrapApiCall(async () => context._channel.createTempFiles({
|
|
||||||
rootDirName: localDirectory ? _path.default.basename(localDirectory) : undefined,
|
|
||||||
items: await Promise.all(files.map(async file => {
|
|
||||||
const lastModifiedMs = (await _fs.default.promises.stat(file)).mtimeMs;
|
|
||||||
return {
|
return {
|
||||||
name: localDirectory ? _path.default.relative(localDirectory, file) : _path.default.basename(file),
|
name: localDirectory ? platform.path().relative(localDirectory, file) : platform.path().basename(file),
|
||||||
lastModifiedMs
|
lastModifiedMs
|
||||||
};
|
};
|
||||||
}))
|
}))
|
||||||
}), true);
|
}), true);
|
||||||
for (let i = 0; i < files.length; i++) {
|
for (let i = 0; i < files2.length; i++) {
|
||||||
const writable = _writableStream.WritableStream.from(writableStreams[i]);
|
const writable = import_writableStream.WritableStream.from(writableStreams[i]);
|
||||||
await pipelineAsync(_fs.default.createReadStream(files[i]), writable.stream());
|
await platform.streamFile(files2[i], writable.stream());
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
directoryStream: rootDir,
|
directoryStream: rootDir,
|
||||||
streams: localDirectory ? undefined : writableStreams
|
streams: localDirectory ? void 0 : writableStreams
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -306,16 +260,25 @@ async function convertInputFiles(files, context) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
const payloads = items;
|
const payloads = items;
|
||||||
if (filePayloadExceedsSizeLimit(payloads)) throw new Error('Cannot set buffer larger than 50Mb, please write it to a file and pass its path instead.');
|
if (filePayloadExceedsSizeLimit(payloads))
|
||||||
return {
|
throw new Error("Cannot set buffer larger than 50Mb, please write it to a file and pass its path instead.");
|
||||||
payloads
|
return { payloads };
|
||||||
};
|
|
||||||
}
|
}
|
||||||
function determineScreenshotType(options) {
|
function determineScreenshotType(options) {
|
||||||
if (options.path) {
|
if (options.path) {
|
||||||
const mimeType = _utilsBundle.mime.getType(options.path);
|
const mimeType = (0, import_mimeType.getMimeTypeForPath)(options.path);
|
||||||
if (mimeType === 'image/png') return 'png';else if (mimeType === 'image/jpeg') return 'jpeg';
|
if (mimeType === "image/png")
|
||||||
|
return "png";
|
||||||
|
else if (mimeType === "image/jpeg")
|
||||||
|
return "jpeg";
|
||||||
throw new Error(`path: unsupported mime type "${mimeType}"`);
|
throw new Error(`path: unsupported mime type "${mimeType}"`);
|
||||||
}
|
}
|
||||||
return options.type;
|
return options.type;
|
||||||
}
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
ElementHandle,
|
||||||
|
convertInputFiles,
|
||||||
|
convertSelectOptionValues,
|
||||||
|
determineScreenshotType
|
||||||
|
});
|
||||||
|
|||||||
104
tvapp2/node_modules/playwright-core/lib/client/errors.js
generated
vendored
@@ -1,77 +1,77 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var errors_exports = {};
|
||||||
|
__export(errors_exports, {
|
||||||
|
TargetClosedError: () => TargetClosedError,
|
||||||
|
TimeoutError: () => TimeoutError,
|
||||||
|
isTargetClosedError: () => isTargetClosedError,
|
||||||
|
parseError: () => parseError,
|
||||||
|
serializeError: () => serializeError
|
||||||
});
|
});
|
||||||
exports.TimeoutError = exports.TargetClosedError = void 0;
|
module.exports = __toCommonJS(errors_exports);
|
||||||
exports.isTargetClosedError = isTargetClosedError;
|
var import_serializers = require("../protocol/serializers");
|
||||||
exports.parseError = parseError;
|
var import_rtti = require("../utils/isomorphic/rtti");
|
||||||
exports.serializeError = serializeError;
|
|
||||||
var _utils = require("../utils");
|
|
||||||
var _serializers = require("../protocol/serializers");
|
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class TimeoutError extends Error {
|
class TimeoutError extends Error {
|
||||||
constructor(message) {
|
constructor(message) {
|
||||||
super(message);
|
super(message);
|
||||||
this.name = 'TimeoutError';
|
this.name = "TimeoutError";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.TimeoutError = TimeoutError;
|
|
||||||
class TargetClosedError extends Error {
|
class TargetClosedError extends Error {
|
||||||
constructor(cause) {
|
constructor(cause) {
|
||||||
super(cause || 'Target page, context or browser has been closed');
|
super(cause || "Target page, context or browser has been closed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.TargetClosedError = TargetClosedError;
|
|
||||||
function isTargetClosedError(error) {
|
function isTargetClosedError(error) {
|
||||||
return error instanceof TargetClosedError;
|
return error instanceof TargetClosedError;
|
||||||
}
|
}
|
||||||
function serializeError(e) {
|
function serializeError(e) {
|
||||||
if ((0, _utils.isError)(e)) return {
|
if ((0, import_rtti.isError)(e))
|
||||||
error: {
|
return { error: { message: e.message, stack: e.stack, name: e.name } };
|
||||||
message: e.message,
|
return { value: (0, import_serializers.serializeValue)(e, (value) => ({ fallThrough: value })) };
|
||||||
stack: e.stack,
|
|
||||||
name: e.name
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
value: (0, _serializers.serializeValue)(e, value => ({
|
|
||||||
fallThrough: value
|
|
||||||
}))
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
function parseError(error) {
|
function parseError(error) {
|
||||||
if (!error.error) {
|
if (!error.error) {
|
||||||
if (error.value === undefined) throw new Error('Serialized error must have either an error or a value');
|
if (error.value === void 0)
|
||||||
return (0, _serializers.parseSerializedValue)(error.value, undefined);
|
throw new Error("Serialized error must have either an error or a value");
|
||||||
|
return (0, import_serializers.parseSerializedValue)(error.value, void 0);
|
||||||
}
|
}
|
||||||
if (error.error.name === 'TimeoutError') {
|
if (error.error.name === "TimeoutError") {
|
||||||
const e = new TimeoutError(error.error.message);
|
const e2 = new TimeoutError(error.error.message);
|
||||||
e.stack = error.error.stack || '';
|
e2.stack = error.error.stack || "";
|
||||||
return e;
|
return e2;
|
||||||
}
|
}
|
||||||
if (error.error.name === 'TargetClosedError') {
|
if (error.error.name === "TargetClosedError") {
|
||||||
const e = new TargetClosedError(error.error.message);
|
const e2 = new TargetClosedError(error.error.message);
|
||||||
e.stack = error.error.stack || '';
|
e2.stack = error.error.stack || "";
|
||||||
return e;
|
return e2;
|
||||||
}
|
}
|
||||||
const e = new Error(error.error.message);
|
const e = new Error(error.error.message);
|
||||||
e.stack = error.error.stack || '';
|
e.stack = error.error.stack || "";
|
||||||
e.name = error.error.name;
|
e.name = error.error.name;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
TargetClosedError,
|
||||||
|
TimeoutError,
|
||||||
|
isTargetClosedError,
|
||||||
|
parseError,
|
||||||
|
serializeError
|
||||||
|
});
|
||||||
|
|||||||
252
tvapp2/node_modules/playwright-core/lib/client/eventEmitter.js
generated
vendored
@@ -1,83 +1,82 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var eventEmitter_exports = {};
|
||||||
|
__export(eventEmitter_exports, {
|
||||||
|
EventEmitter: () => EventEmitter
|
||||||
});
|
});
|
||||||
exports.EventEmitter = void 0;
|
module.exports = __toCommonJS(eventEmitter_exports);
|
||||||
var _events = require("events");
|
|
||||||
var _utils = require("../utils");
|
|
||||||
/**
|
|
||||||
* Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
* Modifications copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the
|
|
||||||
* "Software"), to deal in the Software without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
* persons to whom the Software is furnished to do so, subject to the
|
|
||||||
* following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class EventEmitter {
|
class EventEmitter {
|
||||||
constructor() {
|
constructor(platform) {
|
||||||
this._events = undefined;
|
this._events = void 0;
|
||||||
this._eventsCount = 0;
|
this._eventsCount = 0;
|
||||||
this._maxListeners = undefined;
|
this._maxListeners = void 0;
|
||||||
this._pendingHandlers = new Map();
|
this._pendingHandlers = /* @__PURE__ */ new Map();
|
||||||
this._rejectionHandler = void 0;
|
this._platform = platform;
|
||||||
if (this._events === undefined || this._events === Object.getPrototypeOf(this)._events) {
|
if (this._events === void 0 || this._events === Object.getPrototypeOf(this)._events) {
|
||||||
this._events = Object.create(null);
|
this._events = /* @__PURE__ */ Object.create(null);
|
||||||
this._eventsCount = 0;
|
this._eventsCount = 0;
|
||||||
}
|
}
|
||||||
this._maxListeners = this._maxListeners || undefined;
|
this._maxListeners = this._maxListeners || void 0;
|
||||||
this.on = this.addListener;
|
this.on = this.addListener;
|
||||||
this.off = this.removeListener;
|
this.off = this.removeListener;
|
||||||
}
|
}
|
||||||
setMaxListeners(n) {
|
setMaxListeners(n) {
|
||||||
if (typeof n !== 'number' || n < 0 || Number.isNaN(n)) throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.');
|
if (typeof n !== "number" || n < 0 || Number.isNaN(n))
|
||||||
|
throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + ".");
|
||||||
this._maxListeners = n;
|
this._maxListeners = n;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
getMaxListeners() {
|
getMaxListeners() {
|
||||||
return this._maxListeners === undefined ? _events.EventEmitter.defaultMaxListeners : this._maxListeners;
|
return this._maxListeners === void 0 ? this._platform.defaultMaxListeners() : this._maxListeners;
|
||||||
}
|
}
|
||||||
emit(type, ...args) {
|
emit(type, ...args) {
|
||||||
const events = this._events;
|
const events = this._events;
|
||||||
if (events === undefined) return false;
|
if (events === void 0)
|
||||||
const handler = events === null || events === void 0 ? void 0 : events[type];
|
return false;
|
||||||
if (handler === undefined) return false;
|
const handler = events?.[type];
|
||||||
if (typeof handler === 'function') {
|
if (handler === void 0)
|
||||||
|
return false;
|
||||||
|
if (typeof handler === "function") {
|
||||||
this._callHandler(type, handler, args);
|
this._callHandler(type, handler, args);
|
||||||
} else {
|
} else {
|
||||||
const len = handler.length;
|
const len = handler.length;
|
||||||
const listeners = handler.slice();
|
const listeners = handler.slice();
|
||||||
for (let i = 0; i < len; ++i) this._callHandler(type, listeners[i], args);
|
for (let i = 0; i < len; ++i)
|
||||||
|
this._callHandler(type, listeners[i], args);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
_callHandler(type, handler, args) {
|
_callHandler(type, handler, args) {
|
||||||
const promise = Reflect.apply(handler, this, args);
|
const promise = Reflect.apply(handler, this, args);
|
||||||
if (!(promise instanceof Promise)) return;
|
if (!(promise instanceof Promise))
|
||||||
|
return;
|
||||||
let set = this._pendingHandlers.get(type);
|
let set = this._pendingHandlers.get(type);
|
||||||
if (!set) {
|
if (!set) {
|
||||||
set = new Set();
|
set = /* @__PURE__ */ new Set();
|
||||||
this._pendingHandlers.set(type, set);
|
this._pendingHandlers.set(type, set);
|
||||||
}
|
}
|
||||||
set.add(promise);
|
set.add(promise);
|
||||||
promise.catch(e => {
|
promise.catch((e) => {
|
||||||
if (this._rejectionHandler) this._rejectionHandler(e);else throw e;
|
if (this._rejectionHandler)
|
||||||
|
this._rejectionHandler(e);
|
||||||
|
else
|
||||||
|
throw e;
|
||||||
}).finally(() => set.delete(promise));
|
}).finally(() => set.delete(promise));
|
||||||
}
|
}
|
||||||
addListener(type, listener) {
|
addListener(type, listener) {
|
||||||
@@ -90,48 +89,36 @@ class EventEmitter {
|
|||||||
checkListener(listener);
|
checkListener(listener);
|
||||||
let events = this._events;
|
let events = this._events;
|
||||||
let existing;
|
let existing;
|
||||||
if (events === undefined) {
|
if (events === void 0) {
|
||||||
events = this._events = Object.create(null);
|
events = this._events = /* @__PURE__ */ Object.create(null);
|
||||||
this._eventsCount = 0;
|
this._eventsCount = 0;
|
||||||
} else {
|
} else {
|
||||||
// To avoid recursion in the case that type === "newListener"! Before
|
if (events.newListener !== void 0) {
|
||||||
// adding it to the listeners, first emit "newListener".
|
this.emit("newListener", type, unwrapListener(listener));
|
||||||
if (events.newListener !== undefined) {
|
|
||||||
this.emit('newListener', type, unwrapListener(listener));
|
|
||||||
|
|
||||||
// Re-assign `events` because a newListener handler could have caused the
|
|
||||||
// this._events to be assigned to a new object
|
|
||||||
events = this._events;
|
events = this._events;
|
||||||
}
|
}
|
||||||
existing = events[type];
|
existing = events[type];
|
||||||
}
|
}
|
||||||
if (existing === undefined) {
|
if (existing === void 0) {
|
||||||
// Optimize the case of one listener. Don't need the extra array object.
|
|
||||||
existing = events[type] = listener;
|
existing = events[type] = listener;
|
||||||
++this._eventsCount;
|
++this._eventsCount;
|
||||||
} else {
|
} else {
|
||||||
if (typeof existing === 'function') {
|
if (typeof existing === "function") {
|
||||||
// Adding the second element, need to change to array.
|
|
||||||
existing = events[type] = prepend ? [listener, existing] : [existing, listener];
|
existing = events[type] = prepend ? [listener, existing] : [existing, listener];
|
||||||
// If we've already got an array, just append.
|
|
||||||
} else if (prepend) {
|
} else if (prepend) {
|
||||||
existing.unshift(listener);
|
existing.unshift(listener);
|
||||||
} else {
|
} else {
|
||||||
existing.push(listener);
|
existing.push(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for listener leak
|
|
||||||
const m = this.getMaxListeners();
|
const m = this.getMaxListeners();
|
||||||
if (m > 0 && existing.length > m && !existing.warned) {
|
if (m > 0 && existing.length > m && !existing.warned) {
|
||||||
existing.warned = true;
|
existing.warned = true;
|
||||||
// No error code for this since it is a Warning
|
const w = new Error("Possible EventEmitter memory leak detected. " + existing.length + " " + String(type) + " listeners added. Use emitter.setMaxListeners() to increase limit");
|
||||||
const w = new Error('Possible EventEmitter memory leak detected. ' + existing.length + ' ' + String(type) + ' listeners ' + 'added. Use emitter.setMaxListeners() to ' + 'increase limit');
|
w.name = "MaxListenersExceededWarning";
|
||||||
w.name = 'MaxListenersExceededWarning';
|
|
||||||
w.emitter = this;
|
w.emitter = this;
|
||||||
w.type = type;
|
w.type = type;
|
||||||
w.count = existing.length;
|
w.count = existing.length;
|
||||||
if (!(0, _utils.isUnderTest)()) {
|
if (!this._platform.isUnderTest()) {
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.warn(w);
|
console.warn(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,18 +141,20 @@ class EventEmitter {
|
|||||||
removeListener(type, listener) {
|
removeListener(type, listener) {
|
||||||
checkListener(listener);
|
checkListener(listener);
|
||||||
const events = this._events;
|
const events = this._events;
|
||||||
if (events === undefined) return this;
|
if (events === void 0)
|
||||||
|
return this;
|
||||||
const list = events[type];
|
const list = events[type];
|
||||||
if (list === undefined) return this;
|
if (list === void 0)
|
||||||
|
return this;
|
||||||
if (list === listener || list.listener === listener) {
|
if (list === listener || list.listener === listener) {
|
||||||
if (--this._eventsCount === 0) {
|
if (--this._eventsCount === 0) {
|
||||||
this._events = Object.create(null);
|
this._events = /* @__PURE__ */ Object.create(null);
|
||||||
} else {
|
} else {
|
||||||
var _listener;
|
|
||||||
delete events[type];
|
delete events[type];
|
||||||
if (events.removeListener) this.emit('removeListener', type, (_listener = list.listener) !== null && _listener !== void 0 ? _listener : listener);
|
if (events.removeListener)
|
||||||
|
this.emit("removeListener", type, list.listener ?? listener);
|
||||||
}
|
}
|
||||||
} else if (typeof list !== 'function') {
|
} else if (typeof list !== "function") {
|
||||||
let position = -1;
|
let position = -1;
|
||||||
let originalListener;
|
let originalListener;
|
||||||
for (let i = list.length - 1; i >= 0; i--) {
|
for (let i = list.length - 1; i >= 0; i--) {
|
||||||
@@ -175,10 +164,16 @@ class EventEmitter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (position < 0) return this;
|
if (position < 0)
|
||||||
if (position === 0) list.shift();else list.splice(position, 1);
|
return this;
|
||||||
if (list.length === 1) events[type] = list[0];
|
if (position === 0)
|
||||||
if (events.removeListener !== undefined) this.emit('removeListener', type, originalListener || listener);
|
list.shift();
|
||||||
|
else
|
||||||
|
list.splice(position, 1);
|
||||||
|
if (list.length === 1)
|
||||||
|
events[type] = list[0];
|
||||||
|
if (events.removeListener !== void 0)
|
||||||
|
this.emit("removeListener", type, originalListener || listener);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -187,55 +182,57 @@ class EventEmitter {
|
|||||||
}
|
}
|
||||||
removeAllListeners(type, options) {
|
removeAllListeners(type, options) {
|
||||||
this._removeAllListeners(type);
|
this._removeAllListeners(type);
|
||||||
if (!options) return this;
|
if (!options)
|
||||||
if (options.behavior === 'wait') {
|
return this;
|
||||||
|
if (options.behavior === "wait") {
|
||||||
const errors = [];
|
const errors = [];
|
||||||
this._rejectionHandler = error => errors.push(error);
|
this._rejectionHandler = (error) => errors.push(error);
|
||||||
// eslint-disable-next-line internal-playwright/await-promise-in-class-returns
|
|
||||||
return this._waitFor(type).then(() => {
|
return this._waitFor(type).then(() => {
|
||||||
if (errors.length) throw errors[0];
|
if (errors.length)
|
||||||
|
throw errors[0];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (options.behavior === 'ignoreErrors') this._rejectionHandler = () => {};
|
if (options.behavior === "ignoreErrors")
|
||||||
|
this._rejectionHandler = () => {
|
||||||
// eslint-disable-next-line internal-playwright/await-promise-in-class-returns
|
};
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
_removeAllListeners(type) {
|
_removeAllListeners(type) {
|
||||||
const events = this._events;
|
const events = this._events;
|
||||||
if (!events) return;
|
if (!events)
|
||||||
|
return;
|
||||||
// not listening for removeListener, no need to emit
|
|
||||||
if (!events.removeListener) {
|
if (!events.removeListener) {
|
||||||
if (type === undefined) {
|
if (type === void 0) {
|
||||||
this._events = Object.create(null);
|
this._events = /* @__PURE__ */ Object.create(null);
|
||||||
this._eventsCount = 0;
|
this._eventsCount = 0;
|
||||||
} else if (events[type] !== undefined) {
|
} else if (events[type] !== void 0) {
|
||||||
if (--this._eventsCount === 0) this._events = Object.create(null);else delete events[type];
|
if (--this._eventsCount === 0)
|
||||||
|
this._events = /* @__PURE__ */ Object.create(null);
|
||||||
|
else
|
||||||
|
delete events[type];
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (type === void 0) {
|
||||||
// emit removeListener for all listeners on all events
|
|
||||||
if (type === undefined) {
|
|
||||||
const keys = Object.keys(events);
|
const keys = Object.keys(events);
|
||||||
let key;
|
let key;
|
||||||
for (let i = 0; i < keys.length; ++i) {
|
for (let i = 0; i < keys.length; ++i) {
|
||||||
key = keys[i];
|
key = keys[i];
|
||||||
if (key === 'removeListener') continue;
|
if (key === "removeListener")
|
||||||
|
continue;
|
||||||
this._removeAllListeners(key);
|
this._removeAllListeners(key);
|
||||||
}
|
}
|
||||||
this._removeAllListeners('removeListener');
|
this._removeAllListeners("removeListener");
|
||||||
this._events = Object.create(null);
|
this._events = /* @__PURE__ */ Object.create(null);
|
||||||
this._eventsCount = 0;
|
this._eventsCount = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const listeners = events[type];
|
const listeners = events[type];
|
||||||
if (typeof listeners === 'function') {
|
if (typeof listeners === "function") {
|
||||||
this.removeListener(type, listeners);
|
this.removeListener(type, listeners);
|
||||||
} else if (listeners !== undefined) {
|
} else if (listeners !== void 0) {
|
||||||
// LIFO order
|
for (let i = listeners.length - 1; i >= 0; i--)
|
||||||
for (let i = listeners.length - 1; i >= 0; i--) this.removeListener(type, listeners[i]);
|
this.removeListener(type, listeners[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
listeners(type) {
|
listeners(type) {
|
||||||
@@ -246,10 +243,12 @@ class EventEmitter {
|
|||||||
}
|
}
|
||||||
listenerCount(type) {
|
listenerCount(type) {
|
||||||
const events = this._events;
|
const events = this._events;
|
||||||
if (events !== undefined) {
|
if (events !== void 0) {
|
||||||
const listener = events[type];
|
const listener = events[type];
|
||||||
if (typeof listener === 'function') return 1;
|
if (typeof listener === "function")
|
||||||
if (listener !== undefined) return listener.length;
|
return 1;
|
||||||
|
if (listener !== void 0)
|
||||||
|
return listener.length;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -259,33 +258,33 @@ class EventEmitter {
|
|||||||
async _waitFor(type) {
|
async _waitFor(type) {
|
||||||
let promises = [];
|
let promises = [];
|
||||||
if (type) {
|
if (type) {
|
||||||
promises = [...(this._pendingHandlers.get(type) || [])];
|
promises = [...this._pendingHandlers.get(type) || []];
|
||||||
} else {
|
} else {
|
||||||
promises = [];
|
promises = [];
|
||||||
for (const [, pending] of this._pendingHandlers) promises.push(...pending);
|
for (const [, pending] of this._pendingHandlers)
|
||||||
|
promises.push(...pending);
|
||||||
}
|
}
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
}
|
}
|
||||||
_listeners(target, type, unwrap) {
|
_listeners(target, type, unwrap) {
|
||||||
const events = target._events;
|
const events = target._events;
|
||||||
if (events === undefined) return [];
|
if (events === void 0)
|
||||||
|
return [];
|
||||||
const listener = events[type];
|
const listener = events[type];
|
||||||
if (listener === undefined) return [];
|
if (listener === void 0)
|
||||||
if (typeof listener === 'function') return unwrap ? [unwrapListener(listener)] : [listener];
|
return [];
|
||||||
|
if (typeof listener === "function")
|
||||||
|
return unwrap ? [unwrapListener(listener)] : [listener];
|
||||||
return unwrap ? unwrapListeners(listener) : listener.slice();
|
return unwrap ? unwrapListeners(listener) : listener.slice();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.EventEmitter = EventEmitter;
|
|
||||||
function checkListener(listener) {
|
function checkListener(listener) {
|
||||||
if (typeof listener !== 'function') throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
|
if (typeof listener !== "function")
|
||||||
|
throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
|
||||||
}
|
}
|
||||||
class OnceWrapper {
|
class OnceWrapper {
|
||||||
constructor(eventEmitter, eventType, listener) {
|
constructor(eventEmitter, eventType, listener) {
|
||||||
this._fired = false;
|
this._fired = false;
|
||||||
this.wrapperFunction = void 0;
|
|
||||||
this._listener = void 0;
|
|
||||||
this._eventEmitter = void 0;
|
|
||||||
this._eventType = void 0;
|
|
||||||
this._eventEmitter = eventEmitter;
|
this._eventEmitter = eventEmitter;
|
||||||
this._eventType = eventType;
|
this._eventType = eventType;
|
||||||
this._listener = listener;
|
this._listener = listener;
|
||||||
@@ -293,22 +292,23 @@ class OnceWrapper {
|
|||||||
this.wrapperFunction.listener = listener;
|
this.wrapperFunction.listener = listener;
|
||||||
}
|
}
|
||||||
_handle(...args) {
|
_handle(...args) {
|
||||||
if (this._fired) return;
|
if (this._fired)
|
||||||
|
return;
|
||||||
this._fired = true;
|
this._fired = true;
|
||||||
this._eventEmitter.removeListener(this._eventType, this.wrapperFunction);
|
this._eventEmitter.removeListener(this._eventType, this.wrapperFunction);
|
||||||
return this._listener.apply(this._eventEmitter, args);
|
return this._listener.apply(this._eventEmitter, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function unwrapListener(l) {
|
function unwrapListener(l) {
|
||||||
var _wrappedListener;
|
return wrappedListener(l) ?? l;
|
||||||
return (_wrappedListener = wrappedListener(l)) !== null && _wrappedListener !== void 0 ? _wrappedListener : l;
|
|
||||||
}
|
}
|
||||||
function unwrapListeners(arr) {
|
function unwrapListeners(arr) {
|
||||||
return arr.map(l => {
|
return arr.map((l) => wrappedListener(l) ?? l);
|
||||||
var _wrappedListener2;
|
|
||||||
return (_wrappedListener2 = wrappedListener(l)) !== null && _wrappedListener2 !== void 0 ? _wrappedListener2 : l;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
function wrappedListener(l) {
|
function wrappedListener(l) {
|
||||||
return l.listener;
|
return l.listener;
|
||||||
}
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
EventEmitter
|
||||||
|
});
|
||||||
|
|||||||
138
tvapp2/node_modules/playwright-core/lib/client/events.js
generated
vendored
@@ -1,94 +1,98 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var events_exports = {};
|
||||||
|
__export(events_exports, {
|
||||||
|
Events: () => Events
|
||||||
});
|
});
|
||||||
exports.Events = void 0;
|
module.exports = __toCommonJS(events_exports);
|
||||||
/**
|
const Events = {
|
||||||
* Copyright 2019 Google Inc. All rights reserved.
|
|
||||||
* Modifications copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const Events = exports.Events = {
|
|
||||||
AndroidDevice: {
|
AndroidDevice: {
|
||||||
WebView: 'webview',
|
WebView: "webview",
|
||||||
Close: 'close'
|
Close: "close"
|
||||||
},
|
},
|
||||||
AndroidSocket: {
|
AndroidSocket: {
|
||||||
Data: 'data',
|
Data: "data",
|
||||||
Close: 'close'
|
Close: "close"
|
||||||
},
|
},
|
||||||
AndroidWebView: {
|
AndroidWebView: {
|
||||||
Close: 'close'
|
Close: "close"
|
||||||
},
|
},
|
||||||
Browser: {
|
Browser: {
|
||||||
Disconnected: 'disconnected'
|
Disconnected: "disconnected"
|
||||||
},
|
},
|
||||||
BrowserContext: {
|
BrowserContext: {
|
||||||
Console: 'console',
|
Console: "console",
|
||||||
Close: 'close',
|
Close: "close",
|
||||||
Dialog: 'dialog',
|
Dialog: "dialog",
|
||||||
Page: 'page',
|
Page: "page",
|
||||||
// Can't use just 'error' due to node.js special treatment of error events.
|
// Can't use just 'error' due to node.js special treatment of error events.
|
||||||
// @see https://nodejs.org/api/events.html#events_error_events
|
// @see https://nodejs.org/api/events.html#events_error_events
|
||||||
WebError: 'weberror',
|
WebError: "weberror",
|
||||||
BackgroundPage: 'backgroundpage',
|
BackgroundPage: "backgroundpage",
|
||||||
ServiceWorker: 'serviceworker',
|
ServiceWorker: "serviceworker",
|
||||||
Request: 'request',
|
Request: "request",
|
||||||
Response: 'response',
|
Response: "response",
|
||||||
RequestFailed: 'requestfailed',
|
RequestFailed: "requestfailed",
|
||||||
RequestFinished: 'requestfinished'
|
RequestFinished: "requestfinished"
|
||||||
},
|
},
|
||||||
BrowserServer: {
|
BrowserServer: {
|
||||||
Close: 'close'
|
Close: "close"
|
||||||
},
|
},
|
||||||
Page: {
|
Page: {
|
||||||
Close: 'close',
|
Close: "close",
|
||||||
Crash: 'crash',
|
Crash: "crash",
|
||||||
Console: 'console',
|
Console: "console",
|
||||||
Dialog: 'dialog',
|
Dialog: "dialog",
|
||||||
Download: 'download',
|
Download: "download",
|
||||||
FileChooser: 'filechooser',
|
FileChooser: "filechooser",
|
||||||
DOMContentLoaded: 'domcontentloaded',
|
DOMContentLoaded: "domcontentloaded",
|
||||||
// Can't use just 'error' due to node.js special treatment of error events.
|
// Can't use just 'error' due to node.js special treatment of error events.
|
||||||
// @see https://nodejs.org/api/events.html#events_error_events
|
// @see https://nodejs.org/api/events.html#events_error_events
|
||||||
PageError: 'pageerror',
|
PageError: "pageerror",
|
||||||
Request: 'request',
|
Request: "request",
|
||||||
Response: 'response',
|
Response: "response",
|
||||||
RequestFailed: 'requestfailed',
|
RequestFailed: "requestfailed",
|
||||||
RequestFinished: 'requestfinished',
|
RequestFinished: "requestfinished",
|
||||||
FrameAttached: 'frameattached',
|
FrameAttached: "frameattached",
|
||||||
FrameDetached: 'framedetached',
|
FrameDetached: "framedetached",
|
||||||
FrameNavigated: 'framenavigated',
|
FrameNavigated: "framenavigated",
|
||||||
Load: 'load',
|
Load: "load",
|
||||||
Popup: 'popup',
|
Popup: "popup",
|
||||||
WebSocket: 'websocket',
|
WebSocket: "websocket",
|
||||||
Worker: 'worker'
|
Worker: "worker"
|
||||||
},
|
},
|
||||||
WebSocket: {
|
WebSocket: {
|
||||||
Close: 'close',
|
Close: "close",
|
||||||
Error: 'socketerror',
|
Error: "socketerror",
|
||||||
FrameReceived: 'framereceived',
|
FrameReceived: "framereceived",
|
||||||
FrameSent: 'framesent'
|
FrameSent: "framesent"
|
||||||
},
|
},
|
||||||
Worker: {
|
Worker: {
|
||||||
Close: 'close'
|
Close: "close"
|
||||||
},
|
},
|
||||||
ElectronApplication: {
|
ElectronApplication: {
|
||||||
Close: 'close',
|
Close: "close",
|
||||||
Console: 'console',
|
Console: "console",
|
||||||
Window: 'window'
|
Window: "window"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
Events
|
||||||
|
});
|
||||||
|
|||||||
330
tvapp2/node_modules/playwright-core/lib/client/fetch.js
generated
vendored
@@ -1,168 +1,159 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var fetch_exports = {};
|
||||||
|
__export(fetch_exports, {
|
||||||
|
APIRequest: () => APIRequest,
|
||||||
|
APIRequestContext: () => APIRequestContext,
|
||||||
|
APIResponse: () => APIResponse
|
||||||
});
|
});
|
||||||
exports.APIResponse = exports.APIRequestContext = exports.APIRequest = void 0;
|
module.exports = __toCommonJS(fetch_exports);
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
var import_browserContext = require("./browserContext");
|
||||||
var _path = _interopRequireDefault(require("path"));
|
var import_channelOwner = require("./channelOwner");
|
||||||
var util = _interopRequireWildcard(require("util"));
|
var import_errors = require("./errors");
|
||||||
var _utils = require("../utils");
|
var import_network = require("./network");
|
||||||
var _fileUtils = require("../utils/fileUtils");
|
var import_tracing = require("./tracing");
|
||||||
var _channelOwner = require("./channelOwner");
|
var import_assert = require("../utils/isomorphic/assert");
|
||||||
var _network = require("./network");
|
var import_fileUtils = require("./fileUtils");
|
||||||
var _tracing = require("./tracing");
|
var import_headers = require("../utils/isomorphic/headers");
|
||||||
var _errors = require("./errors");
|
var import_rtti = require("../utils/isomorphic/rtti");
|
||||||
var _browserContext = require("./browserContext");
|
|
||||||
let _Symbol$asyncDispose, _Symbol$asyncDispose2, _util$inspect$custom;
|
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
||||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
class APIRequest {
|
class APIRequest {
|
||||||
constructor(playwright) {
|
constructor(playwright) {
|
||||||
this._playwright = void 0;
|
this._contexts = /* @__PURE__ */ new Set();
|
||||||
this._contexts = new Set();
|
|
||||||
// Instrumentation.
|
|
||||||
this._defaultContextOptions = void 0;
|
|
||||||
this._playwright = playwright;
|
this._playwright = playwright;
|
||||||
}
|
}
|
||||||
async newContext(options = {}) {
|
async newContext(options = {}) {
|
||||||
var _this$_defaultContext;
|
|
||||||
options = {
|
options = {
|
||||||
...this._defaultContextOptions,
|
...this._playwright._defaultContextOptions,
|
||||||
|
timeout: this._playwright._defaultContextTimeout,
|
||||||
...options
|
...options
|
||||||
};
|
};
|
||||||
const storageState = typeof options.storageState === 'string' ? JSON.parse(await _fs.default.promises.readFile(options.storageState, 'utf8')) : options.storageState;
|
const storageState = typeof options.storageState === "string" ? JSON.parse(await this._playwright._platform.fs().promises.readFile(options.storageState, "utf8")) : options.storageState;
|
||||||
// We do not expose tracesDir in the API, so do not allow options to accidentally override it.
|
|
||||||
const tracesDir = (_this$_defaultContext = this._defaultContextOptions) === null || _this$_defaultContext === void 0 ? void 0 : _this$_defaultContext.tracesDir;
|
|
||||||
const context = APIRequestContext.from((await this._playwright._channel.newRequest({
|
const context = APIRequestContext.from((await this._playwright._channel.newRequest({
|
||||||
...options,
|
...options,
|
||||||
extraHTTPHeaders: options.extraHTTPHeaders ? (0, _utils.headersObjectToArray)(options.extraHTTPHeaders) : undefined,
|
extraHTTPHeaders: options.extraHTTPHeaders ? (0, import_headers.headersObjectToArray)(options.extraHTTPHeaders) : void 0,
|
||||||
storageState,
|
storageState,
|
||||||
tracesDir,
|
tracesDir: this._playwright._defaultLaunchOptions?.tracesDir,
|
||||||
clientCertificates: await (0, _browserContext.toClientCertificatesProtocol)(options.clientCertificates)
|
// We do not expose tracesDir in the API, so do not allow options to accidentally override it.
|
||||||
|
clientCertificates: await (0, import_browserContext.toClientCertificatesProtocol)(this._playwright._platform, options.clientCertificates)
|
||||||
})).request);
|
})).request);
|
||||||
this._contexts.add(context);
|
this._contexts.add(context);
|
||||||
context._request = this;
|
context._request = this;
|
||||||
context._tracing._tracesDir = tracesDir;
|
context._tracing._tracesDir = this._playwright._defaultLaunchOptions?.tracesDir;
|
||||||
await context._instrumentation.runAfterCreateRequestContext(context);
|
await context._instrumentation.runAfterCreateRequestContext(context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.APIRequest = APIRequest;
|
class APIRequestContext extends import_channelOwner.ChannelOwner {
|
||||||
_Symbol$asyncDispose = Symbol.asyncDispose;
|
|
||||||
class APIRequestContext extends _channelOwner.ChannelOwner {
|
|
||||||
static from(channel) {
|
static from(channel) {
|
||||||
return channel._object;
|
return channel._object;
|
||||||
}
|
}
|
||||||
constructor(parent, type, guid, initializer) {
|
constructor(parent, type, guid, initializer) {
|
||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
this._request = void 0;
|
this._tracing = import_tracing.Tracing.from(initializer.tracing);
|
||||||
this._tracing = void 0;
|
|
||||||
this._closeReason = void 0;
|
|
||||||
this._tracing = _tracing.Tracing.from(initializer.tracing);
|
|
||||||
}
|
}
|
||||||
async [_Symbol$asyncDispose]() {
|
async [Symbol.asyncDispose]() {
|
||||||
await this.dispose();
|
await this.dispose();
|
||||||
}
|
}
|
||||||
async dispose(options = {}) {
|
async dispose(options = {}) {
|
||||||
var _this$_request;
|
|
||||||
this._closeReason = options.reason;
|
this._closeReason = options.reason;
|
||||||
await this._instrumentation.runBeforeCloseRequestContext(this);
|
await this._instrumentation.runBeforeCloseRequestContext(this);
|
||||||
try {
|
try {
|
||||||
await this._channel.dispose(options);
|
await this._channel.dispose(options);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if ((0, _errors.isTargetClosedError)(e)) return;
|
if ((0, import_errors.isTargetClosedError)(e))
|
||||||
|
return;
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
this._tracing._resetStackCounter();
|
this._tracing._resetStackCounter();
|
||||||
(_this$_request = this._request) === null || _this$_request === void 0 || _this$_request._contexts.delete(this);
|
this._request?._contexts.delete(this);
|
||||||
}
|
}
|
||||||
async delete(url, options) {
|
async delete(url, options) {
|
||||||
return await this.fetch(url, {
|
return await this.fetch(url, {
|
||||||
...options,
|
...options,
|
||||||
method: 'DELETE'
|
method: "DELETE"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async head(url, options) {
|
async head(url, options) {
|
||||||
return await this.fetch(url, {
|
return await this.fetch(url, {
|
||||||
...options,
|
...options,
|
||||||
method: 'HEAD'
|
method: "HEAD"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async get(url, options) {
|
async get(url, options) {
|
||||||
return await this.fetch(url, {
|
return await this.fetch(url, {
|
||||||
...options,
|
...options,
|
||||||
method: 'GET'
|
method: "GET"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async patch(url, options) {
|
async patch(url, options) {
|
||||||
return await this.fetch(url, {
|
return await this.fetch(url, {
|
||||||
...options,
|
...options,
|
||||||
method: 'PATCH'
|
method: "PATCH"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async post(url, options) {
|
async post(url, options) {
|
||||||
return await this.fetch(url, {
|
return await this.fetch(url, {
|
||||||
...options,
|
...options,
|
||||||
method: 'POST'
|
method: "POST"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async put(url, options) {
|
async put(url, options) {
|
||||||
return await this.fetch(url, {
|
return await this.fetch(url, {
|
||||||
...options,
|
...options,
|
||||||
method: 'PUT'
|
method: "PUT"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async fetch(urlOrRequest, options = {}) {
|
async fetch(urlOrRequest, options = {}) {
|
||||||
const url = (0, _utils.isString)(urlOrRequest) ? urlOrRequest : undefined;
|
const url = (0, import_rtti.isString)(urlOrRequest) ? urlOrRequest : void 0;
|
||||||
const request = (0, _utils.isString)(urlOrRequest) ? undefined : urlOrRequest;
|
const request = (0, import_rtti.isString)(urlOrRequest) ? void 0 : urlOrRequest;
|
||||||
return await this._innerFetch({
|
return await this._innerFetch({ url, request, ...options });
|
||||||
url,
|
|
||||||
request,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async _innerFetch(options = {}) {
|
async _innerFetch(options = {}) {
|
||||||
return await this._wrapApiCall(async () => {
|
return await this._wrapApiCall(async () => {
|
||||||
var _options$request, _options$request2, _options$request3;
|
if (this._closeReason)
|
||||||
if (this._closeReason) throw new _errors.TargetClosedError(this._closeReason);
|
throw new import_errors.TargetClosedError(this._closeReason);
|
||||||
(0, _utils.assert)(options.request || typeof options.url === 'string', 'First argument must be either URL string or Request');
|
(0, import_assert.assert)(options.request || typeof options.url === "string", "First argument must be either URL string or Request");
|
||||||
(0, _utils.assert)((options.data === undefined ? 0 : 1) + (options.form === undefined ? 0 : 1) + (options.multipart === undefined ? 0 : 1) <= 1, `Only one of 'data', 'form' or 'multipart' can be specified`);
|
(0, import_assert.assert)((options.data === void 0 ? 0 : 1) + (options.form === void 0 ? 0 : 1) + (options.multipart === void 0 ? 0 : 1) <= 1, `Only one of 'data', 'form' or 'multipart' can be specified`);
|
||||||
(0, _utils.assert)(options.maxRedirects === undefined || options.maxRedirects >= 0, `'maxRedirects' must be greater than or equal to '0'`);
|
(0, import_assert.assert)(options.maxRedirects === void 0 || options.maxRedirects >= 0, `'maxRedirects' must be greater than or equal to '0'`);
|
||||||
(0, _utils.assert)(options.maxRetries === undefined || options.maxRetries >= 0, `'maxRetries' must be greater than or equal to '0'`);
|
(0, import_assert.assert)(options.maxRetries === void 0 || options.maxRetries >= 0, `'maxRetries' must be greater than or equal to '0'`);
|
||||||
const url = options.url !== undefined ? options.url : options.request.url();
|
const url = options.url !== void 0 ? options.url : options.request.url();
|
||||||
const method = options.method || ((_options$request = options.request) === null || _options$request === void 0 ? void 0 : _options$request.method());
|
const method = options.method || options.request?.method();
|
||||||
let encodedParams = undefined;
|
let encodedParams = void 0;
|
||||||
if (typeof options.params === 'string') encodedParams = options.params;else if (options.params instanceof URLSearchParams) encodedParams = options.params.toString();
|
if (typeof options.params === "string")
|
||||||
// Cannot call allHeaders() here as the request may be paused inside route handler.
|
encodedParams = options.params;
|
||||||
const headersObj = options.headers || ((_options$request2 = options.request) === null || _options$request2 === void 0 ? void 0 : _options$request2.headers());
|
else if (options.params instanceof URLSearchParams)
|
||||||
const headers = headersObj ? (0, _utils.headersObjectToArray)(headersObj) : undefined;
|
encodedParams = options.params.toString();
|
||||||
|
const headersObj = options.headers || options.request?.headers();
|
||||||
|
const headers = headersObj ? (0, import_headers.headersObjectToArray)(headersObj) : void 0;
|
||||||
let jsonData;
|
let jsonData;
|
||||||
let formData;
|
let formData;
|
||||||
let multipartData;
|
let multipartData;
|
||||||
let postDataBuffer;
|
let postDataBuffer;
|
||||||
if (options.data !== undefined) {
|
if (options.data !== void 0) {
|
||||||
if ((0, _utils.isString)(options.data)) {
|
if ((0, import_rtti.isString)(options.data)) {
|
||||||
if (isJsonContentType(headers)) jsonData = isJsonParsable(options.data) ? options.data : JSON.stringify(options.data);else postDataBuffer = Buffer.from(options.data, 'utf8');
|
if (isJsonContentType(headers))
|
||||||
|
jsonData = isJsonParsable(options.data) ? options.data : JSON.stringify(options.data);
|
||||||
|
else
|
||||||
|
postDataBuffer = Buffer.from(options.data, "utf8");
|
||||||
} else if (Buffer.isBuffer(options.data)) {
|
} else if (Buffer.isBuffer(options.data)) {
|
||||||
postDataBuffer = options.data;
|
postDataBuffer = options.data;
|
||||||
} else if (typeof options.data === 'object' || typeof options.data === 'number' || typeof options.data === 'boolean') {
|
} else if (typeof options.data === "object" || typeof options.data === "number" || typeof options.data === "boolean") {
|
||||||
jsonData = JSON.stringify(options.data);
|
jsonData = JSON.stringify(options.data);
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Unexpected 'data' type`);
|
throw new Error(`Unexpected 'data' type`);
|
||||||
@@ -171,11 +162,9 @@ class APIRequestContext extends _channelOwner.ChannelOwner {
|
|||||||
if (globalThis.FormData && options.form instanceof FormData) {
|
if (globalThis.FormData && options.form instanceof FormData) {
|
||||||
formData = [];
|
formData = [];
|
||||||
for (const [name, value] of options.form.entries()) {
|
for (const [name, value] of options.form.entries()) {
|
||||||
if (typeof value !== 'string') throw new Error(`Expected string for options.form["${name}"], found File. Please use options.multipart instead.`);
|
if (typeof value !== "string")
|
||||||
formData.push({
|
throw new Error(`Expected string for options.form["${name}"], found File. Please use options.multipart instead.`);
|
||||||
name,
|
formData.push({ name, value });
|
||||||
value
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
formData = objectToArray(options.form);
|
formData = objectToArray(options.form);
|
||||||
@@ -185,35 +174,30 @@ class APIRequestContext extends _channelOwner.ChannelOwner {
|
|||||||
if (globalThis.FormData && options.multipart instanceof FormData) {
|
if (globalThis.FormData && options.multipart instanceof FormData) {
|
||||||
const form = options.multipart;
|
const form = options.multipart;
|
||||||
for (const [name, value] of form.entries()) {
|
for (const [name, value] of form.entries()) {
|
||||||
if ((0, _utils.isString)(value)) {
|
if ((0, import_rtti.isString)(value)) {
|
||||||
multipartData.push({
|
multipartData.push({ name, value });
|
||||||
name,
|
|
||||||
value
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
const file = {
|
const file = {
|
||||||
name: value.name,
|
name: value.name,
|
||||||
mimeType: value.type,
|
mimeType: value.type,
|
||||||
buffer: Buffer.from(await value.arrayBuffer())
|
buffer: Buffer.from(await value.arrayBuffer())
|
||||||
};
|
};
|
||||||
multipartData.push({
|
multipartData.push({ name, file });
|
||||||
name,
|
|
||||||
file
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Convert file-like values to ServerFilePayload structs.
|
for (const [name, value] of Object.entries(options.multipart))
|
||||||
for (const [name, value] of Object.entries(options.multipart)) multipartData.push(await toFormField(name, value));
|
multipartData.push(await toFormField(this._platform, name, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (postDataBuffer === undefined && jsonData === undefined && formData === undefined && multipartData === undefined) postDataBuffer = ((_options$request3 = options.request) === null || _options$request3 === void 0 ? void 0 : _options$request3.postDataBuffer()) || undefined;
|
if (postDataBuffer === void 0 && jsonData === void 0 && formData === void 0 && multipartData === void 0)
|
||||||
|
postDataBuffer = options.request?.postDataBuffer() || void 0;
|
||||||
const fixtures = {
|
const fixtures = {
|
||||||
__testHookLookup: options.__testHookLookup
|
__testHookLookup: options.__testHookLookup
|
||||||
};
|
};
|
||||||
const result = await this._channel.fetch({
|
const result = await this._channel.fetch({
|
||||||
url,
|
url,
|
||||||
params: typeof options.params === 'object' ? objectToArray(options.params) : undefined,
|
params: typeof options.params === "object" ? objectToArray(options.params) : void 0,
|
||||||
encodedParams,
|
encodedParams,
|
||||||
method,
|
method,
|
||||||
headers,
|
headers,
|
||||||
@@ -232,54 +216,47 @@ class APIRequestContext extends _channelOwner.ChannelOwner {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async storageState(options = {}) {
|
async storageState(options = {}) {
|
||||||
const state = await this._channel.storageState();
|
const state = await this._channel.storageState({ indexedDB: options.indexedDB });
|
||||||
if (options.path) {
|
if (options.path) {
|
||||||
await (0, _fileUtils.mkdirIfNeeded)(options.path);
|
await (0, import_fileUtils.mkdirIfNeeded)(this._platform, options.path);
|
||||||
await _fs.default.promises.writeFile(options.path, JSON.stringify(state, undefined, 2), 'utf8');
|
await this._platform.fs().promises.writeFile(options.path, JSON.stringify(state, void 0, 2), "utf8");
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.APIRequestContext = APIRequestContext;
|
async function toFormField(platform, name, value) {
|
||||||
async function toFormField(name, value) {
|
const typeOfValue = typeof value;
|
||||||
if (isFilePayload(value)) {
|
if (isFilePayload(value)) {
|
||||||
const payload = value;
|
const payload = value;
|
||||||
if (!Buffer.isBuffer(payload.buffer)) throw new Error(`Unexpected buffer type of 'data.${name}'`);
|
if (!Buffer.isBuffer(payload.buffer))
|
||||||
return {
|
throw new Error(`Unexpected buffer type of 'data.${name}'`);
|
||||||
name,
|
return { name, file: filePayloadToJson(payload) };
|
||||||
file: filePayloadToJson(payload)
|
} else if (typeOfValue === "string" || typeOfValue === "number" || typeOfValue === "boolean") {
|
||||||
};
|
return { name, value: String(value) };
|
||||||
} else if (value instanceof _fs.default.ReadStream) {
|
|
||||||
return {
|
|
||||||
name,
|
|
||||||
file: await readStreamToJson(value)
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
return {
|
return { name, file: await readStreamToJson(platform, value) };
|
||||||
name,
|
|
||||||
value: String(value)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function isJsonParsable(value) {
|
function isJsonParsable(value) {
|
||||||
if (typeof value !== 'string') return false;
|
if (typeof value !== "string")
|
||||||
|
return false;
|
||||||
try {
|
try {
|
||||||
JSON.parse(value);
|
JSON.parse(value);
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof SyntaxError) return false;else throw e;
|
if (e instanceof SyntaxError)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_Symbol$asyncDispose2 = Symbol.asyncDispose;
|
|
||||||
_util$inspect$custom = util.inspect.custom;
|
|
||||||
class APIResponse {
|
class APIResponse {
|
||||||
constructor(context, initializer) {
|
constructor(context, initializer) {
|
||||||
this._initializer = void 0;
|
|
||||||
this._headers = void 0;
|
|
||||||
this._request = void 0;
|
|
||||||
this._request = context;
|
this._request = context;
|
||||||
this._initializer = initializer;
|
this._initializer = initializer;
|
||||||
this._headers = new _network.RawHeaders(this._initializer.headers);
|
this._headers = new import_network.RawHeaders(this._initializer.headers);
|
||||||
|
if (context._platform.inspectCustom)
|
||||||
|
this[context._platform.inspectCustom] = () => this._inspect();
|
||||||
}
|
}
|
||||||
ok() {
|
ok() {
|
||||||
return this._initializer.status >= 200 && this._initializer.status <= 299;
|
return this._initializer.status >= 200 && this._initializer.status <= 299;
|
||||||
@@ -300,53 +277,46 @@ class APIResponse {
|
|||||||
return this._headers.headersArray();
|
return this._headers.headersArray();
|
||||||
}
|
}
|
||||||
async body() {
|
async body() {
|
||||||
try {
|
return await this._request._wrapApiCall(async () => {
|
||||||
const result = await this._request._channel.fetchResponseBody({
|
try {
|
||||||
fetchUid: this._fetchUid()
|
const result = await this._request._channel.fetchResponseBody({ fetchUid: this._fetchUid() });
|
||||||
});
|
if (result.binary === void 0)
|
||||||
if (result.binary === undefined) throw new Error('Response has been disposed');
|
throw new Error("Response has been disposed");
|
||||||
return result.binary;
|
return result.binary;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if ((0, _errors.isTargetClosedError)(e)) throw new Error('Response has been disposed');
|
if ((0, import_errors.isTargetClosedError)(e))
|
||||||
throw e;
|
throw new Error("Response has been disposed");
|
||||||
}
|
throw e;
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
}
|
}
|
||||||
async text() {
|
async text() {
|
||||||
const content = await this.body();
|
const content = await this.body();
|
||||||
return content.toString('utf8');
|
return content.toString("utf8");
|
||||||
}
|
}
|
||||||
async json() {
|
async json() {
|
||||||
const content = await this.text();
|
const content = await this.text();
|
||||||
return JSON.parse(content);
|
return JSON.parse(content);
|
||||||
}
|
}
|
||||||
async [_Symbol$asyncDispose2]() {
|
async [Symbol.asyncDispose]() {
|
||||||
await this.dispose();
|
await this.dispose();
|
||||||
}
|
}
|
||||||
async dispose() {
|
async dispose() {
|
||||||
await this._request._channel.disposeAPIResponse({
|
await this._request._channel.disposeAPIResponse({ fetchUid: this._fetchUid() });
|
||||||
fetchUid: this._fetchUid()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
[_util$inspect$custom]() {
|
_inspect() {
|
||||||
const headers = this.headersArray().map(({
|
const headers = this.headersArray().map(({ name, value }) => ` ${name}: ${value}`);
|
||||||
name,
|
return `APIResponse: ${this.status()} ${this.statusText()}
|
||||||
value
|
${headers.join("\n")}`;
|
||||||
}) => ` ${name}: ${value}`);
|
|
||||||
return `APIResponse: ${this.status()} ${this.statusText()}\n${headers.join('\n')}`;
|
|
||||||
}
|
}
|
||||||
_fetchUid() {
|
_fetchUid() {
|
||||||
return this._initializer.fetchUid;
|
return this._initializer.fetchUid;
|
||||||
}
|
}
|
||||||
async _fetchLog() {
|
async _fetchLog() {
|
||||||
const {
|
const { log } = await this._request._channel.fetchLog({ fetchUid: this._fetchUid() });
|
||||||
log
|
|
||||||
} = await this._request._channel.fetchLog({
|
|
||||||
fetchUid: this._fetchUid()
|
|
||||||
});
|
|
||||||
return log;
|
return log;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.APIResponse = APIResponse;
|
|
||||||
function filePayloadToJson(payload) {
|
function filePayloadToJson(payload) {
|
||||||
return {
|
return {
|
||||||
name: payload.name,
|
name: payload.name,
|
||||||
@@ -354,38 +324,44 @@ function filePayloadToJson(payload) {
|
|||||||
buffer: payload.buffer
|
buffer: payload.buffer
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async function readStreamToJson(stream) {
|
async function readStreamToJson(platform, stream) {
|
||||||
const buffer = await new Promise((resolve, reject) => {
|
const buffer = await new Promise((resolve, reject) => {
|
||||||
const chunks = [];
|
const chunks = [];
|
||||||
stream.on('data', chunk => chunks.push(chunk));
|
stream.on("data", (chunk) => chunks.push(chunk));
|
||||||
stream.on('end', () => resolve(Buffer.concat(chunks)));
|
stream.on("end", () => resolve(Buffer.concat(chunks)));
|
||||||
stream.on('error', err => reject(err));
|
stream.on("error", (err) => reject(err));
|
||||||
});
|
});
|
||||||
const streamPath = Buffer.isBuffer(stream.path) ? stream.path.toString('utf8') : stream.path;
|
const streamPath = Buffer.isBuffer(stream.path) ? stream.path.toString("utf8") : stream.path;
|
||||||
return {
|
return {
|
||||||
name: _path.default.basename(streamPath),
|
name: platform.path().basename(streamPath),
|
||||||
buffer
|
buffer
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function isJsonContentType(headers) {
|
function isJsonContentType(headers) {
|
||||||
if (!headers) return false;
|
if (!headers)
|
||||||
for (const {
|
return false;
|
||||||
name,
|
for (const { name, value } of headers) {
|
||||||
value
|
if (name.toLocaleLowerCase() === "content-type")
|
||||||
} of headers) {
|
return value === "application/json";
|
||||||
if (name.toLocaleLowerCase() === 'content-type') return value === 'application/json';
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
function objectToArray(map) {
|
function objectToArray(map) {
|
||||||
if (!map) return undefined;
|
if (!map)
|
||||||
|
return void 0;
|
||||||
const result = [];
|
const result = [];
|
||||||
for (const [name, value] of Object.entries(map)) result.push({
|
for (const [name, value] of Object.entries(map)) {
|
||||||
name,
|
if (value !== void 0)
|
||||||
value: String(value)
|
result.push({ name, value: String(value) });
|
||||||
});
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
function isFilePayload(value) {
|
function isFilePayload(value) {
|
||||||
return typeof value === 'object' && value['name'] && value['mimeType'] && value['buffer'];
|
return typeof value === "object" && value["name"] && value["mimeType"] && value["buffer"];
|
||||||
}
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
APIRequest,
|
||||||
|
APIRequestContext,
|
||||||
|
APIResponse
|
||||||
|
});
|
||||||
|
|||||||
49
tvapp2/node_modules/playwright-core/lib/client/fileChooser.js
generated
vendored
@@ -1,30 +1,28 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var fileChooser_exports = {};
|
||||||
|
__export(fileChooser_exports, {
|
||||||
|
FileChooser: () => FileChooser
|
||||||
});
|
});
|
||||||
exports.FileChooser = void 0;
|
module.exports = __toCommonJS(fileChooser_exports);
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class FileChooser {
|
class FileChooser {
|
||||||
constructor(page, elementHandle, isMultiple) {
|
constructor(page, elementHandle, isMultiple) {
|
||||||
this._page = void 0;
|
|
||||||
this._elementHandle = void 0;
|
|
||||||
this._isMultiple = void 0;
|
|
||||||
this._page = page;
|
this._page = page;
|
||||||
this._elementHandle = elementHandle;
|
this._elementHandle = elementHandle;
|
||||||
this._isMultiple = isMultiple;
|
this._isMultiple = isMultiple;
|
||||||
@@ -42,4 +40,7 @@ class FileChooser {
|
|||||||
return await this._elementHandle.setInputFiles(files, options);
|
return await this._elementHandle.setInputFiles(files, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.FileChooser = FileChooser;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
FileChooser
|
||||||
|
});
|
||||||
|
|||||||
516
tvapp2/node_modules/playwright-core/lib/client/frame.js
generated
vendored
@@ -1,124 +1,129 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __create = Object.create;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __defProp = Object.defineProperty;
|
||||||
value: true
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __getProtoOf = Object.getPrototypeOf;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||||
|
// If the importer is in node compatibility mode or this is not an ESM
|
||||||
|
// file that has been converted to a CommonJS file using a Babel-
|
||||||
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||||
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||||
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||||
|
mod
|
||||||
|
));
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var frame_exports = {};
|
||||||
|
__export(frame_exports, {
|
||||||
|
Frame: () => Frame,
|
||||||
|
verifyLoadState: () => verifyLoadState
|
||||||
});
|
});
|
||||||
exports.Frame = void 0;
|
module.exports = __toCommonJS(frame_exports);
|
||||||
exports.verifyLoadState = verifyLoadState;
|
var import_eventEmitter = require("./eventEmitter");
|
||||||
var _utils = require("../utils");
|
var import_channelOwner = require("./channelOwner");
|
||||||
var _channelOwner = require("./channelOwner");
|
var import_clientHelper = require("./clientHelper");
|
||||||
var _locator = require("./locator");
|
var import_elementHandle = require("./elementHandle");
|
||||||
var _locatorUtils = require("../utils/isomorphic/locatorUtils");
|
var import_events = require("./events");
|
||||||
var _elementHandle = require("./elementHandle");
|
var import_jsHandle = require("./jsHandle");
|
||||||
var _jsHandle = require("./jsHandle");
|
var import_locator = require("./locator");
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
var network = __toESM(require("./network"));
|
||||||
var network = _interopRequireWildcard(require("./network"));
|
var import_types = require("./types");
|
||||||
var _events = require("events");
|
var import_waiter = require("./waiter");
|
||||||
var _waiter = require("./waiter");
|
var import_assert = require("../utils/isomorphic/assert");
|
||||||
var _events2 = require("./events");
|
var import_locatorUtils = require("../utils/isomorphic/locatorUtils");
|
||||||
var _types = require("./types");
|
var import_urlMatch = require("../utils/isomorphic/urlMatch");
|
||||||
var _clientHelper = require("./clientHelper");
|
class Frame extends import_channelOwner.ChannelOwner {
|
||||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
constructor(parent, type, guid, initializer) {
|
||||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
super(parent, type, guid, initializer);
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
this._parentFrame = null;
|
||||||
/**
|
this._url = "";
|
||||||
* Copyright 2017 Google Inc. All rights reserved.
|
this._name = "";
|
||||||
* Modifications copyright (c) Microsoft Corporation.
|
this._detached = false;
|
||||||
*
|
this._childFrames = /* @__PURE__ */ new Set();
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
this._eventEmitter = new import_eventEmitter.EventEmitter(parent._platform);
|
||||||
* you may not use this file except in compliance with the License.
|
this._eventEmitter.setMaxListeners(0);
|
||||||
* You may obtain a copy of the License at
|
this._parentFrame = Frame.fromNullable(initializer.parentFrame);
|
||||||
*
|
if (this._parentFrame)
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
this._parentFrame._childFrames.add(this);
|
||||||
*
|
this._name = initializer.name;
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
this._url = initializer.url;
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
this._loadStates = new Set(initializer.loadStates);
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
this._channel.on("loadstate", (event) => {
|
||||||
* See the License for the specific language governing permissions and
|
if (event.add) {
|
||||||
* limitations under the License.
|
this._loadStates.add(event.add);
|
||||||
*/
|
this._eventEmitter.emit("loadstate", event.add);
|
||||||
|
}
|
||||||
class Frame extends _channelOwner.ChannelOwner {
|
if (event.remove)
|
||||||
|
this._loadStates.delete(event.remove);
|
||||||
|
if (!this._parentFrame && event.add === "load" && this._page)
|
||||||
|
this._page.emit(import_events.Events.Page.Load, this._page);
|
||||||
|
if (!this._parentFrame && event.add === "domcontentloaded" && this._page)
|
||||||
|
this._page.emit(import_events.Events.Page.DOMContentLoaded, this._page);
|
||||||
|
});
|
||||||
|
this._channel.on("navigated", (event) => {
|
||||||
|
this._url = event.url;
|
||||||
|
this._name = event.name;
|
||||||
|
this._eventEmitter.emit("navigated", event);
|
||||||
|
if (!event.error && this._page)
|
||||||
|
this._page.emit(import_events.Events.Page.FrameNavigated, this);
|
||||||
|
});
|
||||||
|
}
|
||||||
static from(frame) {
|
static from(frame) {
|
||||||
return frame._object;
|
return frame._object;
|
||||||
}
|
}
|
||||||
static fromNullable(frame) {
|
static fromNullable(frame) {
|
||||||
return frame ? Frame.from(frame) : null;
|
return frame ? Frame.from(frame) : null;
|
||||||
}
|
}
|
||||||
constructor(parent, type, guid, initializer) {
|
|
||||||
super(parent, type, guid, initializer);
|
|
||||||
this._eventEmitter = void 0;
|
|
||||||
this._loadStates = void 0;
|
|
||||||
this._parentFrame = null;
|
|
||||||
this._url = '';
|
|
||||||
this._name = '';
|
|
||||||
this._detached = false;
|
|
||||||
this._childFrames = new Set();
|
|
||||||
this._page = void 0;
|
|
||||||
this._eventEmitter = new _events.EventEmitter();
|
|
||||||
this._eventEmitter.setMaxListeners(0);
|
|
||||||
this._parentFrame = Frame.fromNullable(initializer.parentFrame);
|
|
||||||
if (this._parentFrame) this._parentFrame._childFrames.add(this);
|
|
||||||
this._name = initializer.name;
|
|
||||||
this._url = initializer.url;
|
|
||||||
this._loadStates = new Set(initializer.loadStates);
|
|
||||||
this._channel.on('loadstate', event => {
|
|
||||||
if (event.add) {
|
|
||||||
this._loadStates.add(event.add);
|
|
||||||
this._eventEmitter.emit('loadstate', event.add);
|
|
||||||
}
|
|
||||||
if (event.remove) this._loadStates.delete(event.remove);
|
|
||||||
if (!this._parentFrame && event.add === 'load' && this._page) this._page.emit(_events2.Events.Page.Load, this._page);
|
|
||||||
if (!this._parentFrame && event.add === 'domcontentloaded' && this._page) this._page.emit(_events2.Events.Page.DOMContentLoaded, this._page);
|
|
||||||
});
|
|
||||||
this._channel.on('navigated', event => {
|
|
||||||
this._url = event.url;
|
|
||||||
this._name = event.name;
|
|
||||||
this._eventEmitter.emit('navigated', event);
|
|
||||||
if (!event.error && this._page) this._page.emit(_events2.Events.Page.FrameNavigated, this);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
page() {
|
page() {
|
||||||
return this._page;
|
return this._page;
|
||||||
}
|
}
|
||||||
async goto(url, options = {}) {
|
async goto(url, options = {}) {
|
||||||
const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);
|
const waitUntil = verifyLoadState("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil);
|
||||||
return network.Response.fromNullable((await this._channel.goto({
|
return network.Response.fromNullable((await this._channel.goto({ url, ...options, waitUntil })).response);
|
||||||
url,
|
|
||||||
...options,
|
|
||||||
waitUntil
|
|
||||||
})).response);
|
|
||||||
}
|
}
|
||||||
_setupNavigationWaiter(options) {
|
_setupNavigationWaiter(options) {
|
||||||
const waiter = new _waiter.Waiter(this._page, '');
|
const waiter = new import_waiter.Waiter(this._page, "");
|
||||||
if (this._page.isClosed()) waiter.rejectImmediately(this._page._closeErrorWithReason());
|
if (this._page.isClosed())
|
||||||
waiter.rejectOnEvent(this._page, _events2.Events.Page.Close, () => this._page._closeErrorWithReason());
|
waiter.rejectImmediately(this._page._closeErrorWithReason());
|
||||||
waiter.rejectOnEvent(this._page, _events2.Events.Page.Crash, new Error('Navigation failed because page crashed!'));
|
waiter.rejectOnEvent(this._page, import_events.Events.Page.Close, () => this._page._closeErrorWithReason());
|
||||||
waiter.rejectOnEvent(this._page, _events2.Events.Page.FrameDetached, new Error('Navigating frame was detached!'), frame => frame === this);
|
waiter.rejectOnEvent(this._page, import_events.Events.Page.Crash, new Error("Navigation failed because page crashed!"));
|
||||||
|
waiter.rejectOnEvent(this._page, import_events.Events.Page.FrameDetached, new Error("Navigating frame was detached!"), (frame) => frame === this);
|
||||||
const timeout = this._page._timeoutSettings.navigationTimeout(options);
|
const timeout = this._page._timeoutSettings.navigationTimeout(options);
|
||||||
waiter.rejectOnTimeout(timeout, `Timeout ${timeout}ms exceeded.`);
|
waiter.rejectOnTimeout(timeout, `Timeout ${timeout}ms exceeded.`);
|
||||||
return waiter;
|
return waiter;
|
||||||
}
|
}
|
||||||
async waitForNavigation(options = {}) {
|
async waitForNavigation(options = {}) {
|
||||||
return await this._page._wrapApiCall(async () => {
|
return await this._page._wrapApiCall(async () => {
|
||||||
const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);
|
const waitUntil = verifyLoadState("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil);
|
||||||
const waiter = this._setupNavigationWaiter(options);
|
const waiter = this._setupNavigationWaiter(options);
|
||||||
const toUrl = typeof options.url === 'string' ? ` to "${options.url}"` : '';
|
const toUrl = typeof options.url === "string" ? ` to "${options.url}"` : "";
|
||||||
waiter.log(`waiting for navigation${toUrl} until "${waitUntil}"`);
|
waiter.log(`waiting for navigation${toUrl} until "${waitUntil}"`);
|
||||||
const navigatedEvent = await waiter.waitForEvent(this._eventEmitter, 'navigated', event => {
|
const navigatedEvent = await waiter.waitForEvent(this._eventEmitter, "navigated", (event) => {
|
||||||
var _this$_page;
|
if (event.error)
|
||||||
// Any failed navigation results in a rejection.
|
return true;
|
||||||
if (event.error) return true;
|
|
||||||
waiter.log(` navigated to "${event.url}"`);
|
waiter.log(` navigated to "${event.url}"`);
|
||||||
return (0, _utils.urlMatches)((_this$_page = this._page) === null || _this$_page === void 0 ? void 0 : _this$_page.context()._options.baseURL, event.url, options.url);
|
return (0, import_urlMatch.urlMatches)(this._page?.context()._options.baseURL, event.url, options.url);
|
||||||
});
|
});
|
||||||
if (navigatedEvent.error) {
|
if (navigatedEvent.error) {
|
||||||
const e = new Error(navigatedEvent.error);
|
const e = new Error(navigatedEvent.error);
|
||||||
e.stack = '';
|
e.stack = "";
|
||||||
await waiter.waitForPromise(Promise.reject(e));
|
await waiter.waitForPromise(Promise.reject(e));
|
||||||
}
|
}
|
||||||
if (!this._loadStates.has(waitUntil)) {
|
if (!this._loadStates.has(waitUntil)) {
|
||||||
await waiter.waitForEvent(this._eventEmitter, 'loadstate', s => {
|
await waiter.waitForEvent(this._eventEmitter, "loadstate", (s) => {
|
||||||
waiter.log(` "${s}" event fired`);
|
waiter.log(` "${s}" event fired`);
|
||||||
return s === waitUntil;
|
return s === waitUntil;
|
||||||
});
|
});
|
||||||
@@ -129,14 +134,14 @@ class Frame extends _channelOwner.ChannelOwner {
|
|||||||
return response;
|
return response;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async waitForLoadState(state = 'load', options = {}) {
|
async waitForLoadState(state = "load", options = {}) {
|
||||||
state = verifyLoadState('state', state);
|
state = verifyLoadState("state", state);
|
||||||
return await this._page._wrapApiCall(async () => {
|
return await this._page._wrapApiCall(async () => {
|
||||||
const waiter = this._setupNavigationWaiter(options);
|
const waiter = this._setupNavigationWaiter(options);
|
||||||
if (this._loadStates.has(state)) {
|
if (this._loadStates.has(state)) {
|
||||||
waiter.log(` not waiting, "${state}" event already fired`);
|
waiter.log(` not waiting, "${state}" event already fired`);
|
||||||
} else {
|
} else {
|
||||||
await waiter.waitForEvent(this._eventEmitter, 'loadstate', s => {
|
await waiter.waitForEvent(this._eventEmitter, "loadstate", (s) => {
|
||||||
waiter.log(` "${s}" event fired`);
|
waiter.log(` "${s}" event fired`);
|
||||||
return s === state;
|
return s === state;
|
||||||
});
|
});
|
||||||
@@ -145,111 +150,69 @@ class Frame extends _channelOwner.ChannelOwner {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async waitForURL(url, options = {}) {
|
async waitForURL(url, options = {}) {
|
||||||
var _this$_page2;
|
if ((0, import_urlMatch.urlMatches)(this._page?.context()._options.baseURL, this.url(), url))
|
||||||
if ((0, _utils.urlMatches)((_this$_page2 = this._page) === null || _this$_page2 === void 0 ? void 0 : _this$_page2.context()._options.baseURL, this.url(), url)) return await this.waitForLoadState(options.waitUntil, options);
|
return await this.waitForLoadState(options.waitUntil, options);
|
||||||
await this.waitForNavigation({
|
await this.waitForNavigation({ url, ...options });
|
||||||
url,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async frameElement() {
|
async frameElement() {
|
||||||
return _elementHandle.ElementHandle.from((await this._channel.frameElement()).element);
|
return import_elementHandle.ElementHandle.from((await this._channel.frameElement()).element);
|
||||||
}
|
}
|
||||||
async evaluateHandle(pageFunction, arg) {
|
async evaluateHandle(pageFunction, arg) {
|
||||||
(0, _jsHandle.assertMaxArguments)(arguments.length, 2);
|
(0, import_jsHandle.assertMaxArguments)(arguments.length, 2);
|
||||||
const result = await this._channel.evaluateExpressionHandle({
|
const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
|
||||||
expression: String(pageFunction),
|
return import_jsHandle.JSHandle.from(result.handle);
|
||||||
isFunction: typeof pageFunction === 'function',
|
|
||||||
arg: (0, _jsHandle.serializeArgument)(arg)
|
|
||||||
});
|
|
||||||
return _jsHandle.JSHandle.from(result.handle);
|
|
||||||
}
|
}
|
||||||
async evaluate(pageFunction, arg) {
|
async evaluate(pageFunction, arg) {
|
||||||
(0, _jsHandle.assertMaxArguments)(arguments.length, 2);
|
(0, import_jsHandle.assertMaxArguments)(arguments.length, 2);
|
||||||
const result = await this._channel.evaluateExpression({
|
const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
|
||||||
expression: String(pageFunction),
|
return (0, import_jsHandle.parseResult)(result.value);
|
||||||
isFunction: typeof pageFunction === 'function',
|
|
||||||
arg: (0, _jsHandle.serializeArgument)(arg)
|
|
||||||
});
|
|
||||||
return (0, _jsHandle.parseResult)(result.value);
|
|
||||||
}
|
}
|
||||||
async _evaluateExposeUtilityScript(pageFunction, arg) {
|
async _evaluateExposeUtilityScript(pageFunction, arg) {
|
||||||
(0, _jsHandle.assertMaxArguments)(arguments.length, 2);
|
(0, import_jsHandle.assertMaxArguments)(arguments.length, 2);
|
||||||
const result = await this._channel.evaluateExpression({
|
const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
|
||||||
expression: String(pageFunction),
|
return (0, import_jsHandle.parseResult)(result.value);
|
||||||
isFunction: typeof pageFunction === 'function',
|
|
||||||
arg: (0, _jsHandle.serializeArgument)(arg)
|
|
||||||
});
|
|
||||||
return (0, _jsHandle.parseResult)(result.value);
|
|
||||||
}
|
}
|
||||||
async $(selector, options) {
|
async $(selector, options) {
|
||||||
const result = await this._channel.querySelector({
|
const result = await this._channel.querySelector({ selector, ...options });
|
||||||
selector,
|
return import_elementHandle.ElementHandle.fromNullable(result.element);
|
||||||
...options
|
|
||||||
});
|
|
||||||
return _elementHandle.ElementHandle.fromNullable(result.element);
|
|
||||||
}
|
}
|
||||||
async waitForSelector(selector, options = {}) {
|
async waitForSelector(selector, options = {}) {
|
||||||
if (options.visibility) throw new Error('options.visibility is not supported, did you mean options.state?');
|
if (options.visibility)
|
||||||
if (options.waitFor && options.waitFor !== 'visible') throw new Error('options.waitFor is not supported, did you mean options.state?');
|
throw new Error("options.visibility is not supported, did you mean options.state?");
|
||||||
const result = await this._channel.waitForSelector({
|
if (options.waitFor && options.waitFor !== "visible")
|
||||||
selector,
|
throw new Error("options.waitFor is not supported, did you mean options.state?");
|
||||||
...options
|
const result = await this._channel.waitForSelector({ selector, ...options });
|
||||||
});
|
return import_elementHandle.ElementHandle.fromNullable(result.element);
|
||||||
return _elementHandle.ElementHandle.fromNullable(result.element);
|
|
||||||
}
|
}
|
||||||
async dispatchEvent(selector, type, eventInit, options = {}) {
|
async dispatchEvent(selector, type, eventInit, options = {}) {
|
||||||
await this._channel.dispatchEvent({
|
await this._channel.dispatchEvent({ selector, type, eventInit: (0, import_jsHandle.serializeArgument)(eventInit), ...options });
|
||||||
selector,
|
|
||||||
type,
|
|
||||||
eventInit: (0, _jsHandle.serializeArgument)(eventInit),
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async $eval(selector, pageFunction, arg) {
|
async $eval(selector, pageFunction, arg) {
|
||||||
(0, _jsHandle.assertMaxArguments)(arguments.length, 3);
|
(0, import_jsHandle.assertMaxArguments)(arguments.length, 3);
|
||||||
const result = await this._channel.evalOnSelector({
|
const result = await this._channel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
|
||||||
selector,
|
return (0, import_jsHandle.parseResult)(result.value);
|
||||||
expression: String(pageFunction),
|
|
||||||
isFunction: typeof pageFunction === 'function',
|
|
||||||
arg: (0, _jsHandle.serializeArgument)(arg)
|
|
||||||
});
|
|
||||||
return (0, _jsHandle.parseResult)(result.value);
|
|
||||||
}
|
}
|
||||||
async $$eval(selector, pageFunction, arg) {
|
async $$eval(selector, pageFunction, arg) {
|
||||||
(0, _jsHandle.assertMaxArguments)(arguments.length, 3);
|
(0, import_jsHandle.assertMaxArguments)(arguments.length, 3);
|
||||||
const result = await this._channel.evalOnSelectorAll({
|
const result = await this._channel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
|
||||||
selector,
|
return (0, import_jsHandle.parseResult)(result.value);
|
||||||
expression: String(pageFunction),
|
|
||||||
isFunction: typeof pageFunction === 'function',
|
|
||||||
arg: (0, _jsHandle.serializeArgument)(arg)
|
|
||||||
});
|
|
||||||
return (0, _jsHandle.parseResult)(result.value);
|
|
||||||
}
|
}
|
||||||
async $$(selector) {
|
async $$(selector) {
|
||||||
const result = await this._channel.querySelectorAll({
|
const result = await this._channel.querySelectorAll({ selector });
|
||||||
selector
|
return result.elements.map((e) => import_elementHandle.ElementHandle.from(e));
|
||||||
});
|
|
||||||
return result.elements.map(e => _elementHandle.ElementHandle.from(e));
|
|
||||||
}
|
}
|
||||||
async _queryCount(selector) {
|
async _queryCount(selector) {
|
||||||
return (await this._channel.queryCount({
|
return (await this._channel.queryCount({ selector })).value;
|
||||||
selector
|
|
||||||
})).value;
|
|
||||||
}
|
}
|
||||||
async content() {
|
async content() {
|
||||||
return (await this._channel.content()).value;
|
return (await this._channel.content()).value;
|
||||||
}
|
}
|
||||||
async setContent(html, options = {}) {
|
async setContent(html, options = {}) {
|
||||||
const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);
|
const waitUntil = verifyLoadState("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil);
|
||||||
await this._channel.setContent({
|
await this._channel.setContent({ html, ...options, waitUntil });
|
||||||
html,
|
|
||||||
...options,
|
|
||||||
waitUntil
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
name() {
|
name() {
|
||||||
return this._name || '';
|
return this._name || "";
|
||||||
}
|
}
|
||||||
url() {
|
url() {
|
||||||
return this._url;
|
return this._url;
|
||||||
@@ -264,241 +227,160 @@ class Frame extends _channelOwner.ChannelOwner {
|
|||||||
return this._detached;
|
return this._detached;
|
||||||
}
|
}
|
||||||
async addScriptTag(options = {}) {
|
async addScriptTag(options = {}) {
|
||||||
const copy = {
|
const copy = { ...options };
|
||||||
...options
|
|
||||||
};
|
|
||||||
if (copy.path) {
|
if (copy.path) {
|
||||||
copy.content = (await _fs.default.promises.readFile(copy.path)).toString();
|
copy.content = (await this._platform.fs().promises.readFile(copy.path)).toString();
|
||||||
copy.content = (0, _clientHelper.addSourceUrlToScript)(copy.content, copy.path);
|
copy.content = (0, import_clientHelper.addSourceUrlToScript)(copy.content, copy.path);
|
||||||
}
|
}
|
||||||
return _elementHandle.ElementHandle.from((await this._channel.addScriptTag({
|
return import_elementHandle.ElementHandle.from((await this._channel.addScriptTag({ ...copy })).element);
|
||||||
...copy
|
|
||||||
})).element);
|
|
||||||
}
|
}
|
||||||
async addStyleTag(options = {}) {
|
async addStyleTag(options = {}) {
|
||||||
const copy = {
|
const copy = { ...options };
|
||||||
...options
|
|
||||||
};
|
|
||||||
if (copy.path) {
|
if (copy.path) {
|
||||||
copy.content = (await _fs.default.promises.readFile(copy.path)).toString();
|
copy.content = (await this._platform.fs().promises.readFile(copy.path)).toString();
|
||||||
copy.content += '/*# sourceURL=' + copy.path.replace(/\n/g, '') + '*/';
|
copy.content += "/*# sourceURL=" + copy.path.replace(/\n/g, "") + "*/";
|
||||||
}
|
}
|
||||||
return _elementHandle.ElementHandle.from((await this._channel.addStyleTag({
|
return import_elementHandle.ElementHandle.from((await this._channel.addStyleTag({ ...copy })).element);
|
||||||
...copy
|
|
||||||
})).element);
|
|
||||||
}
|
}
|
||||||
async click(selector, options = {}) {
|
async click(selector, options = {}) {
|
||||||
return await this._channel.click({
|
return await this._channel.click({ selector, ...options });
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async dblclick(selector, options = {}) {
|
async dblclick(selector, options = {}) {
|
||||||
return await this._channel.dblclick({
|
return await this._channel.dblclick({ selector, ...options });
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async dragAndDrop(source, target, options = {}) {
|
async dragAndDrop(source, target, options = {}) {
|
||||||
return await this._channel.dragAndDrop({
|
return await this._channel.dragAndDrop({ source, target, ...options });
|
||||||
source,
|
|
||||||
target,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async tap(selector, options = {}) {
|
async tap(selector, options = {}) {
|
||||||
return await this._channel.tap({
|
return await this._channel.tap({ selector, ...options });
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async fill(selector, value, options = {}) {
|
async fill(selector, value, options = {}) {
|
||||||
return await this._channel.fill({
|
return await this._channel.fill({ selector, value, ...options });
|
||||||
selector,
|
|
||||||
value,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async _highlight(selector) {
|
async _highlight(selector) {
|
||||||
return await this._channel.highlight({
|
return await this._channel.highlight({ selector });
|
||||||
selector
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
locator(selector, options) {
|
locator(selector, options) {
|
||||||
return new _locator.Locator(this, selector, options);
|
return new import_locator.Locator(this, selector, options);
|
||||||
}
|
}
|
||||||
getByTestId(testId) {
|
getByTestId(testId) {
|
||||||
return this.locator((0, _locatorUtils.getByTestIdSelector)((0, _locator.testIdAttributeName)(), testId));
|
return this.locator((0, import_locatorUtils.getByTestIdSelector)((0, import_locator.testIdAttributeName)(), testId));
|
||||||
}
|
}
|
||||||
getByAltText(text, options) {
|
getByAltText(text, options) {
|
||||||
return this.locator((0, _locatorUtils.getByAltTextSelector)(text, options));
|
return this.locator((0, import_locatorUtils.getByAltTextSelector)(text, options));
|
||||||
}
|
}
|
||||||
getByLabel(text, options) {
|
getByLabel(text, options) {
|
||||||
return this.locator((0, _locatorUtils.getByLabelSelector)(text, options));
|
return this.locator((0, import_locatorUtils.getByLabelSelector)(text, options));
|
||||||
}
|
}
|
||||||
getByPlaceholder(text, options) {
|
getByPlaceholder(text, options) {
|
||||||
return this.locator((0, _locatorUtils.getByPlaceholderSelector)(text, options));
|
return this.locator((0, import_locatorUtils.getByPlaceholderSelector)(text, options));
|
||||||
}
|
}
|
||||||
getByText(text, options) {
|
getByText(text, options) {
|
||||||
return this.locator((0, _locatorUtils.getByTextSelector)(text, options));
|
return this.locator((0, import_locatorUtils.getByTextSelector)(text, options));
|
||||||
}
|
}
|
||||||
getByTitle(text, options) {
|
getByTitle(text, options) {
|
||||||
return this.locator((0, _locatorUtils.getByTitleSelector)(text, options));
|
return this.locator((0, import_locatorUtils.getByTitleSelector)(text, options));
|
||||||
}
|
}
|
||||||
getByRole(role, options = {}) {
|
getByRole(role, options = {}) {
|
||||||
return this.locator((0, _locatorUtils.getByRoleSelector)(role, options));
|
return this.locator((0, import_locatorUtils.getByRoleSelector)(role, options));
|
||||||
}
|
}
|
||||||
frameLocator(selector) {
|
frameLocator(selector) {
|
||||||
return new _locator.FrameLocator(this, selector);
|
return new import_locator.FrameLocator(this, selector);
|
||||||
}
|
}
|
||||||
async focus(selector, options = {}) {
|
async focus(selector, options = {}) {
|
||||||
await this._channel.focus({
|
await this._channel.focus({ selector, ...options });
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async textContent(selector, options = {}) {
|
async textContent(selector, options = {}) {
|
||||||
const value = (await this._channel.textContent({
|
const value = (await this._channel.textContent({ selector, ...options })).value;
|
||||||
selector,
|
return value === void 0 ? null : value;
|
||||||
...options
|
|
||||||
})).value;
|
|
||||||
return value === undefined ? null : value;
|
|
||||||
}
|
}
|
||||||
async innerText(selector, options = {}) {
|
async innerText(selector, options = {}) {
|
||||||
return (await this._channel.innerText({
|
return (await this._channel.innerText({ selector, ...options })).value;
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
})).value;
|
|
||||||
}
|
}
|
||||||
async innerHTML(selector, options = {}) {
|
async innerHTML(selector, options = {}) {
|
||||||
return (await this._channel.innerHTML({
|
return (await this._channel.innerHTML({ selector, ...options })).value;
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
})).value;
|
|
||||||
}
|
}
|
||||||
async getAttribute(selector, name, options = {}) {
|
async getAttribute(selector, name, options = {}) {
|
||||||
const value = (await this._channel.getAttribute({
|
const value = (await this._channel.getAttribute({ selector, name, ...options })).value;
|
||||||
selector,
|
return value === void 0 ? null : value;
|
||||||
name,
|
|
||||||
...options
|
|
||||||
})).value;
|
|
||||||
return value === undefined ? null : value;
|
|
||||||
}
|
}
|
||||||
async inputValue(selector, options = {}) {
|
async inputValue(selector, options = {}) {
|
||||||
return (await this._channel.inputValue({
|
return (await this._channel.inputValue({ selector, ...options })).value;
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
})).value;
|
|
||||||
}
|
}
|
||||||
async isChecked(selector, options = {}) {
|
async isChecked(selector, options = {}) {
|
||||||
return (await this._channel.isChecked({
|
return (await this._channel.isChecked({ selector, ...options })).value;
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
})).value;
|
|
||||||
}
|
}
|
||||||
async isDisabled(selector, options = {}) {
|
async isDisabled(selector, options = {}) {
|
||||||
return (await this._channel.isDisabled({
|
return (await this._channel.isDisabled({ selector, ...options })).value;
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
})).value;
|
|
||||||
}
|
}
|
||||||
async isEditable(selector, options = {}) {
|
async isEditable(selector, options = {}) {
|
||||||
return (await this._channel.isEditable({
|
return (await this._channel.isEditable({ selector, ...options })).value;
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
})).value;
|
|
||||||
}
|
}
|
||||||
async isEnabled(selector, options = {}) {
|
async isEnabled(selector, options = {}) {
|
||||||
return (await this._channel.isEnabled({
|
return (await this._channel.isEnabled({ selector, ...options })).value;
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
})).value;
|
|
||||||
}
|
}
|
||||||
async isHidden(selector, options = {}) {
|
async isHidden(selector, options = {}) {
|
||||||
return (await this._channel.isHidden({
|
return (await this._channel.isHidden({ selector, ...options })).value;
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
})).value;
|
|
||||||
}
|
}
|
||||||
async isVisible(selector, options = {}) {
|
async isVisible(selector, options = {}) {
|
||||||
return (await this._channel.isVisible({
|
return (await this._channel.isVisible({ selector, ...options })).value;
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
})).value;
|
|
||||||
}
|
}
|
||||||
async hover(selector, options = {}) {
|
async hover(selector, options = {}) {
|
||||||
await this._channel.hover({
|
await this._channel.hover({ selector, ...options });
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async selectOption(selector, values, options = {}) {
|
async selectOption(selector, values, options = {}) {
|
||||||
return (await this._channel.selectOption({
|
return (await this._channel.selectOption({ selector, ...(0, import_elementHandle.convertSelectOptionValues)(values), ...options })).values;
|
||||||
selector,
|
|
||||||
...(0, _elementHandle.convertSelectOptionValues)(values),
|
|
||||||
...options
|
|
||||||
})).values;
|
|
||||||
}
|
}
|
||||||
async setInputFiles(selector, files, options = {}) {
|
async setInputFiles(selector, files, options = {}) {
|
||||||
const converted = await (0, _elementHandle.convertInputFiles)(files, this.page().context());
|
const converted = await (0, import_elementHandle.convertInputFiles)(this._platform, files, this.page().context());
|
||||||
await this._channel.setInputFiles({
|
await this._channel.setInputFiles({ selector, ...converted, ...options });
|
||||||
selector,
|
|
||||||
...converted,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async type(selector, text, options = {}) {
|
async type(selector, text, options = {}) {
|
||||||
await this._channel.type({
|
await this._channel.type({ selector, text, ...options });
|
||||||
selector,
|
|
||||||
text,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async press(selector, key, options = {}) {
|
async press(selector, key, options = {}) {
|
||||||
await this._channel.press({
|
await this._channel.press({ selector, key, ...options });
|
||||||
selector,
|
|
||||||
key,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async check(selector, options = {}) {
|
async check(selector, options = {}) {
|
||||||
await this._channel.check({
|
await this._channel.check({ selector, ...options });
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async uncheck(selector, options = {}) {
|
async uncheck(selector, options = {}) {
|
||||||
await this._channel.uncheck({
|
await this._channel.uncheck({ selector, ...options });
|
||||||
selector,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async setChecked(selector, checked, options) {
|
async setChecked(selector, checked, options) {
|
||||||
if (checked) await this.check(selector, options);else await this.uncheck(selector, options);
|
if (checked)
|
||||||
|
await this.check(selector, options);
|
||||||
|
else
|
||||||
|
await this.uncheck(selector, options);
|
||||||
}
|
}
|
||||||
async waitForTimeout(timeout) {
|
async waitForTimeout(timeout) {
|
||||||
await this._channel.waitForTimeout({
|
await this._channel.waitForTimeout({ timeout });
|
||||||
timeout
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async waitForFunction(pageFunction, arg, options = {}) {
|
async waitForFunction(pageFunction, arg, options = {}) {
|
||||||
if (typeof options.polling === 'string') (0, _utils.assert)(options.polling === 'raf', 'Unknown polling option: ' + options.polling);
|
if (typeof options.polling === "string")
|
||||||
|
(0, import_assert.assert)(options.polling === "raf", "Unknown polling option: " + options.polling);
|
||||||
const result = await this._channel.waitForFunction({
|
const result = await this._channel.waitForFunction({
|
||||||
...options,
|
...options,
|
||||||
pollingInterval: options.polling === 'raf' ? undefined : options.polling,
|
pollingInterval: options.polling === "raf" ? void 0 : options.polling,
|
||||||
expression: String(pageFunction),
|
expression: String(pageFunction),
|
||||||
isFunction: typeof pageFunction === 'function',
|
isFunction: typeof pageFunction === "function",
|
||||||
arg: (0, _jsHandle.serializeArgument)(arg)
|
arg: (0, import_jsHandle.serializeArgument)(arg)
|
||||||
});
|
});
|
||||||
return _jsHandle.JSHandle.from(result.handle);
|
return import_jsHandle.JSHandle.from(result.handle);
|
||||||
}
|
}
|
||||||
async title() {
|
async title() {
|
||||||
return (await this._channel.title()).value;
|
return (await this._channel.title()).value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Frame = Frame;
|
|
||||||
function verifyLoadState(name, waitUntil) {
|
function verifyLoadState(name, waitUntil) {
|
||||||
if (waitUntil === 'networkidle0') waitUntil = 'networkidle';
|
if (waitUntil === "networkidle0")
|
||||||
if (!_types.kLifecycleEvents.has(waitUntil)) throw new Error(`${name}: expected one of (load|domcontentloaded|networkidle|commit)`);
|
waitUntil = "networkidle";
|
||||||
|
if (!import_types.kLifecycleEvents.has(waitUntil))
|
||||||
|
throw new Error(`${name}: expected one of (load|domcontentloaded|networkidle|commit)`);
|
||||||
return waitUntil;
|
return waitUntil;
|
||||||
}
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
Frame,
|
||||||
|
verifyLoadState
|
||||||
|
});
|
||||||
|
|||||||
100
tvapp2/node_modules/playwright-core/lib/client/harRouter.js
generated
vendored
@@ -1,43 +1,34 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var harRouter_exports = {};
|
||||||
|
__export(harRouter_exports, {
|
||||||
|
HarRouter: () => HarRouter
|
||||||
});
|
});
|
||||||
exports.HarRouter = void 0;
|
module.exports = __toCommonJS(harRouter_exports);
|
||||||
var _debugLogger = require("../utils/debugLogger");
|
|
||||||
let _Symbol$asyncDispose;
|
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
_Symbol$asyncDispose = Symbol.asyncDispose;
|
|
||||||
class HarRouter {
|
class HarRouter {
|
||||||
static async create(localUtils, file, notFoundAction, options) {
|
static async create(localUtils, file, notFoundAction, options) {
|
||||||
const {
|
const { harId, error } = await localUtils.harOpen({ file });
|
||||||
harId,
|
if (error)
|
||||||
error
|
throw new Error(error);
|
||||||
} = await localUtils._channel.harOpen({
|
|
||||||
file
|
|
||||||
});
|
|
||||||
if (error) throw new Error(error);
|
|
||||||
return new HarRouter(localUtils, harId, notFoundAction, options);
|
return new HarRouter(localUtils, harId, notFoundAction, options);
|
||||||
}
|
}
|
||||||
constructor(localUtils, harId, notFoundAction, options) {
|
constructor(localUtils, harId, notFoundAction, options) {
|
||||||
this._localUtils = void 0;
|
|
||||||
this._harId = void 0;
|
|
||||||
this._notFoundAction = void 0;
|
|
||||||
this._options = void 0;
|
|
||||||
this._localUtils = localUtils;
|
this._localUtils = localUtils;
|
||||||
this._harId = harId;
|
this._harId = harId;
|
||||||
this._options = options;
|
this._options = options;
|
||||||
@@ -45,55 +36,52 @@ class HarRouter {
|
|||||||
}
|
}
|
||||||
async _handle(route) {
|
async _handle(route) {
|
||||||
const request = route.request();
|
const request = route.request();
|
||||||
const response = await this._localUtils._channel.harLookup({
|
const response = await this._localUtils.harLookup({
|
||||||
harId: this._harId,
|
harId: this._harId,
|
||||||
url: request.url(),
|
url: request.url(),
|
||||||
method: request.method(),
|
method: request.method(),
|
||||||
headers: await request.headersArray(),
|
headers: await request.headersArray(),
|
||||||
postData: request.postDataBuffer() || undefined,
|
postData: request.postDataBuffer() || void 0,
|
||||||
isNavigationRequest: request.isNavigationRequest()
|
isNavigationRequest: request.isNavigationRequest()
|
||||||
});
|
});
|
||||||
if (response.action === 'redirect') {
|
if (response.action === "redirect") {
|
||||||
_debugLogger.debugLogger.log('api', `HAR: ${route.request().url()} redirected to ${response.redirectURL}`);
|
route._platform.log("api", `HAR: ${route.request().url()} redirected to ${response.redirectURL}`);
|
||||||
await route._redirectNavigationRequest(response.redirectURL);
|
await route._redirectNavigationRequest(response.redirectURL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (response.action === 'fulfill') {
|
if (response.action === "fulfill") {
|
||||||
// If the response status is -1, the request was canceled or stalled, so we just stall it here.
|
if (response.status === -1)
|
||||||
// See https://github.com/microsoft/playwright/issues/29311.
|
return;
|
||||||
// TODO: it'd be better to abort such requests, but then we likely need to respect the timing,
|
|
||||||
// because the request might have been stalled for a long time until the very end of the
|
|
||||||
// test when HAR was recorded but we'd abort it immediately.
|
|
||||||
if (response.status === -1) return;
|
|
||||||
await route.fulfill({
|
await route.fulfill({
|
||||||
status: response.status,
|
status: response.status,
|
||||||
headers: Object.fromEntries(response.headers.map(h => [h.name, h.value])),
|
headers: Object.fromEntries(response.headers.map((h) => [h.name, h.value])),
|
||||||
body: response.body
|
body: response.body
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (response.action === 'error') _debugLogger.debugLogger.log('api', 'HAR: ' + response.message);
|
if (response.action === "error")
|
||||||
// Report the error, but fall through to the default handler.
|
route._platform.log("api", "HAR: " + response.message);
|
||||||
|
if (this._notFoundAction === "abort") {
|
||||||
if (this._notFoundAction === 'abort') {
|
|
||||||
await route.abort();
|
await route.abort();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await route.fallback();
|
await route.fallback();
|
||||||
}
|
}
|
||||||
async addContextRoute(context) {
|
async addContextRoute(context) {
|
||||||
await context.route(this._options.urlMatch || '**/*', route => this._handle(route));
|
await context.route(this._options.urlMatch || "**/*", (route) => this._handle(route));
|
||||||
}
|
}
|
||||||
async addPageRoute(page) {
|
async addPageRoute(page) {
|
||||||
await page.route(this._options.urlMatch || '**/*', route => this._handle(route));
|
await page.route(this._options.urlMatch || "**/*", (route) => this._handle(route));
|
||||||
}
|
}
|
||||||
async [_Symbol$asyncDispose]() {
|
async [Symbol.asyncDispose]() {
|
||||||
await this.dispose();
|
await this.dispose();
|
||||||
}
|
}
|
||||||
dispose() {
|
dispose() {
|
||||||
this._localUtils._channel.harClose({
|
this._localUtils.harClose({ harId: this._harId }).catch(() => {
|
||||||
harId: this._harId
|
});
|
||||||
}).catch(() => {});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.HarRouter = HarRouter;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
HarRouter
|
||||||
|
});
|
||||||
|
|||||||
109
tvapp2/node_modules/playwright-core/lib/client/input.js
generated
vendored
@@ -1,111 +1,82 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var input_exports = {};
|
||||||
|
__export(input_exports, {
|
||||||
|
Keyboard: () => Keyboard,
|
||||||
|
Mouse: () => Mouse,
|
||||||
|
Touchscreen: () => Touchscreen
|
||||||
});
|
});
|
||||||
exports.Touchscreen = exports.Mouse = exports.Keyboard = void 0;
|
module.exports = __toCommonJS(input_exports);
|
||||||
/**
|
|
||||||
* Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
* Modifications copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Keyboard {
|
class Keyboard {
|
||||||
constructor(page) {
|
constructor(page) {
|
||||||
this._page = void 0;
|
|
||||||
this._page = page;
|
this._page = page;
|
||||||
}
|
}
|
||||||
async down(key) {
|
async down(key) {
|
||||||
await this._page._channel.keyboardDown({
|
await this._page._channel.keyboardDown({ key });
|
||||||
key
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async up(key) {
|
async up(key) {
|
||||||
await this._page._channel.keyboardUp({
|
await this._page._channel.keyboardUp({ key });
|
||||||
key
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async insertText(text) {
|
async insertText(text) {
|
||||||
await this._page._channel.keyboardInsertText({
|
await this._page._channel.keyboardInsertText({ text });
|
||||||
text
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async type(text, options = {}) {
|
async type(text, options = {}) {
|
||||||
await this._page._channel.keyboardType({
|
await this._page._channel.keyboardType({ text, ...options });
|
||||||
text,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async press(key, options = {}) {
|
async press(key, options = {}) {
|
||||||
await this._page._channel.keyboardPress({
|
await this._page._channel.keyboardPress({ key, ...options });
|
||||||
key,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Keyboard = Keyboard;
|
|
||||||
class Mouse {
|
class Mouse {
|
||||||
constructor(page) {
|
constructor(page) {
|
||||||
this._page = void 0;
|
|
||||||
this._page = page;
|
this._page = page;
|
||||||
}
|
}
|
||||||
async move(x, y, options = {}) {
|
async move(x, y, options = {}) {
|
||||||
await this._page._channel.mouseMove({
|
await this._page._channel.mouseMove({ x, y, ...options });
|
||||||
x,
|
|
||||||
y,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async down(options = {}) {
|
async down(options = {}) {
|
||||||
await this._page._channel.mouseDown({
|
await this._page._channel.mouseDown({ ...options });
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async up(options = {}) {
|
async up(options = {}) {
|
||||||
await this._page._channel.mouseUp(options);
|
await this._page._channel.mouseUp(options);
|
||||||
}
|
}
|
||||||
async click(x, y, options = {}) {
|
async click(x, y, options = {}) {
|
||||||
await this._page._channel.mouseClick({
|
await this._page._channel.mouseClick({ x, y, ...options });
|
||||||
x,
|
|
||||||
y,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async dblclick(x, y, options = {}) {
|
async dblclick(x, y, options = {}) {
|
||||||
await this.click(x, y, {
|
await this.click(x, y, { ...options, clickCount: 2 });
|
||||||
...options,
|
|
||||||
clickCount: 2
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async wheel(deltaX, deltaY) {
|
async wheel(deltaX, deltaY) {
|
||||||
await this._page._channel.mouseWheel({
|
await this._page._channel.mouseWheel({ deltaX, deltaY });
|
||||||
deltaX,
|
|
||||||
deltaY
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Mouse = Mouse;
|
|
||||||
class Touchscreen {
|
class Touchscreen {
|
||||||
constructor(page) {
|
constructor(page) {
|
||||||
this._page = void 0;
|
|
||||||
this._page = page;
|
this._page = page;
|
||||||
}
|
}
|
||||||
async tap(x, y) {
|
async tap(x, y) {
|
||||||
await this._page._channel.touchscreenTap({
|
await this._page._channel.touchscreenTap({ x, y });
|
||||||
x,
|
|
||||||
y
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Touchscreen = Touchscreen;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
Keyboard,
|
||||||
|
Mouse,
|
||||||
|
Touchscreen
|
||||||
|
});
|
||||||
|
|||||||
124
tvapp2/node_modules/playwright-core/lib/client/jsHandle.js
generated
vendored
@@ -1,72 +1,57 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var jsHandle_exports = {};
|
||||||
|
__export(jsHandle_exports, {
|
||||||
|
JSHandle: () => JSHandle,
|
||||||
|
assertMaxArguments: () => assertMaxArguments,
|
||||||
|
parseResult: () => parseResult,
|
||||||
|
serializeArgument: () => serializeArgument
|
||||||
});
|
});
|
||||||
exports.JSHandle = void 0;
|
module.exports = __toCommonJS(jsHandle_exports);
|
||||||
exports.assertMaxArguments = assertMaxArguments;
|
var import_channelOwner = require("./channelOwner");
|
||||||
exports.parseResult = parseResult;
|
var import_errors = require("./errors");
|
||||||
exports.serializeArgument = serializeArgument;
|
var import_serializers = require("../protocol/serializers");
|
||||||
var _channelOwner = require("./channelOwner");
|
class JSHandle extends import_channelOwner.ChannelOwner {
|
||||||
var _serializers = require("../protocol/serializers");
|
|
||||||
var _errors = require("./errors");
|
|
||||||
let _Symbol$asyncDispose;
|
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
_Symbol$asyncDispose = Symbol.asyncDispose;
|
|
||||||
class JSHandle extends _channelOwner.ChannelOwner {
|
|
||||||
static from(handle) {
|
static from(handle) {
|
||||||
return handle._object;
|
return handle._object;
|
||||||
}
|
}
|
||||||
constructor(parent, type, guid, initializer) {
|
constructor(parent, type, guid, initializer) {
|
||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
this._preview = void 0;
|
|
||||||
this._preview = this._initializer.preview;
|
this._preview = this._initializer.preview;
|
||||||
this._channel.on('previewUpdated', ({
|
this._channel.on("previewUpdated", ({ preview }) => this._preview = preview);
|
||||||
preview
|
|
||||||
}) => this._preview = preview);
|
|
||||||
}
|
}
|
||||||
async evaluate(pageFunction, arg) {
|
async evaluate(pageFunction, arg) {
|
||||||
const result = await this._channel.evaluateExpression({
|
const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: serializeArgument(arg) });
|
||||||
expression: String(pageFunction),
|
|
||||||
isFunction: typeof pageFunction === 'function',
|
|
||||||
arg: serializeArgument(arg)
|
|
||||||
});
|
|
||||||
return parseResult(result.value);
|
return parseResult(result.value);
|
||||||
}
|
}
|
||||||
async evaluateHandle(pageFunction, arg) {
|
async evaluateHandle(pageFunction, arg) {
|
||||||
const result = await this._channel.evaluateExpressionHandle({
|
const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: serializeArgument(arg) });
|
||||||
expression: String(pageFunction),
|
|
||||||
isFunction: typeof pageFunction === 'function',
|
|
||||||
arg: serializeArgument(arg)
|
|
||||||
});
|
|
||||||
return JSHandle.from(result.handle);
|
return JSHandle.from(result.handle);
|
||||||
}
|
}
|
||||||
async getProperty(propertyName) {
|
async getProperty(propertyName) {
|
||||||
const result = await this._channel.getProperty({
|
const result = await this._channel.getProperty({ name: propertyName });
|
||||||
name: propertyName
|
|
||||||
});
|
|
||||||
return JSHandle.from(result.handle);
|
return JSHandle.from(result.handle);
|
||||||
}
|
}
|
||||||
async getProperties() {
|
async getProperties() {
|
||||||
const map = new Map();
|
const map = /* @__PURE__ */ new Map();
|
||||||
for (const {
|
for (const { name, value } of (await this._channel.getPropertyList()).properties)
|
||||||
name,
|
map.set(name, JSHandle.from(value));
|
||||||
value
|
|
||||||
} of (await this._channel.getPropertyList()).properties) map.set(name, JSHandle.from(value));
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
async jsonValue() {
|
async jsonValue() {
|
||||||
@@ -75,14 +60,15 @@ class JSHandle extends _channelOwner.ChannelOwner {
|
|||||||
asElement() {
|
asElement() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
async [_Symbol$asyncDispose]() {
|
async [Symbol.asyncDispose]() {
|
||||||
await this.dispose();
|
await this.dispose();
|
||||||
}
|
}
|
||||||
async dispose() {
|
async dispose() {
|
||||||
try {
|
try {
|
||||||
await this._channel.dispose();
|
await this._channel.dispose();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if ((0, _errors.isTargetClosedError)(e)) return;
|
if ((0, import_errors.isTargetClosedError)(e))
|
||||||
|
return;
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,32 +76,30 @@ class JSHandle extends _channelOwner.ChannelOwner {
|
|||||||
return this._preview;
|
return this._preview;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function takes care of converting all JSHandles to their channels,
|
|
||||||
// so that generic channel serializer converts them to guids.
|
|
||||||
exports.JSHandle = JSHandle;
|
|
||||||
function serializeArgument(arg) {
|
function serializeArgument(arg) {
|
||||||
const handles = [];
|
const handles = [];
|
||||||
const pushHandle = channel => {
|
const pushHandle = (channel) => {
|
||||||
handles.push(channel);
|
handles.push(channel);
|
||||||
return handles.length - 1;
|
return handles.length - 1;
|
||||||
};
|
};
|
||||||
const value = (0, _serializers.serializeValue)(arg, value => {
|
const value = (0, import_serializers.serializeValue)(arg, (value2) => {
|
||||||
if (value instanceof JSHandle) return {
|
if (value2 instanceof JSHandle)
|
||||||
h: pushHandle(value._channel)
|
return { h: pushHandle(value2._channel) };
|
||||||
};
|
return { fallThrough: value2 };
|
||||||
return {
|
|
||||||
fallThrough: value
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
return {
|
return { value, handles };
|
||||||
value,
|
|
||||||
handles
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
function parseResult(value) {
|
function parseResult(value) {
|
||||||
return (0, _serializers.parseSerializedValue)(value, undefined);
|
return (0, import_serializers.parseSerializedValue)(value, void 0);
|
||||||
}
|
}
|
||||||
function assertMaxArguments(count, max) {
|
function assertMaxArguments(count, max) {
|
||||||
if (count > max) throw new Error('Too many arguments. If you need to pass more than 1 argument to the function wrap them in an object.');
|
if (count > max)
|
||||||
|
throw new Error("Too many arguments. If you need to pass more than 1 argument to the function wrap them in an object.");
|
||||||
}
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
JSHandle,
|
||||||
|
assertMaxArguments,
|
||||||
|
parseResult,
|
||||||
|
serializeArgument
|
||||||
|
});
|
||||||
|
|||||||
50
tvapp2/node_modules/playwright-core/lib/client/jsonPipe.js
generated
vendored
@@ -1,27 +1,28 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var jsonPipe_exports = {};
|
||||||
|
__export(jsonPipe_exports, {
|
||||||
|
JsonPipe: () => JsonPipe
|
||||||
});
|
});
|
||||||
exports.JsonPipe = void 0;
|
module.exports = __toCommonJS(jsonPipe_exports);
|
||||||
var _channelOwner = require("./channelOwner");
|
var import_channelOwner = require("./channelOwner");
|
||||||
/**
|
class JsonPipe extends import_channelOwner.ChannelOwner {
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class JsonPipe extends _channelOwner.ChannelOwner {
|
|
||||||
static from(jsonPipe) {
|
static from(jsonPipe) {
|
||||||
return jsonPipe._object;
|
return jsonPipe._object;
|
||||||
}
|
}
|
||||||
@@ -32,4 +33,7 @@ class JsonPipe extends _channelOwner.ChannelOwner {
|
|||||||
return this._channel;
|
return this._channel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.JsonPipe = JsonPipe;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
JsonPipe
|
||||||
|
});
|
||||||
|
|||||||
81
tvapp2/node_modules/playwright-core/lib/client/localUtils.js
generated
vendored
@@ -1,36 +1,61 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var localUtils_exports = {};
|
||||||
|
__export(localUtils_exports, {
|
||||||
|
LocalUtils: () => LocalUtils
|
||||||
});
|
});
|
||||||
exports.LocalUtils = void 0;
|
module.exports = __toCommonJS(localUtils_exports);
|
||||||
var _channelOwner = require("./channelOwner");
|
var import_channelOwner = require("./channelOwner");
|
||||||
/**
|
class LocalUtils extends import_channelOwner.ChannelOwner {
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class LocalUtils extends _channelOwner.ChannelOwner {
|
|
||||||
constructor(parent, type, guid, initializer) {
|
constructor(parent, type, guid, initializer) {
|
||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
this.devices = void 0;
|
|
||||||
this.markAsInternalType();
|
this.markAsInternalType();
|
||||||
this.devices = {};
|
this.devices = {};
|
||||||
for (const {
|
for (const { name, descriptor } of initializer.deviceDescriptors)
|
||||||
name,
|
this.devices[name] = descriptor;
|
||||||
descriptor
|
}
|
||||||
} of initializer.deviceDescriptors) this.devices[name] = descriptor;
|
async zip(params) {
|
||||||
|
return await this._channel.zip(params);
|
||||||
|
}
|
||||||
|
async harOpen(params) {
|
||||||
|
return await this._channel.harOpen(params);
|
||||||
|
}
|
||||||
|
async harLookup(params) {
|
||||||
|
return await this._channel.harLookup(params);
|
||||||
|
}
|
||||||
|
async harClose(params) {
|
||||||
|
return await this._channel.harClose(params);
|
||||||
|
}
|
||||||
|
async harUnzip(params) {
|
||||||
|
return await this._channel.harUnzip(params);
|
||||||
|
}
|
||||||
|
async tracingStarted(params) {
|
||||||
|
return await this._channel.tracingStarted(params);
|
||||||
|
}
|
||||||
|
async traceDiscarded(params) {
|
||||||
|
return await this._channel.traceDiscarded(params);
|
||||||
|
}
|
||||||
|
async addStackToTracingNoReply(params) {
|
||||||
|
return await this._channel.addStackToTracingNoReply(params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.LocalUtils = LocalUtils;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
LocalUtils
|
||||||
|
});
|
||||||
|
|||||||
372
tvapp2/node_modules/playwright-core/lib/client/locator.js
generated
vendored
@@ -1,71 +1,71 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
Object.defineProperty(exports, "__esModule", {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
value: true
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var locator_exports = {};
|
||||||
|
__export(locator_exports, {
|
||||||
|
FrameLocator: () => FrameLocator,
|
||||||
|
Locator: () => Locator,
|
||||||
|
setTestIdAttribute: () => setTestIdAttribute,
|
||||||
|
testIdAttributeName: () => testIdAttributeName
|
||||||
});
|
});
|
||||||
exports.Locator = exports.FrameLocator = void 0;
|
module.exports = __toCommonJS(locator_exports);
|
||||||
exports.setTestIdAttribute = setTestIdAttribute;
|
var import_elementHandle = require("./elementHandle");
|
||||||
exports.testIdAttributeName = testIdAttributeName;
|
var import_jsHandle = require("./jsHandle");
|
||||||
var util = _interopRequireWildcard(require("util"));
|
var import_locatorGenerators = require("../utils/isomorphic/locatorGenerators");
|
||||||
var _utils = require("../utils");
|
var import_locatorUtils = require("../utils/isomorphic/locatorUtils");
|
||||||
var _elementHandle = require("./elementHandle");
|
var import_stringUtils = require("../utils/isomorphic/stringUtils");
|
||||||
var _jsHandle = require("./jsHandle");
|
var import_rtti = require("../utils/isomorphic/rtti");
|
||||||
var _stringUtils = require("../utils/isomorphic/stringUtils");
|
var import_time = require("../utils/isomorphic/time");
|
||||||
var _locatorUtils = require("../utils/isomorphic/locatorUtils");
|
|
||||||
let _util$inspect$custom;
|
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
||||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
||||||
_util$inspect$custom = util.inspect.custom;
|
|
||||||
class Locator {
|
class Locator {
|
||||||
constructor(frame, selector, options) {
|
constructor(frame, selector, options) {
|
||||||
this._frame = void 0;
|
|
||||||
this._selector = void 0;
|
|
||||||
this._frame = frame;
|
this._frame = frame;
|
||||||
this._selector = selector;
|
this._selector = selector;
|
||||||
if (options !== null && options !== void 0 && options.hasText) this._selector += ` >> internal:has-text=${(0, _stringUtils.escapeForTextSelector)(options.hasText, false)}`;
|
if (options?.hasText)
|
||||||
if (options !== null && options !== void 0 && options.hasNotText) this._selector += ` >> internal:has-not-text=${(0, _stringUtils.escapeForTextSelector)(options.hasNotText, false)}`;
|
this._selector += ` >> internal:has-text=${(0, import_stringUtils.escapeForTextSelector)(options.hasText, false)}`;
|
||||||
if (options !== null && options !== void 0 && options.has) {
|
if (options?.hasNotText)
|
||||||
|
this._selector += ` >> internal:has-not-text=${(0, import_stringUtils.escapeForTextSelector)(options.hasNotText, false)}`;
|
||||||
|
if (options?.has) {
|
||||||
const locator = options.has;
|
const locator = options.has;
|
||||||
if (locator._frame !== frame) throw new Error(`Inner "has" locator must belong to the same frame.`);
|
if (locator._frame !== frame)
|
||||||
|
throw new Error(`Inner "has" locator must belong to the same frame.`);
|
||||||
this._selector += ` >> internal:has=` + JSON.stringify(locator._selector);
|
this._selector += ` >> internal:has=` + JSON.stringify(locator._selector);
|
||||||
}
|
}
|
||||||
if (options !== null && options !== void 0 && options.hasNot) {
|
if (options?.hasNot) {
|
||||||
const locator = options.hasNot;
|
const locator = options.hasNot;
|
||||||
if (locator._frame !== frame) throw new Error(`Inner "hasNot" locator must belong to the same frame.`);
|
if (locator._frame !== frame)
|
||||||
|
throw new Error(`Inner "hasNot" locator must belong to the same frame.`);
|
||||||
this._selector += ` >> internal:has-not=` + JSON.stringify(locator._selector);
|
this._selector += ` >> internal:has-not=` + JSON.stringify(locator._selector);
|
||||||
}
|
}
|
||||||
|
if (options?.visible !== void 0)
|
||||||
|
this._selector += ` >> visible=${options.visible ? "true" : "false"}`;
|
||||||
|
if (this._frame._platform.inspectCustom)
|
||||||
|
this[this._frame._platform.inspectCustom] = () => this._inspect();
|
||||||
}
|
}
|
||||||
async _withElement(task, timeout) {
|
async _withElement(task, timeout) {
|
||||||
timeout = this._frame.page()._timeoutSettings.timeout({
|
timeout = this._frame.page()._timeoutSettings.timeout({ timeout });
|
||||||
timeout
|
const deadline = timeout ? (0, import_time.monotonicTime)() + timeout : 0;
|
||||||
});
|
|
||||||
const deadline = timeout ? (0, _utils.monotonicTime)() + timeout : 0;
|
|
||||||
return await this._frame._wrapApiCall(async () => {
|
return await this._frame._wrapApiCall(async () => {
|
||||||
const result = await this._frame._channel.waitForSelector({
|
const result = await this._frame._channel.waitForSelector({ selector: this._selector, strict: true, state: "attached", timeout });
|
||||||
selector: this._selector,
|
const handle = import_elementHandle.ElementHandle.fromNullable(result.element);
|
||||||
strict: true,
|
if (!handle)
|
||||||
state: 'attached',
|
throw new Error(`Could not resolve ${this._selector} to DOM Element`);
|
||||||
timeout
|
|
||||||
});
|
|
||||||
const handle = _elementHandle.ElementHandle.fromNullable(result.element);
|
|
||||||
if (!handle) throw new Error(`Could not resolve ${this._selector} to DOM Element`);
|
|
||||||
try {
|
try {
|
||||||
return await task(handle, deadline ? deadline - (0, _utils.monotonicTime)() : 0);
|
return await task(handle, deadline ? deadline - (0, import_time.monotonicTime)() : 0);
|
||||||
} finally {
|
} finally {
|
||||||
await handle.dispose();
|
await handle.dispose();
|
||||||
}
|
}
|
||||||
@@ -78,31 +78,19 @@ class Locator {
|
|||||||
return this._frame.page();
|
return this._frame.page();
|
||||||
}
|
}
|
||||||
async boundingBox(options) {
|
async boundingBox(options) {
|
||||||
return await this._withElement(h => h.boundingBox(), options === null || options === void 0 ? void 0 : options.timeout);
|
return await this._withElement((h) => h.boundingBox(), options?.timeout);
|
||||||
}
|
}
|
||||||
async check(options = {}) {
|
async check(options = {}) {
|
||||||
return await this._frame.check(this._selector, {
|
return await this._frame.check(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async click(options = {}) {
|
async click(options = {}) {
|
||||||
return await this._frame.click(this._selector, {
|
return await this._frame.click(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async dblclick(options = {}) {
|
async dblclick(options = {}) {
|
||||||
return await this._frame.dblclick(this._selector, {
|
return await this._frame.dblclick(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async dispatchEvent(type, eventInit = {}, options) {
|
async dispatchEvent(type, eventInit = {}, options) {
|
||||||
return await this._frame.dispatchEvent(this._selector, type, eventInit, {
|
return await this._frame.dispatchEvent(this._selector, type, eventInit, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async dragTo(target, options = {}) {
|
async dragTo(target, options = {}) {
|
||||||
return await this._frame.dragAndDrop(this._selector, target._selector, {
|
return await this._frame.dragAndDrop(this._selector, target._selector, {
|
||||||
@@ -111,68 +99,62 @@ class Locator {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async evaluate(pageFunction, arg, options) {
|
async evaluate(pageFunction, arg, options) {
|
||||||
return await this._withElement(h => h.evaluate(pageFunction, arg), options === null || options === void 0 ? void 0 : options.timeout);
|
return await this._withElement((h) => h.evaluate(pageFunction, arg), options?.timeout);
|
||||||
}
|
}
|
||||||
async evaluateAll(pageFunction, arg) {
|
async evaluateAll(pageFunction, arg) {
|
||||||
return await this._frame.$$eval(this._selector, pageFunction, arg);
|
return await this._frame.$$eval(this._selector, pageFunction, arg);
|
||||||
}
|
}
|
||||||
async evaluateHandle(pageFunction, arg, options) {
|
async evaluateHandle(pageFunction, arg, options) {
|
||||||
return await this._withElement(h => h.evaluateHandle(pageFunction, arg), options === null || options === void 0 ? void 0 : options.timeout);
|
return await this._withElement((h) => h.evaluateHandle(pageFunction, arg), options?.timeout);
|
||||||
}
|
}
|
||||||
async fill(value, options = {}) {
|
async fill(value, options = {}) {
|
||||||
return await this._frame.fill(this._selector, value, {
|
return await this._frame.fill(this._selector, value, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async clear(options = {}) {
|
async clear(options = {}) {
|
||||||
return await this.fill('', options);
|
return await this.fill("", options);
|
||||||
}
|
}
|
||||||
async _highlight() {
|
async _highlight() {
|
||||||
// VS Code extension uses this one, keep it for now.
|
|
||||||
return await this._frame._highlight(this._selector);
|
return await this._frame._highlight(this._selector);
|
||||||
}
|
}
|
||||||
async highlight() {
|
async highlight() {
|
||||||
return await this._frame._highlight(this._selector);
|
return await this._frame._highlight(this._selector);
|
||||||
}
|
}
|
||||||
locator(selectorOrLocator, options) {
|
locator(selectorOrLocator, options) {
|
||||||
if ((0, _utils.isString)(selectorOrLocator)) return new Locator(this._frame, this._selector + ' >> ' + selectorOrLocator, options);
|
if ((0, import_rtti.isString)(selectorOrLocator))
|
||||||
if (selectorOrLocator._frame !== this._frame) throw new Error(`Locators must belong to the same frame.`);
|
return new Locator(this._frame, this._selector + " >> " + selectorOrLocator, options);
|
||||||
return new Locator(this._frame, this._selector + ' >> internal:chain=' + JSON.stringify(selectorOrLocator._selector), options);
|
if (selectorOrLocator._frame !== this._frame)
|
||||||
|
throw new Error(`Locators must belong to the same frame.`);
|
||||||
|
return new Locator(this._frame, this._selector + " >> internal:chain=" + JSON.stringify(selectorOrLocator._selector), options);
|
||||||
}
|
}
|
||||||
getByTestId(testId) {
|
getByTestId(testId) {
|
||||||
return this.locator((0, _locatorUtils.getByTestIdSelector)(testIdAttributeName(), testId));
|
return this.locator((0, import_locatorUtils.getByTestIdSelector)(testIdAttributeName(), testId));
|
||||||
}
|
}
|
||||||
getByAltText(text, options) {
|
getByAltText(text, options) {
|
||||||
return this.locator((0, _locatorUtils.getByAltTextSelector)(text, options));
|
return this.locator((0, import_locatorUtils.getByAltTextSelector)(text, options));
|
||||||
}
|
}
|
||||||
getByLabel(text, options) {
|
getByLabel(text, options) {
|
||||||
return this.locator((0, _locatorUtils.getByLabelSelector)(text, options));
|
return this.locator((0, import_locatorUtils.getByLabelSelector)(text, options));
|
||||||
}
|
}
|
||||||
getByPlaceholder(text, options) {
|
getByPlaceholder(text, options) {
|
||||||
return this.locator((0, _locatorUtils.getByPlaceholderSelector)(text, options));
|
return this.locator((0, import_locatorUtils.getByPlaceholderSelector)(text, options));
|
||||||
}
|
}
|
||||||
getByText(text, options) {
|
getByText(text, options) {
|
||||||
return this.locator((0, _locatorUtils.getByTextSelector)(text, options));
|
return this.locator((0, import_locatorUtils.getByTextSelector)(text, options));
|
||||||
}
|
}
|
||||||
getByTitle(text, options) {
|
getByTitle(text, options) {
|
||||||
return this.locator((0, _locatorUtils.getByTitleSelector)(text, options));
|
return this.locator((0, import_locatorUtils.getByTitleSelector)(text, options));
|
||||||
}
|
}
|
||||||
getByRole(role, options = {}) {
|
getByRole(role, options = {}) {
|
||||||
return this.locator((0, _locatorUtils.getByRoleSelector)(role, options));
|
return this.locator((0, import_locatorUtils.getByRoleSelector)(role, options));
|
||||||
}
|
}
|
||||||
frameLocator(selector) {
|
frameLocator(selector) {
|
||||||
return new FrameLocator(this._frame, this._selector + ' >> ' + selector);
|
return new FrameLocator(this._frame, this._selector + " >> " + selector);
|
||||||
}
|
}
|
||||||
filter(options) {
|
filter(options) {
|
||||||
return new Locator(this._frame, this._selector, options);
|
return new Locator(this._frame, this._selector, options);
|
||||||
}
|
}
|
||||||
async elementHandle(options) {
|
async elementHandle(options) {
|
||||||
return await this._frame.waitForSelector(this._selector, {
|
return await this._frame.waitForSelector(this._selector, { strict: true, state: "attached", ...options });
|
||||||
strict: true,
|
|
||||||
state: 'attached',
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async elementHandles() {
|
async elementHandles() {
|
||||||
return await this._frame.$$(this._selector);
|
return await this._frame.$$(this._selector);
|
||||||
@@ -181,7 +163,7 @@ class Locator {
|
|||||||
return new FrameLocator(this._frame, this._selector);
|
return new FrameLocator(this._frame, this._selector);
|
||||||
}
|
}
|
||||||
first() {
|
first() {
|
||||||
return new Locator(this._frame, this._selector + ' >> nth=0');
|
return new Locator(this._frame, this._selector + " >> nth=0");
|
||||||
}
|
}
|
||||||
last() {
|
last() {
|
||||||
return new Locator(this._frame, this._selector + ` >> nth=-1`);
|
return new Locator(this._frame, this._selector + ` >> nth=-1`);
|
||||||
@@ -190,246 +172,172 @@ class Locator {
|
|||||||
return new Locator(this._frame, this._selector + ` >> nth=${index}`);
|
return new Locator(this._frame, this._selector + ` >> nth=${index}`);
|
||||||
}
|
}
|
||||||
and(locator) {
|
and(locator) {
|
||||||
if (locator._frame !== this._frame) throw new Error(`Locators must belong to the same frame.`);
|
if (locator._frame !== this._frame)
|
||||||
|
throw new Error(`Locators must belong to the same frame.`);
|
||||||
return new Locator(this._frame, this._selector + ` >> internal:and=` + JSON.stringify(locator._selector));
|
return new Locator(this._frame, this._selector + ` >> internal:and=` + JSON.stringify(locator._selector));
|
||||||
}
|
}
|
||||||
or(locator) {
|
or(locator) {
|
||||||
if (locator._frame !== this._frame) throw new Error(`Locators must belong to the same frame.`);
|
if (locator._frame !== this._frame)
|
||||||
|
throw new Error(`Locators must belong to the same frame.`);
|
||||||
return new Locator(this._frame, this._selector + ` >> internal:or=` + JSON.stringify(locator._selector));
|
return new Locator(this._frame, this._selector + ` >> internal:or=` + JSON.stringify(locator._selector));
|
||||||
}
|
}
|
||||||
async focus(options) {
|
async focus(options) {
|
||||||
return await this._frame.focus(this._selector, {
|
return await this._frame.focus(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async blur(options) {
|
async blur(options) {
|
||||||
await this._frame._channel.blur({
|
await this._frame._channel.blur({ selector: this._selector, strict: true, ...options });
|
||||||
selector: this._selector,
|
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async count() {
|
async count() {
|
||||||
return await this._frame._queryCount(this._selector);
|
return await this._frame._queryCount(this._selector);
|
||||||
}
|
}
|
||||||
|
async _generateLocatorString() {
|
||||||
|
return await this._withElement((h) => h._generateLocatorString());
|
||||||
|
}
|
||||||
async getAttribute(name, options) {
|
async getAttribute(name, options) {
|
||||||
return await this._frame.getAttribute(this._selector, name, {
|
return await this._frame.getAttribute(this._selector, name, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async hover(options = {}) {
|
async hover(options = {}) {
|
||||||
return await this._frame.hover(this._selector, {
|
return await this._frame.hover(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async innerHTML(options) {
|
async innerHTML(options) {
|
||||||
return await this._frame.innerHTML(this._selector, {
|
return await this._frame.innerHTML(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async innerText(options) {
|
async innerText(options) {
|
||||||
return await this._frame.innerText(this._selector, {
|
return await this._frame.innerText(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async inputValue(options) {
|
async inputValue(options) {
|
||||||
return await this._frame.inputValue(this._selector, {
|
return await this._frame.inputValue(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async isChecked(options) {
|
async isChecked(options) {
|
||||||
return await this._frame.isChecked(this._selector, {
|
return await this._frame.isChecked(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async isDisabled(options) {
|
async isDisabled(options) {
|
||||||
return await this._frame.isDisabled(this._selector, {
|
return await this._frame.isDisabled(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async isEditable(options) {
|
async isEditable(options) {
|
||||||
return await this._frame.isEditable(this._selector, {
|
return await this._frame.isEditable(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async isEnabled(options) {
|
async isEnabled(options) {
|
||||||
return await this._frame.isEnabled(this._selector, {
|
return await this._frame.isEnabled(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async isHidden(options) {
|
async isHidden(options) {
|
||||||
return await this._frame.isHidden(this._selector, {
|
return await this._frame.isHidden(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async isVisible(options) {
|
async isVisible(options) {
|
||||||
return await this._frame.isVisible(this._selector, {
|
return await this._frame.isVisible(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async press(key, options = {}) {
|
async press(key, options = {}) {
|
||||||
return await this._frame.press(this._selector, key, {
|
return await this._frame.press(this._selector, key, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async screenshot(options = {}) {
|
async screenshot(options = {}) {
|
||||||
return await this._withElement((h, timeout) => h.screenshot({
|
const mask = options.mask;
|
||||||
...options,
|
return await this._withElement((h, timeout) => h.screenshot({ ...options, mask, timeout }), options.timeout);
|
||||||
timeout
|
|
||||||
}), options.timeout);
|
|
||||||
}
|
}
|
||||||
async ariaSnapshot(options) {
|
async ariaSnapshot(options) {
|
||||||
const result = await this._frame._channel.ariaSnapshot({
|
const result = await this._frame._channel.ariaSnapshot({ ...options, mode: options?._mode, selector: this._selector });
|
||||||
...options,
|
|
||||||
selector: this._selector
|
|
||||||
});
|
|
||||||
return result.snapshot;
|
return result.snapshot;
|
||||||
}
|
}
|
||||||
async scrollIntoViewIfNeeded(options = {}) {
|
async scrollIntoViewIfNeeded(options = {}) {
|
||||||
return await this._withElement((h, timeout) => h.scrollIntoViewIfNeeded({
|
return await this._withElement((h, timeout) => h.scrollIntoViewIfNeeded({ ...options, timeout }), options.timeout);
|
||||||
...options,
|
|
||||||
timeout
|
|
||||||
}), options.timeout);
|
|
||||||
}
|
}
|
||||||
async selectOption(values, options = {}) {
|
async selectOption(values, options = {}) {
|
||||||
return await this._frame.selectOption(this._selector, values, {
|
return await this._frame.selectOption(this._selector, values, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async selectText(options = {}) {
|
async selectText(options = {}) {
|
||||||
return await this._withElement((h, timeout) => h.selectText({
|
return await this._withElement((h, timeout) => h.selectText({ ...options, timeout }), options.timeout);
|
||||||
...options,
|
|
||||||
timeout
|
|
||||||
}), options.timeout);
|
|
||||||
}
|
}
|
||||||
async setChecked(checked, options) {
|
async setChecked(checked, options) {
|
||||||
if (checked) await this.check(options);else await this.uncheck(options);
|
if (checked)
|
||||||
|
await this.check(options);
|
||||||
|
else
|
||||||
|
await this.uncheck(options);
|
||||||
}
|
}
|
||||||
async setInputFiles(files, options = {}) {
|
async setInputFiles(files, options = {}) {
|
||||||
return await this._frame.setInputFiles(this._selector, files, {
|
return await this._frame.setInputFiles(this._selector, files, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async tap(options = {}) {
|
async tap(options = {}) {
|
||||||
return await this._frame.tap(this._selector, {
|
return await this._frame.tap(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async textContent(options) {
|
async textContent(options) {
|
||||||
return await this._frame.textContent(this._selector, {
|
return await this._frame.textContent(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async type(text, options = {}) {
|
async type(text, options = {}) {
|
||||||
return await this._frame.type(this._selector, text, {
|
return await this._frame.type(this._selector, text, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async pressSequentially(text, options = {}) {
|
async pressSequentially(text, options = {}) {
|
||||||
return await this.type(text, options);
|
return await this.type(text, options);
|
||||||
}
|
}
|
||||||
async uncheck(options = {}) {
|
async uncheck(options = {}) {
|
||||||
return await this._frame.uncheck(this._selector, {
|
return await this._frame.uncheck(this._selector, { strict: true, ...options });
|
||||||
strict: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async all() {
|
async all() {
|
||||||
return new Array(await this.count()).fill(0).map((e, i) => this.nth(i));
|
return new Array(await this.count()).fill(0).map((e, i) => this.nth(i));
|
||||||
}
|
}
|
||||||
async allInnerTexts() {
|
async allInnerTexts() {
|
||||||
return await this._frame.$$eval(this._selector, ee => ee.map(e => e.innerText));
|
return await this._frame.$$eval(this._selector, (ee) => ee.map((e) => e.innerText));
|
||||||
}
|
}
|
||||||
async allTextContents() {
|
async allTextContents() {
|
||||||
return await this._frame.$$eval(this._selector, ee => ee.map(e => e.textContent || ''));
|
return await this._frame.$$eval(this._selector, (ee) => ee.map((e) => e.textContent || ""));
|
||||||
}
|
}
|
||||||
async waitFor(options) {
|
async waitFor(options) {
|
||||||
await this._frame._channel.waitForSelector({
|
await this._frame._channel.waitForSelector({ selector: this._selector, strict: true, omitReturnValue: true, ...options });
|
||||||
selector: this._selector,
|
|
||||||
strict: true,
|
|
||||||
omitReturnValue: true,
|
|
||||||
...options
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async _expect(expression, options) {
|
async _expect(expression, options) {
|
||||||
const params = {
|
const params = { selector: this._selector, expression, ...options, isNot: !!options.isNot };
|
||||||
selector: this._selector,
|
params.expectedValue = (0, import_jsHandle.serializeArgument)(options.expectedValue);
|
||||||
expression,
|
|
||||||
...options,
|
|
||||||
isNot: !!options.isNot
|
|
||||||
};
|
|
||||||
params.expectedValue = (0, _jsHandle.serializeArgument)(options.expectedValue);
|
|
||||||
const result = await this._frame._channel.expect(params);
|
const result = await this._frame._channel.expect(params);
|
||||||
if (result.received !== undefined) result.received = (0, _jsHandle.parseResult)(result.received);
|
if (result.received !== void 0)
|
||||||
|
result.received = (0, import_jsHandle.parseResult)(result.received);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
[_util$inspect$custom]() {
|
_inspect() {
|
||||||
return this.toString();
|
return this.toString();
|
||||||
}
|
}
|
||||||
toString() {
|
toString() {
|
||||||
return (0, _utils.asLocator)('javascript', this._selector);
|
return (0, import_locatorGenerators.asLocator)("javascript", this._selector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Locator = Locator;
|
|
||||||
class FrameLocator {
|
class FrameLocator {
|
||||||
constructor(frame, selector) {
|
constructor(frame, selector) {
|
||||||
this._frame = void 0;
|
|
||||||
this._frameSelector = void 0;
|
|
||||||
this._frame = frame;
|
this._frame = frame;
|
||||||
this._frameSelector = selector;
|
this._frameSelector = selector;
|
||||||
}
|
}
|
||||||
locator(selectorOrLocator, options) {
|
locator(selectorOrLocator, options) {
|
||||||
if ((0, _utils.isString)(selectorOrLocator)) return new Locator(this._frame, this._frameSelector + ' >> internal:control=enter-frame >> ' + selectorOrLocator, options);
|
if ((0, import_rtti.isString)(selectorOrLocator))
|
||||||
if (selectorOrLocator._frame !== this._frame) throw new Error(`Locators must belong to the same frame.`);
|
return new Locator(this._frame, this._frameSelector + " >> internal:control=enter-frame >> " + selectorOrLocator, options);
|
||||||
return new Locator(this._frame, this._frameSelector + ' >> internal:control=enter-frame >> ' + selectorOrLocator._selector, options);
|
if (selectorOrLocator._frame !== this._frame)
|
||||||
|
throw new Error(`Locators must belong to the same frame.`);
|
||||||
|
return new Locator(this._frame, this._frameSelector + " >> internal:control=enter-frame >> " + selectorOrLocator._selector, options);
|
||||||
}
|
}
|
||||||
getByTestId(testId) {
|
getByTestId(testId) {
|
||||||
return this.locator((0, _locatorUtils.getByTestIdSelector)(testIdAttributeName(), testId));
|
return this.locator((0, import_locatorUtils.getByTestIdSelector)(testIdAttributeName(), testId));
|
||||||
}
|
}
|
||||||
getByAltText(text, options) {
|
getByAltText(text, options) {
|
||||||
return this.locator((0, _locatorUtils.getByAltTextSelector)(text, options));
|
return this.locator((0, import_locatorUtils.getByAltTextSelector)(text, options));
|
||||||
}
|
}
|
||||||
getByLabel(text, options) {
|
getByLabel(text, options) {
|
||||||
return this.locator((0, _locatorUtils.getByLabelSelector)(text, options));
|
return this.locator((0, import_locatorUtils.getByLabelSelector)(text, options));
|
||||||
}
|
}
|
||||||
getByPlaceholder(text, options) {
|
getByPlaceholder(text, options) {
|
||||||
return this.locator((0, _locatorUtils.getByPlaceholderSelector)(text, options));
|
return this.locator((0, import_locatorUtils.getByPlaceholderSelector)(text, options));
|
||||||
}
|
}
|
||||||
getByText(text, options) {
|
getByText(text, options) {
|
||||||
return this.locator((0, _locatorUtils.getByTextSelector)(text, options));
|
return this.locator((0, import_locatorUtils.getByTextSelector)(text, options));
|
||||||
}
|
}
|
||||||
getByTitle(text, options) {
|
getByTitle(text, options) {
|
||||||
return this.locator((0, _locatorUtils.getByTitleSelector)(text, options));
|
return this.locator((0, import_locatorUtils.getByTitleSelector)(text, options));
|
||||||
}
|
}
|
||||||
getByRole(role, options = {}) {
|
getByRole(role, options = {}) {
|
||||||
return this.locator((0, _locatorUtils.getByRoleSelector)(role, options));
|
return this.locator((0, import_locatorUtils.getByRoleSelector)(role, options));
|
||||||
}
|
}
|
||||||
owner() {
|
owner() {
|
||||||
return new Locator(this._frame, this._frameSelector);
|
return new Locator(this._frame, this._frameSelector);
|
||||||
}
|
}
|
||||||
frameLocator(selector) {
|
frameLocator(selector) {
|
||||||
return new FrameLocator(this._frame, this._frameSelector + ' >> internal:control=enter-frame >> ' + selector);
|
return new FrameLocator(this._frame, this._frameSelector + " >> internal:control=enter-frame >> " + selector);
|
||||||
}
|
}
|
||||||
first() {
|
first() {
|
||||||
return new FrameLocator(this._frame, this._frameSelector + ' >> nth=0');
|
return new FrameLocator(this._frame, this._frameSelector + " >> nth=0");
|
||||||
}
|
}
|
||||||
last() {
|
last() {
|
||||||
return new FrameLocator(this._frame, this._frameSelector + ` >> nth=-1`);
|
return new FrameLocator(this._frame, this._frameSelector + ` >> nth=-1`);
|
||||||
@@ -438,11 +346,17 @@ class FrameLocator {
|
|||||||
return new FrameLocator(this._frame, this._frameSelector + ` >> nth=${index}`);
|
return new FrameLocator(this._frame, this._frameSelector + ` >> nth=${index}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.FrameLocator = FrameLocator;
|
let _testIdAttributeName = "data-testid";
|
||||||
let _testIdAttributeName = 'data-testid';
|
|
||||||
function testIdAttributeName() {
|
function testIdAttributeName() {
|
||||||
return _testIdAttributeName;
|
return _testIdAttributeName;
|
||||||
}
|
}
|
||||||
function setTestIdAttribute(attributeName) {
|
function setTestIdAttribute(attributeName) {
|
||||||
_testIdAttributeName = attributeName;
|
_testIdAttributeName = attributeName;
|
||||||
}
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
FrameLocator,
|
||||||
|
Locator,
|
||||||
|
setTestIdAttribute,
|
||||||
|
testIdAttributeName
|
||||||
|
});
|
||||||
|
|||||||